此篇文章在2023年3月24日被记录
ARM单片机使用自定义bootloader
什么是BOOT
懂得计算机的同学都知道,电脑在开机时,从上电的那一刻开始,首先会进入bios,这个bios的作用就类似于单片机中的bootloader。万一我们浏览某些不可言状的网站导致系统崩溃时,我们就可以在这个临时的系统(bios)中切换到另一个windows系统(PE)进行对主系统(APP)的抢救修复。同样的,我们单片机中APP分区崩溃或者需要更新时,我们可以停留在boot分区恢复APP分区。
怎样制作一个BOOT
1、需求
我们的BOOT分区需要满足如下需求:
- 上电后,如果APP分区没有固件,停留在boot中等待上位机发送固件包,并将固件包储存在外部flash中
- 上位机发送完固件包后,将外部flash中的固件拷贝到内部APP分区
- 检测到APP分区正常运行后,跳转到APP分区去运行
2、实现方式:
- 首先,我们需要对内部falsh进行分区,哪部分是boot,哪部分时APP,如图所示,BOOT地址位于flash零地址,BOOT大小为24KB。
- 因为APP分区的起始地址为24KB偏移处,所以在MDK中需要修改APP的FLASH起始地址,并且需要使用MDK生成bin固件
$K\ARM\ARMCC\bin\fromelf.exe --bin --output=Bin\@L.bin !L
- 编写上位机,实现从上位机发送固件到下位机
- 编写下位机,实现接受上位机的数据保存到下位机的外部flash中
- 上位机和下位机的数据运行流程图如下,通常来说对于固件来说,必须保证百分之百的错误率,因此每个数据包都需要进行校验。
3、boot启动流程
启动标志位保存在外部flash中的固定地址,供APP和BOOT修改,在进行片上编程时,对APP区域编程完成后仍然需要进行一次校验,本文中提到的所有的校验使用的crc16
4、跳转函数
typedef void (*APP_Function)(void);
APP_Function Jump_To_Application;static void _jump_to_app(uint32_t addr)
{uint32_t JumpAddress;__disable_irq();/* Jump to user application */JumpAddress = *(__IO uint32_t *)(addr + 4);Jump_To_Application = (APP_Function)JumpAddress;/* Initialize user application's Stack Pointer */__set_MSP(*(__IO uint32_t *)addr);Jump_To_Application();
}
因为我们的APP地址是0x8006000,因此调用跳转函数为_jump_to_app(0x8006000)