#嵌入式Linux最小系统移植# 对uboot移植和裁剪的一点点个人思考和总结

2019-07-12 16:04发布

思路: 1.分析启动流程 2.移植config文件(smdk440_config) 3.移植包含控制条件编译宏的.h文件(configs/s3c2440.h) 4.移植板级初始化.c文件(s3c2440.c) 5.移植RAM初始化?DDR? 6.移植NorFlash 7.移植NandFlash 8.uboot应该能启动了? //分析启动流程 1.make xx_config 2.在makefile中有以下依赖关系 %_config: $(MKCONFIG) 3.在mkconfig中会去解析board.cfg,根据输入的xx去匹配board.cfg中的TARGET项,提取出ARCH、CPU、SOC、VENDOR等 然后自动生成config.h,其中config.h中定义了一些关于ARCH、SOC等的宏,以及包含configs/xx.h头文件来控制uboot中的条件编译 4. make 生成 uboot.bin uboot.bin依赖于 OBJ LIB LDS,其中LIB变量为cpu/ drivers/ board/ 随后依次进入各文件夹进行make,生成buitin.o,最后链接成uboot.bin start.s ... lowlevel_init.S ... _main(arm/lib/crt0.S) board_init_f board_early_init_f board_init_r board_init start.S主要完成了: a.初始化异常向量表 b.设置cpu svc模式,关中断 c.配置cp15协处理器,设置异常向量入口 d.配置cp15,初始化mmu cache tlb e.板级初始化,pll memory初始化 一、Uboot从norflash启动和nandflash启动的区别 1.norflash启动 norflash是可以片上执行代码(XIP)的,也就是说,将bootloader烧写到norflash的开始地址后,开发板上电以后,cpu直接从0x00开始执行(也就是在norflash中执行)整个uboot,直到引导内核启动。 2.nandflash启动 由于norflash有地址线,因此可以直接执行代码,而nandflash只有数据线,因此无法片上执行。开发板上电以后,nandflash控制器会自动把nandflash中的前4K代码拷贝至CPU内部RAM(SRAM-CACHE), 同时把片内SRAM映射到0x00,随后CPU从0x00开始执行,这个过程程序不需要干涉。但是uboot肯定是大于4K,这样的话4K以后的代码怎么办? 所以如果是从nandflash启动,前4K代码首先会设置CPU运行模式,关看门狗,设置时钟,关中断,初始化内存,初始化nandflash,设置堆栈,然后把整个bootloader搬运到SDRAM中,并跳转到SDRAM中 执行。 一、总结: 对于Uboot来说,主要有两大阶段,第一阶段主要使用汇编语言实现,包括cpu、时钟、关watchdog、mmu等初始化,并设置堆栈,为C语言调用做好准备。 随后进入board_init_f阶段,该阶段的主要工作就是初始化Clock、serial和RAM,实现最精简系统启动。 最后调用board_init_r函数,该阶段主要是做了一些mmc、flash、eth等外设的初始化以及环境变量的设置等,最后进入main_loop死循环,打印命令行,等待命令输入和解析。 uboot移植主要涉及几方面: 1.向board_cfg文件中添加需要支持的新板,包括SOC、CPU、VENDOR、TARGET等项; 2.向board/文件夹中添加对应的板级函数,如board/samsung/mini2440(mini2440.c Makefile)等; 3.向include/configs文件夹中添加对应的头文件如mini2440.h,这个文件在mkconfig时会被包含进config.h,用于控制Uboot编译过程的各条件编译。 4.修改arch/cpu文件夹下对应的start.S,适配对应的cpu型号(比如主频、时钟等)。 5.Uboot可以从norflash、nandflash、RAM启动,不同的启动方式在start.S会有不同。 本次Uboot移植主要修改了的文件夹: u-boot-2012.10oardsamsungmini2440 u-boot-2012.10includeconfigsmini2440.h u-boot-2012.10archarmcpuu-boot.lds u-boot-2012.10archarmcpuarm920tstart.S 本次uboot移植遇到的坑: 1.一操作全局变量(赋值等操作)就卡死;一打印(如puts、printf)就卡死,最后发现原因是使用的arm-linux-gcc4.7.3交叉编译器的原因,换成4.4.3就好了,原因未明。 uboot移植需要知道的点: 1.要完整一个完全新板的uboot移植并没有想象的那么简单: a.需要对所使用的cpu型号很熟悉(datasheet) ------> 因为要配置时钟、各寄存器等; b.需要对某一架构(如arm、ppc)熟悉 ------> 因为在start.S中要配置svc32模式等; c.需要对某一体系下的汇编指令熟悉(如arm) -----> 因为start.S都是用汇编实现的; d.需要对外设的硬件特性熟悉 -----> 比如uboot对nandflash的裸读/写(还有要熟悉cpu中的nandflash控制器的寄存器读写); 2.uboot编译过程是通过config.h(会包含板级头文件,如mini2440.h)文件内定义的宏去控制条件编译,这是要重点关注的: a.由于第一点所需要的知识点太过底层,而且一般由芯片厂商实现,如果不想进芯片公司的话,没有兴趣去深入了解。因此,关注重点放在了第二点。 在实际的产品开发时,芯片厂商会提供SDK,内含移植好的uboot,但是自研板子的外设不可能和芯片厂商的完全一样。所以,我们就需要知道如何控制uboot 支持不同的外设。 b.如何知道某个driver是由哪个宏控制的?-----> 可以去driver/文件夹内找,在Makefile中会通过宏去控制对应的c文件是否要包含进去进行编译。 c.除了支持不同的外设,还需要知道uboot的默认配置在哪改。------> 也是在config.g文件中的各种宏定义。 3.uboot的调试方式: a.uboot在第一阶段没有初始化串口,所以是没有打印的,这个时候的调试方式主要是通过点灯来查看运行状态。 b.还有可以通过汇编直接操作寄存器来输出相关信息。 c.本次调试还是在确认硬件工作正常的情况下调试的,因此不会去怀疑硬件问题,只需关注代码实现。如果真的是全新的板子,那么Uboot的调试难度肯定大幅增加。 UBOOT启动流程: 时钟初始化、关看门狗、MMU、TLB初始化 ---> RAM初始化 ---> FLASH_TO_RAM ---> ---> board_init_f ---> 串口初始化 ---> RAM信息配置 ---> 代码重定位(对RAM空间进行规划,如堆栈空间等)---> board_init_r ---> NORFLASH初始化 ---> NANDFLASH初始化 ---> ETH以太网PHY初始化 ---> main_loop ---> 接收命令解析命令