1.环境搭建
硬件条件
- 开发板:GD32L235Q-START
存储空间 ROM(FLASH)128K RAM 24K - 串口数据线
- GD-link下载器(本开发板自带,用于下载程序)
软件条件
- notepad++ 读取HEX文件非常好用(有彩色注释)
- keil MDK 开发平台
- GDL235固件库
- MinGW -w64(用于写window桌面级c程序和单片机串口通信,方便传输hex文件)
下载链接 - 串口软件助手(用于单行调试)
2.bootloader程序编写
bootloader代码 keil MDK配置
bootloader代码需要在路径
C:\Users\zhaozijun\Desktop\GD32L235KBQ6_IAP_update\GD32L235Q_START_Demo_Suites\Projects\04_USART_HyperTerminal_Interrupt\MDK-ARM\Listings下找到 .map 文件,阅读最后部分得到
==============================================================================
Total RO Size (Code + RO Data) 13188 ( 12.88kB)
Total RW Size (RW Data + ZI Data) 1304 ( 1.27kB)
Total ROM Size (Code + RO Data + RW Data) 13320 ( 13.01kB)
==============================================================================
Total ROM Size 是bootloader的代码大小为13.01KB,使用keil的内存观察器看到
程序的起始地址为0x08000000,截至地址为0x08003410,3410转为十进制是13328,与map文件大体一致,表示bootlaoder程序所占用的空间。由此在target下设置size为0x4000即可够用。(可按bootloader代码大小和芯片flash大小自行设定以便后续bootloader代码升级,bootloader的代码地址空间与app代码地址空间不可冲突)。
bootloader代码 keil设置如图所示
以下是bootloader代码实现:
串口空闲中断+DMA 接收数据
接收协议按照HEX协议接收
完整代码:main.c
#include "gd32l23x.h"
#include "gd32l235q_start.h"
#include "systick.h"
#include "stdio.h"
#include <stdlib.h>
///////////////////////////////hex协议////////////////////////////////
uint8_t start = 0;
uint8_t bytes_num = 0;
uint16_t addr = 0;
uint8_t record_type = 0;
uint8_t checksum = 0;
uint8_t write_buffer[20];
uint8_t flash_easer_flag = 1;
////////////////////////////end hex///////////////////////////////////
char rev_complete_flag = 0;
uint32_t rev_num=0;
///////////////////////////////IAP////////////////////////////////////////////////////////
typedef void (*pFunction)(void);
#define rxbuffersize 50
//#define rxbuffersize 0x1000 //4k
uint32_t ApplicationAddress = 0x08004000 ; //16k
pFunction Jump_To_Application;
uint32_t JumpAddress = 0;
uint8_t rx_buffer[rxbuffersize];
uint32_t nbr_data_to_read = rxbuffersize;
uint32_t num_of_data_write = rxbuffersize;
//////////////////////////////END IAP////////////////////////////////////////////////////////////
////////////////////////////rx_buffer and tx_buffer///////////////////////////////////////
//#define BUFFER_SIZE 256
//#define BUFFER_SIZE (COUNTOF(tx_buffer))
//#define COUNTOF(a) (sizeof(a)/sizeof(*(a)))
static uint8_t hello[] = {" Hello , This is a iap flash download app \r\n please input your hex/bin code \r\n"};
static uint8_t waiting[] = {" waiting \r\n"};
static uint8_t start_writing[] = {" writing \r\n"};
static uint8_t end_successful[] = {" successful \r\n"};
static uint8_t end_failed[] = {" failed \r\n"};
volatile uint32_t tx_counter = 0, rx_counter = 0;
/////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////function /////////////////////////////////////////////////
void led_init(void);
void led_flash(void);
void usart_send(uint8_t* p);
void DMA_config(void);
int fputc(int ch, FILE *f);
void usart_config(void);
void gpio_config(void);
ErrStatus gd_check_sum(uint8_t *data, uint8_t data_num, uint8_t check_data);
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// FMC ////////////////////////////////////////////
#ifdef GD32L235
#define FMC_PAGE_SIZE ((uint16_t)0x0400U) //1024
#else
#define FMC_PAGE_SIZE ((uint16_t)0x1000U)
#endif /* GD32L235 */
uint32_t FMC_WRITE_START_ADDR = 0;
uint32_t FMC_WRITE_BASE_ADDR =0;
#define FMC_WRITE_END_ADDR ((uint32_t)0x08008000U)
#define FMC_PROGRAM_TYPE_WORD ((uint8_t)0x00U)
#define FMC_PROGRAM_TYPE_FAST ((uint8_t)0x01U)
#define FMC_PROGRAM_TYPE_DWORD ((uint8_t)0x02U)
uint32_t address = 0x00000000U;
#define write_size 4
uint64_t data[write_size/2]={0,0};
ErrStatus status = SUCCESS;
/* clear pengding flags */
void fmc_flags_clear(void);
/* erase fmc pages from FMC_WRITE_START_ADDR to FMC_WRITE_END_ADDR */
void fmc_erase_pages(uint32_t FMC_WRITE_START_ADDR);
/* program fmc word by word from FMC_WRITE_START_ADDR to FMC_WRITE_END_ADDR */
void fmc_program(uint8_t program_type,uint32_t FMC_WRITE_START_ADDR, uint16_t size , uint64_t* data);
/* check fmc erase result */
void fmc_erase_pages_check(uint32_t FMC_WRITE_START_ADDR);
/* check fmc program result */
void fmc_program_check(uint8_t program_type,uint32_t FMC_WRITE_START_ADDR, uint16_t size , uint64_t* data);
/////////////////////////////////////////END FMC/////////////////////////////////////////////
unsigned char hex_of_char(char c)
{
unsigned char tmp = 0;
if(c >= '0' && c <= '9')
tmp = (c - '0');
else if(c>='A' && c <='F')
tmp = (c -'A' + 10);
else if(c>='a' && c<='f')
tmp = (c-'a'+10);
return tmp;
}
uint8_t checksum_fun(uint8_t checksum,uint8_t* rec)
{
uint8_t i=0;
uint8_t sum=0 ;
for(i=1;i<(bytes_num+4)*2;i=i+2)
{
sum = sum + ((hex_of_char(rec[i])<<4) + hex_of_char(rec[i+1]));
}
sum = 0x100 - sum;
if(checksum == sum)
{
//printf("checksum is