Обработка данных для флеш-чипа

Я копирую отрывок из здесь

Циклы стирания флеш-памяти длинные - очень длинные - стирание сектора флеш-памяти может занять несколько секунд. Кроме того, поскольку количество гарантированных циклов стирания / перезаписи обычно ограничено (обычно около 10 000 или до 100 000), мы не можем позволить себе стереть весь сектор только потому, что изменилась одна переменная. Подход состоит в том, чтобы «пожертвовать» целым сектором для хранения переменных. В этом секторе переменные хранятся в таблице. Если переменная изменяется, она не перезаписывается, вместо этого старое значение отбрасывается и создается новая запись в таблице.

Я не понимаю приведенное выше утверждение.

Почему нам не нужно стирать сектор, когда мы добавляем данные, которые нужно изменить, как новый элемент данных вместо того, чтобы изменять существующие данные «на месте»? Это потому, что свободная область в секторе, где мы собираемся хранить новые данные, предварительно стерта с помощью 0x00 или 0xFF?

Если ответ на вышеупомянутый вопрос - «Да», можно ли избежать цикла стирания в указанном ниже случае?

Пишу системные логи на флешку. Как только область флеш-памяти будет полностью заполнена системными журналами, мне нужно стереть самую раннюю запись журнала и заменить ее самой новой. В этом случае я не могу придумать случая, когда я мог бы избежать стирания. Раньше с прошивальщиком не работал. Любая помощь будет оценена. Я не являюсь носителем английского языка и надеюсь, что вопрос не расплывчатый. Спасибо.


person NeonGlow    schedule 26.05.2016    source источник
comment
обычно, но не всегда, стирание устанавливает, что программное обеспечение считает битами данных за единицы. когда мы пишем, мы делаем некоторые из них нулями (или нестираемым состоянием). запись может идти только в одну сторону, например, нули, вы можете сделать больше нулей, но чтобы сделать их снова единицами, вам нужно выполнить цикл стирания блока. запись или стирание занимают много времени, не секунды, а много времени. все хорошо задокументировано для рассматриваемой вспышки.   -  person old_timer    schedule 26.05.2016


Ответы (1)


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

Проблема в том, что стирание большого флеш-сектора занимает много времени. Но как только весь сектор будет стерт (обычно все ячейки имеют значение 1), вы можете один раз выполнить запись в любую стертую ячейку памяти. В принципе, вы всегда можете превратить 1 в 0, но не из 0 в 1 без стирания. Так что вы действительно можете писать, потому что область уже стерта. Такая запись не занимает столько же времени, как стирание.

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

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

Address  Key   Value
0x0000   0x01  0xAA
0x0002   0x02  0xBB

У вас будет некоторая структура программы, например

typedef struct
{
  uint8_t key;
  uint8_t val;
} flash_var;

const flash_var* x = (flash_var*)0x0001;
const flash_var* y = (flash_var*)0x0002;

Затем вы хотите изменить значение x на 0xCC. Вы должны вызвать свой драйвер для программирования флеш-памяти, и он запишет копию новой переменной в следующее доступное место для флеш-памяти. Теперь ваша вспышка будет выглядеть так:

Address  Key   Value
0x0000   0x01  0xAA
0x0002   0x02  0xBB
0x0004   0x01  0xCC

Итак, у вас есть две копии переменной x, но программа обновит указатель, указав только на самое последнее его появление. Предыдущая просто сидит во флешке как "мертвое место". Вы всегда можете узнать, какой из них самый последний, выполнив поиск от конца блока flash назад к началу, ища первое вхождение ключа поиска 0x01.

Это означает, что при включении поиск переменных будет производиться не с произвольным доступом, а с довольно медленным линейным поиском.

У этого алгоритма есть несколько проблем:

  • Не произвольный доступ, а очень медленный поиск.
  • Множество дополнительных сложностей для реализации, что увеличивает вероятность ошибок и требует ресурсов.
  • Существуют дубликаты одних и тех же данных. Это неприемлемо для критически важных систем. Предположим, что ключ поиска поврежден - вместо того, чтобы ничего не находить и сообщать об ошибке, программа вместо этого берет старые данные.
  • В зависимости от характера вспышки вы можете захотеть включить во вспышку контрольную сумму. В приведенном выше алгоритме должна быть индивидуальная контрольная сумма для каждой переменной, что является огромной тратой места.
  • Когда сектор флеш-памяти заполняется, вы должны стереть его несмотря ни на что. Затем вам нужно будет придумать способ временного хранения переменных в ОЗУ. Получается сложно.
  • Но самое главное, сектор, вероятно, может быть заполнен в любой момент времени, и, вероятно, трудно предсказать, когда. Ваша программа должна уметь обрабатывать этот особый случай и справляться с длительным временем стирания, когда это происходит. Это наихудший случай, и встраиваемые системы реального времени всегда должны разрабатываться с учетом наихудшего сценария.

    И вот главный логический недостаток: если ваша программа может обрабатывать особый случай, когда сектор заполняется, и вам нужно стереть, то почему она не может обрабатывать один и тот же случай каждый раз? То есть, поскольку ваша программа в любом случае должна уметь справляться с этим, вы можете каждый раз стирать весь сектор.

    Получается, что алгоритм экономит время только в лучшем случае, что совершенно бесполезно, так как он должен быть написан так, чтобы он работал в худшем случае. А в худшем случае, для которого вы должны спроектировать, это вообще не экономит времени. Фактически, из-за дополнительной сложности, которую привнес в алгоритм, наихудший сценарий потребовал больше времени.

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

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

person Lundin    schedule 26.05.2016
comment
Я думал, что это обычный сценарий, и будут доступны общие решения. Но, к моему удивлению, найти правильные решения оказалось непросто. Информация, которую вы предоставили, была очень полезной. Большое спасибо за подробное объяснение. - person NeonGlow; 26.05.2016
comment
Вы, конечно, можете использовать двоичный поиск, но время запуска для линейного поиска типичного размера стираемого блока на самом деле не так уж и плохо. Кроме того, при желании вы можете уничтожить старые записи, перезаписав их до состояния записи всех битов, хотя может быть полезно оставить более одной действительной в качестве запасного варианта. - person Chris Stratton; 27.05.2016
comment
@ChrisStratton Нет, вы не можете выполнить двоичный поиск, потому что данные не будут отсортированы. Кроме того, я полагаю, вы могли бы выполнить двоичный поиск, чтобы найти, где заканчиваются действительные данные. Лучший алгоритм действительно будет зависеть от размера сегмента. - person Lundin; 29.05.2016
comment
Кажется, вы начали это понимать - вам нужно только найти конец, поэтому он доступен для двоичного поиска так же, как и любой другой вид поиска. - person Chris Stratton; 29.05.2016
comment
@ChrisStratton Но чтобы найти каждый тип сохраненных данных, вам нужно выполнить линейный поиск с конца ... в худшем случае вам придется выполнить линейный поиск по всему сегменту. На самом деле это еще одна причина того, почему этот алгоритм плох: если одни данные меняются реже, чем другие (что весьма вероятно), это замедлит поиск. - person Lundin; 30.05.2016