495 lines
15 KiB
Markdown
495 lines
15 KiB
Markdown
# HC32F460 BootLoader 项目架构和工作流程分析
|
|
|
|
## 1. 项目概述
|
|
|
|
### 1.1 项目简介
|
|
HC32F460 BootLoader是基于HC32F460微控制器的固件更新引导程序,采用RT-Thread Nano 3.1.5实时操作系统框架,支持通过RS485接口进行远程固件更新。
|
|
|
|
### 1.2 主要功能
|
|
- **系统引导**:检测并启动应用程序
|
|
- **固件更新**:支持远程固件下载和更新
|
|
- **通信协议**:实现自定义的固件更新协议
|
|
- **错误处理**:提供完整的更新流程错误处理
|
|
|
|
## 2. 系统架构分析
|
|
|
|
### 2.1 整体架构图
|
|
|
|
```
|
|
┌─────────────────────────────────────────────┐
|
|
│ BootLoader系统架构 │
|
|
├─────────────────────────────────────────────┤
|
|
│ 应用层 (App/) │
|
|
│ ┌─────────────┬─────────────┬─────────────┐ │
|
|
│ │ 主程序模块 │ 更新任务模块 │ LED状态模块 │ │
|
|
│ │ (main.c) │ (app_update.c)│ (app_led.c) │ │
|
|
│ └─────────────┴─────────────┴─────────────┘ │
|
|
├─────────────────────────────────────────────┤
|
|
│ 组件层 (components/) │
|
|
│ ┌─────────────┬─────────────┐ │
|
|
│ │ 协议处理模块 │ 环形缓冲区模块 │ │
|
|
│ │(update_protocol)│ (ringbuffer) │ │
|
|
│ └─────────────┴─────────────┘ │
|
|
├─────────────────────────────────────────────┤
|
|
│ 驱动层 (device/) │
|
|
│ ┌─────────────┬─────────────┐ │
|
|
│ │ Boot驱动 │ RS485驱动 │ │
|
|
│ │ (dev_boot.c)│(dev_rs485.c)│ │
|
|
│ └─────────────┴─────────────┘ │
|
|
├─────────────────────────────────────────────┤
|
|
│ 硬件抽象层 (hdl/) │
|
|
│ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │
|
|
│ │时钟 │Flash│串口 │SPI │PWM │LED │LCD │ │
|
|
│ │管理 │驱动 │驱动 │驱动 │驱动 │驱动 │驱动 │ │
|
|
│ └─────┴─────┴─────┴─────┴─────┴─────┴─────┘ │
|
|
└─────────────────────────────────────────────┘
|
|
```
|
|
|
|
### 2.2 目录结构详解
|
|
|
|
```
|
|
hc32f460_boot/
|
|
├── App/ # 应用层 - 业务逻辑实现
|
|
│ ├── main.c # 系统主程序入口
|
|
│ ├── app_led.c # LED状态指示模块
|
|
│ └── app_update.c # 固件更新核心逻辑
|
|
├── Project/ # 项目配置 - 编译和运行配置
|
|
│ └── RTE/RTOS/ # RT-Thread操作系统配置
|
|
├── components/ # 组件层 - 通用功能模块
|
|
│ ├── ringbuffer.c # 环形缓冲区实现
|
|
│ └── update_protocol.c # 更新协议处理
|
|
├── device/ # 驱动层 - 设备驱动接口
|
|
│ ├── dev_boot.c # Boot相关操作驱动
|
|
│ └── dev_rs485.c # RS485通信驱动
|
|
└── hdl/ # 硬件抽象层 - 底层硬件操作
|
|
├── hdl_clk.c # 系统时钟管理
|
|
├── hdl_flash.c # Flash存储器操作
|
|
├── hdl_usart.c # 串口通信驱动
|
|
└── ... # 其他外设驱动
|
|
```
|
|
|
|
## 3. 核心模块分析
|
|
|
|
### 3.1 主程序模块 (main.c)
|
|
|
|
#### 3.1.1 系统初始化流程
|
|
|
|
```c
|
|
int32_t main(void)
|
|
{
|
|
// 1. 禁用调试接口
|
|
JDI_Disable();
|
|
|
|
// 2. 初始化系统时钟
|
|
hdl_clk_init();
|
|
|
|
// 3. 主循环 - 协程任务调度
|
|
while (1)
|
|
{
|
|
// 喂狗操作
|
|
SWDT_FeedDog();
|
|
|
|
// 协程任务调度
|
|
pt_task_schedule();
|
|
|
|
// 电源管理
|
|
pt_task_pm();
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3.1.2 协程调度机制
|
|
|
|
```c
|
|
// 协程任务调度器
|
|
void pt_task_schedule(void)
|
|
{
|
|
for (int i = 0; i < TASK_MAX_NUM; i++) {
|
|
if (g_task_list[i].enabled && g_task_list[i].entry) {
|
|
g_task_list[i].entry(g_task_list[i].param);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3.2 固件更新模块 (app_update.c)
|
|
|
|
#### 3.2.1 更新状态机设计
|
|
|
|
```c
|
|
// 更新状态定义
|
|
typedef enum {
|
|
UPDATE_STATE_IDLE = 0, // 空闲状态
|
|
UPDATE_STATE_RECEIVING, // 接收数据状态
|
|
UPDATE_STATE_PROCESSING, // 处理数据状态
|
|
UPDATE_STATE_WRITING, // 写入Flash状态
|
|
UPDATE_STATE_VERIFYING, // 验证状态
|
|
UPDATE_STATE_COMPLETED, // 完成状态
|
|
UPDATE_STATE_ERROR // 错误状态
|
|
} update_state_t;
|
|
```
|
|
|
|
#### 3.2.2 核心数据结构
|
|
|
|
```c
|
|
// 全局更新状态结构
|
|
static struct
|
|
{
|
|
boot_para_t cfg; // Boot参数配置
|
|
uint32_t PackageRecvIndx; // 当前接收包索引
|
|
uint32_t PackageRecvBytes; // 已接收字节数
|
|
uint8_t isNeedUpdate; // 需要更新标志
|
|
uint8_t isUpdateGoing; // 更新进行中标志
|
|
} g_update;
|
|
|
|
// 接收缓冲区结构
|
|
static struct
|
|
{
|
|
uint8_t rb_pool[512]; // 环形缓冲区池
|
|
ring_buf_t rb; // 环形缓冲区实例
|
|
uint8_t frame[256]; // 帧缓冲区
|
|
int frame_len; // 帧长度
|
|
} g_recive;
|
|
```
|
|
|
|
#### 3.2.3 更新任务入口函数
|
|
|
|
```c
|
|
int app_update_entry(struct pt *pt)
|
|
{
|
|
PT_BEGIN(pt);
|
|
|
|
// 1. 读取Boot参数
|
|
dev_boot_read_param(&g_update.cfg);
|
|
|
|
// 2. 检查是否需要更新
|
|
if (g_update.cfg.UpdateFlag == APP_UPDATE_FLAG) {
|
|
g_update.isNeedUpdate = 1;
|
|
} else {
|
|
// 检查应用程序完整性
|
|
if (dev_boot_check_app()) {
|
|
uint32_t crc_rom = dev_boot_get_app_crc32(g_update.cfg.AppSize);
|
|
if (crc_rom == g_update.cfg.Crc32Check) {
|
|
g_update.isNeedUpdate = 0;
|
|
// 启动应用程序
|
|
dev_boot_run_app();
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. 如果需要更新,初始化通信
|
|
if (g_update.isNeedUpdate) {
|
|
ring_buf_init(&g_recive.rb, g_recive.rb_pool, sizeof(g_recive.rb_pool));
|
|
dev_rs485_init();
|
|
dev_rs485_rx_register(rx_callback);
|
|
update_init(send_bytes);
|
|
|
|
// 设置LED状态为准备更新
|
|
app_led_set_status(APP_LED_STATUS_UPDATE_RDY);
|
|
}
|
|
|
|
// 4. 主处理循环
|
|
while (1) {
|
|
PT_YIELD(pt);
|
|
|
|
// 处理接收数据
|
|
int len = read_frame();
|
|
|
|
if (len == 0) {
|
|
PT_DELAY_MS(pt, 20);
|
|
|
|
len = read_frame();
|
|
if (len == 0) {
|
|
if (g_recive.frame_len > 0) {
|
|
// 处理完整帧
|
|
app_led_set_status(APP_LED_STATUS_UPDATE_ING);
|
|
update_process(g_recive.frame, g_recive.frame_len);
|
|
g_recive.frame_len = 0;
|
|
} else {
|
|
// 发送更新状态请求
|
|
if (g_update.cfg.UpdateFlag == APP_UPDATE_FLAG &&
|
|
g_update.PackageRecvBytes < g_update.cfg.AppSize) {
|
|
update_send_cmd(0x02, g_update.PackageRecvIndx, g_update.cfg.PackageNum);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PT_END(pt);
|
|
}
|
|
```
|
|
|
|
### 3.3 协议处理模块 (update_protocol.c)
|
|
|
|
#### 3.3.1 协议帧格式
|
|
|
|
```c
|
|
// 协议头结构
|
|
typedef struct {
|
|
uint8_t Header; // 帧头 (0x7A)
|
|
uint8_t SlvAddr; // 从机地址
|
|
uint8_t Cmd; // 命令字
|
|
uint8_t PayloadLen; // 数据长度
|
|
} update_protocol_hd_t;
|
|
|
|
// 更新请求数据结构
|
|
typedef struct {
|
|
uint16_t PackageNum; // 总包数
|
|
uint32_t AppSize; // 应用程序大小
|
|
uint32_t AppCrc32; // 应用程序CRC32校验值
|
|
} __attribute__ ((packed)) update_protocol_req_t;
|
|
|
|
// 下载响应数据结构
|
|
typedef struct {
|
|
uint16_t PackageIndex; // 包索引
|
|
uint16_t PackageNum; // 总包数
|
|
uint8_t DataLen; // 数据长度
|
|
} __attribute__ ((packed)) update_protocol_rsp_t;
|
|
```
|
|
|
|
#### 3.3.2 CRC校验算法
|
|
|
|
```c
|
|
// Modbus CRC16校验算法
|
|
uint16_t CRC_Modbus(uint16_t wBase, uint8_t* para, uint16_t length)
|
|
{
|
|
uint16_t crc = 0xffff;
|
|
uint16_t index, i;
|
|
|
|
for (index = 0; index < length; index++) {
|
|
crc ^= para[index];
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
if (crc & 1) {
|
|
crc >>= 1;
|
|
crc ^= wBase;
|
|
} else {
|
|
crc >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return crc;
|
|
}
|
|
```
|
|
|
|
### 3.4 Boot驱动模块 (dev_boot.c)
|
|
|
|
#### 3.4.1 Flash分区定义
|
|
|
|
```c
|
|
// Flash分区配置
|
|
#define FLASH_BINFO_BASE 0x00003000 // Boot参数区起始地址
|
|
#define FLASH_BINFO_SIZE 0x00001000 // Boot参数区大小
|
|
#define FLASH_APP_BASE 0x00004000 // 应用程序区起始地址
|
|
#define FLASH_APP_SIZE 0x00070000 // 应用程序区大小
|
|
#define FLASH_SECTOR_SIZE 0x00001000 // Flash扇区大小
|
|
```
|
|
|
|
#### 3.4.2 应用程序启动流程
|
|
|
|
```c
|
|
void dev_boot_run_app(void)
|
|
{
|
|
volatile uint32_t JumpAddress;
|
|
func_ptr_t JumpToApplication;
|
|
uint32_t AppAddr = FLASH_APP_BASE;
|
|
|
|
// 检查栈指针有效性
|
|
uint32_t u32StackTop = *((__IO uint32_t*)AppAddr);
|
|
|
|
if ((u32StackTop > SRAM_BASE) && (u32StackTop <= (SRAM_BASE + SRAM_SIZE))) {
|
|
// 获取应用程序入口地址
|
|
JumpAddress = *(__IO uint32_t*)(AppAddr + 4);
|
|
JumpToApplication = (func_ptr_t)JumpAddress;
|
|
|
|
// 禁用中断
|
|
__disable_fiq();
|
|
|
|
// 设置主栈指针
|
|
__set_MSP(*(__IO uint32_t*)AppAddr);
|
|
|
|
// 跳转到应用程序
|
|
JumpToApplication();
|
|
}
|
|
}
|
|
```
|
|
|
|
## 4. 工作流程分析
|
|
|
|
### 4.1 系统启动流程
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A[系统上电] --> B[硬件初始化]
|
|
B --> C[读取Boot参数]
|
|
C --> D{应用程序有效?}
|
|
D -->|是| E[启动应用程序]
|
|
D -->|否| F[进入BootLoader模式]
|
|
F --> G[初始化通信接口]
|
|
G --> H[等待更新命令]
|
|
```
|
|
|
|
### 4.2 固件更新流程
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A[等待更新命令] --> B[接收更新开始命令]
|
|
B --> C[擦除应用程序区]
|
|
C --> D[接收数据包]
|
|
D --> E[写入Flash]
|
|
E --> F{所有包接收完成?}
|
|
F -->|否| D
|
|
F -->|是| G[验证应用程序]
|
|
G --> H{验证通过?}
|
|
H -->|是| I[系统复位]
|
|
H -->|否| J[报告错误]
|
|
J --> A
|
|
```
|
|
|
|
### 4.3 协议交互流程
|
|
|
|
#### 4.3.1 更新开始命令交互
|
|
|
|
```
|
|
主机发送:
|
|
7A 01 81 06 [PackageNum(2)][AppSize(4)][AppCrc32(4)] [CRC16(2)]
|
|
|
|
从机响应:
|
|
7A 01 01 01 [Result(1)] [CRC16(2)]
|
|
```
|
|
|
|
#### 4.3.2 数据下载命令交互
|
|
|
|
```
|
|
主机发送:
|
|
7A 01 82 05 [PackageIndex(2)][PackageNum(2)][DataLen(1)] [Data(N)] [CRC16(2)]
|
|
|
|
从机响应:
|
|
7A 01 02 04 [PackageIndex(2)][PackageNum(2)] [CRC16(2)]
|
|
```
|
|
|
|
## 5. 关键技术特性
|
|
|
|
### 5.1 协程任务调度
|
|
|
|
**优势**:
|
|
- 内存占用小,适合资源受限环境
|
|
- 实现简单,代码可读性好
|
|
- 无需复杂的上下文切换
|
|
|
|
**局限性**:
|
|
- 缺乏优先级调度机制
|
|
- 实时性相对较差
|
|
- 任务间协作需要手动管理
|
|
|
|
### 5.2 安全机制
|
|
|
|
#### 5.2.1 CRC校验
|
|
- 使用Modbus CRC16进行通信数据校验
|
|
- 应用程序使用CRC32进行完整性验证
|
|
|
|
#### 5.2.2 Flash保护
|
|
- 写操作前进行Flash解锁
|
|
- 操作完成后立即锁定Flash
|
|
- 支持扇区级别的擦除保护
|
|
|
|
### 5.3 错误恢复机制
|
|
|
|
#### 5.3.1 通信超时处理
|
|
```c
|
|
// 超时重传机制
|
|
if (g_update.cfg.UpdateFlag == APP_UPDATE_FLAG &&
|
|
g_update.PackageRecvBytes < g_update.cfg.AppSize) {
|
|
update_send_cmd(0x02, g_update.PackageRecvIndx, g_update.cfg.PackageNum);
|
|
}
|
|
```
|
|
|
|
#### 5.3.2 应用程序验证
|
|
```c
|
|
// 应用程序完整性检查
|
|
uint8_t dev_boot_check_app(void)
|
|
{
|
|
uint32_t AppAddr = FLASH_APP_BASE;
|
|
uint32_t u32StackTop = *((__IO uint32_t*)AppAddr);
|
|
|
|
// 检查栈指针是否在有效RAM范围内
|
|
if ((u32StackTop > SRAM_BASE) && (u32StackTop <= (SRAM_BASE + SRAM_SIZE))) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
## 6. 性能指标分析
|
|
|
|
### 6.1 内存使用情况
|
|
|
|
| 内存区域 | 大小 | 用途说明 |
|
|
|---------|------|----------|
|
|
| 代码段 | ~20KB | BootLoader核心代码 |
|
|
| 数据段 | ~4KB | 全局变量和缓冲区 |
|
|
| 栈空间 | ~1KB | 任务栈空间 |
|
|
| 堆空间 | ~2KB | 动态内存分配 |
|
|
|
|
### 6.2 时间性能指标
|
|
|
|
| 操作类型 | 典型时间 | 影响因素 |
|
|
|---------|----------|----------|
|
|
| 系统启动 | < 100ms | 硬件初始化时间 |
|
|
| Flash擦除 | ~100ms/扇区 | Flash芯片特性 |
|
|
| 数据编程 | ~10μs/字节 | 编程算法效率 |
|
|
| 协议处理 | < 10ms | 数据处理复杂度 |
|
|
|
|
### 6.3 可靠性指标
|
|
|
|
| 指标类型 | 目标值 | 实现方式 |
|
|
|---------|--------|----------|
|
|
| 通信误码率 | < 10⁻⁶ | CRC校验机制 |
|
|
| 更新成功率 | > 99% | 完整的错误处理 |
|
|
| 系统稳定性 | 7x24小时 | 看门狗保护 |
|
|
|
|
## 7. 扩展性和优化建议
|
|
|
|
### 7.1 架构优化建议
|
|
|
|
#### 7.1.1 任务调度改进
|
|
```c
|
|
// 建议迁移到标准RT-Thread任务调度
|
|
rt_thread_t update_thread = rt_thread_create("update",
|
|
update_task_entry,
|
|
RT_NULL,
|
|
512, 10, 20);
|
|
```
|
|
|
|
#### 7.1.2 内存管理优化
|
|
```c
|
|
// 实现内存池管理
|
|
static rt_uint8_t mempool_pool[64 * 32];
|
|
static struct rt_mempool mempool;
|
|
rt_mp_init(&mempool, "boot_mp", &mempool_pool[0], 64, 64*32, RT_IPC_FLAG_FIFO);
|
|
```
|
|
|
|
### 7.2 功能扩展建议
|
|
|
|
#### 7.2.1 支持多种更新方式
|
|
- 增加USB DFU支持
|
|
- 支持以太网更新
|
|
- 添加SD卡更新功能
|
|
|
|
#### 7.2.2 增强安全性
|
|
- 实现数字签名验证
|
|
- 支持加密传输
|
|
- 添加回滚保护机制
|
|
|
|
## 8. 总结
|
|
|
|
HC32F460 BootLoader项目采用了清晰的模块化架构设计,通过协程任务调度实现了高效的固件更新功能。项目具有以下特点:
|
|
|
|
1. **架构清晰**:分层设计,模块职责明确
|
|
2. **功能完整**:支持完整的固件更新流程
|
|
3. **可靠性高**:多重安全保护和错误恢复机制
|
|
4. **资源优化**:内存使用效率高,适合嵌入式环境
|
|
|
|
通过本文档的分析,可以为项目的后续维护、功能扩展和性能优化提供全面的技术参考。 |