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:
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:
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
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.