Jump to content

    

Хранение данных на NOR flash (Кольцевой буфер)

4 часа назад, x893 сказал:

Всё это прекрасно, но что произойдет при плохом секторе ?

Что это такое "плохой"?

3 часа назад, pokk сказал:

Наоборот, 2-3 сектора за глаза хватает, по этому и удивлялся что перетираем сразу 60% информации которая отображается, но хотя если взять десяток секторов то это 60% будет "100 летней" давности.

На 2-х секторах алгоритм работать не будет. На 3-х - не знаю, надо смотреть. А зачем такая экономия при нынешних объёмах флеши?

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

 

Кроме того: я создавал этот алгоритм для хранения главным образом структуры конфигурации прибора; формат и размер которой со временем к новым версиям может измениться и заранее не известны. Этот алгоритм позволяет такое без проблем.

Share this post


Link to post
Share on other sites
On 3/20/2020 at 3:00 AM, jcxz said:

Кроме того: я создавал этот алгоритм для хранения главным образом структуры конфигурации прибора

А как у вас происходит перезапись, одного параметра в конфигурации ? Записью всей структуры данных(конфигурации) как новый блок данных?
Добавление аварии журнала аварий и лог хотел сделать "отложенной" операцией (установкой данных в очередь), с последующим считыванием из задачи на запись, а вот как быть с файлом конфигурации, он может быть достаточно большой что бы при каждом изменение его в очередь пихать (жалко мне 300-900 байт).  Хотя запись конфигурации можно сделать напрямую и не откладывать (естественно дождавшись), но тогда пользовательский интерфейс будет подтормаживать на момент записи (максимум 0.5с не заметно же ? )

Кстати разделение на несколько файлов как лучше сделать ?
Разбить всю FLASH на 3 области и в каждом, запустить свой кольцевой буфер или же все в одном с пометкой в блоке данных к какому файлу относился записанный блок данных ?

Edited by pokk

Share this post


Link to post
Share on other sites
4 часа назад, pokk сказал:

А как у вас происходит перезапись, одного параметра в конфигурации ? Записью всей структуры данных(конфигурации) как новый блок данных?

да

Цитата

Добавление аварии журнала аварий и лог хотел сделать "отложенной" операцией (установкой данных в очередь), с последующим считыванием из задачи на запись, а вот как быть с файлом конфигурации, он может быть достаточно большой что бы при каждом изменение его в очередь пихать (жалко мне 300-900 байт).

Жалко чего? Не понятно...

У меня объём конфига примерно такой-же. Объём флеша у меня 512 секторов по 256К каждый. Допустим выделим 16 секторов под кольцо с конфигом (16 секторов - ерунда ведь по сравнению со всем объёмом в 512 секторов?). 1e+5 - число циклов перезаписи. Считаем: 0x40000*16/900*100000=~466e+6 - столько циклов записи конфига выдержит кольцевой буфер флешки. У Вас реально может быть больше и боитесь что протрётся???  :shok:

Цитата

Хотя запись конфигурации можно сделать напрямую и не откладывать (естественно дождавшись), но тогда пользовательский интерфейс будет подтормаживать на момент записи (максимум 0.5с не заметно же ? )

Почему должен "подтормаживать"? Тоже непонятно...

Цитата

Кстати разделение на несколько файлов как лучше сделать ?
Разбить всю FLASH на 3 области и в каждом, запустить свой кольцевой буфер

Конечно так.

Цитата

или же все в одном с пометкой в блоке данных к какому файлу относился записанный блок данных ?

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

Share this post


Link to post
Share on other sites
11 hours ago, jcxz said:

Жалко чего? Не понятно...

Не flash а озу, для организации очереди, если всю конфигурацию передавать через очередь задаче которая будет записывать.
Если же передавать указатель на конфигурацию, то надо блокировать задачу из которой вызывается функция на запись, что бы данные в момент записи не менялись.
Соответственно от суда и "притормаживания" интерфейса, на время записи.

Кстати, как правильнее передавать данные разного размера в очередь (FreeRTOS)? (т.е одна задача принимает данные, а другие здачи передают не фиксированный размер данных, к примеру строки)
Адаптировать функцию под любой тип  через union ?
Или создать несколько очередей по свой тип данных и в них записывать, а в задаче на запись ожидать данные из любой очереди (как ?).

 

 

 

Share this post


Link to post
Share on other sites
12 часов назад, pokk сказал:

Не flash а озу, для организации очереди, если всю конфигурацию передавать через очередь задаче которая будет записывать.
Если же передавать указатель на конфигурацию, то надо блокировать задачу из которой вызывается функция на запись, что бы данные в момент записи не менялись.
Соответственно от суда и "притормаживания" интерфейса, на время записи.

Вы хотя-бы откройте мануал на ваш flash и посмотрите время записи страницы. А то имхо - печётесь о каких-то высосанных из пальца проблемах.

Например в моём чипе (S70FL01GS) время записи страницы == 340мкс. Т.е. на запись 900 байт потребуется 340мкс + время пересылки по SPI (десятки мкс). Вы реально сможете заметить такую задержку???

Зачем какие-то очереди для этого - тоже не понятно. Зачем усложнять?

Если всё-таки и задержка в сотни мкс критична - так можно придумать целую кучу способов чтобы не блокировать задачу юзер-интерфейса на время записи или стирания, например: делать это в отдельной задаче, или вообще в ISR. Стирать секторы в "дырке" кольца - для этого тоже не нужно блокировать никакую задачу: дал команду, а дальше в ISR периодически опрашивать регистр статуса на предмет завершения операции. И связывать с задачей пользовательского интерфейса это тоже не нужно. Зачем?

12 часов назад, pokk сказал:

а в задаче на запись ожидать данные из любой очереди (как ?).

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

Да ещё тысячу способов можно придумать - зависит от вашего алгоритма работы всей системы.

Share this post


Link to post
Share on other sites
11 hours ago, jcxz said:

Вы хотя-бы откройте мануал на ваш flash и посмотрите время записи страницы

Я ориентировался на самое большое время, это стирание страницы 80-200ms, когда происходит переход с одного сектора на другой, причем стирать надо 2 сектора для дырки и новый куда буду записываться данные, отсюда и задержка около 400 ms.

11 hours ago, jcxz said:

Если всё-таки и задержка в сотни мкс критична - так можно придумать целую кучу способов чтобы не блокировать задачу юзер-интерфейса на время записи или стирания

У меня задача юзер-интерфейса выглядит как в web странице, вводятся данные и нажимается кнопка сохранить, после чего формируется xml запрос с веденным данными и отправляется в процессор. В процессоре, вызывается  Callback функция соответственной кнопке web. Внутри функции происходит последовательное модификация конфигурация, запись, верификация(что данные корректно записаны), и возврат статуса записи в web(ответ на запрос) по которому отображается сообщение как произошла запись. В данном случае через 13 сохранений, сообщение об записи отобразиться  с задержкой( 400ms), вот это я и назвал "подтормаживание". Ну и задача  Callback блокируется на запись, что бы потом отправить подтверждение + зашита от модификации конфигурации, из другого  Callback.
Особо от этого ни куда не денешься(и буферы тут да не помогают) , по факту стирание странице будет быстрее, и надеюсь это будет не так заметно.

PS: а время стирания страници, случайно не зависит, количеста записанной информации в старнице? Пока писал функцию заметил что она выполняеться в 40ms  в 2 раза меньше чем указанно в даташите, но там у меня пару 10 байт записанно только было. 

Share this post


Link to post
Share on other sites
1 час назад, pokk сказал:

Я ориентировался на самое большое время, это стирание страницы 80-200ms, когда происходит переход с одного сектора на другой, причем стирать надо 2 сектора для дырки и новый куда буду записываться данные, отсюда и задержка около 400 ms.

Так зачем берёте такой алгоритм где нужно 2 стирать? Я же вам описывал свой - там всего один за раз нужно стирать.

 

Цитата

В данном случае через 13 сохранений, сообщение об записи отобразиться  с задержкой( 400ms), вот это я и назвал "подтормаживание".

И опять - зачем берёте такой алгоритм, где нужны 13 стираний???

Я Вас не понимаю: сами же выбираете МК, в с урезанной периферией, а потом думаете как это обойти костылями (хотя есть куча МК с нормальной периферией); выбираете алгоритм хранения в котором требуется 13 сохранений чего-то куда и 2 стирания сектора - и жалуетесь на это. Вы же сами такой выбрали! Или кто-то вас заставлял?  :unknw:

 

PS: Прям как в анекдоте: "Доктор, почему мне больно когда я так делаю?" "Пациент, так не делайте так и не будет больно".

Share this post


Link to post
Share on other sites
1 hour ago, jcxz said:

Я же вам описывал свой - там всего один за раз нужно стирать.

Упс мой косяк, сектор с дыркой хотел стерать, а не записывать. 

1 hour ago, jcxz said:

И опять - зачем берёте такой алгоритм, где нужны 13 стираний??? 

Откуда 13 стираний ??? Я описывал ситуацию что каждая 13 итерация сохраненя будет происходит в новый сектор  (размер сектор у меня 4096, размер конфигурации примерно 300 байт 4096/300=13)

Edited by pokk

Share this post


Link to post
Share on other sites
5 минут назад, pokk сказал:

Откуда 13 стираний ??? Я описывал ситуацию что каждая 13 итерация сохраненя будет происходит в новый сектор  (размер сектор у меня 4096, размер конфигурации примерно 300 байт 4096/300=13)

Опечатался. Хотел написать "сохранений". Если беспокоитесь о задержке каждые 13 записей страниц, то стирайте дополнительный сектор в дырке заранее, в фоне, например пока конфиг редактируется юзером. Или сразу после того как сохранили очередной конфиг и оказалось, что при следующем сохранении может потребоваться стирание. Мой алгоритм требует только чтобы дырка была >= 1 сектора, максимальный её размер ничем не ограничен (ну т.е. ограничен только минимальным требуемым размером записанной области).

Share this post


Link to post
Share on other sites

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

On 3/19/2020 at 1:32 PM, jcxz said:

Данные перед записью в КОХ, сперва дополняются CRC, обрамляются маркерами начала и конца блока данных (не равными 0), затем кодируются по протоколу COBS и пишутся во флешь закодированными COBS

Для чего используються маркер начала и конца блока данных? И как его макеры правильно добавлять что бы они не совпали а данными?
Если декодировать блок данных из COBS , то получаем сразу данные + CRC

Share this post


Link to post
Share on other sites

Я добавил для упрощения алгоритма кодирования/декодирования. Да - только маркер конца добавил, в начале - нет. Маркер - любое число не равное 0.

Может можно и обойтись, но 1 байт на фоне КБ данных роли не играет.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now