В этой статье мы продолжим знакомство с программированием криптомикросхемы ATSHA204A, начатое в статье Библиотека и примеры. В ней было рассмотрено устройство библиотеки ATSHA204A и назначение её функций, а также было дано несколько примеров их использования.
В этой части мы начнём знакомство с программированием области конфигурации ATSHA204A и последовательно разберём какую информацию и каким образом можно читать из этого раздела EEPROM памяти ATSHA204A. Все наши действия будут проиллюстрированы практическими примерами кода, который вы можете использовать в ваших собственных проектах.
Зона конфигурации
Как уже отмечалось в разделе Спецификации этого руководства, микросхема ATSHA204A содержит так называемую Configuration Zone, в которой хранится серийный номер и другие идентификационные данные микросхемы ATSHA204A, а также информация о разрешении доступа для каждого слота данных и прочие настройки. Эта зона занимает 88 байт (704 бита) в EEPROM памяти ATSHA204A.
Ниже приведена таблица из даташита на эту микросхему, в которой производителем подробно расписаны содержание и назначение всех частей этой области памяти ATSHA204A.
Давайте подробно разберём все составные части конфигурационной зоны ATSHA204A.
Serial Number — уникальный серийный номер микросхемы. Устанавливается на заводе при производстве микросхемы и доступен только для чтения.
Revision Number — номер заводской ревизии микросхемы. Тоже устанавливается на заводе и доступен только для чтения.
I2C Enable — байт режима работы интерфейса микросхемы I2C/SWI. Устанавливается на заводе и доступен только для чтения.
I2C Address — адрес микросхемы на шине I2C или напряжение логических сигналов в случае использования шины SWI. Доступен для изменения, пока конфигурационная зона не залочена.
CheckMacConfig — байт настройки режимов работы команд CheckMac, Read и Write. Доступен для изменения, пока конфигурационная зона не залочена.
OTP Mode — байт режима работы OTP зоны памяти микросхемы ATSHA204A. Доступен для изменения, пока конфигурационная зона не залочена.
Selector Mode — байт режима работы селектора (Selector). Доступен для изменения, пока конфигурационная зона не залочена.
Slot Configuration (0 – 15) — байты конфигурации работы и доступа к 16-и слотам зоны данных (Data Zone) микросхемы ATSHA204A. Доступны для изменения, пока конфигурационная зона не залочена.
Use Flag (0 – 7) — байты количества раз использования перед отключением «одноразовых» слотов 0 – 7. Доступны для изменения, пока конфигурационная зона не залочена.
Update Count (0 – 7) — байты количества обновлений слотов 0 – 7 с помощью DeriveKey. Доступны для изменения, пока конфигурационная зона не залочена.
Last Key Use (0 – 15) — байты для управления ограничением использования слотов 0 – 15. Доступны для изменения, пока конфигурационная зона не залочена.
UserExtra — байт устанавливается с помощью команды CreateExtra. Доступен для изменения, пока конфигурационная зона не залочена.
Selector — байт выбора устройства, которое останется в активном режиме после выполнения команды Pause. Доступен для изменения, пока конфигурационная зона не залочена.
Lock Data — байт управления разблокировкой зон Data и OTP. Доступен для изменения, пока конфигурационная зона не залочена.
Lock Config — байт блокировки конфигурационной зоны микросхемы ATSHA204A.
В конфигурационной зоне содержатся все основные настройки микросхемы ATSHA204A и предполагается, что после внесения всех изменений в эту зону, она должна быть залочена (закрыта от возможности записи и изменения настроек).
Поэтому чёткое понимание смысла данных, содержащихся в конфигурационной зоне микросхемы ATSHA204A, а также приёмов и методов чтения и изменения (записи) этих данных является очень важным для успешной работы с ATSHA204A.
Далее мы на практических примерах подробно разберём чтение и работу с данными в конфигурационной зоне микросхемы ATSHA204A.
Чтение серийного номера
Начнём мы с чтения серийного номера из конфигурационной зоны микросхемы ATSHA204A. Для того, чтобы был понятен принцип работы с конфигурационной зоной, подробно разберём все детали и нюансы чтения серийного номера из неё.
Ниже представлен фрагмент уже знакомой вам таблицы, красным цветом в нём выделены данные, относящиеся к серийному номеру микросхемы. Видно, что номер фрагментирован и «размазан» по нескольким полям таблицы и ячейкам EEPROM памяти микросхемы ATSHA204A. В частности, в середину серийного номера производитель «вклинил» данные о заводской ревизии микросхемы.
Поэтому у нас стоит задача прочитать данные о серийном номере по частям и затем «склеить» их в одну правильную последовательность. Обратите внимание, что в первом столбце «Word» цифры указаны в формате шестнадцатеричного слова по 4 байта, то есть в привычной нам форме это будет выглядеть так:
Word (Слот) – 16-адрес (10-адрес)
0x00 (0) – 0x00 (0)
0x01 (1) – 0x04 (4)
0x02 (2) – 0x08 (8)
0x03 (3) – 0x0C (12)
0x04 (4) – 0x10 (16)
0x05 (5) – 0x14 (20)
0x06 (6) – 0x18 (24)
0x07 (7) – 0x1C (28)
0x08 (8) – 0x20 (32)
0x09 (9) – 0x24 (36)
0x0A (10) – 0x28 (40)
0x0B (11) – 0x2C (44)
0x0C (12) – 0x30 (48)
0x0D (13) – 0x34 (52)
0x0E (14) – 0x38 (56)
0x0F (15) – 0x3C (60)
0x10 (16) – 0x40 (64)
0x11 (17) – 0x44 (68)
0x12 (18) – 0x48 (72)
0x13 (19) – 0x4C (76)
0x14 (20) – 0x50 (80)
0x15 (21) – 0x54 (84)
В общем, говоря проще, мы имеем дело с 22-я «слотами» (строки таблицы) по 4 байта в каждой строке (в каждом слоте). Суммарно, это те 88 байт конфигурационной зоны, о которых говорилось ранее. Обратите внимание: микросхема ATSHA204A устроена таким образом, что физически чтение из неё можно осуществлять только «словами» (word) по 4 или 32 байта. В данных примерах мы будем использовать чтение «словами» или «слотами» по 4 байта.
Теперь приведём полный код скетча, который осуществляет чтение серийного номера из конфигурационной зоны микросхемы ATSHA204A, а затем подробно разберём его работу.
/* ATSHA204 Read Config Serial */ #include <sha204_library.h> #define ATSHA204_PIN A3 byte bufTx[SHA204_CMD_SIZE_MAX]; byte bufRx[SHA204_RSP_SIZE_MAX]; #define SERIAL_LEN 9 byte bufSerial[SERIAL_LEN]; byte slot = 0; byte retCode = 0; atsha204Class sha204(ATSHA204_PIN); void setup() { Serial.begin(115200); Serial.println("ATSHA204 Read Config Serial start..."); Serial.print(F("Serial: ")); readConf(); printBuffer(bufSerial, SERIAL_LEN); } void printBuffer(byte* data, byte len) { for (size_t i = 0; i < len; i++) { if (data[i] < 10) {Serial.print('0');} Serial.print(data[i], HEX); if (i < len - 1) {Serial.print(' ');} } } byte addr(byte slot) { return slot * 4; } void readConf() { slot = 0; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufSerial[0] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufSerial[1] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufSerial[2] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufSerial[3] = bufRx[SHA204_BUFFER_POS_DATA + 3]; slot = 2; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufSerial[4] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufSerial[5] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufSerial[6] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufSerial[7] = bufRx[SHA204_BUFFER_POS_DATA + 3]; slot = 3; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufSerial[8] = bufRx[SHA204_BUFFER_POS_DATA + 0]; } void loop() { }
Вначале скетча мы подключаем библиотеку для работы с чипом ATSHA204A.
#include <sha204_library.h>
Затем определяем к какому пину микроконтроллера подключён чип ATSHA204A. В случае использования uniSensors LoRa в качестве тестового стенда, это пин A3.
#define ATSHA204_PIN A3
Далее определяем два байтовых массива для входных и выходных данных функций взаимодействия с микросхемой ATSHA204A.
byte bufTx[SHA204_CMD_SIZE_MAX]; byte bufRx[SHA204_RSP_SIZE_MAX];
Константы
SHA204_CMD_SIZE_MAX SHA204_RSP_SIZE_MAX
определены в библиотеке ATSHA204A и представляют собой максимально возможное количество байт для команды и ответа микросхемы ATSHA204A.
Затем определяем массив для хранения серийного номера длиной в 9 байт.
#define SERIAL_LEN 9 byte bufSerial[SERIAL_LEN];
Объявляем переменную slot для хранения значения текущего (того, с которым мы работаем в данный момент) слота из 4-х байт.
byte slot = 0;
И переменную для хранения кода возврата функции чтения данных из микросхемы ATSHA204A. Любой результат, отличный от нуля, говорит о том, что чтение произошло с ошибкой; если код возврата равен нулю, то операция завершилась успешно.
byte retCode = 0;
И далее создаём объект для работы с чипом ATSHA204A и передаём ему номер пина, к которому подключена наша микросхема.
atsha204Class sha204(ATSHA204_PIN);
Затем инициализируем Serial интерфейс и выводим сообщение о старте скетча.
void setup() { Serial.begin(115200); Serial.println("ATSHA204 Read Config Serial start...");
Чтение данных из микросхемы ATSHA204A производится функцией readConf().
void readConf() { slot = 0; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufSerial[0] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufSerial[1] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufSerial[2] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufSerial[3] = bufRx[SHA204_BUFFER_POS_DATA + 3]; slot = 2; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufSerial[4] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufSerial[5] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufSerial[6] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufSerial[7] = bufRx[SHA204_BUFFER_POS_DATA + 3]; slot = 3; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufSerial[8] = bufRx[SHA204_BUFFER_POS_DATA + 0]; }
Вначале мы определяем номер слота из 4-х байт, с которым будем работать. Согласно даташиту (см. таблицу выше) начало серийного номера лежит в слоте 0 (0x00).
slot = 0;
Затем вызываем библиотечную функцию sha204.sha204m_read() для чтения данных из конфигурационной зоны (SHA204_ZONE_CONFIG) по адресу текущего (выбранного нами) 4-байтового слота.
retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
Функция addr() формирует адрес для чтения из номера слота конфигурационной зоны, просто умножая его на 4 (один слот содержит 4 байта).
byte addr(byte slot) { return slot * 4; }
Результат чтения данных из ATSHA204A записывается в приёмный массив bufRx и затем копируется в 9-байтовый массив для хранения серийного номера bufSerial на соответствующие позиции байтов в массиве.
0 - 0 1 - 1 2 - 2 3 - 3
bufSerial[0] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufSerial[1] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufSerial[2] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufSerial[3] = bufRx[SHA204_BUFFER_POS_DATA + 3];
Затем выставляется следующий слот хранения серийного номера согласно даташита.
slot = 2;
И производится чтение данных и дальнейшая сборка серийного номера по схеме
4 - 0 5 - 1 6 - 2 7 - 3
retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufSerial[4] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufSerial[5] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufSerial[6] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufSerial[7] = bufRx[SHA204_BUFFER_POS_DATA + 3];
И в конце читается последний байт и осуществляется окончательное формирование серийного номера в массиве bufSerial.
slot = 3; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufSerial[8] = bufRx[SHA204_BUFFER_POS_DATA + 0];
Далее осуществляется вывод в Serial результатов работы нашей программы.
Serial.print(F("Serial: ")); readConf(); printBuffer(bufSerial, SERIAL_LEN);
Функция printBuffer() побайтно выводит массив bufSerial на печать в шестнадцатеричной форме. Вот скриншот результата работы нашего скетча.
Красным цветом здесь выделены действительно уникальные байты серийного номера, остальные 3 байта являются одинаковыми и повторяющимися у всех микросхем семейства ATSHA204A.
Мы подробным образом описали и разобрали пример чтения из конфигурационной зоны микросхемы ATSHA204A её серийного номера, теперь давайте перейдём к рассмотрению примеров чтения других параметров из этой зоны.
Чтение номера заводской ревизии
Теперь давайте прочитаем из микросхемы ATSHA204A номер её заводской ревизии. Согласно таблице из даташита он находится в первом слоте (0x01). Этот номер, также как и серийный, доступен только для чтения и изменить его нельзя.
Теперь полный код скетча, осуществляющего чтение и вывод номера заводской ревизии микросхемы ATSHA204A.
/* ATSHA204 Read Config Revision */ #include <sha204_library.h> #define ATSHA204_PIN A3 byte bufTx[SHA204_CMD_SIZE_MAX]; byte bufRx[SHA204_RSP_SIZE_MAX]; #define REV_LEN 4 byte bufRev[REV_LEN]; byte slot = 0; byte retCode = 0; atsha204Class sha204(ATSHA204_PIN); void setup() { Serial.begin(115200); Serial.println("ATSHA204 Read Config Revision start..."); Serial.print(F("Revision: ")); readConf(); printBuffer(bufRev, REV_LEN); } void printBuffer(byte* data, byte len) { for (size_t i = 0; i < len; i++) { if (data[i] < 10) {Serial.print('0');} Serial.print(data[i], HEX); if (i < len - 1) {Serial.print(' ');} } } byte addr(byte slot) { return slot * 4; } void readConf() { slot = 1; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufRev[0] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufRev[1] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufRev[2] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufRev[3] = bufRx[SHA204_BUFFER_POS_DATA + 3]; } void loop() { }
Этот скетч похож на предыдущий, поэтому мы остановимся только на их отличиях. Мы объявляем 4-байтовый массив bufRev для хранения номера заводской ревизии ATSHA204A.
#define REV_LEN 4 byte bufRev[REV_LEN];
Само чтение данных о номере осуществляет функция readConf().
void readConf() { slot = 1; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); bufRev[0] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufRev[1] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufRev[2] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufRev[3] = bufRx[SHA204_BUFFER_POS_DATA + 3]; }
Мы присваиваем переменной slot значение «1» (согласно информации из даташита)
slot = 1;
и производим чтение 4-х байт номера ревизии при помощи библиотечной функции sha204.sha204m_read()
retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
и далее присваиваем массиву bufRev значения этих байтов.
bufRev[0] = bufRx[SHA204_BUFFER_POS_DATA + 0]; bufRev[1] = bufRx[SHA204_BUFFER_POS_DATA + 1]; bufRev[2] = bufRx[SHA204_BUFFER_POS_DATA + 2]; bufRev[3] = bufRx[SHA204_BUFFER_POS_DATA + 3];
Далее просто выводим эту информацию в Serial.
Serial.print(F("Revision: ")); readConf(); printBuffer(bufRev, REV_LEN);
И видим номер ревизии нашей микросхемы ATSHA204A.
Чтение I2C Enable
Теперь получим из ATSHA204A байт I2C Enable, указывающий по какому интерфейсу (I2C/SWI) работает наша микросхема. Согласно даташита, эта информация находится в 3-м слоте, на 2-й позиции. Полный код скетча:
/* ATSHA204 Read Config I2C enable */ #include <sha204_library.h> #define ATSHA204_PIN A3 byte bufTx[SHA204_CMD_SIZE_MAX]; byte bufRx[SHA204_RSP_SIZE_MAX]; byte i2cEn = 0; byte slot = 0; byte retCode = 0; atsha204Class sha204(ATSHA204_PIN); void setup() { Serial.begin(115200); Serial.println("ATSHA204 Read Config I2C enable start..."); Serial.print(F("Byte I2C enable: ")); readConf(); Serial.println(i2cEn, HEX); Serial.print(F("Bit #0: ")); Serial.println(bitRead(i2cEn, 0)); } byte addr(byte slot) { return slot * 4; } void readConf() { slot = 3; retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); i2cEn = bufRx[SHA204_BUFFER_POS_DATA + 2]; } void loop() { }
Присваиваем переменной slot значение «3»
slot = 3;
получаем данные 3-го слота
retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
и присваиваем переменной i2cEn значение выходного массива bufRx со смещением «2» (+ 2).
i2cEn = bufRx[SHA204_BUFFER_POS_DATA + 2];
Далее выводим результат в Serial.
Согласно даташита, информацию о типе интерфейса несёт в себе нулевой бит байта I2C Enable, поэтому дополнительно выводим информацию об этом бите.
Serial.print(F("Bit #0: ")); Serial.println(bitRead(i2cEn, 0));
Если нулевой бит байта I2C Enable равен единице, то значит работает I2C интерфейс, если он равен нулю, то SWI. Всё правильно, в нашем случае микросхема подключена по SWI интерфейсу.
Также, согласно даташита, этот байт нельзя изменить — он устанавливается при производстве чипа на заводе производителя.
Заключение
В этой части руководства по мы начали знакомство с чтением и программированием конфигурационной зоны микросхемы ATSHA204A. Это базовая и очень важная часть работы с этим чипом, поскольку от грамотной его конфигурации зависит вся его дальнейшая криптографическая работа и, соответственно, качество защиты всего вашего проекта.
В следующих статьях мы продолжим разбор работы с конфигурационной зоной ATSHA204A и на практических примерах научимся грамотно конфигурировать этот крипточип.
Ссылки по теме
ATSHA204 - Библиотека и примеры
ATSHA204A - Чтение зоны конфигурации 2
ATSHA204A - Чтение зоны конфигурации 3
ATSHA204A - Запись конфигурации 1
ATSHA204A - Запись конфигурации 2
ATSHA204A - Запись конфигурации 3
ATSHA204A - Запись конфигурации 4
ATSHA204A - Работа в режиме Config Lock
ATSHA204A - Работа с зонами памяти
ATSHA204A - Чтение Data и OTP зон памяти
ATSHA204A - Аутентификация. Базовый блок
ATSHA204A - Аутентификация. Датчик
ATSHA204A - Криптография и команды
ATSHA204A - nRF24 аутентификация. База
ATSHA204A - nRF24 аутентификация. Датчик