今天是uboot移植学习第二天,通过csdn博客记录自己的学习过程,希望通过这个方法,使自己所学的知识得到复习和扩展,总结经验发现不足,也希望自己的博客能够给人启发,疑问的到解决。
这次主要对代码分析(1)的第一阶段相关代码分析
设置为管理模式 reset: /* * set the cpu to SVC32 mode */ mrs r0,cpsr① bic r0,r0,#0x1f② orr r0,r0,#0xd3③ msr cpsr,r0④ CPSR 是当前的程序状态寄存器(Current Program Status Register), 而 SPSR 是保存的程序状态寄存器(Saved Program Status Register) 1、 MRS指令 MRS指令的格式为: MRS{条件} 通用寄存器,程序状态寄存器(CPSR或SPSR) MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。该指令一般用在以①:将cpsr(当前程序状态寄存器)的值读到r0中 ②:清除r0中的后5位,因为在cpsr中第五位为模式设置位 ③:将r0第五位或上0xd3 ④:将r0的值写入cpsr,这样就将我们的处理器设置为了管理模式
2、turn off the watchdog——关闭看门狗
ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] 解释:往pWTCON寄存器中写0即可3、mask all IRQs by setting all bits in the INTMR——关闭外部中断
ldr r1, =0x7fff ldr r0, =INTSUBMSK str r1, [r0] 解释:INTSUBMSK寄存器全写1,就把中断给mask了。INTSUBMSK寄存器如下:4、设置时钟比例
/* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] 解析:The S3C2440A supports selection of Dividing Ratio between FCLK, HLCK and PCLK. This ratio is determined by HDIVN and PDIVN of CLKDIVN control register. 通过设置HDIVN and PDIVN of CLKDIVN的值确定时钟的比例5、bl lowlevel_init——存储控制器初始化
ldr r0, =SMRDATA ldr r1, _TEXT_BASE sub r0, r0, r1 ldr r1, =BWSCON /* Bus Width Status Controller 0x48000000*/ add r2, r0, #13*4 解析:刚开始时代码和数据都只是保存在norflash上内存中还没有。 所以不能用链接地址读取SMRDATA开始处的数据。 _TEXT_BASE: .word TEXT_BASE 这个是我们的链接地址,即代码运行时所在的地址。 BWSCON:存储控制器相关寄存器的起始寄存器 SMRDATA:表示13个寄存器的值得存放的开始地址(链接地址)在内存中,但现在不能读取。 sub r0, r0, r1算出SMRDATA的相对地址(在norflash上13个寄存器的值得存放的开始地址)启动时是可以读取的,使得板子启动时不在连接地址上时也能取SMRDATA中的值进行初始化存储控制器。注: 在重定位后,在我们的内存中(sdram)会有我们flash中的内容,在编译时是按链接地址编译,ldr r0, =SMRDATA中r0的值为内存中的地址(即在内存中13个寄存器的值得存放的开始地址,在flash中也有,TEXT_BASE 链接地址也是内存的地址,因此我们要计算出SMRDATA对于TEXT_BASE的相对偏移,这个相对偏移的值就是SMRDATA在flash的起始地址)。
6、重定位——即就是把falsh中的代码复制到ram中,本开发板复制到sdram中;
7、stack_setup——设置堆栈,因为接下来要调c函数,来进行更复杂的处理。
stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo 解析: r0 = TEXT_BASE = 0x33D00000 而关于sub指令: SUB : 减法 (Subtraction) SUB{条件}{S} <dest>, <op 1>, <op 2> dest = op_1 - op_2 SUB 用操作数 one 减去操作数 two,把结果放置到目的寄存器中。操作数 1 是一 个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值: SUB R0, R1, R2 ; R0 = R1 - R2 SUB R0, R1, #256 ; R0 = R1 - 256 SUB R0, R2, R3,LSL#1 ; R0 = R2 - (R3 << 1) 减法可以在有符号和无符号数上进行 #CFG_MALLOC_LEN、#CFG_GBL_DATA_SIZE是宏定义8、clear_bss——清bss段,该段存放的是初始化为零或为未初始化的变量,只要额外的放在一个段就行,使用时取就行; 进入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_start是: .globl _bss_start _bss_start: .word __bss_start 而_bss_end,是: .globl _bss_end _bss_end: .word _end 对应的,__bss_start和_end,都在前面提到过的那个链接脚本里面: u-boot-1.1.6\board\smdk2410\u-boot.lds中的: __bss_start = .; .bss : { *(.bss) } _end = .; 即bss段的起始地址和结束地址 往里面的值全部赋值为0以上对uboot做了个非常粗略的分析,因本人初学记录下的学习笔记,也希望能够帮到正在学习uboot移植的学子,若有不对之处,望各位指出。