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

1

I am trying to use core-coupled memory (CCMRAM) of my cortex-m4 (STM32F407). It works fine with Keil MDK-ARM but gcc-arm-none-eabi ignores __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. */
 };

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

According to manual I also tried to initialize ucHeap1

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

But does no effect.

Map-file contains nothing about ucHeap1. GCC compiles with no warnings about attribute. But fail to link because of:

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

These 55032 should be allocated in CCMRAM. But it tries to use RAM. Please help me to understand what to do to make it work.

Linker script:

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) }
}
c
gcc
linker
arm
ld
asked on Stack Overflow Oct 5, 2020 by kyb • edited Oct 5, 2020 by kyb

2 Answers

2

.ccmram section name is not CCMRAM. Note that sections with a leading dot should be by a small ignored convention left to implementations. So prefer just section names without leading dot.

Remove your .ccmram : { ... } and replace it by:

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

after that change:

$ 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

Or alternatively you could change __attribute__((section("CCMRAM"))) to __attribute__((section(".ccmram"))) or to __attribute__((section(".ccmram*"))) to match section names used in linker script.

Your .bss section could be overflowing nonetheless. As in my tests configTOTAL_HEAP_SIZE macro was undefined, region2_HEAP_SIZE was - 40*1024 which is negative so wraped around and resulted in a big positive number.

I tested with:

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
answered on Stack Overflow Oct 5, 2020 by KamilCuk
1
__attribute__((section("CCMRAM")));

you do not have section CCMRAM. You have section .ccmram.


User contributions licensed under CC BY-SA 3.0