DFU (Device Firmware Update)
The BNO08x driver includes support for updating sensor firmware via the Device Firmware Update (DFU) protocol. This allows you to update the sensor’s firmware without removing it from your system.
Overview
DFU mode allows you to:
- Update sensor firmware in the field
- Fix firmware bugs without hardware replacement
- Upgrade to newer firmware versions
- Support multiple firmware formats (BNO08x and FSP200/201)
Entering Bootloader Mode
The sensor must be in bootloader mode to perform a firmware update:
- Hold BOOTN pin low (active low)
- Reset the sensor (toggle RSTN pin or power cycle)
- Release BOOTN after reset completes
- Sensor is now in bootloader mode
Hardware Method:
1
2
3
4
// If you have BOOTN and RSTN pins wired
imu.SetBootPin(true); // BOOTN low
imu.HardwareReset(10); // Reset for 10ms
imu.SetBootPin(false); // Release BOOTN
Manual Method:
- Physically hold BOOTN pin low
- Power cycle or reset the sensor
- Release BOOTN
Firmware Image Format
Firmware must be provided as an HcBin_t object. The driver includes stub firmware files:
src/dfu/firmware-bno.c: Stub firmware for BNO08x (compile-time image)src/dfu/firmware-fsp.c: Stub firmware for FSP200/201 (compile-time image)
Note: These are minimal stub images. For production, obtain firmware from the sensor vendor.
Implementation
Step 1: Implement IDfuTransport Interface
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "src/dfu/IDfuTransport.hpp"
class MyDfuTransport : public IDfuTransport {
public:
bool open() override {
// Initialize communication interface for bootloader
return true;
}
void close() override {
// Close communication interface
}
int write(const uint8_t* data, size_t length) override {
// Write data to sensor
return /* your write implementation */;
}
int read(uint8_t* data, size_t length) override {
// Read data from sensor
return /* your read implementation */;
}
uint32_t getTimeUs() override {
// Return current time in microseconds
return /* your time implementation */;
}
};
Step 2: Use HalTransport Adapter (Alternative)
If you already have an sh2_Hal_t implementation, you can use the adapter:
1
2
3
4
5
6
#include "src/dfu/HalTransport.hpp"
extern sh2_Hal_t my_hal;
HalTransport transport(&my_hal);
// Use transport with dfu()
Step 3: Perform Firmware Update
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "bno08x.hpp"
#include "src/dfu/firmware.h" // Provides 'firmware' HcBin_t object
MyComm comm;
bno08x::BNO085<MyComm> imu(comm);
// Enter bootloader mode first (see above)
// Method 1: Using BNO085::Dfu() convenience method
int result = imu.Dfu(firmware);
if (result == SH2_OK) {
printf("Firmware update successful!\n");
} else {
printf("Firmware update failed: %d\n", result);
}
// Method 2: Using dfu() function directly
MyDfuTransport transport;
result = dfu(transport, firmware);
Step 4: Using Custom Firmware Source
If firmware is stored elsewhere (e.g., flash, network), use MemoryFirmware:
1
2
3
4
5
6
7
8
9
10
#include "src/dfu/MemoryFirmware.hpp"
// Firmware stored in memory/flash
const uint8_t* firmware_data = /* your firmware data */;
size_t firmware_size = /* firmware size */;
MemoryFirmware custom_fw(firmware_data, firmware_size);
HcBin_t* fw_bin = custom_fw.getBin();
int result = imu.Dfu(*fw_bin);
Complete Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "bno08x.hpp"
#include "src/dfu/firmware.h"
#include "src/dfu/HalTransport.hpp"
void update_firmware() {
Esp32Bno08xBus comm(/* config */);
bno08x::BNO085<Esp32Bno08xBus> imu(comm);
// 1. Enter bootloader mode
printf("Entering bootloader mode...\n");
imu.SetBootPin(true); // BOOTN low
vTaskDelay(pdMS_TO_TICKS(10));
imu.HardwareReset(10); // Reset
vTaskDelay(pdMS_TO_TICKS(100));
imu.SetBootPin(false); // Release BOOTN
// 2. Reinitialize communication for bootloader
comm->Close();
vTaskDelay(pdMS_TO_TICKS(100));
comm->Open();
// 3. Perform firmware update
printf("Starting firmware update...\n");
int result = imu.Dfu(firmware);
if (result == SH2_OK) {
printf("Firmware update successful!\n");
} else {
printf("Firmware update failed: %d\n", result);
return;
}
// 4. Reset sensor to normal mode
printf("Resetting sensor to normal mode...\n");
imu.HardwareReset(10);
vTaskDelay(pdMS_TO_TICKS(100));
// 5. Reinitialize for normal operation
comm->Close();
vTaskDelay(pdMS_TO_TICKS(100));
comm->Open();
if (imu.Begin()) {
printf("Sensor reinitialized successfully\n");
}
}
Timeout Handling
The DFU implementation includes built-in timeouts for slow communication links:
- Default timeout: Several minutes (varies by firmware size)
- Automatic retries: Built into DFU protocol
- Progress indication: Check return codes for status
Error Codes
DFU returns SH-2 status codes:
SH2_OK(0): Update successfulSH2_ERR(non-zero): Update failed
Common error causes:
- Communication timeout
- Invalid firmware image
- Bootloader not responding
- Checksum mismatch
Firmware Sources
Compile-Time Firmware
1
2
3
4
#include "src/dfu/firmware.h"
// Use default firmware object
imu.Dfu(firmware);
Runtime Firmware
1
2
3
4
5
6
7
8
#include "src/dfu/MemoryFirmware.hpp"
// Load from flash/memory
const uint8_t* fw_data = load_from_flash();
size_t fw_size = get_firmware_size();
MemoryFirmware fw(fw_data, fw_size);
imu.Dfu(*fw.getBin());
Network/File Firmware
1
2
3
4
// Load firmware from file or network
std::vector<uint8_t> fw_data = load_firmware_file("firmware.bin");
MemoryFirmware fw(fw_data.data(), fw_data.size());
imu.Dfu(*fw.getBin());
Best Practices
- Backup Current Firmware: If possible, read current firmware before updating
- Verify Firmware Source: Ensure firmware is from trusted source
- Test First: Test firmware update process in development before field deployment
- Handle Errors: Always check return codes and handle failures gracefully
- Power Stability: Ensure stable power during update (avoid brownouts)
- Don’t Interrupt: Never interrupt firmware update process
Troubleshooting
Update Fails Immediately
- Check Bootloader Mode: Verify sensor is actually in bootloader mode
- Verify Communication: Test communication interface works
- Check Firmware: Ensure firmware image is valid
Update Times Out
- Increase Timeout: Modify timeout values in DFU source if needed
- Check Communication Speed: Try slower communication speed
- Verify Connection: Check all connections are secure
Sensor Doesn’t Respond After Update
- Reset Sensor: Perform hardware reset after update
- Reinitialize: Call
Begin()again after reset - Check Firmware: Verify firmware is compatible with your sensor model
Next Steps
- Review Examples for more usage examples
- Check Troubleshooting for common issues
- See RVC Mode for alternative operation mode
Navigation ⬅️ RVC Mode | Back to Index