资料下载: https://download.csdn.net/download/vvoennvv/88713921
一、概述
关于IAP的原理和Ymodem协议,本文不做任何论述,本文只论述bootloader如何使用串口通过Ymodem协议接收升级程序并进行IAP升级,以及bootloader和主程序两个工程的配置注意事项。
实验板子主芯片:GD32F103C8T6
二,代码
1,Bootloader部分
主要流程如下:
(1)上电开机之后,会先运行bootloader引导程序,bootloader检测串口是否有数据,超时没有收到收据会直接跳转进入主程序中,超时时间使用定时器设置,可根据产品需求和使用场景设置一个合理的超时时间。也可以通过检测按键是否按下,再进入这个检测串口是否有数据的步骤,这样更加灵活。
(2)上位机将升级程序(bin文件)分包发送到设备,设备接收到数据之后进行校验,校验通过后写入到芯片,替换原有的旧程序,完成整个升级过程。
部分代码如下:
int main(void)
{
SystemInit();
GPIO_Configuration(); //配置串口IO
FLASH_Unlock(); //解锁flash
UART_Init(); //配置串口波特率,校验位等
BspTim2Init(); //Timer 用于超时判断
SerialPutString("\n\rbootloader\r\n");
//进入bootloader后菜单选择,已取消显示,直接进入检测串口数据状态
//如果3s之内没有选择,跳出,执行后面代码
Main_Menu();
//通过判断栈顶地址值是否正确(是否在0x2000 0000 - 0x2000 2000之间)来判断是否应用程序已经下载了
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
{
BspTim2Close();
__disable_irq() ;
//跳转至用户代码
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
//初始化用户程序的堆栈指针
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
}
else
{
SerialPutString("no user Program\r\n\n");
}
while(1);
}
void Main_Menu(void)
{
FLASH_Status FLASHstatus;//定义一个flash操作状态变量
uint8_t key = 0;
static uint8_t uStatus = 0;
BlockNbr = (ApplicationAddress - 0x08000000) >> 12;
#if defined (STM32F10X_MD) || defined (STM32F10X_MD_VL)
UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));
#else /* USE_STM3210E_EVAL */
if (BlockNbr < 62)
{
UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));
}
else
{
UserMemoryMask = ((uint32_t)0x80000000);
}
#endif /* (STM32F10X_MD) || (STM32F10X_MD_VL) */
//返回flash写保护选择字节的值
if ((FLASH_GetWriteProtectionOptionByte() & UserMemoryMask) != UserMemoryMask)
{
FlashProtection = 1;
}
else
{
FlashProtection = 0;
}
/* Download user application in the Flash */
SerialDownload(); //使用YModem协议接收app bin文件
SerialPutString("Auto jump App \r\n");
}
2,主程序部分
主程序只需要增加两行代码即可,如下所示:
int main(void)
{
// 主程序里,在main()前面增加下面两行代码即可
// 把栈顶设置到0x3000,0x3000是主程序的烧录位置,也是bootloader跳转的位置
// 这个位置可以根据实际情况统一调整
nvic_vector_table_set(NVIC_VECTTAB_FLASH , 0x3000);
__set_PRIMASK(0);
systick_config();
/* enable the LED clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* configure LED GPIO port */
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
/* reset LED GPIO pin */
gpio_bit_reset(GPIOB, GPIO_PIN_8);
while (1)
{
// app1 快闪
gpio_bit_reset(GPIOB, GPIO_PIN_8);
delay_1ms(500);
gpio_bit_set(GPIOB, GPIO_PIN_8);
delay_1ms(500);
// app2 慢闪
//gpio_bit_reset(GPIOB, GPIO_PIN_8);
//delay_1ms(2000);
//gpio_bit_set(GPIOB, GPIO_PIN_8);
//delay_1ms(2000);
}
}
三,工程配置
1,Bootloader部分
0x3000是分配给bootloader的空间,可根据实际情况修改。
2,主程序部分
Start填写0x08003000,是因为主程序烧录在这个位置,和分配给bootloader的空间有关。
增加
fromelf --bin -o "$L@L.bin" "#L"
这句,可以在编译时生成bin文件
四,测试
使用上位机软件(支持Ymodem协议的软件都可以),选择编译好的主程序(bin文件),在板子上电之后,通过串口发送过去即可。
资料下载: https://download.csdn.net/download/vvoennvv/88713921