This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

iOSDFULibrary hang at discoverCharacteristics()

We're encountering a frequent but intermittent hang after handing off OTA DFU to iOSDFULibrary 3.1.0. In the happy case, the characteristics are discovered and DFU process proceeds normally:

[DFU] Discovering characteristics in DFU Service...
[DFU] peripheral.discoverCharacteristics(nil, for: FE59)
[DFU] DFU characteristics discovered
...

When we get a hang, it's characterized by the following logging snippet:

[DFU] Discovering characteristics in DFU Service...
[DFU] peripheral.discoverCharacteristics(nil, for: FE59)
[DFU] [Callback] Central Manager did disconnect peripheral 
[DFU] Disconnected by the remote device

There are no DFUState updates to the dfuStateDidChange(to:) delegate method that indicate that DFU has encountered a problem. It just locks up and sits at this point forevermore. We've replicated this issue across multiple of our nrf51422-based devices, and across multiple iOS devices, in both Debug and Release builds.

At this point, it's not even fully clear whether this represents a bug in iOSDFULibrary, or whether we're somehow getting into a bad state before our iOS codebase hands off to the DFU library.

Full iOSDFULibrary hang log

  • @John: Could you capture a sniffer trace ?

    Which SDK did you use for the bootloader and application ? Have you tried to test with a fresh copy of the bootloader ?

    Did you try to do DFU with only the bootloader or it's the butonless dfu application you were trying ?

  • @hungbui: We're using the sdk12.1.0 bootloader, customized slightly as follows: We send our company-id in the manufacturer data, we change the name from "DfuTarg" to "Gemio Update", and we are always buttonless, so we have the buttonless dfu patch discussed elsewhere in the forum. (The buttonless works perfectly with NRFToolbox, we only have this problem from our iOS App). Working presently on capturing a trace of the failure mode.

  • I would suggest to test with unmodified bootloader, also try to do DFU update with just bootloader first, no buttonless. After that try to test with the ble_app_hrs buttonless.

    I suspect Att table cache on iOS could be the issue here.

  • In fixing another Bluetooth issue with our app, we appear to have resolved this issue.

    For some time, we had been using one CBCentralManager instance for the entire app, using it to scan both for our device in its normal operational mode, and to scan for it when running the bootloader ("Dfu Targ/Gemio Update" mode). This was working well, but at some point this intermitted problem appeared, likely in response to a refactoring or possibly an iOSDFULibrary update. I broke out our central manager usage as follows:

    1. There's one CBCentralManager used for our BLE devices in normal operation.
    2. For each DFU workflow we initiate, create a new CBCentralManager to scan for the "Gemio Update" device and pass that instance off to iOSDFULibrary.
    3. Be absolutely sure that this DFU-only CBCentralManager is deallocated when DFU has finished. I instrumented its containing class via logging in deinit() to this end. Helpful, as it turns out a subtle retain cycle had been introduced elsewhere.

    These steps together have been sufficient to resolve this issue, and some other vexing DFU-related problems as well. E.g. our app stopped being able to scan for BLE devices after DFU without an app restart. It appears that the central manager was getting into a bad state post-DFU, and obvious fixes such as ensuring stopScan() was called were of no help.

Related