UBoot user-customization 过程 ( for a certain medical system)
-u中基本变量和其展开过程
- 输入
make smdk2416_config
- 跳转到目标位置
smd2416_config: unconfig
$(MKCONFIG) $(@:_config=) arm xxx xx xxx
#跳入makeconfig
- mkconfig 确定基本变量 ARCH,CPU,BOARD 【建立必要链接】,
export出相关变量;变量导入到config.mk.基本配置完成 - 输入
make
启动编译
以上是UBOOT的基本流程
链接和运行过程.
- 根据运行的过程来看UBOOT是怎么完成它的功能的。
- start.S ()一般在cpu目录下。 体系结构相关的代码里面。为上电后前期布局使用。注意代码跳转的地方:
relocate:
adr r0, _start
ldr r1, _TEXT_BASE
ldr r1, _TEXT_PHY_BASE
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2
add r2, r0, r2
- start_armboot() 与板载内容相关,一般为初始化板载设备的,如串口,USB,LCD,NAND等之类的设备。位于lib_arm目录下board.c中。核心部分代码如下: gd参考这里;
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;//初始化的函数表
char *s;
gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");
memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
memset (gd->bd, 0, sizeof (bd_t));
monitor_flash_len = _bss_start - _armboot_start;
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}//各种初始化函数的执行, init_fnc_ptr 就在board.c中
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
nand_init();//nand 初始化
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
/* MAC Address */
{
int i;
ulong reg;
char *s, *e;
char tmp[64];
i = getenv_r ("ethaddr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
#ifdef CONFIG_HAS_ETH1
i = getenv_r ("eth1addr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
#endif//网络初始化
devices_init (); /* get the devices list going. */ //设备初始化
jumptable_init (); //跳转表初始化
console_init_r (); /* fully init console as a device */ //terminal
/* enable exceptions */
enable_interrupts (); //中断
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
/* NOTREACHED - no way out of command loop except booting */
}
- init_sequence 函数
init_sequence就是指的上面的那个init_fnc_ptr的初始化过程,init_fnc_ptr的列表如下(ARM的)
init_fnc_t *init_sequence[] = {
cpu_init, /* basic cpu dependent setup */
board_init, /* basic board dependent setup */
interrupt_init, /* set up exceptions */
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
dram_init, /* configure available RAM banks */
display_dram_config,
NULL,
};
- main_loop()
前期一系列的初始化之后,进入main_loop主循环,main_loop只有两件事,一是 如果没什么事儿uboot进入内核启动,如果需要在uboot下配置,那就进入uboot的命令行。main_loop函数位于:/common/main.c中 As follows: ( 更细致的分析可以参考这里)
void main_loop (void)
{
run_command (p, 0);
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
s = getenv ("bootdelay");
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
s = getenv ("bootcmd");
debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
parse_string_outer(s, FLAG_PARSE_SEMICOLON |
FLAG_EXIT_FROM_LOOP);
}
#endif /* CONFIG_BOOTDELAY */
for (;;) {
len = readline (CFG_PROMPT);
flag = 0; /* assume no special flags for now */
if (len > 0)
strcpy (lastcommand, console_buffer);
else if (len == 0)
flag |= CMD_FLAG_REPEAT;
if (len == -1)
puts ("<INTERRUPT>\n");
else
rc = run_command (lastcommand, flag);
if (rc <= 0) {
/* invalid command or not repeatable, forget it */
lastcommand[0] = 0;
}
}
#endif /*CFG_HUSH_PARSER*/
}