AT91Bootstrap1.16第一阶段汇编程序详解
以下是bootstrap的启动过程,主要分为两个步骤: 第一阶段:汇编程序,主要负责最低层的硬件初始化 第二阶段:c程序,主要负责SDRAM初始化,Dataflash的拷贝工作,完成程序在SDRAM中运行的准备工作 第一阶段主要是在crt0_gnu.S中,和前面的链接脚本文件有很大关系() crt0_gnu.S的汇编程序是bootstrap的第一阶段执行过程: 主要实现的目的是: 1 建立中断向量表(_exception_vectors:在此标号处) 2 设置堆栈SP(代码在内部SRAM0中运行,堆栈在内部SRAM1中运行。启动过程是cpu启动后先检测外部的dataflash,有接,则拷贝dataflash从0开始的4K字节到内部SRAM1中,开始执行) (_init_stack:在此处) 3 主晶振使能为主时钟(设置时钟_setup_clocks: 使能主晶振_enable_mosc: 打开主晶振_switch_to_mosc: ) 4 数据段拷贝 (_init_data:) 5 BSS段数据初始化(_init_bss:) 6 底层基本初始化完成,跳转到C代码的MAIN函数中执行(_branch_main:) 至此bootstrap第一阶段汇编代码的任务执行完毕。接下来执行C代码。 ? 以下是汇编代码的详细注释: .sectionstart 定义域中包含的段 .text 代码段开始 #include"include/part.h" 包含头文件,供编译使用 /*---------------------------------------------------------------------------- Area Definition 区域定义 Must be defined as function to put first inthe code as it must be mapped at offset 0 of the flash EBI_CSR0,ie. ataddress 0 before remap.必须先定义一个函数进入第一段代码必须映射到flash(EBI_CSR0)的偏移0地址处例如地址重映射后在0地址 --------------------------------------------------------------------------*/ /*Application startup entry point */应用程序开始进入点 .globl reset 定义全局符号 .align 4 以下以4字节对齐 reset: //Exception vectors (should be a branch to be detected as a valid code by the rom异常向量表8个 _exception_vectors: b reset_vector /* reset */ b undef_vector /* Undefined Instruction */ b swi_vector /*Software Interrupt */ b pabt_vector /*Prefetch Abort */ b dabt_vector /* DataAbort */ .word _edata /* Size of the image for SAM-BA */ b irq_vector /* IRQ : read the AIC */ b fiq_vector /* FIQ */ undef_vector: b undef_vector swi_vector: b swi_vector pabt_vector: b pabt_vector dabt_vector: b dabt_vector rsvd_vector: b rsvd_vector irq_vector: b irq_vector fiq_vector: b fiq_vector reset_vector: /*Init the stack */堆栈初始化 _init_stack: ldr sp,=TOP_OF_MEM //TOP_OF_MEMORY=0x301000 //在Makefile文件中的# Link Address andTop_of_Memory //LINK_ADDR=0x20 0000 内部SRAM0 的起始位置 0x20 0000 共4k //TOP_OF_MEMORY=0x30 1000 内部SRAM1的起始位置 0x30 1000 共4K #ifdef CFG_NORFLASH //NORFLASH启动时要使用的代码段,本次移植使用的是DATAFLASH /* When running from NOR,we must relocate to SRAM prior toresetting the clocks and SMC timings. */ _relocate_to_sram: #if 0 /*relocation is slow,disable the watchdog or it will trigger */ ldr r1,=0xFFFFFD44 mov r2,#0x00008000 str r2,[r1] #endif mov r1,#0 ldr r3,=_stext ldr r4,=_edata 1: cmp r3,r4 ldrcc r2,[r1],#4 strcc r2,[r3],sans-serif; line-height:24px; text-indent:2em"> bcc 1b ldr pc,=_setup_clocks #endif /* CFG_NORFLASH */ _setup_clocks: 设置时钟寄存器 /*Test if main oscillator is enabled */测试主晶振是否使能 ldr r0,=AT91C_PMC_SR // (PMC) Status Register 0xFFFFFC68 ldr r2,=AT91C_PMC_MOSCS //R2= (0x1 << 0) ands r1,r1,r2 //R1=R1与R2 判断主晶振是否起振了 // r1=1 则晶振已经启动 r1=0则晶振未启动 bne _switch_to_mosc //未起振,则继续执行函数_enable_mosc执行启动主晶振 bne不等于 则跳转 /*Enable the main oscillator */使能主晶振 _enable_mosc:
orr r1,r2 // r1,=r1或 r2 str r1,[r0] //将r1的值写入寄存器 AT91C_PMC_MOR
beq 1b //如果等于0,就继续循环检测,为1为止说明晶振已启动跳到下面函数处理 /*Test if MCK == SLOW CLOCK */ _switch_to_mosc: // 到此函数说明主晶振已起振
and r2,r2,r1 //R2=R2与R1 cmp r1,r2 //判断R2是否位0 /* No=> Do nothing */是0,则主时钟选择是MCK ==SLOW CLOCK bne _init_bss //R1=R2直接初始化bss段 /*Yes => Switch to the main oscillator */打开主晶振开关
beq 1b//如果不等于,就继续循环检测,直到为1为止,跳到下面函数处理 //Copythe data section in RAM at .data link address从连接地址.data开始拷贝数据段到 RAM _init_data: ldmia r2,{r1,r3,r4} //r1=[ r2] r3=[ r2] +4 r4=[ r2] +8 /*Initialize the bss segment *///初始化bss段 _init_bss: adr r2,_lp_bss //伪指令:小范围内读取数据 /*Branch on C code Main function (with interworking) *///进入C代码MAIN函数 _branch_main: mov lr,pc //将LR寄存器的值直接写入道PC中 bx r4 //此处真正跳转到MAIN函数执行 /*Branch to the application at the end of the bootstrap init *//在bootstrap初始化最后分支进入应用程序中执行 _go: //main函数执行完毕返回,一个地址传递到r0中,此地址是SDRAM中的地址
bx r0 //跳转到main函数执行完毕的返回地址,也就是跳转到bootstrap加载的 //程序(uboot)在SDRAM中的位置 .align _lp_data: .word _etext .word _sdata .word _edata _lp_bss: .word _sbss .word _ebss 问题: 1 _init_data的数据拷贝为什么从代码段的结束位置开始到数据段的结束位置结束????? 2 汇编中bne和beq的各自跳转使用方式??? 3 汇编中 ldmia,ldrcc,strcc,bcc 具体的指令说明?其中的cc是什么意思??? 问题解决办法: 1: 2:汇编中bne和beq的各自跳转使 B是跳转,后面的是跳转条件,EQ 相等 NE 不相等 3: LDMIA? bcc //一旦遇到一个B指令,ARM处理器将立即跳转到给定的目标地址,从那里继续执行 条件助记符: BEQ 相等则跳转, B跳转,EQ相等(,前面有CMP) LDRCC 小于则装载内存数据到寄存器,LDR装载,CC小于 STRCC BCC类似 <助记符>{<执行条件>}{S}<Rd>,<Rn>{,第2操作数} 有S则表示影响CPSR寄存器的值 条件码助记符: EQ 相等 NE 不相等 CS/HS 无符号数大于或等于 CC/LO 无符号数小于 文章转载自:http://www.verydemo.com/demo_c161_i58112.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- angularjs – AngularFire $requireAuth未检测到过期的身份
- scala – Spark ML VectorAssembler返回奇怪的输出
- 我的Docker容器没有IP地址.为什么?
- angularjs解决方案之 子表添加初始化值
- 如何处理一个playframework异常2异步块(scala)
- 解决webservice用Ajax(jquery)传递客户端请求时ip跨域问题(
- AngularJS – 如果child循环为空(过滤),则隐藏父元素
- 使用angularjs对数据进行排序筛选
- angularjs – 从另一个模块获取一个对象(控制器,服务或指令
- Docker容器上的Mysql安装