u-boot启动过程分解 1
这篇文章是tiny6410到手以后分析的第一个程序后写下的记录,由于各种原因整理一半以后就被搁置了,有些未解决问题, U-Boot启动代码分析第一部分(汇编语言): ?????? 主要完成cpu初始化所涉及到寄存器设置,并将第二部分C语言代码复制到RAM中; ?????? 此部分内容起始于/cpu/s3c64xx/S3c6410/start.S; 涉及文件: ?????? /cpu/s3c64xx/S3c6410/start.S ?????? /board/Samsung/Mini6410/lowlevel_init.S??? ?????? Note:此文件夹为FriendlyARM针对Mini6410修改代码,移植于Smdk6410 ?????? /include/s3c6410.h
存储器映射定义:
上电后执行动作:
2.2 配置ONENAND控制器: #ifdef CONFIG_BOOT_ONENAND ????? ldr?? r0,=0x70000000?????????? @ onenand controller setup ????? orr?? r0,#0x100000 ????? ldr?? r1,=0x4000 ????? orr?? r1,r1,#0xe0 ????? str?? r1,[r0] ? #if defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430) ????? orr?? r0,#300?????????? @ disable watchdog ????? mov r1,#1 ????? str?? r1,[r0] ? ????? mov r1,#0x23000000?????????? @ start buffer register ????? orr?? r1,#0x30000 ????? orr?? r1,#0xc800 #else ????? mov r1,=0x20000000?????????? @ start buffer register ????? orr?? r1,#0xc30000 ????? orr?? r1,#0xc800 #endif ? ????? sub? r0,#0x0400???????????? @ start address1 register ? ????? ldr?? r2,[r1,#0x84]????????????? @ ecc bypass ????? orr?? r2,r2,#0x100 ????? str?? r2,#0x84] ? ????? mov r3,#0x0???????? @ DFS,FBA ????? str?? r3,[r0,#0x00] ????? str?? r3,#0x04]????????????? @ select dataram for DDP as 0 ? ????? mov r4,#0x104???????????? @ interrupt register ????? mov r5,#0x0002?????????? @ FPA,FSA ????? mov r6,#0x0800?????????? @ BSA ? onenand_bl1_load: ????? str?? r5,#0x1c]????????????? @ save FPA,FSA ????? orr?? r6,r6,#0x02???????? @ BSC ????? str?? r6,#0x00]????????????? @ save BSA,BSC ????? str?? r3,r4]???????????? @ clear interrupt ????? str?? r3,#0x80]????????????? @ write load command ? ????? mov r7,#0x100???????????? @ need small delay ? onenand_wait_loop1: ????? subs r7,r7,#0x1 ????? bne? onenand_wait_loop1 ? ????? add? r5,r5,#0x2?????????? @ next FPA,FSA ????? sub? r6,#0x2 ????? add? r6,#0x200??????? @ next BSA ????? cmp r5,#0x8 ????? bne? onenand_bl1_load #endif 若启动定义了CONFIG_BOOT_ONENAND,对ONENAND flash 初始化,此类型ROM暂时不涉及,内容跳过。 ? 2.3 调用lowlevel_init对底层的初始化: lowlevel_init: ?????? mov r12,lr???? /*保存程序返回地址,待调用执行完成后返回原地址*/ ? ?????? /* LED on only #8 */ ?????? ldr?? r0,=ELFIN_GPIO_BASE ?????? ldr?? r1,=0x55540000 ?????? str?? r1,#GPNCON_OFFSET] ? ?????? ldr?? r1,=0x55555555 ?????? str?? r1,#GPNPUD_OFFSET] ? ?????? ldr?? r1,=0xf000 ?????? str?? r1,#GPNDAT_OFFSET] ? ?????? ldr?? r0,=0x1 ?????? str?? r1,#GPECON_OFFSET] ?????? ldr?? r1,=0x0 ?????? str?? r1,#GPEDAT_OFFSET] ? ?????? ldr?? r0,=0x2A5AAAAA ?????? str?? r1,#GPPCON_OFFSET] ?????? ldr?? r1,#GPPDAT_OFFSET] ?????? ? ?????? ldr?? r1,#MEM1DRVCON_OFFSET] ?????? /*以上为配置GPNIO、GPEIO、GPPIO端口输出*/ ?????? /* Disable Watchdog关闭看门狗 */ ?????? ldr?? r0,=0x7e000000?????????? @0x7e004000 ?????? orr?? r0,#0x4000 ?????? mov r1,#0 ?????? str?? r1,[r0] ? ?????? @ External interrupt pending clear清除外部中断标志 ?????? ldr?? r0,=(ELFIN_GPIO_BASE+EINTPEND_OFFSET)??? /*EINTPEND*/ ?????? ldr?? r1,[r0] ?????? str?? r1,[r0] ? ?????? ldr?? r0,=ELFIN_VIC0_BASE_ADDR ?????? @0x71200000 ?????? ldr?? r1,=ELFIN_VIC1_BASE_ADDR ?????? @0x71300000 ? ?????? @ Disable all interrupts (VIC0 and VIC1)关闭中断 ?????? mvn r3,#0x0 ?????? str?? r3,#oINTMSK] ?????? str?? r3,#oINTMSK] ? ?????? @ Set all interrupts as IRQ设置所有中断类型为IRQ ?????? mov r3,#oINTMOD] ?????? str?? r3,#oINTMOD] ? ?????? @ Pending Interrupt Clear清除中断标志 ?????? mov r3,#oVECTADDR] ?????? str?? r3,#oVECTADDR] ?????? /* * 以下为系统时钟初始化、串口初始化、NAND flash初始化调用,均为 * 对寄存器相应位设置,参考用户手册 */ /* * init system clock :关闭看门狗、屏蔽中断、设置FCLK:HCLK:PCLK时* 钟比例 */ ?????? bl system_clock_init ? ?????? /* for UART */ ?????? bl uart_asm_init ? #if defined(CONFIG_NAND) ?????? /* simple init for NAND */ ?????? bl nand_asm_init #endif /* * 猜测:此部分已屏蔽判断初始化地址,转为跳转至电源唤醒模式处 */ #if 0 ?????? ldr?? r0,=0xff000fff ?????? bic?? r1,pc,r0??????? /* r0 <- current base addr of code */ ?????? ldr?? r2,_TEXT_BASE???????? /* r1 <- original base addr in ram */ ?????? bic?? r2,r0??????? /* r0 <- current base addr of code */ ?????? cmp ????? r1,r2??????????????????? /* compare r0,r1????????????????? */ ?????? beq? 1f????????????????? /* r0 == r1 then skip sdram init?? */ #endif ? ?????? bl???? mem_ctrl_asm_init ? #if 1 ??????? ldr???? r0,=(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) ??????? ldr???? r1,[r0] ??????? bic???? r1,#0xfffffff7 ??????? cmp???? r1,#0x8 ??????? beq???? wakeup_reset ? #endif /* * UART channel 0 transmit buffer register setting 0x4b4b4b4b */ 1: ?????? ldr?? r0,=ELFIN_UART_BASE ?????? ldr?? r1,=0x4b4b4b4b ?????? str?? r1,#UTXH_OFFSET] ? ?????? mov lr,r12 ?????? mov pc,lr ? 此刻lowlevle_inti执行完成,返回start.S中line240 2.4 判断启动地址并复制程序至RAM: ????? ldr?? r0,=0xff000fff ????? bic?? r1,r0??????? /* r0 <- current base addr of code */ ????? ldr?? r2,_TEXT_BASE???????? /* r1 <- original base addr in ram */ ????? bic?? r2,r0??????? /* r0 <- current base addr of code */ ????? cmp???? r1,r2????????????????? /* compare r0,r1????????????????? */ ????? beq???? after_copy???????????? /* r0 == r1 then skip flash copy?? */ ? 此处判断程序运行地址是否在RAM中,如果没有,复制启动程序否则调用after_copy; ? 2.5 不同ROM设备的程序复制工作 ??????? Line252-line364针对NOR FLASH/NAND FLASH/MOVINAND FLASH/ONE NAND FLASH设备启动的代码复制进行区分设置,此部分代码量较大,不再附上; ? 2.6 copy code 后进行的工作(line365-line393): ?????? 1. GPP输出0xc00(why??) ?????? 2. enable domain access(why??) 3. 设置TTB寄存器 4. 使能MMU ? 2.7 清除RAM空间(line397-line423): ?????? 1. 通过_TEXT_BASE地址推算出映像的起始地址; ?????? 2. 设置_bss_start、_bss_end地址; ?????? 3. 清除bss空间; ? 2.8 程序跳转到_start_armboot处。 U-Boot启动第二部分(C语言): ?????? 继续汇编程序后的_start_armboot衔接部分,此部分已复制到RAM中,转为C语言启动过程继续; ?????? 此部分内容起始于:/Lib_arm/Board.c ?????? 涉及文件: ????????????? /Lib_arm/Board.c C语言的入口函数:/board/Lib_arm/board.c void start_armboot(void); 1.?????? 定义所需变量并为全局变量指针gd初始化: ????? init_fnc_t **init_fnc_ptr; ????? char *s; #ifndef CFG_NO_FLASH ????? ulong size; #endif ? #if defined(CONFIG_VFD) || defined(CONFIG_LCD) ????? unsigned long addr; #endif ? #if defined(CONFIG_BOOT_MOVINAND) ????? uint *magic = (uint *) (PHYS_SDRAM_1); #endif ? ????? /* Pointer is writable since we allocated a register for it */ #ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */ ????? ulong gd_base; ? ????? gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t); #ifdef CONFIG_USE_IRQ ????? gd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ); #endif ????? gd = (gd_t*)gd_base; #else ????? gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); #endif ? ????? /* compiler optimization barrier needed for GCC >= 3.4 */ ????? __asm__ __volatile__("": : :"memory"); ? ????? memset ((void*)gd,sizeof (gd_t)); ????? gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); ????? memset (gd->bd,sizeof (bd_t)); ? monitor_flash_len = _bss_start - _armboot_start; ?????? 此处定义init_fnc_ptr,s指针; 如果未定义CFG_NO_FLASH定义size; 如果定义CONFIG_VFD或CONFIG_LCD则定义addr; 如果定义CONFIG_BOOT_MOVI_NAND则定义magic并初始化为PHYS_SDRAM_1; ? 如果定义CONFIG_MEMORY_UPPER_ CODE则定义gd_base并初始化为SDRAM起始地址;如果定义CONFIG_USE_IRQ重新计算,减去IRQ和FIQ长度,并将gd_base计算值作为地址对gd初始化; 对gd指针初始化设置内存空间; 对gd->bd指针初始化地址,并设置内存空间; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |