I've been messing with this a bit; here's what I've found out so far.
For reference, these tests were all performed with today's libmaple master, which has SHA 3887713e693967983b4247dbb7dd3318a57f73c5.
This is my test rig:
#include "wirish.h"
<define an array of uint32 named 'array'>
int main(void) {
while (true) {
for (unsigned i = 0; i < sizeof(array)/sizeof(array[0]); i++) {
SerialUSB.write(array[i]);
}
}
return 0;
}
I used uint32 so that the numbers wouldn't get confused by padding issues. I print the entire array to defeat any optimizations that might prune it out of the final binary, in whole or in part. Here are some sizes I get for various declarations of "array":
With "uint32 array[4] = {1, 2, 3, 4};"
-------------------------------------
Object file sizes:
text data bss dec hex filename
36 16 0 52 34 build/main.o
As expected, 16 bytes of initialized, mutable data. This will be the baseline for later comparisons.
With "uint32 array[8] = {1, 2, 3, 4, 5, 6, 7, 8};"
-------------------------------------------------
Object file sizes:
text data bss dec hex filename
36 32 0 68 44 build/main.o
As expected, data goes up by 16 bytes, and the other sizes remain the same. This is consistent with non-const initialized variables living in the .data section.
With "const uint32 array[4] = {1, 2, 3, 4};"
-------------------------------------------
Object file sizes:
text data bss dec hex filename
52 0 0 52 34 build/main.o
Interestingly, compared to the baseline, text increases by 16 bytes, and data goes down by the same amount. I took a look at the file build/maple_mini.disas (produced by our Makefile); it had this to say:
08007f2c <_ZL5array>:
8007f2c: 00000001 00000002 00000003 00000004 ................
0x08007f2c is an address in Flash! Interesting.
To dig further, I got GCC to give me its assembly output for main.cpp; here's the relevant excerpt:
.section .rodata._ZL5array,"a",%progbits
.align 2
.set .LANCHOR0,. + 0
.type _ZL5array, %object
.size _ZL5array, 16
_ZL5array:
.word 1
.word 2
.word 3
.word 4
This excerpt from the linker file common_rom.inc explains what happened:
SECTIONS
{
.text :
[ ... irrelevant text omitted ...]
*(.rodata .rodata.* .gnu.linkonce.r.*)
Whenever GCC sticks something into an .rodata section, the linker shoves it into Flash. No idea if this happens for all definitions qualified with const. If so, we might want to deprecate the __FLASH__
macro in favor of just using const
, especially given the situation explained in the following section.
With "uint32 array[4] __FLASH__ = {1, 2, 3, 4};"
-----------------------------------------------
Object file sizes:
text data bss dec hex filename
36 16 0 52 34 build/main.o
This reproduces your results concerning __FLASH__
, namely, that allocations with __FLASH__
appear in data when size output is determined. Confusingly, array no longer shows up in the .disas!
All's not lost, though; from main.cpp's assembly:
.global array
.section .USER_FLASH,"aw",%progbits
.align 2
.set .LANCHOR0,. + 0
.type array, %object
.size array, 16
array:
.word 1
.word 2
.word 3
.word 4
It correctly is in section .USER_FLASH, so it will definitely get stored in Flash on the STM32, since common_rom.inc says this:
/* expose a custom rom only section */
.USER_FLASH :
{
*(.USER_FLASH)
} >rom
And Maple Mini's Flash linker script (support/ld/maple_mini/flash.ld) says this:
MEMORY
{
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
rom (rx) : ORIGIN = 0x08005000, LENGTH = 108K
}
I'm not sure why arm-none-eabi-size is reporting that it lives in data. However, here's a guess: __FLASH__
just ends up expanding into __attribute__((section (".USER_FLASH")))
, and that's just a section which we handle specially in our linker scripts. Since that's all information that arm-none-eabi-size doesn't have, it seems like it's just ignoring the __attribute__(), with the result that array is assumed to live in data.
That obviously really sucks when trying to figure out how much RAM you're using. As a workaround, I'd recommend using both const
and __FLASH__
for the time being. (I checked; all the usages of __FLASH__ in libmaple are also accompanied by 'const', so if the compiler's .rodata behavior is consistent, we shouldn't be giving you any false readings in that regard).
*Whew*! Not sure how many people are still reading by this point, but hopefully this should clarify things a bit.