Android

Doing Over The Air Download (OAD) or Firmware Upgrade for TI cc2541/cc2540 in Android Using BLE

Pradeep V R

03 Jul 2024

Doing Over The Air Download (OAD)

Let’s look into Over The Air Download (OAD). In today’s Internet of things, (IoT) domain BLE (Bluetooth Low Energy or Bluetooth smart) is playing a major role in communication purposes, especially for wearable devices. In this tutorial, we will be explaining how to do a firmware upgrade over BLE or over-the-air download (OAD) on TI’s Sensor Tag which has CC2541 SoC. Sensor Tag is a BLE-enabled multi-sensor device that has an ambient temperature, infrared temperature, relative humidity, barometer, magnetometer, accelerometer, and gyroscope. It’s a general practice and required feature in all mobile apps for Wearables and the Internet of things to flash new firmware over BLE when there is an update.

Problem Statement: Android BLE stack is a bit unstable compared to iOS, mainly when the app is running continuously for hours and keeps interacting with the external hardware. This causes a frequent disconnection between the phone and the hardware. After days of research, we found a solution wherein changing the connection parameters of the hardware reduces the number of disconnections in a big way. But how do we pass on this solution to our existing customers for whom hardware devices are already distributed and are up and running?

Solution:

We can solve this problem by doing a firmware upgrade over-the-air download(OAD) from the app to the hardware!!! We asked users to download the latest app from the google play store so that they can have their latest firmware on their BLE device.

Texas Instruments has defined procedural steps to flash firmware onto the device as described below. Before writing the steps I am assuming the reader will have basic knowledge about interacting with BLE devices (using services and characteristics which are identified by their UUIDs).

Steps in Over The Air Download

Step 1: To begin with set the profile of the device to OAD mode by writing a one-byte value(in our case value is 4) to the profile characteristic. Below is the code to set the profile to OAD mode :

             BluetoothGattService otaService = mBluetoothGatt.getService(OTA_SERVICE_UUID);

BluetoothGattCharacteristic otaCharacteristic = otaService.getCharacteristic(OTA_CHARACTERISTIC_UUID);

if (otaCharacteristic != null) {

byte[] value = new byte[1];

value[0] = 4;

otaCharacteristic.setValue(value);

boolean status = mBluetoothGatt.writeCharacteristic(otaCharacteristic);

}

Step 2: After writing the profile mode we get on Characteristic Write callback registered with the BLE framework. If the profile mode is set successfully, set the connection parameters for the device that is suitable for transferring chunks of firmware for an upgrade. These connection parameters should be only temporary which means these values are applicable only during an upgrade process.

Briefly explaining, connection parameters are nothing but the time at which a sequence of data is exchanged (which is also known as a connection event) between master and slave. Below is the set of key variables that define connection parameters between master and slave:

a . Connection interval: The time between the beginning of two consecutive connection events, we need to pass it as minimum and maximum values. For the OAD upgrade we pass 15 million for both min and max intervals.

b . Slave latency: The number of connection events that can be skipped to decide the disconnection between master and slave. During OAD this value should be 0 since we can’t afford to miss any packets to make the successful firmware upgrade.

c . Connection supervision timeout: The maximum time between 2 received data packets before a connection is considered lost. In our case, the value of this variable is 500 miles.

Below is the code to set connection parameters for the device :

            BluetoothGattService connService = mBluetoothGatt.getService(CONN_SERVICE_UUID);

if (connService != null) {

BluetoothGattCharacteristic connCharacteristic = connService.getCharacteristic(CONN_CHARACTERISTIC_UUID);

if (connCharacteristic != null) {

// Make sure connection interval is long enough for OAD (Android default connection interval is 7.5 ms)

byte[] value = { Conversion.loUint16(OAD_CONN_INTERVAL), // gets LSB of 2 byte value

Conversion.hiUint16(OAD_CONN_INTERVAL), // gets MSB of 2 byte value

Conversion.loUint16(OAD_CONN_INTERVAL),

Conversion.hiUint16(OAD_CONN_INTERVAL), 0, 0,

Conversion.loUint16(OAD_SUPERVISION_TIMEOUT),

Conversion.hiUint16(OAD_SUPERVISION_TIMEOUT)

};

connCharacteristic.setValue(value);

status = mBluetoothGatt.writeCharacteristic(connCharacteristic);

}

Step 3: Once the connection parameter is set we should disconnect and connect the device to make sure new values are used by the master. Again the disconnection should be done in on Characteristic Write callback after making sure that the connection parameter is set successfully.

Step 4: After the above step wait for the connection to be established between the devices to proceed further. Once a connection is set between the devices we should get the current firmware image info on the master device. This can be achieved by enabling the notification on a device to read the firmware information (we can also get the firmware info by reading the characteristic from BluetoothGatt, but this solely depends on how the master device is programmed).

             BluetoothGattService fwService = mBluetoothGatt.getService(FW_SERVICE_UUID);

if(fwService != null) {

BluetoothGattCharacteristic fwCharacteristic = fwService.getCharacteristic(FW_CHARACTERISTIC_UUID);

// Enable notification

status = mBluetoothGatt.setCharacteristicNotification(fwCharacteristic, true);

// Prepare data for request (try image A and B respectively, only one of

// them will give a notification with the image info)

if (status) {

status = mBluetoothGatt.writeCharacteristic(fwCharacteristic, (byte) 0);

}

// Give some delay before enabling notification for B type firmware

if (status) {

status = mBluetoothGatt.writeCharacteristic(fwCharacteristic, (byte) 1);

}

}

Step 5: After enabling notification in step 4, we get the onCharacteristicChanged callback which carries current firmware info. Basically, there are two types of firmware versions ‘A’ and ‘B’, if the current firmware version is ‘A’ we should flash ‘B’ else if the current firmware version is ‘B’ we should flash the ‘A’ version firmware. After deciding on the new firmware (to be flashed) we should write its version, length, and uid in the same order onto the device.

         // Prepare image notification

byte[] buf = new byte[2 + 2 + 8]; // 2 bytes for version, 2 bytes for length and 8 bytes for UID

buf[0] = Conversion.loUint16(mFileImgHdr.ver); // version of new firmware

buf[1] = Conversion.hiUint16(mFileImgHdr.ver);

buf[2] = Conversion.loUint16(mFileImgHdr.len); // length of new firmware

buf[3] = Conversion.hiUint16(mFileImgHdr.len);

System.arraycopy(mFileImgHdr.uid, 0, buf, 4, 4); // UID of new firmware

BluetoothGattService fwService = mBluetoothGatt.getService(FW_SERVICE_UUID);

if(fwService != null) {

BluetoothGattCharacteristic fwCharacteristic = fwService.getCharacteristic(FW_CHARACTERISTIC_UUID);

if(fwCharacteristic != null) {

// Send image notification

fwCharacteristic.setValue(buf);

status = mBluetoothGatt.writeCharacteristic(fwCharacteristic);

}

}

 

Step 6: Wait for the onCharacteristicWrite callback and check the write status, if new firmware info is successfully written start writing new firmware in blocks of 18 bytes (the first 2 bytes contain block number and the next 16 bytes contain actual firmware data). This step is the final stage where we flash firmware binary files of around 127 KB(126976 bytes) by dividing them into 16 bytes blocks, so totally we need to write 7936 blocks. Each block of data should be prefixed with extra 2 bytes which contain the block number.

After writing each block we need to give a time delay of around 30 million which sums up to approximately 4 mins to finish the firmware upgrade. This cannot be done on the main thread else we will end up with an ANR scenario. So we need to spawn a new thread that can be executed every 30 miles. We can do this by creating HandlerThread or TimerTask. If we are using HandlerThread we need to send a delayed message using Handler(attached to the HandlerThread instance created) every 30 millis, this triggers the handleMessage() function of the Handler on the background thread inside which we write each block. We can also use TimerTask API which can be assigned to a Timer. Calling Timer.scheduleAtFixedRate() (which takes time delay as one of its parameters) triggers the run() method on the background thread of the TimerTask class every 30 millis.

 

        // This function should be called every 30-40 millis

private void programBlock() {

// Prepare buffer of size 18 bytes, having first 2 bytes as block number and next 16 bytes firmware data

mOadBuffer[0] = Conversion.loUint16(BLOCK_NUMBER);

mOadBuffer[1] = Conversion.hiUint16(BLOCK_NUMBER);

// copy 16 bytes from file to buffer

System.arraycopy(mFileBuffer, mFileBlockIndex, mOadBuffer, 2, BLOCK_SIZE);

BluetoothGattService oadService = mBluetoothGatt.getService(OAD_SERVICE_UUID);

if(oadService != null) {

BluetoothGattCharacteristic oadCharacteristic = oadService.getCharacteristic(OAD_CHARACTERISTIC);

if(oadCharacteristic != null) {

oadCharacteristic.setValue(mOadBuffer);

success = mBluetoothGatt.writeCharacteristic(oadCharacteristic);

}

}

}

After writing all the blocks the master device automatically disconnects itself so that when it is again reconnected it runs on the new firmware and switches to the normal connection parameters.

 

FAQ: 

Q1: What is over the air download (OAD) and how is it used in firmware updates?

A1: Over the air download (OAD) is a process that allows for firmware updates to be transmitted to a device wirelessly via Bluetooth Low Energy (BLE). For TI’s Sensor Tag, this means you can perform an OAD upgrade to update the firmware without needing a physical connection. This is crucial for wearable devices and IoT applications, allowing for seamless software updates and improvements.

Q2: How do you perform a firmware upgrade on the CC2541 SoC using OAD?

A2: To perform a firmware upgrade on the CC2541 SoC using OAD, follow these steps:

  1. Set the device to OAD mode by writing a specific value to the profile characteristic.
  2. Adjust the connection parameters to optimize data transfer for the firmware update.
  3. Disconnect and reconnect the device to apply new connection parameters.
  4. Retrieve current firmware information to determine the appropriate firmware version to flash.
  5. Write the new firmware information to the device.
  6. Send the firmware in blocks, ensuring each block is properly transmitted and received.

Q3: What are the key connection parameters to set for a successful OAD firmware upgrade?

A3: Key connection parameters for a successful OAD software update include:

– Connection Interval: The time between consecutive connection events, typically set to 15 million for OAD.

– Slave Latency: Set to 0 to ensure no packets are missed during the firmware upgrade.

– Connection Supervision Timeout: The maximum time between received packets before a connection is considered lost, often set to 500 miles for OAD.

Q4: How does i oad air 2 relate to firmware upgrades over BLE?

A4: The i oad air 2 refers to a specific version of the OAD protocol or firmware upgrade method used in certain devices. It represents a model or approach for performing over the air download updates efficiently. This term might also be related to specific firmware versions or updates in the OAD process.

Q5: What should I do if the Android BLE stack is unstable during firmware updates?

A5: If the Android BLE stack is unstable, leading to frequent disconnections, it is recommended to:

  1. Set the connection parameters specifically for OAD as described.
  2. Ensure you are using appropriate connection intervals and latency settings.
  3. Implement the firmware upgrade process as described to minimize disconnections and ensure a successful update.

Q6: How can I update the cc2540 firmware using OAD?

A6: Updating the CC2540 firmware follows a similar process as the CC2541. You need to:

  1. Put the device into OAD mode.
  2. Adjust connection parameters suitable for the firmware transfer.
  3. Disconnect and reconnect the device.
  4. Retrieve and set the new firmware information.
  5. Write the firmware in blocks, ensuring proper data transmission and handling.

Q7: What is the significance of OAD update for IoT devices?

A7: An OAD update is crucial for IoT devices as it allows manufacturers to deploy firmware updates remotely, improving functionality and security without physical intervention. This is especially important for wearable devices and other connected hardware where manual updates would be impractical.

Q8: Can you explain the difference between OAD software update and traditional firmware updates?

A8: The OAD software update involves sending firmware updates wirelessly via BLE, whereas traditional firmware updates might require physical connections or manual interventions. OAD offers the convenience of remote updates, which is ideal for devices in the field or those requiring frequent updates.

Q9: How do I ensure the successful execution of a firmware update on i oad air devices?

A9: To ensure a successful firmware update on i oad air devices, follow the detailed OAD procedure:

  1. Set the device to OAD mode.
  2. Adjust connection parameters.
  3. Disconnect and reconnect the device.
  4. Retrieve and write new firmware information.
  5. Send firmware blocks with appropriate delays.

Q10: What are the common issues encountered during the OAD upgrade process and how can they be resolved?

A10: Common issues include unstable BLE connections, incomplete firmware blocks, or incorrect connection parameters. To resolve these:

  1. Ensure connection parameters are correctly set for OAD.
  2. Use error-checking and retries for firmware blocks.
  3. Verify BLE connection stability and adjust parameters as needed.

At Cumulations, we have expertise in building Bluetooth low-energy apps. If you have any requirements to build mobile apps for wearable devices and internet of things mobile apps, please contact us: https://www.cumulations.com/contact-us