logo
+7 (495) 997-37-74
Москва, ул.Международная, 15

ATSHA204A — Чтение зоны конфигурации 1

В этой статье мы продолжим знакомство с программированием криптомикросхемы 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 и на практических примерах научимся грамотно конфигурировать этот крипточип.

Ссылки по теме

Работа с SHA-256

ATSHA204 - Обзор

ATSHA204 - Спецификации

ATSHA204 - Библиотека и примеры

ATSHA204A - Чтение зоны конфигурации 2

ATSHA204A - Чтение зоны конфигурации 3

ATSHA204A - Запись конфигурации 1