shuichan_old/V1.4-Chinese/STM32F103_BootLoader/Src/main.c

194 lines
5.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* BootLoader 程序入口
*
* 功能:
* 1. 上电后最先运行,初始化硬件
* 2. 检查 W25Q64 外部 Flash 中的 OTA 信息区
* 3. 根据信息区状态选择:
* - DOWNLOADED: 新固件已下载,备份当前 APP1 后写入新固件
* - INSTALLED: 已安装新固件,等待 APP 确认;超过重试次数则回退
* - ROLLBACK: 已回退到旧固件,直接跳转
* - 无有效标志: 直接跳转 APP1 运行
* 4. BootLoader 不设置 VTOR 偏移(默认0x08000000)
*
* Flash 布局 (STM32F103RCT6 256KB):
* 0x08000000 ─ BootLoader (32KB)
* 0x08008000 ─ APP1 运行区 (224KB)
*
* W25Q64 外部 Flash 布局:
* 0x000000 ─ 槽 A: 旧固件备份 (256KB)
* 0x040000 ─ 槽 B: 新固件下载 (256KB)
* 0x080000 ─ 信息区 A (4KB)
* 0x081000 ─ 信息区 B (4KB)
*/
#include "main.h"
#include "ota_boot.h"
#include "../HardWare/W25Q64/w25q64.h"
#include "../HardWare/LOG/log.h"
/* 串口句柄 */
UART_HandleTypeDef huart1; /* USART1: 调试日志输出 */
UART_HandleTypeDef huart3; /* USART3: OTA 数据通信 */
DMA_HandleTypeDef hdma_usart3_rx; /* USART3 RX DMA */
IWDG_HandleTypeDef hiwdg; /* 独立看门狗:防止擦写/拷贝流程卡死 */
/* OTA 协议接收缓冲区 */
uint8_t Rx_Flag = 0; /* 收到一帧数据标志 */
uint16_t Rx_Len = 0; /* 当前帧数据长度 */
uint8_t Rx_Buf[Rx_Max] = {0}; /* DMA 接收缓冲区 */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_IWDG_Init(void);
/**
* @brief BootLoader 主函数
*
* 启动流程:
* 硬件初始化 → 启动串口DMA → 打印横幅
* → 等待1秒OTA数据 → 读模式 → 分模式处理 → 跳转APP1
*
* @note BootLoader 不设置 VTOR 偏移(默认0x08000000)
*/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
/* USART3: 启动 DMA + IDLE 中断接收 OTA 数据帧 */
HAL_UART_Receive_DMA(&huart3, Rx_Buf, Rx_Max);
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
/* 启动独立看门狗:跳转 APP 后由 APP 继续喂狗 */
MX_IWDG_Init();
/* 核心启动逻辑 */
if (W25Q64_Init() != 0) {
log_error("[BL] W25Q64 初始化失败!");
}
Start_BootLoader();
}
/**
* @brief 系统时钟配置: HSE(8MHz) → PLL×9 → 72MHz SYSCLK
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) Error_Handler();
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) Error_Handler();
}
/**
* @brief USART1 初始化: 调试日志输出, PA9(TX)/PA10(RX), 115200-8N1
*/
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK) Error_Handler();
}
/**
* @brief USART3 初始化: OTA 数据通信, PB10(TX)/PB11(RX), 921600-8N1, DMA+IDLE
* @note 波特率与 APP 侧 4G 模块配置(AT+IPR=921600)保持一致
*/
static void MX_USART3_UART_Init(void)
{
huart3.Instance = USART3;
huart3.Init.BaudRate = 921600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK) Error_Handler();
}
/**
* @brief DMA 初始化: USART3 RX 使用 DMA1 通道3
*/
static void MX_DMA_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
}
/**
* @brief GPIO 初始化: GPIOA/USART1, GPIOB/USART3 引脚, GPIOD/其他
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef g = {0};
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_AFIO_CLK_ENABLE();
/* 关闭 JTAG保留 SWD释放 PA15/PB3/PB4 给 W25Q64 */
__HAL_AFIO_REMAP_SWJ_NOJTAG();
/* PC13(LED2):外部看门狗 TPL5010 的 DONE 喂狗引脚 */
g.Pin = GPIO_PIN_13;
g.Mode = GPIO_MODE_OUTPUT_PP;
g.Pull = GPIO_NOPULL;
g.Speed = GPIO_SPEED_FREQ_LOW; /* PC13 驱动能力弱,只能低速 */
HAL_GPIO_Init(GPIOC, &g);
}
/**
* @brief 独立看门狗初始化: LSI(~40kHz) / 256分频 / 重载4095 → 超时约26s
* @note LSI 实际频率 30~60kHz 漂移,最短超时约 17s
* 单个最长阻塞操作W25Q64 忙等待 5s远小于该值
*/
static void MX_IWDG_Init(void)
{
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_256;
hiwdg.Init.Reload = 4095;
if (HAL_IWDG_Init(&hiwdg) != HAL_OK) Error_Handler();
}
void Error_Handler(void)
{
/* 初始化失败:停在这里,避免带着未就绪的硬件继续运行 */
__disable_irq();
while (1)
{
}
}