第2期ARM裸机篇:【7】IMX启动方式

简介

I.MX6U 支持多种启动方式以及启动设备,比如可以从 SD/EMMC、NAND Flash、QSPI Flash等启动。用户可以根据实际情况,选择合适的启动设备。

不同的启动方式其启动方式和启动要求也不一样,比如前面从 SD 卡启动就需要在 bin 文件前面添加一个数据头,其它的启动设备也是需要这个数据头的

目标

了解一下 I.MX6U 的启动方式,以及不同设备启动的要求。

阅读基础

熟悉计算机。

环境说明

  • windows10

参考资料

  • 原子文档:I.MX6ULL开发指南 第九章
  • NXP官方文档:I.MX6ULL参考手册、数据手册

启动方式选择

拨码选择启动方式

BOOT 的处理过程是发生在 I.MX6U 芯片上电以后,芯片会根据 BOOT_MODE[1:0]的设置来选择 BOOT 方式

BOOT_MODE[1:0]的值是可以改变的,有两种方式,

  • 一种是改写 eFUSE(熔 丝)
  • 一种是修改相应的 GPIO 高低电平

第一种修改 eFUSE 的方式只能修改一次,后面就不能再修改了,所以我们不使用。我们使用的是通过修改 BOOT_MODE[1:0]对应的 GPIO 高低电平来选择启动方式,所有的开发板都使用的这种方式

I.MX6U 有一个 BOOT_MODE1 引脚和BOOT_MODE0 引脚,这两个引脚对应这BOOT_MODE[1:0]。I.MX6U-ALPHA 开发板的这两个引脚原理图如图所示:

BlogImage-20210910174152

其中 BOOT_MODE1 和 BOOT_MODE0 在芯片内部是有 100KΩ下拉电阻的,所以默认是0

BOOT_MODE1 和 BOOT_MODE0 这两个引脚我们也接到了底板的拨码开关上,这样我们就可以通过拨码开关来控制 BOOT_MODE1 和 BOOT_MODE0 的高低电平

以 BOOT_MODE1为例,当我们把 BOOT_CFG 的第一个开关拨到“ON”的时候,就相当于 BOOT_MODE1 引脚通过 R88 这个 10K 电阻接到了 3.3V 电源,芯片内部的 BOOT_MODE1 又是 100K 下拉电阻接地,因此此时 BOOT_MODE1 的电压就是 100/(10+100)*3.3V= 3V,这是个高电平,因此BOOT_CFG 的中的 8 个开关拨到“ON”就是高电平,拨到“OFF”就是低电平

四种启动方式

而 I.MX6U 有四个 BOOT 模式,这四个 BOOT 模式由 BOOT_MODE[1:0]来控制,也就是
BOOT_MODE1 和 BOOT_MODE0 这两 IO,BOOT 模式配置如表所示:

BlogImage-20210910174543

我们用到的只有第二和第三种 BOOT 方式。

串行下载

当 BOOT_MODE1 为 0,BOOT_MODE0 为 1 的时候此模式使能串行下载的意思就是可以通过 USB 或者 UART 将代码下载到板子上的外置存储设备中,我们可以使用 OTG1 这个 USB口向开发板上的 SD/EMMC、NAND 等存储设备下载代码

我们需要将 BOOT_MODE1 拨到“OFF”,将BOOT_MODE0 拨到“ON”。这个下载是需要用到 NXP 提供的一个软件,一般用来最终量产的时候将代码烧写到外置存储设备中的,我们后面讲解如何使用。

内部 BOOT 模式

当 BOOT_MODE1 为 1,BOOT_MODE0 为 0 的时候此模式使能在此模式下,芯片会执行内部的 boot ROM 代码,这段 boot ROM 代码会进行硬件初始化(一部分外设),然后从 boot 设 备(就是存放代码的设备、比如 SD/EMMC、NAND)中将代码拷贝出来复制到指定的 RAM 中,一般是 DDR。

BOOT ROM 初始化内容

当我们设置 BOOT 模式为“内部 BOOT 模式”以后,I.MX6U 内部的 boot ROM 代码就会执行。

这个 boot ROM 代码都会做什么处理呢?首先肯定是初始化时钟,boot ROM 设置的系统时钟如图所示:

BlogImage-20210910175210

在图中 BT_FREQ 模式为 0,可以看到,boot ROM 会将 I.MX6U 的

  • 内核时钟设置为396MHz,也就是主频为 396Mhz。
  • System PLL=528Mhz,
  • USB PLL=480MHz,
  • AHB=132MHz,
  • IPG=66MHz。

关于 I.MX6U 的系统时钟,我们后面会详细讲解。

内部 boot ROM 为了加快执行速度会打开 MMU 和 Cache,下载镜像的时候 L1 ICache 会打开,验证镜像的时候 L1 DCache、L2 Cache 和 MMU 都会打开。一旦镜像验证完成,boot ROM就会关闭 L1 DCache、L2 Cache 和 MMU

中断向量偏移会被设置到 boot ROM 的起始位置,当 boot ROM 启动了用户代码以后就可以重新设置中断向量偏移了。一般是重新设置到我们用户代码的开始地方,关于中断的内容后面会详细讲解。

启动设备

IMX6U支持的启动设备

当 BOOT_MODE 设置为内部 BOOT 模式以后,可以从以下设备中启动:

①、接到 EIM 接口的 CS0 上的 16 位 NOR Flash

②、接到 EIM 接口的 CS0 上的 OneNAND Flash

③、接到 GPMI 接口上的 MLC/SLC NAND FlashNAND Flash 页大小支持 2KByte、4KByte
和 8KByte,8 位宽。

④、Quad SPI Flash

⑤、接到 USDHC 接口上的 SD/MMC/eSD/SDXC/eMMC 等设备。

⑥、SPI 接口的 EEPROM

通过 GPIO 来选择启动设备

这些启动设备如何选择呢?I.MX6U 同样提供了 eFUSE 和 GPIO 配置两种,eFUSE 就不讲解了。

我们重点看如何通过 GPIO 来选择启动设备,因为所有的 I.MX6U 开发板都是通过 GPIO来配置启动设备的。正如启动模式由 BOOT_MODE[1:0]来选择一样,启动设备是通过BOOT_CFG1[7:0]、BOOT_CFG2[7:0]和 BOOT_CFG4[7:0]这 24 个配置 IO这 24 个配置 IO 刚好对应着 LCD 的 24 根数据线 LCD_DATA0~LCDDATA23,当启动完成以后这 24 个 IO 就可以作为 LCD 的数据线使用

这 24 根线和 BOOT_MODE1、BOOT_MODE0 共同组成了 I.MX6U的启动选择引脚,如图所示:

BlogImage-20210910202432

通过图中的 26 个启动 IO 即可实现 I.MX6U 从不同的设备启动,BOOT_MODE1 和BOOT_MODE0 已经讲过了。

看到这 24 个 IO 是不是头大?调整这 24 个 IO 的高低电平得多复杂啊?其实不然,虽然有 24 个 IO,但是实际需要调整的只有那几个 IO,其它的 IO 全部下拉接地即可,也就是设置为 0。打开 I.MX6U-ALPHA 开发板的核心板原理图,这 24 个 IO 的默认设置如图所示:

可以看出在图中大部分的 IO 都接地了,只有几个 IO 接高,尤其是 BOOT_CFG4[7:0] 这 8个 IO 都 10K 电阻下拉接地,所以我们压根就不需要去关注 BOOT_CFG4[7:0]

我们需要重点关注的就只剩下了 BOOT_CFG2[7:0]和 BOOT_CFG1[7:0]这 16 个 IO。这 16 个配置 IO 含义在原理图的左侧已经贴出来了,如图所示:

拨码开关配置启动设备

图看着是不是也很头大,BOOT_CFG1[7:0]BOOT_CFG2[7:0]这 16 个 IO 还能不能在减少呢?可以!打开 I.MX6U-ALPHA 开发板的底板原理图,底板上启动设备选择拨码开关原理图如图所示:

BlogImage-20210910203838

在 图中 , 除 了 BOOT_MODE1 和 BOOT_MODE0 必 须 引 出 来 ,LCD_DATA3~LCDDATA7、LCD_DATA11 这 6 个 IO 也被引出来了,可以通过拨码开关来设置其对应的高低电平拨码开关拨到“ON”就是 1,拨到“OFF”就是 0

其中 LCD_DATA11 就 是 BOOT_CFG2[3],LCD_DATA3~LCD_DATA7 就是BOOT_CFG1[3]~BOOT_CFG1[7],这 6 个IO 的配置含义如表所示:

BlogImage-20210910204141

根据表中的 BOOT IO 含义,I.MX6U-ALPHA 开发板从 SD 卡、EMMC、NAND 启动的时候拨码开关各个位设置方式如表所示:

BlogImage-20210910204341

我们在“汇编 LED 灯试验”中,最终的可执行文件 led.bin 烧写到了 SD 卡里面,然后开发板从 SD 卡启动,其拨码开关就是根据表来设置的,通过上面的讲解就知道为什么拨码开关要这么设置了。

镜像烧写

注意!本小节会分析 bin 文件添加的头部信息,但是在笔者写本教程的时候关于 I.MX 系列SOC 头部信息的资料很少,基本只能参考 NXP 官方资料,而官方资料有些地方讲解的又不是很详细。所以本节有部分内容是笔者根据 NXP 官方 u-boo.imx 文件的头部信息反推出来的,因此难免有错误的地方,还望大家谅解!如有发现错误之处,欢迎大家在 www.openedv.com 论坛上留言。

前面我们设置好 BOOT 以后就能从指定的设备启动了,但是你的设备里面得有代码啊,在前面我们使用 imxdownload 这个软件将 led.bin 烧写到了 SD 卡中。imxdownload 会在 led.bin前面添加一些头信息,重新生成一个叫做 load.imx 的文件,最终实际烧写的是 laod.imx

那么肯定就有人问:imxdownload 究竟做了什么?load.imx 和 led.bin 究竟是什么关系?本节我们就来详细的讲解一下 imxdownload 是如何将 led.bin 打包成 load.imx 的。

打包文件组成

学习 STM32 的时候我们可以直接将编译生成的.bin 文件烧写到 STM32 内部 flash 里面,但是 I.MX6U 不能直接烧写编译生成的.bin 文件,我们需要在.bin 文件前面添加一些头信息构成满足 I.MX6U 需求的最终可烧写文件,I.MX6U 的最终可烧写文件组成如下:

、Image vector table,简称 IVT,IVT 里面包含了一系列的地址信息,这些地址信息在ROM 中按照固定的地址存放着

②、Boot data启动数据包含了镜像要拷贝到哪个地址,拷贝的大小是多少等等

③、Device configuration data,简称 DCD,设备配置信息重点是 DDR3 的初始化配置

④、用户代码可执行文件,比如 led.bin。

可以看出最终烧写到 I.MX6U 中的程序其组成为:IVT+Boot data+DCD+.bin所以imxdownload 所生成的 load.imx 就是在 led.bin 前面加上 IVT+Boot data+DCD

打包文件存储到启动设备的位置

IVT 包含了镜像程序的入口点、指向 DCD 的指针和一些用作其它用途的指针

内部 Boot ROM 要求 IVT 放到启动设备中指定的位置(不同的启动设备位置不同),而IVT 在整个 load.imx 的最前面,其实就相当于要求 将load.imx 烧写到存储设备的指定位置去

  1. 启动时,内部 BootROM 会将 load.imx 从启动设备拷贝到 DDR 中。
  2. 用户代码是一定要从 0X87800000 这个地方开始的,因为链接地址为 0X87800000
  3. load.imx 打包文件,在用户代码前面有还 3KByte 的 IVT+Boot Data+DCD 数据(下面会讲为什么是3KByte),因此 load.imx 在 DDR 中的起始地址就是 0X87800000-3072=0X877FF400

整个位置都是相对于存储设备的起始地址的偏移,如图所示:

BlogImage-20210910210420

以 SD/EMMC 存储可执行文件load.imx为例,

假如 SD/EMMC 5个扇区,每个扇区为 512 字节。

假如IVT 偏移为 1Kbyte,IVT+Boot data+DCD 的总大小为 4KByte- 1KByte=3KByte。

那么 load.imx 应该从第三个扇区开始烧写,前两个扇区(1kByte)要留出来,从第 3KByte 开始才是真正的.bin 文件。

IVT 和 Boot Data 数据

那么 IVT 里面究竟存放着什么东西呢?

IVT 里面存放的内容如图所示:

BlogImage-20210910212332

从图可以看到,第一个存放的就是 header(头),header 格式如图所示:

BlogImage-20210910212423

在上图中,

  • Tag 为一个字节长度,固定为 0XD1,
  • Length是两个字节,保存着 IVT 长度,为大端格式,也就是高字节保存在低内存中
  • Version是一个字节,为 0X40 或者0X41。

Boot Data 的数据格式如图所示:

BlogImage-20210910212633

实际情况是不是这样的呢?我们用 winhex 软件打开 load.imx 一看便知。winhex 可以直接
查看一个文件的二进制格式数据,winhex 软件文末获取。用 winhex 打开以后的 load.imxd 如图所示:

BlogImage-20210910213715

上图是我们截取的 load.imx 的一部分内容,从地址0X00000000~0X000025F,共 608个字节的数据。

我们将前 44 个字节的数据按照 4 个字节一组组合在一起(高位在右)就是:

0X402000D1、 0X87800000、0X00000000、0X877FF42C、0X877FF420、0X877FF400、0X00000000、0X00000000

0X877FF000、0X00200000、0X00000000

这 44 个字节的数据就是 IVT 和 Boot Data 数据,按照 IVT 和 Boot Data 所示的格式对应起来如表所示:

BlogImage-20210910214015

BlogImage-20210910214131

在表中,我们详细的列出了 load.imx 的 IVT+Boot Data 每 32 位数据所代表的意义。这些数据都是由 imxdownload 这个软件添加进去的

DCD 数据

复位以后,I.MX6U 片内的所有寄存器都会复位为默认值,但是这些默认值往往不是我们想要的值,而且有些外设我们必须在使用之前初始化它

为此 I.MX6U 提出了一个 DCD(Device Config Data)的概念,和 IVT、Boot Data 一样,DCD 也是添加到 load.imx 里面的,紧跟在 IVT和 Boot Data 后面,IVT 里面也指定了 DCD 的位置

DCD 其实就是 I.MX6U 寄存器地址和对应的配置信息集合,Boot ROM 会使用这些寄存器地址和配置集合来初始化相应的寄存器,比如开启某些外设的时钟、初始化 DDR 等等。DCD 区域不能超过 1768Byte,DCD 区域结构如下图:

BlogImage-20210910214432

DCD 的 header 和 IVT 的 header 类似,结构如下图所示:

BlogImage-20210910214513

其中

  • Tag是单字节,固定为 0XD2,
  • Length为两个字节,表示 DCD 区域的大小,包含header,同样是大端模式,
  • Version是单字节,固定为 0X40 或者 0X41。

图中的 CMD 就是要初始化的寄存器地址和相应的寄存器值,结构如下图所示:

BlogImage-20210910214629

图中的

  • Address,要初始化的寄存器地址
  • Vlalue/Mask ,初始化的寄存器的值,注意采用的是大端模式!
  • Tag为一个字节,固定为 0XCC
  • Length是两个字节,包含写入的命令数据长度,包含 header,同样是大端模式。
  • Parameter为一个字节。

Parameter每个位含义如图下所示:

BlogImage-20210910214707

图中的

  • bytes表示是目标位置宽度,单位为 byte,可以选择 1、2和 4 字节。
  • flags是命令控制标志位。

DCD 结构就分析到这里,在分析 IVT 的时候我们就已经说过了,DCD数据是从load.imx二进制的 0X2C 地址开始的。

load.imx 的 DCD数据

根据我们分析的 DCD 结构可以得到 load.imx 的 DCD数据如下表所示:

BlogImage-20210910215443

BlogImage-20210910215513

从上表中可以看出,DCD 里面的初始化配置主要包括三方面:

①、设置 CCGR0~CCGR6 这 7 个外设时钟使能寄存器,默认打开所有的外设时钟。

②、配置 DDR3 所用的所有 IO。

③、配置 MMDC 控制器,初始化 DDR3。

I.MX6U 的启动过程我们就讲解到这里,本章我们详细的讲解了 I.MX6U 的启动模式、启动设备类型和镜像烧写过程。总结一下,我们编译出来的.bin 文件不能直接烧写到 SD 卡中,需要在.bin 文件前面加上 IVT、Boot Data 和 DCD 这三个数据块。这三个数据块是有指定格式的,我们必须按照格式填写,然后将其放到.bin 文件前面,最终合成的才是可以直接烧写到 SD 卡中的文件。

其他

相关资源下载

winhex19.rar-嵌入式文档类资源-CSDN下载

最近更新

查看本文最近更新请点击

欢迎关注微信公众号

weixingognzhonghaoerweima

おすすめ

転載: blog.csdn.net/aa1319594154/article/details/120234485