STM32---串口实现在应用程序的固件更新(IAP)

背景:

        在产品发布后,可能需要对固件进行更新或者升级,那么在影响产品正常运行的情况下,如果升级固件呢?

理论:

        下面的所有理论部分内容参考《STM32开发指南》。

什么是IAP:

        指在应用编程。即用户程序运行中作自身的更新操作。需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,(功能操作指:main函数里面的功能)而只是通过某种通信方式(如USB、USART)接收程序或数据,执行对第二部分代码的更新;(第二部分代码指需要更新的程序第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在User Flash中,当芯片上电后,首先是第一个项目代码开始运行。操作如下:

        1.检查是否需要对第二部分代码进行更新;

        2.不需要更新的话,跳转到第二部分代码执行。需要更新的话执行更新操作。 

生成两个项目代码:

        这里将第一个项目代码称之为Bootloader程序,第二个项目代码称为APP程序,他们存放在STM32 FLASH的不同地址范围,一般从最低地址区开始存放第一个项目代码,紧跟其后的就是第二项目代码,当然如果内存够,可以再紧跟多个APP程序。并且,这个APP程序,可以放到FLASH中,也可以放到SRAM中运行。

两个项目代码烧录:

          第一部分代码必须JTAG 或ISP烧入;第二部分代码可以使用第一部分代码的IAP功能烧入,也可以和第一部分代码一起烧入,以后需要更新程序时再通过第一部分IAP代码更新。     

STM32正常运行流程:

        如上图所示,STM32F4的内部FLASH位于Block 0,地址起始于0x0800 0000,一般情况下,程序文件就从此地址开始写入。程序启动后(这里程序启动应该指上电。根据启动文件描述:系统上电复位后执行的是由汇编编写的启动文件,启动文件主要包含:初始化堆栈指针、初始化PC指针、初始化中断向量表、配置系统时钟、进入main函数),将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动。cortex-m4内核的“中断向量表”起始地址是0x0800 0004,当中断来临,内部硬件机制会将PC指针定位到“中断向量表”处,取出对应的中断向量执行中断服务程序。执行完复位中断后,会跳转到main函数,如果再发生中断,STM32会强制将PC指针指到中断向量表处执行中断完后再继续运行main函数。

 加入IAP之后的运行流程: 

        

        如上图所示,对应的两个项目的程序存储地址。IC复位后,还是从0x0800 0004取复位中断向量的地址并跳转到中断服务程序,再运行完后,跳转到IAP的main函数,之后执行新的程序的复位中断、main函数,并响应其他中断。执行的是上图下面灰色的部分。不同的是,在CPU得到一个中断后,PC指针将强制跳转到0x0800 0004中断向量表处,而不是新程序的中断向量表。

        那么,新的程序必须在IAP程序之后的某个偏移地址开始,新的程序的中断向量表也需要相应的移动偏移量。        

如何配置/编写IAP程序:

        APP偏移地址配置:

        在options for target选型的target页面下,IROM1的起始地址一般为0x0800 0000,大小为0x0010 0000,即从0x0800 0000开始的1024K空间是程序存储区。而若将此起始地址设置为0x0801 0000,相当于偏移量0x10000(64K字节)。那么留给APP用的flash区域就只有0x0010 0000-0x10000=0xF0000(960K字节)。

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif

        偏移量在systemInit()函数中定义了,如上图所示。一般不会在系统文件中修改code,而在flash的APP的main函数最开头处添加偏移量配置。那么:

        1.如果不使用IAP功能,是否还需要设置偏移量?

·       2. 偏移量我的理解是设置APP程序的起始地址。而如果在APP的main函数中才定义偏移量,是不是有误?

        3. 偏移量的目的只是将flash程序与IAP的程序区分开?

        如下图所示:

        烧录配置:

        MDK默认生成的文件是.hex文件,而IAP更新希望用的是.bin文件。通过MDK自带的fromeif.exe可以将.axf转换成.bin文件。

        IAP程序编写:

        在实现固件升级的功能中,需要先编写IAP程序,包含1)编写函数将串口接收到的数据Buf中的内容保存在flash中;2)写一个函数实现IAP到APP的跳转;3)编写main函数实现串口的接收,APP程序保存及跳转。

最后:在查资料过程中遇到以下疑问,下面将疑问以及理解写出,供由相同疑问的学者参考:(其实疑问在代码中可以解决)      

       1.  上面的这种方式和我们普通运行的程序是否不一样?区别?

        这里需要说STM32编程的两种方式,一种是在线编程 ICP,通过JTAG/SWD协议或者系统加载程序(bootloader)下载用户应用程序到微控制器;一种是在程序中编程IAP,通过任何一种通信接口下载程序或者应用数据到存储器中。    但是,IAP需要至少一部分程序已经使用ICP方式烧录到FLASH中(bootloader)。  同时,每种STM32芯片,虽然主存储器结构可能不同,但是都“系统存储区域”,该区域是留给ST自己用来存放芯片的bootloader,此程序在芯片出厂的时候已经固化在芯片内部。

             STM32 启动模式:B1=0,B0=1,程序从系统存储器中执行启动程序bootloader,也就是从串口下载程序到主程序中。B0=0,FLASH被选为启动区域,执行写入的应用程序。

        2.  那么,自己写的bootloader和系统存储器里本身有的是否一样?  

        不一样,自己写的bootloader 需要先通过ICP的方式下载到存储区域中,然后再通过IAP下载应用程序。

        3. 在上图3中,执行bootloader程序会跳转到IAPmain,那么IAP的地址是什么?如何实现的跳转?

       其实,IAP就是bootloader程序,他们只有一个Main 函数,执行完复位中断会直接跳转到main函数。

        4. 偏移的地址根据描述是APP程序的起始地址,还需要再在APP程序中配置中断向量表?

        通过上面IAP的main函数可以实现跳转到APP程序,但是新的程序的中断向量表需要重新配置,不然没办法响应中断。

        

猜你喜欢

转载自blog.csdn.net/weixin_41155462/article/details/121785350