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

Внешние чипы памяти особенно важны так как прошивку микроконтроллера могут полностью стереть, поэтому хранить серийный номер на микроконтроллере внутри on-chip NOR-Flash самого микроконтроллера ненадежно. Микроконтроллер могут и перепаять (перекинуть). Получается что надо где-то хранить Serial Number (SN) самой PCB.

В этом тексте я написал с какой стороны подходить к чипам внешней EEPROM.

Ещё в 2012 году у меня была задача на четырех микросхемах AT24C16 (2kByte) организовать энергонезависимый журнал для хранения наработок на отказ в холодильном оборудовании с резервированием. Надо было быстро читать и писать блоки по 16 байт каждый. Тогда я записывал блоки в циклический массив на 100kHz-I2C EEPROM. В каждом блоке был 4х байтный time stamp от RTC. Для чтения и поиска я применил метод бинарного поиска для извлечения нужной записи. У меня за 4-6 секунд находился любой блок в памяти общим размером 8kByte.

Что надо из доков?

Название дока

Количество страниц

Vendor

1

AT24C02/04/08/16

13

Huaguan

2

AT24C02/04/08/16

14

Huaguan

3

Two-wire Serial EEPROM

27

Atmel

ASIC AT24C02M5/TR это китайский чип EEPROM на 256 байт с доступом по двухпроводному синхронному последовательному интерфейсу I2C от компании Huaguan Semiconductor. Чип является I2C slave устройством. Память поддерживает только 1 миллион записей. Это простой чип. Вся его спека - это всего 14 страниц.

Стоит чип AT24C02M5/TR всего 11 рублей.

В нем 256 байт. Получается, что 0.042 RUR/Byte= 44 RUR/kByte=45056 RUR/Mbyte=46.1 MRUR/GByte. Да уж. Жесткий диск на чипах EEPROM строить точно нет смысла. Иначе бы он стоил как 2 квартиры в Москве...

Вот так выглядит микросхема памяти AT24C02N EEPROM 2kBit, в корпусе DIP-8. Обратите внимание на маркировку 24С02.

Вот так выглядит микросхема памяти AT24C02N (EEPROM 2kBit, в корпусе DIP-8)
Вот так выглядит микросхема памяти AT24C02N (EEPROM 2kBit, в корпусе DIP-8)

Что значит маркировка микросхемы AT24C02M5/TR?

Аппаратная часть

Это распиновка микросхемы

На I2C шину можно подцепить до 8ми таких чипов. Чтобы и них били разные I2C адреса придумали пины A[3]. Старший нимбл всегда 0b1010=0xA=10

Получается, что на одной I2C шине из этих микросхем можно собрать планку памяти максимум 8*2kByte=16kByte. А если учесть, что у среднего микроконтроллеров обычно три I2C интерфейса, то получается, что на этой элементной базе на одной электронной плате может быть максимум 48kByte EEPROM.

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

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

Что надо из оборудования?
Для разработки и отладки драйвера I2C-EEPROM надо следующее оборудование

Оборудование

Назначение

1

Логический анализатор

Для записи электрического сигнала с I2C шины

2

перемычки

для соединения отладочной платы и модуля

3

отладочный модуль с чипом AT24C02

для отладки драйвера

4

отладочная плата с микроконтроллером и I2C интерфейсом

Для исполнения кода Cи-драйвера

5

Зажимы WAGO 3pin

для соединения логического анализатора и проводов шины I2C

6

DMM, 2 щупа, батарейка 9V для DMM

Для измерения напряжения на электронной плате

Так как общение c памятью происходит по I2C, то вот небольшая подсказка по I2C.

Программная часть

Про то как написать нормальный драйвер для ASIC есть вот эта методичка. Архитектура Хорошо Поддерживаемого драйвера для I2C/SPI/MDIO Чипа https://habr.com/ru/articles/683762/

Обычно у драйвера чипа AT24Cxx вот такие зависимости (Рис. 6). Чтобы заработал драйвер AT24Cxx нужно чтобы у вас уже был реализован определенный MCAL. Это драйвер I2C, GPIO, аппаратные таймеры или SysTick. Функции установки миллисекундных пауз. И желательно программный компонент расчета контрольных сумм. Без этого джентельменского набора говорить о разработке драйвера AT24Cxx не приходится.

Рис. 6 Программные зависимости драйвера AT24Cxx
Рис. 6 Программные зависимости драйвера AT24Cxx

В интерфейсе I2C биты передаются старшим битом вперед. Чтение из памяти выглядит так. Тут надо сразу отметить, что WORD ADDRESS это 2 байта даже вопреки тому, что в datasheet показали как 8 бит. Видимо это ошибка в datasheet(е). Иначе просто не проходят модульные тесты.

чтение
чтение

На практике чтение выглядит так. Тут видно, что из чипа 0x50 по адресу 7 прочиталось число 0x34. Тут видно два старта и один стоп.

Из I2C чипа c адресом 0x50 по адресу 0x0007 прочиталось число 0x34.
Из I2C чипа c адресом 0x50 по адресу 0x0007 прочиталось число 0x34.

Запись в память выглядит так. В в спецификации чтение показано так.

Figure 6: Page Write
Figure 6: Page Write

На практике оказывается, что адрес это тоже 2 байта. Однако в спеке адрес опять выглядит как один байт. Вот работающая I2C осциллограмма записи в чип 0х50 по адресу 7 значения 0х34.

Write in I2C сhip 0x50, Addr 0x0007, Byte 0x34
Write in I2C сhip 0x50, Addr 0x0007, Byte 0x34

Тут стоит заметить, что чипу AT24C02 надо минимум 5ms, чтобы завершить запись в ячейки EEPROM.

Записывать можно максимум количество байт в станице. Для чипа AT24C02 это 8 байт. Иначе внутренний приемный буфер переполнится и данные не будут записаны. Ну сами представьте, куда денутся данные, если вы по I2C решите отправить сразу поезд байтов длинной в гигабайт?

Самый простой вариант - это записывать байт за байтом. Один I2C пакет на один байт. Но только тогда придется ждать 5ms окончания записи каждого байта. Всю память можно будет прошить за 1.5 секунд. Либо прописать 32 страницы и это потребует всего 0.19 сек.

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

Вот так может выглядеть API для драйвера чипа AT24CXX. Функции для чтения и функции для записи.

#ifndef AT24CXX_DRV_H
#define AT24CXX_DRV_H

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "at24cxx_config.h"
#include "at24cxx_types.h"

uint8_t at24cxx_read_byte_short(uint8_t num, uint16_t address);
bool at24cxx_read_byte(uint8_t num, uint16_t address, uint8_t* const data);
bool at24cxx_read(uint8_t num, uint16_t address, void* const data, size_t size);
bool at24cxx_read_address(uint8_t num, uint16_t* const address);
bool at24cxx_is_connected(uint8_t num);
bool at24cxx_init(void);
bool at24cxx_write_ctrl(uint8_t num, bool on_off);

bool at24cxx_write(uint8_t num, uint16_t address, 
                   const uint8_t* const data, size_t size);
bool at24cxx_write_byte(uint8_t num, uint16_t address, uint8_t data);
bool at24cxx_write_page(uint8_t num, uint16_t address, uint8_t* page);
bool at24cxx_erase(uint8_t num, uint16_t address, size_t size);
bool at24cxx_erase_chip(uint8_t num);

#endif /* AT24CXX_DRV_H */

Отладка драйвера I2C-EEPROM

Подали питание и в UART логе загрузки микроконтроллер написал, что обнаружил чип AT24Cxx.

фрагмент лога загрузки микроконтроллера
фрагмент лога загрузки микроконтроллера

В функцию инициализации имеет смысл добавить функцию вычисления CRC8. Один байт проще запомнить. Так можно будет, например, через день определить не санкционное изменение I2C-EEPROM, если в логе загрузки CRC8 вдруг окажется другим (в данном случае не 0x7F). CRC нужна для регистрации факта изменения/повреждения данных. Например, заряженными частицами из космоса. Плюс CRC это требование ISO26262 часть 6.

Вот результат сканирования I2C шины на которой сидит AT24C02N.

Вот кого мы тут обнаружили. Я взял в работу адрес 0x50, однако зачем оставшиеся совсем не ясно.

Ответивший на чтение адрес

hex

Bin

1

0x50*

0101_0000*

3

0xD0

1101_0000

GPIO пины для I2C должны быть подтянуты к VCC.

Чтение байта по адресу 8. Прочиталось значение 0x55.

В чипе AT24C02 так мало памяти, что всё вычитанное компактно помещается на одном квадрате 16*16 байт.



Запись байта 0x85 по адресу 8. Тут, кстати, пример того как UART-CLI консоль одной строчкой исполняет последовательно 2 команды: запись потом чтение. Разделитель команд это символ ;

Стирание памяти - это по сути прописывание значения 0xFF.

Можно также в супер цикле периодически читать адрес I2C-чипа. Своего рода "Hello пакеты". Это поможет оперативно обнаружить обрыв соединения I2C шины до того как это понадобится для записи или чтения. Особенно полезно при отладке на прототипах из навесных перемычек типа "гнезо-вилка".

Вот задача AT24CXX, которая проверяет факт подключения I2C проводов.
Вот задача AT24CXX, которая проверяет факт подключения I2C проводов.

Если я отключу питание от микросхемы AT24Cxx, то в UART-CLI выскочит красное сообщение об ошибке.

Тестирование драйвера AT24Cxx

Для драйвера AT24C02 у меня заготовлены вот эти 9 тестов.

Что ж, прогоним модульные тесты...

Видно, что все тесты прошли!

Успех!

Достоинства I2C-EEPROM на основе AT24Cxx

1--Энергонезависимость

2--EEPROM хороша тем, что можно прописывать отдельные FF.

3--два провода для доступа к памяти

4--У I2C-EEPROM шире температурный диапазон чем у SD-карт. Особенно в области отрицательных температур. –55°C to +125°C в то время как SD-карты это от -25 °C до +85 °C.

Недостатки AT24C02

1--Дорогая память для масштабирования (45056 RUR/Mbyte)

2--Надо ждать 5ms окончания каждой записи. В среднем случае это 0,7ms на запись одного байта.

3--В спеке не сказано, что адрес для адресации внутри памяти на самом деле двухбайтовый.

4--Мало памяти. Всего 256 байт. Можно сохранить только 23 телефонных номера, причем без пояснений чьи это номера. Однако есть и более вместительные чипы I2C-EEPROM. Вот например HG24LC512M/TR, 512kBit, 64kByte, SOP-8. 70RUR. Это в 256 раз больше чем в AT24C02.

5--Отсутствует регистр с id номером ревизии микросхемы. Из-за этого не написать модульный тест для проверки чтения. При разработке в случае проблем ты долго не понимаешь в чем проблема: либо сломалась чтение либо сломалась запись.

6--За раз можно записать максимум 8 байт. Большие куски записываются по частям.

Идеи проектов на чипах I2C-EEPROM

1-- Подпись PCB: ID, SN.

2-- Хранение ключей (например для RFID)

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

Удивительно но у российского Ангстрема тоже есть своя микросхема I2C-EERPOM на 512 байт. Называется К5004РР4Т. Однако где её купить и за сколько выяснить так и не удалось.

Итоги

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

В отладке кода очень помогла UART-CLI(шка) и встроенные в прошивку модульные тесты. Во время разработки драйвера мне даже ни разу не пришлось воспользоваться JTAG пошаговой отладкой.

Если Вам нужен Си-драйвера для семейства микросхем AT24Cxx, то пишете в личку, я пришлю сорцы.

Словарь

Акроним

Расшифровка

EEPROM

electrically erasable programmable read-only memory

I2C

Inter-Integrated Circuit

MCAL

micro-controller Abstraction Layer

SCL

SERIAL CLOCK

PCB

Printed circuit board

SDA

SERIAL DATA

ASIC

application-specific integrated circuit

Links

Архитектура Хорошо Поддерживаемого драйвера для I2C/SPI/MDIO Чипа https://habr.com/ru/articles/683762/

Программирование EEPROM 93C76. Пишем программатор. Часть 1
https://habr.com/ru/articles/705072/

https://docs.google.com/spreadsheets/d/11aj3NdqWaDlz4OA9JxOmdXYTAaJEBaWIYc7GP2Ownq0/edit#gid=0

http://www.hgsemi.com.cn
https://www.youtube.com/watch?v=s7MYZamZ4hw

https://www.youtube.com/watch?v=urfhXmCd-uA

Сравнение разновидностей энергонезависимой памяти
https://docs.google.com/spreadsheets/d/1m3TZK1-Uz6JjKpv7rpEAgvpW_WwF1x2sX78ZtoO9huI/edit#gid=634440697

Программирование EEPROM AT24C04
https://www.youtube.com/watch?v=urfhXmCd-uA&t=305s

EEPROM и STM32 || I2C || Многостраничная запись и чтение
https://www.youtube.com/watch?v=-tV2pPXZ4VM

Контрольные вопросы:

1--Какой бит в адреcе I2C соответствует записи данных?

2--Как отличить ошибку "не читается по I2C" от ошибки "не пишется по I2C"?

3--Что такое Lazy Write?

4--Чем I2C-EEPROM лучше SPI-NOR Flash?

Комментарии (32)


  1. Arhammon
    19.11.2023 05:02
    +2

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

    Такое ощущение, что попало в начало текста случайным копипастом...


    1. iamkisly
      19.11.2023 05:02
      +1

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

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

      Словно EEPROM стереть нельзя. В общем бред сивой кобылы. Если бы автор как-то хотел раскрыть эту тему, то к примеру там было бы упоминание о том, что те же stm32 имеют зашитый на производстве uid, или внешняя микросхема с зашитым uid и каким-нибудь aes протектором (у exDallaSemiconductor их навалом)


      1. Azeront
        19.11.2023 05:02

        Наверное, автор имел в виду именно "серийный номер изделия", а не какой-то случайный предустановленный UID. Чтобы само устройство могло сообщить "я - № 437-ое изделие данного модельного ряда".


        1. makkarpov
          19.11.2023 05:02
          +2

          Для этого у многих МК есть OTP flash, которую тоже нельзя стереть после записи. Так что пример реально из пальца высосан.


          1. aabzel Автор
            19.11.2023 05:02

            Микроконтроллер могут и перекинуть. А надо где-то хранить SN самой PCB.


            1. Arhammon
              19.11.2023 05:02
              +2

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

              А зачем нужен разработчику именно серийный номер платы...


              1. aabzel Автор
                19.11.2023 05:02

                А зачем нужен разработчику именно серийный номер платы...

                Чтобы найти в базе данных отчет модульных тестов для этой конкретной платы.


        1. iamkisly
          19.11.2023 05:02
          +1

          Кому сообщить? Пользователю? Для чего? В чем смысл вот этого human like сообщения? Модель обычно на корпусе указана. Его достаточно и в прошивке захардкодить вместе с контрольной суммой. Это не сложно. Но зачем когда есть заранее прожитый uid (а производитель микроконтроллера редко меняется), который можно записать в базу во время автоматического тестирования.


      1. aabzel Автор
        19.11.2023 05:02
        +1

        Словно EEPROM стереть нельзя.

        Можно из релизной прошивки исключить функции записи и стирания из драйвера EEPROM. Оставить только чтение.


        1. makkarpov
          19.11.2023 05:02
          +2

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

          Чтобы найти в базе данных отчет модульных тестов для этой конкретной платы.

          Интересная и информативная база данных получится - "PASS, PASS, PASS, PASS, PASS, PASS, PASS, PASS, ...". Те платы, где был другой вердикт, улетели в мусорку (или на доработку).

          Микроконтроллер могут и перекинуть

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


          1. aabzel Автор
            19.11.2023 05:02

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

            Там такая плата что пин WP всегда на GND.
            Это значит что пин всегда можно писать стирать.


            1. makkarpov
              19.11.2023 05:02
              +2

              Хорошо, тогда к питанию через резистор. Я почему-то думал, что по аналогии с SPI-флешками пин инверсный.

              На момент начальной прошивки закорачивать на землю пого-пином, разрешая запись.


  1. sav13
    19.11.2023 05:02
    +1

    А не проще для записи логов было использовать обычную SD-CARD подключенную по SPI?

    Тут и масштабируемость лучше. И читать можно на любом компьютере, в случае чего.


    1. aabzel Автор
      19.11.2023 05:02

      А не проще для записи логов было использовать обычную SD-CARD подключенную по SPI?

      Надо чтобы память была неразрывно связана с электронной платой. А SD карту можно вытащить и потерять.


    1. aabzel Автор
      19.11.2023 05:02

      А не проще для записи логов было использовать обычную SD-CARD подключенную по SPI?

      Большинство SD карт не проходят по температурному диапазону


  1. GennPen
    19.11.2023 05:02
    +6

    1--Дорогая память для масштабирования.

    4--Мало памяти. Всего 256 байт.

    Нормальная память. Для каждых задач свой тип памяти. Конкретно эта предназначена для частой записи мелких данных, т.к. выдерживает около 1млн. циклов перезаписи.

    Если нужно еще чаще записывать, то стоит посмотреть в сторону FRAM, она совмещает достоинства EEPROM и имеет практически неограниченное кол-во циклов перезаписи, к тому же ее можно использовать без изменения кода.


    1. ponikrf
      19.11.2023 05:02
      +2

      FRAM просто прелесть, вместо использования батареек сейчас предпочитаю использовать FRAM. О ресурсе перезаписи не думаю, в моих кейсах использования, достаточно и того что есть. А вот то что не надо ставить батарейку и мониторить ее - это прям реально радует.


      1. Demonter
        19.11.2023 05:02
        +1

        У FRAM есть такой нюанс, как разрушающее чтение. Полностью игнорировать вопрос питания не стоит.


        1. av-86
          19.11.2023 05:02
          +1

          А можно в двух словах? При чтении расходуется ресурс? И сколько это (хотя бы порядок)?


          1. Demonter
            19.11.2023 05:02
            +3

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


            1. GennPen
              19.11.2023 05:02
              +4

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


  1. vv_kuznetsov
    19.11.2023 05:02
    +5

    Этим микросхемам EEPROM уже сто лет в обед. По ним всё 1000 раз жёвано-пережёвано. Имеются даже готовые библиотеки под любой МК. В чём был смысл делать про это статью в 2023 году?


    1. vblats1984
      19.11.2023 05:02
      +10

      Человек открыл для себя EEPROM.

      Лучше такие топики, чем очередное "почему OpenAI уволило Альтмана".


    1. iamkisly
      19.11.2023 05:02
      +3

      Поддерживаю. И все-таки статья достаточно полная.


    1. aabzel Автор
      19.11.2023 05:02
      +1

      Имеются даже готовые библиотеки под любой МК.

      Хороший драйвер для I2C-EEPROM должен быть единообразным для всех микроконтроллеров и собираться без изменения кода на всех ToolChain(aх).

      Обычно у драйвера чипа AT24Cxx вот такие зависимости .


      Чтобы заработал драйвер AT24Cxx нужно чтобы у вас уже был реализован определенный MCAL. Это драйвер I2C, драйвер GPIO, драйвер аппаратного таймера или SysTick. Функции установки миллисекундных пауз. И желательно программный компонент расчета контрольных сумм. Без этого джентельменского набора говорить о разработке драйвера AT24Cxx не приходится.


      1. aumi13
        19.11.2023 05:02
        +2

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

        спрошу лиш о том почему за 10 лет программирования микроконтроллеров мне ни разу ни понадобился црц. на всякий случай уточню - использовал 24c32, 24LC256, 24LC512, m24m01, AT25F512, w25q32jv


        1. aabzel Автор
          19.11.2023 05:02

          CRC нужна для регистрации факта изменения/повреждения данных.
          Например заряженными частицами из космоса.

          + CRC это требование ISO26262-6


    1. aabzel Автор
      19.11.2023 05:02
      +2

       По ним всё 1000 раз жёвано-пережёвано. Имеются даже готовые библиотеки под любой МК. В чём был смысл делать про это статью в 2023 году?


      GIT Hub наполнен низкопробными драйверами от embedded школоты и Junior разработчиков.

      Про то как писать добротный драйвер для ASIC есть вот эта методичка.

      Архитектура Хорошо Поддерживаемого драйвера для I2C/SPI/MDIO Чипа
      https://habr.com/ru/articles/683762/

      +надо чтобы код драйвера проходил по ISO 26262-6

      И вероятность найти такой код в интернете крайне мала.


  1. pecmapm
    19.11.2023 05:02
    +2

    Круто! Огромное спасибо за статью.


  1. DungeonLords
    19.11.2023 05:02
    +1

    Также вам может быть интересно База по SPI NOR FLASH


  1. vit496
    19.11.2023 05:02

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


    1. aabzel Автор
      19.11.2023 05:02

      Если бы вы поинтересовались у любого ремонтника бытовой техники,

      С каких это пор маститые вендоры бытовой техники предоставляют ремонтникам бытовой техники из торговых центров схемотехнику электронных плат?