В разработке электронных плат часто надо подписывать электронные платы (изделия) каким-то серийным номером. Это нужно для идентификации платы при серийном производстве и при сопровождении товара при техподдержке.
Внешние чипы памяти особенно важны так как прошивку микроконтроллера могут полностью стереть, поэтому хранить серийный номер на микроконтроллере внутри 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.
Что значит маркировка микросхемы 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 не приходится.
В интерфейсе I2C биты передаются старшим битом вперед. Чтение из памяти выглядит так.
На практике чтение выглядит так. Тут видно, что из чипа 0x50 по адресу 7 прочиталось число 0x78. Тут видно два старта и один стоп.
или это
Запись в память выглядит так. В в спецификации чтение показано так.
Вот работающая I2C осциллограмма записи в чип 0х50 по адресу 7 значения 0х78.
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, то в 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 на запись одного байта.
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?