S3c2440代码重定位详解6---重定位清除BSS段的C函数实现

最新更新时间:2021-09-10来源: eefocus关键字:S3c2440  代码重定位  C函数 手机看文章 扫描二维码
随时随地手机看文章

在前面,我们使用汇编程序来实现了重定位和清bss段,本节我们将使用C语言,实现重定位和清除bss段。


1.打开start.S把原来的汇编代码删除改为调用C函数


    /* 重定位text, rodata, data段整个程序 */

    mov r1, #0

    ldr r2, =_start         /* 第1条指令运行时的地址 */

    ldr r3, =__bss_start    /* bss段的起始地址 */


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, =_end

    mov r3, #0

clean:

    str r3, [r1]

    add r1, r1, #4

    cmp r1, r2

    ble clean


改为:


    /* 重定位text, rodata, data段整个程序 */

    mov r0, #0

    ldr r1, =_start         /* 第1条指令运行时的地址 */

    ldr r2, =__bss_start    /* bss段的起始地址 */

    sub r2, r2, r1          /*长度*/



    bl copy2sdram  /* src, dest, len */


    /* 清除BSS段 */

    ldr r0, =__bss_start

    ldr r1, =_end


    bl clean_bss  /* start, end */


1、在init.c 实现如上两个C函数


void copy2sdram(volatile unsigned int *src, volatile unsigned int *dest, unsigned int len)  /* src, dest, len */

{

    unsigned int i = 0;


    while (i < len)

    {

        *dest++ = *src++;

        i += 4;

    }

}



void clean_bss(volatile unsigned int *start, volatile unsigned int *end)  /* start, end */

{

    while (start <= end)

    {

        *start++ = 0;

    }

}


汇编中,为C语言传入的参数,依次就是R1、R2、R3。

编译,烧写运行没有问题。


我们假设不想汇编传入参数,而是C语言直接取参数。

1、修改start.S 跳转到C函数不需要任何参数


    bl sdram_init

    //bl sdram_init2     /* 用到有初始值的数组, 不是位置无关码 */


    /* 重定位text, rodata, data段整个程序 */

    bl copy2sdram


    /* 清除BSS段 */

    bl clean_bss


2、修改链接脚本,让__code_start 等于当前地址,也就是这里的0x30000000


SECTIONS

{

    . = 0x30000000;


    __code_start = .; //定义__code_start地址位当前地址


    . = ALIGN(4);

    .text      :

    {

      *(.text)

    }


    . = ALIGN(4);

    .rodata : { *(.rodata) }


    . = ALIGN(4);

    .data : { *(.data) }


    . = ALIGN(4);

    __bss_start = .;

    .bss : { *(.bss) *(.COMMON) }

    _end = .;

}


3、修改init.c 用函数来获取参数


void copy2sdram(void)

{

    /* 要从lds文件中获得 __code_start, __bss_start

     * 然后从0地址把数据复制到__code_start

     */


    extern int __code_start, __bss_start;//声明外部变量


    volatile unsigned int *dest = (volatile unsigned int *)&__code_start;

    volatile unsigned int *end = (volatile unsigned int *)&__bss_start;

    volatile unsigned int *src = (volatile unsigned int *)0;


    while (dest < end)

    {

        *dest++ = *src++;

    }

}



void clean_bss(void)

{

    /* 要从lds文件中获得 __bss_start, _end

     */

    extern int _end, __bss_start;


    volatile unsigned int *start = (volatile unsigned int *)&__bss_start;

    volatile unsigned int *end = (volatile unsigned int *)&_end;



    while (start <= end)

    {

        *start++ = 0;

    }

}


编译烧写运行 ,没有问题。


总结:

C函数怎么使用lds文件总的变量abc?

1、在C函数中声明改变量为extern外部变量类型,比如extern int abc;

2、使用时,要取址,比如:int *p = &abc;//p的只即为lds文件中abc的值

汇编文件中可以直接使用外部链接脚本中的变量,但C函数中要加上取址符号。


解释一下原因:

C函数中,定义一个全局变量int g_i;程序中必然有4字节的空间留出来给这个变量g_i

假如我们的lds文件中有很多变量


lds{

    a1 = ;

    a2 = ;

    a3 = ;

    ...

}


如果我们C程序只用到几个变量,完全没必要全部存储lds里面的所有变量,C程序是不保存lds中的变量的。


对于万一要用到的变量,编译程序时,有一个symbol table符号表:

在这里插入图片描述

如何使用symbol table符号表?

1、对于常规变量g_i,得到里面的值,使用&g_i得到addr;

2、为了保持代码的一致,对于lds中的a1,使用&a1得到里面的值;


结论:

1、C程序中不保存lds文件中的变量,lds再大也不影响;

2、借助symbol table保存lds的变量,使用时加上”&”得到它的值,链接脚本的变量要在C程序中声明为外部变量,任何类型都可以;

关键字:S3c2440  代码重定位  C函数 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic547569.html

上一篇:S3c2440代码重定位详解5---代码重定位与位置无关码
下一篇:S3c2440ARM异常与中断体系详解1---概念引入与处理流程

推荐阅读

S3C2440裸机------Nor Flash原理及硬件操作
1. nandflash和norflash的区别我们的nandflash上面只有8条数据线,在数据线上既传输命令又传输数据,但是我们的norflash和内存接口是一样的,有地址线和数据线,norflash可以像内存一样读,但是不能像内存一样写。如果norflash也能像内存那样写的话,那就比较容易被破坏,如果想写norflash,要发出某些特定的命令,需要做一些特殊的操作才能烧写norflash。下图是norflash和nandflash的区别。2.norflash的操作上图是norflash的命令,如果想复位norflash,那么只需要向任意地址写入F0即可。2.1 读idNOR手册上:往地址555H写AAH往地址2AAH写55H
发表于 2021-10-12
<font color='red'>S3C2440</font>裸机------Nor Flash原理及硬件操作
S3C2440裸机------Nor Flash编程_识别
1.编写菜单程序首先我们编写一个测试菜单程序,用来获取norFlash信息以及对NorFlash进行读写操作,代码如下:void nor_flash_test(void){ char c;  while (1) { /* 打印菜单, 供我们选择测试内容 */ printf("[s] Scan nor flashnr"); printf("[e] Erase nor flashnr"); printf("[w] Write nor flashnr"); printf("[r] Read nor flashnr"); printf(&q
发表于 2021-10-12
<font color='red'>S3C2440</font>裸机------Nor Flash编程_识别
S3C2440裸机------Nor Flash编程_擦写读
1.读NorFlash我们首先来实现读flash的函数,我们默认每次读取64个字节,然后我们把读取到的内容打印出来,其中前面打印数值,后面打印字符,对于不可见字符用...代替。void do_read_nor_flash(void){ unsigned int addr; volatile unsigned char *p; int i, j; unsigned char c; unsigned char str[16]; /* 获得地址 */ printf("Enter the address to read: "); addr = get_uint();  p = (volatile unsign
发表于 2021-10-12
<font color='red'>S3C2440</font>裸机------Nor Flash编程_擦写读
S3C2440裸机------NandFlash操作原理
1.Nandflash操作原理下图是原理图中NandFlash和S3C2440的连接图,问1. 原理图上NAND FLASH和S3C2440之间只有数据线,     怎么传输地址?答1.在DATA0~DATA7上既传输数据,又传输地址     当ALE为高电平时传输的是地址,问2. 从NAND FLASH芯片手册可知,要操作NAND FLASH需要先发出命令     怎么传入命令?答2.在DATA0~DATA7上既传输数据,又传输地址,也传输命令     当ALE为高电平时传输的是地址,   
发表于 2021-10-11
<font color='red'>S3C2440</font>裸机------NandFlash操作原理
S3C2440裸机------NandFlash编程_时序及初始化
1.NandFlash初始化 Nandflash初始化主要包括时序图的设置和Nandflash控制器的使能,我们首先看一下S3C2440芯片手册里面的时序图。上图中的HCLK我们已经设置成了100M。那么时钟周期是1/100M=10ns 然后下图是NandFlash芯片手册里面的时序图。我们将S2C2440里面NandFlash控制器的时序图和NandFlash时序图结合起来看。左图中的TACLS表示当我们的CLE/ALE发出之后,再过多长时间再发出WE信号,就是右图中的tcls-twp,而我们从右下图可以看到,tcls的最小值是12,twp的最小值也是12,就表明tcls-twp可以为零,也就表明CLE和WE
发表于 2021-10-11
<font color='red'>S3C2440</font>裸机------NandFlash编程_时序及初始化
S3C2440裸机------NandFlash编程_芯片id读取
1.芯片id读取时序图我们先看一下NandFlash芯片手册中读取id的时序图,后面我们要根据这个时序图去写代码。2.使能芯片从前面的时序图我们可以看出,我们首先要发出片选信号,我们通过设置下图寄存器的Reg_nCE位来进行设置,void nand_select(void){ /*使能片选*/ NFCONT &=~(1<<1);} void nand_deselect(void){ /*禁止片选*/ NFCONT |= (1<<1);}3.发送命令函数我们从最前面的时序图可以看到,要想读取设备id,首先要向NandFlash发送90命令,然后相应的CLE和WE信号要使能,这里的时序不需要我们
发表于 2021-10-11
<font color='red'>S3C2440</font>裸机------NandFlash编程_芯片id读取

推荐帖子

#8月原创# keil生成bin和反汇编
keil中如何生成bin或者反汇编文件?使用fromelf 魔法棒或者project->optionsfortarget弹出下图界面,选择user选项卡 在如图的地方 生成bin文件 fromelf--bin--output=xxxx.binxxxx\\xxxx.axf 其中--bin是制定输出文件格式是bin格式, --output=xxxx.bin指定输出文件名, xxxx\\xxxx.axf是指定路径下的指定axf文件,此文件
白丁 ARM技术
锂电池充放电一体的芯片
现在要做几节锂电池并联,只扩容,不升压,有没有集充放电一体的芯片?外围最好简单,因为板子空间比较小,现在知道的只有BQ25703,麻烦各位帮忙再推荐几款,谢谢了 锂电池充放电一体的芯片
轩辕默殇 电源技术
TI C2000 LaunchPad“画”外围之家用智能功率监视器方案描述
一、信号采集部分 做信号采集首先得了解源信号和目标信号的相关信息,以便在中间进行信号的变换。家用智能功率监视器监视的是家用电器的功率,因此源信号为家用电,也就是我们俗说的市电。目标信号是给ADC采集时的最终信号,应该根据所选的ADC决定。既然使用C2000LaunchPad作为主CPU,为了设计简单,ADC自然也就使用28027的内部AD了。28027的内部AD为12位,输入信号为0-3.3V(内部基准,同样为了设计简单,不使用外部基准)。但
Aguilera 微控制器 MCU
S5PV210 把电阻屏幕换成电容屏幕挂起的问题解决办法探讨
打印如下信息,貌似就挂起了,USB鼠标也不能用了。[84.284184] [84.285380]Freezingofuserspaceaborted [84.290014] [84.290992]Restartingtasks...done. [84.326401]suspend:exitsuspend,re
Wince.Android 嵌入式系统
nand flash & mtd 驱动高手请进来,高分交流!
本人目前使用的单板是使用nandflash,本人在上面开发了基于mtd框架的NFTL驱动,目前读写擦除都ok,但是怎么利用mkdosfs为这个nandflash的某个分区生成fat文件系统呢?我们的nandflash一个页有2048字节,默认的mkdosfs都是用的512字节,怎么样修改mkdosfs比较好,有人对这部分有研究么?nandflash&mtd驱动高手请进来,高分交流!
sicpetter 嵌入式系统
波形不稳定
请问一个电路直流供电,在示波器上能显示出波形,但是波形不稳定,是滤波电路的问题吗? 波形不稳定
梅花飘落孤人醉 模拟电子
小广播
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved