U-Boot,全称 Universal Boot Loader,是遵循GPL条款的开放源码项目。U-Boot的作用是系统引导。U-Boot从FADSROM、8xxROM、PPCBOOT逐步发展演化而来。其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是根据相应的Linux内核源程序进行简化而形成的,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。-----百度百科
U-boot源码分析
移植U-boot
之前,我们首先需要弄明白U-boot本身是怎么运行的,移植的时候需要修改那些东西,这些实际都可以通过阅读源代码实现,这里我们下载的是Emcraft的源码包,因为最终是要在cortex-M系列的处理器上实现。
之所以下载emcraft
的源码包是因为里面已经做了一些相关的porting工作了,比如针对cortex-m
系列的启动函数就在cpu/arm-cortexm3/start.c
,下面就是一个简化的_start
函数:
void _start(void)
{
#if !defined(CONFIG_HW_WATCHDOG)
#if !defined(CONFIG_SYS_M2S)
wdt_disable();
#endif
#else
wdt_enable();
#endif
/*
* Make sure interrupts are disabled.
*/
__disable_irq();
/*
* Copy data and initialize BSS
* This is in lieu of the U-boot "conventional" relocation
* of code & data from Flash to RAM.
* With Cortex-M3, we execute from NVRAM (internal Flash),
* having relocated data to internal RAM (and having cleared the BSS
* area in internal RAM as well)
* Stack grows downwards; the stack base is set-up by the first
* value in the first word in the vectors.
*/
memcpy(&_data_start, &_data_lma_start, &_data_end - &_data_start);
memset(&_bss_start, 0, &_bss_end - &_bss_start);
/*
* Copy RAMCODE separately, if it is separated
*/
#if defined(CONFIG_MEM_RAMCODE_BASE) && defined(CONFIG_MEM_RAMCODE_LEN)
memcpy(&_ramcode_start, &_ramcode_lma_start,
&_ramcode_end - &_ramcode_start);
#endif
/*
* In U-boot (armboot) lingvo, "go to the C code" -
* in fact, with M3, we are at the C code from the very beginning.
* In actuality, this is the jump to the ARM generic start code.
* ...
* Note initialization of _armboot_start below. The ARM generic
* code expects that this variable is set to the upper boundary of
* the malloc pool area.
* For Cortex-M3, where we do not relocate the code to RAM, I set
* the malloc pool right behind the stack. See how armboot_start
* is defined in the CPU specific .lds file.
*/
_armboot_start = (unsigned long)&_mem_stack_base;
start_armboot();
}
这里就是一个比较基本的memor初始化,之后就跳转到和具体CPU以及板子相关的start_armboot函数中去了,在start_armboot
中,uboot首先会初始化一个全局变量gd
和bd
,它们占用内存的一段固定区域。再后面就是一系列的初始化函数,这些函数根据不同的板子也有不同,不过基本都是:
- arch_cpu_init --- CPU clock init
- board_init --- pin相关的init
- interrupt
- timer_init
- get_clocks
- env_init -- 初始化环境变量,这个对u-boot非常重要,我为了简单就没有把环境变量放到Flash里面,而是直接编译的时候弄好,直接放在ram里面,这样就不支持变量的保存操作了。
- init_baudrate
- serial_init --- 串口的初始化,这个我为了简单也是直接用了固定的串口波特率。
- console_init_f --- 基本平台无关,可以直接调用
- dram_init --- 初始化SDRAM,因为一般cortex-M系列处理器RAM都比较小,所以程序需要在SDRAM里面运行,所以要对SDRAM进行初始化,当然如果支持DDR这里就是初始化DDR了。
11.NULL --- 结束初始化循环的一个标志
在初始化完成这个序列之后,我i们还可以选择是不是将堆栈改到SDRAM上去,另外如果系统支持LCD显示等,还需要对显存空间进行必要的初始化操作了。
所有的初始化函数执行完成这之后就会跳转到main_loop
,他是在一个死循环中不停的执行的。也是最终u-boot执行的一个循环,提供一个用户终端界面,可以对用户命令进行解析,启动系统镜像以及对参数配置等等。
总结
以上就是对uboot启动流程的一个非常简单的介绍,其实uboot关键的还是在最后的一个大的循环上面,另外一个就是内存的分配,总的来说u-boot还是比较简单的,后面有时间我们再来看看main_loop
里面究竟执行了哪些程序,以及u-boot是如何实现系统的启动的。
网友评论