This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

DFU on nRF51822 + iOS -- Have to toggle Bluetooth ON/OFF

I'm wondering (hoping) if there is something that I'm not doing correctly ...

We have a BLE application on the nRF51822 which has been working nicely. It is a custom BLE Service/Characteristic which supports a command/response protocol that we've developed for reading the captured information on our device.

We also support DFU mode -- using the DFU bootloader example -- pretty much AS-IS, except for checking the (gpregret == 1) condition on reset (which we set in the main application via a BLE command).

What 'appears' to be happening is this :

1 -- BLE application is running, connected to the iOS App -- able to view data, etc.

2 -- DFU 'key' is hit in the App which does the following on the device : sd_power_gpregret_set(0x01); sd_nvic_SystemReset();

3 -- The device resets, detects the gpreget bit set -- and (successfully) enters DFU mode.

4 -- We use nRF Toolbox to update the F/W. All works well -- find DfuTarg, select file, file type, etc. Upload is successful. Device resets and is now running with new F/W.

5 -- Here is where it gets 'weird' ? In order to get the device to show-up again (even if I remove power from the device and then bring it back up) -- I must cycle BT Off/On on my iOS device! Our App is looking for it's desired Service UUID (0x1723) and Characteristic (0x1724) -- and doesn't find them.

6 -- Prior to cycling BT Off/On in the Settings Menu -- if I run an App that I downloaded on iTunes : itunes.apple.com/.../id525235616 -- then what I see are the Service/Characteristics (0x1530, 1531, 1523) which are the ones in the DFU Bootloader?!?!

SO -- it seems like somehow/someway? iOS is 'latching' those DFU characteristics -- even though the device is correctly advertising with it's non-DFU (1723/1724) Service/Characteristic.

As soon as I cycle BT Off/On on the iOS device -- even the BLE Tool shows the proper results (0x1723/1724) -- with the device being on throughout all this -- no change to/from DFU mode.

I'm wondering if it there is any chance that iOS is getting irk'd with the fact that the default DFU bootloader calls the device DfuTarg -- and our application code calls it something different?

Appreciate any input/guidance that you might have -- as it just can't be that we have to tell user's to cycle BT after a F/W update!

Cheers, -Tim

Parents
  • Hi Tim,

    I agree with Nate and jt, this does indeed look like a caching issue.

    One problem with the bootloader as it is now is that the bootloader has a completely different GATT database than your normal application. When a Central device re-connects to your nRF51, it expects that the GATT database is the same, so it can avoid doing a Service Discovery procedure (which takes time). Bluetooth does have functionality for dealing with this situation: one of the native characteristics on a BLE device is the "Service Changed Characteristic". The idea is that the GATT Server can use this to indicate to the GATT Client that the GATT database has changed (see developer.nordicsemi.com/.../a01060.html. There's not guarantee that the peer device will take action when this happens, but it's worth a try looking into. Note that with S110 v7.0.0 and later, you must specifically tell the stack to include this characteristic when enabling the stack (see developer.nordicsemi.com/.../a01045.html

    You can also add the DFU Service to your normal GATT database before your other services. I mean, just add the Service to your database, but not include any of the actual bootloader functionality in there. This way the peer device will the the following services during normal operation:

    • DFU Service
    • Battery Service (for example)
    • Device Information Service (for example)
    • Your other Services

    When the bootloader is active, the peer device will see the following services:

    • DFU Service

    Thus you won't have to force flushing the cache in order to find the DFU Service in bootloader mode (as the DFU Service will now be at the exact same place in the GATT database), and hopefully you will see the full set of Services again when you resume normal operation.

    It might be easier to "just" flush the cache when triggering the bootloader, but I'm not exactly sure how/if that can be done without disabling and re-enabling Bluetooth (I'm not an iOS developer).

    Hope this helps!

    Audun

Reply
  • Hi Tim,

    I agree with Nate and jt, this does indeed look like a caching issue.

    One problem with the bootloader as it is now is that the bootloader has a completely different GATT database than your normal application. When a Central device re-connects to your nRF51, it expects that the GATT database is the same, so it can avoid doing a Service Discovery procedure (which takes time). Bluetooth does have functionality for dealing with this situation: one of the native characteristics on a BLE device is the "Service Changed Characteristic". The idea is that the GATT Server can use this to indicate to the GATT Client that the GATT database has changed (see developer.nordicsemi.com/.../a01060.html. There's not guarantee that the peer device will take action when this happens, but it's worth a try looking into. Note that with S110 v7.0.0 and later, you must specifically tell the stack to include this characteristic when enabling the stack (see developer.nordicsemi.com/.../a01045.html

    You can also add the DFU Service to your normal GATT database before your other services. I mean, just add the Service to your database, but not include any of the actual bootloader functionality in there. This way the peer device will the the following services during normal operation:

    • DFU Service
    • Battery Service (for example)
    • Device Information Service (for example)
    • Your other Services

    When the bootloader is active, the peer device will see the following services:

    • DFU Service

    Thus you won't have to force flushing the cache in order to find the DFU Service in bootloader mode (as the DFU Service will now be at the exact same place in the GATT database), and hopefully you will see the full set of Services again when you resume normal operation.

    It might be easier to "just" flush the cache when triggering the bootloader, but I'm not exactly sure how/if that can be done without disabling and re-enabling Bluetooth (I'm not an iOS developer).

    Hope this helps!

    Audun

Children
  • By design, you cannot 'flush' the CoreBluetooth GATT cache. Even setting the CBCentral object to nil, or instantiating another CBCentral won't help in these circumstances.

    I wouldn't recommend the second part of your suggestion as technically you're violating both Spec (removing Services is just as much a no-no as adding them without Service Discovery enabled) and Apple's guidelines for dealing with this situation.

  • Altering the GATT database isn't in violation of the Bluetooth spec. The Service Changed characteristic exists explicitly to handle this situation: "If the list of GATT based services and the service definitions cannot change for the lifetime of the device then this characteristic shall not exist, otherwise this characteristic shall exist."

    However, if this doesn't work with iOS, I suggest keeping the same GATT database both for normal operation and when the bootloader is active. That is, adding a dummy DFU Service in normal mode, and dummy other-Services in the bootloader.

  • Altering the GATT table without Service Changed Characteristic is a violation of the Spec. If you read Audun's post carefully, he's suggesting either the Service Changed characteristic (the right way to do this) or "fooling" the device by using the same Services in both application and DFU "mode".

    If you use the former, you don't need the latter.

  • Ah, yes, I agree. I missed your point about choosing one or the other.

  • The OP should really read Apple's own guidelines, per my previous suggestion. :)

Related