uboot详细解读
大多数bootloader都分为stage1和stage2两部分,u-boot也不例外。依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。 #include <config.h> @由顶层的mkconfig生成,其中只包含了一个文件:configs/<顶层makefile中6个参数的第1个参数>.h?? /* ?*************************************************************************?*?* Jump vector table as in table 3.1 in [1]?*/ 注:ARM微处理器支持字节(8位)、半字(16位)、字(32位)3种数据类型 @转指令,通过硬件实现。他们就是异常向量表。ARM在上电复位后,@是从0x00000000开始启动的,其实如果bootloader存在,在执行 @下面第一条指令后,就无条件跳转到start_code,下面一部分并没@执行。设置异常向量表的作用是识别bootloader。以后系统每当有@异常出现,则CPU会根据异常号,从内存的0x00000000处开始查表@做相应的处理 /****************************************************** ;当一个异常出现以后,ARM会自动执行以下几个步骤: .globl _start??/*系统复位位置,整个程序入口*/ @reset用b,就是因为reset在MMU建立前后都有可能发生 @对于ARM数据从内存到CPU之间的移动只能通过L/S指令,如:ldr r0,0x12345678为把0x12345678内存中的数据写到r0中,还有一个就是ldr伪指令,如:ldr r0,=0x12345678为把0x12345678地址写到r0中,mov只能完成寄存器间数据的移动,而且立即数长度限制在8位 _undefined_instruction:?.word undefined_instruction_software_interrupt:?.word software_interrupt_prefetch_abort:?.word prefetch_abort_data_abort:??.word data_abort_not_used:??.word not_used_irq:???.word irq_fiq:???.word fiq ?.balignl 16,0xdeadbeef @?.align伪操作用于表示对齐方式:通过添加填充字节使当前位置 @满足一定的对齐方式。.balign的作用同.align。 @幂,缺省为4。fill是填充内容,缺省用0填充。max是填充字节@数最大值,如果填充字节数超过max,??就不进行对齐,例如: 【参考好野人的窝,于关u-boot中的.balignl 16,0xdeadbeef的理解http://haoyeren.blog.sohu.com/84511571.html】 /*?* Startup Code (called from the ARM reset exception vector)?* do important init only if we don't start from memory!?* relocate armboot to ram?* setup stack?* jump to second stage @保存变量的数据区,保存一些全局变量,用于BOOT程序从FLASH拷贝@到RAM,或者其它的使用。 @来的 _TEXT_BASE: @因为linux开始地址是0x30000000,我这里是64M SDRAM,所以@TEXT_BASE = 0x33F80000?????.word?TEXT_BASE?/*uboot映像在SDRAM中的重定位地址*/ @义了代码在运行时所在的地址,?那么_TEXT_BASE中保存了这个地 @址(这个TEXT_BASE怎么来的还不清楚) .globl _armboot_start_armboot_start:?.word _start ?* These are defined in the board-specific linker script.?*/ .globl _bss_start???? .globl _bss_end_bss_end:?.word _end @中断的堆栈设置 #ifdef CONFIG_USE_IRQ/* IRQ stack memory (calculated at run-time) */.globl IRQ_STACK_STARTIRQ_STACK_START:?.word?0x0badc0de .globl FIQ_STACK_STARTFIQ_STACK_START:?.word 0x0badc0de#endif ? ?* the actual start code ?mrs?r0,cpsr @以下是点灯了,这里应该会牵涉到硬件设置,移植的时候应该可以不要?bl coloured_LED_init?bl red_LED_on @针对AT91RM9200进行特殊处理#if?defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)? * relocate exception table?ldr?r0,=_start?ldr?r1,=0x0?mov?r2,#16copyex:?subs?r2,r2,#1 @针对S3C2400和S3C2410进行特殊处理 @关闭看门狗定时器的自动复位功能并屏蔽所有中断,上电后看门狗为开,中断为关# if defined(CONFIG_S3C2400)#? define pWTCON??0x15300000#? define INTMSK??0x14400008?/* Interupt-Controller base addresses */#? define CLKDIVN?0x14800014?/* clock divisor register */#else?@s3c2410的配置 ?dr???? r0,=pWTCON ?mov???? r1,#0x0?str???? r1,[r0] ? * mask all IRQs by setting all bits in the INTMR - default?mov?r1,#0xffffffff?str?r1,68)"># if defined(CONFIG_S3C2410)@2410好像应该为7ff才对(不理解uboot为何是这个数字) /* FCLK:HCLK:PCLK = 1:2:4 */?/* default FCLK is 120 MHz ! */ ? * we do sys-critical inits only at reboot,? * not when booting from ram! @调试阶段的代码是直接在RAM中运行的,而最后需要把这些代码?@固化到Flash中,因此U-Boot需要自己从Flash转移到 copy_loop:?ldmia?r0!,{r3-r10}??/* copy from source address [r0]??? */ @从源地址[r0]读取8个字节到寄存器,每读一个就更新一次r0地址 @据块 ?cmp?r0,r2???/* until source end addreee [r2]??? */ ?/* Set up the stack????????? */ ldr?r0,_TEXT_BASE??/* upper 128 KiB: relocated uboot?? */ @获取分配区域起始指针, sub?r0,#CONFIG_SYS_MALLOC_LEN?/* malloc area??? */ @CFG_MALLOC_LEN=128*1024+CFG_ENV_SIZE=128*1024+0x1@0000=192K /* bdinfo?? */ @CFG_GBL_DATA_SIZE????128---size in bytes reserved for initial data?用来存储开发板信息#ifdef CONFIG_USE_IRQ @这里如果需要使用IRQ,?还有给IRQ保留堆栈空间,?一般不使用.?sub?r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)#endif?sub?sp,#12??/* leave 3 words for abort-stack??? */ @该部分将未初始化数据段_bss_start----_bss_end中的数据?@清零clear_bss:clbss_l:str?r2,[r0]??/* clear loop...??????????????????? */?add?r0,r1?ble?clbss_l @跳到阶段二C语言中去?ldr?pc,_start_armboot _start_armboot:?.word start_armboot ?* CPU_init_critical registers?* setup important registers?* setup memory timing @在“relocate:?/* relocate U-Boot to RAM?*/?”之前被调用 cpu_init_crit:??????? * flush v4 I/D caches ? * disable MMU stuff and caches ? * before relocating,we have to setup RAM timing? * because memory timing is board-dependend,you will? * find a lowlevel_init.S in your board directory. #if?defined(CONFIG_AT91RM9200EK) #else?bl?lowlevel_init @在重定向代码之前,必须初始化内存时序,因为重定向时需要将@flash中的代码复制到内存中lowlevel_init在@/board/smdk2410/lowlevel_init.S中。??????????????? ?mov?lr,ip?mov?pc,lr #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ ?* Interrupt handling ?#define S_OLD_R0?68 #define S_PSR??64#define S_PC??60#define S_LR??56#define S_SP??52 #define S_IP??48#define S_FP??44#define S_R10??40#define S_R9??36#define S_R8??32#define S_R7??28#define S_R6??24#define S_R5??20#define S_R4??16#define S_R3??12#define S_R2??8#define S_R1??4#define S_R0??0 #define MODE_SVC 0x13#define I_BIT? 0x80 ?* use bad_save_user_regs for abort/prefetch/undef/swi ...?* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling?*/ ?.macro?bad_save_user_regs?stmia?sp,{r0 - r12}???@ Calling r0-r12?ldmia?r2,{r2 - r3}???@ get pc,#S_FRAME_SIZE??@ restore sp_SVC ?add?r5,#S_SP?stmia?r5,{r0 - r3}???@ save sp_SVC,lr_SVC,pc,sp?.endm ?.macro?irq_save_user_regs?add???? r7,#S_PC?stmdb?? r7,{sp,lr}^?????????????????? @ Calling SP,LR?str???? lr,[r7,#0]??????????????????? @ Save calling PC?mrs???? r6,spsr?str???? r6,#4]??????????????????? @ Save CPSR?str???? r0,#8]??????????????????? @ Save OLD_R0?.macro?irq_restore_user_regs?ldmia?sp,{r0 - lr}^???@ Calling r0 - lr?ldr?lr,[sp,#S_PC]???@ Get PC?add?sp,68)">?subs?pc,lr,#4???@ return & move spsr_svc into cpsr?.macro get_bad_stack?ldr?r13,_armboot_start??@ setup our mode stack?sub?r13,r13,#(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack ?str?lr,[r13]???@ save caller lr / spsr ?mrs?lr,[r13,#4] ?mov?r13,#MODE_SVC???@ prepare SVC-Mode?@ msr?spsr_c,r13?msr?spsr,pc?movs?pc,68)">?.macro get_irq_stack???@ setup IRQ stack?ldr?sp,IRQ_STACK_START?.macro get_fiq_stack???@ setup FIQ stack/*********************************************************?* exception handlers?********************************************************/ ?.align?5software_interrupt:?bl?do_software_interrupt prefetch_abort:?bl?do_prefetch_abort data_abort:?bl?do_data_abort not_used:?bl?do_not_used #ifdef CONFIG_USE_IRQ irq:?get_irq_stack?irq_save_user_regs?bl?do_irq?irq_restore_user_regs fiq:?get_fiq_stack?/* someone ought to write a more effiction fiq_save_user_regs */?bl?do_fiq#else ?bl?do_irq ?bl?do_fiq #endif?/*CONFIG_USE_IRQ*/可知start.S的流程为:异常向量——上电复位后进入复位异常向量——跳到启动代码处——设置处理器进入管理模式——关闭看门狗——关闭中断——设置时钟分频——关闭MMU和CACHE——进入lowlever_init.S——检查当前代码所处的位置,如果在FLASH中就将代码搬移到RAM中 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |