从前面一节Exynos 4412的启动过程分析 ,我们知道:一上电,exynos4412首先执行固化在IROM中的代码,iROM首先设置程序运行环境 (比如关看门狗、关中断、关MMU 、设置栈 、设置栈 、启动PLL等 ),然后根据OM引脚确定启动设备 (NAND Flash/SD 卡/其他 ),把 BL1从里面读出存入iRAM的0x02021400地址处,最后启动 BL1; BL1从SD卡适当的位置读入14K 字节的数据,存在iRAM地址0x02023400处,所以BL2不能大于(14K – 4) 字节,这里引出了为什么写这一节的原因:如果我们的程序很大,大于14K怎么办????
下面我们先来介绍两个概念:
一是程序当前所处的地址,即程序在运行时,所处的当前地址;二是程序的链接地址,即程序运行时应该位于的运行地址。编译程序时,可以指定程序的链接地址。
什么是重定位
对于Tiny4412而言,前面我们已经说过:启动时BL1只会从sd等启动设备中拷贝14K的代码到IRAM中,那么当我们的程序超过14K怎么办?那就需要我们在前14K的代码中将整个程序完完整整地拷贝到DRAM等其他更大存储空间,然后再跳转到DRAM中继续运行我们的代码,这个拷贝然后跳转的过程就叫重定位。
本章中我们主要学习如何重定位,但是并不会涉如何使用到DRAM,而是简单地将代码从IRAM的0x02023400处拷贝到IRAM的0x0202a000处,然后跳转到0x0202a000处继续运行我们的代码。
一、程序说明
基于上一个实验的代码进行修改,修改了start,S文件以及链接脚本文件:
在start.S文件中增加如下代码:
.text
.globl _start
_start:
/* 关闭看门狗 */
ldr r0, =0x10060000
mov r1, #0x0
str r1, [r0]
/* 启动Icache */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0x00001000 //打开ICache
//bic r0, r0, #0x00001000 //关闭ICache
mcr p15, 0, r0, c1, c0, 0
/* 重定位 - 将代码从0x02023400处拷贝到链接地址0x0202a000处(在链接脚本里指定的),并跳转到这个地址去执行 */
adr r0, _start /* adr指令用于读取_start在当前的运行的物理地址,即0x02023400 */
ldr r1, =_start /* 读取_start的链接地址,即0x0202a000 */
ldr r2, =bss_start /* 读取bss段的起始地址,用于计算需要拷贝的字节多少 */
cmp r0, r1
beq clean_bss /* 如果r0=r1,则跳转到clean_bss,说明此时已经在链接地址处了 */
/* 如果r0!=r1,则进行如下的拷贝 */
copy_loop:
ldr r3, [r0], #4 /* 源 */
str r3, [r1], #4 /* 目的 */
cmp r1, r2 /* 判断是否已经拷贝完 */
bne copy_loop /* 如果没有拷贝完就继续拷贝 */
/* 清bss段 */
clean_bss:
ldr r0, =bss_start /* r0保存bss段的起始地址 */
ldr r1, =bss_end /* r1保存bss段的起始地址 */
cmp r0, r1
beq run_on_dram /* 如果r0=r1,则跳转到run_on_dram,说明bss段里边没有变量 */
mov r2, #0
clear_loop:
str r2, [r0], #4
cmp r0, r1
bne clear_loop
ldr sp, =0x02060000
/* 跳转 */
run_on_dram:
ldr pc, =main /* 执行完这句话之后,PC就指向了main的链接地址 */
这段代码主要实现了代码重定位、清除BSS段、以及跳转到链接地址继续运行,注释说的已经很明白了,有什么的不熟悉的,大家可以留言共同探讨。
链接脚本reload.lds修改为如下:
SECTIONS {
. = 0x0202A000;
.text : {
*(.text)
}
.rodata ALIGN(4) : {
*(.rodata*)
}
.data ALIGN(4) : {
*(.data*)
}
bss_start = . ;
.bss ALIGN(4) : {
*(.bss) *(COMMON)
}
bss_end = . ;
}
主要增加了bss段的起始bss_start及结束bss_end 的定义,这两个标号在start.S中被用到。
二、编译、烧写、运行
1.编译
通过FTP或者其他工具将文件上传到服务器上去,输入make命令进行编译将得到reload.bin文件。
2.烧写
将SD卡插入电脑,并让VmWare里的Ubuntu识别出来,然后执行如下命令:
sudo ./sd_fusing.sh /dev/sdb ../8_reload/reload.bin
将SD卡插入Tiny4412开发板,上电,你会看到和上一节的运行效果一样(因为我们没有修改LED的显示效果,只是修改了程序的运行地址,这个对外是看不出区别的)。
三、反汇编文件分析
将反汇编文件reload.dis,从服务器上下载下来,我们进行简单分析一下:
从上图可以看出,程序的链接地址确实是我们在连接脚本里指定的0x0202a000
我们再来看看跳转的那条指令;
202a060: e59ff010 ldr pc, [pc, #16] ; 202a078 将当前PC的值加上24后的地址的内容赋给PC,即: 0x202a060 + 8 +16 = 0x0202a078 将0x0202a078这个地址的值赋给PC 0x0202a0b0这个地址正是main函数的入口地址。 我在自己的开发板上面试验成功。有兴趣的小伙伴可以自行试验。
上一篇:Exynos4412 文件系统制作(三)—— 文件系统移植
下一篇:TINY4412 裸机程序之点灯
推荐阅读最新更新时间:2024-11-07 16:38
推荐帖子
- 谁有 at89s51实验板的资料啊?
- 朋友给我一个是实验板子,上面接了好多元件,6个数码管,步进机,A/D转换器,4*4键盘..液晶显示,可都不知道这些元件是怎么接到那些引脚上的,原来写的程序也不知道要怎么改.....谁有at89s51实验板的资料啊?可都不知道这些元件是怎么接到那些引脚上的,不同的器件设计有不同的通信接口,以及自身的操作方式.这才能用起来.最好有原理图在,不然的话就要麻烦些...但是,也不是说不能办事.万用表啥的,总有吧?呵呵举个例子:6个数码管你要看一个它的显示方式,是动态显示还是静态显示.(不
- kids85 嵌入式系统
- 新产品快递High-Side Current Monitors Simplify Measurement at High Voltage
- Diodes’High-SideCurrentMonitorsSimplifyMeasurementatHighVoltageDiodesIncorporatedhasintroducedafamilyof6highreliabilitycurrentmonitorsfor40Vand60Voperation.TheZXCT108Xdevicesdetectcurrentinahighsidesens
- 安_然 模拟电子
- WindRiver 2000万美元收购移动软件公司
- WindRiver系统公司日前宣布,WindRiver将通过现金和股票的形式,以2000万美元的价格收购InterpeakAB公司。InterpeakAB公司是网络、安全以及移动中介软件的领导供货商,其中间件软件可使新一代设备安全地连接至互联网。这项收购案将为WindRiver系统公司注入高品质安全网络技术,进一步扩大其设备软件平台的版图,同时强化其为设备制造商提供更高的平台扩充性、安全性与关键认证支持的能力。WindRiver公司主席、董事长、首席执行官KenKlein认为,W
- rain 单片机
- 最新版的TivaWare_C_Series-2.0.1.11577出来了
- 俺刚装的这个版本软件,但不知道是否有所提高,然而在dk-tm4c123g增加了新的例程,俺原来装的是1.0版的 最新版的TivaWare_C_Series-2.0.1.11577出来了固件库增加超过250页,改动不能说不大固件库增加超过250页奈斯~~~在哪下载啊。。。给个链接。。。最好还是不用,时钟配置都有BUG。。。。。大家觉发表于2014-7-1710:08最好还是不用,时钟配置都有BUG。。。。。 应该会有改进的,有bug不可怕,怕的是不知道
- 平湖秋月 微控制器 MCU
- 430F169AD采样工作有间断期
- #includemsp430x16x.h#defineNum_of_Results8uintADC_BUF0;uintADC_BUF1;uintsumI;//定义电流采样均值uintsumV;//定义电压采样均值//***************************主程序*****************************************voidmain(void){WDTCTL=WDTPW+WDT
- dearestwsc 微控制器 MCU
- ARM 嵌入式main()的运行过程
- 刚入手嵌入式,看了一些资料,有一点不是很明白,就是在做完初始化init.s的操作之后,系统转入main()入口,那么这之后系统是如何捕获消息并触发相应的时间的??应该在哪写这些代码呢??ARM嵌入式main()的运行过程看不明白楼主的意思,帮你顶一下吧!裸机程序??裸机的话就跟单片机一样的,别告诉我没学过单片机啊!!!呵呵就是说正常的程序是从第一句执行到最后一句,那么进入main()后像捕获键盘消息的操作和处理过程应该怎么写???还真没学过单片机,公司临时项目,没搞这方面
- hehewyx ARM技术
设计资源 培训 开发板 精华推荐
- 使用 Analog Devices 的 ADXL212 的参考设计
- 使用 LTC3639EMSE 5 至 150V 输入至 5V/100mA 输出稳压器和 20kHz 最小突发频率的典型应用
- NCP3232N 大电流同步降压转换器的典型应用
- L78L05AC正压稳压器Edit boost电路的典型应用
- 4 通道 I2C 多路复用器提供地址扩展、总线缓冲和故障管理
- LTC2970 的典型应用 - 双路 I2C 电源监视器和裕度控制器
- AD8534ARZ-REEL 用于多媒体和汽车应用的单电源、平衡线路驱动器的典型应用
- 使用 NXP Semiconductors 的 SKEAZN8AMFK 的参考设计
- LTC4218 热插拔控制器的典型应用
- LTC3716EG 演示板,2 相移动 CPU VRM,7 至 24Vin,0.6 至 1.75Vout @ 25A(最大性能)