The short answer is to declare your variable with the const
keyword. If your MCU actually remembers the value of your const
variable (i.e. your sine computation actually works), it pretty much has to be stored in flash memory, otherwise it would be lost at the first reboot after programming.
The long answer has to do with linker script. These scripts are MCU-dependant and tell the linker where to put what. Usually, this script is provided by the IDE, but you can write your own. On my STM32F4 setup, my linker script starts with a such a statement:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
}
It says that the flash starts at address 0x08000000
and the RAM at address 0x20000000
. These addresses can be found in the datasheet where the memory map is described. The rest of the script can get involved, but at some point something along these lines will be present:
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
This says that all .text
sections (that's how the compiler calls code section) and .rodata
sections (that's how the compiler calls const
variables) are to be put in the flash section.
As suggested above, the .map
file is the primary way you can check what the linker puts where. You tell the linker to generate it using this option:
arm-eabi-gcc -Wl,-Map=my_program.map ...
You can search for your symbole inside this map file, see at which address it has been stored and check that against the memory map specified in the MCU datasheet.