GCC ignore __attribute __ ((section («CCMRAM»))). Comment réparer?
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
.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
__attribute__((section("CCMRAM")));
vous n'avez pas de section CCMRAM. Vous avez une section .ccmram.