zoukankan      html  css  js  c++  java
  • tiny4412 裸机程序 六、重定位代码到IRAM+0x8000【转】

    本文转载自: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
  • 相关阅读:
    Python爬虫一
    Python爬虫二
    DRF框架中的演变View
    计算时间复杂度例题
    vue2.x webpack打包资源路径问题
    vs code运行c语言 控制台乱码 问题
    解决视频的声音和画面不同步问题
    c语言数据结构,静态链表,结构体数组
    swagger @ApiModel添加实体类不生效
    计算及校验海明码的3个举例
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7248961.html
Copyright © 2011-2022 走看看