2021-09-28 02:20 PM
Yet another question on locating data, this time fixed in flash. I want to place some main application attributes at a fixed flash location so that my bootloader can learn about the installed app. I have had partial success. (For now this is for an STM32F103, but I'm just learning so that's not for sure.)
With STM32CubeIde I have this in my main.c application code:
uint32_t const Version __attribute__((section(".AppInfo"))) = 0x12345678UL;
uint32_t const Features __attribute__((section(".AppInfo"))) = 0xDEADC0DEUL;
And in the .ld file I have added this (between .isr_vector (0x08002000) and .text:
.AppInfo 0X08003000 :
{
. = ALIGN(4);
KEEP(*(.AppInfo))
. = ALIGN(4);
} >FLASH
Now, while this works (I checked the .map file), I get a giant hole in my Flash usage between the vectors and where my AppInfo goes. Then of course the .text begins after.
There is no way to have the linker mix this into the .text area? I would like to have control over where the AppInfo goes, so any suggestions? Should I just pick the next boundary after the ISR Vectors and hope that table never grows? (seems like not a brilliant idea!)
2021-09-28 02:23 PM
For comparison, here is what I am doing in Keil (I build in both for now).
uint32_t const Version __attribute__((at(0X08003000UL))) = 0x12345678UL; // Compiler v5
uint32_t const Features __attribute__((at(0X08003004UL))) = 0xDEADC0DEUL; // Compiler v5
And that's all I've had to do (surprisingly).
2021-09-28 02:35 PM
The GCC Linker, which is used by STM32CubeIDE, has no way of doing this in a similar fashion to Keil.
The vector table length won't change unless you change chips. Seems like a fine place. It won't grow by a lot, in any case, so having a bit of buffer for the vector table and placing your structure right after that seems like a fine solution.
Another solution is to place things like this in unused spaces within the vector table. Technically not allowed, but it works. Would also be chip dependent.
2021-09-28 03:05 PM
I'd make it a structure to commit the ordering, content, and __attribute__ it into the carved out AppInfo section.
2021-09-28 07:14 PM
>There is no way to have the linker mix this into the .text area? I would like to have control over where the AppInfo goes, so any suggestions? Should I just pick the next boundary after the ISR Vectors and hope that table never grows? (seems like not a brilliant idea!)
The data is for the boot code to interrogate. You could put it anywhere. But you want the boot to find it at some fixed start address and you want it to be simple.
Placing it in the middle of the .text section is not sensible because of its unnecessary impacts.
You could make it the first input section of the .text section, if you want to. But placing it immediately following the vector table is more sensible as it is better to read and to administer.
Putting it in the vector table is sensible too, so long as it is after any vectors you'd use.
Its length may change with no trouble. Whether that's because it is variable length and the boot code would know how to parse it, or that's because you may need to add details in some backwards compatible fashion in future, the linking takes care of that.
Your C definition
const char myData[] __attribute__ ((section ("MY_SECTION"))) = "the data";
Your linker command file:
<snip>
SECTIONS
{
.isr_vector :
{
KEEP(*(.isr_vector))
} >APP_VECTOR
MY_SECTION :
{
KEEP(*(MY_SECTION))
} >APP_ROM
.text : ALIGN(4)
{
*(.text*)
<snip>
} >APP_ROM
<snip>
https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-section-variable-attribute
https://sourceware.org/binutils/docs/ld/MEMORY.html#MEMORY
https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS
2021-09-29 07:15 AM
Thanks gang! As mentioned I need to establish the address for all time, so I will place it after the vectors as recommended. I will also allow (waste) a bit of space between the vectors and my section in case the vector table size changes due to a micro part change. It may be that F103 is not suitable (I'm only using it due to the wealth of educational materials available). I may switch to F4 or newer G0 or L0 part or other.
If I end up using the Keil tools, then this question is moot.
2021-09-29 11:57 AM
You can combine both methods. Put your constant data immediately after the vector table and put an address to that location in an unused slot of vector table. There are 5 unused slots between the first 16, which will be the same for almost all Cortex-M CPUs. Linker script can do all of it automatically.
2021-09-30 08:18 AM
This is a very interesting idea! I assume you mean the "Reserved" ones from the table below (found in startup_stm32f103xb.s for example)? I would prefer it said "Unused" rather than "Reserved" though. 😊 Alternatively one could choose a vector in the silicon vendor section after, but I'm not experienced enough to know how stable those are from variant to variant.
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0