Files
HC32F460BootLoader/ARCHITECTURE.md
T

12 KiB
Raw Blame History

HC32F460 BootLoader 项目架构与工作流程分析

⚠️ 每次下载 Boot 前必查配置项

以下配置集中在 source/User/Inc/bsp.h,每次重新下载 Boot 程序前必须核对, 修改后 需重新编译并烧录,配置会由 Boot 首次运行时自动写入 Flash 参数区。

① 当前设备版本 / 项目选择(决定本机 MAC 编码,bsp.h:62-64

#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

#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

#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_INFOGATEWAY_PRJ_NUMGATEWAY_GW_NUMbsp.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_ADDRESSBOOT_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 等耗时操作中喂狗,防误复位