Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Как вы храните настройки в энергонезависимой памяти?

Сб фев 23, 2013 13:07:57

Собственно задался вопросом - кто как организует хранение настроек в энергонезависимой памяти. Может почерпну для себя что-нибудь интересное.

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

По понятным причинам это не очень удобно, поэтому, в идеале, мне видится некое хранилище "ключ-значение", со значением произвольного типа и размера. Иначе говоря, мне должен быть предоставлен вот такой интерфейс:
Код:
settings_save(key, buffer, length);
settings_load(key, buffer, length);

Реализовать такое хранилище можно с помощью простецкой файловой системы, эдакой урезанной FAT. Однако, сразу же всплывают серьезные недостатки такого решения: даже при небольшом нарушении целостности файловой системы мы можем потерять все данные, либо их восстановление займет неоправданно много времени.

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

Re: Как вы храните настройки в энергонезависимой памяти?

Сб фев 23, 2013 13:57:01

Я в одном проектике хранил настройки в EEPROM в структуре.
Код:
//СТРУКТУРА ВОССТАНАВЛИВАЕМЫХ ИЗ EEPROM ДАННЫХ
struct {
    char FirstOnDevice;                            //байт для инициализации при первом включении устройства (при первом включении = 255)
                                                //при первом включении записывается "s"    
    char FlagsEE;                                //байт флагов
        #define bEERegEnbl        (1<<0)            /*флаг включения регистрации данных в EEPROM*/
        #define bEEAlrmOn        (1<<1)            /*флаг включения будильника*/

    char AlrmHour, AlrmMin;                        //данные настроек будильника

    char OneWireDevEnMask;                        //байт индикатор запрограммированных датчиков (0-7)
    char OneWireDevNum [64];                    //массив номеров устройств 1wire (8 устройств по 8 байт)

    char TermoUpLimitEnMask;                    //байт флагов включенных верхних лимитов
    int  TermoUpLimitData [8];                    //верхние пороги сигнализации температуры
    char TermoDnLimitEnMask;                    //байт флагов включенных нижних лимитов
    int  TermoDnLimitData [8];                    //нижние пороги сигнализации температуры
    unsigned char PeriodAlrm;                    //константа периода напоминания о сработавшем сенсоре (5 - 255 мин)

    int PeriodReg;                                //константа периода регистрации данных (1, 10, 60, 600, 3600 сек)    
    unsigned int FieldStrtPtr;                    //указатель на текущую позицию записи в поле данных
    unsigned int FieldEndPtr;                     //указатель на байт следующий за доступным полем данных

    char SensName [64];                            //имена температурных датчиков 8шт по 8 байтов
} StructEE; 


После старта, читаю структуру в RAM соответствующей функцией.
Код:
//ФУНКЦИЯ ЧТЕНИЯ СТРУКТУРЫ ИЗ EEPROM  
NOINLINE void StructEERead (void)
{
    IICMemReadData (&StructEE.FirstOnDevice, 0, sizeof (StructEE));//читаем структуру
} 
проверяю первый байт (ну или контрольную сумму) если не совпадает - инициализация настроек.


Если надо, редактирую настройки и сохраняю структуру.
Код:
//ФУНКЦИЯ ЗАПИСИ СТРУКТУРЫ В EEPROM  
NOINLINE void StructEEWrite (void)
{
    IICMemWriteData (&StructEE.FirstOnDevice, 0, sizeof (StructEE));//пишем структуру
}
 



Но это конечно если настроек не много, а вот если много то не знаю, еще не сталкивался с такими задачами.

P.S. В функциях чтения\сохранения (задавал адрес первого элемента структуры)
Код:
&StructEE.FirstOnDevice
наверное можно поменять на просто (адрес структуры)
Код:
StructEE



2P.S. Не так не получается, надо указывать именно адрес первого элемента структуры.

Re: Как вы храните настройки в энергонезависимой памяти?

Сб фев 23, 2013 15:19:45

Может чего не понял,а использовать переменные в eeprom,ну пускай компилятор сам думает по каким адресам их размещать.

Re: Как вы храните настройки в энергонезависимой памяти?

Сб фев 23, 2013 16:07:18

Vov123
Далеко не все компиляторы умеют размещать в eeprom переменные. Даже дело не в этом, а в том что мало какие МК имеют свой EEPROM.

menzoda
Самый простой и удобный способ сохранения - структура, ИМХО. Для надежности - повторить последовательно несколько раз. При чтении сверяем контр. суммы, допустимость параметров и загружаем правильную структуру.
Про FAT не совсем понял. FAT - для сохранения данных(файлов) заранее неопределенной длины. Настройки системы же имеют вполне определенный размер и тип данных.

Re: Как вы храните настройки в энергонезависимой памяти?

Сб фев 23, 2013 16:35:43

Насчет EEPROM. Я ничего не говорил о типе энергонезависимой памяти. Это может быть не только внутренняя EEPROM. Я например, сейчас работаю с внешней FRAM по SPI шине, так что компилятор сам ничего не сможет размещать.

Хранить все настройки в структуре - да, есть такой вариант, но как правильно заметили, если настроек много, то выходит очень накладно перезаписывать их все из-за изменения всего одного параметра. К тому же, если мы вдруг в новой версии захотим изменить тип какого-нибудь поля с int16 на float например, то все остальные поля "поедут", что не очень хорошо.
Еще, при таком подходе, если мы захотим использовать контрольную сумму, то она будет одна для всей структуры. Ошибка записи одного параметра приведет к несовпадению контрольной суммы, что равно потере всех параметров, что уже очень нехорошо.
Конечно можно не использовать контрольную сумму, а дублировать структуру в нескольких местах энергонезависимой памяти, но тогда накладные расходы при изменении одного параметра будут уж совсем дикие на мой взгляд.

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

Re: Как вы храните настройки в энергонезависимой памяти?

Сб фев 23, 2013 19:04:23

menzoda писал(а):но тогда накладные расходы при изменении одного параметра будут уж совсем дикие на мой взгляд.

Сколько тысяч раз в секунду пользователь желает изменять параметр чтоб начались тормоза системы? Или память на перфокартах организована? :)
В крайнем случае можно чтоб на экранчик вывалилось окошко, мол ждите сохранения изменений как в винде или телефоне это сделано.
menzoda писал(а):Конечно можно не использовать контрольную сумму, а дублировать структуру в нескольких местах энергонезависимой памяти
.
Как делаю я:
В память пишется 2-3 структуры, у каждой структуры своя КС. У первой структуры не совпадает КС, идем ко второй и т.д. Вдруг и у последней КС битая - тогда ой. Мигаем светодиодами, пищим бузером, на экранчике требуем нести девайс в сервис-центр. Не так уж и часто происходят ошибки записи и они в моем случае простительны. Не в космос девайс запускаем же.

menzoda писал(а):если настроек много, то выходит очень накладно перезаписывать их все из-за изменения всего одного параметра.

А что мешает вычислить адрес поля structure.parameterX ?

menzoda писал(а):но вылезают проблемы надежности, которые я не знаю как решить малой кровью.
А никак, только дублированием параметра. И то под вопросом. Если допустим поле length исказилось то вся система полетит. Получается дублировать FAT нужно, точнее резервный логический раздел создавать с известного фиксированного адреса.

Re: Как вы храните настройки в энергонезависимой памяти?

Сб фев 23, 2013 20:23:50

uk8amk писал(а):Сколько тысяч раз в секунду пользователь желает изменять параметр чтоб начались тормоза системы?

Медленный МК, медленная энергонезависимая память с ограниченным объемом, ограниченная оперативная память, параметр изменяется мастером по какому-нибудь MODBUS и вуаля! Мастер не дожидается ответа за установленный интервал. Неее. Такой подход на мой взгляд имеет больше всех недостатков. Уж лучше я вручную адреса для каждого параметра дефайнами определю и буду с ними по отдельности работать.

Кстати, а что если придется сохранять строки произвольной длины? От одного символа до нескольких десятков? Это еще один гвоздь в крышку гроба идеи объединить все параметры в одну структуру. А вот мини файловая система пригодилась бы как нельзя лучше, но соглашусь, что с файловой системой придется дублировать служебные данные. Сложно и очень медленно.
Ответить