128 lines
3.7 KiB
C
128 lines
3.7 KiB
C
#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;
|
||
} |