From f1ae83dcf1fe8d4088269648148c5e898e1d6081 Mon Sep 17 00:00:00 2001 From: lulko Date: Tue, 15 Apr 2025 16:13:08 +0300 Subject: [PATCH] Added CRC check for CAN data and FLASH data --- include/flash.h | 6 +++--- src/flash.cpp | 45 +++++++++++++++++++++++++----------------- src/main.cpp | 27 +++++++++++++++++++++++-- test/python_test_id.py | 2 +- 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/include/flash.h b/include/flash.h index eb9682b..773cfb4 100644 --- a/include/flash.h +++ b/include/flash.h @@ -1,8 +1,8 @@ #ifndef FLASH_H_ #define FLASH_H_ #include "stm32f446xx.h" - - +#include +#include /* for addr in FLASH */ @@ -66,7 +66,7 @@ void write_param(uint8_t param_id, uint8_t val); FLASH_RECORD* load_params(); void compact_page(); void flash_read(uint32_t addr,FLASH_RECORD* ptr); -bool validate_crc(FLASH_RECORD* crc,uint32_t length); +uint16_t validate_crc16(uint8_t *data,uint32_t length); void flash_write(uint32_t addr, FLASH_RECORD* record); #endif /* FLASH_H_ */ diff --git a/src/flash.cpp b/src/flash.cpp index fed53e4..c7f2ba1 100644 --- a/src/flash.cpp +++ b/src/flash.cpp @@ -116,22 +116,23 @@ uint8_t flash_read_word(uint32_t address){ } // Wait if flash -bool validate_crc(FLASH_RECORD* ptr, uint32_t length) { - uint16_t crc = 0xFFFF; // Начальное значение - uint16_t crc_value = ptr->crc; - uint8_t* data = reinterpret_cast(&crc_value); +uint16_t validate_crc16(uint8_t *data, uint32_t length) { + uint16_t crc = 0xFFFF; // Начальное значение для MODBUS while (length--) { - crc ^= *data++; // Обрабатываем LSB первым + crc ^= *data++; // XOR с очередным байтом данных for (uint8_t i = 0; i < 8; i++) { - if (crc & 0x0001) { // Проверяем младший бит + if (crc & 0x0001) { crc = (crc >> 1) ^ 0xA001; // Полином 0x8005 (reverse) } else { crc >>= 1; } } } - return crc == 0? true : false; + return crc; // Возвращаем вычисленный CRC } + + + /* read struct from FLASH */ void flash_read(uint32_t addr,FLASH_RECORD* ptr){ uint8_t* flash_ptr = (uint8_t*)addr; @@ -145,14 +146,19 @@ void compact_page(){ for(int i = (uint32_t)SECTOR_6;i < (uint32_t)SECTOR_7;i += FLASH_RECORD_SIZE) { FLASH_RECORD rec; flash_read(i,&rec); - - if (validate_crc(&rec,2)){ + uint16_t calculated_crc = validate_crc16((uint8_t*)&rec, sizeof(FLASH_RECORD) - 2); //Вычисляем CRC без последних двух байтов.STRUCT - 2BYTE__CRC + + if (calculated_crc == rec.crc && rec.data_id < PARAM_COUNT) { + // Если CRC совпадает и ID параметра валидный, сохраняем последнее значение latest[rec.data_id] = rec; } + else + //Если не совпадает продолжить читать флэш + continue; } + erase_sector(6); write_ptr = SECTOR_6; // Сброс на начало - for (int i = 0; i < PARAM_COUNT; i++) { if (latest[i].data_id != 0xFF) { // Выравнивание перед каждой записью @@ -165,12 +171,14 @@ void compact_page(){ } } + void write_param(uint8_t param_id, uint8_t val) { - FLASH_RECORD param_flash = {param_id, val, 6933}; - + FLASH_RECORD param_flash = {param_id, val}; __disable_irq(); // Запрещаем прерывания на время всей операции + + param_flash.crc = validate_crc16((uint8_t*)¶m_flash,sizeof(param_flash) - 2);//Нахождение CRC для данных, хранящихся во флэш памяти - // Проверка выравнивания ДО проверки границ сектора + // Проверка выравнивания ДО проверки границ сектора кратного 4 if (write_ptr % 4 != 0) { write_ptr += (4 - (write_ptr % 4)); } @@ -178,14 +186,13 @@ void write_param(uint8_t param_id, uint8_t val) { // Проверка переполнения с учётом выравнивания if (write_ptr + FLASH_RECORD_SIZE >= SECTOR_6_END) { compact_page(); // После compact_page write_ptr обновляется - // Повторно выравниваем после компактификации. То есть сколько не хватает для кратности + // Повторно выравниваем после функции. То есть сколько не хватает для кратности if (write_ptr % 4 != 0) { write_ptr += (4 - (write_ptr % 4)); } } - flash_write(write_ptr, ¶m_flash); - write_ptr += FLASH_RECORD_SIZE; + flash_write(write_ptr, ¶m_flash); //внутри функции итак автоматические инкрементируется указатель write_ptr на размер структуры __enable_irq(); // Разрешаем прерывания } @@ -196,8 +203,10 @@ FLASH_RECORD* load_params(){ FLASH_RECORD res; for(uint32_t addr = SECTOR_6;addr < SECTOR_6_END;addr +=FLASH_RECORD_SIZE) { flash_read(addr,&res); - if (!validate_crc(&res,2)) - break; + /* провекра CRC */ + uint16_t calculated_crc = validate_crc16((uint8_t*)&res, sizeof(FLASH_RECORD) - 2); //Вычисляем CRC без последних двух байтов.STRUCT - 2BYTE__CRC + if (calculated_crc != res.crc || res.data_id >= PARAM_COUNT) + continue; else{ latest[res.data_id] = res; } diff --git a/src/main.cpp b/src/main.cpp index 29ff725..593e5d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -157,8 +157,8 @@ void send_id() { CAN_TX_msg.id = flash_rec->value; CAN_TX_msg.buf[0] = 'I'; memcpy(&CAN_TX_msg.buf[1], &(flash_rec->value), sizeof(uint8_t)); - memcpy(&CAN_TX_msg.buf[6], (uint8_t*)&crc_h, sizeof(uint8_t)); - memcpy(&CAN_TX_msg.buf[7], (uint8_t*)&crc_l, sizeof(uint8_t)); + // memcpy(&CAN_TX_msg.buf[6], (uint8_t*)&crc_h, sizeof(uint8_t)); + // memcpy(&CAN_TX_msg.buf[7], (uint8_t*)&crc_l, sizeof(uint8_t)); Can.write(CAN_TX_msg); } @@ -191,8 +191,31 @@ void send_data() { void listen_can(const CAN_message_t &msg) { msg_id = msg.id; + /* Проверка CRC с фрейма данных */ + + // Extract CRC from message crc_h = msg.buf[6]; crc_l = msg.buf[7]; + + // Combine high and low bytes to form the received CRC + uint16_t received_crc = (crc_h << 8) | crc_l; + + // Create a temporary buffer for CRC calculation + uint8_t crc_data[6]; // First 6 bytes of message data + + // Copy message ID and data for CRC calculation + memcpy(crc_data, (uint32_t*)&msg_id, sizeof(msg_id)); + memcpy(crc_data + sizeof(msg_id), msg.buf, 2); // First 2 bytes of data + + // Calculate CRC + uint16_t calculated_crc = validate_crc16(crc_data, sizeof(crc_data)); + + // Verify CRC matches + if (calculated_crc != received_crc) { + // CRC mismatch, ignore message + return; + } + /* 0x691 69 - адрес устройства 1 - что делать дальше с данными */ diff --git a/test/python_test_id.py b/test/python_test_id.py index e313966..36e687c 100644 --- a/test/python_test_id.py +++ b/test/python_test_id.py @@ -17,7 +17,7 @@ def calculate_crc16_modbus(data: bytes) -> int: if crc & 0x0001: crc = (crc >> 1) ^ 0xA001 else: - crc >>= 1 + crc >>= 2 return crc def send_can_message(bus, can_id, data):