IAP和Bootloader

目录

一、引言

二、IAP的基础知识

三、实验配置及代码讲解

四、实验结果


一、引言

       IAP的全称是In Application Programing,即在应用编程,说的直白点就是在程序中编程。目的是为了产品发布以后想要对产品中的固件程序进行更新升级,那就需要重新烧录程序,但是产品一般都封装完好,不能拆开进行烧录调试,此时就需要IAP通过预留的通信接口(包括但不仅限于串口、IIC、SPI、CAN等通信方式),将所要更新的程序传入设备。

二、IAP的基础知识

      接下来讲解IAP的实现流程,如果不好理解的话,建议b站搜索正点原子。

       一般而言,想要实现IAP,需要两段程序:第一段叫做bootloader程序;第二段叫做APP程序。bootloader程序也叫做引导加载程序(前面章节有讲),这里的bootloader程序有点区别,即IAP中的bootloader为下载模式下的bootloader程序,用于更新调试。该程序是在产品出厂之前就已经烧录在设备里,一般将其烧录在flash闪存上。在串口IAP中,bootloader程序主要做三件事:1.通过串口接收要更新的程序暂存到RAM;2.将RAM里边的程序拷贝/写入到flash(或者SRAM中,在这里我们主要讨论flash);3.跳转到所更新的程序中去执行新程序。而APP程序也就是你所要更新的新程序,上述提到的更新程序都是APP程序。

      我们用如下图所示的实现流程来帮助理解上述这段话:

      首先,我们先来看一下正常程序的一般启动流程 :

         一般来说这个流程是这样的:当你烧录一个程序,程序文件一般是写入flash(起始地址0x08000000)中的。当你单片机上电以后,首先会将flash的前四个字节写入栈顶地址,也就是堆栈指针。这样做的目的是初始化堆栈指针,使其能够安全调用函数和中断服务。接下来会将0x08000004这里写入复位中断向量的地址,当单片机上电复位后,会触发复位中断,此时PC会根据中断向量表中的地址去执行中断服务函数,如上图步骤一所示;接下来在复位中断服务函数中会进行必要的时钟初始化,然后调用用户程序的main函数,此时会进入用户程序的main函数处继续执行程序。如上图2所示。在main函数中,发生了中断,此时PC指针会跳转到中断向量表去寻找对应的中断服务地址执行对应的中断服务函数,如图3、4所示。再执行完中断服务函数以后,程序返回main函数处继续执行。上述就是普通程序的启动流程。

       接下来我们看一下加入IAP以后有什么不同:

    从上图可以看到,加入了IAP之后的启动流程与正常程序的启动流程区别在于在进入IAP的main函数之后,此时会跳转到一个新的复位中断向量,这个复位中断向量的地址与之前的不一样,此时的地址明显比之前的地址偏移了M。然后跳转到新的复位中断函数,在新的复位中断程序中调用新的main函数。上述就是IAP程序的流程图。

     在上述两个流程图中,我们把第一个流程图叫做bootloader的启动流程,第二个流程图是APP程序的启动流程。可以看到,在上述启动流程中,APP程序的地址明显的发生了偏移,这表明新的APP程序至少要在bootloader程序之后的某个偏移量M地址处开始执行。

三、实验配置及代码讲解

    在理解上述流程之后,我们来看一下具体是怎么进行用户程序的更新的。

    首先,第一步是编写bootloader程序:在编写bootloader程序开始前,要首先思考给bootloader程序的flash内存要多大,同时给APP程序的flash内存又是多大(此处仅讨论flashAPP程序),这样才好去设置APP程序的地址偏移量。最后还应该考虑接收的程序的ram内存是多大,因为之前说过在下载bootloader模式下,APP程序都是先暂存在RAM里边的,而此处我用的是C8T6,其RAM只有20K。因此,我给接收APP程序的内存不能超过这个数。如下图所示,先来看一下bootloader的串口接收程序。

       主要关注第一行代码,这里是定义了一个数组来存放所接收到的APP程序,我在代码中也给了相应的注释。注意看这个数组的元素容量用的是一个宏变量USART_REC_LEN,这个我是定义成了13*1024,即13k的内存去接收这个APP程序,因为我本身所要升级的APP程序RAM大小为11k多一点,因此这个容量是够的。而后边的__attribute__(0x20001000)代表的是这个数组被存放了某个具体的地址处,这里0x20000000实际上是SRAM的起始地址,这里偏移了0x1000地址量来存放APP程序,而0x1000是4k的ram内存,也就是说这个4k内存的ram是用来存bootloader程序。因此,这样总共我们在bootloader程序就分配了17k内存,没有超过20k大小的ram,其中,13k给APP程序,4k给bootloader。但是需要说明的是这里的数组地址在FLASH中更新APP的时候,是不需要去设置的,可以交由编译器自动分配,但是在SRAM中更新APP,就需要设置其地址。

      我们知道,这个APP程序它只是暂存在RAM中,最终还是得将其拷贝到FLASH中,因此我们还得为APP程序分配FLASH内存。经过编译,我们得bootloader程序得flash大小是在5K左右,因此我将地址偏移量设置成了0x4000代表得是16k的flash内存给我们的bootloader程序,而我们这款的C8T6的flash内存是64k,因此,64-16=48K留给APP程序。因此,APP程序的起始地址应该赋为0x08004000,这个地址很关键,也是你需要将ram中接收到APP程序以后,要写入到FLASH的起始地址,那我们来看一下代码中如何实现拷贝功能的。

  代码是什么意思我已经详细的注释了,这里就不再多做解释。接下来我们主要看一下appxaddr这个参数,这个参数代表的是APP程序的起始地址,也是刚刚我们打算赋值的0x08004000,因此我们定义了一个宏常量来表示这个用户程序的起始地址。如下图所示,

上述就是拷贝APP程序到flashROM的代码。其中要注意的就是APP程序的起始地址,这个待会儿还会再用到。

   接下来我们看看跳转函数,是如何跳转到新的APP程序去运行的,代码如下:

   每行代码我都已经注释了,主要说一下跳转函数jump,这个函数名被定义成了一个函数指针,指向新的复位向量地址,然后调用jump函数,去执行新的复位中断函数。在中断函数里边,完成相应的时钟初始化以后,调用新的APP程序的main函数。

    最后,bootloader的main函数代码如下:

不多做解释了。上述就是整个bootloader程序的代码讲解。

接下来,我们看一下在APP程序中,我们需要配置哪些内容。

首先,先要设置APP程序的flash ROM起始地址,0xC000代表的是给APP程序多大内存。注意这里设置的flash rom地址与之前在代码中设置的0x08004000一模一样,如果不一致,是不会成功的,如下图所示:

然后,我们还需要在APP程序的main函数的最开头写上一段代码:SCB->VTOR = FLASH_BASE | 0x4000;     代表地址偏移,这里的0x4000也是直接对应我们的bootloader程序,请注意这一点。如下图所示:

最后,我们要利用一个转换工具将keil生成的.hex文件转化为.bin文件,这是因为,hex文件指定了地址,bin文件没有指定地址,很明显,在IAP中,我们不需要系统自行指定,而是需要自己定制,因此需要转换为bin文件,这是keil安装目录下的fromelf.exe应用程序来做的,具体操作为:先点开魔术棒,在user选项卡输入以下内容,请按照自己的安装目录去填充,此处仅供参考。

点击ok,之后一定要再进行一次编译,这样在你工程的OBJ目录下,就可以找到这个.bin文件了,否则找不到。

四、实验结果

       得到上述APP程序的.bin文件之后,先将你的bootloader程序下载在单片机这个,随后打开你的串口软件,选择波特率,点击打开文件,选择.bin文件,传输文件,此时固件升级成功,如下图操作:

实验结果如视频所示,可以看到bootloder下载成功以后,小灯亮起。此时LCD屏无显示。当传入文件以后,按下按键,此时固件升级成功,会看到LCD有参数显示,同时小灯熄灭。

VID_20240612_142404

上述实验全是参考正点原子例程修改而来,如有疑问,可参考b站正点原子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值