虽然已经写了几篇关于uboot移植的、但是觉得整体对uboot的理解还是只停留在copy的层面。
狠下心来,从代码进行uboot的分析,并从新移植一次uboot。
这次更侧重于记录代码分析心得。
使用uboot的版本仍为2010.3版本。
这里有一个很是详尽的start.S分析网站,分析过程借鉴了网站的方法,但也有一些不同的地方
http://www.crifan.com/files/doc/docbook/uboot_starts_analysis/release/html/uboot_starts_analysis.html
总的不同有如下
在网站的分析中,基于代码为arm920t,即ARM9系列芯片,ARM9系列芯片的初始化过程为:
1、设置CPU模式
2、关闭看门狗
3、关闭中断
4、设置堆栈sp指针
5、清除bss段
6、异常中断处理
然后我现在选择的修改模板是arm1176,即ARM11系列芯片,ARM11系列芯片的初始化过程为:
1、设置CPU模式
// -- 关闭看门狗
// -- 关闭中断
2、初始化MMU // ++
3、设置堆栈sp指针
4、清除bss段
5、异常中断处理
两种芯片的start.S的区别一目了然。
接着开始分析代码了。
一切的开始:start.S (文件路径为/cpu/arm1176/start.S)
为了方便跳转阅读,启用行号。
为避免误导,在此说明:
此时我使用的是未经修改的uboot2010版本的start.S,在这篇分析中不会对它进行任何修改。
在随后的blog中才对start.S进行修改并阐述理由,修改处必有类似 git diff 的说明
1、头文件
1 /*
2 * ……
3 */
4
5 #include 6 #include 7 #ifdef CONFIG_ENABLE_MMU 8 #include 9 #endif 10 #include 11 12 #if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE) 13 #define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE 14 #endif 头文件部分不必赘述,但是这里有一个不得不说的地方 13 #define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE 为了解析这个定义,找到了 /include/configs/smdk6400.h /* NAND U-Boot load and start address */ #define CONFIG_SYS_UBOOT_BASE (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000) 继续跳转搜索 CONFIG_SYS_MAPPED_RAM_BASE: #ifdef CONFIG_ENABLE_MMU #define CONFIG_SYS_MAPPED_RAM_BASE 0xc0000000 #define CONFIG_BOOTCOMMAND 'nand read 0xc0018000 0x60000 0x1c0000;' 'bootm 0xc0018000' #else #define CONFIG_SYS_MAPPED_RAM_BASE CONFIG_SYS_SDRAM_BASE #define CONFIG_BOOTCOMMAND 'nand read 0x50018000 0x60000 0x1c0000;' 'bootm 0x50018000' #endif 很显然了,在MMU工作的状态下: #define CONFIG_SYS_MAPPED_RAM_BASE 0xc0000000 MMU工作就是开发板播到从NAND flash启动的状态。 而在MMU未工作的状态下: #define CONFIG_SYS_MAPPED_RAM_BASE CONFIG_SYS_SDRAM_BASE .... #define CONFIG_SYS_SDRAM_BASE 0x50000000 从这里,可以理解在使用dnw下载的时候,Download Address为 #define CONFIG_SYS_UBOOT_BASE (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000) // 0x5000000 + 0x07e00000 = 0x57e00000 uboot是bootloader的一种,要更为准确地描述这两种状态可以说为 1、启动加载(Boot loading)模式,即自主'(Autonomous)模式; 2、下载(Downloading)模式。 更为详细的描述可以参详 http://blog.csdn.net/r91987/article/details/6695007 接下来进入正文分析了 1 /* 2 ************************************************************************* 3 * 4 * Jump vector table as in table 3.1 in [1] 5 * 6 ************************************************************************* 7 */ 8 9 .globl _start 10 _start: b reset //跳转到reset处执行,即下一段代码的44行 //但此时不必急着看reset的执行代码,可以继续顺序往下 11 #ifndef CONFIG_NAND_SPL //定义NAND_SPL时 12 ldr pc, _undefined_instruction //ldr = Load Register 13 ldr pc, _software_interrupt //软件中断 14 ldr pc, _prefetch_abort //预取指中止 15 ldr pc, _data_abort //数据中止 16 ldr pc, _not_used //保留 17 ldr pc, _irq //IRQ中断 18 ldr pc, _fiq //FIQ中断 19 //这里的七种异常就是ARM的七种异常处理类型,对应的声明在 20 - 33行 20 _undefined_instruction: //.word = 32bit , 这里可以理解为 _undef.. = &undef.. 21 .word undefined_instruction //这里将地址放入 _undef.. ,而_undef的地址又放入pc 22 _software_interrupt: //双层取址,所以最终送入pc的数据为 undefined_instruction 23 .word software_interrupt //以下含义相同 24 _prefetch_abort: 25 .word prefetch_abort //pc 是 ARM 的指令寄存器 26 _data_abort: //将这些异常送入 pc ,意为让 ARM 运行这些指令的初始化代码(后文可见) 27 .word data_abort 28 _not_used: 29 .word not_used 30 _irq: 31 .word irq 32 _fiq: 33 .word fiq 34 _pad: 35 .word 0x12345678 /* now 16*4=64 */ 36 #else 37 . = _start + 64 38 #endif 39 40 .global _end_vect 41 _end_vect: 42 .balignl 16,0xdeadbeef // .balignl 为对其指令,意为让以下的代码按16位对其 //不足为则补上0xdeadbeef //很有意思的dead beef,为数不多的能用16进制表示的单词 接下来为正式的启动指令了 1 /* 2 ************************************************************************* 3 * 4 * Startup Code (reset vector) 5 * 6 * do important init only if we don't start from memory! 7 * setup Memory and board specific bits prior to relocation. 8 * relocate armboot to ram 9 * setup stack 10 * 11 ************************************************************************* 12 */ 13 14 _TEXT_BASE: 15 .word TEXT_BASE //这里是 .text 的 base ,即代码段的基址 16 17 /* 18 * Below variable is very important because we use MMU in U-Boot. 19 * Without it, we cannot run code correctly before MMU is ON. 20 * by scsuh. 21 */ 22 _TEXT_PHY_BASE: //上面的注释很清晰了 23 .word CONFIG_SYS_PHY_UBOOT_BASE 24 25 .globl _armboot_start //此处声明了 _armboot_start 指向 _start 26 _armboot_start: 27 .word _start 28 29 /* 30 * These are defined in the board-specific linker script. 31 */ 32 .globl _bss_start //此处的标号其实最终指向的是链接脚本文件(.lds)中的定义 33 _bss_start: 34 .word __bss_start 35 36 .globl _bss_end //同上 37 _bss_end: 38 .word _end 39 40 /* 41 * the actual reset code 42 */ 43 44 reset: //这里就是start之后跳转的地方了 45 /* 46 * set the cpu to SVC32 mode 47 */ //SVC模式也成为管理模式,是操作系统的一种保护模式 48 mrs r0, cpsr //mrs为读寄存器指令 49 bic r0, r0, #0x3f //清除r0的低7位 50 orr r0, r0, #0xd3 //将r0置为0b1101_0011,我们只看低5位 51 msr cpsr, r0 //查CPSR处理器模式位知SVC模式位就是0b1_0011 至此,CPU的SVC模式设置成功了。 最后补充一个内容,.lds文件是编译脚本文件,展开可以看成ld script。 这里的 ld 对应于编译器的 arm-linux-ld。 有关于.lds文件的说明,可以参阅 http://blog.csdn.net/pottichu/article/details/4261289 在后面的篇幅中,也会涉及.lds文件的修改。
上一篇:S3C6410之uboot回炉再造(3)lowlevle_init.S
下一篇:uboot nand erase 的显示错误修复
推荐阅读最新更新时间:2024-11-01 19:50
设计资源 培训 开发板 精华推荐
- AM2S-2407SH30Z 7.2V 2瓦直流转直流转换器的典型应用
- AD5348 并行接口、八路电压输出、12 位 DAC 的典型应用
- ADA4000-1ARZ-R7运算放大器建立时间电路的典型应用电路
- arduino uno
- 使用 Richtek Technology Corporation 的 RT9917 的参考设计
- RD-330,用于 LCD 显示器的 25.4W、5V、14V AC 到 DC 多输出电源的参考设计
- 使用 NXP Semiconductors 的 MPC5553 的参考设计
- STR-NCP171-EVK:支持 Strata 的 NCP171 - 具有 0.6V 至 3.3V 固定输出电压的 80mA 双电源模式 LDO
- AD8604ARUZ 高端运算放大器电流监视器的典型应用
- 使用 Microchip Technology 的 TC660 的参考设计