前言
中秋国庆放假8天太无聊,发现之前买的两块STM32WB55CGU6的开发板,看下下它的资源还挺丰富的,而且还号称是超低功耗的处理器。首先是看了下OTA的功能,本文讲解如何进行OTA。
文章
在使用OTA之前,我已经使用过NRF52832的OTA功能,实现起来较为繁琐,看了STM32WB55的OTA方式,还是简单易懂的,主要是文章写得好,结合例程来看,很快就学会了。这篇官方的文章写的很好,还是中文的,我的方法步骤就是从这来的,但是略有不同。
体验OTA
开始之前我们可以先体验一下OTA的功能,在你的软件包的安装目录下有这几个工程,我们将用的这几个来体验OTA的功能。在此之前,请确认已经烧录好了对应的协议栈以及FUS,不然你是无法使用的。
- BLE_HeartRate_ota
- BLE_Ota
- BLE_p2pServer_ota
1. 首先需要下载BLE_Ota,这个就是OTA的固件,它负责擦写FLASH来实现IAP编程,所以,它是必须要的。BLE_HeartRate_ota以及BLE_p2pServer_ota两个测试的工程,我们将在这两个程序之间切换。
2.再下载BLE_HeartRate_ota,两个程序先下哪个都一样的。下载完成之后打开ST BLE ToolBox,可以看到已经在广播了,而且可以看有OTA标识的,意味着它是可以OTA的。
连接好以后,进行reboot,进入OTA程序,
它会自动断开,然后可以看到新的广播,
点击下载之后即可完成OTA的升级(注:两个bin文件需要发送到手机上,通过手机来完成OTA)。
参考https://blog.csdn.net/qq_43286438/article/details/125269370
普通程序的修改
新的应用程序的修改
既然使用的是OTA固件来实现的IAP编程,实际上是OTA程序擦写FLASH,然后跳转罢了,实际上确实是这样的,但是你会发现,我随意写一个程序是无法运行的,使用ST BLE ToolBox软件上传我的固件后是无法运行的。下面讲解如何修改这个程序。
我这里编写了一个LED的程序,没有其他的操作用来测试,应该来说我下载这个程序后是可以实现LED闪烁的功能的。
编译生成bin文件然后发送到我的手机,MCU里先下载好 BLE_Ota固件以及BLE_HeartRate_ota固件。操作和上面一样,下载后你会发现LED根本就不闪烁。其实是要对链接地址进行修改。
1.修改分散加载文件
2.去除中断向量
3.添加 magic 关键字
const uint32_t MagicKeywordValue = 0x94448A29 ;
const uint32_t MagicKeywordAddress __attribute__((at(0x08007140))) = (uint32_t)&MagicKeywordValue;
这样修改以后就可以运行了,具体为什么,那就看文件吧。
后面再写如何优化,现在的程序只是可以运行,不能继续升级。
添加REBOOT特征
之前我们的程序只是显示了一次OTA升级,不能进行下一次了。那么为什么会这样呢?
这就要看OTA程序是如何实现IAP编程的,STM32WB55在启动的时候做了些什么,在哪里实现的跳转的。
打开BLE_Ota工程,在这个文件下有具体的跳转功能的实现,
找到 void SystemInit(void) 函数,就是这个函数判断的,
具体就不再深究了,简而言之就是实现程序的跳转需要两个条件,
- *((uint32_t*) 0x08007140 )= 0x94448A29 ;不然的话,它会认为没有应用程序,会将0x08007000之后的FLASH擦除。
- *((uint32_t*) 0x20000000UL)= 0 ;
...
观察下来是这几句起到了标识擦除的作用,
那么只要添加这几句就可以实现擦除了。原理也是比较简单,假设原来的固件为A,需要升级到固件B,用来升级的OTA固件为C。流程大概就是,系统启动,运行固件C,检测到magic 关键字存在,跳转到运行固件A,一旦固件A触发了OTA事件,需要改写SRAM1_BASE0,1,2,地址的值,标识需要OTA,然后系统重启,还是运行固件C,检测到需要进行OTA,然后擦除FLASH,原本的固件A被擦除,之后开始广播,进行下载固件B,完成升级。
/*****/
#define CFG_OTA_REBOOT_VAL_MSG (*(uint8_t*)(SRAM1_BASE+0))
#define CFG_OTA_START_SECTOR_IDX_VAL_MSG (*(uint8_t*)(SRAM1_BASE+1))
#define CFG_OTA_NBR_OF_SECTOR_VAL_MSG (*(uint8_t*)(SRAM1_BASE+2))
/**在需要升级的时候调用***/
CFG_OTA_REBOOT_VAL_MSG = 0x01;
CFG_OTA_START_SECTOR_IDX_VAL_MSG = 0x07;
CFG_OTA_NBR_OF_SECTOR_VAL_MSG = 0xFF;
NVIC_SystemReset();
其中 CFG_OTA_REBOOT_VAL_MSG标识的是从何处启动, CFG_OTA_START_SECTOR_IDX_VAL_MSG标识需要擦除的扇区,CFG_OTA_NBR_OF_SECTOR_VAL_MSG 标识需要擦除的扇区数量,如果这个数量设置得小于实际的固件大小的话,升级的过程中会卡住。
其他的考虑
整个流程就是应用程序的广播中带有可以重启的特性,让MCU进入到OTA程序当中进行升级,但是如果应用程序发生了异常,导致无法正常广播,这将无法进行升级了,所以下面对BLE_Ota进行修改,让他在上电的时候延时一段时间再进行检测,而如果是软复位的话,就立即检测。
这里不赘述了,实现也是比较简单。需要注意的是,这个工程需要在放在原来的BLE_Ota路径下才能编译成功,而且使用的固件是STM32Cube_FW_WB_V1.14.1。
代码https://gitee.com/lei_kkaaa/stm32-wb55_-ota.git
自己的服务里面添加REBOOT特征值貌似并不能实现,即使是按照文档添加了特征值,手机工具依然不能实现烧写。测试发现,只有P2P服务,以及心率服务,下添加特征值是可以的。所以可以使用custom的服务,然后UUID写P2P或者心率服务,同时添加相应的特征值,不需要实现功能。之后再添加REBOOT的特征值,手机才能识别。
之后就是实现回调了,可以查看例程是如何实现的。
要想手机标识OTA,还要广播设置下,