Я работаю с оценочной платой STM32 от STMicro, которая включает в себя процессор ARM Cortex-M4. Мне нужна LUT для косинуса и синуса (переменные только для чтения). Мне нужно управлять моей оперативной памятью, поэтому я хочу хранить эти LUT во флэш-памяти.
Во-первых: лучше создать интерполяционное вычисление косинуса/синуса или чтение FLASH будет достаточно быстрым?
Во-вторых, как поместить переменные во FLASH-память. ST предоставляет несколько примеров, но, может быть, для моей проблемы мне просто нужно объявить переменные LUT как статические константы, и это будет похоже на код?
Короткий ответ — объявить переменную с помощью 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 unsigned int lut[]= { 0x1234, 0xab, 0xcd, 0xefa1123, 0x1122334, ...
в вашем скрипте компоновщика может потребоваться запись, в зависимости от вкуса и возраста вашей цепочки инструментов, она может быть в .text или .rodata или в другом, опять же в зависимости от вашей цепочки инструментов. и вы бы поместили этот раздел во флэш-память.
пользователь 2412542
Олин Латроп
Джо Хасс
суперкот
const
модификатором будут размещены в отдельном разделе компоновщика от переменных без модификатора; обычно есть возможность принудительно разместить некоторые разделы компоновщика в пространстве кода, и во многих случаях разделы, в которых хранятсяconst
переменные, будут автоматически помещены туда. Я считаю, что компиляторы ARM обычно имеют такое поведение по умолчанию, поэтомуconst
директивы должно быть достаточно для того, что вам нужно.Бармалей