GCC 忽略 __attribute__((section("CCMRAM")))。怎么修?

GCC ignores __attribute__((section("CCMRAM"))). How to fix?

我正在尝试使用我的 cortex-m4 (STM32F407) 的核心耦合存储器 (CCMRAM)。它适用于 Keil MDK-ARM,但 gcc-arm-none-eabi 忽略 __attribute__((section("CCMRAM"))).

 #define configTOTAL_HEAP_SIZE 1000*1024
 #define region1_HEAP_SIZE  (40*1024)
 #define region2_HEAP_SIZE  (configTOTAL_HEAP_SIZE - region1_HEAP_SIZE)

 static uint8_t ucHeap1[ region1_HEAP_SIZE ]  __attribute__((section("CCMRAM")));
 static uint8_t ucHeap2[ region2_HEAP_SIZE ];
 const HeapRegion_t xHeapRegions[] =
 {
     { ucHeap1, sizeof(ucHeap1) },
     { ucHeap2, sizeof(ucHeap2) },
     { NULL, 0 } /* Terminates the array. */
 };

手动https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes

根据手册我也尝试初始化ucHeap1

 static uint8_t ucHeap1[ region1_HEAP_SIZE ]  __attribute__((section("CCMRAM"))) = {0};

但是没有效果。

地图文件不包含任何关于 ucHeap1 的内容。 GCC 编译时没有关于属性的警告。但未能 link 因为:

arm-none-eabi/bin/ld: avds.elf section `.bss' will not fit in region `RAM'
arm-none-eabi/bin/ld: region `RAM' overflowed by 55032 bytes

这55032应该分配在CCMRAM中。但它会尝试使用 RAM。 请帮助我了解如何让它发挥作用。

链接描述文件:

ENTRY(Reset_Handler)
_estack = 0x20000000 + 128K - 1;
_Min_Heap_Size = 0;
_Min_Stack_Size = 0x200;
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1024K
  RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
  CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
SECTIONS
{
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector))
    . = ALIGN(4);
  } >FLASH
  .text :
  {
    . = ALIGN(4);
    *(.text)
    *(.text*)
    *(.glue_7)
    *(.glue_7t)
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
    _etext = .;
  } >FLASH
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)
    *(.rodata*)
    . = ALIGN(4);
  } >FLASH
  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH
  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH
  _sidata = LOADADDR(.data);
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;
  } >RAM AT> FLASH
  _siccmram = LOADADDR(.ccmram);
  .ccmram :
  {    . = ALIGN(4);
    _sccmram = .;
    *(.ccmram)
    *(.ccmram*)
    . = ALIGN(4);
    _eccmram = .;
  } >CCMRAM AT> FLASH
  . = ALIGN(4);
  .bss :
  {
    _sbss = .;
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    _ebss = .;
    __bss_end__ = _ebss;
  } >RAM
  ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
  .ARM.attributes 0 : { *(.ARM.attributes) }
}

.ccmram 部分名称不是 CCMRAM。请注意,带有前导点的部分应该通过一个小的忽略约定留给实现。所以更喜欢没有前导点的部分名称。

删除您的 .ccmram : { ... } 并将其替换为:

 .ccmram :   {
    .  = ALIGN(4);
    _sccmram = .;
    KEEP(*(CCMRAM))    # section is named CCMRAM __not__ .ccmram and __not__ .ccmram*
    . = ALIGN(4);  
    _eccmram = .;
 } >CCMRAM AT> FLASH

更改后:

$ arm-none-eabi-gcc main.c -Wl,-T,./linker.ld --specs=nosys.specs && arm-none-eabi-nm ./a.out  | grep ucHeap
/usr/lib/gcc/arm-none-eabi/10.2.0/../../../../arm-none-eabi/bin/ld: warning: cannot find entry symbol Reset_Handler; defaulting to 0000000008000000
10000000 d ucHeap1
20000434 b ucHeap2

或者您可以将 __attribute__((section("CCMRAM"))) 更改为 __attribute__((section(".ccmram")))__attribute__((section(".ccmram*"))) 以匹配链接描述文件中使用的节名称。

尽管如此,您的 .bss 部分可能会溢出。在我的测试中,configTOTAL_HEAP_SIZE 宏未定义,region2_HEAP_SIZE- 40*1024,它是负数,因此环绕并导致一个大的正数。

我测试了:

cat >Makefile <<EOF    
all:
    arm-none-eabi-gcc main.c -Wl,-T,./linker.ld --specs=nosys.specs && arm-none-eabi-nm ./a.out  | grep ucHeap
EOF

cat >linker.ld <<EOF
ENTRY(Reset_Handler)
_estack = 0x20000000 + 128K - 1;
_Min_Heap_Size = 0;
_Min_Stack_Size = 0x200;
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1024K
  RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
  CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
SECTIONS
{
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector))
    . = ALIGN(4);
  } >FLASH
  .text :
  {
    . = ALIGN(4);
    *(.text)
    *(.text*)
    *(.glue_7)
    *(.glue_7t)
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
    _etext = .;
  } >FLASH
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)
    *(.rodata*)
    . = ALIGN(4);
  } >FLASH
  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH
  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH
  _sidata = LOADADDR(.data);
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;
  } >RAM AT> FLASH

  .ccmram :
  {
    . = ALIGN(4);
    _sccmram = .;
    KEEP(*(CCMRAM))
    . = ALIGN(4);
    _eccmram = .;
  } >CCMRAM AT> FLASH
  . = ALIGN(4);
  .bss :
  {
    _sbss = .;
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    _ebss = .;
    __bss_end__ = _ebss;
  } >RAM
  ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
  .ARM.attributes 0 : { *(.ARM.attributes) }
}
EOF

cat >main.c <<EOF
#include <stdint.h>
#include <stddef.h>
static uint8_t ucHeap1[ 10 ]  __attribute__((section("CCMRAM")));
static uint8_t ucHeap2[ 20 ];
typedef struct {
    uint8_t *p;
    size_t s;
} HeapRegion_t;
const HeapRegion_t xHeapRegions[] =
{
     { ucHeap1, sizeof(ucHeap1) },
     { ucHeap2, sizeof(ucHeap2) },
     { NULL, 0 } /* Terminates the array. */
};
int main() {
    return xHeapRegions[1].s;
}
EOF
__attribute__((section("CCMRAM")));

您没有 CCMRAM 部分。您有 .ccmram.

部分