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

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

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

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

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

Запись Update Count (0–7)

Байты Update Count показывают сколько раз слоты 0–7 были обновлены с помощью DeriveKey. За основу скетча записи байтов Update Count мы возьмём скетч их чтения из предыдущих статей цикла. Немного модифицируем его и добавим нужные нам функции. Код скетча ATSHA204 Write Update Count:

/* 
  ATSHA204 Write Config Update Count
*/

#include <sha204_library.h>

#define ATSHA204_PIN A3

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

byte updateCount = 0;

byte  slots[8] = {13, 13, 14, 14, 15, 15, 16, 16};
byte shifts[8] = {1, 3, 1, 3, 1, 3, 1, 3};

#define SLOT_NUM 0

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

#define BUF_WRITE_LEN 4
byte bufWrite[BUF_WRITE_LEN];

byte newVal = 5;

atsha204Class sha204(ATSHA204_PIN);

void setup() {
  Serial.begin(115200);
  Serial.println("ATSHA204 Write Config Update Count start...");

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

  read();

  setNew(newVal);
  writeConfig();

  read();
}

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

void readConf() {
  byte retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  updateCount = bufRx[SHA204_BUFFER_POS_DATA + shift];

  bufWrite[0] = bufRx[SHA204_BUFFER_POS_DATA + 0];
  bufWrite[1] = bufRx[SHA204_BUFFER_POS_DATA + 1];
  bufWrite[2] = bufRx[SHA204_BUFFER_POS_DATA + 2];
  bufWrite[3] = bufRx[SHA204_BUFFER_POS_DATA + 3];
}

void read() {
  Serial.print(F("Update Count"));
  Serial.print(SLOT_NUM);
  Serial.print(F(": 0x"));
  readConf();
  Serial.println(updateCount, HEX);
}


void setNew(byte b) {
  bufWrite[shift] = b;
}

void writeConfig() {
  byte retCode = sha204.sha204m_execute(SHA204_WRITE,
                                        SHA204_ZONE_CONFIG, slot,
                                        4, bufWrite,
                                        0, NULL,
                                        0, NULL,
                                        WRITE_COUNT_SHORT, bufTx,
                                        WRITE_RSP_SIZE,    bufRx);
}

void loop() {

}

Вначале задаём номера слотов и смещений байтов Update Count в конфигурационной зоне микросхемы ATSHA204A, согласно даташита (см. таблицу в начале статьи).

byte  slots[8] = {13, 13, 14, 14, 15, 15, 16, 16};
byte shifts[8] = {1, 3, 1, 3, 1, 3, 1, 3};

В данном примере мы будем работать со слотом 0 (первым из восьми возможных 0–7) и зададим соответствующее определение. Вы можете поменять это значение на любое из диапазона 0–7.

#define SLOT_NUM 0

Далее определяем размер и вводим новый буфер для хранения данных одного слота размером 4 байта (чтение или запись в конфигурационную зону ATSHA204A производится блоками по 4 байта).

#define BUF_WRITE_LEN 4
byte bufWrite[BUF_WRITE_LEN];

Затем вводим новое значение для нулевого байта Update Count. Значение 5 взято для примера и оно может быль любым из диапазона 0–255.

byte newVal = 5;

Логика работы скетча задаётся в функции setup()

  read();

  setNew(newVal);
  writeConfig();

  read();

и состоит она в чтении значения выбранного слота из памяти микросхемы ATSHA204A, вывода в Serial нужного нам значения Update Count, записи нового значения в память микросхемы и контрольного чтения нового значения из ATSHA204A, чтобы убедиться в успешности изменения нужного нам байта.

Чтение данных из памяти осуществляется функцией readConf()

void readConf() {
  byte retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  updateCount = bufRx[SHA204_BUFFER_POS_DATA + shift];

  bufWrite[0] = bufRx[SHA204_BUFFER_POS_DATA + 0];
  bufWrite[1] = bufRx[SHA204_BUFFER_POS_DATA + 1];
  bufWrite[2] = bufRx[SHA204_BUFFER_POS_DATA + 2];
  bufWrite[3] = bufRx[SHA204_BUFFER_POS_DATA + 3];
}
в которую мы добавили блок заполнения массива bufWrite.
  bufWrite[0] = bufRx[SHA204_BUFFER_POS_DATA + 0];
  bufWrite[1] = bufRx[SHA204_BUFFER_POS_DATA + 1];
  bufWrite[2] = bufRx[SHA204_BUFFER_POS_DATA + 2];
  bufWrite[3] = bufRx[SHA204_BUFFER_POS_DATA + 3];

Изменение нужного нам байта Update Count начинается с функции setNew(), которая записывает новое значение байта на соответствующее место в прочитанном слоте (пока только в массиве bufWrite).

void setNew(byte b) {
  bufWrite[shift] = b;
}

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

void writeConfig() {
  byte retCode = sha204.sha204m_execute(SHA204_WRITE,
                                        SHA204_ZONE_CONFIG, slot,
                                        4, bufWrite,
                                        0, NULL,
                                        0, NULL,
                                        WRITE_COUNT_SHORT, bufTx,
                                        WRITE_RSP_SIZE,    bufRx);
}

Затем осуществляется повторное чтение памяти микросхемы для контроля правильности произведённых изменений.

  read();

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

В слоте 0 (из диапазона 0–7) значение по умолчанию 0x0 (0) заменено на 0x5 (5).

Запись Last Key Use (0–15)

Байты Last Key Use используются для ограничения использования слотов, каждый единичный бит представляет оставшееся использование. Применяется только в том случае, если 5-й бит SlotConfig (Single Use) установлен в единицу.

В отличие от предыдущих скетчей, в которых изменение данных производилось в каком-либо отдельном слоте, здесь мы разберём пример серийного изменения сразу всего массива байтов Last Key Use. Полный код скетча Write Config Last Key Use:

/* 
  ATSHA204 Write Config Last Key Use
*/

#include <sha204_library.h>

#define ATSHA204_PIN A3

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

byte lastKeyUse = 0;

byte  slots[] = {17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20};
byte shifts[] = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3};

byte news[4][4] = {
  { 0,  1,  2,  3},
  { 4,  5,  6,  7},
  { 8,  9, 10, 11},
  {12, 13, 14, 15}
};

byte defs[4][4] = {
  {0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF}
};

#define SLOT_NUM 0

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

#define BUF_WRITE_LEN 4
byte bufWrite[BUF_WRITE_LEN];

atsha204Class sha204(ATSHA204_PIN);

void setup() {
  Serial.begin(115200);
  Serial.println(F("ATSHA204 Write Config Last Key Use start..."));

  Serial.println("Old:");
  read();

  write();

  Serial.println("New:");
  read();
}

// Read

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

void readConf() {
  byte retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot));
  lastKeyUse = bufRx[SHA204_BUFFER_POS_DATA + shift];
}

void read() {
  for (byte i = 0; i < 16; i++) {
    slot  =  slots[i];
    shift = shifts[i];
  
    Serial.print(F("Last Key Use"));
    Serial.print(i);
    Serial.print(F(": 0x"));
    readConf();
    Serial.println(lastKeyUse, HEX);
  }
}

// Write

void setNew(byte row) {
  bufWrite[0] = news[row][0];
  bufWrite[1] = news[row][1];
  bufWrite[2] = news[row][2];
  bufWrite[3] = news[row][3];
}

void setDef(byte row) {
  bufWrite[0] = defs[row][0];
  bufWrite[1] = defs[row][1];
  bufWrite[2] = defs[row][2];
  bufWrite[3] = defs[row][3];
}

void writeConfig(byte slt) {
  byte retCode = sha204.sha204m_execute(SHA204_WRITE,
                                        SHA204_ZONE_CONFIG, slt,
                                        4, bufWrite,
                                        0, NULL,
                                        0, NULL,
                                        WRITE_COUNT_SHORT, bufTx,
                                        WRITE_RSP_SIZE,    bufRx);
}

void write() {
  for (byte i = 0; i < 4; i++) {
    setNew(i);
    //setDef(i);
    writeConfig(i + 17);
  }
}

void loop() {

}

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

Вначале мы объявляем массив news для хранения всех 16-и новых значений байтов Last Key Use. Массив будет многомерным, поскольку у нас есть 4 слота по 4 байта в каждом слоте. Для примера в качестве новых значений мы взяли последовательность от 0 (0x0) до 15 (0xF), в реальных проектах вам нужно будет заменить эти значения на требуемые вам.

byte news[4][4] = {
  { 0,  1,  2,  3},
  { 4,  5,  6,  7},
  { 8,  9, 10, 11},
  {12, 13, 14, 15}
};

Также мы объявляем массив defs для хранения значения байтов Last Key Use по умолчанию (на случай, если вы захотите восстановить исходное состояние памяти своей микросхемы ATSHA204A).

byte defs[4][4] = {
  {0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF}
};

Далее определяем размер и вводим новый буфер для хранения данных одного слота размером 4 байта (чтение или запись в конфигурационную зону ATSHA204A производится блоками по 4 байта).

#define BUF_WRITE_LEN 4
byte bufWrite[BUF_WRITE_LEN];

Логика работы скетча задаётся в функции setup()

  Serial.println("Old:");
  read();

  write();

  Serial.println("New:");
  read();

и состоит она в чтении всех значений Last Key Use из памяти микросхемы ATSHA204A, вывода их в Serial, записи массива новых значений в память микросхемы и контрольного чтения из памяти ATSHA204A, чтобы убедиться в успешности произведённых нами изменений.

Всю работу по организации записи новых значений Last Key Use осуществляет функция write()

void write() {
  for (byte i = 0; i < 4; i++) {
    setNew(i);
    //setDef(i);
    writeConfig(i + 17);
  }
}

где в цикле перебираются 4 слота значений Last Key Use и записываются в память новые значения из массива news. Подстановка новых значений происходит по 4 байта в функции setNew()

void setNew(byte row) {
  bufWrite[0] = news[row][0];
  bufWrite[1] = news[row][1];
  bufWrite[2] = news[row][2];
  bufWrite[3] = news[row][3];
}

а непосредственно сама запись осуществляется функцией writeConfig()

void writeConfig(byte slt) {
  byte retCode = sha204.sha204m_execute(SHA204_WRITE,
                                        SHA204_ZONE_CONFIG, slt,
                                        4, bufWrite,
                                        0, NULL,
                                        0, NULL,
                                        WRITE_COUNT_SHORT, bufTx,
                                        WRITE_RSP_SIZE,    bufRx);
}

«Магическая» цифра 17

    writeConfig(i + 17);

обусловлена расположением в памяти микросхемы ATSHA204A слотов байтов Last Key Use (см. вышеприведённую таблицу конфигурационной зоны из даташита).

И в результате мы можем видеть успешную замену всего массива байтов Last Key Use на нужные нам.

И, как уже было отмечено выше, вы можете изменить значения массива news на нужные вам и «зашить» эти данные Last Key Use в память вашей микросхемы ATSHA204A.

Заключение

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

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

Работа с SHA-256

ATSHA204 - Обзор

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

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

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

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

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

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

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

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

ATSHA204A - Config Lock

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

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

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

ATSHA204A - Data Lock

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

ATSHA204A - Команда MAC

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

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