KBA_BT_0802: Uploading images to internal/external flash using OTA DFU
09/263/2017 | 12:58 PM
Gecko Bootloader can load application images into the application area from different sources.
It can load from host controller via UART/SPI.
It can load from a remote device OTA (over-the-air) via Bluetooth connection with the help of the Apploader.
It can load from internal flash (if the internal flash is big enough to accomodate both the application code and an upgrade image).
It can load from external flash.
What it cannot do is uploading the application image to a temporary storage slot of the internal/external flash before loading it from there into the application area. This article helps you implement the missing step: uploading the image to the internal/external flash via a Bluetooth connection.
To make the OTA uploader compatible with Silicon Labs Bluetooth OTA Apploader that loads the image directly to the application area, first we have to understand how the standard OTA DFU method works.
The standard OTA DFU sequence (implemented in the OTA Apploader) looks like this:
App is running.
Device is reset into DFU mode. In this mode the bootloader will start the Apploader instead of the Application. The Apploader is a simple application with a minimal Bluetooth stack, that handles the upload process. The Apploader uses the API of the Gecko Bootloader to decode the GBL files and to store the application image in the flash. (Note: before Bluetooth SDK v2.7 the Apploader was built into the stack binary and was referenced as supervisor code. To learn more about the legacy OTA update process please refer to AN1045: Bluetooth ® Over-the-Air Device Firmware Update for EFR32xG1 and BGM11x Series Products. Standalone Apploader is used only since Bluetooth SDK v2.7)
The Apploader advertises and waits for a Bluetooth connection
The Apploader waits for the OTA start command (using OTA control characteristic)
The Apploader starts receiving the GBL file (using OTA data characteristic)
The headers of the GBL file are stored in Slot 0 to be parsed
After parsing the headers, the rest of the GBL file is decoded on-the-fly, and the application is copied right to the application area, overwriting the old application
The Apploader receives the OTA end command and restarts the device in normal mode.
The OTA uploader uses a similar process:
App is running (device is not reset, since the uploader is implemented in the user application)
If there are multiple slots, the remote device chooses which slot to upload to, using a custom characteristic (e.g. slot0. Slot0 can be either in the internal or in the external flash. The application do not have to know this, flash is handled by the bootloader API)
The uploader waits for the OTA start command (using OTA control characteristic)
The uploader starts receiving the GBL file (using OTA data characteristic)
the GBL file is saved into slot0/slot1 as it is using the bootloader API (the application does not have to know where Slot0/Slot1 is located, bootloader API handles the writing)
The uploader receives the OTA end command
If there are multiple slots, the remote device may upload a new image to the other slot(s)
The remote device chooses which slot to bootload from using a custom characteristic
The device is reset in bootloader mode
The bootloader parses the given slot, retrieves the Application code from the GBLfile and copies the code to the application area from the internal/external flash
The bootloader starts the new Application
Implementation
The attached code implements image uploading to the slots using the standard OTA process. It is also extended with the possibility to select a slot to upload to, and to select a slot to boot from. You are free to modify this example according to your needs.
To create a project with multislot OTA DFU follow these steps:
Create an Internal Storage Bootloader (multiple images) or a SPI Flash Storage Bootloader (multiple images) project in Simplicity Studio
Check the Storage Slot configuration in AppBuilder and modify it according to your needs.
Generate and build the project
Create a SoC – Empty project
Remove the Silicon Labs OTA service from your GATT database if it is present
Add the Silicon Labs OTA service in Visual GATT Editor (BLE GATT Configurator)
On the left plane select Services
Find Silicon Labs OTA services
Drag and drop it to the right pane
Select the Silicon Labs OTA Data characteristic
Set its type to user (the content will not be stored to database but processed by the application)
Set its length to 244
Set Write and Write Without Response properties to true
Select the Silicon Labs OTA control characteristic
set its type the user
Set Write and Write Without Response properties to true
Add Slot Manager service in Visual GATT Editor (only needed if you want to manage multiple slots)
Add a new service, named e.g. Slot Manager Service
Add a new characteristic within this service called e.g. Upload Slot (this will be used to select a slot to upload data to)
Set its ID to upload_slot (needed for reference in the code)
Set its type to hex
Set its length to 1
Add Read and Write properties
Add a new characteristic within this service called e.g. Bootload Slot (this will be used to trigger bootload from the given slot)
Set its ID to boot_slot (needed for reference in the code)
Set its type to hex
Set its length to 1
Add Write property
Now your GATT database should look like this:
Click Generate to build the GATT database
Copy the attached ota_dfu_multislot.c and ota_dfu_multislot.h files into the project
Copy btl_interface.c and btl_interface_storage.c from C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v1.1\platform\bootloader\api to your project
Go to Project Properties > C/C++ Build > Settings and add the following folders to the Includes:
"${StudioSdkPath}/platform/bootloader"
"${StudioSdkPath}/platform/bootloader/api"
or copy the .h files from these folders to your project
Remove apploader from the project as we won't need it anymore:
Go to Project Properties > C/C++ Build > Settings
Go to GNU ARM C Linker > Miscellaneous or IAR Linker for ARM > Library
Remove binapploader.o from the list
Add the followings to main.c
Add #include “ota_dfu_multislot.h” to the beginning of main.c
Add ota_dfu_handle_event(evt); after evt = gecko_wait_event();
Remove the code that triggers DFU reset upon writing into ota_control characteristic
(Note: setting gecko_bootloader=true in the .isc file will copy btl_interface.c and btl_interface_storage.c into your project again. Remove the instances you copied before to avoid duplicated definitions)
Flash the image to your device
Usage
Create full.gbl file from the application you want to upload. (Note: since the uploader is implemented in the user application, and not in the Apploader, you should implement the uploader in the application to be uploaded, as well!!) E.g.
Make a copy of your multislot OTA DFU project
Change the Device Name from “Empty Example” to “Updated app” in the Visual GATT Editor
Press Generate
Build the project
Run create_bl_files.bat
Find the .gbl files in output_gbl folder
Copy full.gbl to your smartphone (in case of Android copy it to SiliconLabs_BGApp/OTAFiles/myproject, in case of iOS upload it to iCloud)
Open Blue Gecko app on your smartphone
Find your device with Bluetooth browser (advertising as Empty Example) and connect to it
Find the unknown service and open it (this is your custom service including Upload slot and Bootload slot characteristics)
Open the first characteristic (this is the upload characteristic) and write the slot number in it, you want to upload to
In the local menu select OTA
Select the partial OTA tab
Select the folder and the full.gbl file you want to upload
Click OTA. The file will be uploaded to the selected slot.
Now open the second characteristic in the unknown service (Bootload slot) and write the slot number in it, you want to load the application from. The device will be reset and the application will be loaded.
Disconnect and find your device advertising itself as “Updated app”
I get an error "GATT:BUSY" when I try to do the OTA part.
What could be the problem?
I followed all the steps in this tutorial.
0
Hi,
GATT:BUSY is error code 0x84 which corresponds to OTA_EraseError in the provided example. It means that your storage wasn't erased properly. Please check your Slot settings, maybe it points to some invalid or read-only memory space. Or you have set a non-existent slot to be erased via the upload_slot characteristic.
Arnold
0
I have followed all the steps mentioned above (used with BTMesh SDK and Blue Gecko board) and I am getting Error 133 (0x85): GATT ERROR
I have generated GATT service for OTA using BTMesh SDK. First time the Blue gecko board got connected with "BlueGecko App" and have copied OTA files as well in the mobile App storage but before OTA get started, App got crashed. Right now, I am facing issue while connecting Blue gecko board with Android App. I have tested it with "BlueGecko App" it is showing "connection timeout".
Also, I have tried with another Blue Gecko module and didn't changed anything in soc-btmesh-empty code (just to verify the connection with the App), only dumped boot loader code and then application code in the module, but it didn't work, getting same error with connection establishment.
Please guide.
Thanks,
Shruti
0
Hi,
Sorry for the late response. This solution was not tested with BT mesh SDK, so I cannot guarantee it works.
The provided code have error codes between 0x81-0x84. Getting error code 0x85 suggests that you still use the appLoader to upload the image. Did you remove the default event handler for gecko_evt_gatt_server_user_write_request_id?
Best Regards,
Arnold
0
Is this needed if we only want one running application and one upload slot?
[ bootloader ] [ running app ] [ GBL ]
Also, if we use this method and use the user application method can we only upload the app.gbl and not the full.gbl?
Richard
0
Hello platyrhynchos,
When I tried testing it on BLE mesh SDK 1.6, I got an error during compilation
undefined reference to gecko_cmd_endpoint_close
at line 76 of the ota_dfu_multislot.h file.
0
Any guide on how to do this on simplicity v5? I want to use bg22 with 512kb flash and use storage slot to save blueooth downloads and parse data received
KBA_BT_0802: Uploading images to internal/external flash using OTA DFU
Gecko Bootloader can load application images into the application area from different sources.
What it cannot do is uploading the application image to a temporary storage slot of the internal/external flash before loading it from there into the application area. This article helps you implement the missing step: uploading the image to the internal/external flash via a Bluetooth connection.
This article guides you through how to upload images to storage slots using the standard OTA DFU process (used by the OTA Apploader). To learn how to load the uploaded images from the slots into the application area please read this article: https://www.silabs.com/community/wireless/bluetooth/knowledge-base.entry.html/2017/07/19/switching_betweenfi-GnNI
To make the OTA uploader compatible with Silicon Labs Bluetooth OTA Apploader that loads the image directly to the application area, first we have to understand how the standard OTA DFU method works.
The standard OTA DFU sequence (implemented in the OTA Apploader) looks like this:
The OTA uploader uses a similar process:
Implementation
The attached code implements image uploading to the slots using the standard OTA process. It is also extended with the possibility to select a slot to upload to, and to select a slot to boot from. You are free to modify this example according to your needs.
To create a project with multislot OTA DFU follow these steps:
"${StudioSdkPath}/platform/bootloader"
"${StudioSdkPath}/platform/bootloader/api"
or copy the .h files from these folders to your project
http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/Adding-Gecko-Bootloader-to-Bluetooth-projects/ta-p/195432
(Note: setting gecko_bootloader=true in the .isc file will copy btl_interface.c and btl_interface_storage.c into your project again. Remove the instances you copied before to avoid duplicated definitions)
Usage
Hey,
I get an error "GATT:BUSY" when I try to do the OTA part.
What could be the problem?
I followed all the steps in this tutorial.
Hi,
GATT:BUSY is error code 0x84 which corresponds to OTA_EraseError in the provided example. It means that your storage wasn't erased properly. Please check your Slot settings, maybe it points to some invalid or read-only memory space. Or you have set a non-existent slot to be erased via the upload_slot characteristic.
Arnold
I have followed all the steps mentioned above (used with BTMesh SDK and Blue Gecko board) and I am getting Error 133 (0x85): GATT ERROR
I have generated GATT service for OTA using BTMesh SDK. First time the Blue gecko board got connected with "BlueGecko App" and have copied OTA files as well in the mobile App storage but before OTA get started, App got crashed. Right now, I am facing issue while connecting Blue gecko board with Android App. I have tested it with "BlueGecko App" it is showing "connection timeout".
Also, I have tried with another Blue Gecko module and didn't changed anything in soc-btmesh-empty code (just to verify the connection with the App), only dumped boot loader code and then application code in the module, but it didn't work, getting same error with connection establishment.
Please guide.
Thanks,
Shruti
Hi,
Sorry for the late response. This solution was not tested with BT mesh SDK, so I cannot guarantee it works.
The provided code have error codes between 0x81-0x84. Getting error code 0x85 suggests that you still use the appLoader to upload the image. Did you remove the default event handler for gecko_evt_gatt_server_user_write_request_id?
Best Regards,
Arnold
Is this needed if we only want one running application and one upload slot?
[ bootloader ] [ running app ] [ GBL ]
Also, if we use this method and use the user application method can we only upload the app.gbl and not the full.gbl?
Richard
Hello platyrhynchos,
When I tried testing it on BLE mesh SDK 1.6, I got an error during compilation
at line 76 of the ota_dfu_multislot.h file.