arm-none-eabi 全局初始化变量值不正确

Posted

技术标签:

【中文标题】arm-none-eabi 全局初始化变量值不正确【英文标题】:arm-none-eabi global initialized variable incorrect value 【发布时间】:2019-04-15 05:45:10 【问题描述】:

我尝试为 stm32f334 做一些示例(只是 LED 闪烁)。当我想使用 .data 部分(通过使用初始化的全局变量)进行约束时,链接器出现问题,我遇到了问题。全局变量的值不正确!

这是我的代码:

startup.s:

    .global _start
    .thumb_func
    _start:
    .word 0x20003000
    .word reset
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang

    .thumb_func
    reset:
        bl main
        b hang
    .thumb_func
    hang:   b .

blink.c:

    #define RCCBASE 0x40021000
    #define GPIOBBASE 0x48000400

    static int wymuszenie_bss;
    int wymuszenie_data = GPIOBBASE;

    int main ( void )
    
        unsigned int* ptr;

        wymuszenie_bss = 0x40021000;

        ptr = (unsigned int*)(wymuszenie_bss+0x14);
        *ptr |= 1<<18; //enable port B;
        //moder
        ptr = (unsigned int*)(wymuszenie_data+0x00);
        *ptr &= ~(3<<24); //PB12
        *ptr |= 1<<24; //PB12
        //OTYPER
        ptr = (unsigned int*)(wymuszenie_data+0x04);
        *ptr &= ~(1<<6); //PB12
        //ospeedr
        ptr = (unsigned int*)(GPIOBBASE+0x08);
        *ptr |= ~(3<<24); //PB12
        //pupdr
        ptr = (unsigned int*)(GPIOBBASE+0x0C);
        *ptr &= ~(3<<24); //PB12

        while(1)
        
            ptr = (unsigned int*)(GPIOBBASE+0x18);
            *ptr = (1<<12)<<0;
            for(int ra=0;ra<400000;ra++) asm("NOP");;
            ptr = (unsigned int*)(GPIOBBASE+0x18);
            *ptr = (1<<12)<<16;
            for(int ra=0;ra<400000;ra++) asm("NOP");;
        
        return(0);
    

链接脚本:

    MEMORY
    
        flash : ORIGIN = 0x08000000, LENGTH = 0x1000
        SRAM  : ORIGIN = 0x20000000, LENGTH = 12K
    

    SECTIONS
    
        .text : 
        
            __text_start__ = .;
            *(.text) 
            startup.o (.text);
            blink.o (.text);
            __text_end__ = .;
         > flash

        .data :
        
            __data_start__ = .;
            KEEP (*(.data))
            KEEP (*(.data*))
            __data_end__ = .;
         > SRAM AT > flash 

        .bss : 
        
             __bss_start__ = .;
            *(.bss)
            __bss_end__ = .;
         > SRAM
    

makefile:

    ARMGNU = arm-none-eabi

    gcc : blink.bin 

    all : gcc

    clean:
        rm -f *.bin
        rm -f *.o
        rm -f *.elf
        rm -f *.list
        rm -f *.bc
        rm -f *.opt.s
        rm -f *.norm.s
        rm -f *.nm

    startup.o : startup.s
        $(ARMGNU)-as --warn --fatal-warnings -mcpu=cortex-m4 startup.s -o startup.o

    blink.o : blink.c
        $(ARMGNU)-gcc -Wall -Wint-to-pointer-cast -g -c -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -c blink.c -o blink.o

    blink.bin : startup.o blink.o
        $(ARMGNU)-ld -o blink.elf -T startup.ld startup.o blink.o
        $(ARMGNU)-objdump -D blink.elf > blink.list
        $(ARMGNU)-nm blink.elf > blink.nm
        $(ARMGNU)-objcopy blink.elf blink.bin -O binary

在 .list 上我看到了正确的值和地址:

Disassembly of section .data:

20000000 <wymuszenie_data>:
20000000:   48000400    stmdami r0, sl

Disassembly of section .bss:

20000004 <__bss_start__>:
20000004:   00000000    andeq   r0, r0, r0

但是当我调试变量“wymuszenie_data”的代码值时已损坏(0x2e006816)。

我真的不知道为什么全局变量值不正确。

最好的问候, 马辛

【问题讨论】:

我在您的启动代码中没有看到任何将.data 部分的内容复制到 RAM 的内容。 【参考方案1】:

这一行

 > SRAM AT > flash

告诉链接器前面块中的部分应该被链接就像它们被放置在RAM中,但实际上被放置到闪存中的不同地址。该代码在 RAM 中查找数据,但它还没有。您应该在致电main() 之前将其复制。由于它是一个裸机嵌入式平台,因此没有操作系统加载程序来执行此任务。

首先,在链接描述文件中创建一个带有目标地址的符号。

__data_destination__ = LOADADDR(.data);

然后在调用main()之前将(&amp;__data_end__ - &amp;__data_start__)字节从&amp;__data_start__复制到&amp;__data_destination__

您还应该清除.bss,即用零填充它以避免下一个意外。

如果您要与 C 库链接,则可以使用 memcpy()memset(),否则您必须使用 C 或汇编编写自己的代码。

【讨论】:

谢谢,这是个问题。我编写了将 .bss 归零并将 .data 从闪存移动到 ram 的代码,一切正常。

以上是关于arm-none-eabi 全局初始化变量值不正确的主要内容,如果未能解决你的问题,请参考以下文章

Shell之环境变量、局部变量

jQuery全局变量值超出功能[重复]

QT 调试器显示不正确的变量值(假而不是真)

Swift 3 设置全局变量值

仅在目标 C 中本地更新全局变量值

动态加载引用后如何保存全局变量值?