S3C2440 lds链接脚本解析

1.  SECTIONS到底意味着什么

    在一个裸版程序里面含有*.lds文件,而lds文件意味着如果你的程序烧录在nandflash,那在nandflash的内存将根据lds文件指定偏移来分布,下面从不同场景来解释SECTIONS的内容。


2.  小于4K程序

    若程序小于4K,那程序的整个重定位地址设置为0,可以没有拷贝到sdram的处理。

    uart.lds

SECTIONS {. = 0x00000000;.text          :   { *(.text) }.rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) }.bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

    head.S

.text
.global _start
_start:ldr     r0, =0x53000000     @ WATCHDOG寄存器地址mov     r1, #0x0                     str   r1, [r0]              @ 写入0,禁止WATCHDOG,否则CPU会不断重启ldr     sp, =1024*4         @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K@ nand flash中的代码在复位后会移到内部ram中,此ram只有4Kbl      main                @ 调用C程序中的main函数
halt_loop:b       halt_loop

    Nandflash其内存结构如下:


    一开始运行之前,默认会从NandFlash拷贝4K大小的程序代码到芯片片内内存上面并且从0开始执行,由于片内内存只有4K,所以链接脚本只适用于程序运行空间小于4K的情况。


3. 大于4K程序

    若要支持程序大于4K,就需要考虑将程序拷贝到sdram中运行,修改head.s文件,添加从片内内存拷贝到Sdram的操作,同时链接脚本设置重定位地址为0x30000000。

   uart.lds

SECTIONS {. = 0x30000000;.text          :   { *(.text) }.rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) }.bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

    head.S

.extern     main
.text 
.global _start 
_start:
Reset:                  ldr sp, =4096          bl  disable_watch_dog  bl  clock_init         bl  memsetup           bl  nand_initldr r0, =0x30000000    mov r1, #0         mov r2, #(1024*10)     bl  nand_read          ldr pc, =on_sdram
onsdram:ldr sp, =0x34000000    ldr lr, =halt_loop     ldr pc, =main          
halt_loop:b   halt_loop

    此时NanFlash和Sdram内存分布如下:


    当重定位0x30000000后,其内存的指令码后会发生什么变化呢?以main函数里面,获取全局变量值为例,

    重定位0x00的时候:

 690:	e59f2224 	ldr	r2, [pc, #548]	; 8bc <main+0x234>
 8bc:	000009d4 	ldrdeq	r0, [r0], -r4
 9d4:	00000000 	andeq	r0, r0, r0

    重定位0x30000000的时候:

30000690:	e59f2224 	ldr	r2, [pc, #548]	; 300008bc <main+0x234>
300008bc:	300009d4 	ldrdcc	r0, [r0], -r4
300009d4:	00000000 	andeq	r0, r0, r0

    三句汇编代码其作用是获取全局变量的值,将其放入寄存器r2中。可以看到第一条汇编指令码和第三条汇编指令码没有变化,重点分析第二条汇编指令码,第二条汇编指令码实际上是第一条汇编寄存器寻址偏移, [pc, #548]的值需要找8bc或300008bc偏移的汇编指令,而其汇编指令又指向0x9d4或0x300009d4偏移,最终获取在其偏移的内容。由此推想若重定位到0x00,当执行到main函数时,会导致执行地址还在片内范围,假设9d4大于4K,则寻址大于片内内存4K,程序就会溢出。所以链接脚本需要设置重定位地址为0x30000000。


5. 大于4K程序并支持中断

    当需要支持中断时,head.S需要加上中断向量表,如下:

@******************************************************************************
@ File锟斤拷head.S
@ 锟斤拷锟杰o拷锟斤拷锟斤拷SDRAM锟斤拷锟斤拷锟斤拷锟斤拷锟狡碉拷SDRAM锟斤拷然锟斤拷锟斤拷锟斤拷SDRAM锟斤拷锟斤拷执锟斤拷
@******************************************************************************       .extern     main
.text 
.global _start 
_start:
@******************************************************************************
@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
@******************************************************************************b   Reset@ 0x04: 未定义指令中止模式的向量地?
HandleUndef:b   HandleUndef@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:b   HandleSWI@ 0x0c: 指令预取终止导致的异常的向量地址
HandlePrefetchAbort:b   HandlePrefetchAbort@ 0x10: 数据访问终止导致的异常的向量地址
HandleDataAbort:b   HandleDataAbort@ 0x14: 保留
HandleNotUsed:b   HandleNotUsed@ 0x18: 中断模式的向量地址b   HandleIRQ@ 0x1c: 快中断模式的向量地址
HandleFIQ:b   HandleFIQReset:                  ldr sp, =4096           @ 锟斤拷锟斤拷栈指锟诫,锟斤拷锟铰讹拷锟斤拷C锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷前锟斤拷要锟斤拷锟秸�bl  disable_watch_dog   @ 锟截憋拷WATCHDOG锟斤拷锟斤拷锟斤拷CPU锟结不锟斤拷锟斤拷锟斤拷bl  clock_init          @ 锟斤拷锟斤拷MPLL锟斤拷锟侥憋拷FCLK锟斤拷HCLK锟斤拷PCLKbl  memsetup            @ 锟斤拷锟矫存储锟斤拷锟斤拷锟斤拷锟斤拷使锟斤拷SDRAMbl  nand_initldr r0, =0x30000000     @1. 鐩爣鍦板潃=0x30000000锛岃繖鏄疭DRAM鐨勮捣濮嬪湴鍧�mov r1, #4096           	@2. 婧愬湴鍧�   = 4096锛岃繛鎺ョ殑鏃跺�欙紝main.c涓殑浠g爜閮藉瓨鍦∟AND Flash鍦板潃4096寮�濮嬪mov r2, #(1024*20)      @3. 澶嶅埗闀垮害= 1024(bytes)锛屽浜庢湰瀹為獙鐨刴ain.c锛岃繖鏄冻澶熶簡bl  nand_read           @璋冪敤C鍑芥暟nand_read_llldr pc, =on_sdram                   @ 跳到SDRAM中继续执行
on_sdram:msr cpsr_c, #0xd2    	@ 进入中断模式ldr sp, =4096           @ 设置中断模式栈指针msr cpsr_c, #0xdf       @ 进入系统模式ldr sp, =0x34000000     @ 锟斤拷锟斤拷栈指锟斤拷msr cpsr_c, #0x5f       @ 设置I-bit=0,开IRQ中断ldr lr, =halt_loop      @ 锟斤拷锟矫凤拷锟截碉拷址ldr pc, =main           @ 锟斤拷锟斤拷main锟斤拷锟斤拷
halt_loop:b   halt_loopHandleIRQ:sub lr, lr, #4                  		@ 计算返回地址stmdb   sp!,    { r0-r12,lr }   	@ 保存使用到的寄存器@ 注意,此时的sp是中断模式的sp@ 初始值是上面设置的4096ldr lr, =int_return             		@ 设置调用ISR即EINT_Handle函数后的返回地址ldr pc, =Uart0_Handle 			@ 调用中断服务函数,在interrupt.c中int_return:ldmia   sp!,    { r0-r12,pc }^  	@ 中断返回, ^表示将spsr的值复制到cpsr

  此时需要修改链接脚本,若延续上述写法,如下:

SECTIONS {. = 0x30000000;.text          :   { *(.text) }.rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) }.bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

   则会有严重的问题,这时看head.S生成的汇编指令

Disassembly of section .text:30000000 <_start>:
30000000:	ea000006 	b	30000020 <Reset>

    第一条指令码,直接程序跑飞,因为这条指令码ea000006表示跳转到30000020执行,而30000020位于Sdram,还并没有初始化,所以链接脚本应该这样写:

SECTIONS {. = 0x00000000;.init : AT(0){ head.o init.o nand.o} . = 0x30000000;.text ALIGN(4) : AT(4096) { *(.text) } .rodata ALIGN(4) :  {*(.rodata)}.data ALIGN(4)   :  { *(.data) }__bss_start = .;.bss ALIGN(4)  : { *(.bss)  *(COMMON) }__bss_end = .;
}

    可以看到main函数的重定位也以0x30000000为基准。当执行到main函数时,此时能保证在sdram里执行,并且也能保证取数据段的时候,能得到偏移哪怕大于4K也能正确的重定位到,看如下main汇编指令码:

300025a4 <main>:
300025a4:	e92d4080 	push	{r7, lr}
300025a8:	e24dd080 	sub	sp, sp, #128	; 0x80
300025ac:	e3a0207d 	mov	r2, #125	; 0x7d

    此时看nandflash和sdram的内存分布如下:

    

    

    


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装qt5.9.5 windows环境

下载&#xff1a;用国外链接下载慢&#xff0c;还是乖乖用国内链接地址吧&#xff0c;我这里5.9.5http://mirrors.ustc.edu.cn/qtproject/archive/qt/5.9/5.9.5/qt-opensource-windows-x86-5.9.5.exe。安装&#xff1a; 在安装的时候需要创建qt账号&#xff0c;然后根据你的vis…

qt在visual studio 2015下的使用

创建工程&#xff1a; 打开visual studio&#xff0c;按上一篇文章的方式创建新工程QtGuiApplication1&#xff0c;默认我们可以看到里面会出现QtGuiApplication1这个类是继承于QMainWindow这个类的。在创建过程中注意下图选项&#xff1a;有三个对象分别是QMainwindow&#xf…

qt 收缩窗体

效果图&#xff1a;功能拆分图&#xff1a;代码&#xff1a; QtStubOption.cpp QtSubOption::QtSubOption(QWidget *parent): QLabel(parent) {ui.setupUi(this);m_GuiShow SHOWGUI;setMouseTracking(true);m_PicStatus[SHOWGUI] ":/QtGuiApplication3/tile";m_Pic…

Android的ELF文件重定位详解,包括64位

0x01 引言 ELF文件格式&#xff0c;主要基于两种&#xff0c;一种是基于链接视图&#xff0c;链接视图即是基于节(Section)来进行解析&#xff0c;一种是基于执行视图&#xff0c;执行视图即是基于段(Segment)来进行解析。前一种是用于静态分析的时候&#xff0c;譬如IDA载入。…

IBinder获取手机服务信息异常

小米8 利用IBinder transact获取服务的接口名字&#xff0c;结果出现以下异常&#xff1a; W/System.err: java.lang.SecurityException W/System.err: at android.os.BinderProxy.transactNative(Native Method) W/System.err: at android.os.BinderProxy.transact(B…

初学C遇到的一些知识点汇总

<span style"font-family: arial, courier new, courier, 宋体, monospace; white-space: pre-wrap;">本人是以C#为入门语言&#xff0c;现在开始学习数字图像处理&#xff0c;正在学习c语言&#xff0c;在这方面还是小白&#xff0c;所以打算把遇到的问题进行…

利用OpenCV的Haar特征目标检测方法进行人脸识别的尝试(一)

一、前言 由于还处于学习阶段&#xff0c;大多数内容都是从网上学习借鉴的&#xff0c;重复的内容就不多赘述&#xff0c;只是将自己的经验和想法分享出来。感觉不错的学习资源如下 http://www.cnblogs.com/tornadomeet/archive/2012/03/28/2420936.html http://www.cnblog…

Haar特征原理与icvCreateIntHaarFeatures方法的具体实现附详细注释—— 人脸识别的尝试系列(二)

带着强烈的兴趣&#xff0c;上周开始人脸识别的尝试与学习&#xff0c;并且将具体的操作过程记录了下来 链接如下&#xff1a;http://blog.csdn.net/u011583927/article/details/44627493 这周开始了对于算法的深入学习&#xff0c;下面进入正题。 Haar特征的原理是什么&…

createsamples.cpp中生成vec文件的实现及详细注释、图解——人脸识别的尝试系列(三)

在我们开始训练我们的Haar分类器之前&#xff0c;首先要对样本进行处理。 人脸识别的尝试系列&#xff08;一&#xff09;中&#xff1a;http://blog.csdn.net/u011583927/article/details/44627493 我们已经提到了如何准备我们的样本&#xff0c;在如下图准备好样本之后 需…

设置同时上内外网+文件共享

最近做了这样一个小项目&#xff0c;逻辑是这样的。 需要在某个办公人员的电脑上装个软件&#xff0c;从局域网中的另一台电脑中读取access数据库&#xff0c;然后用apn接入某个系统的内网传输数据。 同时还要保证这个工作人员能够正常的浏览因特网。 这就涉及到了两个内容。…

浅析haartraining方法进行人脸检测

上个月用了两周的时间&#xff0c;学习了用于人脸检测的haartraining算法&#xff0c;今天打算做一总结 首先先为和我一样的初学者推荐几篇博客 http://blog.csdn.net/zouxy09/article/details/7922923真的很感谢写这篇文章的博主&#xff0c;讲解深入浅出。本文中的主要逻辑…

haartraining训练分类器方法cvCreateTreeCascadeClassifier()详解——人脸识别的尝试系列(四)

本文将介绍opencv_haartraining.exe中训练分类器的核心方法cvCreateTreeCascadeClassifier&#xff08;&#xff09;中参数的具体含义&#xff0c;以及具体实现代码附加详细的注释。最后给出运行截图以作代码阅读的参考 我们还是从具体的例子出发&#xff0c;以一些实际的参数帮…

常用知识总结——模板Template

1. 模板的概念。 我们已经学过重载(Overloading)&#xff0c;对重载函数而言,C的检查机制能通过函数参数的不同及所属类的不同。正确的调用重载函数。例如&#xff0c;为求两个数的最大值&#xff0c;我们定义MAX()函数需要对不同的数据类型分别定义不同重载(Overload)版本。 /…

opencv视频读写和视频等间隔采样

今天学习了opencv的HighGUI的内容 总结了两个视频读写demo以备以后进行视频处理和识别用 demo1 视频的读取和写入 按顺序读取视频的每一帧。对于读取的每一帧图像&#xff0c;显示在窗口中&#xff0c;然后转化为灰度图像输出到指定的文件中。 运行期间可以按ESC键退出。 还…

Socket通用TCP通信协议设计及实现(防止粘包,可移植,可靠)

Socket通用TCP通信协议设计及实现&#xff08;防止粘包&#xff0c;可移植&#xff0c;可靠&#xff09; 引文 我们接收Socket字节流数据一般都会定义一个数据包协议。我们每次开发一个软件的通信模块时&#xff0c;尽管具体的数据内容是不尽相同的&#xff0c;但是大体上的框…

浅谈 Adaboost 算法

注&#xff1a;本文全文引用自http://blog.csdn.net/carson2005/article/details/41444289 当然作者也是转载的&#xff0c;原文是http://blog.csdn.net/haidao2009/article/details/7514787 写的很好所以转载过来以便之后再次翻阅。 一 Boosting 算法的起源 boost 算法系列的起…

如何理解离散傅里叶变换(一)实数形式傅里叶变换

如何理解离散傅里叶变换&#xff08;一&#xff09; ——实数形式傅里叶变换 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 本文…