Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

nRF51 Legacy DFU SDK 9.0 Fails on MediaTek Android

Hi,

I'm looking for help with an Android DFU failure involving an old nRF51 Legacy DFU bootloader.

Setup:
- Bootloader: nRF51 Legacy DFU v0.8 (SDK 9.0)
- Firmware package: application ZIP, 129,016 bytes
- Device is already in DFU bootloader mode
- Reconnect behavior: same MAC address on reconnect
- Android device: MediaTek-based phone
- iOS works against the same target

Problem:
On Android, DFU always fails right after `Start DFU` + image sizes.

Observed sequence:
1. Connect to device
2. Enable notifications on DFU Control Point
3. Send `Start DFU` (Op Code 1, Upload Mode 4)
4. Send image sizes
5. Device disconnects immediately with status 8
6. Android DFU library reports `Response not received: device disconnected`
7. Reconnect and retry repeats the same pattern forever

Important details:
- Same-MAC reconnect is confirmed. This device does not use MAC+1.
- iOS succeeds, which suggests the bootloader behavior itself is acceptable there.
- On Android, it looks like the BLE stack either delivers disconnect before the response notification, or drops the Start DFU response entirely.

What I already tried:
- Disabled app-side BLE scan interference
- Removed app-side UI abort/timeout issues
- Disabled MTU request
- Enabled PRN with value 12
- Confirmed `forceScanningForNewAddressInLegacyDfu` is irrelevant on this path
- Vendored Nordic Android DFU 2.9.0 sources
- Patched `LegacyDfuImpl` to catch the first disconnect after image sizes and reconnect intentionally
- Patched `BaseDfuImpl.readNotificationResponse()` to wait briefly for a late notification after disconnect

Result:
- No change. Android still never gets a usable Start DFU response after the disconnect.

Question:
Is this a known incompatibility between nRF51 Legacy DFU SDK 9.0 and some Android BLE stacks, especially MediaTek?

If so, is there any supported workaround besides:
- using iOS,
- using Nordic desktop tooling,
- or changing the device-side bootloader / DFU implementation?

I can provide full logs and the specific code patches if needed.


Parents
  • Thanks. I tested again and it still fails.

    Additional findings:
    - Our app still fails even after removing neverForLocation and enabling Android location permission.
    - Nordic’s own DFU app also fails on the same MediaTek Android phone with the same device / file.
    - iOS still succeeds.

    From our logs, the failure sequence is very consistent:

    1. Connect to DFU device
    2. Services discovered
    3. DFU Version read successfully:
    "Version number read: 0.8 -> Bootloader from SDK 9.0 or newer"
    4. Notifications enabled on Control Point
    5. Start DFU sent
    6. Image size array sent
    7. Device disconnects immediately:
    "Target device disconnected with status: 8"
    8. Library then reports:
    "Response not received: device disconnected (error 8)"

    Relevant log excerpt:

    - "Sending Start DFU command (Op Code = 1, Upload Mode = 4)"
    - "Sending image size array to DFU Packet (0b, 0b, 129016b)"
    - "Target device disconnected with status: 8"
    - "Response not received: device disconnected (error 8)"

    I also confirmed:
    - same MAC is used on reconnect (DB:98:FB:62:DD:B3)
    - this is not a MAC+1 case
    - the failure happens before init packet / firmware upload begins
    - changing app-side scan/location handling did not change the result

    At this point it seems the key problem is that on this MediaTek Android stack, after Start DFU + image sizes, the disconnect happens and Android never provides a usable Start DFU response to the host.

    Since Nordic’s own DFU app also fails on the same phone, this no longer looks app-specific.

    Do you know whether this is a known incompatibility with old nRF51 Legacy DFU (SDK 9.0), especially on some Android BLE stacks? If so, is the recommended workaround simply to use iOS / desktop tooling / another Android device, or is there any device-side or host-side setting that may still help?

  • Do you see the same issue on other Android phones, or is it specific to the MediaTek Android stack?

  • So far I have only reproduced it on the MediaTek Android phone.

    I have not yet tested the same device / firmware package on a second Android phone with a different chipset, so at the moment I cannot say whether it is specific to MediaTek or affects Android more broadly.

    What I can confirm is:
    - it fails on our app on this MediaTek phone,
    - it also fails on Nordic’s DFU app on this same phone,
    - and iOS succeeds with the same target.

    My current suspicion is that this may be specific to this Android BLE stack, but I do not have a non-MediaTek Android comparison yet.

  • Hello!

    Error 8 received as a status for disconnection is ERROR_CONN_TIMEOUT. This can happen if the device does not respond within the connection interval. The "Start DFU" command was designed to erase the flash for the new image, which, depending on the image size, may take longer time. It also looks like the bootloader is spending 100% of time on this task and doesn't bother keeping the open connection.

    If this happens on some phones, but works on another, the issue may be the connection interval or supervision timeout. With too short interval the erase operation may not complete withing the expected time and the phone may assume the connection is dead. Some other phones may have longer interval, greater supervision timeout (how many packets a peripheral can "sleep" without replying), so the connection is kept alive for a longer time. Also, decreasing the image size may help, but that isn't something that you could easily do (would require changing the firmware), but you may use for testing in nRF Connect:

    1. Connect in nRF Connect for Android
    2. Enable notifications on DFU Control Point
    3. Send "Start DFU" and set the same app size 129016 bytes or try smaller size
    4. Observe if the device disconnects with larger images
    5. You may also LOW_POWER or BALANCED Reqeust Connection Proirity from nRF Connect and try with larget image size, giving the target more time to erase the image.

    If that works, you may request lower connection priority to the device in your app before you send Start DFU packet.

Reply
  • Hello!

    Error 8 received as a status for disconnection is ERROR_CONN_TIMEOUT. This can happen if the device does not respond within the connection interval. The "Start DFU" command was designed to erase the flash for the new image, which, depending on the image size, may take longer time. It also looks like the bootloader is spending 100% of time on this task and doesn't bother keeping the open connection.

    If this happens on some phones, but works on another, the issue may be the connection interval or supervision timeout. With too short interval the erase operation may not complete withing the expected time and the phone may assume the connection is dead. Some other phones may have longer interval, greater supervision timeout (how many packets a peripheral can "sleep" without replying), so the connection is kept alive for a longer time. Also, decreasing the image size may help, but that isn't something that you could easily do (would require changing the firmware), but you may use for testing in nRF Connect:

    1. Connect in nRF Connect for Android
    2. Enable notifications on DFU Control Point
    3. Send "Start DFU" and set the same app size 129016 bytes or try smaller size
    4. Observe if the device disconnects with larger images
    5. You may also LOW_POWER or BALANCED Reqeust Connection Proirity from nRF Connect and try with larget image size, giving the target more time to erase the image.

    If that works, you may request lower connection priority to the device in your app before you send Start DFU packet.

Children
No Data
Related