Можно ли использовать флэш-чип SPI с Arduino (Atmega328p)

Можно ли использовать микросхему флэш-памяти SPI с минимальным размером стираемого сектора 4 КБ с Atmega 328p (2 КБ внутренней памяти)?

Проблема, которую я вижу: для того, чтобы данные были записаны на флэш, страница должна быть стерта. Если вы хотите обновить данные внутри сектора, вам сначала нужно прочитать все страницы внутри сектора, сохранить их с чипа, стереть сектор и записать страницы по порядку с вашими изменениями.

Но сектор размером 4 КБ нельзя сохранить в ОЗУ объемом 2 КБ, так какие решения используют другие люди в этой ситуации? Потому что я видел, как в этой установке использовались Arduinos, но не мог определить, каково их решение.

(Arduino — просто пример маленького микроконтроллера в этом вопросе)

сохранить сектор в другом секторе, а не в ОЗУ (к тому же это безопаснее в случае потери питания), сохраняя только те данные, которые вам нужны

Julien 27.05.2019 11:12

Ну и сколько данных вам нужно? Во время стирания вам нужно хранить в ОЗУ ровно столько, сколько необходимо. Если вам действительно нужно хранить данные размером 4 КБ, вам, вероятно, следует выбрать другой тип памяти, такой как классическая EEPROM.

Lundin 27.05.2019 13:09
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
167
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете просто использовать схему с двойной избыточностью страниц. Данные два страниц размером 4 КБ организованы следующим образом:

 Page A           Page B
+------------+   +------------+
| Sequence A |   | Sequence B |
!~Sequence A |   !~Sequence B |
+------------+   +------------+
|            |   |            |
|            |   |            |
| Data A     |   |  Data B    |
|            |   |            |
|            |   |            |
|            |   |            |
|            |   |            |
|            |   |            |
|            |   |            |
|            |   |            |
+------------+   +------------+

Сначала вы пишете Data A и устанавливаете Sequence A в ноль обратное ~Sequence A. При запуске вы проверяете порядковый номер каждой страницы и устанавливаете страницу с самым высоким допустимым порядковым номером (действительным, когда sequence ^ ~sequnece == 0xff) как текущая прочитанная страница, а другую — как текущая страница записи.

Когда вы обновляете данные, вы стираете текущая страница записи, записываете область данные, затем устанавливаете порядковый номер равным порядковому номеру прочитанной страницы плюс 1 (по модулю 256) и устанавливаете его инверсию. Затем поменяйте местами текущие страницы чтения/записи. При обновлении вы можете копировать данные с одной страницы на другую, не буферизируя всю страницу, и изменять только ту часть, которую хотите изменить.

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

При выборе текущей активной страницы вам, конечно же, приходится иметь дело с переносом (то есть, когда порядковые номера равны 255 и ноль, ноль новее).

Эта схема подходит для данных, которые будут часто считываться и редко записываться. Характер и частота ваших циклов чтения/записи энергонезависимой памяти будут диктовать подходящий механизм, поскольку для последовательной регистрации или энергонезависимых счетчиков событий подходят разные решения.

Для придирчивости, если во время стирания/программирования произойдет отключение питания или сброс, производитель не дает никаких гарантий содержания данных. Строго говоря, это должно сопровождаться контрольной суммой CRC.

Lundin 27.05.2019 17:05

@Lundin: Моя ошибка, делая это из памяти моей собственной реализации много лет назад (все еще используется, но редко пересматривается) - добавлена ​​необходимая проверка порядкового номера (а не использование CRC). В противном случае, как вы говорите, существует небольшое окно риска при записи байта последовательности и большее окно риска при стирании страницы. CRC все еще может быть полезен, но на практике я нашел это решение надежным.

Clifford 27.05.2019 18:02

Немного непонятно, какой контент (размер) вы собираетесь писать и как часто.

Вы могли бы подумать о нескольких меньших блоках NV, которые намного меньше размера страницы. Каждый блок NV имеет некоторый заголовок блока, идентифицирующий блок (например, BlockID + Size). Затем вы можете обновить страницу, пока новый блок NV помещается на этой странице. Если нет, напишите это на следующей странице и скопируйте все последние другие блоки на новую страницу. Затем вы можете тем временем стереть и подготовить старую страницу для следующего обмена.

Другие вопросы по теме