logo
+7 (951) 999-89-94
428003, г. Чебоксары, ул. Федора Гладкова, д.9, оф.319

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

В этой статье мы продолжим знакомство с программированием зоны конфигурации микросхемы ATSHA204A и разберём примеры чтения её различных параметров. Также мы уделим внимание объяснению смысла и назначения этих параметров. Это крайне важная информация, без хорошего понимания этих вопросов работа с микросхемой ATSHA204A попросту невозможна.

Таблица зоны конфигурации

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

В предыдущей статье мы уже разобрали работу и чтение из зоны конфигурации ATSHA204A серийного номера микросхемы, номера её заводской ревизии и флага работы по I2C/SWI интерфейсам. Эту статью мы начнём с разбора и чтения байта I2C Address.

Чтение I2C Address

В даташите на ATSHA204A указано, что в случае работы чипа по I2C интерфейсу, бит I2C Address содержит адрес ATSHA204A на I2C шине, а в случае работы по SWI интерфейсу, в этом байте содержится информация об уровне напряжения логики.

В нашем случае используется SWI интерфейс, поэтому нас будет интересовать 3-й бит байта I2C Address (TTL Enable) — если он равен нулю, то используется фиксированное напряжение, если единице, то VCC напряжение источника питания.

Теперь рассмотрим код скетча получения байта I2C Address и бита TTL Enable и разберём его работу.

/* 
  ATSHA204 Read Config I2C Address
*/

#include <sha204_library.h>

#define ATSHA204_PIN A3

byte bufTx[SHA204_CMD_SIZE_MAX];
byte bufRx[SHA204_RSP_SIZE_MAX];

byte i2cAddr = 0;

byte slot = 0;
byte retCode = 0;

atsha204Class sha204(ATSHA204_PIN);

void setup() {
  Serial.begin(115200);
  Serial.println("ATSHA204 Read Config I2C Address start...");

  Serial.print(F("I2C Address: "));
  readConf();
  Serial.println(i2cAddr, HEX);

  Serial.print(F("Bit #3: ")); Serial.println(bitRead(i2cAddr, 3));
}

byte addr(byte slot) {
  return slot * 4;
}

void readConf() {
  slot = 4;
  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  
  i2cAddr = bufRx[SHA204_BUFFER_POS_DATA + 0];
}

void loop() {

}

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

Итак, выставляем 4-й слот, согласно даташита ATSHA204A.

  slot = 4;

Читаем данные из ATSHA204A и получаем байт i2cAddr по нулевому смещению в слоте (+ 0).

  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  
  i2cAddr = bufRx[SHA204_BUFFER_POS_DATA + 0];

И выводим на печать байт I2C Address.

  Serial.print(F("I2C Address: "));
  readConf();
  Serial.println(i2cAddr, HEX);

И третий бит TTL Enable.

  Serial.print(F("Bit #3: ")); Serial.println(bitRead(i2cAddr, 3));

Вот скриншот результата работы нашего скетча.

Третий бит (TTL Enable) равен единице, значит используется напряжение источника питания VCC.

Чтение CheckMacConfig

Байт CheckMacConfig — это байт настройки режимов работы команд CheckMac, Read и Write.

Относительно команд Read и Write:

Бит 0 управляет слотами 0 и 1
Бит 1 управляет слотами 2 и 3
Бит 2 управляет слотами 4 и 5
Бит 3 управляет слотами 6 и 7
Бит 4 управляет слотами 8 и 9
Бит 5 управляет слотами 10 и 11
Бит 6 управляет слотами 12 и 13
Бит 7 управляет слотами 14 и 15

Любая зашифрованная команда чтения/записи завершится неудачей, если значение в TempKey.SourceFlag не совпадёт с соответствующим битом в этом байте. Байт CheckMacConfig игнорируется при чтении и записи открытого текста.

Относительно команды CheckMac:

Бит 0 управляет слотом 1
Бит 1 управляет слотом 3
Бит 2 управляет слотом 5
Бит 3 управляет слотом 7
Бит 4 управляет слотом 9
Бит 5 управляет слотом 11
Бит 6 управляет слотом 13
Бит 7 управляет слотом 15

Копирование будет возможно только в том случае, если значение CheckMacSource целевого слота соответствует значению бита 2 режима команды CheckMac. Команда не будет выполнена, если бит 2 режима не соответствует TempKey.SourceFlag.

Теперь создадим скетч, который получает значение байта CheckMacConfig из конфигурационной зоны микросхемы ATSHA204A и выводит на печать все его биты. Полный код скетча ATSHA204 Read Config CheckMac:

/* 
  ATSHA204 Read Config CheckMac
*/

#include <sha204_library.h>

#define ATSHA204_PIN A3

byte bufTx[SHA204_CMD_SIZE_MAX];
byte bufRx[SHA204_RSP_SIZE_MAX];

byte checkMac = 0;

byte slot = 0;
byte retCode = 0;

atsha204Class sha204(ATSHA204_PIN);

void setup() {
  Serial.begin(115200);
  Serial.println("ATSHA204 Read Config CheckMac start...");

  Serial.print(F("CheckMac: "));
  readConf();
  Serial.println(checkMac, HEX);

  Serial.print(F("Bit #0: ")); Serial.println(bitRead(checkMac, 0));
  Serial.print(F("Bit #1: ")); Serial.println(bitRead(checkMac, 1));
  Serial.print(F("Bit #2: ")); Serial.println(bitRead(checkMac, 2));
  Serial.print(F("Bit #3: ")); Serial.println(bitRead(checkMac, 3));
  Serial.print(F("Bit #4: ")); Serial.println(bitRead(checkMac, 4));
  Serial.print(F("Bit #5: ")); Serial.println(bitRead(checkMac, 5));
  Serial.print(F("Bit #6: ")); Serial.println(bitRead(checkMac, 6));
  Serial.print(F("Bit #7: ")); Serial.println(bitRead(checkMac, 7));
}

byte addr(byte slot) {
  return slot * 4;
}

void readConf() {
  slot = 4;
  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  
  checkMac = bufRx[SHA204_BUFFER_POS_DATA + 1];
}

void loop() {

}

Получаем байт CheckMacConfig из 4-го слота по смещению 1, согласно информации из даташита.

void readConf() {
  slot = 4;
  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  
  checkMac = bufRx[SHA204_BUFFER_POS_DATA + 1];
}

И далее выводим на печать полученные данные.

  Serial.print(F("CheckMac: "));
  readConf();
  Serial.println(checkMac, HEX);

  Serial.print(F("Bit #0: ")); Serial.println(bitRead(checkMac, 0));
  Serial.print(F("Bit #1: ")); Serial.println(bitRead(checkMac, 1));
  Serial.print(F("Bit #2: ")); Serial.println(bitRead(checkMac, 2));
  Serial.print(F("Bit #3: ")); Serial.println(bitRead(checkMac, 3));
  Serial.print(F("Bit #4: ")); Serial.println(bitRead(checkMac, 4));
  Serial.print(F("Bit #5: ")); Serial.println(bitRead(checkMac, 5));
  Serial.print(F("Bit #6: ")); Serial.println(bitRead(checkMac, 6));
  Serial.print(F("Bit #7: ")); Serial.println(bitRead(checkMac, 7));

Результат работы нашего скетча:

В данном случае байт CheckMacConfig равен нулю и, соответственно, все его биты тоже равны нулю.

Чтение OTP Mode

Байт OTP Mode определяет режим работы OTP зоны памяти микросхемы ATSHA204. Возможны три варианта режима работы этой зоны:

0xAA — Режим только для чтения. Если OTP зона заблокирована, то запись всех слотов отключена, а чтение разрешено.

0x55 — Режим расхода (уменьшения). Запись в OTP зону, когда она заблокирована, приводит к тому, что биты изменяются только от единицы к нулю. Разрешено чтение всех слотов.

0x00 — Унаследованный режим. Если зона OTP заблокирована, то запись отключена, плюс чтение слотов 0 и 1 и 32-битное чтение отключено.

Код скетча чтения байта OTP Mode микросхемы ATSHA204:

/* 
  ATSHA204 Read Config OTP Mode
*/

#include <sha204_library.h>

#define ATSHA204_PIN A3

byte bufTx[SHA204_CMD_SIZE_MAX];
byte bufRx[SHA204_RSP_SIZE_MAX];

byte otpMode = 0;

byte slot = 0;
byte retCode = 0;

atsha204Class sha204(ATSHA204_PIN);

void setup() {
  Serial.begin(115200);
  Serial.println("ATSHA204 Read Config OTP Mode start...");

  Serial.print(F("OTP Mode: 0x"));
  readConf();
  Serial.println(otpMode, HEX);
}

byte addr(byte slot) {
  return slot * 4;
}

void readConf() {
  slot = 4;
  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  
  otpMode = bufRx[SHA204_BUFFER_POS_DATA + 2];
}

void loop() {

}

Здесь всё просто — читаем байт из 4-го слота

  slot = 4;

по смещению 2

  otpMode = bufRx[SHA204_BUFFER_POS_DATA + 2];

и выводим на печать значение полученного байта в шестнадцатеричном формате.

Как вы видите, OTP зона нашей микросхема работает в режиме 0xAA, то есть после блокировки будет возможно только чтение всех слотов, а их запись будет запрещена.

Чтение Selector Mode

Байт Selector Mode отвечает за режим работы селектора (Selector). Сам Selector определяет устройство, которое останется в активном режиме после выполнения команды Pause.

Если байт Selector Mode равен нулю, то селектор может быть обновлен с помощью CreateExtra, любое другое значение запрещают обновление селектора.

Текст скетча получения байта Selector Mode:

/* 
  ATSHA204 Read Config Selector Mode
*/

#include <sha204_library.h>

#define ATSHA204_PIN A3

byte bufTx[SHA204_CMD_SIZE_MAX];
byte bufRx[SHA204_RSP_SIZE_MAX];

byte selectorMode = 0;

byte slot = 0;
byte retCode = 0;

atsha204Class sha204(ATSHA204_PIN);

void setup() {
  Serial.begin(115200);
  Serial.println("ATSHA204 Read Config Selector Mode start...");

  Serial.print(F("Selector Mode: 0x"));
  readConf();
  Serial.println(selectorMode, HEX);
}

byte addr(byte slot) {
  return slot * 4;
}

void readConf() {
  slot = 4;
  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  
  selectorMode = bufRx[SHA204_BUFFER_POS_DATA + 3];
}

void loop() {

}

Согласно даташита, читаем байт из 4-го слота по смещению 3.

void readConf() {
  slot = 4;
  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  
  selectorMode = bufRx[SHA204_BUFFER_POS_DATA + 3];
}

и выводим на печать значение полученного байта.

  Serial.print(F("Selector Mode: 0x"));
  readConf();
  Serial.println(selectorMode, HEX);

Результат работы нашего скетча:

Байт Selector Mode равен нулю, значит селектор может быть обновлен с помощью CreateExtra.

Чтение Slot Configuration (0 – 15)

Slot Configuration (0 – 15) — это блоки конфигурации работы и доступа к 16-и слотам зоны данных (Data Zone) микросхемы ATSHA204A. Каждый блок состоит из 16-и битов (2-х байт), которые управляют использованием и доступом для данного конкретного слота (ключа).

Если зона данных заблокирована, то блок SlotConfig интерпретируется в соответствии с нижеприведённой таблицей. Когда Data зона разблокирована, эти ограничения не применяются и все слоты могут быть свободно записаны, но ни один из них не может быть прочитан.

Теперь создадим скетч, который получает из микросхемы ATSHA204A блок конфигурации одного из 16-и слотов данных и побитно выводит его на печать. Полный текст скетча:

/* 
  ATSHA204 Read Config Slots
*/

#include <sha204_library.h>

#define ATSHA204_PIN A3

#define SLOT_LEN 2
byte bufSlot[SLOT_LEN];

String func[] = {"ReadKey", "ReadKey", "ReadKey", "ReadKey",
                 "CheckOnly",
                 "SingleUse",
                 "EncryptRead",
                 "IsSecret",
                 "WriteKey", "WriteKey", "WriteKey", "WriteKey",
                 "WriteConf", "WriteConf", "WriteConf", "WriteConf"};

byte  slots[16] = {5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12};
byte shifts[16] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1};

#define SLOT_NUM 15

byte slot  =  slots[SLOT_NUM];
byte shift = shifts[SLOT_NUM];

atsha204Class sha204(ATSHA204_PIN);

void setup() {
  Serial.begin(115200);
  Serial.println("ATSHA204 Read Config Slots start...");

  Serial.print(F("Slot: ")); Serial.println(SLOT_NUM);

  Serial.print(F("Block: "));
  readConf();
  printBuffer(bufSlot, SLOT_LEN);
  Serial.println();

  Serial.println(F("Byte #0:"));
  for (byte i = 0; i < 8; i++) {printBit(    i, bitRead(bufSlot[0], i), func[i]);}
  Serial.println(F("Byte #1:"));
  for (byte i = 0; i < 8; i++) {printBit(8 + i, bitRead(bufSlot[1], i), func[8 + i]);}
}

void printBit(byte n, byte b, String s) {
  Serial.print(F("Bit ")); Serial.print(n); Serial.print(F(": "));
  Serial.print(b);
  Serial.print(F(" (")); Serial.print(s); Serial.println(F(")"));
}

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() {
  byte bufTx[SHA204_CMD_SIZE_MAX];
  byte bufRx[SHA204_RSP_SIZE_MAX];

  byte retCode = 0;

  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  bufSlot[0] = bufRx[SHA204_BUFFER_POS_DATA + 0 + shift*2];
  bufSlot[1] = bufRx[SHA204_BUFFER_POS_DATA + 1 + shift*2];
}

void loop() {

}

Теперь подробнее разберём его работу, опуская детали, которые уже были описаны ранее при разборе предыдущих скетчей.

Объявляем массив с комментариями по поводу назначения конкретных битов.

String func[] = {"ReadKey", "ReadKey", "ReadKey", "ReadKey",
                 "CheckOnly",
                 "SingleUse",
                 "EncryptRead",
                 "IsSecret",
                 "WriteKey", "WriteKey", "WriteKey", "WriteKey",
                 "WriteConf", "WriteConf", "WriteConf", "WriteConf"};

Далее объявляем два массива с данными о слотах и смещениях блоков данных, согласно даташита.

byte  slots[16] = {5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12};
byte shifts[16] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1};

И задаём текущий слот (блок), с которым будем работать, в данном случае это блок 15.

#define SLOT_NUM 15

Присваиваем значения соответствующим переменным.

byte slot  =  slots[SLOT_NUM];
byte shift = shifts[SLOT_NUM];

Далее получаем байты выбранного нами блока.

void readConf() {
  byte bufTx[SHA204_CMD_SIZE_MAX];
  byte bufRx[SHA204_RSP_SIZE_MAX];

  byte retCode = 0;

  retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  bufSlot[0] = bufRx[SHA204_BUFFER_POS_DATA + 0 + shift*2];
  bufSlot[1] = bufRx[SHA204_BUFFER_POS_DATA + 1 + shift*2];
}

И выводим на печать.

  Serial.print(F("Slot: ")); Serial.println(SLOT_NUM);

  Serial.print(F("Block: "));
  readConf();
  printBuffer(bufSlot, SLOT_LEN);
  Serial.println();

А также печатаем развёрнутую таблицу битов конфигурационного блока с пояснениями по их назначению.

  Serial.println(F("Byte #0:"));
  for (byte i = 0; i < 8; i++) {printBit(    i, bitRead(bufSlot[0], i), func[i]);}
  Serial.println(F("Byte #1:"));
  for (byte i = 0; i < 8; i++) {printBit(8 + i, bitRead(bufSlot[1], i), func[8 + i]);}

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

Таким же образом можно получить данные о конфигурации любого из 16-и слотов памяти, достаточно просто изменить этот номер в скетче и вписать нужное значение от 0 до 15.

#define SLOT_NUM 15

Заключение

В этой статье мы продолжили изучение работы с конфигурационной зоной микросхемы ATSHA204A, в следующей статье мы разберём примеры чтения других данных из этой зоны и подробно разберём смысл и назначение самих этих конфигурационных данных и настроек.

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

Работа с SHA-256

ATSHA204 - Обзор

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

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

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

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

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

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

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

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

ATSHA204A - Config Lock

ATSHA204A - Работа в режиме Config Lock

ATSHA204A - Работа с зонами памяти

ATSHA204A - Запись зоны OTP

ATSHA204A - Data Lock

ATSHA204A - Чтение Data и OTP зон памяти

ATSHA204A - Команда MAC

ATSHA204A - Аутентификация. Базовый блок

ATSHA204A - Аутентификация. Датчик

ATSHA204A - Криптография и команды

ATSHA204A - Команда CheckMac

ATSHA204A - Команда Nonce

ATSHA204A - Команда GenDig

ATSHA204A - Команда HMAC

ATSHA204A - Команда DeriveKey

ATSHA204A - Команда DeriveKey

ATSHA204A - nRF24 аутентификация. База

ATSHA204A - nRF24 аутентификация. Датчик

ATSHA204A - LoRa аутентификация. База

ATSHA204A - LoRa аутентификация. Датчик