Защита памяти eeprom

PIC Урок 11. Внутренняя энергонезависимая память EEPROM. Часть 1

Очень многие знают, что в контроллерах PIC помимо основной оперативной памяти, а также памяти для хранения прошивки существует ещё и энергонезависимая память типа EEPROM.

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

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

Работать мы также будем с контроллером PIC16F877A, расположенном на удобной отладочной плате. Судя по технической документации на данный микроконтроллер, памяти EEPROM у него 256 байт. Этого вроде бы по нынешним меркам не так много, но вполне достаточно, чтобы хранить какую-то информацию, которая должна у нас остаться после отключения питания.

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

Существуют два регистра для записи и чтения памяти EEPROM. Это регистр, в котором хранятся данные, – EEDATA, а также регистр, в который мы посылаем адрес перед записью или чтения определённого байта, – EEADR. Также существует регистр управления EECON1, в котором находятся определённые биты настройки работы с памятью EEPROM, а также есть нефизический регистр EECON2, который мы используем для защиты от случайной записи данной памяти.

Также с помощью определённых конфигурационных битов мы можем защитить память EEPROM от стирания и перезаписи программатором.

Теперь немного подробнее про регистр управления EECON1

Теперь о назначении определённых битов данного регистра.

EEPGD – бит доступа к памяти (относится к памяти Flash)

1 – доступ к памяти для программы,

– доступ к памяти для данных.

WRERR (EEPROM Error Flag bit) — флаг ошибки записи данных в память EEPROM

1 – операция записи данных прервана (случился сброс либо по сигналу MCLR, либо по переполнению WDT в нормальном режиме),

– операция записи данных завершена.

WREN (EEPROM Write Enable bit) – бит разрешения записи данных в память EEPROM

1 – запись данных разрешена,

– запись данных запрещена.

WR (Write Control bit) – включение (инициализация) записи данных в память EEPROM

1 – инициализация цикла записи памяти EEPROM. Включается программно,

– цикл записи EEPROM закончен. Установка в 0 (сброс) осуществляется только аппаратным путём. Программно данный флаг сбросить невозможно.

RD (Read Control bit) – включение (инициализация) чтение данных из памяти EEPROM.

1 – инициализация цикла чтения памяти EEPROM. Включается программно,

– цикл чтения EEPROM закончен. Установка в 0 (сброс) осуществляется только аппаратным путём. Программно данный флаг сбросить также невозможно.

Чтение байта из памяти EEPROM производится следующим образом.

Первым делом мы должны удостовериться, что биты RD и WR регистра EECON1 у нас сброшены, то есть у нас в данный момент все циклы записи/чтения памяти EEPROM завершены. Затем мы записываем в регистр EEADR адрес считываемого байта, затем устанавливаем в 1 бит RD регистра EECON1 и считываем значение регистра EEDATA.

А вот запись байта в память EEPROM в целях безопасности происходит несколько посложнее.

Сначала мы также убеждаемся в сброшенном бите WR, затем разрешаем запись с помощью установки бита WREN регистра EECON1. Затем желательно запретить прерывания с помощью сброса бита GIE регистра INTCON, перед этим сохранив его значение, а то вдруг он уже был сброшен. А вот теперь мы делаем интересную вещь. Мы последовательно передаём байты 0x55 и 0xAA в регистр ЕЕСОN2. И только после этого мы пишем данные в память EEPROM, устанавливая бит инициализации записи WR. Затем мы возвращаем значение бита GIE в регистр INTCON, разрешив тем самым глобальные прерывания, если они до этого были разрешены. Потом мы сбрасываем бит WREN.

Чтобы нам теперь данную теорию понять и закрепить, мы должны отработать это на практике.

Поэтому создадим проект с именем EEPROM_LCD на основе проекта прошлого занятия LCD2004_8BIT.

Подключим нашу схему вместе с программатором и дисплеем, блок питания пока в целях безопасности не подключаем.

Откроем данный проект в MPLAB X, зайдём в его настройки и убедимся, что у нас схема не будет питаться от программатора и сохраним настройки проекта.

Теперь мы можем смело подключить блок питания, также попытаться собрать наш проект и прошить его в контроллер. Работоспособность нашего кода мы поймём по появившимся строкам на дисплее

Создадим каркас нашей будущей библиотеки для работы с памятью EEPROM с помощью двух файлов EEPROM.h и EEPROM.c следующего стандартного содержания

EEPROM.h:

#ifndef _EEPROM_H_H

#define _EEPROM_H_H

#include // include processor files — each processor file is guarded.

#endif /* _EEPROM_H */

EEPROM.c:

#include «EEPROM.h»

Также нашу библиотеку, а заодно и строковую, подключим в файле main.h

#include «EEPROM.h»

#include

Вернёмся в файл EEPROM.c и напишем функцию записи байта в память EEPROM по определённому адресу, руководствуясь объяснению, как это делается, написанному выше. Заодно сразу добавим и функцию чтения байта по определённому адресу

void EEPROM_WriteByte ( unsigned char addr, unsigned char dt)

unsigned char status;

while (WR);

EEADR = addr;

EEDATA = dt;

WREN= 1 ;

status = GIE;

GIE = 0 ;

EECON2 = 0x55 ;

EECON2 = 0xAA ;

WR= 1 ;

GIE = status;

WREN= 0 ;

unsigned char EEPROM_ReadByte( unsigned char addr)

while (RD || WR);

EEADR=addr;

RD = 1 ;

return EEDATA;

Также нам будет интересно писать и читать данные других типов.

Добавим функции записи и чтения двухбайтовой целочисленной беззнаковой величины в память EEPROM и из неё

void EEPROM_WriteWord( unsigned char addr, unsigned int ucData)

EEPROM_WriteByte(addr, ( unsigned char ) ucData);

unsigned char dt = ucData>> 8 ;

EEPROM_WriteByte(addr +1 , dt);

unsigned int EEPROM_ReadWord( unsigned char addr)

unsigned int dt = EEPROM_ReadByte(addr +1 )* 256 ;

dt += EEPROM_ReadByte(addr);

return dt;

Здесь у нас всё ещё проще. Мы читаем и пишем раздельно старший и младший байты, пользуясь уже добавленными функциями чтения и записи байтов.

Теперь добавим ещё функции записи и чтения четырёхбайтовых величин (двойных слов)

void EEPROM_WriteDword( unsigned char addr, unsigned long ucData)

EEPROM_WriteWord(addr, ( unsigned int ) ucData);

unsigned int dt = ucData>> 16 ;

EEPROM_WriteWord(addr +2 , dt);

unsigned long EEPROM_ReadDword( unsigned char addr)

unsigned long dt = EEPROM_ReadWord(addr +2 )* 65536 ;

dt += EEPROM_ReadWord(addr);

return dt;

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

Теперь давайте запишем строку символов по определённому адресу

void EEPROM_WriteString( unsigned char addr, char * str1)

unsigned char n;

for (n= 0 ;str1[n]!= ‘’ ;n++)

EEPROM_WriteByte(addr+n,str1[n]);

Здесь также всё элементарно. Мы, инкрементируя адрес, постепенно записываем наши байты. И так до встречи с нулём.

Функцию чтения строки по определённому адресу нас написать также не затруднит

void EEPROM_ReadString( unsigned char addr, char * str1, unsigned char sz)

unsigned char i;

for (i= 0 ;i

str1[i] = 0 ;

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

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

Перейдём в файл EEPROM.h и добавим прототипы наших функций

void EEPROM_WriteByte( unsigned char addr, unsigned char dt);

unsigned char EEPROM_ReadByte( unsigned char addr);

void EEPROM_WriteWord( unsigned char addr, unsigned int ucData);

unsigned int EEPROM_ReadWord( unsigned char addr);

void EEPROM_WriteDword( unsigned char addr, unsigned long ucData);

unsigned long EEPROM_ReadDword( unsigned char addr);

void EEPROM_WriteString( unsigned char addr, char * str1);

void EEPROM_ReadString( unsigned char addr, char * str1, unsigned char sz);

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

Купить программатор (неоригинальный) можно здесь: PICKit3

Купить программатор (оригинальный) можно здесь: PICKit3 original

Отладочную плату PIC Open18F4520-16F877A можно приобрести здесь: PIC Open18F4520-16F877A

Дисплей LCD 20×4 можно приобрести тут: Дисплей LCD 20×4

Смотреть ВИДЕОУРОК (нажмите на картинку)

Введение

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

Повреждение EEPROM при пониженном напряжении питания

Одна из старых проблем AVR — это повреждение EEPROM данных при пониженном питании микроконтроллера. Это может происходить в двух случаях:

— Если напряжение питания ниже определенной величины, запись в EEPROM будет выполняться некорректно.
— При пониженном напряжении питания микроконтроллер сам может выполнять команды некорректно.

Этих повреждений EEPROM данных можно избежать, соблюдая следующие рекомендации:

— Нужно удерживать микроконтроллер AVR в состоянии сброса, если напряжение питания находится ниже нормы. Для этого можно использовать внешние супервизоры питания или встроенный детектор пониженного питания — Brown-out Detector (BOD). Встроенный детектор управляется с помощью fuse битов микроконтроллера — BODEN и BODLEVEL. BODEN — разрешает/запрещает работу детектора, а BODLEVEL — определяет его уровень срабатывания.
Если сброс микроконтроллера происходит во время процесса записи в EEPROM, то операция записи будет завершена только при достаточном уровне напряжения.

— Также в многие разработчике рекомендуют не использовать 0-ую ячейку EEPROM`a, поскольку именно ее содержимое чаще всего повреждается при снижении питания микроконтроллера.

Проблемы с EEPROM из-за прерываний

Операция записи в EEPROM состоит из нескольких шагов. Вспомним эту последовательность:

1. Ожидаем готовности EEPROM, опрашивая бит EEWE регистра EECR.
2. Устанавливаем адрес в регистре EEAR.
3. Записываем байт данных в регистр EEDR.
4. Устанавливаем основной флаг разрешения записи EEMWE регистра EECE
5. Устанавливаем флаг разрешения записи EEWE регистра EECE

Бит EEWE должен быть установлен в течении 4-ех тактов после установки бита EEMWE. Если этого не произойдет по причине прерываний, то запись в EEPROM не будет произведена. Этого легко избежать, если запретить прерывания перед 4-м шагом, а после 5-го снова разрешить их.

Однако есть еще один подводный камень. Если прерывание возникло после 1-го, 2-го или 3-го шага, и в прерывании тоже используются операции с EEPROM (чтение или запись), то запись может не состояться, или запишутся не те данные и не туда, потому что содержимое регистров EEAR (адрес) и EEDR (данные) будет изменено.

Описанное выше касается и процедуры чтения EEPROM.

Лечить это можно следующими способами:

Не использовать операции чтения и записи EEPROM в прерываниях.
Это особенно касается операции записи, потому что она медленная и выполняется с использованием внутреннего RC генератора. Например, для mega16 в даташите указано, что при записи в EEPROM используется внутренний RC генератор с частотой 1 МГц (независимо от установок fuse битов CKSEL) и время записи составляет 8.5 мс. Для прерывания это очень долго.

Читайте также  Включение-отключение акустики синхронно с компьютером

— Запрещать прерывания на время всей процедуры записи (чтения) EEPROM, то есть в самом начале.

— Сохранять в начале обработчика прерывания содержимое регистров EEAR (адрес) и EEDR (данные), а перед выходом восстанавливать их.

— Использовать флаги (семафоры) для сигнализации о выполнении работы с EEPROM.
Перед выполнением записи в основном цикле программы (или задаче, если используется ос) устанавливать программный флаг, а в прерывании (или другой задаче) проверять его.

Ресурс EEPROM

EEPROM имеет ограниченный ресурс. Atmel гарантирует, что количество циклов перезаписи EEPROM составляет не меньше 100000. Цифра довольно большая, однако и она может быть достигнута, если записывать в EEPROM часто и на протяжении долгого времени.
Есть два приема по «увеличению» ресурса EEPROM.
Первый — простой и состоит в том, чтобы записывать в EEPROM данные, только если они изменили свое значение.

Второй- хитрый и состоит в том, чтобы хранить данные не в одной ячейки памяти (или группе ячеек, если речь идет о многобайтных переменных), а в нескольких, и записывать в них по очереди.
Допустим, нам нужно хранить в EEPROM один байт. Выделяем под него 8 байтов и каждый раз записываем в следующую ячейку, когда доходим до последней ячейки, то записываем в первую. И так по кругу, как в кольцевом буфере. Если каждая ячейка EEPROM имеет ресурс 100000, то записывая в 8 ячеек по очереди, мы получаем ресурс перезаписи байта 800000.

EEPROM и оптимизация компилятора

Переменные, которые объявлены, но не используются, часто удаляются компилятором в процессе оптимизации. Если такие переменные нужны, перед ними следует добавлять ключевое слово volatile.

Если используются свои функции для работы с EEPROM, то могут возникнуть проблемы при высоких уровнях оптимизации компилятора. Компилятор может объединить одинаковые (с его точки зрения) части кода в одну подпрограмму и нарушить логику работы вашей функции. Чтобы этого не происходило нужно или запрещать оптимизацию данной функции, или отключать перекрестную оптимизацию (cross call optimization) для функции или файла. Как это делается зависит от компилятора. Как правило, для этого существуют определенные ключи и прагмы.

Программные способы повышения надежности EEPROM

Один из простых способов повышения надежности хранения данных в EEPROM — это метод мажоритарного резервирования. Суть метода заключается в том, что для хранения данных выделяется нечетное количество ячеек памяти — N. При сохранении данных — запись производится во все выделенные ячейки. При чтении — читаются тоже все, но решение относительно содержимого принимается на основе равенства (N+1)/2 ячеек.

Рассмотрим пример тройного мажоритарного резервирования байта данных. Для сохранения байта используются три байта EEPROM, а решение о содержимом принимается на основании равенства 2 байтов. Код приведен для компилятора IAR AVR.

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

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

На этом все.

Решено ЕПРОМ 27Сххх серии защита от копирования

qwert2

  • 9 Окт 2008

Информация Неисправность Прошивки Схемы Справочники Маркировка Корпуса Сокращения и аббревиатуры Частые вопросы Полезные ссылки

Справочная информация

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

  • Диагностика
  • Определение неисправности
  • Выбор метода ремонта
  • Поиск запчастей
  • Устранение дефекта
  • Настройка

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

Неисправности

Все неисправности по их проявлению можно разделить на два вида — стабильные и периодические. Наиболее часто рассматриваются следующие:

  • не включается
  • не корректно работает какой-то узел (блок)
  • периодически (иногда) что-то происходит

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

  • О прошивках

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

    На сайте существуют разделы с прошивками (дампами памяти) для микросхем, либо для обновления ПО через интерфейсы типа USB.

    • Прошивки ТВ (упорядоченные)
    • Запросы прошивок для ТВ
    • Прошивки для мониторов
    • Запросы разных прошивок
    • . и другие разделы

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

  • Схемы аппаратуры

    Начинающие ремонтники часто ищут принципиальные схемы, схемы соединений, пользовательские и сервисные инструкции. Это могут быть как отдельные платы (блоки питания, основные платы, панели), так и полные Service Manual-ы. На сайте они размещены в специально отведенных разделах и доступны к скачиванию гостям, либо после создания аккаунта:

    • Схемы телевизоров (запросы)
    • Схемы телевизоров (хранилище)
    • Схемы мониторов (запросы)
    • Различные схемы (запросы)

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

  • Справочники

    На сайте Вы можете скачать справочную литературу по электронным компонентам (справочники, таблицу аналогов, SMD-кодировку элементов, и тд.).

    • Справочник по транзисторам
    • ТДКС — распиновка, ремонт, прочее
    • Справочники по микросхемам
    • . и другие .

    Информация размещена в каталогах, файловых архивах, и отдельных темах, в зависимости от типов элементов.

    Marking (маркировка) — обозначение на электронных компонентах

    Современная элементная база стремится к миниатюрным размерам. Места на корпусе для нанесения маркировки не хватает. Поэтому, производители их маркируют СМД-кодами.

    Package (корпус) — вид корпуса электронного компонента

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

    • DIP (Dual In Package) – корпус с двухрядным расположением контактов для монтажа в отверстия
    • SOT-89 — пластковый корпус для поверхностного монтажа
    • SOT-23 — миниатюрный пластиковый корпус для поверхностного монтажа
    • TO-220 — тип корпуса для монтажа (пайки) в отверстия
    • SOP (SOIC, SO) — миниатюрные корпуса для поверхностного монтажа (SMD)
    • TSOP (Thin Small Outline Package) – тонкий корпус с уменьшенным расстоянием между выводами
    • BGA (Ball Grid Array) — корпус для монтажа выводов на шарики из припоя

  • Краткие сокращения

    При подаче информации, на форуме принято использование сокращений и аббревиатур, например:

    Сокращение Краткое описание
    LED Light Emitting Diode — Светодиод (Светоизлучающий диод)
    MOSFET Metal Oxide Semiconductor Field Effect Transistor — Полевой транзистор с МОП структурой затвора
    EEPROM Electrically Erasable Programmable Read-Only Memory — Электрически стираемая память
    eMMC embedded Multimedia Memory Card — Встроенная мультимедийная карта памяти
    LCD Liquid Crystal Display — Жидкокристаллический дисплей (экран)
    SCL Serial Clock — Шина интерфейса I2C для передачи тактового сигнала
    SDA Serial Data — Шина интерфейса I2C для обмена данными
    ICSP In-Circuit Serial Programming – Протокол для внутрисхемного последовательного программирования
    IIC, I2C Inter-Integrated Circuit — Двухпроводный интерфейс обмена данными между микросхемами
    PCB Printed Circuit Board — Печатная плата
    PWM Pulse Width Modulation — Широтно-импульсная модуляция
    SPI Serial Peripheral Interface Protocol — Протокол последовательного периферийного интерфейса
    USB Universal Serial Bus — Универсальная последовательная шина
    DMA Direct Memory Access — Модуль для считывания и записи RAM без задействования процессора
    AC Alternating Current — Переменный ток
    DC Direct Current — Постоянный ток
    FM Frequency Modulation — Частотная модуляция (ЧМ)
    AFC Automatic Frequency Control — Автоматическое управление частотой

    Частые вопросы

    После регистрации аккаунта на сайте Вы сможете опубликовать свой вопрос или отвечать в существующих темах. Участие абсолютно бесплатное.

    Кто отвечает в форуме на вопросы ?

    Ответ в тему ЕПРОМ 27Сххх серии защита от копирования как и все другие советы публикуются всем сообществом. Большинство участников это профессиональные мастера по ремонту и специалисты в области электроники.

    Как найти нужную информацию по форуму ?

    Возможность поиска по всему сайту и файловому архиву появится после регистрации. В верхнем правом углу будет отображаться форма поиска по сайту.

    По каким еще маркам можно спросить ?

    По любым. Наиболее частые ответы по популярным брэндам — LG, Samsung, Philips, Toshiba, Sony, Panasonic, Xiaomi, Sharp, JVC, DEXP, TCL, Hisense, и многие другие в том числе китайские модели.

    Какие еще файлы я смогу здесь скачать ?

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

    Полезные ссылки

    Здесь просто полезные ссылки для мастеров. Ссылки периодически обновляемые, в зависимости от востребованности тем.

    EEPROM и flash память

    EEPROM — это энергонезавимая память с электрическим стиранием информации. Количество циклов записи-стирания в этих микросхемах достигает 1000000 раз. Заминающие ячейки в них, также как и в постоянных запоминающих устройствах с электрическим стиранием EPROM, реализуются на основе транзисторов с плавающим затвором. Внутреннее устройство этой запоминающей ячейки приведено на рисунке 1:


    Рисунок 1. Запоминающая ячейка ПЗУ с электрическим стиранием (EEPROM)

    Ячейка EEPROM памяти представляет собой МОП транзистор, в котором затвор выполняется из поликристаллического кремния. Затем в процессе изготовления микросхемы этот затвор окисляется и в результате он будет окружен оксидом кремния — диэлектриком с прекрасными изолирующими свойствами. В транзисторе с плавающим затвором при полностью стертом ПЗУ, заряда в «плавающем» затворе нет, и поэтому данный транзистор ток не проводит. При программировании, на второй затвор, находящийся над «плавающим» затвором, подаётся высокое напряжение и в него за счет туннельного эффекта индуцируются заряды. После снятия программирующего напряжения индуцированный заряд остаётся на плавающем затворе, и, следовательно, транзистор остаётся в проводящем состоянии. Заряд на его плавающем затворе может храниться десятки лет.

    Подобная ячейка памяти применялась в ПЗУ с ультрафиолетовым стиранием (EPROM). В ячейке памяти с электрическим стиранием возможна не только запись, но и стирание информации. Стирание информации производится подачей на программирующий затвор напряжения, противоположного напряжению записи. В отличие от ПЗУ с ультрафиолетовым стиранием, время стирания информации в EEPROM памяти составляет около 10 мс.

    Структурная схема энергонезависимой памяти с электрическим стиранием не отличается от структурной схемы масочного ПЗУ. Единственное отличие — вместо плавкой перемычки используется описанная выше ячейка. Ее упрощенная структурная схема приведена на рисунке 2.


    Рисунок 2. Упрощенная структурная схема EEPROM

    В качестве примера микросхем EEPROM памяти можно назвать отечественные микросхемы 573РР3, 558РР3 и зарубежные микросхемы серий AT28с010, AT28с040 фирмы Atmel, HN58V1001 фирмы Hitachi Semiconductor, X28C010 фирмы Intersil Corporation. В EEPROM памяти чаще всего хранятся пользовательские данные в сотовых аппаратах, которые не должны стираться при выключении питания (например адресные книги), конфигурационная информация роутеров или сотовых аппаратов, реже эти микросхемы применяются в качестве конфигурационной памяти FPGA или хранения данных DSP. EEPROM изображаются на принципиальных схемах как показано на рисунке 3.


    Рисунок 3. Условно-графическое обозначение электрически стираемого постоянного запоминающего устройства

    Чтение информации из параллельной EEPROM памяти производится аналогично чтению из масочного ПЗУ. Сначала на шине адреса выставляется адрес считываемой ячейки памяти в двоичном коде A0. A9, затем подается сигнал чтения RD. Сигнал выбора кристалла CS обычно используется в качестве дополнительного адресного провода для обращения к микросхеме. Временные диаграммы сигналов на входах и выходах этого вида ПЗУ приведены на рисунке 4.


    Рисунок 4. Временные диаграммы сигналов чтения информации из EEPROM памяти

    На рисунке 5 приведен чертеж типового корпуса микросхемы параллельной EEPROM памяти.


    Рисунок 5. Чертеж корпуса микросхемы параллельной EEPROM

    Обычно данные, которые хранятся в EEPROM требуются достаточно редко. Время считывания при этом не критично. Поэтому в ряде случаев адрес и данные передаются в микросхему и обратно через последовательный порт. Это позволяет уменьшить габариты микросхем за счет уменьшения количества внешних выводов. При этом используются два вида последовательных портов — SPI порт и I2C порт (микросхемы 25сXX и 24cXX серий соответственно). Зарубежной серии 24cXX соответствует отечественная серия микросхем 558РРX.

    Читайте также  Каким прибором измеряется освещенность рабочей поверхности?

    Внутренняя схема микросхем серии 24сXX (например AT24C01) приведена на рисунке 6.


    Рисунок 6. Внутренняя схема микросхемы AT24C01

    Подобные микросхемы широко используются для сохранения настроек телевизоров, в качестве памяти plug and play в компьютерах и ноутбуках, конфигурационной памяти ПЛИС и сигнальных процессоров (DSP). Применение последовательной EEPROM памяти позволило значительно уменьшить стоимость данных устройств и увеличить удобство работы с ними. Пример расположения данной микросхемы на печатной плате карты памяти компьютера приведен на рисунке 7.


    Рисунок 7. EEPROM на печатной плате карты памяти компьютера

    На рисунке 8 приведена схема электронной карты с применением внешней EEPROM микросхемы.


    Рисунок 8. Схема электронной карты с применением внешней EEPROM

    На данной схеме микроконтроллер PIC16F84 осуществляет обмен данными с EEPROM памятью 24LC16B. В таких устройствах, как SIM-карта, уже не применяется внешняя микросхема памяти. В SIM-картах сотовых аппаратов используется внутренняя EEPROM память однокристального микроконтроллера. Это позволяет максимально снизить цену данного устройства.

    Схема управления для электрически стираемых программируемых ПЗУ получилась сложная, поэтому наметилось два направления развития этих микросхем:

    1. ЕСППЗУ (EEPROM) — электрически стираемое программируемое постоянное запоминающее устройство
    2. FLASH-ПЗУ

    FLASH — ПЗУ отличаются от ЭСППЗУ тем, что стирание производится не каждой ячейки отдельно, а всей микросхемы в целом или блока запоминающей матрицы этой микросхемы, как это делалось в РПЗУ.


    Рисунок 9. Условно-графическое обозначение FLASH памяти

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


    Рисунок 10. Временные диаграммы сигналов чтения информации из ПЗУ

    На рисунке 10 стрелочками показана последовательность, в которой должны формироваться управляющие сигналы. На этом рисунке RD — это сигнал чтения, A — сигналы выбора адреса ячейки (так как отдельные биты в шине адреса могут принимать разные значения, то показаны пути перехода как в единичное, так и в нулевое состояние), D — выходная информация, считанная из выбранной ячейки ПЗУ.

    В настоящее время широко распространилось название флешка. Это связано с внешними накопителями, предназначенными для переноски данных с одного компьютера на другой. В составе подобного устройства основной элемент, это FLASH-ПЗУ. Именно в него записывает данные, полученные по USB-интерфейсу контроллер FLASH памяти. Ну, и считывает, конечно. Фотография печатной платы USB флешки без корпуса приведена на рисунке 11.


    Рисунок 11. Внутреннее устройство флешки

    Именно микроконтроллер формирует сигналы, временные диаграммы которых показаны на рисунке 10, которые необходимы для работы микросхемы FLASH-ПЗУ.

    Дата последнего обновления файла 04.08.2020

    Понравился материал? Поделись с друзьями!

    1. Микушин А.В. Занимательно о микроконтроллерах. — СПб, БХВ-Петербург, 2006.
    2. Микушин А.В., Сажнев А.М., Сединин В.И. Цифровые устройства и микропроцессоры. — СПб, БХВ-Петербург, 2010.
    3. С.А. Майоров, В.В. Кириллов, А.А. Приблуда Введение в микро ЭВМ — Л., Машиностроение 1988
    4. Постоянные запоминающие устройства (http://naf-st.ru/)
    5. EEPROM Параллельные (http://www.chipfind.ru/)

    Вместе со статьей «Постоянные запоминающие устройства (ПЗУ)» читают:

    Память данных EEPROM

    Что нужно для того, чтобы стать профессиональным разработчиком программ для микроконтроллеров и выйти на такой уровень мастерства, который позволит с лёгкостью найти и устроиться на работу с высокой зарплатой (средняя зарплата программиста микроконтроллеров по России на начало 2017 года составляет 80 000 рублей). Подробнее.

    ATtiny13A содержит 64 байта памяти данных EEPROM. Эта память организована как отдельное пространство данных, в котором отдельные байты могут быть прочитаны и записаны. EEPROM имеет выносливость по крайней мере 100 000 циклов записи/стирания. Обмен данными между EEPROM и процессором описан далее, и основан на использовании Регистров Адреса EEPROM (EEPROM Address Registers), Регистра Данных EEPROM (EEPROM Data Register) и Регистра Управления EEPROM (EEPROM Control Register). Подробное описания последовательной загрузки данных в EEPROM описано в документации (в оригинале это страница 106, на моём сайте будет опубликовано позже).

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

    • EEAR — Регистр Адреса EEPROM (EEPROM Address Register)
    • EEDR — Регистр Данных EEPROM (EEPROM Data Register)
    • EECR — Регистр Управления EEPROM (EEPROM Control Register)

    Если объём EEPROM превышает 256 байт (вообще в AVR эта память может иметь объём до 8 КБ в зависимости от модели МК), то вместо одного регистра адреса EEAR микроконтроллер имеет два регистра: EEARH и EEARL. Регистры доступа к EEPROM имеют следующие номера:

    • EEAR — 0x1E
    • EEARL — 0x1E
    • EEARH — 0x1F
    • EEDR — 0x1D
    • EECR — 0x1C

    Как видите, регистры EEAR и EEARL имеют одинаковые номера. То есть в микроконтроллере, где объём EEPROM меньше 256 байт (в таком, как ATtiny13A), можно использовать только EEAR (он же EEARL).

    Регистры EEAR (или EEARH и EEARL) работают только на запись. То есть в эти регистры вы можете только записать значение — адрес EEPROM, тем самым указав микроконтроллеру, с какой ячейкой памяти дальше надо будет работать.

    Регистр EEDR работает как на запись, так и на чтение. При записи через этот регистр в EEPROM поступает записываемый байт. При чтениии через этот регистр микроконтроллер получает байт из EEPROM.

    Регистр управления EECR устанавливает режим работы. Через него подаются команды чтения и записи EEPROM. Установка 0-го бита начинает чтение из EEPROM. Установка 1-го бита начинает запись в EEPROM. Для управляющих битов имеются соответствующие константы (биты регистра EECR будут описаны позже в других статьях, в оригинальной документации см. стр. 21).

    Чтение и запись EEPROM

    Регистры Адреса EEPROM (EEPROM Access Registers) доступны через область ввода-вывода.

    Время доступа для записи в EEPROM приведено в таблице 5.1. Функция самоуправления временем, однако, позволяет программному обеспечению пользователя определить, когда можно записать следующий байт. Если код пользователя содержит инструкции по записи EEPROM, необходимо принять некоторые меры предосторожности. В источниках питания с мощными фильтрами, питание VCC при включении/выключении медленно повышается (понижается). По этой причине микроконтроллер в течение некоторого времени запускается на более низком напряжении, чем допустимо для используемой тактовой частоты. Дополнительные сведения о том, как избежать сложностей в таких случаях, см. ниже в разделе “Предотвращение повреждения EEPROM”.

    Таблица 5.1. Биты режимов EEPROM.

    EECR Время программирования Операция
    EEPM1 EEPM0
    3,4 мс Стирание и запись за одну операцию (Атомарная операция)
    1 1,8 мс Только стирание
    1 1,8 мс Только запись
    1 1 Зарезервировано для будущего использования

    Чтобы предотвратить непреднамеренную запись EEPROM, необходимо выполнить определенные правила записи. Подробности см. ниже в разделах “Атомарное программирование байта” и “Раздельное программирование байта”.

    Когда выполняется чтение EEPROM, работа процессора приостанавливается на четыре такта, прежде чем следующая инструкция может быть выполнена. При записи EEPROM процессор останавливается на два такта перед выполнением следующей инструкции. То есть на время чтения/записи EEPROM процессор перестаёт выполнять команды и никакие другие инструкции не могут быть выполнены.

    Атомарное программирование байта (Atomic Byte Programming)

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

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

    Использование Атомарного Программирования байта (Atomic Byte Programming) — это самый простой режим. Записывая байт в EEPROM, пользователь должен записать адрес в регистр EEARL, а данные в регистр EEDR. Если биты EEPMn равны нулю, запись EEPE (в течение четырех тактов после записи EEMPE) вызовет операцию стирания/записи.

    И стирание, и запись выполняются за одну операцию (полное время программирования показано в таблица 5-1 выше). Бит EEPE остается установленным до завершения операций стирания и записи. Пока микроконтроллер занят программированием, невозможно выполнять какие-либо другие операции с EEPROM.

    Раздельное программирование байта (Split Byte Programming)

    Можно разделить операции стирания и записи байта на две различных операции. Это может быть полезно, если системе требуется короткое время доступа в течение некоторого ограниченного периода времени (обычно при падении напряжения питания). Чтобы воспользоваться преимуществами этого способа, необходимо, чтобы записываемые ячейки памяти были очищены (стёрты) перед операцией записи. Но поскольку операции стирания и записи разделены, можно выполнять операции стирания, когда система позволяет выполнять критические по времени операции (обычно после включения питания).

    Стирание EEPROM

    Для того, чтобы стереть байт, его адрес необходимо записать в регистр EEARL. Если биты EEPMn равны 0b01, то запись EEPE (в течение четырех тактов после записи EEMPE) вызовет только операцию стирания (время программирования указано выше в таблице 5-1). Бит EEPE остается установленным до завершения операции стирания. Пока микроконтроллер занят программированием, невозможно выполнить какие-либо другие операции с EEPROM.

    Запись EEPROM

    Для записи ячейки памяти пользователь должен записать адрес в EEARL, а данные — в EEDR. Если биты EEPMn равны 0b10, то запись EEPE (в течение четырех тактов после записи EEMPE) вызовет только операцию записи (время программирования приведено выше в таблице 5-1). В EEPE бит остается установленным до тех пор, пока операция записи не завершится. Если записываемая ячейка не была очищена (стерта) перед записью, сохраненные данные должны считаться потерянными. Пока микроконтроллер занят программированием, невозможно выполнить какие-либо другие операции с EEPROM.

    Калибровка генератора тактовой частоты с помощью регистра калибровки (Oscillator Calibration Register) используется для настройки времени доступа к EEPROM. Убедитесь, что частота генератора соответствует требованиям, описанным в разделе “OSCCAL – Oscillator Calibration Register » (в оригинальной документации стр. 27, на моём сайте будет описана позже).

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

    См. также пример здесь.

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

    См. также пример здесь.

    Предотвращение повреждения EEPROM

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

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

    Повреждения данных EEPROM можно легко избежать, следуя этому совету по проектированию:

    Поддерживайте активный (низкий) сброс AVR во время недостаточного напряжения питания. Это можно сделать, включив внутренний детектор (Brown-out Detector (BOD)). Если уровень напряжения BOD не соответствует необходимому уровню напряжения, то можно использовать внешнюю цепь сброса, поддерживающую низкий уровень на выводе сброса и предохраняющую EEPROM от порчи. Если сброс происходит во время выполнения операции записи, операция записи будет завершена при условии, что напряжение питания достаточно.

    ПРИМЕЧАНИЕ
    Обычно все типовые схемы предусматривают такую защиту без дополнительного программирования (без использования BOD). Самое простое решение — подключить вход сброса микроконтроллера к плюсу источника питания через резистор, а к минусу — через конденсатор. При подаче питания на входе сброса будет низкий уровень, пока не зарядится конденсатор. То есть микроконтроллер не запустится, пока не зарядится конденсатор. Остаётся только рассчитать номиналы резистора и конденсатора, но это уже другая тема.

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

    Введение

    Доброго времени суток. Прошлая моя статья про параметры в 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 за замечания.

    Все очень просто, существует огромный пласт измерительных устройств, которые используют полевые протоколы такие как HART, FF или PF, где пользовательские команды очень атомарные. Например, в HART протоколе есть отдельные команды — запись единиц изменения, запись верхнего диапазона, запись времени демпфирования, калибровка нуля, запись адрес опроса и т.д. Каждая такая команда должна записать один параметр, при этом успеть подготовить ответ и ответить. Таких параметров может быть до 500 — 600, а в небольших устройствах их около 200.

    Если использовать способ, который предложил пользователь @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.

    Да придется пожертвовать память, но как сделать по другому, я пока не знаю. Если есть какие мысли — пишите в комментариях.

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

    Итак, мы почти поняли что хотим. Но давайте немного формализуем это. Для начала, назовем наши параметры, которые нужно писать постоянно — AntiWearNvData (антиизносные данные). Мы хотим, чтобы обращение к ним было такое же простое и юзер френдли, как и к кешируемым параметрам из предыдущей статьи.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Класс AntiWearNvData будет похож на, CachedNvData из прошлой статьи, но с небольшими изменениям. При каждой записи в EEPROM, нам нужно постоянно сдвигать адрес записи, поэтому необходимо хранить индекс, который будет указывать на номер текущей записи. Этот индекс должен записываться в EEPROM вместе с параметром, чтобы после инициализации можно было найти запись с самым большим индексом — эта запись и будет самой актуальной. Индекс можно сделать uint32_t точно хватит на 30 лет — даже при 100 000 циклах записи.

    И вот наш класс:

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

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

    В отличии от CachedNvData Из предыдущей статьи здесь появился параметр updateTime . На основе этого параметра можно посчитать сколько записей необходимо для того, чтобы уложиться в ожидаемое время жизни EEPROM. Сами параметры EEPROM можно задать в отдельном заголовочнике. Например, так:

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

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

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

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

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

    Для этого заведена специальная структура tAntiWear . Её то мы и будем сохранять при вызове метода Set(. ) , который, кроме непосредственно записи, еще сдвигает индекс текущей записи на 1.

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

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

    Метод Get() — крайне простой, он просто возвращает копию из ОЗУ

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

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

    Полный код класса

    По аналогии с CachedNvData из прошлой статьи, все параметры должны быть зарегистрированы в едином списке, причем, в этом списке мы можем регистрировать как и CachedNvData , так и наши AntiWearNvData параметры.

    Я немного переделал список, так как IAR компилятор все еще не понимает много фишек из С++17, и собственно теперь список принимает только типы, а не ссылки на параметры. Кроме того, теперь у него появились методы SetToDefault и Init . Первый нужен, например, чтобы сбросить все параметры в их начальное значение. А второй, чтобы проинициализировать кешируемые в ОЗУ копии.

    Также в CachedNvData я добавил параметр recordSize и recordCounts = 1 . Чтобы расчет адреса параметра был унифицирован для разного типа параметров.

    Результат

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

    Замечу, что пользователю параметров нужно только объявить параметр и список, а вся портянка с кодом, до этого, пишется один раз. Используются параметры точно также как и CachedNvData .

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

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

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

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