我尝试为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)。
我真的不知道为什么全局变量值不正确。
最好的问候, 马辛
答案 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或汇编语言编写自己的代码。