本文转载自:http://blog.csdn.net/eshing/article/details/37115697

一、重定向

对于程序而言,我们需要理解两个概念,一是程序当前所处的地址,即程序在运行时,所处的当前地址;二是程序的链接地址,即程序运行时应该位于的运行地址。编译程序时,可以指定程序的链接地址。对于Tiny4412而言,启动时只会从MMC/sd等启动设备中拷贝前16K的代码到IRAM中,那么当我们的程序超过16K怎么办?那就需要我们在前16K的代码中将整个程序完完整整地拷贝到DRAM等其他更大存储空间,然后再跳转到DRAM中继续运行我们的代码,这个拷贝然后跳转的过程就叫重定位。

本章中我们主要学习如何重定位,但是并不会涉如何使用到DRAM,而是简单地将代码从IRAM的0x02020010处拷贝到IRAM的0x02028000处,然后跳转到0x02028000处继续运行我们的代码。

二、程序说明

完整代码见目录5_link_0x8000,该目录下的代码与上一章的代码的差别在于start.S和使用了

链接脚本link.lds,我们首先分析link.lds。

1. link.lds

什么是链接脚本?链接脚本就是程序链接时的参考文件,其主要目的是描述如何把输入文件中的段(SECTION)映射到输出文件中,并控制输出文件的存储布局。链接脚本的基本命令式SECTIONS命令,一个SECTIONS命令内部包含一个或多个段,段(SECTION)是链接脚本的基本单元,它表示输入文件中的某个段是如何放置的。

链接脚本的标准格式如下:

SECTIONS

{

sections-command

sections-command

}

下面我们配合link.lds进行具体讲解:

SECTIONS

{

. = 0x02028000;

.text : {

start.o

* (.text)

}

.data : {

* (.data)

}

bss_start = .;

.bss : {

* (.bss)

}

bss_end = .;

}

1)  在链接脚本中,单独的点号(.)代表了当前位置,. =0x02028000;表示程序的链接地址是00x02028000;

2)  link.lds中的.text 、 .data 、 .bss分别是text段、data段、bss段的段名(这些段名并不是固定的,是可以随便起的)。.text 段包含的内容是start.o 和其余代码中所有的text段;.data段包含的内容是代码中所有的data段;.bss段包含的内容是代码中所有的bss段。

3)  bss_start和bss_end保存的是bss段的起始地址和结束地址,在start.S中会被用到。

下面解释一下什么是data、text、bss段:

1)  data段:数据段(datasegment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

2)  text段:代码段通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

3)  bss段:指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文BlockStarted by Symbol的简称。当我们的程序有全局变量是,它是放在bss段的,由于全局变量默认初始值都是0,所有我们需要手动清bss段。

2. start.S

在start.S中,我们初始化时钟后,增加了3个步骤:

第一步重定位,代码如下:

// _start当前所位于的地址

adr r0, _start

// _start的链接地址

ldr r1, =_start

ldr r2, =bss_start

cmp r0, r1

beq clean_bss

copy_loop:

ldr r3, [r0], #4

str r3, [r1], #4

cmp r1, r2

bne copy_loop

首先需要知道的是,adr指令获取的值是代码当前位于的地址,而ldr指令获取的值是代码的链接地址。再来看代码,代码里首先获得_start标号的当前地址(即0x02020010),然后获取_start标号的链接地址(即0x02028000),因为bin文件中不需要保存bss段,所有拷贝的代码长度为bss_start的运行地址-_start的运行地址,使用copy_loop进行拷贝。

第二步清bss,代码如下:

ldr r0, =bss_start

ldr r1, =bss_end

cmp r0, r1

beq run_on_dram

mov r2, #0

clear_loop:

str r2, [r0], #4

cmp r0, r1

bne clear_loop

首先获得bss段的起始地址(即bss_start),然后获得bss段的结束地址(即bss_end),最后使用clear_loop将bss段所位于的内存清0,bss_start和bss_end的定义位于link.lds。

第三步跳转,代码如下:

run_on_dram:

ldr pc, =main

由于ldr 指令获取的是main函数的链接地址,所以执行ldrpc, =main 后,程序就跳转到

0x02020000+main函数的offset的地址处了。

三、完整的烧写过程

已将SD卡插入电脑,假设Linux识别了SD卡,其识别号为sdb。执行下面命令:

# chmod 777 –R 5_link_0x8000

# cd 5_link_0x8000

# make

# cd sd_fuse

# make

# ./ fast_fuse /dev/sdb

四、上电实验

将sd卡插入Tiny4412中,选择sd卡启动,然后上电,可以看到以下现象:

LED正常闪烁,该现象与前面章节的代码的运行效果一模一样,但是程序的运行过程却有了很大的区别。通过本章的学习,我们已经知道了如何对代码进行重定位,这为我们下一章节将代码重定位到DRAM奠定了基础。

备注:说明一下,代码已上传到我的资源里,我要了两个下载分,不好意思,我的资源分太少了,我得赚点,我相信我的程序是绝对能运行的,觉得值就去下载。

 
0

tiny4412 裸机程序 六、重定位代码到IRAM+0x8000【转】的更多相关文章

  1. Tiny6410之重定位代码到SRAM+4096

    重定位代码 两个不同的地址概念: 对于程序而言,需要理解两个地址,一个是程序当前所处的地址,即程序运行时所处的当前地址.二是程序应该位于的运行地址,即编译程序时所指定的程序的链接地址.在Tiny641 ...

  2. uboot重定位代码分析(转)

    概述 重定位(relocate)代码将BootLoader自身由Flash复制到SDRAM,以便跳转到SDRAM执行.之所以需要进行重定位是因为在Flash中执行速度比较慢,而系统复位后总是从0x00 ...

  3. tiny4412 裸机程序 七、重定位代码到DRAM【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37116637 一.关于DRAM 上一章我们讲解了如何对代码进行重定位,但是将代码重定位到只有25 ...

  4. tiny4412 裸机程序 八、重定位到DRAM及LCD实验【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37407423 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   一 ...

  5. tiny4412 裸机程序 九、串口排查驱动原因及字符图片显示【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37410571 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   一 ...

  6. Tiny4412之C语言实现流水灯,Tiny4412裸机程序[3]

    在前边我们使用汇编完成了一个流水灯实验: Tiny4412汇编流水灯代码,Tiny4412裸机LED操作 ---- - -- -- -- - -- -- 修改: # ${MKBL2} ${SOURCE ...

  7. Tiny6410之重定位代码到SDRAM

    在上一章中,将代码重定位到了SRAM中,但是这样的做法作用不大.正确的做法的是将代码重定位到更大的主存中,即DRAM.Tiny6410的DRAM控制寄存器最多只能支持两个同一类型的芯片.每个芯片最多可 ...

  8. tiny4412 裸机程序 一、说明【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37109115 首先.我想说明为什么我写这个文档?我自己想学点东西,过于求成,又过于自信,直接买了 ...

  9. tiny4412 裸机程序 五、控制icache【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37115411 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   一 ...

随机推荐

  1. 【前端路由】Vue-router 中hash模式和history模式的区别

    咱们今天说说VUE路由的hash模式与history模式的区别,这个也是面试常问的问题,不要小看这道题其实问到这里的时候那个面试官应该是个大牛,开发经验丰富,这个题其实就是考验你的开发经验是否属实. ...

  2. java基础学习之垃圾回收机制

    回收过程: 1.发现无用的对象 2.回收无用对象占用的内存的空间. 垃圾回收相关算法: 1.引用计数法 堆中每个对象都有一个引用计数.被引用一次,计数加一.被引用变量值变为null,则计数减一. 到计 ...

  3. @ControllerAdvice全局异常拦截

    @ControllerAdvice 拦截异常并统一处理 在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder ...

  4. 并发和多线程(二)--线程安全、synchronized、CAS简介

    线程安全性: 当多个线程访问一个类的时候,这个类始终表示出正确的行为,那么这个类是线程安全的. 无状态的对象一定是线程安全的,例如大部分service.dao.Servlet都是无状态的. 线程安全体 ...

  5. linux cp复制文件 直接覆盖

    命令: \cp -rf aaaa/* bbbb 复制aaa下的文件到bbb目录

  6. A1. JVM 内存区域

    [概述] 在这篇笔记中,需要描述虚拟机中的内存是如何划分的,哪部分区域.什么样的代码和操作可能导致内存溢出异常.虽然 Java 有垃圾处理机制,但是如果生产环境在出现内存溢出异常时,由于开发人员不熟悉 ...

  7. Executors工厂类

    newCachedThreadPool 重用之前的线程 适合执行许多短期异步任务的程序. 调用 execute() 将重用以前构造的线程 如果没有可用的线程,则创建一个新线程并添加到池中 默认为60s ...

  8. vivo手机执行input命令提示killed

    异常现象: 使用vivo手机时发现通过inputManager发送按键.执行屏幕滑动等动作失效,相关API并没有任何异常抛出,继续跟踪发现shell控制台执行input进行屏幕滑动.发送文本.模拟按键 ...

  9. MYEclipse Available Memory is low 警告 解决方法

    1,  设置Eclipse内存使用情况 修改eclipse根目录下的eclipse.ini文件 -vmargs  //虚拟机设置 -Xms40m -Xmx256m -XX:PermSize=128M ...

  10. Xmind的使用

    Xmind是用来学习整理思维的工具