Ra57 eeprom toyota чем читать

Работа с параметрами в EEPROM, как не износить память

Введение

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

А именно поговорим о том, как хранить параметры, которые необходимо писать в EEPROM постоянно.

Особенность таких параметров заключается в том, что их нельзя писать просто так в одно и то же место EEPROM, вы просто израсходуете все циклы записи EEPROM. Например, если, необходимо писать время работы один раз в 1 минуту, то нетрудно посчитать, что с EEPROM в 1 000 000 циклов записей, вы загубите его меньше чем за 2 года. А что такое 2 года, если обычное измерительное устройство имеет время поверки 3 и даже 5 лет.

Кроме того, не все EEPROM имеют 1 000 000 циклов записей, многие дешевые EEPROM все еще производятся по старым технологиям с количеством записей 100 000. А если учесть, что 1 000 000 циклов указывается только при идеальных условиях, а скажем при высоких температурах это число может снизиться вдвое, то ваша EEPROM способно оказаться самым ненадежным элементом уже в первый год работы устройства.

Поэтому давайте попробуем решить эту проблему, и сделать так, чтобы обращение к параметрам было столь же простым как в прошлой статье, но при этом EEPROM хватало бы на 30 лет, ну или на 100 (чисто теоретически).

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

Для начала проясню, для чего вообще нужно обращаться по отдельности к каждому параметру, этот момент был упущен в прошлой статье. Спасибо товарищам @Andy_Big и @HiSER за замечания.

Если использовать способ, который предложил пользователь @HiSER- это будет означать, что для перезаписи одного параметра размером в 1 byte, я должен буду переписать всю EEPROM. А если алгоритм контроля целостности подразумевает хранение копии параметров, то для 200 параметров со средней длиной в 4 байта, мне нужно будет переписать 1600 байт EEPROM, а если параметров 500, то и все 4000.

Малопотребляющие устройства или устройства, питающиеся от от токовой петли 4-20мА должны потреблять, ну скажем 3 мА, и при этом они должны иметь еще достаточно энергии для питания модема полевого интерфейса, графического индикатора, да еще и BLE в придачу. Запись в EEPROM очень энергозатратная операция. В таких устройствах писать нужно мало и быстро, чтобы средний ток потребления был не высоким.

Очевидно, что необходимо, сделать так, чтобы микроконтроллер ел как можно меньше. Самый простой способ, это уменьшить частоту тактирования, скажем до 500 КГц, или 1 Мгц (Сразу оговорюсь, в надежных применениях использование режима низкого потребления запрещено, поэтому микроконтроллер все время должен работать на одной частоте). На такой частоте, простая передача 4000 байт по SPI займет около 70 мс, прибавим к этому задержку на сохранение данных в страницу (в среднем 7мс на страницу), обратное вычитывание, и вообще обработку запроса микроконтроллером и получим около 3 секунд, на то, чтобы записать один параметр.

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

Как работать с EEPROM, чтобы не износить её

Те кто в курсе, можете пропустить этот раздел. Для остальных краткое, чисто мое дилетантское пояснение.

Как я уже сказал, число записей в EEPROM ограничено. Это число варьируется, и может быть 100 000, а может и 1 000 000. Так как же быть, если я хочу записать параметр 10 000 000 раз? И здесь мы должны понять, как внутри EEPROM устроен доступ к ячейкам памяти.

Итак, в общем случае вся EEPROM разделена на страницы. Страницы изолированы друг от друга. Страницы могут быть разного размера, для небольших EEPROM это, скажем, 16, 32 или 64 байта. Каждый раз когда вы записываете данные по какому-то адресу, EEPROM копирует все содержимое страницы, в которой находятся эти данные, во внутренний буфер. Затем меняет данные, которые вы передали в этом буфере и записывает весь буфер обратно. Т.е. по факту, если вы поменяли 1 байт в странице, вы переписываете всю страницу. Но из-за того, что страницы изолированы друг от друга остальные страницы не трогаются.

Таким образом, если вы записали 1 000 000 раз в одну страницу, вы можете перейти на другую страницу и записать туда еще 1 000 000 раз, потом в другую и так далее. Т.е. весь алгоритм сводится к тому, чтобы писать параметр не в одну страницу, а каждый раз сдвигаться в следующую страницу. Можно закольцевать эти действия и после 10 раз, снова писать в исходную страницу. Таким образом, вы просто отводите под параметр 10 страниц, вместо 1.

Анализ требований и дизайн

Все требования можно сформулировать следующим образом:

Пользователь должен задать параметры EEPROM и время обновления параметра

На этапе компиляции нужно посчитать количество необходимых страниц (записей), чтобы уложиться в необходимое время работы EEPROM. Для этого нужно знать:

Количество циклов перезаписи

Время обновления параметра

Время жизни устройства

Хотя конечно, можно было дать возможность пользователю самому задавать количество записей, но что-то я хочу, чтобы все считалось само на этапе компиляции.

Каждая наша переменная(параметр) должна иметь уникальный начальный адрес в EEPROM

Мы не хотим сами руками задавать адрес, он должен высчитываться на этапе компиляции

При каждой следующей записи, адрес параметра должен изменяться, так, чтобы данные не писались по одному и тому же адресу

Это также должно делаться автоматически, но уже в runtime, никаких дополнительных действий в пользовательском коде мы делать не хотим.

Мы не хотим постоянно лазить в EEPROM, когда пользователь хочет прочитать параметр

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

При инициализации мы должны найти самую последнюю запись, её считать и закешировать.

За целостность должен отвечать драйвер.

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

Ну кажется это все наши хотелки. Как и в прошлой статье давайте прикинем дизайн класса, который будет описывать такой параметр и удовлетворять нашим требованиям:

Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Посмотрим на то, как реализуются наши требования таким дизайном.

Пользователь должен задать параметры EEPROM и время обновления параметр

При каждой следующей записи, адрес параметра должен изменяться, так, чтобы данные не писались по одному и тому же адресу

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

По нему мы будет рассчитывать следующий адрес записи

Для того, чтобы после выключения/включения датчика найти последнюю запись, считать её и проинициализировать значением по адресу этой записи кеширумое значение в ОЗУ.

Давайте посмотрим как реализован метод расчета текущего адреса записи:

Мы не хотим постоянно лазить в EEPROM, когда пользователь хочет прочитать параметр

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

В общем-то и все класс готов, полный код класса:

Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Результат

Собственно все, теперь мы можем регистрировать в списке любые параметры:

Что произойдет в этом примере, когда мы будем писать 10,11,12. 15 в наш параметр. Каждый раз при записи, адрес параметра будет смещаться на размер параметра + размер индекса + размер копии параметра и индекса. Как только количество записей превысит максимальное количество, параметр начнет писаться с начального адреса.

На картинке снизу как раз видно, что число 15 с индексом 5 записалось с начального адреса, а 10 теперь нет вообще.

Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

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

Вот и все, надеюсь в этой статье цель получилось пояснить более детально, спасибо за то, что прочитали до конца.

Источник

Club-Subaru.Com

Украинский Субару Клуб

————————
Как выглядит блок внутри и где там микросхема памяти (картинка кликабельна)?
Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Как протестить прошитый блок? Пока не придумал. Но суть в том что датчики которые стоят на ланжеронах это не единственные датчики. Ещё есть на самом блоке. Вся система детектит скорость, ускорение и показания всех датчиков. И только если всё сходится к аварии то только в этом случае происходит бах. Поэтому открутить датчик и ё*нуть им об стену ни к чему не приведёт (хотя я не проверял Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать).

Для общего развития и памяти оставлю список блоков и их eeprom:
Код: Выделить всё Subaru 98221 AG180 152300-8270 93C57
98221 FE220 Denso 152300-84700 93C57
Forester 98221 SA011 Denso 152399-5181 93C56
98221 SC030 Denso 150300-0940 93C86
98221 SC041 Denso 93C86
Impreza 98221 FA101 Denso 152300-2150 93C46
98221 FA160 Denso 152300-2391 93C46
98221 FA171 Denso 152300-2402 93C46
98221 FE030 Denso 152300-3961 93C46
98221 FE100 Denso 152300-6130 93C56
98221 FE110 Denso 152300-6140 93C56
98221 FE190 Denso 152300-8440 93C56
98221 FG040 Denso 150300-0660 93C86
98221 FG070 Denso 150300-1460 93C86
Justy 89170-B1200 Denso 150300-1071 93C56
Legacy 98221 AG260 Denso 150300-0710 93C86
Outback 98221 AG250 150300-0700 93C56
Tribeca 98221 XA00A Denso 152300-8221 93C56

На просторах инета нашёл ряд дампов. Оставлю их в теме. Уверен что кому то поможет в будущем. Также приатачил внизу код проги ардуины для считывания eeprom и ссылки на даташиты.
[spoiler]
легаси:
Denso(S220)_152300-6631_(98221AG000)-OK.bin
Код: Выделить всё 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0005 000b 800b 800d 800f 8011 8016 800e
800b 820f 820e 820f 820d 820c 8209 b20a
b211 b213 b212 b20d b209 b210 b21b b218
b213 4c0c 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0200 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 ffff ffff ffff ffff ffff 0000
a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5

Denso(S220)_152300-6631_(98221AG000)-BAD.bin
Код: Выделить всё aa71 3134 3f0b 000e 0b00 aa71 3134 3f0b
000e 0b00 aa71 3134 3f0b 000e 0b00 005a
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0005 000b 800b 800d 800f 8011 8016 800e
800b 820f 820e 820f 820d 820c 8209 b20a
b211 b213 b212 b20d b209 b210 b21b b218
b213 4c0c 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0200 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 ffff ffff ffff ffff ffff 0000
a5a5 a5a5 a5a5 a5a5 a5a5 5a5a 5a5a 5a5a

Это дамп от wrx’04 стреляный блок:
152300-6130 Denso 98221FE100 (s220)
Код: Выделить всё 5baa 3431 1104 0b00 0000 5baa 3431 1104
0b00 0000 5baa 3431 1104 0b00 0000 5a00
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 ff00 ff00 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 ff00 ff00 ff00
ff00 ff00 0000 0100 0900 1680 1880 0880
0680 1280 0f80 0680 0480 0c80 0e80 10b2
0eb2 0ab6 0eb6 0fb6 0cb6 0fb6 19b6 27b6
32b7 0d2b 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0002 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 ffff ffff ffff ffff ffff ffff ffff
a5a5 a5a5 a5a5 a5a5 a5a5 5a5a 5a5a 5a5a

Ещё один стреляный
152300-6130 Denso 98221FE100 (s220)
Код: Выделить всё 5baa 3431 0b04 1100 0000 5baa 3431 0b04
1100 0000 5baa 3431 0b04 1100 0000 5a00
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0300
0200 0000 0180 0100 0000 0100 0300 0280
0280 0480 0580 0380 0480 0180 ff80 0180
0180 0200 0680 0780 0280 0480 0680 0380
0580 0780 0780 0880 0880 0680 0480 0380
0380 0480 0380 0380 0300 0300 0480 0580
0680 0480 0280 0180 0380 0780 1280 1680
0d80 0964 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0002 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 ffff ffff ffff ffff ffff ffff ffff
a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 5a5a

DENSO 152300-6130 BAD 93C56 128X16.bin
Код: Выделить всё 30aa 3134 040b 0000 0000 30aa 3134 040b
0000 0000 30aa 3134 040b 0000 0000 005a
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0001
0001 0001 0001 0001 0001 0001 0001 0001
0001 0001 0001 0001 0001 0001 0001 0001
0001 0001 0001 0001 0001 0001 0001 0002
0005 800d 8013 8014 800c 80f7 80f7 800d
8012 800b 800a 800c 8214 8213 8214 821f
931c 931a 971e 971d 971d 9721 971f 9610
970e d20e 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0200 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 ffff ffff ffff ffff ffff ffff ffff
a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5

98221AE160_93C56x16_crash.bin:
Код: Выделить всё 34aa 0b31 040e 0000 0000 34aa 0b31 040e
0000 0000 34aa 0b31 040e 0000 0000 ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0400 0507
0605 0103 0804 0607 0306 0503 0505 0706
0507 1300 0100 f103 ffff ffff ffff ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 ffff
005a 0200 ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
5a5a 5a5a 5a5a 5a5a a5a5 a5a5 a5a5 a5a5

Код arduino для чтения eeprom. Я коннектился внутрисхемно, питание брал с той же ардуины 3.3в. После включения в серийный порт (Мониторинг порта) последовательно выводится отформатированный текст дампа памяти циклически.
Код: Выделить всё //defining pins for eeprom
int CHIP_SEL =8;
int CLOCK =9;
int DATA_IN = 11;
int DATA_OUT =10;

for (int i=0;i = 32) <
Serial.print(«\n»);
charsCount = 0;
>

digitalWrite(CLOCK,HIGH);
digitalWrite(CLOCK,LOW);
delay(1);
>

Полезно для прочтения патчинг eeprom пробега:
http://www.drive2.ru/l/1568805/. Тут же объясняется как подключить чип к LPT или COM порту и работать с ним через PonyProg.

Подчеркну что пишу здесь всё для ознакомительных целей и ответсвенности связанной с предоставленной мною информацией не несу.

ps: неплохо было бы разрешить тег spoiler

Прошивка блока (98221 FE100 Denso 152300-6130) с памятью S220 с помощью arduino.
Написал простенькую прогу для программирования чипов памяти EEPROM по протоколу MicroWire.
Доступна на гитхабе https://github.com/sapzxc/airbag-fix

К сожалению дешман адаптеров под MicroWire протокол китайцы не продают (по крайне мере я не нашёл). В современных ноутах нет ни COM ни LPT. Переходник COM порта не катит, так как для чтения используются дополнительные пины, которых нет в usb-com адаптере, только в нативном COM порте. В моём случае быстрее и дешевле было использовать arduino который лежал уже дома.

Процесс очень простой:
Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать
Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Берётся ардуина Leonardo в моём случае и конектится напрямую к чипу. Подойдёт любая ардуина. Можно даже одолжить, так как в ардуино можно прошивать и стирать многократно программы.
Для удобства советую прикупить прищепку на 8 пинов для soic-8 корпусов. Я покупал на Aukro задорого, но на aliexpress будет гораздо дешевле но дольше.

В программе можно подправить опции и изменить размер банок и объём для чтения записи любой другой памяти по протоколу MicroWire. В начале есть настройки: eeprom_size, eeprom_bank_size, eeprom_address_width_bits.

Источник

Чистый eeprom

Добро пожаловать на ChipTuner Forum.

Опции темы

Leva2000

Бутко

VIKON

Leva2000 Выпаять и в прогроматоре понятно но как и в томже блоке. извините сам-же советовал но ищё можно прогроматором одометров ПО-3 ПО-4

Добавлено через 5 минут

Tom За себя..пытался коротить Флеш и пинцетом и паял почемуто безуспешно

Бутко

syxarik

Добавлено через 4 минуты

Добавлено через 5 минут

Leva2000 Выпаять и в прогроматоре понятно но как и в томже блоке. извините сам-же советовал но ищё можно прогроматором одометров ПО-3 ПО-4

Добавлено через 5 минут

Tom За себя..пытался коротить Флеш и пинцетом и паял почемуто безуспешно

интересно, а после соединения с эбу, перемычку резали чтоле. Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Добавлено через 20 минут

Пошел тренироваться на своем ЭБУ. Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Добавлено через 1 час 46 минут

Leva2000

VIKON

Родная прошивка самоуничтожиласьRa57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать, «не успел» Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читатьУстановил другую, авто уехало. Буду продолжать тренировки по снятию перемычки в нужный момент.

Спасибо за подсказки, советы. Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Leva2000

Leva2000, на будушее может пригодится.

Источник

Работа с EEPROM памятью

Ra57 eeprom toyota чем читать. Смотреть фото Ra57 eeprom toyota чем читать. Смотреть картинку Ra57 eeprom toyota чем читать. Картинка про Ra57 eeprom toyota чем читать. Фото Ra57 eeprom toyota чем читать

Вот и добрались мы до третьего типа памяти, доступного на Arduino: EEPROM (англ. Electrically Erasable Programmable Read-Only Memory – электрически стираемое перепрограммируемое постоянное запоминающее устройство (ЭСППЗУ)), она же энергонезависимая память. Вспомним остальные типы памяти, Flash и SRAM, и их возможности по хранению данных:

ТипЧтение из программыЗапись из программыОчистка при перезагрузке
FlashДа, PROGMEMМожно, но сложноНет
SRAMДаДаДа
EEPROMДаДаНет

Простыми словами: EEPROM – память, к которой мы имеем полный доступ из выполняющейся программы, т.е. можем во время выполнения читать и писать туда данные, и эти данные не сбрасываются при перезагрузке МК. Круто? Круто. Зачем?

Единственный важный момент: EEPROM имеет ресурс по количеству перезаписи ячеек. Производитель гарантирует 100 000 циклов записи каждой ячейки, по факту это количество зависит от конкретного чипа и температурных условий, независимые тесты показали 3-6 миллионов циклов перезаписи при комнатной температуре до появления первой ошибки, т.е. заявленные 100 000 взяты с очень большим запасом. Но есть небольшое уточнение – при заявленных 100 000 циклах перезаписи гарантируется сохранность записанных данных в течение 100 лет при температуре 24°C, если перезаписывать по миллиону – данные испортятся быстрее. В то же время количество чтений каждой ячейки неограниченно.

EEPROM представляет собой область памяти, состоящую из элементарных ячеек с размером в один байт (как SRAM). Объём EEPROM разный у разных моделей МК:

Основная задача при работе с EEPROM – не напутать с адресами, потому что каждый байт имеет свой адрес. Если вы пишете двухбайтные данные, то они займут два байта, и следующие данные нужно будет писать по адресу как минимум +2 к предыдущему, иначе они “перемешаются”. Рассмотрим пример хранения набора данных разного типа, расположенных в памяти последовательно друг за другом (в скобках я пишу размер текущего типа данных, на размер которого увеличится адрес для следующего “блока”):

Важный момент: все ячейки имеют значение по умолчанию (у нового чипа) 255.

Скорость работы с EEPROM (время не зависит от частоты системного клока):

Возможны искажения при записи данных в EEPROM при слишком низком VCC (напряжении питания), настоятельно рекомендуется использовать BOD или вручную мониторить напряжение перед записью.

При использовании внутреннего тактового генератора на 8 МГц, его отклонение не должно быть выше 10% (7.2-8.8 МГц), иначе запись в EEPROM или FLASH скорее всего будет производиться с ошибками. Соответственно все разгоны внутреннего клока недопустимы при записи EEPROM или FLASH.

Для работы с EEPROM в среде Arduino у нас есть целых две библиотеки, вторая является более удобной “оболочкой” для первой. Рассмотрим их обе, потому что в “чужом скетче” может встретиться всё что угодно, да и совместное использование этих двух библиотек делает работу с EEPROM невероятно удобной.

Библиотека avr/eeprom.h

Запись:

Обновление:

Макросы:

Рассмотрим простой пример, в котором происходит запись и чтение единичных типов данных в разные ячейки:

Точно так же можно хранить массивы:

В библиотеке avr/eeprom.h есть ещё один очень полезный инструмент – EEMEM, он позволяет сделать автоматическую адресацию данных путём создания указателей, значение которым присвоит компилятор. Рассмотрим пример, в котором запишем в EEPROM несколько переменных, структуру и массив, раздав им автоматически адреса. Важный момент! Адреса задаются снизу вверх по порядку объявления EEMEM, я подпишу их в примере:

EEMEM сам раздаёт адреса, основываясь на размере данных. Важный момент: данный подход не занимает дополнительного места в памяти, т.е. нумерация адресов вручную цифрами, без создания EEMEM “переменных”, не занимает меньше памяти! Давайте вернёмся к нашему первому примеру и перепишем его с EEMEM. При указании адреса через EEMEM нужно использовать оператор взятия адреса &

Ну и напоследок, запись и чтение блока через EEMEM. Адрес придётся преобразовать в (const void*) вручную:

Таким образом можно добавлять “данные” для хранения в EEPROM прямо по ходу разработки программы, не думая об адресах. Рекомендую добавлять новые данные над старыми, чтобы адресация не сбивалась (напомню, адресация идёт снизу вверх, начиная с нуля).

Библиотека EEPROM.h

Библиотека EEPROM.h идёт в комплекте с ядром Arduino и является стандартной библиотекой. По сути EEPROM.h – это удобная оболочка для avr/eeprom.h, чуть расширяющая её возможности и упрощающая использование. Важный момент: подключая в скетч EEPROM.h мы автоматически подключаем avr/eeprom.h и можем пользоваться её фишками, такими как EEMEM. Рассмотрим инструменты, которые нам предлагает библиотека:

В отличие от avr/eeprom.h у нас нет отдельных инструментов для работы с конкретными типами данных, отличными от byte, и сделать write/update/read для float/long/int мы не можем. Но зато у нас есть всеядный put/get, который очень удобно использовать! Также можем пользоваться тем, что нам даёт avr/eeprom.h, которая подключается автоматически с EEPROM.h. Рассмотрим пример с чтением/записью байтов:

Гораздо удобнее чем write_block и read_block, не правда ли? Put и get сами преобразовывают типы и сами считают размер блока данных, использовать их очень приятно. Они работают как с массивами, так и со структурами.

EEPROM.h + avr/eeprom.h

Ну и конечно же, можно использовать одновременно все преимущества обеих библиотек, например автоматическую адресацию EEMEM и put/get. Рассмотрим на предыдущем примере, вместо ручного задания адресов используем EEMEM, но величину придётся привести к целочисленному типу, сначала взяв от него адрес, т.е. (int)&адрес_еемем

С возможностями библиотек разобрались, перейдём к практике.

Реальный пример

Рассмотрим пример, в котором происходит следующее: две кнопки управляют яркостью светодиода, подключенного к ШИМ пину. Установленная яркость сохраняется в EEPROM, т.е. при перезапуске устройства будет включена яркость, установленная последний раз. Для опроса кнопок используется библиотека GyverButton. Для начала посмотрите на первоначальную программу, где установленная яркость не сохраняется. Программу можно чуть оптимизировать, но это не является целью данного урока.

Полезные трюки

Инициализация

Под инициализацией я имею в виду установку значений ячеек в EEPROM “по умолчанию” во время первого запуска устройства. В рассмотренном выше примере мы действовали в таком порядке:

При первом запуске кода (и при всех дальнейших, в которых в ячейку ничего нового не пишется) переменная получит значение, которое было в EEPROM по умолчанию. В большинстве случаев это значение не подойдёт устройству, например ячейка хранит номер режима, по задумке разработчика – от 0 до 5, а из EEPROM мы прочитаем 255. Непорядок! При первом запуске нужно инициализировать EEPROM так, чтобы устройство работало корректно, для этого нужно определить этот самый первый запуск. Можно сделать это вручную, прошив программу, которая забьёт EEPROM нужными данными. Далее прошить уже рабочую программу. При разработке программы это очень неудобно, ведь количество сохраняемых данных может меняться в процессе разработки, поэтому можно использовать следующий алгоритм:

Рассмотрим на всё том же примере со светодиодом и кнопками:

Сброс до “заводских”

Скорость

Как я писал выше, скорость работы с EEPROM составляет:

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

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

Получим удобные макросы, с которыми писать код будет чуть быстрее и удобнее, т.е. строка SET_MODE(3) запишет 3 в ячейку 0

Уменьшение износа

Важная тема: уменьшение износа ячеек частыми перезаписями. Ситуаций может быть много, интересных решений для них – тоже. Рассмотрим простейший пример – всё тот же код со светодиодом и кнопкой. Делать будем следующее: записывать новое значение будем только в том случае, если после последнего нажатия на кнопку прошло какое-то время. То есть нам понадобится таймер (воспользуемся таймером на millis), при нажатии на кнопку таймер будет сбрасываться, а при срабатывании таймера будем писать актуальное значение в EEPROM. Также понадобится флаг, который будет сигнализировать о записи и позволит записать именно один раз. Алгоритм такой:

Посмотрим на всё том же примере:

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

Видео

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *