自闭症康复网,内容丰富有趣,生活中的好帮手!
自闭症康复网 > Silicon EFR32BG22 BG22(1) 片内OTA(双bank)

Silicon EFR32BG22 BG22(1) 片内OTA(双bank)

时间:2024-05-29 05:18:01

相关推荐

Silicon EFR32BG22 BG22(1) 片内OTA(双bank)

1 前提

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

1.1环境

(1)sdk: gecko_sdk_3.2

(2)IDE: Simplicity Studio 5.0

参考的链接:

(1)参考地址 写的很详细

(2)官方的git路径:参开地址

(3)boot

1.2 flash的分区情况

2 实现步骤

2.1 boot 工程的选择

做空中升级之前是需要先烧录一个BootLoader。做双区更新一般情况下flash需要512KB及以上的大小。本文使用的是这个工程Internal Storage Bootloader (single image on 512kB device)

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

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

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

基于soc_empty -新建的工程默认有一个OTA服务,这个服务只有一个**Control characteristic,**而且在gatt_configuration.btconf文件中不可修改。这个服务不是我们所需要的,需要删除并自己新建一个OTA服务。

可以在下图的位置删除这个服务:

然后自己手动添加服务,如下图:

这里的Data characteristic需要选择user如下图:

到此图形配置完成

3 升级流程

(1)通过Control characteristic进入升级模式,通过data characteristic接收新固件

设置标志,并重启

(2)bootloader_setImageToBootload(0);

(3)bootloader_rebootAndInstall();

3.2 代码的添加

1:基于app.c文件添加

#include "btl_interface.h"#include "btl_interface_storage.h"/* Flag for indicating DFU Reset must be performed */static BootloaderInformation_t bldInfo;static BootloaderStorageSlot_t slotInfo;/* OTA variables */static uint32_t ota_image_position = 0;static uint8_t ota_in_progress = 0;static uint8_t ota_image_finished = 0;static uint16_t ota_time_elapsed = 0;

2:添加函数

/************************************************************************get_slot_info* @return*/static int32_t get_slot_info(void){int32_t err;bootloader_getInfo(&bldInfo);BLE_RTT("Gecko bootloader version: %u.%u\r\n", (bldInfo.version & 0xFF000000) >> 24,(bldInfo.version & 0x00FF0000) >> 16);err = bootloader_getStorageSlotInfo(0, &slotInfo);if(err == BOOTLOADER_OK){BLE_RTT("Slot 0 starts @ 0x%8.8x, size %u bytes\r\n", slotInfo.address, slotInfo.length);}else{BLE_RTT("Unable to get storage slot info, error %x\r\n", err);}return(err);}```c```c

/***********************************************************************************

*erase_slot_if_needed

*/

static void erase_slot_if_needed(void)

{

uint32_t offset = 0, num_blocks = 0, i = 0;

uint8_t buffer[256];

bool dirty = false;

int32_t err = BOOTLOADER_OK;

/* check the download area content by reading it in 256-byte blocks */num_blocks = slotInfo.length / 256;while((dirty == 0) && (offset < 256*num_blocks) && (err == BOOTLOADER_OK)){err = bootloader_readStorage(0, offset, buffer, 256);if(err == BOOTLOADER_OK){i = 0;while(i < 256){if(buffer[i++] != 0xFF){dirty = true;break;}}offset += 256;}BLE_RTT("erase_slot_if_needed.....");}if(err != BOOTLOADER_OK){BLE_RTT("error reading flash! %x\r\n", err);}else if(dirty){BLE_RTT("download area is not empty, erasing...\r\n");bootloader_eraseStorageSlot(0);BLE_RTT("done\r\n");}else{BLE_RTT("download area is empty\r\n");}return;

}

static void print_progress(void){// estimate transfer speed in kbpsint kbps = ota_image_position*8/(1024*ota_time_elapsed);BLE_RTT("pos: %u, time: %u, kbps: %u\r\n", ota_image_position, ota_time_elapsed, kbps);}

(3)初始化BootLoader

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

// bootloader init must be called before calling other bootloader_xxx API callsbootloader_init();// read slot information from bootloaderif(get_slot_info() == BOOTLOADER_OK){// the download area is erased here (if needed), prior to any connections are openederase_slot_if_needed();}else{BLE_RTT("Check that you have installed correct type of Gecko bootloader!\r\n");}

4.向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 rebootota_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;

5.向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 rebootota_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 0ota_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;

6. 升级完成之后断开连接,所以需要添加固件的复制

// This event indicates that a connection was closed.case sl_bt_evt_connection_closed_id:BLE_RTT("Connection closed, reason: 0x%2.2x\r\n", evt->data.evt_connection_closed.reason);if(ota_image_finished){BLE_RTT("Installing new image.......\r\n");bootloader_setImageToBootload(0);bootloader_rebootAndInstall();}else{ble_adv_start(true);BLE_RTT("Started advertising\n");}break;

四 手机端验证

1.手动向Control characteristic写0

2 .选择一个.gbl文件

.gbl文件的制作方法参看

(1) 制作升级文件

当应用程序编译完成之后,只要执行根目录下的create_bl_files.bat批处理文件,平台就会自动帮我们生成可用来升级的.gbl文件。

第一次使用该文件的时候需要添加两个用户变量:

可以百度怎么在电脑上添加用户变量

然后点击这里就可以生成文件

去对应的路径找文件

(2):app连接成功后

手动向Control characteristic写0

(3)在选择需要升级的文件

4. 等待升级完成

如果觉得《Silicon EFR32BG22 BG22(1) 片内OTA(双bank)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。