tiny4412裸机程序——代码重定位

2020-03-25来源: eefocus关键字:tiny4412  裸机程序  代码重定位

在前面介绍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被点亮。说明程序重定位成功。


完毕!

关键字:tiny4412  裸机程序  代码重定位 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic492498.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:tiny4412裸机程序之位置无关码
下一篇:tiny4412开发板的串口介绍与操作

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

tiny4412开发板时钟操作示例
在上一节总我们介绍了《Exynos4412芯片的时钟管理单元》,有了上一节的基础知识我们就可以写程序操作CPU的时钟了。通过操作led来感受时钟速率的变化。本文总共有三个示例,第一个是写一个LED循环点亮的程序;第二个是将iROM中设置的时钟禁止掉,观察LED变化速率;第三个就是设置CPU的时钟速率为1.4GHz,观察LED的变化速率。第一个程序很简单,有两个文件start.S和main.c。其中,start.Sz文件中设置栈,然后跳转到C函数中执行。在main.c中设置LED的亮灭。首先,来看start.S内容:.text.global _start_start: ldr sp, =0x02027400 //设置栈 bl
发表于 2020-03-26
tiny4412开发板icache操作程序
首先,来介绍关于cache的概念。cache的作用:基于程序访问的局限性,在主存和CPU通用寄存器之间设置了一个高速的、容量相对较小的存储器,把正在执行的指令地址附近的一部分指令或数据从主存调入这个存储器,供CPU在一段时间内使用,这对提高程序的运行速度有很大的作用。这个介于主存和CPU之间的高速小容量存储器称作高速缓存存储器(Cache)。启用Cache后,CPU读取数据时,如果Cache中有这个数据的复本则直接返回,否则从主存中读入数据,并存入Cache中,下次再使用(读/写)这个数据时,可以直接使用Cache中的复本。启用Cache后,CPU写数据时有写穿式和回写式两种方式。(1)写穿式(Write Through)任一从CP
发表于 2020-03-25
tiny4412开发板的串口介绍与操作
字符"A"(二进制值为0b1000001)时,TTL/CMOS逻辑电平对应的波形。图2. TTL/CMOS逻辑电平下,传输"A"时的波形UART还有其他功能,比如流量控制等,想深入了解的读者请自行查阅相关资料。Exynos4412的UART特性:Exynos4412中UART,有4个独立的通道,每个通道都可以工作于中断模式或DMA模式,即UART可以发出中断或DMA请求以便在UART、CPU间传输数据。UART由波特率发生器、发送器、接收器和控制逻辑组成。使用系统时钟时,Exynos4412的UART波特率可以达到4Mbps。波特率可以通过编程进行控制。Exynos4412 UART的通道
发表于 2020-03-25
tiny4412开发板的串口介绍与操作
tiny4412裸机程序之位置无关码
在上篇文章中,将代码的.text、.data、.rodata段重定位到了0x02026400位置处去执行点亮LED的操作。但是,在链接脚本里指定的链接地址是0x02026400,那么为什么在重定位之前的代码能够在0x02023400地址处可以开始执行?就是因为前面使用的是位置无关码。写介绍介个概念:链接地址:链接脚本里指定的,理论上程序运行时所处的地址。在编译时,编译器会根据链接地址来翻译位置有关码。加载地址(运行地址):程序运行时,实际所处的地址。位置无关码,位置有关码,是相对于一条指令的正常目的来说的。比如ldr r0, =xx,它的正常目的是取得标号处的地址,对于这个目的,它是位置有关码,运行的地址不对就获取不到正确的标号地址
发表于 2020-03-25
tiny4412裸机程序之位置无关码
tiny4412开发板GPIO试验
GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平、或者通过它们读入引脚的状态——是高电平还是低电平。三星Exynos4412,它有304个 GPIO,分为GPA0、GPA1、GPB、GPC0、GPC1等共37组。可以通过设置寄存器来确定某个引脚用于输入、输出还是其它特殊功能。比如可以设置GPC0、GPC1作为一般的输入引脚、输出引脚,或者用于AC97、SPDIF、I2C、SPI口。GPIO的操作是所有硬件操作的基础,由此扩展开来可以了解所有硬件的操作,这是底层开发人员必须掌握的。Exynos4412芯片的GPIO寄存器:既然一个引脚可以用于输入
发表于 2020-03-25
tiny4412开发板GPIO试验
c语言多文件 6410 led裸机程序
Isr_Eint11(void); #ifdef __cplusplus}#endif #endif //__GPIO_H__这个gpio.h 可以参照三星的示例程序自己改写,可以试一下,很简单。发现的问题:c语言的宏定义,在gpio.c 中定义的  结构体,宏定义 只能只啊.c文件中使用,通过.h 后不能使用。所以,这个变量和宏定义当要在多个文件中使用时,可以定义在.h 文件中,或是 用include“xx.c”(不推荐!!!)。
发表于 2020-03-09
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved