I tried to follow this tutorial to make something similar on STM32F303. I dedicate 4 KiB of CCMRAM to the overlay region:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 12K
CCMRAM_OVERLAY (xrw) : ORIGIN = 0x10003000, LENGTH = 4K
}
Then I define overlay:
/* Define output sections */
SECTIONS
{
/* overlays */
OVERLAY : NOCROSSREFS
{
.eff1 { src/effects/effect1.o(.text .data) }
.eff2 { src/effects/effect2.o(.text .data) }
} >CCMRAM_OVERLAY AT>FLASH
Then I try to place addresses and lengths table into RAM:
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
__eff_table = .;
LONG(ABSOLUTE(ADDR(.eff1))); LONG(SIZEOF(.eff1)); LONG(LOADADDR(.eff1));
LONG(ABSOLUTE(ADDR(.eff2))); LONG(SIZEOF(.eff2)); LONG(LOADADDR(.eff2));
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
Functions themselves end up in FLASH as they should but in .map
file I see that the load addresses are snapped to the beginning of the FLASH and that the sizes of both segments are zero:
.eff1 0x10003000 0x0 load address 0x08000000
src/effects/effect1.o(.text .data)
[!provide] PROVIDE (__load_start_eff1, LOADADDR (.eff1))
[!provide] PROVIDE (__load_stop_eff1, (LOADADDR (.eff1) + SIZEOF (.eff1)))
.eff2 0x10003000 0x0 load address 0x08000000
src/effects/effect2.o(.text .data)
[!provide] PROVIDE (__load_start_eff2, LOADADDR (.eff2))
[!provide] PROVIDE (__load_stop_eff2, (LOADADDR (.eff2) + SIZEOF (.eff2)))
.data 0x20000000 0x2c load address 0x08000564
0x20000000 . = ALIGN (0x4)
0x20000000 _sdata = .
0x20000000 __eff_table = .
0x20000000 0x4 LONG 0x10003000 ABSOLUTE (ADDR (.eff1))
0x20000004 0x4 LONG 0x0 SIZEOF (.eff1)
0x20000008 0x4 LONG 0x8000000 LOADADDR (.eff1)
0x2000000c 0x4 LONG 0x10003000 ABSOLUTE (ADDR (.eff2))
0x20000010 0x4 LONG 0x0 SIZEOF (.eff2)
0x20000014 0x4 LONG 0x8000000 LOADADDR (.eff2)
Meanwhile the functions are located there (not at the beginning of Flash, of course, and they have non-zero length):
My question is: how to make it work? I want functions to be compiled in such a way that I can copy them to CCMRAM and call them, and I want their addresses and lengths array to be properly filled at compilation time. What I am doing wrong? I don't have much experience with linker scripts but in previous project I managed to just copy and execute functions in CCMRAM once. But here I want to swap functions at the same memory location in runtime.
I managed to make it work. You need to replace
/* Define output sections */
SECTIONS
{
/* overlays */
OVERLAY : NOCROSSREFS
{
.eff1 { src/effects/effect1.o(.text .data) }
.eff2 { src/effects/effect2.o(.text .data) }
} >CCMRAM_OVERLAY AT>FLASH
with
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* overlays */
OVERLAY : NOCROSSREFS
{
.eff1 { src/effects/effect1.o(.text .text* .data .data*) }
.eff2 { src/effects/effect2.o(.text .text* .data .data*) }
} >CCMRAM_OVERLAY AT>FLASH
ISR vectors table goes first, otherwise the program won't start!
I tested it on real hardware (it works), and now map file looks correct:
.data 0x20000000 0x2c load address 0x08000578
0x20000000 . = ALIGN (0x4)
0x20000000 _sdata = .
0x20000000 __eff_table = .
0x20000000 0x4 LONG 0x10003000 ABSOLUTE (ADDR (.eff1))
0x20000004 0x4 LONG 0x34 SIZEOF (.eff1)
0x20000008 0x4 LONG 0x8000194 LOADADDR (.eff1)
0x2000000c 0x4 LONG 0x10003000 ABSOLUTE (ADDR (.eff2))
0x20000010 0x4 LONG 0x34 SIZEOF (.eff2)
0x20000014 0x4 LONG 0x80001c8 LOADADDR (.eff2)
As you can see, .eff1
and .eff2
now come directly after ISR vector table (which is precisely 0x194
bytes long) and have valid sizes (both functions are LED blinks with busy waits but have different busy-wait delays).