/* * bootloader.c * * Created on: 2022-4-24 * Author: Administrator */ #include "bootloader.h" #include "flash.h" #include "instruments.h" #include "stdio.h" #include "watchdog.h" #include "sev_usart.h" #include "LCD.h" static unsigned char head_buf[MSGLEN]={0}; unsigned char bin_buf[FRAME_SIZE]={0}; static unsigned char src_code[BIN_FILE_FRAME_SIZE]={0,0}; static unsigned char checkCnt = 0; static unsigned char MsgCnt = 0; static int infocrc_error = 0; // 信息段中92个有效字节的CRC校验出错 static int flashW_error = 0; //flash写入错误 static int boot_err_info = 0; //写flash过程中出现过错误 static int uart_Timeout_error = 0; //串口接收超时 static int Framecrc_error = 0; //帧尾CRC校验错误 static int uart_RecCnt_error = 0; //帧数接收错误 enum updata_flag updata_complete; //升级完成标志 uint32_t *const updataFlag = (uint32_t*)(0x10000000); #pragma pack(push,1) boot_shot_header head_info; #pragma pack(pop) extern struct rt_ringbuffer rb_usart2_rx; //字符串常量的定义 unsigned char state_info[][20]= { {"state_null"}, {"State_Pre"} , {"State_Check"} , {"State_Erease_Write"} , {"State_Crc_Record"} , {"state_Done"} , {"State_none"},//不需要升级 }; unsigned char *boot_error[]={ "err_time_out", "err_platform", "err_3times", "err_flash_write", "err_crc", "err_flash", "err_flash_bad", "err_not_first", }; /*---------------------------------升级数据协议--------------------------------- 7F 7E 00 CRC16 //MCU开机启动间隔一秒发送重启成功进入boot指令; 7F 7E 01 XX XX YY YY ... ... CRC16 //模块回复总包数 当前包数 数据,每包有效数据4096字节,每一包数据前面都有两个标签一个是总包数,一个是当前包序号 7F 7E 02 01 CRC16 //MCU接收成功 7F 7E 02 00 CRC16 //MCU接收失败 7F 7E 03 CRC16 //接收完成 */ uint8_t com_string[4][14]={ {0x55,0xAA,0x01,0x00,0x0c,0x01,0x00,0x02,0x00,0x00,0x00,0,}, {0x55,0xAA,0x01,0x00,0x0d,0x01,0x00,0x02,0x01,0x02,0x01,0,0,}, {0x55,0xAA,0x01,0x00,0x0d,0x01,0x00,0x02,0x01,0x02,0x00,0,0,}, {0x55,0xAA,0x01,0x00,0x0c,0x01,0x00,0x02,0x00,0x03,0x00,0,}, }; //字符串常量的定义 static uint32_t CRCAll = 0; unsigned char Date[10]=__TIME__;//记录升级日期 uint8
时间: 2025-07-06 14:43:14 浏览: 11
<think>好的,我现在需要处理用户关于嵌入式系统中Bootloader实现代码解析的查询,特别是涉及CRC校验、协议和数据传输的部分。首先,我得回顾用户提供的引用内容,看看有哪些相关信息可以利用。
用户提到的引用[2]和[3]提到了YMODEM协议,使用CRC校验确保数据传输的完整性。引用[1]详细说明了STM32的硬件CRC外设,这可能对代码实现有帮助。引用[4]和[5]讨论了U-Boot和Bootloader的通用性以及更新问题,这些背景信息可能对整体理解有帮助。
用户需要代码示例或解析,所以我的回答应该包含具体的实现步骤,比如初始化硬件CRC、数据接收处理、CRC验证,以及跳转应用程序的部分。可能需要分段解释每个部分的功能,并给出代码片段。同时,要确保代码符合用户提到的YMODEM协议和CRC校验的应用,如引用[2][3]所述。
另外,用户要求使用中文回答,行内公式用$...$,独立公式用$$...$$。虽然问题主要涉及代码和协议,但如果有数学表达式,比如CRC计算,可能需要应用这些格式。例如,CRC多项式如$CRC-16-CCITT$,可以写成行内公式。
需要注意引用文献的正确标注,比如在提到STM32的硬件CRC时引用[^1],YMODEM协议部分引用[^2][^3],U-Boot引用[^4],Bootloader更新引用[^5]。
接下来,我需要组织回答的结构。首先概述Bootloader的关键模块,然后分点解析每个模块,包括代码示例和解释。之后生成相关问题,引导用户深入探讨。
在代码部分,可能需要展示初始化CRC、数据接收、校验处理以及跳转的伪代码或简化代码。例如,使用STM32的硬件CRC库函数,如HAL_CRC_Calculate(),如引用[1]提到的。同时,YMODEM协议的数据帧结构,如引用[2]中提到的SOH、包号、数据、CRC校验等字段,需要在代码解析中体现。
在数据传输部分,要强调错误检测和重传机制,如引用[3]所述,当CRC校验失败时请求重发数据包。
最后,生成的相关问题需要涵盖性能优化、协议对比、错误处理、安全机制和硬件CRC应用等方面,帮助用户进一步探索。
现在需要确保所有引用正确,代码示例符合用户的需求,并且语言清晰易懂。同时检查是否有遗漏的关键点,比如Bootloader的存储位置(引用[5]提到的被保护区域)以及UDS服务可能的相关性,但用户主要关注的是代码实现,所以可能不需要深入讨论UDS。
总结,回答应分为几个部分:关键模块概述、代码解析(包括CRC、协议、数据传输、跳转应用)、相关问题。每个部分结合引用内容,确保信息准确,并且代码示例贴合实际应用场景。</think>### 嵌入式 Bootloader 实现代码解析(CRC 校验、协议、数据传输)
#### 1. Bootloader 关键模块概述
嵌入式 Bootloader 实现通常包含以下核心模块:
- **通信协议**:如 YMODEM 协议,用于通过串口传输固件数据[^2]。
- **CRC 校验**:确保数据传输完整性,硬件 CRC 外设可加速计算(如 STM32 的 CRC 模块)。
- **数据写入与验证**:将接收的固件写入 Flash,并校验写入结果。
- **应用程序跳转**:通过函数指针跳转到用户程序入口。
---
#### 2. 代码解析与示例
##### (1) CRC 校验实现
**硬件 CRC 初始化(STM32 示例)**
```c
// 启用 CRC 外设时钟
__HAL_RCC_CRC_CLK_ENABLE();
// 计算数据块的 CRC 值
uint32_t Calculate_CRC(uint32_t *data, uint32_t len) {
return HAL_CRC_Calculate(&hcrc, data, len);
}
```
CRC 校验值用于验证 Flash 完整性(如 IEC60335 要求)。接收数据时,对比发送方和接收方的 CRC 值,若不一致则触发重传。
---
##### (2) YMODEM 协议处理
**数据帧结构解析**
YMODEM 数据帧包含以下字段:
```
| 帧头(SOH/STX) | 包号 | 包号反码 | 数据(128/1024 字节) | CRC 校验(2 字节) |
```
**关键代码逻辑**
```c
// 接收数据帧并解析
uint8_t ymodem_receive_packet(uint8_t *buffer) {
// 1. 读取帧头(SOH 或 STX)
uint8_t header = uart_read_byte();
// 2. 读取包号及反码,验证一致性
uint8_t pkg_num = uart_read_byte();
uint8_t pkg_num_inv = uart_read_byte();
if (pkg_num != (0xFF - pkg_num_inv)) return ERROR;
// 3. 读取数据块
uint16_t data_len = (header == SOH) ? 128 : 1024;
uart_read_bytes(buffer, data_len);
// 4. 计算 CRC 并校验
uint16_t received_crc = (uart_read_byte() << 8) | uart_read_byte();
uint16_t calculated_crc = Calculate_CRC((uint32_t*)buffer, data_len/4);
if (received_crc != calculated_crc) return CRC_ERROR;
return SUCCESS;
}
```
若校验失败,发送 `NAK` 请求重传[^3]。
---
##### (3) 固件写入与跳转
**Flash 写入与验证**
```c
void Write_Firmware(uint32_t addr, uint8_t *data, uint32_t len) {
HAL_FLASH_Unlock();
for (uint32_t i = 0; i < len; i += 4) {
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + i, *(uint32_t*)(data + i));
}
HAL_FLASH_Lock();
// 验证写入内容
if (memcmp((void*)addr, data, len) != 0) Handle_Error();
}
```
**应用程序跳转**
```c
void JumpTo_Application(uint32_t app_addr) {
typedef void (*AppEntry)(void);
AppEntry app_entry = (AppEntry)(*(volatile uint32_t*)(app_addr + 4));
// 重置栈指针
__set_MSP(*(volatile uint32_t*)app_addr);
// 跳转
app_entry();
}
```
---
#### 3. 关键设计要点
- **协议健壮性**:YMODEM 支持大文件传输(1024 字节/包),需处理超时和重传[^2]。
- **硬件加速**:STM32 硬件 CRC 可将计算时间缩短至 $T_{\text{CRC}} = N_{\text{bytes}} \times T_{\text{cycle}}$。
- **安全机制**:Bootloader 需存储在写保护的 Flash 区域,防止意外擦除。
---
阅读全文