ARM---代码重定位

版权声明:本文为小斑马学习文章,技术来源于韦东山著作,转载请注明出处!

一、段的概念__重定位的引入

2440开发版:芯片内部有CPU、内存控制器、4K的配对内存SRAM。还有NandFlash控制器。NandFlash控制器可以直接连接NandFlash。


CPU 能直接到达SDRAM Norflash SRAM Nand Flash控制器 但不能直接到达NandFlash。如果直接把程序烧写到NandFlash CPU不能直接运行该程序。那为什么我们还能设置NANDFlash启动呢? 这里有个机制 1.NandFalsh启动时,硬件将前4K复制到SRAM中。2.CPU从0运行,0对应的就是SRAM。
问题:如果在NandFlash程序超过4K怎么办? 前4K的代码 需要把整个程序读出来 放到SDRAM。这就是重定位,即重新确定程序的地址。

.使用NorFlash启动时,CPU看到的0地址在NorFlash上面,SRAM 配对内存的基地址就是0x40000000 NandFlash地址0, NandFlash不可以访问的。
NorFlash的特点:像内存一样读,但不能像内存可以直接写。

比如 mov R0,#0
LRR R1,[R0]
STR R1,[R0]该指令无效的。
问题:如果程序中含有要写的变量==全局变量/静态变量
他们在bin中,写在NORFlash中,直接修改变量会无效。所以需要重定位放到SDRAM中。

#include "s3c2440_soc.h"
#include "uart.h"
#include "init.h"

char g_Char = 'A';
const char g_Char2 = 'B';
int g_A = 0;
int g_B;

int main(void)
{
 uart0_init();

while (1)
{
    putchar(g_Char);
    g_Char++;         /* nor启动时, 此代码无效 */
    delay(1000000);
}


return 0;
}

对于NORFlash不能直接的写。

程序包含: 代码段 数据段(全局变量) data rodate(const全局变量) bss(初值为0 无初值的全局变量)commen(注释)后面的两个不保存在bin的文件中。

二、链接脚本的引入与简单测试

因为NORFlash不能写入数据,在设置修改MakeFile将数据段写入到SDRAM中,但出现bin文件超大的问题有800多M。问题的根源在于代码段和数据段出现巨大的间隔。成为HOLO黑洞。


怎么解决数据段和代码段出现巨大空洞问题?

  • 1 将bin文件里面的代码段和数据段拼接在一起,烧写在NORFlash里面去,在运行时,将数据段重定位到SDRAM中 地址:0x30000000。
  • 2 将bin文件里面的代码段写在一个地址中,数据段写到另外一个地址中,烧写在NORFlash里面去,在运行时,将数据段和数据段重定位到SDRAM中 地址:0x30000000。
    如何将数据段和代码段拼接在一起呢?
    这要使用到链接脚步。

链接脚本的格式:

 SECTIONS {
     .text   0  : { *(.text) } //先发所有的.text代码段
     .rodata  : { *(.rodata) } //紧接着放 所有的.rodata只读的数据段
     .data 0x30000000 : AT(0x800) { *(.data) }  // 依次是所有文件的数据段 数据放在0x30000000 要加AT
     .bss  : { *(.bss) *(.COMMON) } 
 }

设置链接脚本后,运行时!要将数据段重定位到0x30000000中去。

bl sdram_init   //初始化SDRAM

/* 重定位data段 */
mov r1, #0x800
ldr r0, [r1]
mov r1, #0x30000000
str r0, [r1]

bl main 

通用的重定位代码:解决多个全局变量和未知数据段存储地址的情况下

SECTIONS {
   .text   0  : { *(.text) }
   .rodata  : { *(.rodata) }
   .data 0x30000000 : AT(0x800) 
   { 
      data_load_addr = LOADADDR(.data); //获取数据段的存储地址
      data_start = . ;  //.即是当前位置 0x30000000
     *(.data) 
      data_end = . ; //data_end的值 有data的大小来决定
   }
  .bss  : { *(.bss) *(.COMMON) }
}


/* 重定位data段 */
ldr r1, =data_load_addr  /* data段在bin文件中的地址, 加载地址 */
ldr r2, =data_start      /* data段在重定位地址, 运行时的地址 */
ldr r3, =data_end        /* data段结束地址 */

cpy:
   ldrb r4, [r1]
   strb r4, [r2]
   add r1, r1, #1
   add r2, r2, #1
   cmp r2, r3
   bne cpy
三、 链接脚本的解析

SECTIONS {
...
secname start BLOCK(align)(NOLOAD) : AT (ldadr)
{ contents } >region:phdr =fill
...
}
secname:段名:
start:起始地址:运行时地址runtime addr,重定位地址 relocate addr

AT(ldadr) Load Addr:加载地址 不写时,LoadAddr = runtime addr 如果没有加AT 它的的加载地址就等于链接时的起始地址。

使用链接脚本时
arm-linux-ld -T sdram.lds start.o led.o uart.o init.o main.o -o sdram.elf

把.o文件生成了.elf格式的程序。elf格式程序含有地址信息。再将elf格式的文件生成bin文件 bin文件里面不含有地址信息。
arm-linux-objcopy -O binary -- sdram.elf sdram.bin

elf格式的程序:1.链接得到elf文件,含有地址信息(LoadAddr)2.使用加载器将elf程序读入内存(读到LoadAddr)调试工具。对于APP 加载器也是APP。
3.运行程序 4.如果LoadAddr != RuntimeAddr 程序本身要重定位。

核心:程序运行时,应该位于RuntimeAddr 也可以称为relocate Addr 或者链接地址
对于裸版 1.elf--> 2.硬件机制启动 3.如果bin所在地址 != runtime Addr 程序本身实现重定位

SECTIONS {
   .text   0  : { *(.text) }  //LoadAddr = Runtime Addr  =0 不需要重定位
   .rodata  : { *(.rodata) }
   .data 0x30000000 : AT(0x800) LoadAddr = 0x800 RuntimeAddr = 0x30000000
   { 
      data_load_addr = LOADADDR(.data); //获取数据段的存储地址
      data_start = . ;  //.即是当前位置 0x30000000
      *(.data) 
      data_end = . ; //data_end的值 有data的大小来决定
   }
 .bss  : { *(.bss) *(.COMMON) } runtime = 0x300000000
}

bin文件 left文件都不存bss段 bss段(未初始化的变量和注释) 程序运行时 把bss段对应的空间清零。

 SECTIONS {
   .text   0  : { *(.text) }
   .rodata  : { *(.rodata) }
   .data 0x30000000 : AT(0x800) 
   { 
      data_load_addr = LOADADDR(.data);
      data_start = . ;
      *(.data) 
      data_end = . ;
   }

  bss_start = .;
 .bss  : { *(.bss) *(.COMMON) }
  bss_end = .;
}

/* 清除BSS段 */
ldr r1, = bss_start
ldr r2, = bss_end
mov r3, #0
clean:
strb r3, [r1]
add r1, r1, #1
cmp r1, r2
bne clean
四、拷贝代码和链接脚本的改进

拷贝代码:把数据和代码从NorFlash或者NandFlash中复制到SDRAM去。

cpy:
   ldrb r4, [r1]  //从Flash中读取出一个字节
   strb r4, [r2]  //写到SDRaAM中
   add r1, r1, #1
   add r2, r2, #1
   cmp r2, r3
   bne cpy

bl main

这种效率非常的低。
原因:在2440芯片中有CPU和内存控制器。外接有32bit的SDRAM 和 16bit的NORFlash。如果使用ldrb从NORFalsh中读到数据,使用strb写数据到SDRAM。如果要复制16字节,ldrb要执行16次,访问NORFlash要16次。strb要执行16次,访问SDRAM16次。硬件访问要32次,效率非常的低。

CPU写数据给SDRAM中,先将地址和数据发送到内存控制器,内存控制把32位的数据和数据屏蔽信号DQM 发送给SDRAM。
改进的方法:使用ldr从NORFlash读取 用str写数据到SDRAM去。读取和写入各执行四次。其从NORFlash读取数据时访问硬件为8次,写数据到SDRAM中访问的硬件为4次。总共12次。效率提高。

cpy:
    ldr r4, [r1]
    str r4, [r2]
    add r1, r1, #4
    add r2, r2, #4
    cmp r2, r3
    ble cpy


/* 清除BSS段 */
   ldr r1, =bss_start
   ldr r2, =bss_end
   mov r3, #0
clean:
   str r3, [r1]
   add r1, r1, #4
   cmp r1, r2
   ble clean

bss 清零的时候,要向四取整。否则会出现地址相同,把其他变量的值也清零了。

SECTIONS {
    .text   0  : { *(.text) }
    .rodata  : { *(.rodata) }
    .data 0x30000000 : AT(0x800) 
    { 
        data_load_addr = LOADADDR(.data);
        . = ALIGN(4);
        data_start = . ;
       *(.data) 
        data_end = . ;
    }

. = ALIGN(4);
bss_start = .;
.bss  : { *(.bss) *(.COMMON) }
bss_end = .;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容

  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,709评论 2 59
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,919评论 25 707
  • 根据首都版权产业联盟常务副秘书长宣宏量先生2018年8月14日晚间在DAGA | Blockchain & AI ...
    烛微虑远阅读 3,073评论 0 0
  • 人在草木间 茶的传说 神农氏,:尝百草,中毒晕倒,口中苦涩,身旁树叶解其苦,发现茶。 陆羽:和尚收留多教茶道,陆羽...
    槿柔伊阅读 159评论 0 1
  • 郑贵祥 轰隆隆 嗒嗒嗒 一辆铲车 从远方开来 不要 不要 那是五千年文明 还有住了几辈人的老房 轰隆隆 嗒嗒嗒 一...
    皓白艺术俱乐部Ghost阅读 384评论 0 1