u-boot源码分析(2440第一阶段)

来源:互联网 发布:php fatal error 编辑:程序博客网 时间:2024/04/28 04:12

预习知识
arm指令
1、LDR指令
LDR指令的格式为:
LDR{条件} 目的寄存器,<存储器地址>
LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为 目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计中比较常用,且寻址方式灵活多样,请读者认真掌握。
指令示例:
LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。

LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。
LDR R0,[R1,R2] ! ;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地 址

;R1+R2写入R1。
LDR R0,[R1,#8] ! ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址 R1

;+8写入R1。
LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址 R1+

;R2写入R1。
LDR R0,[R1,R2,LSL#2]! ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并

;将新地址R1+R2×4写入R1。
LDR R0,[R1],R2,LSL#2 ;将存储器地址为R1的字数据读入 寄存器R0,并将新地

;址R1+R2×4写入R1。
2、BL指令
BL指令的格式为:

BL{条件} 目标地址
BL是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC的当前内容,因此,可以通过将R14的内容重新加载到PC中,来返回到跳转指令之后的那个 指令处执行。该指令是实现子程序调用的一个基本但常用的手段。

以 下指令:

BL Label ;当程序无条件跳转到标号Label处执行时,同时将当前的 PC值保存到
;R14(LR)中
4、STR指令
STR指令的格式为:
STR{条件} 源寄存器,<存储器地址>
STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。 该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。
指令示例:
STR R0,[R1],#8 ;将R0中的字数据写入以R1为地址的存储器中,并 将新地址

;R1+8写入R1。
STR R0,[R1,#8] ;将R0中的字数据写入以R1+8为地址的存储器中。
分析:
程序入口 _start: //根据链接文件中可知道
启动流程;
这里写图片描述

各代码模块如下:
设置异常向量表

.text            .global _start_start:    b reset               /*设置异常向量表*/    ldr pc, _undifined_instruction    ldr pc, _software_interrupt    ldr pc, _prefetch_abort    ldr pc, _data_abort    ldr pc, _not_used    ldr pc, _irq    ldr pc, _fiq_undifined_instruction: .word undifined_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 reset           /*前面是标号,后面是装载32位的地址*/undifined_instruction:       /*未定义*/    nopsoftware_interrupt:    nopprefetch_abort:    nopdata_abort:    nopnot_used:                   /*空位*/    nopirq:    nopfiq:        nopreset:    bl set_svc    bl disable_watchdog    bl disable_interrupt    bl disable_mmu    bl init_clock    bl init_sdram    bl copy_to_ram    bl light_led

设置SVC模式
通过cpsr寄存器设置工作模式
这里写图片描述

方法 先清零 (bic )后 置1( orr) 二进制10011(即为关闭模式)转换为16进制为13
或者d3(区别为 I F 也置1,屏蔽了中断和快速中断)
知识点对于cpsr spar 的访问必须先把它们放到通用寄存器中,不能直接进行修改

set_svc:    mrs r0, cpsr       /*cpsr->r0*/    bic r0, r0,#0x1f   /*后5位清零,保存在r0*/    orr r0, r0,#0xd3    msr cpsr, r0    mov pc, lr

关闭看门狗
原理图
这里写图片描述
通过WTCON寄存器控制
这里写图片描述

#define PWTCON 0x53000000     /*保存寄存器的地址*/disable_watchdog:    ldr r0, =PWTCON           /*因为ldr是伪指令*/    mov r1, #0x0              /*mov指令只能访问通用寄存器*/    str r1, [r0]               /*存储器的访问指令*/    mov pc, lr

关闭中断
①cpsr寄存器的I F 位
②中断屏蔽寄存器
这里写图片描述
这里写图片描述
往寄存器中全部写1就可以实现

disable_interrupt:    mvn r1, #0x0         /*全f传到r1中*/    ldr r0, =0x4a000008  /*控制寄存器的地址*/      str r1, [r0]        /*R1->[R0]*/    mov pc, lr

关闭MMU和cacsh
cacsh 是一种容量小但存取速度非常快的存储器分为I-cacsh 和d-cacsh
这里写图片描述
MMU
作用1,虚拟内存与物理内存的映射 2 设置修改内存的访问级别
由CP15寄存器控制
方法:①使Icacsh和Dcacsh失效
这里写图片描述

②关闭icacsh dcacsh mmu
这里写图片描述
这里写图片描述
也是先读后写

disable_mmu:    mcr p15,0,r0,c7,c7,0         /*无效I D cacsh*/    mrc p15,0,r0,c1,c0,0         /*读到r0中*/    bic r0, r0, #0x00000007         mcr p15,0,r0,c1,c0,0       /*重新写回contral寄存器*/    mov pc, lr

时钟初始化
信号的产生 PLL(锁相环)
时钟工作流程:
①上电几毫秒,晶振输出稳定,FCIK=晶振频率,nRESET信号恢复高电平后,CPU开始执行命令
②程序开头启动MPLL,设置MPLL的寄存器
③设置MPLL的寄存器后,需要等待一段时间(Look-time),MPLL才输出稳定,在这段时间内 FCLK 停振,CPU停止工作。Look-Time的时间由寄存器LOCKTIME设置。
这里写图片描述
配置流程:
这里写图片描述
设置ARM频率的快查表
这里写图片描述

#define CLKDIVN 0x4c000014#define MPLLCON 0x4c000004#define MPLL_400MHZ ((92<<12)|(2<<4)|(1<<0))   设置arm频率 通过快查表得init_clock:    ldr r0, =CLKDIVN    mov r1, #0x5            0b101    str r1, [r0]

设置CPU异步模式
这里写图片描述
其中 nf ia,由CP15寄存器的31 和30 位可得
设置ARM核的频率
寄存器为MPLLCON

    mcr p15,0,r0,c1,c0,0    orr r0,r0,#0xc0000000          1100 0000 0000 0000...    mcr p15,0,r0,c1,c0,0    ldr r0, =MPLLCON              装载地址    ldr r1, =MPLL_400MHZ    str r1, [r0]    mov pc, lr

内存初始化
内存 (.DRAM .SRAM)
2440开发板使用的内存是SDRAM(放在Bank 6 7):同步动态随机存储器
内存的表结构 L-Bank 一块内存一般有4个L-Bank
寻址信息:
L-Bank选择信号
行地址
列地址
内存容量计算公式:4*单元的数目*单元和容量
这里写图片描述
还未整理完待补充

#define mem_contrl 0x48000000init_sdram:    ldr r0, =mem_contrl     add r3, r0, #4*13    adrl r1, mem_data0:    ldr r2, [r1], #4    str r2, [r0], #4    cmp r0, r3    bne 0b    mov pc, lrcopy_to_ram:    ldr r0, =0x0    ldr r1, =0x30008000    add r3, r0, #1024*4copy_loop:    ldr r2, [r0], #4    str r2, [r1], #4    cmp r0, r3    bne copy_loop    mov pc, lrmem_data:    .long 0x22000000     0010 0010 0000 0000 ...    .long 0x00000700     默认值    .long 0x00000700    .long 0x00000700    .long 0x00000700    .long 0x00000700    .long 0x00000700    .long 0x00018001        .long 0x00018001    .long 0x008c04f5    .long 0x000000b1    .long 0x00000030    .long 0x00000030

点亮LED
概念:GPIO 通用输入输出端口 ,至少含有两个寄存器,控制寄存器GPFCON选择输入还是输出,数据寄存器GPFDAT存放数据
设计思路
这里写图片描述
这里写图片描述

#define GPFCON 0x56000050#define GPFDAT 0x56000054light_led:    ldr r0, =GPBCON    mov r1, #0x1500          01010100000000    str r1, [r0]    ldr r0, =GPBDAT    mov r1, #0xcf               11001111    str r1, [r0]    mov pc, lr

链接器脚本文件(即为后缀为elf格式文件)

OUTPUT_ARCH(arm)       /*通过两个宏,指明输出格式为armENTRY(_start)           指明程序的入口为_start处SECTIONS{    . = 0x30000000;     链接的起始位置(此值为2440的地址)    . =ALLGN(4);        四字节对齐    .text :    {    start.o(.text)          *(.text)    }    . = ALLGN(4);    .data:    {    *(.data)       所有的数据段    }    . =ALLGN(4);    bass_start = .;      使用变量记录bss段的起始地址    .bass:    {    *(.bss)    }    bass_end = .;        记录变量的结束地址}
0 0
原创粉丝点击