初始版本
This commit is contained in:
@@ -0,0 +1,495 @@
|
||||
# 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. **资源优化**:内存使用效率高,适合嵌入式环境
|
||||
|
||||
通过本文档的分析,可以为项目的后续维护、功能扩展和性能优化提供全面的技术参考。
|
||||
Reference in New Issue
Block a user