Files
HC32F460BootLoader/ARCHITECTURE.md
T

286 lines
12 KiB
Markdown
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.
# 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 GATEWAY_GW_NUM 0x0000 // 网关编号 → 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 | 0x0000 | 写入 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 GATEWAY_SVR_PORT 8080 // 服务器端口
> #define GATEWAY_LORA_FREQ CH3 // Lora 中心频率(CH0~CH45470.1MHz~492.6MHz
> ```
>
> | 项 | 当前值 | 说明 |
> | --- | --- | --- |
> | 服务器 IP | 39.106.103.147 | CAT1 上传的默认服务器地址 |
> | 服务器端口 | 8080 | CAT1 上传的默认端口 |
> | GATEWAY_LORA_FREQ | CH3 | 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 |
## 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)
│ ├─ 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 + 复位 -> 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 跳转 (main.c:85-109)
校验栈顶在 SRAM 范围内后:
1. `__disable_irq()` 关闭全局中断
2. 停止 SysTick
3. 禁用并清挂起 RS485 Ch1 相关 NVIC 中断
4. `__set_MSP()` 设置主栈指针
5. 跳转 APP 复位向量
## 7. 构建配置
- 器件:HC32F460KETAPackHDSC.HC32F460.1.0.12
- 分散加载:`BootLoader_custom.sct`
- 宏定义:`__DEBUG,HC32F460,USE_DEVICE_DRIVER_LIB,JEUA`
- Includedriver/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 等耗时操作中喂狗,防误复位