写出GD32C103的BootLoader升级程序
时间: 2023-08-17 18:06:08 浏览: 103
为了编写 GD32C103 的 BootLoader 升级程序,您需要了解以下几个方面:
1. GD32C103芯片的Flash存储器布局,包括BootLoader区域和应用程序区域;
2. 如何实现串口通信,以便通过串口下载新的BootLoader程序;
3. 如何实现BootLoader程序的更新,包括应用程序的擦除、新BootLoader的下载以及应用程序的重新下载。
下面提供一份可能的GD32C103 BootLoader升级程序参考代码:
```c
#include "gd32c10x.h"
#define BL_VERSION 0x1000 // BootLoader程序版本号
#define APP_ADDRESS 0x08004000 // 应用程序区域起始地址
#define BL_ADDRESS 0x08000000 // BootLoader区域起始地址
#define BL_SIZE 0x2000 // BootLoader区域大小
#define DOWNLOAD_TIMEOUT 1000 // 下载超时时间,单位ms
#define DOWNLOAD_ADDRESS 0x20000000 // 下载地址
uint32_t app_size; // 应用程序大小
uint32_t app_crc; // 应用程序CRC校验值
void delay(uint32_t count)
{
for(; count != 0; count--);
}
void jump_to_app(void)
{
uint32_t addr = APP_ADDRESS;
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
Jump_To_Application = (pFunction) (*((uint32_t*)(addr + 4)));
__set_MSP(*((uint32_t*) addr));
Jump_To_Application();
}
void flash_erase(uint32_t address)
{
uint32_t erase_error;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_ErasePage(address);
erase_error = FLASH_GetFlagStatus(FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
if (erase_error != 0) {
// 擦除失败,进行错误处理
while(1);
}
FLASH_Lock();
}
void flash_write(uint32_t address, uint8_t *data, uint32_t size)
{
uint32_t write_error;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
for (uint32_t i = 0; i < size; i++) {
FLASH_ProgramByte(address + i, *(data + i));
write_error = FLASH_GetFlagStatus(FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
if (write_error != 0) {
// 写入失败,进行错误处理
while(1);
}
}
FLASH_Lock();
}
uint16_t calc_crc(uint8_t *data, uint32_t size)
{
uint16_t crc = 0xFFFF;
for (uint32_t i = 0; i < size; i++) {
crc ^= *(data + i);
for (uint8_t j = 0; j < 8; j++) {
if ((crc & 0x0001) != 0) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc = crc >> 1;
}
}
}
return crc;
}
int main(void)
{
uint32_t download_count = 0;
uint8_t *download_ptr = (uint8_t*)DOWNLOAD_ADDRESS;
uint16_t recv_crc = 0;
uint8_t recv_data;
USART_InitPara usart_initpara;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay(1000); // 等待串口稳定
usart_initpara.USART_BaudRate = 115200;
usart_initpara.USART_WordLength = USART_WordLength_8b;
usart_initpara.USART_StopBits = USART_StopBits_1;
usart_initpara.USART_Parity = USART_Parity_No;
usart_initpara.USART_Mode = USART_Mode_Rx;
usart_initpara.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART0, &usart_initpara);
USART_ITConfig(USART0, USART_IT_RXNE, ENABLE);
USART_Enable(USART0, ENABLE);
while (1) {
if (USART_GetITStatus(USART0, USART_IT_RXNE) == SET) {
recv_data = USART_ReceiveData(USART0);
if (download_count == 0) {
if (recv_data == 'U') {
// 进入BootLoader升级模式
flash_erase(APP_ADDRESS);
flash_erase(BL_ADDRESS);
USART_SendData(USART0, 'U');
download_count = 1;
}
} else if (download_count == 1) {
// 接收应用程序大小
app_size = recv_data;
download_count++;
} else if (download_count == 2) {
app_size |= (recv_data << 8);
if (app_size <= (BL_SIZE - 8)) {
// 应用程序大小合法
USART_SendData(USART0, 'A');
download_count++;
} else {
// 应用程序大小非法,进行错误处理
USART_SendData(USART0, 'N');
download_count = 0;
}
} else if (download_count == 3) {
// 接收应用程序CRC校验值的低8位
app_crc = recv_data;
download_count++;
} else if (download_count == 4) {
// 接收应用程序CRC校验值的高8位
app_crc |= (recv_data << 8);
USART_SendData(USART0, 'C');
download_count++;
} else {
// 接收应用程序数据
*download_ptr++ = recv_data;
if ((download_count % 256) == 0) {
USART_SendData(USART0, 'O');
}
download_count++;
if (download_count > (app_size + 8)) {
// 应用程序下载完成,进行校验
recv_crc = calc_crc((uint8_t*)DOWNLOAD_ADDRESS, app_size);
if (recv_crc == app_crc) {
// 应用程序CRC校验正确,将应用程序下载到Flash中
flash_erase(APP_ADDRESS);
flash_write(APP_ADDRESS, (uint8_t*)DOWNLOAD_ADDRESS, app_size);
USART_SendData(USART0, 'S');
delay(100);
NVIC_SystemReset(); // 重启系统
} else {
// 应用程序CRC校验错误,进行错误处理
USART_SendData(USART0, 'F');
download_count = 0;
}
} else if ((download_count % 256) == 0) {
// 发送下载进度信息
USART_SendData(USART0, 'P');
USART_SendData(USART0, (download_count >> 8) & 0xFF);
USART_SendData(USART0, download_count & 0xFF);
}
}
USART_ClearITPendingBit(USART0, USART_IT_RXNE);
download_timeout = DOWNLOAD_TIMEOUT;
}
if (download_count != 0) {
// 下载超时处理
download_timeout--;
if (download_timeout == 0) {
USART_SendData(USART0, 'T');
download_count = 0;
}
}
}
}
```
这份代码只是提供一个实现BootLoader升级程序的参考,具体实现需要根据具体的芯片和应用场景进行调整。请注意,为了防止程序错误导致系统无法正常运行,编写BootLoader程序需要谨慎并进行充分的测试。
阅读全文