操作系统任务框架
系统任务
空闲任务几乎存在于所有的嵌入式实时操作系统,用户无法自行关闭空闲任务。
空闲任务的作用主要是减少核心芯片的使用率,避免核心芯片的负载压力过大,保证系统的低功耗运行。
时钟节拍任务控制系统的延时函数和等待超时,系统各个子任务之间的切换需要中断服务管理函数的支持。
系统任务包括空闲任务、时钟任务、中断任务、统计任务、定时器任务,其中空闲任务由系统默认创建无法更改。
引导程序设计
嵌入式设备的OTA升级是利用了嵌入式设备的远程升级功能完成的工作,在设备远程升级过程中,设备端的Bootloader程序需要设计一个IAP程序,该程序实现将新工程数据覆盖到旧文件数据存放区域的功能。
IAP(In Application Programming,在程序中编程)是一种通过对外通信接口对正在运行的设备进行软件更新的技术。
该技术不同于ICP,即电路内编程,也不同于ISP技术通过单片机内置的bootloader程序引导进行烧写。
ISP和ICP需要通过特定的设备如连接线进行连接进行更新。
若设备已加工密封,更新就会变得很复杂,而部分小型设备所处的环境难以触及,程序更新变得难上加难。
而IAP技术不需要直接接触设备,从而规避机械操作。并且本文采用远距离无线的数据传输方案,可以实现软件远程更新。
在STM32中实现IAP技术首先需要对其堆栈地址和启动方式进行研究。Cortex-M3架构芯片内存地址映射起始地址为0x8000000,该地址规定了程序存放地址。
并且,Cortex-M3架构内部通过一张中断向量表和中断服务函数完成中断服务。
中断向量表的起始地址是0x8000004,当出现中断源,STM32会指向中断向量表,并根据中断源跳转到正确的中断服务程序。
通过修改STM32工程的写入地址可以修改二进制文件写入Flash的起始地址。
在STM32上实现IAP方案,除了对存储区域有相应的划分以及设计外,还需要设计引导程序与应用程序之间的中断机制以及跳转机制。
该图显示了STM32的启动过程和中断响应过程。
在出现复位中断时,程序指针会在中断向量表中找到对应中断并取出中断服务程序地址,之后跳转到该地址,如1所示。
在处理完中断服务程序后会跳转回应用程序,如2所示,简单程序的应用程序是一个无限循环。
在main函数执行的过程中若出现中断源,程序会重新跳转到中断向量表,如3所示,再次根据中断源进入相应的中断服务程序,如4所示。
之后程序指针指向保留的应用程序线程继续执行,如5所示。
再加入引导程序后,流程如图:
在出现复位中断源时,会首先跳转到中断向量表地址查找中断服务程序地址,并跳转到该地址,随后跳转至引导程序的main函数,该main函数运行的就是IAP程序,如1、2所示。
此时,在新版本固件中会有完整的程序,包括完成功能逻辑的main函数以及中断向量表和中断服务程序,在跳转至新写入程序的中断向量表后,开始正常的应用启动过程。
Flash分区设计
STM32F103RCT6的Flash大小为256K,本文按照IAP以及应用程序的大小进行了Flash分区设计。
因为IAP程序的运行也需要依赖于Flash存储的固件,需要足够的空间进行IAP程序的存储,此外,由于用户程序可能会不断扩展,需要预留足够的空间进行存储,而理论上来说,待升级程序占用的存储空间与用户程序占用的空间相同。
因此,Flash存储设计具有四个分区,包括IAP程序的Bootloader分区、用户程序区、标志区、升级程序区。
引导程序区包括IAP函数,主要功能为检查标志区是否为待升级标志,若是则需要将升级程序区程序搬运到用户程序区,在之前需要先清除用户程序区为拷贝固件做准备。
如果标志区不是升级标志,则需要清除升级程序区并从用户程序区开始执行。这个区域在本文设计中占用24K的Flash存储空间,换算成十六进制为0x6000.
用户程序区即正常的设备运行程序,存放的是本文设计的软件架构相关程序,占用119K内存,换算成十六进制为0x1D000。
升级程序区存放待升级程序,该区具有一个1K的标志区,记录待升级程序是否成功被写入到升级程序区。
这样的Flash分区的设计主要考虑了升级失败的情况,如果没有升级程序存放区域,在执行差分算法时如果出现内存溢出导致更新失败,而此时用户程序区的文件已被修改,这样的错误会使整个设备变成砖头状态,必须使用连接下载线或设置跳线帽等机械性操作重新烧录程序。