XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX 作 者:ZHS(文化人)
XX 联系方式:点击置顶文章(或进群:471144274)
XX 版权声明:原创文章,欢迎评论和转载~转载时能告诉我一声就最好了
XX 要说的话:作者水平有限,难免有不足之处,恳请指正!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
写在前面:每次跟销售或者客户做项目评估的时候,他们都会问到“能支持OTA吗?”,可见OTA升级对于一个产品而言是多么重要(~废话)。
一、OTA空中升级:
1、概念:
DFU:Device Firmware Update(设备固件更新)
OTA: Over The Air (空中升级)
两种不同布局方式的差别:
(1)single bank布局不支持softdevice及bootloader自身的升级,只支持该芯片上应用程序的升级。
(2)采用single bank布局的方式中,一旦开始升级,芯片上原有的应用程序将不能被保存。而以dual bank布局的方式中,在开始接收新的二进制程序(image)时,原有的二进制程序(image)将会被保留,如果升级失败不会影响芯片上原有的程序。目前的SDK DFU都是只支持dual bank升级,如果需要single bank需要使用6.0之前的版本sdk。还有就是采用dual bank升级的代码大小不能超过总(内存-SoftDevice size - Bootloader size)/2.
2、启动的过程:
对于单片机类的产品,要支持空中升级,通常单片机内部会烧录两段代码,一个是bootloader程序,一个是用户app程序,bootloader程序主要就是实现app升级的程序,它是单片机上电后首次运行的程序,app程序就是实现产品功能的程序。对于nRF52832来说,虽然多了Nordic官方提供的softdevice,但是原理还是一样的。芯片上电首次运行softdevice,虽然这段程序不负责程序升级,但是它也具备一点bootloader的功能,也就是说,芯片上电后,它会判断芯片内部是否有bootloader代码(bootloader代码位置固定,所以它能判断出是否有合法的bootloader程序),若有bootloader程序则会跳转到bootloader程序执行,若没有bootloader程序而只检测到了用户的app程序,那么就直接跳转到app程序运行,bootloader程序差不多只做两件事情,1:控制程序的跳转,比如跳转到app程序;2:实现app程序升级;
nRF52832程序加载顺序;
1)SoftDevice加载;
2)SoftDevice初始化蓝牙协议栈;
3)SoftDevice检查0x10001014处是否保存有有效的BootLoader地址, 如果不是跳转到0x14000处的APP执行,流程结束.
4)如果是有效bootloader地址,SoftDevice就跳转到BootLoader执行;
5)BootLoader进行他的业务处理工作;
6)BootLoader跳转到0x14000处的APP执行,流程结束.
3、OTA升级的原理:
正常启动之后,程序会运行在app程序,如果它支持OTA的话,使用 nrftoolbox(推荐使用 v2.0.0 以上)或者 nrf connect 可以进行空中升级,只要向该 DFU control point 特征值中写入 0x01,设备便断开连接,上报 BLE_DFU_EVT_ENTERING_BOOTLOADER 事件,这时程序会跳转到bootloader中,等待OTA升级指令,使用nRF connect进行空中升级,如果升级成功,程序又会自动跳转(setting文件的作用下)到app程序,正常运行;
二、小潘的分享:
1、文档链接:
首先非常感谢小潘大神的分享,详细的操作文档请点击这个。
2、遇到的问题:
根据文档进行操作,编译bootloader出现两个错误,在解决第一个问题(uecc.h)时就卡住了,执行make指令总是提示这个,以为是mingw安装有问题,重新试了好多次都不行~
搜了很多资料,最后找到了这个, 按照4、5的操作,解决了第一个问题;接着根据小潘的文档,一路很顺畅的完成了。
三、OTA升级实操(从零开始建立一个支持dfu服务的应用):
1、参考文档1;
参考文档2;
2、sdk版本是nRF5_SDK_12.2.0,没有dfu服务的工程选择的是app_ble_uart:
1)添加ble_dfu.c、nrf_dfu_settings.c、nrf_dfu_flash.c(app_scheduler.c、crc32.c和nrf_nvmc.c选择添加)到自己的工程中,添加对应头文件的路径;
2)参考experimental_ble_app_buttonless_dfu工程,在main.c文件里找到service_init()函数,添加如下代码:
ble_dfu_init_t dfus_init;
memset(&dfus_init, 0, sizeof(dfus_init));
dfus_init.evt_handler = ble_dfu_evt_handler;
dfus_init.ctrl_point_security_req_write_perm = SEC_SIGNED;
dfus_init.ctrl_point_security_req_cccd_write_perm = SEC_SIGNED;
err_code = ble_dfu_init(&m_dfus, &dfus_init);
APP_ERROR_CHECK(err_code);
找到ble_evt_dispatch()函数,添加如下代码:
ble_dfu_on_ble_evt(&m_dfus, p_ble_evt);
3)编译后,解决提示的错误,按照小潘的文档,烧录,可以成功进行dfu升级;
4)有一个问题:需要把ble_nus_init()屏蔽掉蓝牙才能搜索到,可能是某些属性冲突了,修改了服务的uuid还是不行,暂时先记在这里;
遗留问题收敛:2018-01-12
1、参考文档1;
参考文档2;
2、如图,解决方法可以修改Vendor specific UUID的个数,或者把UUID的类型修改为非BLE_UUID_TYPE_BLE;
PS:如果使用高版本SDK,并且程序中已经自定义基准UUID的话,这个时候添加DFU代码需要修改基准UUID允许添加的个数,因为默认是1。否则ble_dfu_init初始化函数里面调用sd_ble_uuid_vs_add 函数时就会出错。
相关问题补充一:2018-03-06
1、在其他的资料中看到的解释:
相关问题补充二:2018-07-27
1、使用过程中遇到的问题:
烧录的bootloader_setting.hex一定要是对应的application.hex生成的,如果两个不对应,会卡在bootloader里面;
什么意思呢?就是说如果你已经按照softdevice-->bootloader_setting-->bootloader-->application烧录,想再去调试的话直接下载application.hex是不行的,会卡在bootloader里面,因为这个application.hex跟你烧录的bootloader_setting.hex是不对应的。
那怎么办呢?先擦除,只烧录softdevice-->application就行,这样就可以调试了。