第二阶段中首先运行start_armboot函数,在lib_arm/board.c文件中,此函数前几行如下:
- /* Pointer is writable since we allocated a register for it */
-
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); (1)
-
/* compiler optimization barrier needed for GCC >= 3.4 */
-
__asm__ __volatile__("": : :"memory"); (2)
-
-
memset ((void*)gd, 0, sizeof (gd_t)); (3)
-
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); (4)
-
memset (gd->bd, 0, sizeof (bd_t)); (5)
-
-
gd->flags |= GD_FLG_RELOC; (6)
-
-
monitor_flash_len = _bss_start - _armboot_start; (7)
-
-
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { (8)
-
if ((*init_fnc_ptr)() != 0) {
-
hang ();
-
}
-
}
首先gd_t结构体,应注意下,它其中包含结构体db_t的指针。start_armboot函数开始几行主要是在设置gd结构体,在lib_arm/board.c文件开始时有一行宏DECLARE_GLOBAL_DATA_PTR;宏定义在asm-arm/global_data.h文件中定义。
- #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
这句表明引用此宏就会声明一个gd_t结构体的指针,gd指向全局变量并且被指定保存到寄存器r8。函数start_armboot中
(1):_armboot_start定义为程序开始的_start标号,在第二阶段中_start程序代码已经被移动到内存中,不过这个不关这里的事,编译时指定了TEXT_BASE的为编译出程序的起始地址。所以_armboot_start就是TEXT_BASE的地址。这个地址减去CONFIG_SYS_MALLOC_LEN再减去gd_t自身的大小,就是gd这个全局结构体应该存放的地方,然后将地址赋值给gd这个由上述宏声明的指针。在下面一行
(2)是编译器指令,主要是为了禁止从cache读数据,直接从内存读取。详见其他资料。
(3)这句就是为gd指向的区域清出gd_t大小的空间。
(4)(5)两行是设置bd结构体,情况大体与gd相同,
(6)设置标志为重新加在到RAM。
(7)计算uboot整个映像文件的长度,是代码开始地址到BSS段开始地址。
(8)此for循环,循环执行init_sequence函数指令数组中的函数指针所指向的函数。下面大体看一下其中大概有那些函数。
1.board_init,此函数在board/的mini2440.c文件中。它首先定义了两个结构体存储24x0中时钟相关和gpio相关寄存器的地址。因为相关功能的寄存器是在连续地址的,所以可以用一个结构体存储。如存储时钟相关结构体:
- struct s3c24x0_clock_power {
-
S3C24X0_REG32 LOCKTIME;
-
S3C24X0_REG32 MPLLCON;
-
S3C24X0_REG32 UPLLCON;
-
S3C24X0_REG32 CLKCON;
-
S3C24X0_REG32 CLKSLOW;
-
S3C24X0_REG32 CLKDIVN;
-
};
然后设置主时钟频率和USB时钟频率,虽然时钟频率在第一阶段start.S中已经设置过,但是这个还是设置了一边,可能是为了强调分离两个阶段。然后设置GPIO。怎样设置这些寄存器可以参考数据手册,移植到2440上可以根据板子的实际情况设定。这里对GPIO的设置代码注释一下
- gpio->GPACON = 0x007FFFFF; /*23个io端口全部设置为功能引脚*/
-
gpio->GPBCON = 0x00295551; /*B0-B8中B1为输入,其他均为输出,B9和B10为功能*/
-
gpio->GPBUP = 0x000007FF; /*禁止所有B端口的上拉*/
-
gpio->GPCCON = 0xAAAAAAAA; /*C端口全部为功能引脚*/
-
gpio->GPCUP = 0x0000FFFF; /*禁止所有C端口的上拉*/
-
gpio->GPDCON = 0xAAAAAAAA;
-
gpio->GPDUP = 0x0000FFFF;
-
gpio->GPECON = 0xAAAAAAAA;
-
gpio->GPEUP = 0x0000FFFF;
-
gpio->GPFCON = 0x000055AA; /*4个输出,4个外部中断*/
-
gpio->GPFUP = 0x000000FF;
-
gpio->GPGCON = 0xFF95FF3A;
-
gpio->GPGUP = 0x0000FFFF;
-
gpio->GPHCON = 0x0016FAAA;
-
gpio->GPHUP = 0x000007FF;
-
-
gpio->EXTINT0=0x22222222; /*3位设置一个中断 设置为一串2 可以循环所有的触发方式配置*/
-
gpio->EXTINT1=0x22222222;
-
gpio->EXTINT2=0x22222222;
然后这句gd->bd->bi_arch_number = MACH_TYPE_MINI2440;设置机器编码,这个编码要和内核中的匹配。
然后设置内核参数地址!gd->bd->bi_boot_params = 0x30000100。 cache使能(此函数为空)。
2.time_init,此函数是设置定时器的,具体参见datasheet。
各函数也都是进行一些初始化功能,列出如下。
- env_init, /*初始化环境变量,设置gd->env_addr等,具体是哪个源文件中的函数,根据mini2440.h中的定义,相应的Makefile会选择性编译相应源文件*/
-
init_baudrate, /*初始化波特率--lib_arm/board.c 此函数会调用common/cmd_nveidt.c中的getenv_r来获取环境变量。这个函数稍后分析 */
-
serial_init, /* 串口初始化--drivers/serial/serial_s3c24x0.c */
-
console_init_f, /* 控制通讯台初始化阶段1--common/console.c */
-
display_banner, /*打印U-Boot版本、编译的时间--gedit lib_arm/board.c */
-
dram_init, /*配置可用的RAM-- board/samsung/mini2440/mini2440.c */
-
display_dram_config, /* 显示RAM信息--lib_arm/board.c */
getenv_r函数用来获取环境变量安数字返回,getenv则是安字符形式返回环境变量。
getenv函数主要部分:
- for (i=0; env_get_char(i) != '\0'; i=nxt+1) { (1)
-
int val;
-
-
for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) { (2)
-
if (nxt >= CONFIG_ENV_SIZE) {
-
return (NULL);
-
}
-
}
-
if ((val=envmatch((uchar *)name, i)) < 0) (3)
-
continue;
-
return ((char *)env_get_addr(val)); (4)
-
}
(1)每个环境变量之间是以'\0'分割的,如:
"bootargs=" CONFIG_BOOTARGS "\0"
"bootcmd=" CONFIG_BOOTCOMMAND "\0"
i=nxt+1会每次将i加到一个环境变量的开始处索引
(2)将nxt累加到一个环境变量的'\0'结尾出的索引值。
(3)查看此环境变量是否和给定的匹配,匹配则执行(4)返回该变量地址,否则continue
再看回到start_armboot函数。mem_malloc_init为malloc区域清除空间,并设置了mem_malloc_start等变量的值。接着,
- display_flash_config (flash_init ());
flash_init()函数在mini2440/flash.c文件中,在这个文件中添加了对SST_VF1601 nor flash的支持。
- if defined(CONFIG_CMD_NAND)
-
puts ("NAND: ");
-
nand_init(); /* go init the NAND */
-
#endif
nand flash初始化,这里的nand_init()函数使用的是在driver/mtd/nand中的函数,mini2440.c中的已经被注释掉了.
env_relocate ()这个函数将重载环境变量,它将flash中的环境变量,载入到分配的内存中等操作。关于uboot环境变量相关部分以后在分析。
在经过一些初始化函数,直接到main_loop
阅读(862) | 评论(0) | 转发(0) |