历史上的今天
今天是:2025年03月25日(星期二)
2020年03月25日 | tiny4412裸机程序——代码重定位
2020-03-25 来源:eefocus
在前面介绍exynos4412芯片启动过程时,我们知道:一上电,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的代码中将整个程序完完整整地拷贝到LPDDR等其他更大存储空间,然后再跳转到LPDDR中继续运行我们的代码,这个拷贝然后跳转的过程就叫重定位。
本章中讲解学习如何重定位,但是并不会涉如何使用到LPDDR,而是简单地将代码从iRAM的0x02023400处拷贝到iRAM的0x02026400处,然后跳转到0x02026400处继续运行我们的代码。
程序文件介绍:
1.start.S文件内容介绍:
.text
.global _start
_start:
//关闭看门狗;关于看门狗的设置可以查看Spec 1357页
ldr r0, =0x10060000 //将0x10060000数字保存到R0寄存器中
mov r1, #0x0 //将0x0数字保存到R1寄存器中
str r1, [r0] //将R1寄存器中的数字(0)保存到R0寄存器数字表示的地址中
//重定位整个代码到0x0202_6400地址处;这个地址位于iRAM里面
adr r0, _start //将_start标号(程序的开始地址)位于iRAM里的实际地址保存到R0寄存器中;也是开始拷贝程序的地址
ldr r1, =_start //获取链接地址;也就是想将程序运行的地址;将拷贝的程序从这个地址开始保存
ldr r2, =bss_start //将链接地址中的bss_start标识地址保存到R1寄存器中;也是拷贝程序结束的地址;R1-R2的大小也就是要
//重定位代码的大小
cmp r1, r2 //比较两个地址是否相等,如果相等在直接去清除bss段即可;
beq clear_bss //跳转到清零bss处
reload_loop:
ldr r3, [r0], #4 //将R0数字表示地址处的数据加载到R3寄存器中;并将R0+4
str r3, [r1], #4 //将R3中的数据保存到R1寄存器数字表示的地址中,并将R1+4
cmp r1, r2
bne reload_loop //循环拷贝
clear_bss: //将bss段清零
ldr r0, =bss_start //将bss段的开始地址保存到R0寄存器
ldr r1, =bss_end //将bss段的结束地址保存到R1寄存器
mov r2 ,#0x0 //将0数字保存到R2寄存器中
cmp r0, r1 //如果相等则表示bss清零完毕,跳转执行点亮LED
beq run_address
clear_loop:
str r2, [r0], #4 //将0保存到R0寄存器地址,并将R0+4
cmp r0, r1
bne clear_loop //如果不相等则表示没有清零完成
run_address: //点亮LED灯
ldr sp, =0x02027400 //设置栈
ldr pc, =main //使用绝对跳转指令
//bl main
halt_loop: //死循环
b halt_loop
程序中已经做了详细的注释,这里就不再详细介绍。
2.main.c文件详细介绍:
//定义两个宏,方便操作使用到的寄存器
#define GPM4_CON (*(volatile int *)0x110002E0)
#define GPM4_DAT (*(volatile int *)0x110002E4)
int main()
{
//设置GPM4_0引脚为输出
GPM4_CON &= ~0xFF; //GPM4CON寄存器的低8位清零
GPM4_CON |= 0x11; //GPM4CON寄存器的bit0/4置1,设置为输出引脚
//设置GPM4_0引脚为低电平
GPM4_DAT &= ~0x3; //GPM4DAT寄存器bit0/1清零,输出低电平
return 0;
}
程序中已经做了详细的介绍,这里不再介绍。
3.链接脚本:
SECTIONS {
. = 0x02026400; /* 链接地址 */
. = ALIGN(4);
.text :
{
*(.text)
}
. = ALIGN(4);
.rodata :
{
*(.rodata)
}
. = ALIGN(4);
.data :
{
*(.data)
}
. = ALIGN(4);
bss_start = .; /* bss段的开始位置 */
.bss :
{
*(.bss) *(.COMMON)
}
bss_end = .; /* bss段的结束位置 */
}
链接脚本的内容很简单,起始地址是0x02026400,并获取了bss段的起始和结束地址。
按照前面文章讲解的编译和烧写命令,将程序烧写到SD卡中,设置SD卡启动,观察现象,发现LED1/2被点亮。说明程序重定位成功。
完毕!
史海拾趣
|
电气设备的任何部分与大地(土壤)间作良好的电气连接称为接地。 接地是确保电气设备正常工作和安全防护的重要措施。电气设备接地通过接地装置实施。接地装置由接地体和接地线组成。与土壤直接接触的金属体称为接地体;连接电气设备与接地体之间的导 ...… 查看全部问答> |
|
这是一个巧合,以前我从不把两个电池并联使用,从来都是串联!直到有一天,我看别人的文里面有个电路图,图里有两个电池,电池是准并联的,因为有两个二极管!电池并联的情况,如下图1 &n ...… 查看全部问答> |
|
Power Architecture Study Notes Capture 0 A big picturePPC function category:1. Interger (Fixed-point) Facility, using 32 GPRs(General Purpose Registers), each register have 32/64 bits for different mode. 2. Floating-point Facility, using 32 FPRs (Floating- ...… 查看全部问答> |
|
有哪位朋友开发嵌入式产品时用过讯飞公司的s3011语音芯片,本人在使用过程 中遇到不少问题,有哪位朋友有经验帮助咨询一下,谢谢了。… 查看全部问答> |
|
招聘兼职人员做视频音频软硬件开发,要求从事过此方面的工作,如做过MP3、MP4、电视机顶盒等的开发,有意者请将个人简历发送至邮箱nuaacom@163.com,符合我们意向的人员我们将与您联系,谢谢!… 查看全部问答> |
|
写了个IIC键盘驱动有些错误,大牛们过来看看能否解决,同时功能上是否能实现! 附件里面我放了源代码,同时也将源代码帖到下面: /*IIC键盘程序:CPU是S3C2440,嵌入式操作系统是linux2.6.13,IIC键盘芯片是ZLG7290(周立功的片子);硬件中断连接方法, 将ZLG7290的INT按键中断引脚接GPF2(将GPF2配置成中断功能EINT2),当有按键按 ...… 查看全部问答> |
|
想跟大侠们请教一个PXA270+uboot+wince5.0问题,现在uboot已经调试好了,uboot通过tftp下载NK.nb0到sdram中,运行NK时没有串口信息输出。经过“点灯法”发现程序能运行完src\\kenel\\oal\\startup.s,此后跳转到kernelstart(位于WINCEROOT\\Private\ ...… 查看全部问答> |




