Перезапись инициализированного значения переменной в локальную флеш-память коры руки m4 nrf52

Я хотел бы иметь переменную во флэш-памяти, которая сохранит значение, которое я хочу, после сброса. Я знаю, что такая переменная int test_data = 3 хранится в разделе .data флэш-памяти, а затем копируется в ОЗУ во время выполнения. Я хотел бы во время выполнения изменить значение, хранящееся во флэш-памяти, для переменной test_data, чтобы при следующей перезагрузке оно загружало другое инициализированное значение по умолчанию.

Я знаю, что можно записать во флэш-память ЦП во время выполнения, но я не знаю, как найти адрес test_variable во флэш-памяти. Можете подсказать в этом направлении?

Спасибо.


person user1934513    schedule 20.02.2018    source источник
comment
Вы должны указать, какое оборудование и библиотеки Вы используете.   -  person K. Koovalsky    schedule 20.02.2018
comment
Писать на флешку - мучение. Возможно, вам потребуется записать целый блок, и вам, возможно, придется сначала явно стереть его. Это операция, требующая осторожности и планирования :(   -  person Martin James    schedule 20.02.2018
comment
"скопировано в оперативную память во время выполнения" - не обязательно.   -  person Martin James    schedule 20.02.2018
comment
Под разделом .data флэш-памяти вы подразумеваете раздел .data исполняемого файла? (который вы составили). Если ответ да, то я думаю, что вопрос, который вы, вероятно, хотите задать, будет How to rewrite the contents of .data segment in an executable.   -  person Santosh A    schedule 20.02.2018
comment
... и вам может понадобиться тесная связь с вашим компоновщиком, чтобы определить специальный раздел для таких данных, чтобы они могли быть расположены в блоке для записи (не то, что совсем приятно:).   -  person Martin James    schedule 20.02.2018
comment
Этот вопрос задавали бесчисленное количество раз здесь, в SO. Эти ответы не помогли? (Я хочу сохранить некоторое значение во флэш-памяти, чтобы оно было там при следующей загрузке mcu)   -  person old_timer    schedule 21.02.2018
comment
Вот почему выбор микроконтроллера с флэш-памятью данных всегда является хорошей идеей.   -  person Lundin    schedule 21.02.2018


Ответы (1)


То, что вы предлагаете, вряд ли будет практичным. Флэш-память записывает слова, стирает блоки. Переписать одно слово невозможно; вам нужно скопировать весь блок стирания в ОЗУ, изменить значение в копии, стереть блок, а затем записать весь блок из измененной копии ОЗУ. Надеясь, что питание не отключится во время процесса.

Это может быть даже невозможно, если ваша оперативная память меньше размера стираемого блока. Более того, если SoC выполняет код из Flash, стирание блока, скорее всего, стирает исполняемый код.

Проверьте документацию по своей детали, но nRF52840 имеет относительно небольшие страницы по 4 КБ. Поэтому лучшим решением будет зарезервировать страницу для ваших данных конфигурации/инициализации и прочитать эти данные в вашем коде и назначить их соответствующим переменным при запуске, а не пытаться переписать сгенерированный компоновщиком код/данные. Еще лучше, чтобы защитить себя от сбоя питания, используйте две страницы с порядковым номером и подтверждением, которые вы пишете последними; затем при запуске используется страница с наибольшим допустимым порядковым номером. Когда вы изменяете данные, вы перезаписываете более старые данные — таким образом, если произойдет сбой до записи порядкового номера и проверки, вы не потеряете все свои данные. Если страница данных пуста, вы используете инициализацию, сгенерированную компоновщиком.

Это только схема того, что вам нужно сделать — уровень сложности зависит от вас.

Если ваше приложение имеет жесткие ограничения в реальном времени; вам может потребоваться проверить, что шина памяти не блокируется во время стирания/записи страницы - это может остановить выполнение кода, включая обработчики прерываний во время стирания/записи, и привести к пропуску сроков. Время стирания страницы составляет до 85 мс для nRF52840. Если это проблема, то вам лучше использовать внешнюю EEPROM.

person Clifford    schedule 20.02.2018
comment
Почти то же самое я бы написал, если бы мне не пришлось выгуливать нашу собаку :) Некоторые контроллеры прямо указывают, что все прерывания должны быть отключены перед попыткой стереть/записать страницу :( Я согласен, что маленькая EEPROM, может быть, SPI или I2C было бы более простым/безопасным решением. - person Martin James; 20.02.2018
comment
некоторые (/many/all) вспышки позволяют вам продолжать изменять слово, но только в одном направлении. например, если блок стирается до всех единиц, вы можете (иногда в зависимости) сделать некоторые из этих нулей, а затем вернуться позже и сделать больше из них нулями, но вы не можете снова сделать их единицами без стирания блока. серьезно сомневаюсь, что это помогает ОП. хотя... хммм... можно было бы разработать что-то, что работает для некоторого количества изменений. - person old_timer; 20.02.2018
comment
в конце дня, несмотря на то, что это стирание блока, выделите блок для этого одного параметра или вам придется выполнять чтение-изменение-запись всего блока. - person old_timer; 20.02.2018
comment
@old_timer: придерживайтесь многих, на устройствах STM32 вы не можете написать слово с одним или несколькими нулевыми битами (усвоил трудный путь!). Относительно целого блока по одному параметру; то, что я сделал, это использовать описанный двухблочный подход, но записать в него сериализованную ассоциативную карту ключа + типа для значения (содержащую целые числа, строки и двоичные блоки). Во время выполнения данные сериализуются в структуру данных, и вы получаете доступ к данным по ключу (в моем случае это строка имени). Именно это я имел в виду, когда сказал, что это всего лишь минимальная схема. - person Clifford; 20.02.2018
comment
@old_timer: Вы хотели добавить этот комментарий к моему ответу, а не к вопросу? Возможно, был задан вопрос X, решением которого является это, но это проблема X-Y — интересно, был ли задан именно этот вопрос Y — потому что это плохое и непрактичное решение X. - person Clifford; 20.02.2018
comment
Переписать одно слово невозможно; не верное утверждение. Я могу взять 0xFF, изменить его на 0xF3, затем изменить на 0xF0, затем изменить на 0x80 ... без стирания блока ... (для некоторых / многих вспышек) ... нужно еще немного слов ... - person old_timer; 20.02.2018
comment
@old_timer: Я понимаю вашу точку зрения, но, как я уже сказал, это не всегда верно (например, STM32) и, как вы сказали, не имеет практического применения для целей, описанных в вопросе. Я думаю, что оставлю это в силе - тогда это, по крайней мере, общеприменимо - ваш комментарий может послужить информацией для любого, кто хочет использовать такое поведение. Если мы рассматриваем переписывание слова как возможность установить все биты в любое состояние, это достаточно верно, - person Clifford; 20.02.2018
comment
Кроме того, часто невозможно выполнить код драйвера флэш-памяти, выполняющий стирание из того же банка, который стирается. Если вам не повезло, MCU не имеет нескольких флэш-банков. Тогда единственный вариант — запустить прошивальщик из оперативной памяти, что в большинстве приложений является довольно сомнительной практикой. А еще очень сложно сделать, когда драйвер уже написан на Си, а не на ассемблере. - person Lundin; 21.02.2018
comment
Время стирания страницы составляет 85 мс для nRF52840. Один из вариантов здесь — убедиться, что аппаратное обеспечение имеет достаточно большую резервную крышку на источнике питания, чтобы поддерживать питание MCU во время программирования. Обработка сегментов зеркальной вспышки в программном обеспечении болезненна. - person Lundin; 21.02.2018
comment
@Lundin: меня больше беспокоила вероятность того, что код, выполняемый из флэш-памяти, может быть остановлен на этот период, что приведет к пропущенным прерываниям, потере данных связи и сбоям в режиме реального времени. - person Clifford; 21.02.2018
comment
@Lundin: ... эта часть справочного руководства ЦП останавливается, если ЦП выполняет код из флэш-памяти, в то время как NVMC выполняет операцию стирания - аналогично для записи (хотя и намного короче). - person Clifford; 21.02.2018