简单来说,Bootloader就是单片机上电或复位后,在你的主应用程序APP运行之前,先跑起来的一小段特殊程序。
你可以把它想象成电脑开机时的BIOS/UEFI。电脑按下电源键,不是直接就进Windows或MacOS了对吧?得先有个东西检查下硬件,做点初始化,然后再去加载操作系统。
1. 什么是IAP?什么是OTA?
IAP(In-Application Programming),“应用程序内编程”或“在应用中自编程”。本质含义:MCU 在运行用户代码(App或Bootloader)时,通过自身的代码(而不是用外部编程器/仿真器)来擦写和更新片上 Flash 内容。典型的应用场景:在系统上线后,通过串口、CAN、USB、以太网等接口下载新固件,并写入指定Flash区,完成固件升级。
OTA(Over-The-Air),直译就是“空中下载”或者“远程升级”,也就是使用无线的IAP,例如蓝牙或者wifi,它也是IAP。
2. 代码讲解
炸鸡派IAP_F411
的代码详见仓库连接:https://gitee.com/kingham/FryPi/tree/master/2.software/2.Advanced/7.IAP_F411
我们直接打开工程进行学习,外设的初始化我们就不再讲了,LCD、串口、PWM背光这些都是基础的部分内容。
//开机启动时如果按下KEY1, 进入boot中IAP升级模式
if(HAL_GPIO_ReadPin(KEY1_PORT, KEY1_PIN) == 0)
{
// 延时判断是否真的按下
delay_ms(500);
if(HAL_GPIO_ReadPin(KEY1_PORT, KEY1_PIN) == 0)
{
LCD_ShowString(72, LCD_H/2, (uint8_t*)"Bootload", WHITE, BLACK, 24, 0);//12*6,16*8,24*12,32*16
LCD_ShowString(32, LCD_H/2+48, (uint8_t*)"OV-Watch V2.4.1", WHITE, BLACK, 24, 0);
boot_in_menu_flag = 1;
//go in boot menu
FLASH_If_Init();
Main_Menu();
}
}
//如果没按下KEY1, 且有APP程序, 则运行APP, 没有APP则
else
{
uint32_t data1, data2;
char *str_flag;
uint32_t address = 0x08008000; // Flash 中数据的起始地址
// 读取地址为 0x08008000 的数据
data1 = *(uint32_t *)address;
// 读取地址为 0x08008004 的数据
data2 = *(uint32_t *)(address + sizeof(uint32_t));
// 将数据转换为字符数组
char str1[5], str2[5];
memcpy(str1, &data1, sizeof(data1));
memcpy(str2, &data2, sizeof(data2));
str1[4] = '\0';
str2[4] = '\0';
// 拼接两个字符数组
char combined_str[9];
strcpy(combined_str, str1);
strcat(combined_str, str2);
// 检查是否与 "APP FLAG" 相同
if (strcmp(combined_str, "APP FLAG") == 0)
{
// 如果相同则跳转
printf("APP FLAG OK, jump to app\r\n");
//user code here
SysTick->CTRL = 0X00;//禁止SysTick
SysTick->LOAD = 0;
SysTick->VAL = 0;
__disable_irq();
//set JumpAddress
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
/* Jump to user application */
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
}
// no legal APP
else
{
LCD_ShowString(74, LCD_H/2, (uint8_t*)"No App!", WHITE, BLACK, 24, 0);//12*6,16*8,24*12,32*16
LCD_ShowString(32, LCD_H/2+48, (uint8_t*)"Please Download", WHITE, BLACK, 24, 0);
HAL_Delay(1000);
}
}
0X0800 0000是MCU的启动地址,0X0800 8000存放了一个字符串,为自己设定的一个字符"APP FLAG"
,有则代表APP已经正常通过boot烧录了,0X0800 C000之后,就是存放的APP的代码内容了。
上面代码在启动时候的代码的大致意思,用一个流程图来表示更加直观:即上电后检测是否按键按下,按下进入boot升级,可以下载外部的.bin文件,然后再启动APP。如果上电时不按KEY按键,则正常进入APP(如果有的话)。具体的API内部内容,大家可以在源码中查看。
3. 上机实测
3.1. 准备待烧录的APP
接下来我们烧录BootLoader程序,然后使用SecureCRT烧录我们准备好的xxx.bin
文件,注意,这个xxx.bin
的工程的起始地址需要设置为:0x0000C000U
我们直接以LVGL手表例程为例,更改起始地址为0x0000C000
SCB->VTOR = 0x0000C000U;
然后更改设置,更改偏移地址,打开microlib
设置编译完生成.bin文件,稍等用Ymodem协议下载进去。
fromelf.exe --bin -o "$L@L.bin" "#L
3.2. 烧录BootLoader并进入升级模式
烧录IAP程序,然后连接串口,按住按键上电,打开SecureCRT连接串口可以看到这个界面:
然后按照菜单输入数字,进入下载模式,此时会一直输出ccccc...
等待你发送Ymodem
发送完bin后,显示成功,正常重启或者直接输入3就能进入APP了