silicon EFR32BG22 应用内进行OTA

通过Simplicity Studio新建的蓝牙工程默认是带有appLoader的,appLoader的一个缺点就是只能实现单区跟新,而且原厂没有开放appLoader的代码,有的时候可能没办满足用户的需求。比如在更新的时候需要led处于快闪的模式,appLoader就没办法做到。

appLoader的更新流程参考: https://blog.csdn.net/chengbaojin/article/details/113369125

下面说一下如何实现在用户的程序中实现OTA。

本文使用的环境

  • sdk: gecko_sdk_3.1
  • IDE: Simplicity Studio 5.0

一 flash存储情况

在这里插入图片描述
做空中升级之前是需要先烧录一个BootLoader。做双区更新一般情况下flash需要512KB及以上的大小。本文使用的是这个工程bootloader-storage-internal-single-512k

BootLoader的工程需要设置Slot 0也就是app bank2的起始地址,app bank2也就是新固件的存放地址。这里的起始地址是278528(0x4 4000)。如下图所示:
在这里插入图片描述

根据工程的autogen\linkerfile.ld文件可知,用户的应用程序存放的起始地址是0x6000,也就是说留给BootLoader的空间为24KB。

在这里插入图片描述

二 在工程中新建一个OTA服务

新建的工程默认有一个OTA服务,这个服务只有一个Control characteristic,而且在gatt_configuration.btconf文件中不可修改。这个服务不是我们所需要的,需要删除并自己新建一个OTA服务。
在这里插入图片描述

可以在下图的位置删除这个服务:在这里插入图片描述
然后自己手动添加服务,如下图:
在这里插入图片描述
这里的Data characteristic需要选择user如下图:
在这里插入图片描述
在这里插入图片描述

三 升级流程

  • 通过Control characteristic进入升级模式,通过data characteristic接收新固件
  • 设置标志,并重启
    bootloader_setImageToBootload(0);
    bootloader_rebootAndInstall();
  1. 初始化BootLoader

当接收到sl_bt_evt_system_boot_id事件之后调用bootloader_init进行初始化

 /* bootloader init must be called before calling other bootloader_xxx API calls */
 bootloader_init();

 /* read slot information from bootloader */
 if(get_slot_info() == BOOTLOADER_OK)
 {
   /* the download area is erased here (if needed), prior to any connections are opened */
   erase_slot_if_needed();
 }
  1. 向Control characteristic写0,进入升级模式
//实测发现向Control characteristic写0生成的是这个事件
case sl_bt_evt_gatt_server_attribute_value_id:{
      uint32_t connection = evt->data.evt_gatt_server_attribute_value.connection;
      uint32_t characteristic = evt->data.evt_gatt_server_attribute_value.attribute;
      LOGD("characteristic == %d\r\n",characteristic);
      if(characteristic == gattdb_ota_control)
      {
        switch(evt->data.evt_gatt_server_attribute_value.value.data[0])
        {
        case 0://Erase and use slot 0
          // NOTE: download are is NOT erased here, because the long blocking delay would result in supervision timeout
          //bootloader_eraseStorageSlot(0);
          LOGD("control 0\r\n");
          ota_image_position=0;
          ota_in_progress=1;
          sl_bt_gatt_server_send_user_write_response(connection,characteristic,0);
          break;
        case 3://END OTA process
          //wait for connection close and then reboot
          ota_in_progress=0;
          ota_image_finished=1;
          LOGD("upload finished. received file size %u bytes\r\n", ota_image_position);
          sl_bt_gatt_server_send_user_write_response(connection,characteristic,0);
          break;
        default:
          break;
        }
      }
    }
      break;
  1. 向Data characteristic写新的固件

bootloader_writeStorage的起始地址就是BootLoader中设置的slot 0的地址。bootloader_writeStorage其实是在BootLoader中实现的,这里只是一个地址的引用。

 case sl_bt_evt_gatt_server_user_write_request_id:
    {
      uint32_t connection = evt->data.evt_gatt_server_user_write_request.connection;
      uint32_t characteristic = evt->data.evt_gatt_server_user_write_request.characteristic;

      LOGD("characteristic == %d\r\n",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
          // NOTE: download are is NOT erased here, because the long blocking delay would result in supervision timeout
          //bootloader_eraseStorageSlot(0);
          LOGD("control 0\r\n");
          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;
          LOGD("upload finished. received file size %u bytes\r\n", ota_image_position);
          break;
        default:
          break;
        }
      } else if(characteristic == gattdb_ota_data)
      {
        if(ota_in_progress)
        {
            LOGD("wirite data\r\n");
          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;
        }
      }
      //gecko_cmd_gatt_server_send_user_write_response(connection,characteristic,0);
      sl_bt_gatt_server_send_user_write_response(connection,characteristic,0);
    }
      break;
  1. 升级完成之后断开连接
case sl_bt_evt_connection_closed_id:{
      // Restart advertising after client has disconnected.
      pFunction Jump_To_Application;
      uint32_t JumpAddress;

      if (ota_image_finished) {
        LOGD("Installing new image\r\n");

        bootloader_setImageToBootload(0);
     	//设置安装新固件的标志位,复位之后会进入BootLoader,BootLoader负责将bank2中的内容搬运到bank1中
        bootloader_rebootAndInstall();
      
      } else{
      sc = sl_bt_advertiser_start(
        advertising_set_handle,
        advertiser_general_discoverable,
        advertiser_connectable_scannable);
      sl_app_assert(sc == SL_STATUS_OK,
                    "[E: 0x%04x] Failed to start advertising\n",
                    (int)sc);
      }
    }
      break;

四 手机端验证

  1. 手动向Control characteristic写0
    在这里插入图片描述
  2. 选择一个.gbl文件

.gbl文件的制作方法参看:https://blog.csdn.net/chengbaojin/article/details/113369125
在这里插入图片描述
在这里插入图片描述
3. 等待升级完成
在这里插入图片描述

参考文档:

评论 9 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:精致技术 设计师:CSDN官方博客 返回首页

打赏作者

黑刀夜

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值