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
这条线
} > 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或汇编中编写自己的代码.