|
Хранилище "Key->Value" для EEPROM |
|
|
|
Jun 10 2015, 03:05
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
Цитата Самое простое - использовать в качестве ключа смещение данных в ЭППЗУ. +100500 Код typedef struct __eepRecord__ { unsigned char* Addr; // адрес объекта в EEPROM unsigned char* ram; // адрес объекта в оперативке unsigned int Size; // размер объекта } __attribute__ ((packed)) eepRecord;
eepRecord eepBase[100500];
readRecord(eepRecord * Rec) { eepRead(Rec->Addr,Rec->ram,Rec->Size); } writeRecord(eepRecord * Rec) { eepRead(Rec->ram,Rec->Addr,Rec->Size); }
Сообщение отредактировал alexeyv - Jun 10 2015, 03:08
|
|
|
|
|
Jun 10 2015, 04:41
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(RabidRabbit @ Jun 9 2015, 23:26)  Самое простое - использовать в качестве ключа смещение данных в ЭППЗУ. Цитата(alexeyv @ Jun 10 2015, 08:05)  +100500 Нет. Это не соответствует требованию "размер и количество которых заранее неизвестно". В качестве ключа я хочу выбирать число, которое как-то характеризует хранимые данные. Цитата(_Pasha @ Jun 10 2015, 08:42)  ТС, Вы ничего не сказали об интенсивности стираний элементов. Потому что если у Вас пойдет сильная фрагментация, то доступ к объектам нужно делать через двойные указатели. Да, фрагментация будет конечно. Я хочу чтобы эту проблему решала сама библиотека. Фактически, мне нужно от библиотеки что-то типа такого: Код #define CONFIG_KEY 1 #define DATA_KEY 2 #define SUPER_PUPER_KEY 0xFFFFFFFF ... save_into_eeprom(CONFIG_KEY, &config, sizeof(config)); save_into_eeprom(DATA_KEY, &data, sizeof(data)); save_into_eeprom(SUPER_PUPER_KEY, &super_puper_value, sizeof(super_puper_value)); ... load_from_eeprom(CONFIG_KEY, &config, sizeof(config)); load_from_eeprom(DATA_KEY, &data, sizeof(data)); load_from_eeprom(SUPER_PUPER_KEY, &super_puper_value, sizeof(super_puper_value)); ... erase_key(SUPER_PUPER_KEY); + желательно чтобы можно было перечислять ключи записей, которые хранятся на данный момент. Фактически, это должно быть что-то типа файловой системы, только в качестве имени файла выступает целое число.
--------------------
|
|
|
|
|
Jun 10 2015, 05:08
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(ArtDenis @ Jun 9 2015, 15:14)  Предполагается в EEPROM хранить (и при необходимости читать) разные наборы данных, размер и количество которых заранее неизвестно. На мой взгляд для этого подходит идеология хранилища Key->Value, где Key - это например целое число, по которому я идентифицирую сохраняемый набор, а Value - данные этого набора в бинарном виде. Есть ли готовые библиотеки для подобных хранилищ, для которых надо было бы дописать только чтение/запись EEPROM?
PS: размер EEPROM небольшой - всего 12 Кб. Размер сохраняемых наборов - от нескольких байт до килобайта. Так не делают. Это неудобно и негибко. Делают так: В паре Key=Value , Key - это строковый идентификатор, а Value - сериализированные данные, т.е. представленные тоже в виде строки. Если действительно структура данных сложная и неизвестная, то применяют формат JSON, а данные хранятся в древовидных структурах. Но файловую систему к этому не примешивают. Файловая система отдельно, а парсинг файлов отдельно. Для EEPROM очень простая файловая система есть у Keil, она включает и дефрагментацию и равномерный износ в ней учитывается.
|
|
|
|
|
Jun 10 2015, 05:15
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(AlexandrY @ Jun 10 2015, 10:08)  Так не делают. Это неудобно и негибко. Делают так: В паре Key=Value , Key - это строковый идентификатор, а Value - сериализированные данные, т.е. представленные тоже в виде строки. Я не совсем понял, почему хранить данные по ключу, который представляет из себя целое значение это - "неудобно и негибко", и почему их надо хранить по строковому ключу да ещё в строковом виде? Зачем расходовать лишний EEPROM?
--------------------
|
|
|
|
|
Jun 10 2015, 05:37
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(AlexandrY @ Jun 10 2015, 10:31)  Если интересует сжатие, то так прямо и спрашивайте. Какое ещё сжатие? Требования расписаны, пример того, что я хочу - есть. Сжатия среди требований нету. Откуда оно взялось?
--------------------
|
|
|
|
|
Jun 10 2015, 05:40
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390

|
на самом деле в key-value данные хранятся по хешу key, т.е. по целому, а не по строке, а ТС предлагает вместо хеш-функции использовать перечисление. Вообще непонятно зачем это в таком виде нужно, поскольку key-value используется для скоростной выборки данных, а тут всего 12кБ - т.е. можно просто последовательно перечитать весь носитель за миллисекунды. Хранить данные можно друг за другом, например в виде index, type, data, crc. Придумать случай, когда программа не знает размера структуры данных в eeprom затрудняюсь. А так - есть всякие bson, protobuf и т.п., но это в данном случае наверное тяжело будет.
|
|
|
|
|
Jun 10 2015, 05:42
|

Местный
  
Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040

|
Так и почитайте о файловых системах, решение к Вам и придёт  Например, разбиваете Вашу ЭППЗУ на блоки равного размера. Самый первый обзываете суперблоком и пишете туда размер одного блока, их количество, сколько свободных блоков осталось и ещё может что. Следом в одном или нескольких блоках размещаете битовую карту занятых блоков (бит сброшен - блок занят). Каждый блок состоит из номера следующего блока и данных. В следующем после битовой карты блоке размещается каталог, содержащий записи вида: номер первого блока/размер информации. Для добавления нового Value ищете первую свободную запись в каталоге, если нет, добавляете к каталогу ещё один блок. Далее находите столько номеров свободных блоков, сколько требуется для размещения Value, записывается информацию в эти блоки, располагая их цепочкой, вносите изменения в битовую карту и суперблок. Ключом будет являтся номер первого блока в цепочке. Для перечисления просматриваете каталог. Удаление Value также не представляет сложности.
|
|
|
|
|
Jun 10 2015, 05:55
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(psL @ Jun 10 2015, 10:40)  на самом деле в key-value данные хранятся по хешу key, т.е. по целому, а не по строке, а ТС предлагает вместо хеш-функции использовать перечисление. Вообще непонятно зачем это в таком виде нужно, поскольку key-value используется для скоростной выборки данных Скорость для меня не важна. И требования я такого не ставил. Для меня главное, чтобы работа с данными производилась через целочисленный ключ. А идеология "Ключ->Значение" приведена в качестве примера чего я хочу. Цитата(RabidRabbit @ Jun 10 2015, 10:42)  Так и почитайте о файловых системах, решение к Вам и придёт  Я ищу готовый вариант. Свой велосипед я всегда успею написать
--------------------
|
|
|
|
|
Jun 10 2015, 06:41
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(psL @ Jun 10 2015, 08:40)  Придумать случай, когда программа не знает размера структуры данных в eeprom затрудняюсь. Например, когда версий у программы больше одной, а настройки при апгрейде хочется сохранять. Поддерживать, скажем, три разных структуры настроек - геморрой с неожиданными багами. PS делали подобный велосипед (структура - прям по букварю); но там была флеш. При изменении настроек всё вычитывалось, перестраивалось и записывалось обратно; с фрагментацией бороться было не надо.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Jun 10 2015, 07:17
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(ArtDenis @ Jun 10 2015, 08:37)  Какое ещё сжатие? Требования расписаны, пример того, что я хочу - есть. Сжатия среди требований нету. Откуда оно взялось? Не, требования свои оставьте себе. А я пишу как делают, и что можно найти. Так вот когда нужно работать с настройками применяют три отдельные вещи: парсинг файлов, сжатие файлов и файловую систему. Пытаться уменьшить объем файла за счет применения цифр вместо строк это непрофессиональный стиль и никто так не лаж.... Хотя если найдете такое будет интересно. Скорее всего вам надо к ардуинщикам.
|
|
|
|
|
Jun 10 2015, 07:30
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(AlexandrY @ Jun 10 2015, 12:17)  Не, требования свои оставьте себе. Не-не, забираейте. Мне не жалко Цитата(AlexandrY @ Jun 10 2015, 12:17)  А я пишу как делают, и что можно найти. Так вот когда нужно работать с настройками применяют три отдельные вещи: парсинг файлов, сжатие файлов и файловую систему. Я нигде не говорил про работу с настройкам. Это ваши фантазии. Или меня с кем-то перепутали. Перечитайте первое сообщение в теме. PS: и можно конкретную ссылку на реализацию того, о чём вы говорили. Цитата(AlexandrY @ Jun 10 2015, 12:17)  Пытаться уменьшить объем файла за счет применения цифр вместо строк это непрофессиональный стиль и никто так не лаж.... Я не пытаюсь уменьшить объём. Это тоже ваши фантазии. На стиль мне плевать. Мне надо решить задачу, а не строить из себя профессионала Цитата(AlexandrY @ Jun 10 2015, 12:17)  Хотя если найдете такое будет интересно. Скорее всего вам надо к ардуинщикам. Буду рад конкретной ссылке как это реализовано у ардунинщиков.
Сообщение отредактировал ArtDenis - Jun 10 2015, 07:55
--------------------
|
|
|
|
|
Jun 10 2015, 08:41
|
Знающий
   
Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250

|
Чтобы пореже стирать EEPROM, мне как-то предлагали такой вариант: после резета сканируем содержимое EEPROM с инкрементом, равным размеру нашей структуры; как только натыкаемся на ноль, откатываем назад -- вот она, последняя! Для записи, соответственно, прыгаем в перед и пишем. Как только писать уже некуда, стираем страницу и начинаем писать с начала. Если после резета видим в самом начале нуль, то пользуем дефолтные настройки, т.к. EEPROM пуста.
Правда, я такую схему еще не реализовал. Но надо будет, особенно для STM32, у которых только флеш, а EEPROM'а нет.
|
|
|
|
|
Jun 10 2015, 09:55
|
Местный
  
Группа: Участник
Сообщений: 326
Регистрация: 30-05-06
Пользователь №: 17 602

|
Цитата(ArtDenis @ Jun 9 2015, 15:14)  Предполагается в EEPROM хранить (и при необходимости читать) разные наборы данных, размер и количество которых заранее неизвестно. Смотрите в сторону дескрипторов в USB
|
|
|
|
|
Jun 11 2015, 04:31
|
Знающий
   
Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250

|
Цитата(ArtDenis @ Jun 10 2015, 12:47)  Эдди, спасибо за идею! Хотя у меня есть подозрение, что она подходит только для записи структуры фиксированного размера. Пишете же вы! Как можно не знать, какой размер у данных будет? Если же действительно имя и содержимое выдумывает пользователь, то нечего морочить себе и людям голову! Подключайте флешку и пишите на ней либо полноценную ФС, либо БД вроде кастрированной sqlite. С другой стороны, здесь уже упоминали формат JSON — почему бы не использовать его для сериализации хранимых данных? Один только косяк — удалять ненужные данные будет крайне сложно и долго. Однако, и здесь можно выход найти: в отдельном блоке флеш или eeprom сохранять имена структур, нонче уже потерявших актуальность. Ну, а как писать уже некуда будет, все подчищать. Цитата PS: как это у STM32 нету EEPROM? Ещё как есть. Надо только правильную серию выбрать  EEPROM есть только в дорогущих lite-сериях. В дешевой попсе его нет, к сожалению.
|
|
|
|
|
Jun 11 2015, 04:37
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(Эдди @ Jun 11 2015, 09:31)  Пишете же вы! Как можно не знать, какой размер у данных будет? Я имею ввиду, что ваш способ подходит для записей большого количества структур одинакового размера. Или я ошибаюсь? Цитата(ar__systems @ Jun 10 2015, 15:17)  фрагментация не проблема - при каждом стирании все подгребаете к началу. Не совсем понятно что имеется ввиду под "все подгребаете к началу"
--------------------
|
|
|
|
|
Jun 13 2015, 05:02
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(ViKo @ Jun 11 2015, 10:09)  В начале EEPROM создать таблицу, в которой хранить номер-идентификатор (если он нужен), смещение в памяти (чтобы не складывать все размеры при поиске), размер записи. Дальше размещать сами записи. При стирании перемещать записи на свободное место, корректировать номер и смещение. Таблица не нужна. Создаём обычный журнал: длина записи - переменная, имеется фикс. заголовок, после которого - пользовательские данные переменной длины указанной в заголовке; в заголовке также указан ID записи (а также CRC и т.п. по желанию). В заголовке есть флажок валидности записи (1 бит). Новые записи добавляются в конец журнала. Для чтения записи с конца журнала ищется первый попавшийся ID равный нужному. При добавлении записи с ID, который уже есть в журнале, в заголовке старой записи снимается флажок валидности (set 0). В новой записи флаг валидности set 1 (если стёртое состояние флешь == 1). При налезании текущего хвоста журнала на его голову, анализируем какие записи в затирамеой части остались валидны, их перезаписываем в хвост. Такой алгоритм можно использовать и на флешь (где доступ по стиранию поблочный, а не байтовый). Чем больше объём использумой под журнал флешь - тем лучше - меньше износ. Для ускорения поиска в ОЗУ можно хранить таблицу соответствия номеров записей журнала определённым ID. Создавать её при старте ПО, обновлять при добавлении записей в журнал.
|
|
|
|
|
Jun 14 2015, 05:39
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(jcxz @ Jun 13 2015, 11:02)  Таблица не нужна. Создаём обычный журнал: длина записи - переменная, имеется фикс. заголовок, после которого - пользовательские данные переменной длины указанной в заголовке; в заголовке также указан ID записи (а также CRC и т.п. по желанию). В заголовке есть флажок валидности записи (1 бит). Новые записи добавляются в конец журнала. Для чтения записи с конца журнала ищется первый попавшийся ID равный нужному. При добавлении записи с ID, который уже есть в журнале, в заголовке старой записи снимается флажок валидности (set 0). В новой записи флаг валидности set 1 (если стёртое состояние флешь == 1). При налезании текущего хвоста журнала на его голову, анализируем какие записи в затирамеой части остались валидны, их перезаписываем в хвост.
Такой алгоритм можно использовать и на флешь (где доступ по стиранию поблочный, а не байтовый). Чем больше объём использумой под журнал флешь - тем лучше - меньше износ. Для ускорения поиска в ОЗУ можно хранить таблицу соответствия номеров записей журнала определённым ID. Создавать её при старте ПО, обновлять при добавлении записей в журнал. а адресс заголовка где храниться? а понял. то есть если я хочу найти 10-ю запись я должен просуммировать 9 размеров + офсет? нет что то не вяжется. вобщем как ни крути а надо создавать что то вроде а ля фат.
Сообщение отредактировал Jenya7 - Jun 14 2015, 05:52
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|