#include "boot_uart.h" UART_HandleTypeDef huart_boot; /** * @brief Инициализация UART для бутлоадера * @note Использует USART3, PB10 (TX), PB11 (RX) */ void MX_BOOT_UART_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Включаем тактирование */ __RCC_UART_BOOT_CLK_ENABLE(); __RCC_UART_PORT_CLK_ENABLE(); /* Настройка GPIO TX/RX */ GPIO_InitStruct.Pin = UART_PIN_TX | UART_PIN_RX; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(UART_PORT, &GPIO_InitStruct); /* Настройка UART */ huart_boot.Instance = UART_BOOT; huart_boot.Init.BaudRate = UART_SPEED; huart_boot.Init.WordLength = UART_WORDLENGTH_8B; huart_boot.Init.StopBits = UART_STOPBITS_1; huart_boot.Init.Parity = UART_PARITY_NONE; huart_boot.Init.Mode = UART_MODE_TX_RX; huart_boot.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart_boot.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart_boot) != HAL_OK) { Error_Handler(); // твоя функция обработки ошибок } } // ----------------------------- // UART: приём страницы + CRC // ----------------------------- void Bootloader_UART_Receive_Page(Bootloader_t *bl) { uint16_t bytes_received = 0; uint8_t crc_buf[4]; HAL_StatusTypeDef res; uint32_t start_tick = HAL_GetTick(); // старт таймера // Приём данных страницы while(bytes_received < PAGE_SIZE) { uint8_t byte = 0; res = HAL_UART_Receive(bl->huart, &byte, 1, 100); // блокирующий приём 100ms if(res == HAL_OK) { bl->fw_buffer[bytes_received++] = byte; start_tick = HAL_GetTick(); // сброс таймера при успешном приёме } else { // проверка таймаута if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) { bl->state = BL_STATE_ERROR; // превышен таймаут return; } // иначе просто ждем следующего байта } } // Приём CRC (4 байта) for(uint8_t i = 0; i < 4; i++) { res = HAL_UART_Receive(bl->huart, &crc_buf[i], 1, 100); if(res == HAL_OK) { start_tick = HAL_GetTick(); // сброс таймера } else { if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS) { bl->state = BL_STATE_ERROR; return; } } } // Сохраняем CRC в структуру bl->fw_crc = (crc_buf[0] << 24) | (crc_buf[1] << 16) | (crc_buf[2] << 8) | crc_buf[3]; bl->fw_len = bytes_received; bl->state = BL_STATE_IDLE; }