Я создаю систему с STM32, которая использует устройство, которое необходимо откалибровать (данные могут храниться в одном 32-битном регистре). Поскольку я все еще создаю и обновляю код, в идеале мне бы хотелось, чтобы регион оставался в том же месте, чтобы каждый раз, когда я собираю и включаю его, не приходилось перекалибровывать его. Очевидно, что MCU не инициализирует значения в этой области, учитывая данные калибровки.
Прямо сейчас я только что выбрал удаленный адрес внутри флэш-региона и надеюсь, что компилятор не перепишет его. Он работает отлично, но кажется, что есть правильный способ заблокировать память со стороны компилятора.
Непонятно, о чем вы спрашиваете. Предположительно, эти калибровочные данные должны быть энергонезависимыми? Для этого вы можете использовать «резервные регистры», если они есть в вашем конкретном STM32, но для этого вам также потребуется резервная батарея — они энергонезависимы только в том смысле, что имеют независимый источник питания. В противном случае внешний EEPROM. Сохранение таких данных на встроенной флэш-памяти возможно, но неэффективно — вам обязательно придется посвятить этому целую флэш-страницу. Разделы без инициализации применимы только к SRAM, и они не являются энергонезависимыми — данные будут потеряны при отключении питания.
Также обратите внимание, что ваш вопрос мало специфичен для встроенного C, управления памятью или даже stm32cubeide - не спамьте теги. Это все зависит от вашего конкретного оборудования в отношении емкости NV-хранилища и схемы электропитания. Вы не уточнили это.
«Компилятор» ничего не записывает — поведение, о котором вы говорите, является делом компоновщика. Использование флэш-памяти для этого проблематично, и хотя она доступна для записи слов, она допускает стирание страниц. Большинство деталей STM32 имеют страницы большого размера и переменной длины. Меньшие части могут иметь страницы одинакового размера, но даже в этом случае они, скорее всего, будут иметь размер 2 КБ или более.
Я думаю, что некоторые детали STM32 имеют эмуляцию EEPROM. Опять же, вам нужно быть конкретным. Запись «переменных» данных во Flash далеко не идеальна.
@Клиффорд, извините - это похоже на один из тех вопросов, которые находятся между EE и переполнением стека. Я действительно ищу способ настроить энергонезависимую область памяти на моей флэш-памяти STM32, используя мою IDE (IDE-куб). Я думаю, что конкретные регионы адресов зависят от аппаратного обеспечения, но я не уверен, как правильно записать это в программу, кроме простого выбора неиспользуемого адреса и надежды на лучшее, как я сейчас.
Совет, не зависящий от микроконтроллера: размещение калибровочных данных на одной из последних страниц флэш-памяти может быть осуществимо, если вы каким-то образом можете гарантировать, что ваши образы обновления программного обеспечения никогда не будут достаточно большими, чтобы перезаписать эти страницы. У вас также должна быть резервная копия (или две) на отдельных флэш-страницах, целостность которых обеспечивается контрольными суммами или ECC. Если когда-либо произойдет переворот битов в какой-либо из этих калибровочных данных, вы либо захотите исправить ее, либо пометить ее как плохую (никогда ей нельзя доверять) и использовать одну из избыточных копий.
Что ж, если вам необходимо сделать это таким образом, очевидно, что выбор произвольного адреса неприемлем. Ответ заключается в том, чтобы зарезервировать пространство с помощью сценария компоновщика, либо пропустив его, либо явно создав именованный регион. Однако я говорю, что это вряд ли будет приемлемым решением. Все возможные методы обычно включают энергонезависимое хранилище, которое не отображается в памяти или не находится в обычной памяти, видимой компоновщику.
@AndyJ, учитывая, что флэш-страницы в конце флэш-памяти на STM32 состоят из больших частей размером до 128 КБ, это может быть непрактичным советом. Поскольку флэш-память, которую вы предлагаете, также является памятью кода, любая возможность «битового переворота» имеет гораздо более широкие последствия, чем просто эти данные - это не является практическим соображением. Более вероятный сценарий — сбой питания во время операции стирания или записи.
В любом случае, если вам нужен лучший совет, вам нужно конкретно указать MCU и плату, которую вы используете. На самом деле это проблема XY. Вы спрашиваете, как сделать что-то, что, вероятно, не является лучшим решением реальной проблемы, а именно: как хранить данные калибровки. Также было бы полезно понять, когда выполняется калибровка.
Очень простой процесс. Сначала в файле компоновщика (.ld) создается область памяти:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 24K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
CALIBRATION (rx) : ORIGIN = 0x0801FFE0, LENGTH = 8 /* new 8 byte section */
}
Затем в разделе разделов несколькими строками ниже я добавил:
.calibration (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.calibration))
. = ALIGN(4);
} >CALIBRATION
Ключевой частью является NOLOAD, который гарантирует, что значения внутри не инициализируются при запуске.
Затем в основной файл вам просто нужно добавить указатель и адрес для чтения и записи:
volatile uint32_t *calibration_value = (uint32_t *)0x0801FFE0; // create pointer at address
InitialCalib = *calibration_value; // use deferenced pointer to access data
Вам следует избегать магического числа в коде. Определите символ в скрипте компоновщика с помощью PRODIVE: sourceware.org/binutils/docs/ld/PROVIDE.html см. также: sourceware.org/binutils/docs/ld/REGION_005fALIAS.html
Обычно вы настраиваете это через специальный сегмент в своем скрипте компоновщика, а затем либо загружаете значения по умолчанию вместе с программой, либо иным образом устанавливаете для него значение «no init» и сохраняете предыдущие значения - которые будут записаны загрузчиком или аналогичным во время выполнения. . В идеале это должна быть EEPROM или флэш-память, чтобы вам не приходилось стирать большую ее часть каждый раз, когда вы обновляете значение. И чтобы не пришлось прибегать к злым ухищрениям вроде выполнения алгоритма прошивки из ОЗУ, потому что код во флеше не может выполняться, пока программа перепрограммируется.