一、前言
我使用的是JZ2440,soc是s3c2440,架构是ARM920t,指令集是ARM9。
一般来说,开发板的相关配置都存放在board目录,所以根据在board/100ask24x0的链接脚本u-boot.lds可了解到,u-boot的入口地址为_start,其定义在cpu/arm920t/start.S文件中。
ENTRY(_start) SECTIONS { . = 0x00000000; . = ALIGN(4); .text : { cpu/arm920t/start.o (.text) board/100ask24x0/boot_init.o (.text) *(.text) }
二、对start.S的主要代码分析
1、将CPU设为SVC32模式(CPSR寄存器的具体每一位的含义可参考s3c2440手册)。在该模式下,可以访问受控资源,拥有更多的硬件资源,有利于u-boot进行硬件资源的初始化。
1 .globl _start 2 _start: b reset 3 4 reset: 5 mrs r0,cpsr 6 bic r0,r0,#0x1f 7 orr r0,r0,#0xd3 8 msr cpsr,r0
2、关闭看门狗定时器,禁止中断(s3c2440有两个中断控制器)。
1 # define pWTCON 0x53000000 2 3 # define INTMSK 0x4A000008 4 # define INTSUBMSK 0x4A00001C 5 6 ldr r0, =pWTCON 7 mov r1, #0x0 8 str r1, [r0] 9 10 mov r1, #0xffffffff 11 ldr r0, =INTMSK 12 str r1, [r0] 13 14 ldr r1, =0x7fff 15 ldr r0, =INTSUBMSK 16 str r1, [r0]
3、开始配置s3c2440的时钟。之所以在这里就开始配置时钟,是因为后续的SDRAM初始化使用需要用到时钟进行刷下配置。
(1)在配置完CLKDIVN寄存器后,该寄存器的HDIVN=0x10,根据芯片手册,当HDIVN不为零的时候,CPU总线模式必须由快速总线模式改为异步总线模式。
(2)在配置PPL之前,我们需要配置LOCKTIME寄存器,这是因为配置PPL后到PPL输出稳定的时钟信号也是需要一定的时间的。
//FCLK:HCLK:PCLK = 1:4:8, UCLK=UPLL //FCLK=400MHz, HCLK=100MHz, PCLK=50MHz, UCLK=48MHz #define CLKDIVN 0x4C000014 //Clock divider control register #define MPLLCON 0x4C000004 //MPLL configuration register #define UPLLCON 0x4C000008 //UPLL configuration register #define LOCKTIME 0x4C000000 //PLL lock time count register #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01)) #define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02)) #define S3C2440_CLKDIV (0x05) ldr r1, =CLKDIVN ldr r2, =S3C2440_CLKDIV str r2, [r1] //设为异步总线模式 mrc p15, 0, r1, c1, c0, 0 // read ctrl register orr r1, r1, #0xc0000000 // Asynchronous mcr p15, 0, r1, c1, c0, 0 // write ctrl register ldr r0,=LOCKTIME ldr r1,=0xffffff str r1,[r0] ldr r0,=MPLLCON ldr r1,=S3C2440_MPLL_400MHZ str r1,[r0] ldr r0, =UPLLCON ldr r1, =S3C2440_UPLL_48MHZ str r1, [r0]
4、根据GSTATUS2寄存器来判断当前进入这里是复位还是唤醒,若是唤醒,则调用唤醒函数。
#define GSTATUS2 (0x560000B4) ldr r0, =GSTATUS2 ldr r1, [r0] tst r1, #(1<<1) /* r1&(1<<1) */ bne wake_up
5、判断当前的代码是否运行在SDRAM中,如果没有运行在SDRAM中,则进行cpu的初始化。
(1)_TEXT_BASE定义的是u-boot在SDRAM中运行的入口地址(即_start地址),其定义在board/100ask24x0/config.mk中,值为0x33F80000。
(2)CPU的初始化包括flush v4 I/D caches、disable MMU stuff and caches、lowlevel_init(SDRAM初始化)。
adr r0, _start /* current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don‘t reloc during debug */ blne cpu_init_crit
6、在调用C语言函数之前,需要设置好堆栈,这是因为CPU在运行C语言函数时候,会自动使用堆栈
(1)以"CONFIG_"开头的宏一般都定义在include/configs/100ask24x0.h这个头文件中
(2)栈是向下增长的,所以这里是指向栈顶
#define CFG_ENV_SIZE 0x20000 /* 环境变量的总大小,共128K */ #define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024) /* 为malloc()函数分配的大小,共256K */ #define CFG_GBL_DATA_SIZE 128 /* 全局变量struct gd_t gd的大小,共128 */ #define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack,共4K */ #define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack,共4K */ ldr r0, _TEXT_BASE sub r0, r0, #CFG_MALLOC_LEN sub r0, r0, #CFG_GBL_DATA_SIZE sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) sub sp, r0, #12 /* leave 3 words for abort-stack */
(3)示意图如下所示
7、代码的重定向,也就是将代码从Flash中拷贝到SDRAM中
(1)根据APCS(ARM过程调用标准),C语言的前四个形参可以通过访问r0~r3寄存器得到,其余的形参就在堆栈中了
.globl _armboot_start _armboot_start: .word _start relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don‘t reloc during debug */ beq clear_bss /* bss段清零 */ ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ bl CopyCode2Ram /* r0: source, r1: dest, r2: size */ 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
8、设置一个全局变量,用于后续的u-boot运行
.globl PreLoadedONRAM PreLoadedONRAM: .word 0 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 /* don‘t reloc during debug */ ldr r2, =PreLoadedONRAM mov r3, #1 streq r3, [r2] /* 如果r0=r1,也就是已经在SDRAM中运行了,那么 PreLoadedONRAM 就为1 */
9、跳入start_armboot函数,进行相关硬件的初始化
_start_armboot: .word start_armboot ldr pc, _start_armboot
原文:https://www.cnblogs.com/Recca/p/11443734.html