开发基于GDL235KBQ6开发板的IAP升级程序(HEX协议+串口空闲中断 + DMA接收数据)

1.环境搭建

硬件条件

  1. 开发板:GD32L235Q-START
    存储空间 ROM(FLASH)128K RAM 24K
  2. 串口数据线
  3. GD-link下载器(本开发板自带,用于下载程序)

软件条件

  1. notepad++ 读取HEX文件非常好用(有彩色注释)
  2. keil MDK 开发平台
  3. GDL235固件库
  4. MinGW -w64(用于写window桌面级c程序和单片机串口通信,方便传输hex文件)
    下载链接
  5. 串口软件助手(用于单行调试)

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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的竣

感谢打赏,祝您事业有成!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值