学习 uboot 之二启动代码start.S分析
2018-01-03 19:11
441 查看
下面我们正式开始讲解Uboot的启动代码,由uboot的链接脚本能够知道uboot链接时放在代码最开头的是CPU/$(CPUDIR)/start.S
在正式看代码之前,我们需要了解S3C2440的stepping stone机制,即NAND FLASH启动时,S3C2440会利用自己内部的控制器将NAND FLASH前4K的内容拷贝到片内的RAM中并将片内RAM映射到0地址开始的地方。
下面我们就来看下cpu\arm920t目录下的start.S
以上关于协处理器的操作,如果有不明白的地方请参考 ARM920T TRM,里面有详细的描述,这里不再展开叙述。
上面大致介绍了uboot的启动过程的汇编代码分析,主要做了如下的几件事情
设置CPU 工作模式为SVC,关闭IRQ和FIQ
关闭看门狗,置位中断屏蔽寄存器器关闭所有中断
清除I-cache,D-cache,TLB,关闭MMU等
配置RAM,为后面复制FLASH中uboot到RAM做准备
uboot代码重定位
重定位后,赋值PC指针,直接跳转到搬移后的位置开始执行
分析了start.S以后,下一篇接着分析start_armboot
在正式看代码之前,我们需要了解S3C2440的stepping stone机制,即NAND FLASH启动时,S3C2440会利用自己内部的控制器将NAND FLASH前4K的内容拷贝到片内的RAM中并将片内RAM映射到0地址开始的地方。
下面我们就来看下cpu\arm920t目录下的start.S
#include <config.h> /*包含板子的配置文件这里是100ask24x0.h*/ #include <version.h> /*中断向量表,存放跳转到各个中断处理的指令*/ .globl _start _start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq _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 _TEXT_BASE: /*在链接脚本中定义的,值也在链接过程中制定值为0x33F80000*/ .word TEXT_BASE .globl _armboot_start /*全局变量定义,并且进行了初始化*/ _armboot_start: .word _start /* * These are defined in the board-specific linker script. */ /*下面这些全局变量的值都是在链接脚本中定义的*/ .globl _bss_start _bss_start: .word __bss_start .globl _bss_end _bss_end: .word _end .globl FREE_RAM_END FREE_RAM_END: .word 0x0badc0de .globl FREE_RAM_SIZE FREE_RAM_SIZE: .word 0x0badc0de .globl PreLoadedONRAM PreLoadedONRAM: .word 0 /*如果使用中断或者快中断需要定义栈空间*/ #ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */ .globl IRQ_STACK_START IRQ_STACK_START: .word 0x0badc0de /* IRQ stack memory (calculated at run-time) */ .globl FIQ_STACK_START FIQ_STACK_START: .word 0x0badc0de #endif /* 正式开始reset中断向量代码讲解 当软件重启或者硬件重启后从reset开始执行 */ reset: /* * set the cpu to SVC32 mode */ mrs r0,cpsr /*将cpsr读入到r0*/ bic r0,r0,#0x1f /*将低5位全部清0*/ orr r0,r0,#0xd3 /*0xd3= 11010011关闭IRQ,FIQ,置CPU为ARM状态,CPU为SVC模式*/ msr cpsr,r0 /将修改后的r0存入cpsr /* turn off the watchdog */ #if defined(CONFIG_S3C2400) #define pWTCON 0x15300000 #define INTMSK 0x14400008 /* Interupt-Controller base addresses */ #define CLKDIVN 0x14800014 /* clock divisor register */ #elif defined(CONFIG_S3C2410) /*宏定义了相关的相关寄存器的地址,具体请查看S3C2440的手册*/ · #define pWTCON 0x53000000 #define INTMOD 0X4A000004 #define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ #define INTSUBMSK 0x4A00001C #define CLKDIVN 0x4C000014 /* clock divisor register */ #endif #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) ldr r0, =pWTCON /*将看门狗的寄存器地址放到r0中*/ mov r1, #0x0 /*将r1置0*/ str r1, [r0] /*将看门狗寄存器置全0*/ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] /*设置中断屏蔽寄存器,屏蔽所有中断*/ #if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK /*同上,屏蔽一些次级中断*/ str r1, [r0] #endif #endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */ /*对于从FLASH启动,下面代码会执行*/ /* r0 <- current position of code */ /*根据当前PC的值计算出_start代表的地址,相对寻址,与位置无关*/ adr r0, _start ldr r1, _TEXT_BASE /*操作后r1=0X33F80000*/ /* test if we run from flash or RAM */ cmp r0, r1 /*从flash启动,跳转到cpu_init_crit,具体操作在下面介绍*/ blne cpu_init_crit /*cpu_init_crit 在下面分析*/ /*在将完整uboot从NAND FLASH复制到RAM之前,留出一些空间做其它功能之用*/ stack_setup: ldr r0, _TEXT_BASE /*在_TEXT_BASE下方预留出其它功能的区域*/ sub r0, r0, #CFG_MALLOC_LEN /* malloc area留出malloc区域*/ /* 留出128字节空间存放global data 和board info*/ sub r0, r0, #CFG_GBL_DATA_SIZE #ifdef CONFIG_USE_IRQ /*留出IRQ和FIQ栈的地址*/ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12 /* leave 3 words for abort-stack */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT /*进行FCLK:HCLK:PCLK时钟设置,函数在boot_init.c中这里不介绍*/ bl clock_init #endif /*开始复制uboot到RAM中*/ #ifndef CONFIG_SKIP_RELOCATE_UBOOT relocate: /* relocate U-Boot to RAM */ /* r0 <- current position of code */ /*前面解释过adr是相对寻址,实现位置无关,目前代码开始执行的起始位置,这里为0*/ adr r0, _start ldr r1, _TEXT_BASE /* test if we run from flash or RAM *//*需要重新定位到的地址*/ cmp r0, r1 /* dont reloc during debug */ beq clear_bss ldr r2, _armboot_start ldr r3, _bss_start /* r2 <- size of armboot 计算得到除了BSS段外整个uboot的大小 */ sub r2, r3, r2 /*调用NAND FLASH的read函数,将代码从FLASH写入到SDRAM _TEXT_BASE处*/ /* r0: source, r1: dest, r2: size */ bl CopyCode2Ram #endif /* CONFIG_SKIP_RELOCATE_UBOOT */ clear_bss: ldr r0, _bss_start /* find start of bss segment */ ldr r1, _bss_end /* stop here */ mov r2, #0x00000000 /* clear */ clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 ble clbss_l /*将bss段的内容全部清零*/ SetLoadFlag: /* Set a global flag, PreLoadedONRAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* dont reloc during debug */ ldr r2, =PreLoadedONRAM /*r2中是PreLoadedONRAM全局变量的地址*/ mov r3, #1 /*如果相等,设置PreLoadedONRAM为1,表示从RAM中启动*/ streq r3, [r2] ldr pc, _start_armboot /*跳转到start_armboot*/ _start_armboot: .word start_armboot
cpu_init_crit: /* * flush v4 I/D caches */ mov r0, #0 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache *//*清除I-cache,D-cache*/ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ /*清除所有的TLB*/ /* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 /*先从协处理器中,读出C1寄存器的值*/ /*设置中断向量的从0x00000000,关闭MMU*/ bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) /*disable MMU,DCACHE,ALIGNMENT*/ bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) orr r0, r0, #0x00000002 @ set bit 2 (A) Align /*使能对齐检查*/ orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache /*使能I-cache*/ mcr p15, 0, r0, c1, c0, 0 /*将r0的值写C1*/ mov ip, lr /*暂存lr*/ bl lowlevel_init /*配置SDRAM*/ mov lr, ip mov pc, lr
以上关于协处理器的操作,如果有不明白的地方请参考 ARM920T TRM,里面有详细的描述,这里不再展开叙述。
.globl lowlevel_init lowlevel_init: /* memory control configuration */ /* make r0 relative the current location so that it */ /* reads SMRDATA out of FLASH rather than memory ! */ ldr r0, =SMRDATA ldr r1, _TEXT_BASE sub r0, r0, r1 /*计算出SMRDATA和_TEXT_BASE之间的偏移,因为现在是从0地址开始运行,所以偏移就是目前SMRDATA的地址*/ ldr r1, =BWSCON /* Bus Width Status Controller */ add r2, r0, #13*4 /*跟SDRAM相关的寄存器共13个,每个4字节*/ 0: ldr r3, [r0], #4 /*r0中存放配置放置的地址*/ str r3, [r1], #4 /*r1中存放的是BWSCON寄存器的地址*/ cmp r2, r0 bne 0b /* everything is fine now */ mov pc, lr /*配置完成以后,返回*/ .ltorg /* the literal pools origin */ SMRDATA: .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) .word 0xb1 .word 0x30 .word 0x30
上面大致介绍了uboot的启动过程的汇编代码分析,主要做了如下的几件事情
设置CPU 工作模式为SVC,关闭IRQ和FIQ
关闭看门狗,置位中断屏蔽寄存器器关闭所有中断
清除I-cache,D-cache,TLB,关闭MMU等
配置RAM,为后面复制FLASH中uboot到RAM做准备
uboot代码重定位
重定位后,赋值PC指针,直接跳转到搬移后的位置开始执行
分析了start.S以后,下一篇接着分析start_armboot
相关文章推荐
- u-boot_smdkv210 分析二:启动代码start.s分析
- u-boot_smdkv210 分析二:启动代码start.s分析
- Uboot优美代码赏析2:第一阶段_硬件平台启动start.s分析
- u-boot启动代码之start_armboot分析(原创)
- u-boot_smdkv210 分析二:启动代码start.s分析
- u-boot_smdkv210 分析二:启动代码start.s分析
- U-Boot启动代码分析(MIPS)
- u-boot_smdkv210 分析四:启动代码汇编部分总结
- 移植u-boot学习笔记2-----分析启动过程之内存分布
- (others)U-Boot启动代码分析
- VxWorks启动代码romStart()函数分析
- Uboot优美代码赏析2:第一阶段_硬件平台启动start.s分析 .
- 嵌入式Linux启动过程分析4-u-boot-1step-start.S
- U-Boot系列之三:u-boot整体结构及启动代码分析(有加入一些新东西)
- Linux启动过程简略分析-start_kernel部分代码阅读
- Linux 启动代码 Start_kernel()函数分析
- U-Boot启动第二阶段代码分析
- QNX学习笔记-Neutrino-QNX-boot启动流程分析
- 大数据学习笔记:启动脚本分析,start-dfs.cmd与start-yarn.cmd
- SpringBoot系列三:SpringBoot基本概念(统一父 pom 管理、SpringBoot 代码测试、启动注解分析、配置访问路径、使用内置对象、项目打包发布)