我试图在位于地址0x40006000
的STM32设备上使用特殊的SRAM部分。我在ST的示例代码中看到的一种方法是简单地创建指针,其值恰好存在于RAM的那一部分内。我想要做的是让链接器为我管理该部分中的静态分配。
基本上,我是这样的:
static uint16_t *buffer0 = ((uint16_t *)0x40006000);
static uint16_t *buffer1 = ((uint16_t *)0x40006080);
对于这样的事情(我认为远不那么容易破坏,而不是那么hacky,虽然不那么便携):
#define _PMA __attribute__((section(".pma"), aligned(2)))
static uint16_t _PMA buffer0[64];
static uint16_t _PMA buffer1[64];
为了实现这一目标,我修改了我的链接描述文件以获得一个名为" PMA"位于0x40006000
,我找到了#34; .pma"其中的部分如下:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
PMA (xrw) : ORIGIN = 0x40006000, LENGTH = 1024 /* This is the memory I added */
}
SECTIONS
{
.text
{
..blah blah blah..
} > FLASH
...more sections, like rodata and init_array..
/* Initialized data goes into RAM, load LMA copy after code */
.data
{
..blah blah blah with some linker symbols to denote the start and end..
} >RAM AT> FLASH
.bss
{
..blah blah blah..
} >RAM
.pma /* My new section! */
{
_pma_start = .;
. = ALIGN(2);
*(.pma)
*(.pma*)
} >PMA
}
所以这看起来很好,花花公子,我的东西编译,地图显示buffer0
和buffer1
确实放在0x40006000
和0x40006080
。这是我的makefile的最后一位的输出:
arm-none-eabi-gcc obj/usb_desc.o obj/usb_application.o obj/osc.o obj/usb.o obj/main.o obj/system_stm32f1xx.o obj/queue.o obj/list.o obj/heap_1.o obj/port.o obj/tasks.o obj/timers.o obj/startup_stm32f103x6.o -TSTM32F103X8_FLASH.ld -mthumb -mcpu=cortex-m3 --specs=nosys.specs -Wl,-Map,bin/blink.map -o bin/blink.elf
arm-none-eabi-objdump -D bin/blink.elf > bin/blink.lst
arm-none-eabi-size --format=SysV bin/blink.elf
bin/blink.elf :
section size addr
.isr_vector 268 134217728
.text 13504 134218000
.rodata 44 134231504
.ARM 8 134231548
.init_array 8 134231556
.fini_array 4 134231564
.data 1264 536870912
.jcr 4 536872176
.bss 1348 536872180
._user_heap_stack 1536 536873528
.pma 256 1073766400
.ARM.attributes 41 0
.debug_info 26748 0
.debug_abbrev 5331 0
.debug_aranges 368 0
.debug_line 5274 0
.debug_str 8123 0
.comment 29 0
.debug_frame 4988 0
Total 69146
arm-none-eabi-objcopy -R .stack -O binary bin/blink.elf bin/blink.bin
我看到.pma
使用了256个字节,就像我预期的那样。地址看起来也正确。现在,当我ls
bin
目录时,我对此表示欢迎:
-rwxr-xr-x 1 kevin users 939548800 Nov 2 00:04 blink.bin*
-rwxr-xr-x 1 kevin users 221528 Nov 2 00:04 blink.elf*
bin
文件是我通过openocd加载到我芯片上的闪存。它是从0x08000000开始的闪光图像。
旁注:我实际上试图将这个bin文件加载到我的芯片上,然后才意识到它有多大......显然没有用。
这是我删除PMA部分后得到的结果:
arm-none-eabi-size --format=SysV bin/blink.elf
bin/blink.elf :
section size addr
.isr_vector 268 134217728
.text 13504 134218000
.rodata 44 134231504
.ARM 8 134231548
.init_array 8 134231556
.fini_array 4 134231564
.data 1392 536870912
.jcr 4 536872304
.bss 1348 536872308
._user_heap_stack 1536 536873656
.ARM.attributes 41 0
.debug_info 26748 0
.debug_abbrev 5331 0
.debug_aranges 368 0
.debug_line 5274 0
.debug_str 8123 0
.comment 29 0
.debug_frame 4988 0
Total 69018
文件大小完全符合我的预期:
-rwxr-xr-x 1 kevin users 15236 Nov 2 00:09 blink.bin
-rwxr-xr-x 1 kevin users 198132 Nov 2 00:09 blink.elf
据我了解,这里发生的事情是objcopy
刚刚将0x08000000
到0x400060FF
的所有内容复制到该bin文件中。这显然不是我想要发生的事情。我希望它只是复制闪光灯。
现在,显然我可以在-R .pma
命令上说objcopy
,一切都会很开心。但是,我感到好奇的是objcopy
如何知道不将.data
复制到二进制图像中。我注意到,运行objcopy -R .data
与运行objcopy
的结果完全相同。与.bss
相同。这告诉我它不是链接器脚本中的AT
命令(这是我在.data
和.bss
之间唯一真正的区别)
从.pma
的角度来看,我的.data
部分与.bss
或objcopy
的行为方式相同,我该怎么做?我在使用的中间精灵文件中使用.data
/ .bss
是否有一些有趣的事情(请参阅上面的链接器命令生成elf文件)?
答案 0 :(得分:0)
将您的部分定义为“.pma”,最有可能为其提供“PROGBITS”类型(使用readelf检查),这表示要在目标上加载的部分。
您想要/需要的是定义一个不必在目标上加载的部分,例如“.bss”部分,其类型为“NOBITS”。
我经常使用以下部分定义来避免将某些缓冲区放入“.bss”部分(因为这会因“.bss”部分的零初始化而减慢启动阶段):
static uint8_t uart1_buffer_rx [4096] __attribute __((section(“。noinit,\”aw \“,%nobits @”)));
我不记得为什么我使用了名字“.noinit”,但这部分出现在“.bss”部分之后。
在你的情况下,在“.pma”部分声明之后添加“aw”和“nobits”标志可能会有所帮助。