Алгоритмы безопасной работы с flash памятью датчика ZETSENSOR
Процедура записи данных от внешнего устройства в память датчика является очень ответственной задачей. Так как при некорректной записи данных в память, датчик перестанет корректно работать.
Причины некорректной записи данных:
1. В сети находится 2 датчика с одинаковыми нодами. При попытке записи данных в один датчик, те же самые данные запишутся и на другой датчик, что приведёт к порче настроек датчика.
2. Внешнее устройство начало записывать данные на датчик. Но ввиду каких либо причин, связь случайно оборвалась (отсоединили устройство, пропало питание и т.д.). Таким образом, в память датчика могут быть записаны некорректные данные.
Возникает задача, построить алгоритм безопасной записи данных на датчик. Алгоритм должен решить следующие проблемы:
1) Датчик должен принимать только те данные, которые предназначены для него. Для идентификации принимаемых данных можно использовать 64 битный серийный номер датчика.
2) Использование принятых данных разрешено только после принятия всех данных и проверки корректности этих данных.
Первая задача решается путём добавления контрольной суммы CRC16 в каждую из подструктур основной структуры датчика. Благодаря этой контрольной суммы мы всегда можем проверить корректность текущих данных и принадлежность этих данных конкретно этому устройству.
Для решения второй задачи необходимо организовать целостность передаваемых данных. Для этого мы будем использовать младшую часть поля write_enable. Когда данные в структуре корректны это поле имеет статус “Корректные данные”. Перед записью данных мы должны выставить статус “Начало передачи данных”, обозначающий то, что значения данной структуры будут изменены. Далее записать данные. (После получения первого пакета, состояние структуры изменяется в состояние “Активная передача данных” данный статус пока не используется). После окончания записи данных выставить поле write_enable в состояние “Передача данных завершена”. Как только выставлен статус “Передача данных завершена”, датчик начинает проверять корректность полученных данных и в случае успеха записывает их в flash память. Далее выставляется статус “Корректные данные”.
Статус структуры (значение поля write_enable) | Определение данного статуса |
0 – “Корректные данные” | Структура содержит полностью корректные данные, эти данные можно использовать и обрабатывать датчиком. |
1 – “Начало передачи данных” | В данном состоянии запрещается использовать данные находящиеся в структуре датчика. Только в этом состоянии можно начинать передавать данные датчику. |
2 – “Активная передача данных” | В данном состоянии запрещается использовать данные находящиеся в структуре датчика. (Данный статус не обрабатывается в действующем алгоритме). |
3 – “Конец передачи данных” | В данном состоянии датчик должен проверить все переданные ему данные. И сбросить своё состояние в состояние “Корректные данные”. |
Изменения статусов возможно только в следующем порядке:
“Корректные данные” → “Начало передачи данных” → “Активная передача данных” → “Конец передачи данных” → “Корректные данные”
Примечания
- Необходимость выставления статуса “Начало передачи данных” заключается в обозначении того, что данные изменяются извне, а не самим датчиком.
- Необходимость выставления статуса “Конец передачи данных” заключается в том, чтобы датчик обработал полученную информацию, а не сразу перешёл в состояние “Корректные данные”. Статус “Корректные данные” выставляет только датчик (Выставление данного статуса извне запрещено прошивкой устройства).
- Возможен вариант выставления статуса “Начало передачи данных” но сами данные не были переданы (в связи с обрывом соединения или каких-либо других причин). В данном случае статус не сможет сброситься в состояние “Корректные данные”. Данную ситуацию должен обрабатывать компьютер. Так как датчик по определению не может определить были переданы все данные или нет, обрыв соединения это или задержки передачи данных. Поэтому для однозначности эту ситуацию будем обрабатывать компьютером.
- Возможен вариант что статус “Начало передачи данных” не выставился по каким-либо причинам. В данном случае все последующие данные будут игнорироваться
- Компьютеру разрешается выставлять только статусы “Начало передачи данных” или “Конец передачи данных”.
Расчёт контрольной суммы
CRC хранится в старших двух байтах поля: “название_структуры.head.write_enable”.
Важно: Заголовок структуры тоже участвует в расчёте контрольной суммы, за исключением поля CRC16 (старшая часть поля head.write_enable (long)) .
Алгоритм расчёта CRC16
unsigned short CRC16(unsigned char *pBuff, int len, short start_value)
{
unsigned char Hi = (start_value >> 8) & 0xFF;
unsigned char Lo = start_value & 0xFF;
unsigned TableIdx;
while(len—)
{
TableIdx = Hi ^ *pBuff++;
Hi = Lo ^ CRCHi[TableIdx];
Lo = CRCLo[TableIdx];
}
return (Hi << 8 | Lo);
}
unsigned short CRC;
CRC = CRC16(
(unsigned char *)&(указатель на серийный номер датчика long long) 8, MODBUS_CRC16_START_VALUE
); // Стартовое значение CRC (за этого кода определяем принадлежность кода конкретно этому устройству)
CRC = CRC16(
(unsigned char *)(указатель на начало заголовка структуры), 6, CRC
); // CRC заголовка структуры (size + struct_type + status)
CRC = CRC16(
(unsigned char *)(указатель на начало заголовка структуры) + sizeof(STRUCT_HEAD), размер структуры - sizeof(STRUCT_HEAD), CRC
); // Считаем CRC по всей подструктуре
Алгоритм записи данных на датчик
- Выставить статус “Начало передачи данных”, в структуре, данные которой изменяются.
- Начать передачу данных. Для оптимальности передачи данных, передавать нужно не всю структуру, а только изменённые поля.
- Передать пересчитанное значение CRC для передаваемой структуры.
- Выставить статус “Конец передачи данных”, в структуре, данные которой изменяются.
Алгоритм записи данных на flash
- Проверяется вся структура датчика на наличие подструктур с статусом не равным “Корректные данные”. Если такой структуры не найдено, переходим на следующий шаг, в противном случае повторяем текущий шаг.
- Проверяется вся структура на изменение данных (сравниваются значения находящиеся в flash и значения находящиеся в структуре в текущий момент времени). Структура проверяется по 2 байта за каждый проход глобального цикла. Если изменения присутствуют, переписывается вся структура находящаяся в flash. Возвращаемся к шагу 1.
Алгоритм приёма и проверки данных датчиком
- При приёме статуса “Начало передачи данных” в одну из подструктур основной структуры датчика чистим 19 сектор flash памяти и переходим на следующий шаг, в противном случае повторяем текущий шаг.
- Все получаемые данные записываются в flash память. (19 сектор).
- При приёме статуса “Конец передачи данных”, проверяется текущее значение статуса, если оно не равно статусу “Корректные данные” проверяем корректность данных, в противном случае ничего не делаем.Проверка корректности данных: Запись текущих значений подструктуры в 20 сектор. Вносим изменения из 19 сектора. Проверяем CRC в заголовке структуры. Если CRC совпало, оставляем всё как есть. Если не совпало, копируем данные из 20 сектора.
- Выставляем статус “Корректные данные”.