Неверное значение глобальной инициализированной переменной arm-none-eabi
Я пытаюсь сделать пример для 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 ответ
Эта линия
} > SRAM AT > flash
сообщает компоновщику, что разделы в предыдущем блоке должны быть связаны, как если бы они были помещены в оперативную память, но фактически помещаются во флэш-память по другому адресу. Код ищет данные в ОЗУ, но их пока нет. Вы должны организовать его копирование перед звонком main()
, Так как это встроенная платформа с открытым исходным кодом, для выполнения этой задачи нет загрузчика операционной системы.
Сначала создайте символ с адресом назначения в скрипте компоновщика.
__data_destination__ = LOADADDR(.data);
затем скопируйте (&__data_end__ - &__data_start__)
байты из &__data_start__
в &__data_destination__
перед звонком main()
,
Вы должны также очистить .bss
, т.е. заполните его нулями, чтобы избежать следующего сюрприза.
Если вы связываетесь с библиотекой C, вы можете использовать memcpy()
а также memset()
, иначе вы должны написать свой собственный код на C или сборке.