设计了一种基于LoRa技术的STM32F4无线程序升级系统。此系统由PC及相关STM32软件开发环境、LoRa通信模块及控制器和STM32F4终端三部分组成。
本系统采用LoRa技术将程序数据无线发送到终端,终端通过IAP技术实现远程无线程序自动升级。测试结果表明,此系统能够有效地进行无线传感网络终端的程序升级,极大节约了时间和人力成本。
近年来,基于物联网应用的各种嵌入式产品层出不穷。但由于物联网应用中节点众多、分布广泛,为嵌入式终端固件升级带来了很多不便,于是远程、无线程序升级方法吸引了很多学者的研究,其中基于IAP编程模式的程序升级方法应用较多。
有文献提出了利用GPRS通信技术实现51单片机的远程IAP功能;还有文献提出了一种基于HTTP协议的远程嵌入式产品程序升级方法;还有文献实现了一种基于nRF905通信技术的无线程序编程器,可以实现对51系列单片机的无线程序烧写;还有文献提到了Wi-Fi环境覆盖下的嵌入式产品系统升级方法;还由文献提出了一种基于蓝牙串口模块,通过ymodem传输协议实现的IAP方案。
以上的程序升级方法很难在节点众多的物联网应用中取得广泛应用。LoRa技术适合组建低功耗无线传感器网络,广泛应用于物联网研究中。
本文尝试将LoRa技术和IAP技术相结合,实现一种应用与STM32F4控制器的无线程序升级系统。
采用此方案进行程序升级,节约了成本,减少了人力物力的消耗,对同类无线终端和节点的程序升级有借鉴意义。
IAP即在应用中编程,是指通过一种通信接口(USART、USB、CAN等)下载程序或应用数据到存储器中。
通常用户在实现IAP功能时,需要人为地将芯片内部存储区分为两块:一块用于存储IAP程序,称为BOOT区;另一块用于存储除IAP功能外的应用程序,称为常态存储区。
通过设置BOOT0和BOOT1两引脚的高低电平来设置程序的启动区域。一般将程序烧录到主存储区,启动区域设置为主存储区。
STM32F4系列控制器加入IAP后,程序流程为:先取出栈顶地址,然后是复位中断向量,跳转至复位程序处执行,接下来程序便跳转至main函数处(为IAP程序的main)执行IAP过程。
IAP过程中控制器会接收功能程序,写入FLASH并执行。执行过程与IAP程序开始执行过程相似,此时FLASH内部存在着两个不同位置的向量表,当应用程序运行时,产生的中断首先仍然返回地址为0x08000004处的向量表,然后根据设置的向量表偏移量找到向量中断源并执行中断服务程序,执行完成后会返回应用程序的main函数。
本系统由PC及相关STM32软件开发环境、LoRa通信模块及控制器和STM32F4终端三部分组成。
近年来,LoRa技术因支持远距离传输、大数量子节点和低功耗技术,在物联网应用中取得了广泛的使用。
本设计采用成都亿百特电子有限公司的LoRa模块,该模块采用Semtech公司SX1278射频芯片,传输距离最远可达到8km,工作频段为411~441MHz;该模块支持4种工作模式和空中唤醒,可最大限度降低功耗;模块通过串口实现外部通信,易于实现。
该模块共有7个引脚,通过串口实现与外部设备通信,引脚M0,M1来设置模块工作模式,AUX用来指示模块工作状态。
LoRa模块控制器的流程图如图所示,LoRa模块与控制器的连接关系如图所示:
控制器从PC接收程序代码,由于LoRa模块接收缓存有限,控制器须将代码分包,以一定时间间隔发送给LoRa模块。
控制器上电会完成两个串口的初始化,串口1用来接收PC发送的bin文件,串口6用来向LoRa模块发送数据。
串口1接收到数据后会进入串口接收中断函数,数据由DMA通道存储到内存特定区域,串口总线空闲中断标志接收代码完成。
发送循环中,控制器每次将一个512字节的数据包(最后一次将剩余全部)发送给LoRa模块。当LoRa模块内部缓冲区的数据被读取时,AUX引脚的电平会发生变化,PA1引脚会捕捉AUX电平变化并产生中断,中断函数会设置发送下一个数据包,程序依次循环直至代码发送完全。
由于AUX的变化智能表示LoRa模块已开始发送缓冲区内的数据,并不能确保数据已被完全发生且接收方LoRa模块也需要足够的时间来接收数据,因此发生下一个数据包之前会有一段延时,确保完整的数据发送和接收,这个延时数值在应用中赢根据无线传输的距离而定,不能小于数据从写进发送端LoRa缓冲区到接收端完全接收的时间间隔,本系统中设置的时间为1s,满足这一要求。
IAP程序以SWD方式下载至芯片中,IAP程序流程如图3所示。
上电复位后,依照BOOT模式设置,程序会从主存储区开始执行IAP程序。首先完成初始化,LoRa模块处于休眠状态;然后查询存储于FLASH地址为0x080E0000处的更新标志位(upstate_mark)的值,如果该值为0x01,则表示程序需要等待更新,此时需要将LoRa模块从休眠状态唤醒,终端会等待接收程序代码。
终端一旦通过串口接收到LoRa模块发送的程序数据,就会记录所接收的数据的长度,并且以1s的时间间隔查询数据长度,如有两次发现数据长度不变,则判定接收完成,紧接着将update_mark置0x00,表示下次终端上电无需等待更新。
应用程序会被写到起始地址为FLASH_APP1_ADDR的连续FLASH存储区内。在此终端程序中给它分配的值为0x08010000,即在此之前给IAP程序预留的空间为64KB,通过Keil软件查看编译后的IAP程序代码大小完全够用。
向FLASH写入代码前,首先要判断一下复位向量所在的物理存储空间是不是指向FLASH的,代码如下:
(*(u32_t *)(FLASH_APP1_ADDR+4)) & 0xFF000000 == 0x08000000
确认无误后,开始调用向FLASH写应用程序函数,代码如下:
iap_write_app(FLASH_APP1_ADDR,(uint32_t)USART_RX_BUF,REC_CNT);
此函数会调用STM32F4开发库中的写FLASH函数,代码如下:
if(FLASH_ProgramWolrd(WriteAddr, *pBuffer) != FLASH_COMPLETE){
break;
}
WriteAddr += 4;
pBuffer++;
FLASH_ProgramWolrd()每次会向FLASH写入一个字(4字节),接收数组是字节类型的,因此调用时要强调地址类型转换。
执行完写程序后,将upstate_mark变量重写为0x00,下次上电复位标志无需等待更新,直接执行程序调整。
if(((uint32_t *)App1Addr) & 0x2FFE0000) == 0x20000000){
JumpToApp() = (iapfun)*(vu32*)(App1Addr+4); //取出复位函数地址
MSR_MSP(*(uint32_t *)App1Addr); //设置主堆栈指针
JumpToApp(); //跳转执行应用程序
}
首先检查栈顶地址是否合法,App1Addr为应用程序地址,程序代码第一个字为栈顶地址,判断栈顶地址是否在0x2000 0000 ~ 0x2001 FFFF(RAM区域)范围内;取出应用程序复位函数地址;设置栈指针;程序跳转到应用程序复位函数地址处,应用程序开始执行。