Reputation: 133
Recently I've been given some legacy code that has a couple issues. In some code I noticed that a lot of status reporting is stored as 3d char arrays. The kicker is that a LOT of this space is actually unused. For example this:
const char txt[<60>][6][150] =
{
{"This is a very very long string of text", "The others are empty", "", "", "", ""},
{"The text is different, but similarly a lot of unused space", etc...}
};
(The 60 is not there, but there are 60 entries ).
This code is then put into flash through QSPI by using the following above the declaration
__attribute__((section(".ExtQSPIFlashSection")))
This section is defined as such in the linker:
QSPI (rx) : ORIGIN = 0x90000000, LENGTH = 64M
.ExtQSPIFlashSection : { *(.ExtQSPIFlashSection) } >QSPI
As a more memory efficient method I'd like to rewrite it as such:
const char **txt[] =
{
(const char*[]) {"This is a very very long string of text", "The others are empty", "", "", "", ""},
(const char*[]){"The text is different, but similarly a lot of unused space", etc...}
};
However, now the arrays (or whatever is the correct term) are written to the RAM instead, which is causing it to overflow.
'._user_heap_stack' will not fit in region RAM
region 'RAM' overflowed by 6888 bytes
This 6888 bytes is WAY less than it would be with the original method with the section part removed, but not the desired result.
How can I tell the (I think) linker to also write the strings into the flash?
Everything is at all times immutable, no changes will ever be made, let it be the pointer or the values they point to.
Edit: I noticed my title is likely not perfect, please do tell what to change it to.
Upvotes: 4
Views: 1911
Reputation: 213920
This is one of them cases in C where they invented needlessly complex syntax.
The linker needs to know that the table of pointers is read-only, and not just the string literals pointed at. Otherwise the string literals end up in flash as usual, but the pointers in RAM.
const char **
means (read from right to left), pointer to pointer to const char
. But in order to get this inside flash, you need read-only-pointer to read-only-pointer to const char
.
To take a pointer itself read-only, rather than the pointed-at data, you place a const
keyword to the right side of the *
. That is:
const char *const *const txt;
.
Again, read right-to-left: read-only, pointer to read-only pointer, to const char
.
Looking at your .map file, txt
should now be in segment .rodata
or similar.
Upvotes: 8