I'd like to have a variable located in onboard flash
#include <cr_section_macros.h> __RODATA(BoardFlash) const volatile uint64_t BoardFlashMarker = 0x0123456789abcdef;
But a warning is produced:
Warning: setting incorrect section attributes for .rodata.$BoardFlash
This is the compiler generated code:
.global BoardFlashMarker .section .rodata.$BoardFlash,"aw"
Are there any obvious mistakes in my approach?
It seems for some reason the compiler applies the "aw" attribute, even though the variable is declared const.
I tried to work around this by setting the attributes "manually" and hacking the correct(?) attribute:
__attribute__ ((section(".rodata.$BoardFlash,\"a\"@"))) const volatile uint64_t BoardFlashMarker = 0x0123456789abcdef;
which produces the following code:
.global BoardFlashMarker .section .rodata.$BoardFlash,"a"@,"aw"
the @ serves as comment, thus the "aw" is ineffective and the warning is gone.
I'd rather not use such hacks, but also I don't like the warnings.
Did anybody have experienced this behavior?
I use MCUXpresso IDE v11.1.0 [Build 3209].
Same Problem here... I have a three-dimensional array covering two cosecutive flash sectors for configuration data; every now and then one page of data is added by software using iap, and one sector is erased after the other one was used for the first entry.
First I made the array just const, but as you describe the compiler ignored the real flash data (the first byte was read as 0, which is simply nonsense for an erased flash memory, but there is no initializer for the array at all). So I tried the volatile qualifier, and now the program works, but there is this Warning: setting incorrect section attributes for .rodata.$UserFlash... This sort of warnings that tend to be time bombs.
Interestingly, this is an assembler message. Does the compiler use different assembler code for flash read accesses? And what could I do to get things right? Maybe I could build some pointer-to-structure thing around my array, but I don't like workarounds for things that should work directly.
Unfortunately, there is not much you can do here, using standard Gcc - the language is just not designed for these sorts of scenario (data is sometimes const, sometimes volatile...). I’d suggest the best way forward is to use pointers to structures as you suggest, or perhaps the hack as suggested by the original poster (but this may have side-effects and may not work in future release of gcc).
I think it is your use of volatile that is causing the problem. Here is my reasoning.
volatile is normally used on peripheral registers as the values can change externally to the code. Volatile means ever changing. This implies that a volatile is writable (by something). This is therefore obviously incompatible with being in flash, which cannot change (except, of course, if you are a flash programmer, but that is external to this). So, I think volatile and placing in flash are logically incompatible.
this is my theory, but I think it is logical.
So, you need to remove the volatile keyword from your declaration- it won’t affect your code.
Hello Con Verse,
Thanks for your input. Right, when I remove the volatile, the warning goes away.
Unfortunately, when I remove the volatile, the compiler optimizes out the actual read-from-flash and assumes the initialized value. However, the flash might be written by explicitly writing the flash through SPI. That's why I need the variable to be volatile. Actually, this declaration is a basic example for a more complex structure, where data is actually written to flash and read again later. The warning is thrown just the same.
I think volatile is the right way to tell the compiler that it must read the value from flash. Is there any other way I could tackle this? More ideas?
Could you do it with pointers? So, declare your structure (maybe as a const volatile typedef struct...) and then initialise the pointer to your RODATA region?