#include "boot_can.h" CAN_HandleTypeDef hcan_boot; /** * @brief Инициализация CAN для бутлоадера (по defines) */ void MX_BOOT_CAN_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; CAN_FilterTypeDef sFilterConfig; /* Включаем тактирование */ __RCC_CAN_BOOT_CLK_ENABLE(); __RCC_CAN_PORT_CLK_ENABLE(); /* Настройка пинов RX/TX */ GPIO_InitStruct.Pin = CAN_PIN_RX; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(CAN_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = CAN_PIN_TX; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(CAN_PORT, &GPIO_InitStruct); /* Настройка CAN */ hcan_boot.Instance = CAN_BOOT; hcan_boot.Init.Prescaler = CAN_SPEED_PRESCALER; hcan_boot.Init.Mode = CAN_MODE; hcan_boot.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan_boot.Init.TimeSeg1 = CAN_SPEED_BS1; hcan_boot.Init.TimeSeg2 = CAN_SPEED_BS2; hcan_boot.Init.TimeTriggeredMode = DISABLE; hcan_boot.Init.AutoBusOff = DISABLE; hcan_boot.Init.AutoWakeUp = DISABLE; hcan_boot.Init.AutoRetransmission = ENABLE; hcan_boot.Init.ReceiveFifoLocked = DISABLE; hcan_boot.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan_boot) != HAL_OK) { Error_Handler(); } /* Настройка фильтра: пропускать все сообщения */ sFilterConfig.FilterBank = 0; sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterIdHigh = 0x0000; sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000; sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; sFilterConfig.FilterActivation = ENABLE; if (HAL_CAN_ConfigFilter(&hcan_boot, &sFilterConfig) != HAL_OK) { Error_Handler(); } /* Запускаем CAN */ if (HAL_CAN_Start(&hcan_boot) != HAL_OK) { Error_Handler(); } } // ----------------------------- // CAN: приём страницы + CRC с таймаутом // ----------------------------- void Bootloader_CAN_Receive_Page(Bootloader_t *bl) { uint16_t bytes_received = 0; uint8_t crc_buf[4]; CAN_RxHeaderTypeDef canHeader; uint8_t canData[8]; uint32_t start_tick = HAL_GetTick(); // Приём данных страницы while(bytes_received < PAGE_SIZE) { if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0) { if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK) { uint8_t len = canHeader.DLC; if(bytes_received + len > PAGE_SIZE) len = PAGE_SIZE - bytes_received; memcpy(&bl->fw_buffer[bytes_received], canData, len); bytes_received += len; start_tick = HAL_GetTick(); // сброс таймера } } // проверка таймаута if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) { bl->state = BL_STATE_ERROR; return; } } // Приём CRC (следующий CAN пакет) while(1) { if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0) { if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK) { // первые 4 байта = CRC bl->fw_crc = (canData[0] << 24) | (canData[1] << 16) | (canData[2] << 8) | canData[3]; break; } } if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) { bl->state = BL_STATE_ERROR; return; } } bl->fw_len = bytes_received; bl->state = BL_STATE_IDLE; }