参考:《【正点原子】I.MX6U嵌入式Linux驱动开发指南》
正点原子的开发板的配置文件为configs/mx6ull_14x14_ddr512_emmc_defconfig和configs/mx6ull_14x14_ddr512_nand_defconfig
NXP官方的开发板的配置文件为configs/mx6ull_14x14_evk_emmc_defconfig和configs/mx6ull_14x14_evk_nand_defconfig
U-Boot的使用
U-Boot命令使用
uboot 命令中的数字都是十六进制的!不是十进制的!
imx6ull:uboot命令使用
U-Boot顶层Makefile
imx6ull:uboot顶层Makefile分析
U-Boot启动流程
uboot启动流程从uboot代码看,看似很复杂但实际执行的核心操作也就那几条。这个过程中有大量的代码是为了满足通用性、可读性、可移植性以及整体性等而添加的。所以要善于总结出整个过程中的核心操作以及其中的层次调用逻辑关系并搞懂哪些地方可能需要我们在移植时进行修改等,不要陷入到复杂的代码中去。当然uboot代码中的一些代码从设计方面看是非常优秀的,值得我们借鉴和学习。
链接脚本u-boot.lds详解
如果没有编译过 uboot 的话链接脚本为 arch/arm/cpu/u-boot.lds。但是这个不是最终使用的链接脚本,最终的链接脚本是在这个链接脚本的基础上生成的。编译一下 uboot,编译完成以后就会在 uboot 根目录下生成 u-boot.lds文件
imx6ull:uboot链接脚本u-boot.lds详解
U-Boot 启动流程详解
imx6ull:uboot启动流程详解
bootz启动linux内核
总结
- bootz启动Linux内核的zImage镜像主要完成了以下操作:
- 根据魔数判断是否是zImage镜像
- 直接跳转执行zImage镜像的第一条指令,并通过通用寄存器传递3个参数
- 当使用tag方式传参时:固定值0,机器码,一大片tag的首地址
- 当时用设备树方式传参时:固定值0,机器码,设备树的起始地址
- 在上述过程中频繁的使用了一个全局变量images,用于保存这些过程中需要用到的各种信息。包括os镜像起始地址、设备数起始地址、os类型等等
bootz 命令层次调用逻辑关系
imx6ull:bootz启动linux内核
环境变量
环境变量的工作方式
这个版本的uboot中环境变量的工作方式跟之前版本没有太大差距,只是在实现和细节上有所不同。
大体思路为:
- uboot代码中有一份默认环境变量,被编译在镜像文件里面
- uboot启动时环境变量会随整个uboot被加载到DDR中,这一份就是我们程序运行时所使用的默认环境变量
- 程序中会先尝试从存储设备中的环境变量分区读取环境变量到事先在堆内存中申请的一片内存空间中(为什么不直接覆盖掉DDR中默认的那一份环境变量呢?这里涉及到一些问题,比如程序运行时想要读取默认环境变量、运行时用户新增环境变量、内嵌环境(ENV_IS_EMBEDDED,一般不使用)变量等等,总之这样在这里可能相对比较合适,不一样的情况采用不同的方式即可)
- 对刚才从存储设备中读取到堆内存中的这份环境变量进行CRC校验
- 如果CRC校验成功,则就使用这份环境变量;如果CRC校验失败则将默认环境变量拷贝到刚才申请的堆内存中
- uboot运行期间就一直使用堆内存中的这一份环境变量
- 当我们通过saveenv保存环境变量时,会将堆内存中的所有的这些环境变量都写入到存储设备的环境变量分区去
层次调用逻辑关系
env_init(init_sequence_f)
initr_env(init_sequence_r)
env_relocate
env_relocate_spec
ALLOC_CACHE_ALIGN_BUFFER
read_env
crc32
env_import
默认环境变量在env_default.h中定义,但是该文件中有好多环境变量都没有被直接加进去,而是通过CONFIG_EXTRA_ENV_SETTINGS宏加入进去的。CONFIG_EXTRA_ENV_SETTINGS宏定义在mx6ullevk.h中
bootcmd 和 bootargs 环境变量
imx6ull:bootcmd和bootargs环境变量
U-Boot移植
在U-Boot中添加自己的开发板
- 添加开发板默认配置文件
- 复制 xxx_defconfig,然后重命名
- 修改其中的内容。该文件中有两个地方需要修改,均是和后面的修改有关的
CONFIG_SYS_EXTRA_OPTIONS要对应板级文件夹进行修改
CONFIG_TARGET_xxx这一项要对应板级文件夹内的Kconfig文件中的if判断后面的项目
- 添加开发板对应的头文件
- 复制 include/configs/xxx.h,并重命名
- 根据自己板子的情况修改其中的内容
- 添加开发板对应的板级文件夹
- 复制 board/freescale/mx6ullevk,并重命名
- 进入新生成的这个文件夹下,修改mx6ullevk.c文件重命名
- 修改这个文件夹下的那些会因为路径和文件名改变而引起错误的文件
- 修改Kconfig文件中if TARGET_xxx为自己定义的项目名
- 修改 U-Boot 图形界面配置文件
- 修改文件arch/arm/cpu/armv7/mx6/Kconfig。仿照着添加一个config项,这一项要对应板级文件夹内的Kconfig文件中的if判断后面的项目。并用source引入上面添加的板级文件夹下的Kconfig文件