#include #include #include "flash.h" STM32_CAN Can(CAN2, DEF); volatile bool fw_update = false; volatile uint32_t fw_size = 0; volatile uint32_t fw_crc = 0; volatile uint32_t jump; static FLASH_RECORD flash_record = {0}; static uint32_t ptr_flash; // Прототипы функций void jump_to_app(); void process_can_message(const CAN_message_t &msg); void erase_flash_pages(); bool verify_firmware(); void send_ack(uint8_t status); void setup() { // Инициализация периферии Serial.setRx(HARDWARE_SERIAL_RX_PIN); Serial.setTx(HARDWARE_SERIAL_TX_PIN); Serial.begin(115200); Can.begin(); Can.setBaudRate(1000000); TIM_TypeDef *Instance = TIM2; HardwareTimer *SendTimer = new HardwareTimer(Instance); SendTimer->setOverflow(100, HERTZ_FORMAT); // 50 Hz // SendTimer->attachInterrupt(process_can_message); SendTimer->resume(); // Разрешить все ID (маска 0x00000000) Can.setFilter(0, 0, STD); // Настройка GPIO RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; GPIOC->MODER |= GPIO_MODER_MODE10_0 | GPIO_MODER_MODE11_0; GPIOC->ODR |= GPIO_ODR_OD11; // Проверка флага обновления // erase_sector(6); // flash_program_word(FLAG_BOOT,0xDEADBEEF,0); // flash_record.data_id = addr_id; // flash_record.crc = 0x6933; // flash_record.value = 0x69; // flash_record.write_ptr_now = SECTOR_6; // flash_write(SECTOR_6, &flash_record); flash_record = load_params(); /* Добавить проверку адреса, т.е во время отправки запроса прошивки по CAN мы сохраняем как флаг, так и аддрес устройства к которому будет обращатлься во время прошивки */ if(*(volatile uint32_t*)(FLAG_BOOT) == UPDATE_FLAG) { fw_update = true; GPIOC->ODR |= GPIO_ODR_OD10; // Индикация обновления erase_flash_pages(); } else { jump_to_app(); } } void loop() { if(fw_update) { GPIOC->ODR ^= GPIO_ODR_OD10; // HAL_Delay(100); CAN_message_t msg; while(Can.read(msg)) process_can_message(msg); } } void process_can_message(const CAN_message_t &msg) { switch(msg.id) { case BOOT_CAN_ID: if(msg.buf[0] == 0x01) { // Старт передачи fw_size = *(uint32_t*)&msg.buf[1]; //размер прошивки тип 4 байта fw_crc = *(uint16_t*)&msg.buf[5]; //crc ptr_flash = APP_ADDRESS; send_ack(0x01); } break; case DATA_CAN_ID: // Пакет данных if(ptr_flash < (APP_ADDRESS + fw_size)) { write_flash_page((const uint8_t*)msg.buf, msg.len); ptr_flash += msg.len; send_ack(0x02); } break; case BOOT_CAN_END: // Завершение передачи if(verify_firmware()) { erase_sector(7); // Сброс флага send_ack(0xAA); NVIC_SystemReset(); } else { send_ack(0x55); } break; } } void jump_to_app() { __disable_irq(); jump = *(volatile uint32_t*)(APP_ADDRESS + 4); void (*app_entry)(void); app_entry = (void (*)(void))jump; for (uint32_t i = 0; i < 3; i++) { NVIC->ICPR[i] = 0xFFFFFFFF; } __set_MSP(*(volatile uint32_t*)APP_ADDRESS); SCB->VTOR = APP_ADDRESS; app_entry(); } void erase_flash_pages() { FLASH_EraseInitTypeDef erase; erase.TypeErase = FLASH_TYPEERASE_SECTORS; erase.Sector = FLASH_SECTOR_2; erase.NbSectors = 4; erase.VoltageRange = FLASH_VOLTAGE_RANGE_3; uint32_t error; flash_unlock(); HAL_FLASHEx_Erase(&erase, &error); flash_lock(); } uint16_t CalculateCRC16(const uint8_t* data, uint32_t length) { uint16_t crc = 0xFFFF; // Начальное значение while (length--) { crc ^= *data++; // Обрабатываем LSB первым for (uint8_t i = 0; i < 8; i++) { if (crc & 0x0001) { // Проверяем младший бит crc = (crc >> 1) ^ 0xA001; // Полином 0x8005 (reverse) } else { crc >>= 1; } } } return crc; // Финальный XOR = 0x0000 (не требуется) } bool verify_firmware() { uint32_t calculated_crc = 0; calculated_crc = CalculateCRC16((uint8_t*)APP_ADDRESS,fw_size); if(calculated_crc != (uint16_t)fw_crc) return false; // Реализация проверки CRC // ... // return (calculated_crc == fw_crc); else return true; } void send_ack(uint8_t status) { CAN_message_t ack; ack.id = ACK_CAN_ID; ack.len = 1; ack.buf[0] = status; Can.write(ack); }