2009-11-03 3 views
5

Мне нужно хранить предметы разной длины в круговой очереди в микросхеме флэш. Каждый элемент будет иметь свою инкапсуляцию, чтобы я мог понять, насколько он большой и где начинается следующий пункт. Когда в буфере есть достаточно предметов, оно будет перенесено в начало.Циркулярный буфер во Flash

Что такое хороший способ хранения круговой очереди в флеш-чипе?

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

Кроме того, поскольку он является круглым, мне нужно уметь отличать первый элемент от последнего.

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

+1

I «Я смущен вашим языком. Буфер, на мой взгляд, является быстрой, изменчивой частью памяти, которая часто меняется. Как вы правильно отметили, флэш-память может иметь некоторые проблемы с этим. Можете ли вы предоставить немного больше контекста или подробностей относительно того, что вы пытаетесь сделать и почему? – Mikeb

+0

Я хочу сохранить данные в энергонезависимой памяти. Энергонезависимая память, которая у меня есть, мигает. Энергонезависимость важна, потому что продукт может быть отключен в течение определенного периода времени, и я не хочу потерять данные. Когда питание снова включается, ему необходимо поместить следующий фрагмент данных после последнего. – Robert

ответ

9

Во-первых, управление блок:

Поместите меньший заголовок в начале каждого блока. Главное, что вам нужно отслеживать «самые старые» и «самые новые», это номер блока, который просто увеличивает модуль k. k должно быть больше вашего общего количества блоков. В идеале сделайте k меньше вашего значения MAX (например, 0xFFFF), чтобы вы могли легко узнать, что такое стертый блок.

При пуске, код считывает заголовки каждого блока в свою очередь, и размещает первый и последний кадры в последовательности, которая представляет собой н + 1 = (п я + 1) по модулю К. Старайтесь не путать стираемые блоки (номер блока - например, 0xFFFF) или данные, которые каким-то образом повреждены (например, неполное удаление).

В пределах каждого блока

Каждый блок сначала начинается пустым (каждый байт 0xFF). Каждая запись просто записывается один за другим. Если у вас есть записи фиксированного размера, вы можете получить к нему доступ простым индексом. Если у вас есть записи с переменным размером, то для его чтения вам нужно выполнить сканирование с начала стиля, связанного списка.

Если вы хотите иметь записи с переменным размером, но избегайте линейного сканирования, тогда у вас может быть четко определенный заголовок для каждой записи. Например. используйте 0 в качестве разделителя записей и COBS -encode (или COBS/R -encode) каждая запись. Или используйте байт по вашему выбору в качестве разделителя и «выбери» этот байт, если он встречается в каждой записи (аналогично PPP protocol).

При запуске, как только вы узнаете свой последний блок, вы можете выполнить линейное сканирование последней записи. Если у вас есть фиксированные записи или разделители записей, вы можете выполнить двоичный поиск.

планирования Erase

Для некоторых чипов флэш-памяти, стирание блока может занять значительное время - например. 5 секунд. Рассмотрите планирование удаления в качестве фоновой задачи немного «раньше времени». Например. когда текущий блок равен x%, затем начните стирание следующего блока.

Запись нумерации

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

Контрольная сумма или CRC

Если вы хотите, чтобы обнаружить поврежденные данные (например, неполная запись или стирание из-за неожиданный сбой питания), то вы можете добавить контрольную сумму или CRC для каждой записи, и, возможно, к блоку заголовок. Обратите внимание, что заголовок блока CRC будет охватывать только заголовок, а не записи, поскольку он не может быть переписан, когда записывается каждая новая запись.

+0

+1 для кодирования COBS. – starblue

1

Думаю, что я понял. Кажется, что ваша самая большая проблема будет, заполнив доступное пространство для записи, что будет дальше? Новые данные должны перезаписать самые старые данные, что я считаю тем, что вы подразумеваете под круговым буфером. Но поскольку данные не фиксированной длины, вы можете перезаписать более одной записи.

Я предполагаю, что величина изменчивости в длине достаточно высока, чтобы отложить все до фиксированной длины не вариант.

Ваш сегмент записи должен отслеживать адрес, который представляет начало записи следующей записи. Если вы знаете размер блока для записи досрочно, вы можете узнать, закончите ли вы в конце логического буфера и начнете с «0». Я бы не разделил запись с некоторыми в конце, а некоторые в начале.

Отдельный регистр может отслеживать начало; это самые старые данные, которые еще не были перезаписаны. Если вы зачитали данные, вы начнете.

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

По крайней мере, это, вероятно, то, что я буду делать. НТН

0

Я вижу три варианта:

ОПЦИЯ1: это блокнот все из того же размера, что это просто, хранить указатель на голову и хвост буфера, так что вы знаете, куда писать и куда начните чтение с, используйте размер каждого объекта, чтобы получить смещение к следующему, это означает, что вам нужно поперек буфера, как и связанный список, иначе его нужно, если вам нужен элемент 5000.

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

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

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

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

+4

Будьте осторожны с допуском выравнивания износа ... Истина, если у вас есть интерфейс USB или SD. Не так верно, если вы имеете дело со вспышкой напрямую. – Benoit

2

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

До тех пор пока вы не закончите пространство, добавление записей так же просто, как записать их в конец буфера и обновить указатель на хвост.

Как вам нужно освободить место, удалите достаточно записей, чтобы вы могли поместиться в вашу текущую запись. Обновляйте указатель головы при удалении записей.

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

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

+2

Блок, содержащий указатель на первую и последнюю запись, будет износиться быстрее, чем те, которые содержат записи, так как он должен обновляться каждый раз, когда записывается новая запись. Для некоторой флэш-памяти с низкими циклами записи это может произойти уже в 100 000-й записи. – mjh2007

0

«Круговой» во флэш-памяти можно сделать на основе размера блока, а это значит, что вы должны объявить, сколько блоков флэш-памяти вы выделяете для этого буфера.

Фактический размер буфера будет в каждый конкретный момент времени между n-1 (n - количество блоков) и n.

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

Каждый элемент инкапсулирован заголовком и нижним колонтитулом. заголовок по умолчанию содержит все, что вы хотите, но в соответствии с этим заголовком вы должны знать размер элемента. Нижний колонтитул по умолчанию: 0xFFFFFFFF. Это значение указывает на нулевое завершение.

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

Когда вы хотите сохранить новый элемент, вы проверяете, содержит ли последний блок достаточное пространство для этого элемента. Если вы сохраните элемент в конце предыдущего элемента и измените предыдущий нижний колонтитул, чтобы указать на этот элемент. Если он не содержит достаточно места, вам нужно удалить самый старый блок. Перед тем, как стереть этот блок, измените самые старые элементы блока (ОЗУ), чтобы указать на следующий блок, а самый старый элемент - на первый элемент этого блока. Затем вы можете сохранить новый элемент в этом блоке и изменить нижний колонтитул последнего элемента, чтобы указать этот элемент.

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

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

Смежные вопросы