Uncannier Software

It's not enough to just be uncanny

Thunderboard React – Over The Air (OTA) Upgrades

Out of the box, the Thunderboard React doesn’t support Over The Air (OTA) Device Firmware Upgrade (DFU). This article describes how to modify the stock Thunderboard React firmware to enable OTA DFU.

I’ll use Silicon Labs’ standard OTA BLE Service because this enables OTA DFU in the stock Blue Gecko phone app.

In general, Silicon Labs have good documentation covering this. However there is some outdated information. This is largely due to major changes made in the OTA process in Bluetooth SDK 2.7.0 released in December 2017. This article provides a concise summary, correct as at Bluetooth SDK 2.10.0.

Stock Firmware

To get started, you need the Thunderboard React stock firmware. This article presumes you have familiarity with Simplicity Studio, and Eclipse and gcc more generally. Hence it is assumed you can reach the starting point of having the stock firmware building within Simplicity Studio.

Memory Map

The Thunderboard React (and all EFR32xG1 SoCs) has a memory map as follows:

This is the map for the main 256kB Flash. Additionally, there is the Information Block at 0x0FE00000 that, confusingly, includes a 10kB Bootloader area. However, this Bootloader area is defunct (because it’s too small to hold the Gecko Bootloader), and can be ignored for the purposes of this article.

The App Loader was introduced in Bluetooth SDK 2.7.0.

The Silicon Labs Thunderboard React stock firmware project comprises only the Application and App Loader. Therefore it cannot be used to program an erased Flash.

Gecko Bootloader

The Gecko Bootloader is required to enable OTA upgrades, and also to have a complete firmware image. Silicon Labs Simplicity Studio and Gecko SDK come with the stock Gecko Bootloader firmware included.

New->Project->Silicon Labs AppBuilder Project->Gecko Bootloader

Select the particular Gecko Bootloader version you want to use. 1.7.0 in the case of this article. Then select the Bluetooth in-place OTA DFU Bootloader template.

Generate the bootloader source code from the .isc file. I’ll use the default options in the .isc file so that we get the most bog basic bootloader we need to achieve OTA upgrades. I will return to more advanced features, like encryption and signing, in a future article.

Now build the Gecko Bootloader.

The Gecko Bootloader includes a post-build script (utr-bootloader_postbuild.sh in my case), with contents such as this:

echo " "
echo "Add first stage bootloader to image (${FILENAME}-combined.s37)"
echo " "
"${COMMANDER}" convert "/opt/SimplicityStudio_v4/developer/sdks/gecko_sdk_suite/v2.4/platform/bootloader/build/first_stage/gcc/first_stage_btl_efx32xg11.s37" "${FILENAME}.s37" -o "${FILENAME}-combined.s37"

Thus it combines the first and second stage bootloaders into a single S-record file.

If you’re doing this in Windows, I presume it’s a batch file.

Stock Firmware Changes

Add The Silicon Labs OTA Service

Open the stock application .isc file and drag the Silicon Labs OTA Service in the application’s list of services. The only required characteristic is Silicon Labs OTA Control.

So that a gecko_evt_gatt_server_user_write_request_id event is generated when the characteristic is written, the Value Type should be set to user.

Save the file and Generate the BLE code.

This will give the application an OTA service that the Silicon Labs’ Blue Gecko phone app can recognize and use.

Enable OTA In The Stack Configuration

The .ota.flags, .ota.device_name_len and ota.device_name_ptr elements need to be added to the Gecko configuration. These define the BLE device name that will be used when the Thunderboard reboots into DFU mode.

static const gecko_configuration_t config = {
    .config_flags = 0,
    .bluetooth.max_connections = MAX_CONNECTIONS,
    .bluetooth.heap = bluetooth_stack_heap,
    .bluetooth.heap_size = sizeof(bluetooth_stack_heap),
    .bluetooth.sleep_clock_accuracy = 100, // ppm
    .gattdb = &bg_gattdb_data,
    .max_timers = 16,
    .ota.flags = 0,
    .ota.device_name_len = 3,
    .ota.device_name_ptr = "OTA"

main.c changes: https://github.com/gregbreen/uncannier-thunderboard-react/commit/211206cf8230c7ddddaef6b910564f3bfd04f919#diff-ddd9a410c8d39c65ecdf4feda61adad3

Trigger Reboot Into OTA DFU Mode

The Gecko BLE stack generates a gecko_evt_gatt_server_user_write_request_id event when the phone app writes to the Silicon Labs OTA Control characteristic (gattdb_ota_control). Upon receiving this event, the application triggers a reboot into OTA DFU mode. This is a two-step process; firstly it gracefully closes the connection:

boot_to_ota = true;
// Send response to write request
gecko_cmd_gatt_server_send_user_write_response( conGetConnectionId(), gattdb_ota_control, bg_err_success );
// Close connection to enter OTA DFU mode
gecko_cmd_endpoint_close( conGetConnectionId() );

Secondly, the resultant gecko_evt_le_connection_closed_id event triggers the reboot.

if( boot_to_ota )
    // Enter to OTA DFU mode
    gecko_cmd_system_reset( 2 );

ota_service.c new file: https://github.com/gregbreen/uncannier-thunderboard-react/commit/211206cf8230c7ddddaef6b910564f3bfd04f919#diff-8ed1db484470df67fc607778ededfe50

app_ble.c changes: https://github.com/gregbreen/uncannier-thunderboard-react/commit/211206cf8230c7ddddaef6b910564f3bfd04f919#diff-3f1c1a261d442a80b130fec3d59a8180

Custom Post-Build Step: GBL File Generation

You need to create Gecko Bootloader (GBL) files to be able to perform OTA upgrades. Silicon Labs provide the Simplicity Commander tool for this task.

Silicon Labs also provide the create_bl_files.sh script as a wrapper for Simplicity Commander. I’m no big fan. It generates every flavour of GBL file, and it can’t handle your project having more than one build configuration. Furthermore, it doesn’t generate a consolidated HEX, SREC or BIN file that combines application, app loader, and bootloader; this is a minor oversight in my opinion.

So instead, I have my own custom script as a post-build step.

# Extract S-record files for the apploader and application individually
arm-none-eabi-objcopy -O srec -j .text_apploader* "${1}/${2}.axf" "${1}/apploader.srec" >/dev/null
arm-none-eabi-objcopy -O srec -j .text_application* "${1}/${2}.axf" "${1}/application.srec" >/dev/null
# Create a combined image HEX file - bootloader (first and second stage), apploader and application - this is flashable
commander convert ../utr-bootloader/Release/utr-bootloader-combined.s37 ./$1/apploader.srec ./$1/application.srec --outfile ./$1/utr-image.hex
# Create (unsigned & unencrypted) GBL files for OTA updates
commander gbl create "${1}/utr-apploader.gbl" --app "${1}/apploader.srec" >/dev/null
commander gbl create "${1}/utr-application.gbl" --app "${1}/application.srec" >/dev/null

You can then flash the consolidated image to have an Thunderboard React with an OTA Service.

OTA DFU With The Blue Gecko App

The OTA Service is now visible in the Blue Gecko app. And OTA is a menu option. An update can then be performed using the GBL files.

Uncannier Pull Request



  1. https://www.silabs.com/documents/login/user-guides/ug136-ble-c-soc-dev-guide.pdf
  2. https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf
  3. https://www.silabs.com/documents/login/application-notes/an1086-gecko-bootloader-bluetooth.pdf
Tagged , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *