Perusing the GCC linker script supplied as part of SDK v16, I noticed that the .data section is specified as follows:
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
*(.preinit_array)
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
*(SORT(.init_array.*))
*(.init_array)
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE_HIDDEN (__fini_array_end = .);
*(.jcr)
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
Why on earth are virtual tables and the libc initialization/finalization arrays (__pre_init_array, __init_array, __fini_array) placed in RAM?
Let's start with the virtual tables: Vtables are compile-time constants, read-only, and consist entirely of function pointers. They function perfectly well in FLASH. The only reason one might even consider allocating them to RAM is for performance (on some architectures RAM doesn't require as many wait cycles as FLASH). But considering how much more FLASH is available than RAM, I would expect the default placement to be in FLASH.
For the initialization/finalization arrays, these are also compile-time constants, read-only, and consist entirely of function pointers. However, these function pointers are used exactly once, either at boot or if a program ever returns from main(). Thus, there is almost zero performance benefit to placing them to RAM. I would definitely think these belong in FLASH.
So, this begs the question: is there any rational for why RAM is being squandered to store what are effectively read-only lookup tables?