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 = .; 记录变量的结束地址}
- u-boot源码分析(2440第一阶段)
- u-boot-1.1.6 源码分析(2)--第一阶段
- U-Boot启动过程源码分析(1)-第一阶段
- 图解U-Boot:第一阶段源码分析
- 图解U-Boot:第一阶段源码分析
- 图解U-Boot:第一阶段源码分析
- U-boot-1.1.6第一阶段源码分析
- 图解U-Boot:第一阶段源码分析
- U-boot启动第一阶段源码分析
- U-boot第一阶段分析
- U-boot第一阶段分析
- u-boot第一阶段分析(一)
- u-boot第一阶段分析(二)
- u-boot第一阶段分析(三)
- u-boot第一阶段分析(四)
- u-boot第一阶段分析(五)
- U-Boot 启动过程和源码分析(第一阶段)
- u-boot源码分析第一阶段之Start.S
- C#116课的主要内容
- LeetCode 116. Populating Next Right Pointers in Each Node
- cPanel X FTP上传
- 强化学习入门第一讲 马尔科夫决策过程
- IO的分层(转)
- u-boot源码分析(2440第一阶段)
- Python学习之路-历史以及开发环境
- 4 linux 下jni opencv的使用
- 一个遍历二叉树的直观方法
- 杭电acm-1040
- hdu5916 Harmonic Value Description
- 关于堆的判断
- 【程序5】题目:利用条件运算符的嵌套来完成此题:学习成绩>=90分 的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。
- INSERT 语句 (For MySQL)