7
\$\begingroup\$

I am working with a STM32 eval-board from STMicro which includes a ARM Cortex-M4 processor. I need a LUT for cosinus and sinus (read-only variables). I need to manage my RAM memory therefore I want to store these LUT in flash memory.

First: is it better to create a interpolate computation of cosinus/sinus or the FLASH reading is fast enough?

Secondly, how to put the variables in FLASH memory. ST provides some examples, but maybe, for my problem I just need to declare the LUT variables as static const and it will be like code?

\$\endgroup\$
12
\$\begingroup\$

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.

\$\endgroup\$
4
\$\begingroup\$

No, you can't put variables in the read-only memory. You can, however, put constants there, which is all you need since you are asking about a sine/cosine lookup table. Those values are fixed by math and don't need to change on the fly.

Surely the language documentation describes how to force a array of constants into program memory. This is usually done with some keyword, or by specifying attributes for a linker section, or possibly by extra information passed to the linker separately.

As for how to implement a sine and cosine lookup, see these previous answers:

https://electronics.stackexchange.com/a/60819/4512
https://electronics.stackexchange.com/a/16516/4512

\$\endgroup\$
  • \$\begingroup\$ Using the keyword const with the language C seems to put the data into flash/program memory. How to check, with the IDE (I use CooCox with ARM GNU gcc compiler), if these variables are really mapped into the FLASH memory ? Thks. \$\endgroup\$ – user2412542 Jul 1 '13 at 12:34
  • \$\begingroup\$ @user: Probably, although in theory that only tells the compiler that you don't intend to modify the value. There is no way to know for sure for any one compiler/linker toolset. You still need to read the documenation, which of course you should anyway. Keep in mind that the OP never said what language he is using. \$\endgroup\$ – Olin Lathrop Jul 1 '13 at 12:37
  • \$\begingroup\$ @user2412542 You can add an option to the gcc command and have it generate a memory map file, or you can use the objdump command to see where various things will be placed in memory. \$\endgroup\$ – Joe Hass Jul 1 '13 at 14:16
  • \$\begingroup\$ On many compilers, variables with a const modifier will be allocated in a separate linker section from those without; there will typically be an option to force some linker sections to code space, and in many cases the sections that store const variables will automatically be placed there. I believe that ARM compilers typically have such default behavior, so a const directive should suffice for what you need. \$\endgroup\$ – supercat Jul 1 '13 at 16:36
  • \$\begingroup\$ You can use your FLASH memory to store variables. Not right out of the box though, there is some code involved. Here is good example, different MCU but the same Cortex family. os.mbed.com/users/olympux/code/eeprom_flash \$\endgroup\$ – Barmaley Apr 16 '18 at 19:37
4
\$\begingroup\$

to have data put in flash declare it as const

const unsigned int lut[]= { 0x1234, 0xab, 0xcd, 0xefa1123, 0x1122334, ...

your linker script may need to have an entry, depends on the flavor and age of your toolchain, it could go in .text or .rodata or other depending again on your toolchain. and you would then put that section in flash.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.