Как хранить переменные во FLASH-памяти

Я работаю с оценочной платой STM32 от STMicro, которая включает в себя процессор ARM Cortex-M4. Мне нужна LUT для косинуса и синуса (переменные только для чтения). Мне нужно управлять моей оперативной памятью, поэтому я хочу хранить эти LUT во флэш-памяти.

Во-первых: лучше создать интерполяционное вычисление косинуса/синуса или чтение FLASH будет достаточно быстрым?

Во-вторых, как поместить переменные во FLASH-память. ST предоставляет несколько примеров, но, может быть, для моей проблемы мне просто нужно объявить переменные LUT как статические константы, и это будет похоже на код?

Ответы (3)

Короткий ответ — объявить переменную с помощью constключевого слова. Если ваш микроконтроллер действительно помнит значение вашей constпеременной (т. е. ваше вычисление синуса действительно работает), оно в значительной степени должно храниться во флэш-памяти, иначе оно будет потеряно при первой перезагрузке после программирования.

Длинный ответ связан со сценарием компоновщика. Эти скрипты зависят от MCU и сообщают компоновщику, куда и что поместить. Обычно этот скрипт предоставляется IDE, но вы можете написать свой собственный. В моей установке STM32F4 мой скрипт компоновщика начинается с такого утверждения:

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
}

В нем говорится, что флэш-память начинается по адресу 0x08000000, а ОЗУ - по адресу 0x20000000. Эти адреса можно найти в даташите, где описана карта памяти. Остальная часть скрипта может быть задействована, но в какой-то момент будет присутствовать что-то вроде этого:

.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

Это говорит о том, что все .textразделы (так компилятор называет раздел кода) и .rodataразделы (так компилятор называет constпеременные) должны быть помещены в раздел flash.

Как указывалось выше, .mapфайл — это основной способ проверить, что и куда помещает компоновщик. Вы указываете компоновщику сгенерировать его, используя эту опцию:

arm-eabi-gcc -Wl,-Map=my_program.map ...

Вы можете найти свой символ внутри этого файла карты, посмотреть, по какому адресу он был сохранен, и сравнить его с картой памяти, указанной в таблице данных MCU.

Нет, вы не можете поместить переменные в постоянную память. Однако вы можете поместить туда константы, и это все, что вам нужно, поскольку вы спрашиваете о таблице поиска синуса/косинуса. Эти значения фиксируются математикой, и их не нужно менять на лету.

Наверняка документация по языку описывает, как принудительно поместить массив констант в память программы. Обычно это делается с помощью некоторого ключевого слова или путем указания атрибутов для раздела компоновщика или, возможно, дополнительной информации, передаваемой компоновщику отдельно.

Что касается того, как реализовать поиск синуса и косинуса, см. Эти предыдущие ответы:

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

Использование ключевого слова const с языком C, по-видимому, помещает данные во флэш-память/память программ. Как проверить с помощью IDE (я использую CooCox с компилятором ARM GNU gcc), действительно ли эти переменные отображаются во флэш-памяти? Спасибо.
@user: Возможно, хотя теоретически это только сообщает компилятору, что вы не собираетесь изменять значение. Невозможно узнать наверняка для какого-либо одного набора инструментов компилятора/компоновщика. Вам все равно нужно читать документацию, что, конечно, вы должны делать в любом случае. Имейте в виду, что ОП никогда не говорил, какой язык он использует.
@user2412542 user2412542 Вы можете добавить параметр в команду gcc и заставить ее генерировать файл карты памяти, или вы можете использовать команду objdump, чтобы увидеть, где в памяти будут размещены различные вещи.
Во многих компиляторах переменные с constмодификатором будут размещены в отдельном разделе компоновщика от переменных без модификатора; обычно есть возможность принудительно разместить некоторые разделы компоновщика в пространстве кода, и во многих случаях разделы, в которых хранятся constпеременные, будут автоматически помещены туда. Я считаю, что компиляторы ARM обычно имеют такое поведение по умолчанию, поэтому constдирективы должно быть достаточно для того, что вам нужно.
Вы можете использовать свою флэш-память для хранения переменных. Однако не прямо из коробки, здесь задействован некоторый код. Вот хороший пример, разные микроконтроллеры, но одно и то же семейство Cortex. os.mbed.com/users/olympux/code/eeprom_flash

чтобы данные помещались во флэш-память, объявите их константными

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

в вашем скрипте компоновщика может потребоваться запись, в зависимости от вкуса и возраста вашей цепочки инструментов, она может быть в .text или .rodata или в другом, опять же в зависимости от вашей цепочки инструментов. и вы бы поместили этот раздел во флэш-память.