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

时间:2018-11-12 13:31:53

标签: arm stm32 bare-metal linker-scripts gnu-arm

我尝试为stm32f334做出一些示例(只是导致闪烁)。当我想限制使用.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)。

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

最好的问候, 马辛

1 个答案:

答案 0 :(得分:6)

此行

} > SRAM AT > flash

告诉链接器,上一个块中的节应该链接起来,就像放置在RAM中一样,但实际上放在闪存中的其他地址中。该代码在RAM中查找数据,但尚不存在。您应安排在调用main()之前将其复制。由于它是裸机嵌入式平台,因此没有操作系统加载程序可以执行此任务。

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

__data_destination__ = LOADADDR(.data);

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

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

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