неверное значение глобальной инициализированной переменной arm-none-eabi - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь сделать пример для 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

в списке. Я вижу правильное значение и адрес:

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).

Я действительно не знаю, почему существует неверное значение глобальной переменной.

С уважением, Marcin

1 Ответ

0 голосов
/ 12 ноября 2018

Эта строка

} > SRAM AT > flash

сообщает компоновщику, что разделы в предыдущем блоке должны быть связаны , как если бы они были помещены в ОЗУ, но фактически помещались во флэш-память по другому адресу.Код ищет данные в ОЗУ, но их пока нет.Вы должны договориться о копировании перед звонком main().Поскольку это встроенная платформа с нуля, загрузчик операционной системы для выполнения этой задачи отсутствует.

Сначала создайте символ с адресом назначения в сценарии компоновщика.

__data_destination__ = LOADADDR(.data);

затемскопируйте (&__data_end__ - &__data_start__) байтов с &__data_start__ на &__data_destination__ перед вызовом main().

Вам также следует очистить .bss, то есть заполнить его нулями, чтобы избежать следующего сюрприза.

Если вы связываетесь с библиотекой C, вы можете использовать memcpy() и memset(), в противном случае вы должны написать собственный код на C или сборке.

...