EFR32如何在应用程序中通过BLE 进行OTA升级

Bluetooth SDK里的soc-empty例程里面包含了一个AppLoader,可以用OTA_DFU(Over The Air -Device Firmware Upgrade)的方式升级应用程序。但是这个方式需要主机端(手机APP)也按照Silabs定义的OTA profile(包括服务和特性的UUID,以及升级过程中的主从设备之间的交互流程)来做。

实际应用中,通常需要按照生态系统(如腾讯连连)定义的OTA协议来对设备的软件进行升级,因此需要使用Gecko Bootloader配合应用程序来实现。Gecko Bootloader有standalone和application两种模式,这里要用后者,升级的流程如下图:

主机端仍可使用AN1086所述的方法:

  1. 把一块开发板连接到电脑,给它烧写Bluetooth SDK中的例程NCP–Empty Target。
  2. 在电脑上安装MinGW开发工具,然后在命令行窗口cd到目录SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\app\bluetooth\examples_ncp_host\ota_dfu 中,执行mingw32-make,就可以编译出ota-dfu.exe可执行文件。

设备端使用另一块开发板,需要制作BootLoader和应用程序两个工程:

  1. 创建BootLoader工程时,使用Gecko Bootloader的Internal Storage Bootloader(single image on 512kB device)例程,完全按缺省配置Generate代码就可以了。编译后用“Debug”或“Flash Programmer”把它烧写到开发板中。
  2. 使用Bluetooth SDK里的soc-empty例程创建应用程序,
  • 把SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.4\platform\bootloader\api文件夹中的所有文件复制到工程目录下的\platform\bootloader\api文件夹里;
  • 在工程目录下新建\platform\bootloader\core文件夹,并把SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.4\platform\bootloader\core\btl_util.h复制到里面。
  • 在应用程序的工程设置中,把apploader从链接的目标中删掉,如下面一行:

${workspace_loc:/${ProjName}/protocol/bluetooth/lib/EFR32MG13P/GCC/binapploader.o}

设置完了如下图:

  • 修改main.c文件,如下:

#define OTA_DEMO 1

#if OTA_DEMO

#include "btl_interface.h"

#include "btl_interface_storage.h"

int ota_image_position, ota_in_progress, ota_image_finished;

uint32_t connection, characteristic;

BootloaderStorageSlot_t slot;

uint32_t flash_page_erased;

#else

// Flag for indicating DFU Reset must be performed

uint8_t boot_to_dfu = 0;

#endif

在主循环中:

      case gecko_evt_le_connection_closed_id:

#if OTA_DEMO

    if(ota_image_finished)

    {

        bootloader_setImageToBootload(0);

        bootloader_rebootAndInstall();

    }

#else

        /* Check if need to boot to dfu mode */

        if (boot_to_dfu) {

          /* Enter to DFU OTA mode */

          gecko_cmd_system_reset(2);

        } else {

          /* Restart advertising after client has disconnected */

          gecko_cmd_le_gap_start_advertising(0, le_gap_general_discoverable, le_gap_connectable_scannable);

        }

#endif

        break;

      case gecko_evt_gatt_server_user_write_request_id:

#if OTA_DEMO

       /*OTA support*/

        connection = evt->data.evt_gatt_server_user_write_request.connection;

        characteristic = evt->data.evt_gatt_server_user_write_request.characteristic;

        if (characteristic == gattdb_ota_control)

       {

           switch (evt->data.evt_gatt_server_user_write_request.value.data[0])

           {

           case 0://Erase and use slot 0

              bootloader_init();

              //bootloader_eraseStorageSlot(0);

              bootloader_getStorageSlotInfo(0, &slot);

              bootloader_eraseRawStorage(slot.address, FLASH_PAGE_SIZE);

              flash_page_erased = slot.address;

              ota_image_position = 0;

              ota_in_progress = 1;

              break;

           case 3://END OTA process

              //wait for connection close and then reboot

              ota_in_progress = 0;

              ota_image_finished = 1;

              break;

           default:

              UARTDRV_Transmit(handle, "unknown OTA command\n", 20, callback);

              break;

           }

       } else if (characteristic == gattdb_ota_data)

       {

           if(ota_in_progress)

           {

              bootloader_writeStorage(0,//use slot 0

                  ota_image_position,

                  evt->data .evt_gatt_server_user_write_request.value.data,

                  evt->data.evt_gatt_server_user_write_request.value.len);

              ota_image_position += evt->data.evt_gatt_server_user_write_request.value.len;

              if((slot.address + ota_image_position) > flash_page_erased)

              {

                  flash_page_erased += FLASH_PAGE_SIZE;

                  if(flash_page_erased < (slot.address + slot.length))

                     bootloader_eraseRawStorage(flash_page_erased, FLASH_PAGE_SIZE);

              }

           }

       } else

       {

           UARTDRV_Transmit(handle, "unknown characteristic\n", 23, callback);

       }

       gecko_cmd_gatt_server_send_user_write_response(connection, characteristic, 0);

#else

        if (evt->data.evt_gatt_server_user_write_request.characteristic == gattdb_ota_control) {

          /* Set flag to enter to OTA mode */

          boot_to_dfu = 1;

          /* Send response to Write Request */

          gecko_cmd_gatt_server_send_user_write_response(

            evt->data.evt_gatt_server_user_write_request.connection,

            gattdb_ota_control,

            bg_err_success);

          /* Close connection to enter to DFU OTA mode */

          gecko_cmd_le_connection_close(evt->data.evt_gatt_server_user_write_request.connection);

        }

#endif

        break;

  • 在GATT配置器中添加Silicon Labs OTA Data特性,并把它设置为可变长度和可写,如下图:

记得点“Generate”生成代码,然后编译并用“Debug”或“Flash Programmer”把它烧写到开发板中。至此,设备端的初始软件就准备好了。

测试OTA升级软件功能:

  • 稍微修改应用程序,如把串口打印的“BLE OTA APP V1”改为“BLE OTA APP V2”,重新编译生成目标文件。
  • 然后,执行工程目录里的create_bl_files.bat脚本,它会在工程目录里创建output_gbl\application.gbl文件。
  • 把前面做好的ota-dfu.exe文件复制到output_gbl文件夹里,在命令行窗口执行它(COM8是主机端开发板的JLINK CDC UART串口,波特率必须用115200,00:0B:57:93:31:A2是设备端的蓝牙MAC地址),结果如下:

PS E:\Temp\workspace\soc-empty_uart_test\output_gbl>  .\ota-dfu.exe COM8 115200 .\application.gbl 00:0B:57:93:31:A2

System rebooted

Local address:00:0b:57:31:5a:e1

Bytes to send:141588

Scanning...OK

Device address found, connecting.

Connecting...OK

Discovering services...ATT MTU exchanged: 247

OK

Discovering characteristics...OK

    Control handle:19

    Data handle:21

    OTA Data characteristic properties:0x0c

DFU mode...OK

OTA DFU - write with response

100% 39.06kbit/s

time: 29.00s

Finishing DFU block...OK

Closing connection...OK

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值