# HC32F460 BootLoader 项目架构与工作流程分析 > ## ⚠️ 每次下载 Boot 前必查配置项 > > 以下配置集中在 **`source/User/Inc/bsp.h`**,每次重新下载 Boot 程序前必须核对, > 修改后 **需重新编译并烧录**,配置会由 Boot 首次运行时自动写入 Flash 参数区。 > > ### ① 当前设备版本 / 项目选择(决定本机 MAC 编码,bsp.h:62-64) > > ```c > #define GATEWAY_VER_INFO GATEWAY_VER1_0 // 版本信息 → Mac[0](Bit7固定1) > #define GATEWAY_PRJ_NUM GATEWAY_PRJ_YAXIA // 项目编号 → Mac[1:3](枚举见 bsp.h:17-26) > #define $10x0003 // 网关编号 → Mac[4:5](1~65535,按设备唯一分配) > ``` > > | 项 | 当前值 | 影响 | > | --- | --- | --- | > | GATEWAY_VER_INFO | GATEWAY_VER1_0 | 写入 MAC[0],标识网关软件版本 | > | GATEWAY_PRJ_NUM | GATEWAY_PRJ_YAXIA | 写入 MAC[1:3],标识所属项目(换项目必改) | > | GATEWAY_GW_NUM | 0x0003 | 写入 MAC[4:5],每台设备必须唯一(按网关编号分配) | > > ### ② CAT1 服务器 / Lora 配置(bsp.h:67-73) > > ```c > #define GATEWAY_SVR_ADDR0 39 // 服务器 IP[0] > #define GATEWAY_SVR_ADDR1 106 // 服务器 IP[1] > #define GATEWAY_SVR_ADDR2 103 // 服务器 IP[2] > #define GATEWAY_SVR_ADDR3 147 // 服务器 IP[3] > #define $18083 // 服务器端口 > #define GATEWAY_LORA_FREQ CH0 // Lora 中心频率(CH0~CH45,470.1MHz~492.6MHz) > ``` > > | 项 | 当前值 | 说明 | > | --- | --- | --- | > | 服务器 IP | 39.106.103.147 | CAT1 上传的默认服务器地址 | > | 服务器端口 | 8083 | CAT1 上传的默认端口 | > | GATEWAY_LORA_FREQ | CH0 | Lora 中心频率,按现场干扰/组网需要从 CH0~CH45 中选择 | > > ### ③ 默认通道配置(bsp.h:76-79) > > ```c > #define GATEWAY_MUCH CH_ETH // 主上传通道 > #define GATEWAY_AUCH CH_NULL // 辅助上传通道(-1 = 无) > #define GATEWAY_DUCH CH_CAT1 // 调试/升级通道 > #define GATEWAY_CUCH_MASK CUCH_LORA // 通讯单元通道掩码 > ``` > > | 项 | 当前值 | 说明 | > | --- | --- | --- | > | GATEWAY_MUCH | CH_ETH | 主上传通道:CH_DBG/CH_RS485_1/CH_RS485_2/CH_ETH/CH_LORA/CH_CAT1 | > | GATEWAY_AUCH | CH_NULL | 辅助上传通道,-1 表示不使用 | > | GATEWAY_DUCH | CH_CAT1 | 调试/升级通道 | > | GATEWAY_CUCH_MASK | CUCH_LORA | 通讯单元通道掩码,可多通道按位或(CUCH_CH1/CUCH_CH2/CUCH_ETH/CUCH_LORA/CUCH_CAT1) | > > **编码约定**:所有源码文件统一使用 UTF-8 编码(无 BOM),注释使用中文; > 新增/修改代码时勿以 GB2312/ANSI 保存。 ## 1. 项目概述 基于华大半导体 HC32F460KETA (Cortex-M4F) 的 BootLoader 程序,实现通过 RS485 串口对 APP 应用程序进行在线升级。升级协议遵循《传感器通用串口升级协议 V1.1》。 主要功能: - 串口在线升级:RS485 Ch1 (USART2) 作为升级通道,采用主-从应答式通信 - 设备 MAC 编码:固化在 Flash 0x4000 处,供网关 APP 读取本机身份 - APP 跳转:启动参数判断后跳转至 APP 区 (0x8000) - 参数管理:服务器/Lora/通道等默认配置由 Boot 直接写入 Flash 参数区 - 看门狗:SWDT 由 ICG 硬件启动,周期喂狗防止升级过程死机 ## 2. 硬件平台 | 项目 | 说明 | | --- | --- | | MCU | HC32F460KETA (Cortex-M4F, FPU, 512KB Flash / 192KB SRAM) | | 主频 | 内部 HRC 16MHz -> MPLL 200MHz(不使用外部晶振) | | 升级通道 | RS485 Ch1 = USART2 (PA10=RX, PA8=TX),方向控制 PC7 | | 备用串口 | RS485 Ch2 = USART3 (PB14=RX, PB12=TX),方向控制 PB13 | | 调试串口 | USART1 (PA11=RX, PA12=TX) | | 调试器 | Segger J-Link (MDK 工程配置) | ## 3. 目录结构 ``` HC32F460BootLoader/ ├── driver/ # 华大 DDL 设备驱动库 │ ├── inc/ # 外设驱动头文件 │ └── src/ # 外设驱动源文件 ├── mcu/ │ └── common/ # 芯片头文件、系统时钟初始化 (system_hc32f460.c) ├── source/ │ └── User/ # 用户应用层 │ ├── Inc/ # bsp.h / main.h / ddl_config.h │ └── Src/ # main.c / bsp.c ├── MDK/ # Keil 工程 │ ├── BootLoader.uvprojx │ ├── BootLoader.uvoptx │ ├── BootLoader_custom.sct # 自定义分散加载文件 │ └── RTE/ # Keil RTE 配置 ├── 传感器通用串口升级协议V1.1.xlsx # 升级协议规范 ├── 串口升级协议.xlsx └── README.md ``` ## 4. 架构设计 ### 4.1 分层结构 ``` ┌──────────────────────────────────────┐ │ 应用层 (source/User) │ │ main.c 升级状态机/协议解析 │ │ bsp.c 时钟/串口/Flash/看门狗 │ ├──────────────────────────────────────┤ │ 设备驱动层 (driver) │ │ hc32f460_*.c DDL 标准外设驱动 │ ├──────────────────────────────────────┤ │ MCU 层 (mcu/common) │ │ 系统时钟初始化 / 寄存器定义 │ └──────────────────────────────────────┘ ``` ### 4.2 Flash 分区(512KB) | 区域 | 地址范围 | 大小 | 说明 | | --- | --- | --- | --- | | BootLoader | 0x0000_0000 - 0x0000_7FFF | 32KB | Boot 程序 | | └ 网关MAC区 | 0x0000_4000 | 6B | 设备唯一编码(固定) | | APP | 0x0000_8000 - 0x0007_BFFF | 464KB | 应用程序 | | 参数区 | 0x0007_C000 - 0x0007_DFFF | 8KB | Boot 参数 (BootPara_t) | Flash 分区宏定义见 `source/User/Inc/bsp.h:82-93`。 ### 4.3 内存布局(SRAM 192KB) 分散加载文件 `MDK/BootLoader_custom.sct`: - 只读区 (RO):0x0000_0000,长度 32KB,含 `*(.ARM.__at_0x00004000)` MAC 段 - 可读写区 (RW/ZI):0x1FFF_8000,长度 0x2F000 ### 4.4 参数结构体 (BootPara_t) 定义见 `bsp.h:152-167`,与 GateWay APP 保持一致,由 Boot 直接写入默认配置: - `AppFlag` / `UpdateFlag` / `FirstRunFlag`:启动与升级标志 - `GwMac[6]`:网关 MAC 地址 - `SvrAddr[4]` / `SvrPort`:默认服务器 IP/端口 - `LoraFreq`:默认 Lora 中心频率 - `Much` / `Auch` / `Duch`:主/辅助/调试升级通道 - `CuchMask`:通讯单元通道掩码 ## 5. 核心模块分析 ### 5.1 设备 MAC 编码 (main.c:7-14) 固化在 Flash 0x4000 的 `GwMacConst[6]`,由宏构造: ``` Mac[0] = 0x80 | GATEWAY_VER_INFO // 版本信息 (Bit7 固定 1) Mac[1:3] = GATEWAY_PRJ_NUM // 项目编号 (3字节) Mac[4:5] = GATEWAY_GW_NUM // 网关编号 (2字节) ``` `GATEWAY_VER_INFO`、`GATEWAY_PRJ_NUM`、`GATEWAY_GW_NUM` 在 `bsp.h:62-64` 配置。 ### 5.2 串口驱动 (bsp.c) - `DbgUart_Config()`:调试串口 USART1 配置(中断优先级 2) - `RS485Ch1_Config()`:升级通道 USART2 配置(中断优先级 2) - `RS485Ch2_Config()`:备用串口 USART3 配置 - 发送时通过方向引脚切换 RS485 收发:`RS485Ch1UartSend()` 发完拉回接收态 ### 5.3 Flash 操作 (bsp.c) - `FlashWrite()`:单字编程,校验返回值 - `WriteBootPara()`:擦除扇区后写入参数 - `EraseFlash()`:仅擦除 APP 区(`APP_ADDRESS` 到 `BOOT_PARA_ADDRESS`),**不擦参数区**,边擦边喂狗 ### 5.4 看门狗 SWDT 由 ICG 硬件启动(`ddl_config.h` DDL_SWDT_ENABLE=ON),主循环每 200ms 调用 `FeedDog()` 喂狗。 ## 6. 升级工作流程 ### 6.1 启动流程 (main.c:426-478) ``` BSP_Init() // 时钟 200MHz + GPIO + RS485Ch1(500k) + SysTick(1ms) InitCrc32Table() // CRC32 查表 读 0x4000 MAC -> s_DevMac // 从固定地址读入设备编码 ReadBootPara() // 读参数区 ├─ GwMac 无效(0xFF) 首次运行 │ ├─ FirstRunFlag==0xFFFFFFFF -> BL_START_APP (直接启动APP) │ ├─ 否则 -> BL_IDLE │ └─ 写入默认参数 (MAC/服务器/Lora/通道) ├─ GwMac 有效 │ ├─ 同步 s_DevMac │ ├─ 旧参数区(0xFF)补默认值 │ ├─ AppFlag==APP_START_FLAG -> BL_START_APP (直接跳APP) │ ├─ AppFlag==APP_BOOT_UPGRADE_FLAG -> BL_START_APP (升级完成,启动后由App擦参数分区) │ ├─ UpdateFlag==APP_UPDATE_FLAG -> BL_ERASE_FLASH (续升级) │ └─ 否则 -> BL_IDLE (等待升级指令) └─ while(1): FeedDogHandler() + BootLoaderLoopHandler() ``` ### 6.2 升级状态机 (main.c:335-402) ``` BL_IDLE ── 收到 0x81 升级请求 ──> BL_RESET (20ms 后系统复位) BL_RESET ── 复位后参数判断 ──> BL_ERASE_FLASH BL_ERASE_FLASH ── 擦除完成 ──> BL_GET_DATA BL_GET_DATA ── 发 0x02 请求下一包 ──> BL_WAIT_REV BL_WAIT_REV ── 收到 0x82 ──> BL_GET_DATA (写Flash后请求下一包) BL_WAIT_REV ── 500ms 超时 ──> BL_GET_DATA_TIMEOUT BL_GET_DATA_TIMEOUT ── 重试<3次 ──> BL_GET_DATA BL_GET_DATA_TIMEOUT ── 重试>=3次 ──> BL_IDLE (清除升级标志) └─ 全部包写完 -> CRC32 校验 ├─ 成功 -> 写 AppFlag=APP_BOOT_UPGRADE_FLAG + 复位 -> BL_RESET -> 启动 APP └─ 失败 -> 清标志 -> BL_IDLE ``` ### 6.3 升级数据流 ``` 升级主机(网关APP) BootLoader(从机) │ 0x81 升级请求帧 │ │ ────────────────────────────────> │ 保存参数到Flash │ 0x01 ACK应答(载荷0x20) │ │ <──────────────────────────────── │ 复位进入升级 │ 0x02 请求数据(包索引) │ │ <──────────────────────────────── │ 擦除Flash │ 0x82 下发数据包(200字节/包) │ 写Flash │ ────────────────────────────────> │ 循环请求直至收完 │ ... │ │ │ CRC32 校验 │ │ 成功->写AppFlag->复位->启动APP ``` ### 6.4 帧格式(升级协议 V1.1) 帧头 `FrameHeader_t` (main.h:19-24): | 字段 | 长度 | 说明 | | --- | --- | --- | | Header | 1B | 帧头,固定 0x7D | | DevMac | 6B | 目标设备 MAC(全 0xFF 为广播) | | Cmd | 1B | 命令字 | | PayloadLen | 1B | 载荷长度 | 命令字 (main.h:10-16): | 命令 | 值 | 方向 | 说明 | | --- | --- | --- | --- | | UPDATE_CMD_SLAVE_RES | 0x01 | 从->主 | 应答 ACK | | UPDATE_CMD_SLAVE_REQ_DATA | 0x02 | 从->主 | 请求数据包 | | UPDATE_CMD_MASTER_REQ | 0x81 | 主->从 | 升级请求 | | UPDATE_CMD_MASTRE_RES_DATA | 0x82 | 主->从 | 下发数据 | - 帧尾:2 字节 CRC16 (Modbus, 多项式 0xA001) - CRC32 使用查表法 (多项式 0xEDB88320) 校验整个 APP 区 ### 6.5 帧接收组帧 (main.c:291-329) 中断逐字节接收,按 0x7D 帧头、第 9 字节载荷长度、`sizeof(FrameHeader_t)+PayloadLen+2` 组帧完成判断,存入 `BL.RxBuff` 并置 `BL.RxFlag`。 ### 6.6 升级完成后的参数分区擦除(App 侧执行) Boot 升级成功(CRC32 校验通过)后置 `AppFlag = APP_BOOT_UPGRADE_FLAG`(0x5A5A55A5,**每次升级均置位**)并复位; 启动判断对该标记直接放行 `BL_START_APP`,擦除动作由 APP 侧完成: ``` App GateWayInit(): 检测 AppFlag == APP_BOOT_UPGRADE_FLAG ├─ 打印 "Upgrade done, erasing parameter partition..." ├─ 擦除外部 SPI Flash 参数分区(扇区0~1,仅8KB,非全片擦除,历史日志保留) ├─ AppFlag 恢复 APP_START_FLAG 并写回 Boot 参数区 └─ 后续 ReadPara 读到空白数据 -> 自动加载 Boot 默认参数,传感器重新注册 ``` - 设计原因:升级后新固件的参数结构体布局可能变化,保留旧参数会导致字段错位 (曾引发注册表乱码、传感器无法注册)。 - 兜底机制:APP 侧参数 `SavFlag` 绑定 `PARA_LAYOUT_VER` 布局版本戳, 布局变更时旧参数自动失效回退默认值。 - 注意:每次升级后传感器注册表被清空,设备需重新注册。 ### 6.6 APP 跳转 (main.c:85-109) 校验栈顶在 SRAM 范围内后: 1. `__disable_irq()` 关闭全局中断 2. 停止 SysTick 3. 禁用并清挂起 RS485 Ch1 相关 NVIC 中断 4. `__set_MSP()` 设置主栈指针 5. 跳转 APP 复位向量 ## 7. 构建配置 - 器件:HC32F460KETA,Pack:HDSC.HC32F460.1.0.12 - 分散加载:`BootLoader_custom.sct` - 宏定义:`__DEBUG,HC32F460,USE_DEVICE_DRIVER_LIB,JEUA` - Include:driver/src、driver/inc、mcu/common、source/User/Src、source/User/Inc - DDL 模块裁剪见 `source/User/Inc/ddl_config.h` ## 8. 关键设计要点 1. **免外部晶振**:使用内部 HRC 倍频到 200MHz,降低成本与启动依赖 2. **参数区保护**:擦除 APP 区时跳过参数区,升级参数可持久保存 3. **防中断残留**:跳转 APP 前彻底清理中断环境,避免影响 APP 启动 4. **升级续传**:复位后通过 `UpdateFlag` 判断,支持掉电后重新进入升级流程 5. **广播支持**:MAC 匹配支持全 0xFF 广播升级 6. **看门狗**:擦除 Flash 等耗时操作中喂狗,防误复位