2

背景

我试图在我的 STM32 设备上使用 SRAM 的一个特殊部分,它位于 address 0x40006000。我在 ST 的示例代码中看到的一种方法是简单地创建指针,其值恰好位于 RAM 的该部分中。我想要做的是让链接器为我管理该部分中的静态分配。

基本上,我从这样的事情开始:

static uint16_t *buffer0 = ((uint16_t *)0x40006000);
static uint16_t *buffer1 = ((uint16_t *)0x40006080);

像这样的东西(我认为它不容易破碎,也没有那么老套,虽然不那么便携):

#define _PMA __attribute__((section(".pma"), aligned(2)))
static uint16_t _PMA buffer0[64];
static uint16_t _PMA buffer1[64];

为了做到这一点,我修改了我的链接器脚本,在其中有一个名为“PMA”的新内存,0x40006000并且我在其中找到了“.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确实位于0x40006000and 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所有内容从0x08000000to复制0x400060FF到该 bin 文件中。这显然不是我想要发生的。我预计它只会复制闪存。

现在,显然我可以按照-R .pma我的objcopy命令说,一切都会很愉快。但是,我很好奇的是如何objcopy知道不复制.data到二进制图像中。我注意到跑步的结果与没有objcopy -R .data跑步的结果完全相同objcopy。与.bss. 这告诉我它不是链接器脚本中的命令(这是我能看到的和AT之间唯一真正的区别).data.bss

我可以做些什么来使我的.pma部分表现得与 's 的角度相同.data.bssobjcopy's 的角度来看?我正在使用的中间 elf 文件中的.data/是否有一些有趣的事情发生(见上文生成 elf 文件的链接器命令)?.bss

4

1 回答 1

1

将您的部分定义为“.pma”很可能给它类型“PROGBITS”(与 readelf 检查),这表明要在目标上加载的部分。

您想要/需要的是定义一个不必在目标上加载的部分,例如“.bss”部分,其类型为“NOBITS”。

我经常使用以下部分定义来避免将某些缓冲区放入“.bss”部分(因为“.bss”部分的零初始化会减慢启动阶段):

静态 uint8_t uart1_buffer_rx[4096] __attribute__((section(".noinit,\"aw\",%nobits@")));

我不记得我为什么使用名称“.noinit”,但是这部分出现在“.bss”部分之后。

在您的情况下,在“.pma”部分声明之后添加“aw”和“nobits”标志可能会有所帮助。

于 2016-11-09T14:29:49.950 回答