Обзор Чипа Внешней I2C Памяти AT24Cхх
В разработке электронных плат часто надо подписывать электронные платы каким-то серийным номером. Это нужно для идентификации платы при серийном производстве.
Внешние чипы памяти особенно важны та как прошивку могут полностью стереть поэтому хранить серийный номер на микроконтроллере внутри on-chip NOR-Flash самого микроконтроллера ненадежно.
В 2012 году у меня в была задача на четырех микросхемах AT24C16 организовать энергонезависимый журнал для хранения наработок на отказ в холодильном оборудовании. Надо было быстро читать и писать блоки по 16 байт каждый. Тогда я записывал блоки в циклический массив на 100kHz-I2C EEPROM. В каждом блоке был 4 байтный timestamp от RTC. Для чтения и поиска я применил метод бинарного поиска для извлечения нужной записи. У меня за 4–6 секунд находился любой блок в памяти общим размером 8kByte.
В этом тексте я написал с какой стороны подходить к чипам внешней EEPROM.
Что надо из доков?
№ | Название дока | Количество страниц | 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. Память поддерживает только 1 миллион записей. Это простой чип. Вся его спека — это всего 14 страниц.
Стоит чип AT24C02M5/TR всего 11 рублей.
В нем 256 байт. Получается что 0.042 RUR/Byte= 44 RUR/kByte=45056 RUR/Mbyte=46.1 MRUR/GByte. Да уж. Жесткий диск на чипах EEPROM строить точно нет смысла. Иначе бы он стоил как 2 квартиры в Москве.
Что значит маркировка 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 | Для измерения напряжения на электронной плате |
Программная часть
Биты передаются старшим битом вперед. Чтение из памяти выглядит так. Тут надо сразу отметить что WORD ADDRESS это 2 байта даже вопреки тому что в datasheet показали как 8 бит. Видимо это ошибка в datasheet (е). Иначе не проходят модулные тесты.
чтение
На практике чтение выглядит так. Тут видно, что из чипа 0×50 по адресу 7 прочиталось число 0×34. Тут видно два старта и один стоп.
Из I2C чипа c адресом 0×50 по адресу 0×0007 прочиталось число 0×34.
Запись в память выглядит так. В в спецификации чтение показано так.
Figure 6: Page Write
На практике оказывается, что адрес это тоже 2 байта. Однако в спеке адрес опять выглядит как один байт. Вот работающая I2C осциллограмма записи в чип 0×50 по адресу 7 значения 0×34.
Write in I2C сhip 0×50, Addr 0×0007, Byte 0×34
Тут стоит заметить, что чипу 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
#include
#include
#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
Подали питание и в логе загрузке микроконтроллер написал, что обнаружил AT24Cxx чип.
В функцию инициализации имеет смысл добавить функцию вычисления CRC8. Один байт проще запомнить. Так можно будет, например, через день определить не санкционное изменение I2C-EEPROM, если в логе загрузки CRC8 вдруг окажется другим.
Вот результат сканирования I2C шины на которой сидит AT24C02
Вот кого мы тут обнаружили
№ | Ответивший на чтенье адрес, hex | Ответивший на чтенье адрес, Bin |
1 | 0×50 | 0101_0000 |
2 | 0×58 | 0101_1000 |
3 | 0xD0 | 1101_0000 |
4 | 0xD8 | 1101_1000 |
GPIO пины для I2C должны быть подтянуты к VCC.
Чтение байта по адресу 8. Прочиталось значение 0×55.
запись байта 0×85 по адресу 8
Удаление это по сути прописывание значения 0xFF.
Можно также в супер цикле периодически читать адрес I2C-чипа. Это поможет оперативно обнаружить обрыв соединения I2C шины до того как это понадобится для записи или чтения.
Тестирование драйвера AT24Cxx
Для драйвера AT24C02 у меня заготовлены вот эти 9 тестов.
Прогоним модульные тесты…
Видно что все тесты прошли!
Успех!
Достоинства I2C-EEPROM на основе AT24Cxx
1--Энергонезависимость
2--EEPROM хороша тем, что можно прописывать отдельные FF.
3--два провода для доступа к памяти
Недостатки
1--Дорогая память для масштабирования.
2--Надо ждать 5ms окончания каждой записи.
3--В спеке не сказано, что адрес двухбайтовый.
4--Мало памяти. Всего 256 байт.
Итоги
При разработке этого драйвера я столкнулся с контр интуитивными вещами. В спеке не сказано, что адрес двухбайтовый. Тем не менее удалось разработать драйвер для этого ASIC.
В отладке кода очень помогла UART-CLI и модульные тесты. Во время разработки драйвера даже ни разу не пришлось воспользоваться JTAG пошаговой отладкой.
Если вам нужен Си-драйвер для семейства микросхем AT24Cxx, то пишете в личку.
Словарь
Акроним | Расшифровка |
EEPROM | electrically erasable programmable read-only memory |
I2C | Inter-Integrated Circuit |
SCL | SERIAL CLOCK |
SDA | SERIAL DATA |
ASIC | application-specific integrated circuit |
Links
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
Контрольные вопросы:
1--Какой бит в адреcе I2C соответствует записи данных?
2--Как отличить ошибку «не читается по I2C» от ошибки «не пишется по I2C»?
3--Что такое Lazy Write?
4--Чем I2C-EEPROM лучше SPI-NOR Flash?