Продолжим знакомство с записью конфигурационной зоны микросхемы ATSHA204A начатое в предыдущей статье. Эту часть начнём с разбора записи блоков Slot Configuration, отвечающих за режимы работы и доступа к 16-и слотам зоны данных (Data Zone).
Таблица зоны конфигурации
Для начала приведём уже знакомую вам таблицу конфигурационной зоны ATSHA204A из даташита.
Запись Slot Configuration (0–15)
Slot Configuration (0–15) — это блоки конфигурации работы и доступа к 16-и слотам зоны данных (Data Zone) микросхемы ATSHA204A. Каждый блок состоит из 16-и битов (2-х байт), которые управляют использованием и доступом для данного конкретного слота (ключа).
Если зона данных заблокирована, то блок SlotConfig интерпретируется в соответствии с нижеприведённой таблицей. Когда Data зона разблокирована, эти ограничения не применяются и все слоты могут быть свободно записаны, но ни один из них не может быть прочитан.
В качестве основы мы возьмём скетч из предыдущих статей о чтении блоков конфигурации работы и доступа к 16-и слотам зоны данных (Data Zone). Добавим в него функции записи блоков и прочие необходимые изменения и дополнения. Полный код нового скетча:
/* ATSHA204 Write Config Slots */ #include <sha204_library.h> #define ATSHA204_PIN A3 byte bufTx[SHA204_CMD_SIZE_MAX]; byte bufRx[SHA204_RSP_SIZE_MAX]; #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]; #define BUF_WRITE_LEN 4 byte bufWrite[BUF_WRITE_LEN]; byte blockNew[] = {0x00, 0xFF}; atsha204Class sha204(ATSHA204_PIN); void setup() { Serial.begin(115200); Serial.println("ATSHA204 Write Config Slots start..."); Serial.print(F("Slot: ")); Serial.println(SLOT_NUM); // Read 1 readAndPrint(); // Write setNew(blockNew); writeConfig(); // Read 2 readAndPrint(); } // Print 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(' ');} } } 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 printBits() { 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]);} } // Read byte addr(byte slot) { return slot * 4; } void readConf() { 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]; 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 readAndPrint() { readConf(); Serial.print(F("Block: ")); printBuffer(bufSlot, SLOT_LEN); Serial.println(); printBits(); } // Write void setNew(byte* buf) { bufWrite[0 + shift*2] = buf[0]; bufWrite[1 + shift*2] = buf[1]; } 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() { }
Теперь подробно разберём его работу, опуская детали, которые уже были описаны ранее при разборе предыдущих скетчей. Если вы ещё не ознакомились с предыдущими статьями этого цикла, то рекомендуем сделать прямо сейчас.
Итак, рассмотрим все наши нововведения, по сравнению с базовым скетчем чтения 16-и блоков конфигурации Data Zone.
Определяем размер и вводим новый буфер для хранения данных одного слота (4 байта). Напомним, что чтение или запись в конфигурационную зону ATSHA204A производится блоками по 4 байта.
#define BUF_WRITE_LEN 4 byte bufWrite[BUF_WRITE_LEN];
Далее вводим тестовые значения для одного из 16-и блоков конфигурации (в наших экспериментах мы будем работать с 15-м блоком).
byte blockNew[] = {0x00, 0xFF};
Если вы посмотрите на справочную таблицу из даташита, приведённую в начале этой статьи, то увидите, что по умолчанию в 15-м блоке находятся значения AF и 8F. Наша задача записать на их места байты 0x00 и 0xFF, то есть в первом случае все биты будут равны нулям (0b00000000), а во втором — единицам (0b11111111). Эти значения выбраны исключительно из наглядности и в ваших проектах могут быть любыми нужными вам.
Логика работы скетча задаётся в функции setup().
void setup() { Serial.begin(115200); Serial.println("ATSHA204 Write Config Slots start..."); Serial.print(F("Slot: ")); Serial.println(SLOT_NUM); // Read 1 readAndPrint(); // Write setNew(blockNew); writeConfig(); // Read 2 readAndPrint(); }
Сначала мы читаем (15-й) блок и выводим его значения на печать в виде байтов и отдельных битов.
// Read 1 readAndPrint();
Затем меняем нужные нам байты на новые и записываем их в микросхему ATSHA204A.
// Write setNew(blockNew); writeConfig();
И затем снова читаем конфигурационную зону микросхемы ATSHA204A для того, чтобы убедиться в правильности внесённых изменений.
// Read 2 readAndPrint();
Теперь подробно разберём нюансы записи блоков конфигурации в нашем скетче. Чтение данных из памяти осуществляется функцией readConf().
void readConf() { 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]; 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];
Это понадобилось потому, что блок конфигурации занимает 2 байта, а слот чтения/записи ATSHA204A — 4 байта, а нам для записи нужны все эти 4 байта.
Далее в дело вступает функция setNew(), которая меняет в массиве bufWrite 2 байта нужного блока на новые значения, оставляя неизменными 2 байта соседнего блока (который нам по условию задачи изменять не нужно).
void setNew(byte* buf) { bufWrite[0 + shift*2] = buf[0]; bufWrite[1 + shift*2] = buf[1]; }
И далее функция writeConfig() записывает в микросхему ATSHA204A сформированный нами массив из 4-х байт (bufWrite).
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); }
Таким образом мы меняем нужный нам блок из 2-х байт (в нашем случае 15-й) в конфигурационной зоне микросхемы ATSHA204A и записываем в него нужные нам значения.
Далее мы повторяем процедуру чтения для того, чтобы убедиться в правильности внесённых изменений.
Теперь давайте посмотрим на скриншоты работы нашего скетча. На первом скриншоте видно, что работа происходит с 15-м слотом (блоком конфигурации) и его значения по умолчанию AF и 8F, что соответствует таблице из даташита. Красным выделена информация, относящаяся к начальному состоянию памяти ATSHA204A.
Далее производится запись выбранных нами значений и снова выводится состояние 15-го блока конфигурации Data Zone. Скриншот свидетельствует, что наш скетч корректно произвёл запись нужной нам информации в выбранный блок конфигурации ATSHA204A.
В этом примере использовалась работа с 15-м блоком конфигурации, аналогичным образом вы можете работать с любым из 16-и (0–15) блоков конфигурации Data Zone.
Запись Use Flag (0–7)
Байты Use Flag определяют количество раз, когда «одноразовыe» слоты 0–7 могут использоваться перед отключением. Как и в примере записи блоков Slot Configuration, за основу скетча записи байтов Use Flag мы возьмём скетч чтения этих байтов из предыдущих статей цикла.
Немного модифицируем его и добавим функции записи нужных нам байтов. Код скетча ATSHA204 Write Config Use Flag:
/* ATSHA204 Write Config Use Flag */ #include <sha204_library.h> #define ATSHA204_PIN A3 byte bufTx[SHA204_CMD_SIZE_MAX]; byte bufRx[SHA204_RSP_SIZE_MAX]; byte useFlag = 0; byte slots[8] = {13, 13, 14, 14, 15, 15, 16, 16}; byte shifts[8] = {0, 2, 0, 2, 0, 2, 0, 2}; #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 Use Flag start..."); Serial.print(F("Slot: ")); Serial.println(SLOT_NUM); read(); setNew(newVal); writeConfig(); read(); } // Read byte addr(byte slot) { return slot * 4; } void readConf() { byte retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); useFlag = 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("Use Flag")); Serial.print(SLOT_NUM); Serial.print(F(": 0x")); readConf(); Serial.println(useFlag, HEX); } // Write 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() { }
В данном примере мы будем работать со слотом 0 (первым из восьми возможных 0–7) и зададим соответствующее определение. Вы можете поменять это значение на любое из диапазона 0–7.
#define SLOT_NUM 0
Далее определяем размер и вводим новый буфер для хранения данных одного слота размером 4 байта (чтение или запись в конфигурационную зону ATSHA204A производится блоками по 4 байта).
#define BUF_WRITE_LEN 4 byte bufWrite[BUF_WRITE_LEN];
Затем вводим новое значение для нулевого байта Use Flag. Значение 5 взято для примера и оно может быль любым из диапазона 0–255. Напомним, смысл этого значения и самого байта Use Flag — это количество раз, когда «одноразовыe» слоты могут использоваться перед отключением.
byte newVal = 5;
Логика работы скетча задаётся в функции setup()
read(); setNew(newVal); writeConfig(); read();
и состоит она в чтении значения выбранного слота из памяти микросхемы ATSHA204A, вывода в Serial нужного нам значения Use Flag, записи нового значения в память микросхемы и контрольного чтения нового значения из ATSHA204A, чтобы убедиться в успешности изменения нужного нам байта.
Чтение данных из памяти осуществляется функцией readConf()
void readConf() { byte retCode = sha204.sha204m_read(bufTx, bufRx, SHA204_ZONE_CONFIG, addr(slot)); useFlag = 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];
Изменение нужного нам байта Use Flag начинается с функции 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) значение по умолчанию 0xFF (255) заменено на 0x5 (5), то есть, другими словами, количество раз, когда «одноразовый» слот 0 может быть использован перед отключением изменилось с 255 до 5 раз.
Заключение
В этом материале из цикла статей о ATSHA204A мы рассмотрели запись блоков Slot Configuration и байтов Use Flag в конфигурационной зоне микросхемы, в следующих статьях мы продолжим эту тему, а также разберём прочие аспекты работы с ATSHA204A.
Ссылки по теме
ATSHA204 - Библиотека и примеры
ATSHA204A - Чтение зоны конфигурации 1
ATSHA204A - Чтение зоны конфигурации 2
ATSHA204A - Чтение зоны конфигурации 3
ATSHA204A - Запись конфигурации 1
ATSHA204A - Запись конфигурации 3
ATSHA204A - Запись конфигурации 4
ATSHA204A - Работа в режиме Config Lock
ATSHA204A - Работа с зонами памяти
ATSHA204A - Чтение Data и OTP зон памяти
ATSHA204A - Аутентификация. Базовый блок
ATSHA204A - Аутентификация. Датчик
ATSHA204A - Криптография и команды
ATSHA204A - nRF24 аутентификация. База
ATSHA204A - nRF24 аутентификация. Датчик