PDA

Просмотр полной версии : КОнтрольная сумма (CRC16) Библиотека MEM. Проверка целостности сохраняемых данных



RomeoVar
03.09.2021, 23:41
Прошу помочь советом, кто решал подобную задачу
Есть массив структурированных данных (конфигурационные данные для использования в программе). Сразу замечу что структура весьма сложная. Данный массив сохраняется в файл (хотел использовать рецепты, но в SP14 в них нельзя сохранить переменную с типом LTIME). Далее при запуске контроллера приложение проверяет наличие данных конфигурационных файлов. Если файлы есть переменные программы заполняются значениями из файла, если нет - значениями по умолчанию из RETAIN памяти.
Для контроля целостности данных в конец каждого элемента структуры массива я добавить переменую с CRC - кодом (wCRC16Val). Естественно при расчете CRC я должен исключить эту переменную, т.е. уменьшить размер блока на величину переменной. для вычислений я использую MEM.CRC16_standard. ПРимерно так:

GVL.stRecipies[bRecipeIndexTmp].wCRC16Val := MEM.CRC16_standard(pMemoryBlock := ADR(GVL.stRecipies[bRecipeIndexTmp]), uiLength := SIZEOF(GVL.stRecipies[bRecipeIndexTmp])-SIZEOF(GVL.stRecipies[bRecipeIndexTmp].wCRC16Val));

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

Посоветуйте, как выкрутиться? Сохранять CRC в отдельный файл не очень хочется.

Евгений Кислов
04.09.2021, 08:47
но я же этот блок исключил

Нет, не исключили. Вы, вероятно, считаете, что wCRC16Val занимает последние 2 байта структуры - но из-за выравнивания памяти (https://en.wikipedia.org/wiki/Data_structure_alignment) это может быть не так.
Управлять выравниванием можно с помощью атрибута pack_mode:
https://help.codesys.com/webapp/_cds_pragma_attribute_pack_mode;product=codesys;ve rsion=3.5.17.0

Добавление в объявлении структуры атрибута со значением 0 должно позволить вам достичь ожидаемого результата.

RomeoVar
04.09.2021, 22:01
Я и думал о выравнивании, только не добрался проверить.

Я немного схитрил - делаю так:


wCRC16_RCP := GVL.stRecipies[bRecipeIndexTmp].wCRC16Val;
GVL.stRecipies[bRecipeIndexTmp].wCRC16Val := 0;
wCRC16_StdTmp :=
MEM.CRC16_standard
(
pMemoryBlock := ADR(GVL.stRecipies[bRecipeIndexTmp]),
uiLength := SIZEOF(GVL.stRecipies[bRecipeIndexTmp])
);
IF wCRC16_StdTmp <> wCRC16_RCP THEN


Смысл, я думаю понятен.
ЕЩе попробую с атрибутом
Спасибо