logo资料库

U-Boot启动过程完全分析.pdf

第1页 / 共33页
第2页 / 共33页
第3页 / 共33页
第4页 / 共33页
第5页 / 共33页
第6页 / 共33页
第7页 / 共33页
第8页 / 共33页
资料共33页,剩余部分请下载后查看
U-Boot启动过程完全分析 Posted on 2010-07-17 21:31 heaad 阅读(2992) 评论(0) 编辑 收藏 1.1 U-Boot 工作过程 U-Boot 启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶段的功能  硬件设备初始化  加载 U-Boot 第二阶段代码到 RAM 空间  设置好栈  跳转到第二阶段代码入口 (2)第二阶段的功能  初始化本阶段使用的硬件设备  检测系统内存映射  将内核从 Flash 读取到 RAM 中  为内核设置启动参数  调用内核 1.1.1 U-Boot 启动第一阶段代码分析 第一阶段对应的文件是 cpu/arm920t/start.S 和 board/samsung/mini2440/lowlevel_init.S。 U-Boot 启动第一阶段流程如下:
图 2.1 U-Boot 启动第一阶段流程 根据 cpu/arm920t/u-boot.lds 中指定的连接方式: ENTRY(_start) SECTIONS { . = 0x00000000; . = ALIGN(4); .text : { cpu/arm920t/start.o (.text) board/samsung/mini2440/lowlevel_init.o (.text) board/samsung/mini2440/nand_read.o (.text) *(.text) } … … }
第一个链接的是 cpu/arm920t/start.o,因此 u-boot.bin 的入口代码在 cpu/arm920t/start.o 中,其源代码在 cpu/arm920t/start.S 中。下面我们来分析 cpu/arm920t/start.S 的执行。 1. 硬件设备初始化 (1)设置异常向量 cpu/arm920t/start.S 开头有如下的代码: .globl _start _start: b start_code /* 复位 */ 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 /* 软件中断向量 */ /* 预取指令异常向量 */ /* 数据操作异常向量 */ /* 未使用 */ /* irq 中断向量 */ /* 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 .word irq .word fiq _irq: _fiq: .balignl 16,0xdeadbeef 以上代码设置了 ARM 异常向量表,各个异常向量介绍如下: 表 2.1 ARM 异常向量表 地址 异常 进入模式 描述 0x00000000 复位 管理模式 复位电平有效时,产生复位异常,程序跳转 到复位处理程序处执行
0x00000004 未定义指令 未定义模式 遇到不能处理的指令时,产生未定义指令异 常 0x00000008 软件中断 管理模式 执行 SWI 指令产生,用于用户模式下的程序 调用特权操作指令 0x0000000c 预存指令 中止模式 处理器预取指令的地址不存在,或该地址不 允许当前指令访问,产生指令预取中止异常 0x00000010 数据操作 中止模式 处理器数据访问指令的地址不存在,或该地 址不允许当前指令访问时,产生数据中止异 常 0x00000014 未使用 未使用 未使用 0x00000018 IRQ IRQ 外部中断请求有效,且 CPSR 中的 I 位为 0 时, 产生 IRQ 异常 0x0000001c FIQ FIQ 快速中断请求引脚有效,且 CPSR 中的 F 位为 0 时,产生 FIQ 异常 在 cpu/arm920t/start.S 中还有这些异常对应的异常处理程序。当一个异常产生时,CPU 根据异常号在异常向量表 中找到对应的异常向量,然后执行异常向量处的跳转指令,CPU 就跳转到对应的异常处理程序执行。 其中复位异常向量的指令“b start_code”决定了 U-Boot 启动后将自动跳转到标号“start_code”处执行。 (2)CPU 进入 SVC 模式 start_code: /* * set the cpu to SVC32 mode */ mrs r0, cpsr bic r0, r0, #0x1f /*工作模式位清零 */ orr r0, r0, #0xd3 /*工作模式位设置为“10011”(管理模式),并将中断禁止位和快中断禁止位置 1 msr cpsr, r0 以上代码将 CPU 的工作模式位设置为管理模式,并将中断禁止位和快中断禁止位置一,从而屏蔽了 IRQ 和 FIQ 中 */ 断。 (3)设置控制寄存器地址
# if defined(CONFIG_S3C2400) # define pWTCON 0x15300000 # define INTMSK 0x14400008 # define CLKDIVN 0x14800014 #else /* s3c2410 与 s3c2440 下面 4 个寄存器地址相同 */ # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* WATCHDOG 控制寄存器地址 */ /* INTMSK 寄存器地址 */ # define INTSUBMSK 0x4A00001C /* INTSUBMSK 寄存器地址 */ # define CLKDIVN 0x4C000014 /* CLKDIVN 寄存器地址 */ # endif 对与 s3c2440 开发板,以上代码完成了 WATCHDOG,INTMSK,INTSUBMSK,CLKDIVN 四个寄存器的地址的设置。各个 寄存器地址参见参考文献[4] 。 (4)关闭看门狗 ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* 看门狗控制器的最低位为 0 时,看门狗不输出复位信号 */ 以上代码向看门狗控制寄存器写入 0,关闭看门狗。否则在 U-Boot 启动过程中,CPU 将不断重启。 (5)屏蔽中断 /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff /* 某位被置 1 则对应的中断被屏蔽 */ ldr r0, =INTMSK str r1, [r0] INTMSK 是主中断屏蔽寄存器,每一位对应 SRCPND(中断源引脚寄存器)中的一位,表明 SRCPND 相应位代表的中 断请求是否被 CPU 所处理。 根据参考文献 4,INTMSK 寄存器是一个 32 位的寄存器,每位对应一个中断,向其中写入 0xffffffff 就将 INTMSK 寄存器全部位置一,从而屏蔽对应的中断。 # if defined(CONFIG_S3C2440) ldr r1, =0x7fff
ldr r0, =INTSUBMSK str r1, [r0] # endif INTSUBMSK 每一位对应 SUBSRCPND 中的一位,表明 SUBSRCPND 相应位代表的中断请求是否被 CPU 所处理。 根据参考文献 4,INTSUBMSK 寄存器是一个 32 位的寄存器,但是只使用了低 15 位。向其中写入 0x7fff 就是将 INTSUBMSK 寄存器全部有效位(低 15 位)置一,从而屏蔽对应的中断。 (6)设置 MPLLCON,UPLLCON, CLKDIVN # if defined(CONFIG_S3C2440) #define MPLLCON 0x4C000004 #define UPLLCON 0x4C000008 ldr r0, =CLKDIVN mov r1, #5 str r1, [r0] ldr r0, =MPLLCON ldr r1, =0x7F021 str r1, [r0] ldr r0, =UPLLCON ldr r1, =0x38022 str r1, [r0] # else /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] #endif CPU 上电几毫秒后,晶振输出稳定,FCLK=Fin(晶振频率),CPU 开始执行指令。但实际上,FCLK 可以高于 Fin, 为了提高系统时钟,需要用软件来启用 PLL。这就需要设置 CLKDIVN,MPLLCON,UPLLCON 这 3 个寄存器。
CLKDIVN 寄存器用于设置 FCLK,HCLK,PCLK 三者间的比例,可以根据表 2.2 来设置。 表 2.2 S3C2440 的 CLKDIVN 寄存器格式 CLKDIVN 位 说明 HDIVN [2:1] 00 : HCLK = FCLK/1. 01 : HCLK = FCLK/2. 初始值 00 10 : HCLK = FCLK/4 (当 CAMDIVN[9] = 0 时) HCLK= FCLK/8 (当 CAMDIVN[9] = 1 时) 11 : HCLK = FCLK/3 (当 CAMDIVN[8] = 0 时) HCLK = FCLK/6 (当 CAMDIVN[8] = 1 时) PDIVN [0] 0: PCLK = HCLK/1 1: PCLK = HCLK/2 0 设置 CLKDIVN 为 5,就将 HDIVN 设置为二进制的 10,由于 CAMDIVN[9]没有被改变过,取默认值 0,因此 HCLK = FCLK/4。 PDIVN 被设置为 1,因此 PCLK= HCLK/2。因此分频比 FCLK:HCLK:PCLK = 1:4:8 。 MPLLCON 寄存器用于设置 FCLK 与 Fin 的倍数。MPLLCON 的位[19:12]称为 MDIV,位[9:4]称为 PDIV,位[1:0]称为 SDIV。 对于 S3C2440,FCLK 与 Fin 的关系如下面公式: MPLL(FCLK) = (2×m×Fin)/(p× ) 其中: m=MDIC+8,p=PDIV+2,s=SDIV MPLLCON 与 UPLLCON 的值可以根据参考文献 4 中“PLL VALUE SELECTION TABLE”设置。该表部分摘录如下: 表 2.3 推荐 PLL 值 输入频率 输出频率 MDIV PDIV SDIV 12.0000MHz 48.00 MHz 56(0x38) 12.0000MHz 405.00 MHz 127(0x7f) 2 2 2 1 当 mini2440 系统主频设置为 405MHZ,USB 时钟频率设置为 48MHZ 时,系统可以稳定运行,因此设置 MPLLCON 与 UPLLCON 为: MPLLCON=(0x7f<<12) | (0x02<<4) | (0x01) = 0x7f021 UPLLCON=(0x38<<12) | (0x02<<4) | (0x02) = 0x38022 (7)关闭 MMU,cache 接着往下看:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit #endif cpu_init_crit 这段代码在 U-Boot 正常启动时才需要执行,若将 U-Boot 从 RAM 中启动则应该注释掉这段代码。 下面分析一下 cpu_init_crit 到底做了什么: 320 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 321 cpu_init_crit: 322 /* 323 * 使数据 cache 与指令 cache 无效 */ 324 */ 325 mov r0, #0 326 mcr p15, 0, r0, c7, c7, 0 /* 向 c7 写入 0 将使 ICache 与 DCache 无效*/ 327 mcr p15, 0, r0, c8, c7, 0 /* 向 c8 写入 0 将使 TLB 失效 */ 328 329 /* 330 * disable MMU stuff and caches 331 */ 332 mrc p15, 0, r0, c1, c0, 0 /* 读出控制寄存器到 r0 中 */ 333 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 334 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 335 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 336 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 337 mcr p15, 0, r0, c1, c0, 0 /* 保存 r0 到控制寄存器 */ 338 339 /* 340 * before relocating, we have to setup RAM timing 341 * because memory timing is board-dependend, you will 342 * find a lowlevel_init.S in your board directory. 343 */ 344 mov ip, lr
分享到:
收藏