реклама на сайте
подробности

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Хранение указателя на конец данных в AT45xx DataFlash, Как лучше организовать?
Rst7
сообщение Jan 21 2008, 11:21
Сообщение #16


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



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


Вы видимо не совсем поняли идею. Запись организовывается примерно так

Код
WritePointer - номер записи
WriteSector - номер сектора для записи
WritePos - позиция в буфере
Nrec - количество записей помещающихся в буфер (SectorSize/sizeof(Record))
Record - собственно запись

WriteSector=WritePointer/Nrec;
WritePos=(WritePointer%Nrec)*sizeof(Record);
//Заполняем буфер
устанавливаем адрес записи в буфер, равный 0
i=0;
while(i!=WritePos) {SPDR=0xFF;i++;}
j=0;
while(j<sizeof(Record)) {SPDR=Record[j++];i++;}
while(i<PageSize) {SPDR=0xFF;i++;}
//Теперь буфер готов для записи страницы, но предварительно проверяем, а не нужно ли сначала очистить следующую
if (WritePos==(SectorSize-sizeof(Record))
{
ErasePage((WriteSector+1)%MaxSectors);
ErasePage((WriteSector+2)%MaxSectors);
}
WriteSectorWithoutErase(WriteSector);
WritePointer=(WritePointer+1)%(MaxSectors*Nrec);


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


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
alcosar
сообщение Jan 21 2008, 11:46
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 44
Регистрация: 30-03-06
Пользователь №: 15 598



Цитата(Rst7 @ Jan 21 2008, 15:21) *
Вы видимо не совсем поняли идею. Запись организовывается примерно так

Код
WritePointer - номер записи
WriteSector - номер сектора для записи
WritePos - позиция в буфере
Nrec - количество записей помещающихся в буфер (SectorSize/sizeof(Record))
Record - собственно запись

WriteSector=WritePointer/Nrec;
WritePos=(WritePointer%Nrec)*sizeof(Record);
//Заполняем буфер
устанавливаем адрес записи в буфер, равный 0
i=0;
while(i!=WritePos) {SPDR=0xFF;i++;}
j=0;
while(j<sizeof(Record)) {SPDR=Record[j++];i++;}
while(i<PageSize) {SPDR=0xFF;i++;}
//Теперь буфер готов для записи страницы, но предварительно проверяем, а не нужно ли сначала очистить следующую
if (WritePos==(SectorSize-sizeof(Record))
{
ErasePage((WriteSector+1)%MaxSectors);
ErasePage((WriteSector+2)%MaxSectors);
}
WriteSectorWithoutErase(WriteSector);
WritePointer=(WritePointer+1)%(MaxSectors*Nrec);


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


А что будет, если ErasePage из-за пропадания питания не выполнится и следующая страница не пустая?
ИМХО предложение AlexB более надежное. Кроме того, не нужно деление.

Сообщение отредактировал alcosar - Jan 21 2008, 11:48
Go to the top of the page
 
+Quote Post
Rst7
сообщение Jan 21 2008, 11:56
Сообщение #18


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
А что будет, если ErasePage из-за пропадания питания не выполнится и следующая страница не пустая?


Если вдруг из-за понижения питания не сработает ErasePage, то дальше дело не пойдет, процессор просто упадет в сброс от BOD'а. Тут конечно, надо процедуру PageErase делать правильную, с тестом, стаботало или нет. И, например, повторять, пока не очистится. Вообщем, такой алгоритм получается вполне транзакционный (если не учитывать то, что самые старые записи могут быть выброшены до записи новой, но это не беда, если это архив событий).

Цитата
Кроме того, не нужно деление.

Если все числа будут кратны 2, то деление и остаток будут преобразованы компилятором в сдвиги и and. Так что тут не волнуйтесь.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Baser
сообщение Jan 21 2008, 12:03
Сообщение #19


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(Alex B._ @ Jan 21 2008, 13:01) *
С индексом записи (который в каждой записи и хранится) таких проблем не будет. Когда бы не пропало питание вы всегда сможете найти начало и конец, даже если текущий буфер сектора будет потерян.
А алгоритм поиска прост - перебираете все записи, вычисляете CRC, контролируете индексы. Это же сделать надо один раз при включении питания, дальше указатели храняться в ОЗУ

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

Вопрос в придумывании наиболее простого и быстрого алгоритма.

Цитата(defunct @ Jan 21 2008, 13:20) *
Тем что можно писать в произвольные сектора.

Вашу мысль все равно не понял laughing.gif

Цитата(Rst7 @ Jan 21 2008, 11:31) *
У вас конец буфера маркируется пустым сектором из одних 0xFF. Т.е. реальная емкость буфера колеблется от (N-2)/sizeof(Record) до (N-1)/sizeof(Record) - как минимум, один сектор всегда пустой. Сравнивать конечно с буфером, заполненым 0xFF

+1
Вот до этого я уже сам додумался, этот алгоритм мне нравится больше всего.

------------
to All: А другие мысли есть?
В EEPROM никто эти указатели не сохраняет?
Go to the top of the page
 
+Quote Post
Rst7
сообщение Jan 21 2008, 12:16
Сообщение #20


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
В EEPROM никто эти указатели не сохраняет?


В другом приборе сохраняет указатели в EEPROM. Результат: при меньшем количестве произведенных приборов (ну раз в 10 ориентировочно) замечания чаще.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 21 2008, 12:37
Сообщение #21


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Baser @ Jan 21 2008, 15:03) *
Вашу мысль все равно не понял laughing.gif
...
Вопрос в придумывании наиболее простого и быстрого алгоритма.

При каждой записи во флеш увеличивать некий счетчик, записывать в кольцевой буфер внутренней eeprom младший байт этого счетчика (sequence записи), адрес флеш и crc8.
После рестарта - вычитать кольцевой буфер в ОЗУ, пробежаться по всем элементам, найти i-й элемент для которого справедливо условие
sequence[i] == sequence[i - 1] + 1;
sequence[i] != sequence[i + 1] - 1;
вытащить из этого элемента адрес флеш. Инициализировать счетчик числом "i + 1".

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

Для такого алгоритма есть ограничение на количество записей в кольцевом буфере - записей должно быть строго меньше 256.
Go to the top of the page
 
+Quote Post
GDI
сообщение Jan 21 2008, 13:08
Сообщение #22


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



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


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
Rst7
сообщение Jan 21 2008, 13:49
Сообщение #23


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
А я в свое время


Вот и у меня так было (только без указателя в EEPROM). В 2001 году. Потом переделал.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
DenisN
сообщение Jan 21 2008, 18:18
Сообщение #24


Участник
*

Группа: Участник
Сообщений: 36
Регистрация: 4-12-07
Пользователь №: 32 968



Цитата(Baser @ Jan 20 2008, 22:59) *
Это я прикинул. Почти крайний случай - запись страницы раз в минуту.
Год = 365*24*60=525600 минут. За 10 лет = 5.5 млн.записей / 10^5 (ресурс EEPROM)= 55 раз
Буфер из 64 указателей выдерживает такую нагрузку.
Только вот сразу проблемы с алгоритмом:
- Как менять ячейку (по какому алгоритму)
- Как запоминать её (указатель на указатель smile.gif ) Просто тупо искать среди них самый последний (по величине)??


Где-то был описан простой способ "размазывания" данных по EEPROM (для сохранения ее ресурса):

Предположим, нужно "размазать" 1 байт данных, имея массив из 100 байт в EEPROM. Для этого в программе организуем счетчик от 0 до 99, который инкрементируется при каждой записи. В ячейку EEPROM по адресу этого счетчика пишем такое значение, чтобы XOR всех 100 ячеек было равно запоминаемому числу. В итоге максимальное количество записей возрастает в 100 раз.

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

Для защиты от сбоев от выключения питания можно завести несколько таких массивов, например - четыре, и последовательно записывать в них одни и те же данные. При включении питания хотя бы два из них всегда будут одинаковы, и их нужно будет скопировать в оставшиеся.
Go to the top of the page
 
+Quote Post
Baser
сообщение Jan 21 2008, 20:32
Сообщение #25


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



to defunct: все понял, спасибо. Наконец-то до меня дошло, что вы говорите об алгоритме сохранения указателя в EEPROM smile.gif

to DenisN: интересный алгоритм


Все-таки склоняюсь к методу, предложенному Rst7. С EEPROM сложновато получается.
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 07:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.0139 секунд с 7
ELECTRONIX ©2004-2016