weixin_44954297 2020-03-05 13:03 采纳率: 0%
浏览 598

链接脚本中LOADADDR(0x800)语句出错的问题

在学习重定位时遇到的问题,先贴出代码
main.c里定义了两个字符类型的全局变量,在主函数里分别+1然后串口输出,它们链接在.data段,对.data段进行重定位,出现问题

sdram.lds

    SECTIONS{

            .text 0         :        {*(.text)}

            .rodata         :      {*(.rodata)}

            .data  0x30000000         :AT(0x800)

            {

                    data_load_addr = LOADADDR(.data) ;

                    data_start = . ;

                    *(.data)

                    data_end = . ;

            }

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

    }

uart.c

#include "s3c2440.h"





/* 设置引脚用于串口 */

void uart0_init()

{

        GPHCON &= ~((3<<4)|(3<<6));                //清空GPH2,GPH3

        GPHCON |= ((2<<4)|(2<<6));                //GPH2,GPH3用于TXD1,RXD1

        GPHUP &= ~((1<<2)|(1<<3));                //使能内部上拉

        UFCON0  = 0x0;                             //不使用FIFO

    UMCON0  = 0x0;                             //不使用流控

        ULCON0 = 0x3;                        //设置数据格式8n1:8位数据位,无校验位,1停止位

        UCON0 = 0x5;                                //PCLK,中断/查询模式

        UBRDIV0 = 26;//( (int)(50000000/16./115200+0.5) -1 );//设置波特率 115200

}



void sdram_init(void)

{

        BWSCON = 0x22011110;



        BANKCON6 = 0x00018005;

        BANKCON7 = 0x00018005;



        REFRESH = 0x008C04F4;



        BANKSIZE = 0x000000B1;



        MRSRB6 = 0x00000030;

        MRSRB7 = 0x00000030;

}

int putc(int c)

{

        while(!(UTRSTAT0 & 0x2));

        UTXH0 = (unsigned char)c;

}



int getc(void)

{

        while(!(UTRSTAT0 & 1));

        return URXH0;

}



int puts(const char *s)

{

        while(*s)

                putc(*s++);



}

main.c

#include "s3c2440.h"

#include "uart.h"



char g_c1 = 'A';

char g_c2 = 'a';

int main(void)

{

        int i;

        uart0_init();

        sdram_init();



        for(i=0;i<10;i++){

                putc(g_c1);

                putc(g_c2);

                g_c1++;

                g_c2++;

        }

        return 0;

}

start.s

.text

.global _start



_start:

        /* 关闭看门狗 */

        ldr r0, =0x53000000

        ldr r1, =0

        str r1, [r0]



        /* 设置MPLL,FCLK */

        /* CLKDIVN(0x4c000014) = 0x5 */

        ldr r0, =0x4c000014

        ldr r1, =0x5                        /* HCLK = FCLK/4 = 100 MHz , PCLK = HCLK/2 = 50 MHz */

        str r1, [r0]



        /* 设置CPU工作于异步模式 */

        mrc  p15,0,r0,c1,c0,0

        orr  r0,r0,#0xc0000000 //R1_nF:OR:R1_iA

        mcr  p15,0,r0,c1,c0,0



        /* 设置MPLLCON(0x4c000004) = (92<<12)|(1<<4)|(1<<0)          FCLK = 400 MHz*/

        ldr r0, =0x4c000004

        ldr r1, =(92<<12)|(1<<4)|(1<<0)

        str r1,[r0]



        /* 分辨是nand/nor启动

        *  设置内存:sp 栈

        */

        mov r1,        #0

        ldr r0, [r1]        /* 读出原来的备份 */

        str r1,        [r1]        /* 0->[0] */

        ldr r2,        [r1]        /* r2=[0] */

        cmp r1,        r2                /* r1==r2?如果相等表示是nand启动 */

        ldr sp,        =0x40000000+4096        /* 先假设是nor启动 */

        moveq sp,        #4096        /* nand启动 */

        streq r0,        [r1]        /* 恢复原来的值 */



        bl sdram_init



        /* 重定位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



        /*调用main*/

        bl main



halt:

        b halt

我把反汇编关于重定位的一小段单独贴出来

      54:        e59f1034         ldr        r1, [pc, #52]        ; 90 <halt+0x14>
      58:        e59f2034         ldr        r2, [pc, #52]        ; 94 <halt+0x18>
      5c:        e59f3034         ldr        r3, [pc, #52]        ; 98 <halt+0x1c>

    00000060 <cpy>:
      60:        e5d14000         ldrb        r4, [r1]
      64:        e5c24000         strb        r4, [r2]
      68:        e2811001         add        r1, r1, #1
      6c:        e2822001         add        r2, r2, #1
      70:        e1520003         cmp        r2, r3
      74:        1afffff9         bne        60 <cpy>
      78:        eb000085         bl        294 <main>

    0000007c <halt>:
      7c:        eafffffe         b        7c <halt>
      80:        4c000014         stcmi        0, cr0, [r0], {20}
      84:        4c000004         stcmi        0, cr0, [r0], {4}
      88:        0005c011         andeq        ip, r5, r1, lsl r0
      8c:        40001000         andmi        r1, r0, r0
      90:        30000800         andcc        r0, r0, r0, lsl #16
      94:        30000000         andcc        r0, r0, r0
      98:        30000002         andcc        r0, r0, r2

可以看到0x90这个地址存放的是LOADADDR(0X800)的结果,是0x30000800,这显然是不对的,用jlink下载到nor flash里运行,结果串口输出乱码
图片说明

将链接脚本更改为以下代码之后正常输出

    SECTIONS{

            .text 0         :        {*(.text)}

            .rodata         :      {*(.rodata)}

            .data  0x30000000         :AT(ADDR(.rodata)+SIZEOF(.text))

            {

                    data_load_addr = LOADADDR(.data) ;

                    data_start = . ;

                    *(.data)

                    data_end = . ;

            }

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

    }

.data段的加载地址我还尝试写成AT(ADDR(.rodata)+1)也不行

请问这是什么原因?

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 #MATLAB仿真#车辆换道路径规划
    • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
    • ¥15 数据可视化Python
    • ¥15 要给毕业设计添加扫码登录的功能!!有偿
    • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
    • ¥15 微信公众号自制会员卡没有收款渠道啊
    • ¥100 Jenkins自动化部署—悬赏100元
    • ¥15 关于#python#的问题:求帮写python代码
    • ¥20 MATLAB画图图形出现上下震荡的线条
    • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘