How to Add Bluetooth Low Energy (LE) Over the Air Download (OAD) to Basic Example#
Texas Instruments
1 - 2 hours read
Introduction#
Welcome to this laboratory on adding Bluetooth Low Energy (LE) Over the Air Download (OAD) functionality to a basic example! In this lab, you will learn how to enhance your Bluetooth LE application with OAD capabilities, allowing for wireless firmware updates.
Over the Air Download is a crucial feature in modern IoT devices, enabling remote updates and maintenance without physical access to the device. This can significantly reduce costs and improve the user experience for your Bluetooth LE products.
By the end of this lab, you will be able to:
Understand the basic components that need to be added to a project in order to add Bluetooth LE OAD capabilities.
Modify an existing Bluetooth LE example to include OAD functionality
Test the OAD process using provided tools
Let’s get started with upgrading your Bluetooth LE application!
It is recommended to first read the Bluetooth LE Over the Air Download (OAD) Fundamentals to understand the basics behind Over the Air Download functionality.
Prerequisites#
Hardware#
For this lab, you need one Bluetooth-enabled development board. Supported devices are:
Software and Tools for Development#
SIMPLELINK-LOWPOWER-F3-SDK Software Development Kit (SDK)
Code Composer Studio CCS / CCS Cloud or IAR
See Dependencies section of SDK release notes for required version.
Download TI SimpleLink™ Connect App#
Warning
TI SimpleLink™ Connect app does not get automatically updated. You need to update the app in your OS app store manually.
Find the TI SimpleLink™ Connect App on both OS Android and iOS.
TI SimpleLink Connect on Google App Store
Note
This laboratory will use the basic_ble example as the main reference to showcase how to add any type of OAD to it.
Basic Components to enable Bluetooth LE OAD#
To start on this Bluetooth LE Over-the-Air Download (OAD) journey, let’s explore the essential files and building blocks you’ll need to incorporate into your project. Later on, you will see where these files are available in the SDK.
Writing into the NVS:
flash_interface_int_rtos_NVS.c: file that contains the functions required to write data to internal flash via RTOS NVS driver.flash_interface_ext_rtos_NVS.c: file that contains the functions required to write data to external flash via RTOS NVS driver.flash_interface.h: file that abstracts flash operations for OAD this allows on-chip and off-chip OAD to use the same flash APIs.sw_update.candsw_update.h: file that contains function for OAD image header validation.
OAD GATT Service:
oad_profile.candoad_profile.h: implements the TI proprietary OAD profile.oad_service.candoad_service.h: implements the TI proprietary OAD services.oad_reset_service.candoad_reset_service.h: implements the TI proprietary OAD Reset Service.
For further details about the function of the OAD Profile and Service, please see the Section
OAD Protocol/ Bluetooth LE Profileinside Bluetooth LE Over the Air Download (OAD) Fundamentals.Command Linker File symbols, structure and flash sectors allocations: Take a look at the
.cmdfile of a basic_ble project for reference on the structure and values that are used when implementing one of the three different OAD types. You can see what symbols and values will be used for each type of OAD by following the defines:OAD_APP_OFFCHIP,OAD_APP_ONCHIP,OAD_PERSISTENT, andOAD_DUAL_IMAGE.Generation of binary image file through
imgtool: To create the images for the mcuboot to be stored in sections in flash also known asslots, there is a post-build-step added, which calls the mcubootimgtool. The tool adds the 0x100 byte header (which includes information such as the version, image size, etc), and the trailer (which includes the key/hash/signature). The image can also be padded (–pad) to fill the slot size. The padding also adds some copy flags and status bits which are needed for Off-Chip OAD images. This means that Off-Chip OAD Images are required to be padded to the overall slot size (0x76000 in the examples). On-Chip images do not need to be padded.
Steps to add OAD components#
Open the project
Propertiesand go toBuild→Arm Compiler→Include Optionsand add the following file addresses:${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/third_party/mcuboot/boot/bootutil/include${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/third_party/mcuboot/boot/ti/source/mcuboot_app${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/ti/devices/cc23x0r5/driverlib${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/ti/drivers/nvs${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/ti/common/cc26xx/flash_interface
Inside the project
Propertiesgo toBuild→Arm Compiler→Predefined Symbolsand add the followingPre-definedsymbols depending on the type of OAD you are looking to implement:APP_HDR_ADDR=0x32000
APP_HDR_ADDR=0x6000
APP_HDR_ADDR=0x6000
Inside the project
Propertiesgo toBuild→Arm Linker→Advanced Options→Command File Preprocessingand add the followingPre-definedpreprocessor macro depending on the type of OAD you are looking to implement:OAD_APP_ONCHIP=1
APP_HDR_ADDR=0x32000
OAD_APP_OFFCHIP=1
APP_HDR_ADDR=0x6000
OAD_DUAL_IMAGE=1
APP_HDR_ADDR=0x6000
Inside the project folder, go to the
commondirectory and create a new folder namedUtiland inside of this one, create another folder namedSwUpdate. Then, add the following files inside:Inside
SwUpdate, add:<SDK directory>\source\ti\common\cc26xx\flash_interface\internal\flash_interface_int_rtos_NVS.c<SDK directory>\source\ti\common\cc26xx\flash_interface\flash_interface.h<SDK directory>\source\ti\bleapp\util\sw_update\sw_update.c<SDK directory>\source\ti\bleapp\util\sw_update\sw_update.h
Inside
SwUpdate, add:<SDK directory>\source\ti\common\cc26xx\flash_interface\external\flash_interface_ext_rtos_NVS.c<SDK directory>\source\ti\common\cc26xx\flash_interface\flash_interface.h<SDK directory>\source\ti\bleapp\util\sw_update\sw_update.c<SDK directory>\source\ti\bleapp\util\sw_update\sw_update.h
Inside
SwUpdate, add:<SDK directory>\source\ti\common\cc26xx\flash_interface\internal\flash_interface_int_rtos_NVS.c<SDK directory>\source\ti\common\cc26xx\flash_interface\flash_interface.h<SDK directory>\source\ti\bleapp\util\sw_update\sw_update.c<SDK directory>\source\ti\bleapp\util\sw_update\sw_update.h
Inside the project folder, go to the
appdirectory and insideProfilesadd the following file:<SDK directory>\examples\rtos\LP_EM_CC2340R5\ble5stack\basic_ble_oad_dual_image\app\Profiles\app_oad.c
Inside the project folder, go to the
commondirectory and inside theProfileandServicesfolder individually create a new folder namedoad. Then, add the following files inside eachoadfolder accordingly:Inside
Profiles:<SDK directory>\source\ti\bleapp\profiles\oad\oad_profile.c<SDK directory>\source\ti\bleapp\profiles\oad\oad_profile.h
Inside
Services:<SDK directory>\source\ti\bleapp\services\oad\oad_reset_service.c<SDK directory>\source\ti\bleapp\services\oad\oad_reset_service.h
Inside
Profiles:<SDK directory>\source\ti\bleapp\profiles\oad\oad_profile.c<SDK directory>\source\ti\bleapp\profiles\oad\oad_profile.h
Inside
Services:<SDK directory>\source\ti\bleapp\services\oad\oad_profile.c<SDK directory>\source\ti\bleapp\services\oad\oad_profile.h
Inside
Profiles:<SDK directory>\source\ti\bleapp\profiles\oad\oad_profile.c<SDK directory>\source\ti\bleapp\profiles\oad\oad_profile.h
Inside
Services:<SDK directory>\source\ti\bleapp\services\oad\oad_service.c<SDK directory>\source\ti\bleapp\services\oad\oad_service.h<SDK directory>\source\ti\bleapp\services\oad\oad_reset_service.c<SDK directory>\source\ti\bleapp\services\oad\oad_reset_service.h
Open
SysConfigand search forTI-Drivers→NVSto add a new instance of NVS.Add a new NVS instance with the following configuration:
Name:
CONFIG_NVSINTERNAL1Use Hardware:
NoneNVS Type:
InternalRegion Type:
PointerRegion Base:
0x32000Region Size:
0x4A000
Why do we need an extra NVS Internal instance? During the OAD process, the target device will receive segments of the OAD image through GATT writes operations. These segments need to be stored inside internal flash and this new instance is used for it. The
Region Typeis defined asPointeras it uses a pointer to the memory location of a predefined internal flash region. In addition, theRegion Base, where the OAD image is recaptioned, is defined as0x32000because it is the next memory address available in flash after theMCUBootandpersistent appimages. Finally, theRegion Sizeis set to0x4A000as it is the maximum space left to allocate the application image before reaching to the NVS section used for storing theBondinginformation needed for some Bluetooth LE secure operations.Add a new NVS instance with the following configuration:
Name:
CONFIG_NVSEXTERNALUse Hardware:
MX25R8035F SPI FlashNVS Type:
ExternalRegion Base:
0x0Region Size:
0x100000
Why do we need an external NVS instance? During the OAD process, the target device will receive segments of the OAD image through GATT writes operations. These segments need to be stored inside external flash through SPI communication and this new instance is used for it. The
Region Basedefines where in external flash the image will be written into, while theRegion Sizespecifies the size of the external flash.Add a new NVS instance with the following configuration:
Name:
CONFIG_NVSINTERNAL1Use Hardware:
NoneNVS Type:
InternalRegion Type:
PointerRegion Base:
0x41000Region Size:
0x3B000
Why do we need an extra NVS Internal instance? During the OAD process, the target device will receive segments of the OAD image through GATT writes operations. These segments need to be stored inside internal flash and this new instance is used for it. The
Region Typeis defined asPointeras it uses a pointer to the memory location of a predefined internal flash region. It is important to remember that in Dual-Image OAD we need to consider saving space in internal flash for two identical size application images. Therefore, considering theMCUBootimage size and the size of the NVS section used for storing theBondinginformation, theRegion Base, where the OAD image is received, is defined as0x41000with a maximumRegion Sizeof0x3B000(maximum space left to allocate the second application image before reaching to the NVS section used for storing theBonding).Open again the project properties and go to
Build→Steps→Post-build stepsand add the following three post build steps according to the OAD type you are implementing:${CG_TOOL_ROOT}/bin/tiarmobjcopy ${BuildArtifactFileBaseName}.out --output-target binary ${BuildArtifactFileBaseName}_noheader.bin --remove-section=.ccfg${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/tools/common/mcuboot/imgtool sign --header-size 0x100 --align 4 --slot-size 0x4A000 --version 1.0.0 --pad-header --key ${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/third_party/mcuboot/root-ec-p256.pem ${BuildArtifactFileBaseName}_noheader.bin ${BuildArtifactFileBaseName}_v1.bin${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/tools/common/mcuboot/imgtool sign --header-size 0x100 --align 4 --slot-size 0x4A000 --version 2.0.0 --pad-header --key ${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/third_party/mcuboot/root-ec-p256.pem ${BuildArtifactFileBaseName}_noheader.bin ${BuildArtifactFileBaseName}_v2.bin
${CG_TOOL_ROOT}/bin/tiarmobjcopy ${BuildArtifactFileBaseName}.out --output-target binary ${BuildArtifactFileBaseName}_noheader.bin --remove-section=.ccfg${COM_TI_SIMPLELINK_LOWPOWER_F3_SOURCE_SDK_INSTALL_DIR}/tools/common/mcuboot/imgtool sign --header-size 0x100 --align 4 --slot-size 0x76000 --version 1.0.0 --pad-header --pad --key ${COM_TI_SIMPLELINK_LOWPOWER_F3_SOURCE_SDK_INSTALL_DIR}/source/third_party/mcuboot/root-ec-p256.pem ${BuildArtifactFileBaseName}_noheader.bin ${BuildArtifactFileBaseName}_v1.bin${COM_TI_SIMPLELINK_LOWPOWER_F3_SOURCE_SDK_INSTALL_DIR}/tools/common/mcuboot/imgtool sign --header-size 0x100 --align 4 --slot-size 0x76000 --version 2.0.0 --pad-header --pad --key ${COM_TI_SIMPLELINK_LOWPOWER_F3_SOURCE_SDK_INSTALL_DIR}/source/third_party/mcuboot/root-ec-p256.pem ${BuildArtifactFileBaseName}_noheader.bin ${BuildArtifactFileBaseName}_v2.bin
${CG_TOOL_ROOT}/bin/tiarmobjcopy ${BuildArtifactFileBaseName}.out --output-target binary ${BuildArtifactFileBaseName}_noheader.bin --remove-section=.ccfg${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/tools/common/mcuboot/imgtool sign --header-size 0x100 --align 4 --slot-size 0x3B000 --version 1.0.0 --pad-header --pad --key ${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/third_party/mcuboot/root-ec-p256.pem ${BuildArtifactFileBaseName}_noheader.bin ${BuildArtifactFileBaseName}_v1.bin${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/tools/common/mcuboot/imgtool sign --header-size 0x100 --align 4 --slot-size 0x3B000 --version 2.0.0 --pad-header --pad --key ${COM_TI_SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR}/source/third_party/mcuboot/root-ec-p256.pem ${BuildArtifactFileBaseName}_noheader.bin ${BuildArtifactFileBaseName}_v2.bin
Inside the project, go to
appand insideapp_main.cinitialize and register the OAD profile and service, if not already done. To do this, include the following code lines to start the OAD service inside theApp_StackInitDoneHandler()function where the other services are initialized.Start OAD service#App_StackInitDoneHandler() { //... status = OAD_start(); if(status != SUCCESS) { // TODO: Call Error Handler } //... }
Verify OAD functionality#
Build the modified project.
Once the project is built, use the
<Project_Name>_v1.binfrom theReleasefolder to flash the device following the steps mentioned in Bluetooth LE Over the Air Download (OAD) Fundamentals, section: OAD Target Setup. Make sure you follow the steps for the type of OAD you are implementing.Go back to the project and generate a second version of the image. For testing purposes, you can just modify the device name (
BLE→General Configuration→Device Name) so that you can recognize that the new image has booted correctly when looking at the advertisement report data.Get the
<Project_Name>_v2.binfile from theReleasefolder and transfer it to your phone (for example via cloud, email, etc).If you have not use Simple Link Connect mobile application before, you can take a look at TI SimpleLink™ Connect App for more details on how to use it.
Open the Simple Link Connect mobile application, connect to the
cc23xxdevice, select the OAD service, and selectAdd local fileto load the<Project_Name>_v2.binfile you just transferred and click onStartthe OAD process.Once the OAD update process has finished, click on
Doneand after the device resets itself, it should be using the new image (<Project_Name>_v2.bin), which can be identified by looking at the advertising data with the new device name you configured before (sometimes reconnecting and connecting again is needed to erase the previous name the mobile application might have cached).
Congrats! You have been able to add and test the OAD capabilities of your project!
References#
TI CC2340R5 - Technical Reference Manual
Bluetooth Core Specification Version 5.3
Bluetooth LE Scanning and Advertising