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

Laz*_*zor 1 arm bare-metal stm32 linker-scripts gnu-arm

我试着为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 .
Run Code Online (Sandbox Code Playgroud)

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);
    }
Run Code Online (Sandbox Code Playgroud)

链接器脚本:

    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
    }
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

在.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
Run Code Online (Sandbox Code Playgroud)

但是当我调试变量"wymuszenie_data"的代码值被破坏时(0x2e006816).

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

最好的问候,Marcin

ber*_*ing 6

这条线

} > SRAM AT > flash
Run Code Online (Sandbox Code Playgroud)

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

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

__data_destination__ = LOADADDR(.data);
Run Code Online (Sandbox Code Playgroud)

然后在调用之前将(&__data_end__ - &__data_start__)字节复制&__data_start__到.&__data_destination__main()

你应该清楚.bss,即用零填充它以避免下一个惊喜.

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