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。
    1.png
  • 因为APP分区的起始地址为24KB偏移处,所以在MDK中需要修改APP的FLASH起始地址,并且需要使用MDK生成bin固件
    $K\ARM\ARMCC\bin\fromelf.exe --bin --output=Bin\@L.bin !L
    2.png

2.5.png

  • 编写上位机,实现从上位机发送固件到下位机
  • 编写下位机,实现接受上位机的数据保存到下位机的外部flash中
  • 上位机和下位机的数据运行流程图如下,通常来说对于固件来说,必须保证百分之百的错误率,因此每个数据包都需要进行校验。
    3.png

3、boot启动流程

启动标志位保存在外部flash中的固定地址,供APP和BOOT修改,在进行片上编程时,对APP区域编程完成后仍然需要进行一次校验,本文中提到的所有的校验使用的crc16
4.png

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)

原理就是这样,实际实现起来不算困难,我的代码过于契合公司业务,没什么参考性,就不放出来了~
文章目录