GCC ignore __attribute __ ((section («CCMRAM»))). Comment réparer?

Oct 05 2020

J'essaie d'utiliser la mémoire couplée au cœur (CCMRAM) de mon cortex-m4 (STM32F407). Cela fonctionne bien avec Keil MDK-ARM mais gcc-arm-none-eabi ignore __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. */
 };

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

Selon le manuel, j'ai également essayé d'initialiser ucHeap1

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

Mais n'a aucun effet.

Map-file ne contient rien à propos de ucHeap1. GCC compile sans avertissement sur l'attribut. Mais ne parvenez pas à établir un lien à cause de:

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

Ces 55032 doivent être alloués dans CCMRAM. Mais il essaie d'utiliser la RAM. S'il vous plaît, aidez-moi à comprendre ce qu'il faut faire pour que cela fonctionne.

Script de l'éditeur de liens:

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) }
}

Réponses

2 KamilCuk Oct 05 2020 at 14:38

.ccmramle nom de la section ne l'est pas CCMRAM. Notez que les sections avec un point de début devraient être par une petite convention ignorée laissée aux implémentations. Préférez donc uniquement les noms de section sans point de début.

Retirez votre .ccmram : { ... }et remplacez-le par:

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

après ce changement:

$ 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

Ou bien, vous pouvez changer __attribute__((section("CCMRAM")))pour __attribute__((section(".ccmram")))ou __attribute__((section(".ccmram*")))pour correspondre aux noms de section utilisés dans le script de l'éditeur de liens.

Votre .bsssection pourrait néanmoins déborder. Comme dans mes tests, la configTOTAL_HEAP_SIZEmacro n'était pas définie, region2_HEAP_SIZEc'était - 40*1024qui est négatif, donc enveloppé et a abouti à un grand nombre positif.

J'ai testé avec:

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
1 0___________ Oct 05 2020 at 15:55
__attribute__((section("CCMRAM")));

vous n'avez pas de section CCMRAM. Vous avez une section .ccmram.