For what it’s worth, I think I found my issue. I’ve copy/pasted/formatted the exchange from Nordic’s website.
AE - Monday, December 02 2013
We had some problems updating our devices with the nRF Loader App on IOS. After selecting the device in DFU mode the App hangs and aborts with a Bluetooth error after a timeout. As we already had tested, that the same App can update our devices we were quite confused. A lot of tests with various versions of our bootloader code didn't show a solution.
At the end we found out what causes the problem. If the device is paired with the IOS device the App hangs. When the the pairing is removed the App works as expected.
Nordic employee - OM - Monday, December 02 2013, 14:57
Unfortunately this is to be expected with the bootloader as currently implemented in the SDK.
This is a consequence of the bootloader being a completely separate application. Normally, if the main application on a chip does bond, it will store its bonding information in its own part of the flash. This bonding information is also tied to the main application's GATT Table layout. Since the bootloader is currently a separate application, it doesn't have any way to know where any bonding information is stored, and it will also have a different GATT Table layout. It can hence not use the same bonding inforation.
However, for the peer device, the device looks exactly the same (has the same address) no matter if it runs the main application or the bootloader. It will therefore rightfully expect that the bootloader also knows about the bonding information the peer device have exchanged with the main application, and when the bootloader doesn't, things fail.
I'd therefore suggest that you take the bootloader as delivered in the SDK and integrate the DFU service and flash writing in your regular application. In this way, while running the main application and having access to the normal bond information, the a new binary image can be received and written to the swap bank of the flash. The only thing left to do in the bootloader is then to do the actual data copying from the swap bank to the main bank of flash.
The final gotcha is however that bonding information as mentioned above is tied to GATT Table layout. If the new binary changes the GATT Table (adds a new service, removes a service), the system attributes of the old bonding information is no longer valid, and you may get trouble. However, as long as you don't change the GATT table, it should be perfectly possible to make this work by following the above suggestion.
AE - 4 weeks ago Your answer make perfectly sense, but it's not really good news... Adding some parts of the DFU to the normal application would be possible, but i prefer not to use it. Do you konw if it's possible that a IOS app can evaluate if a devie is paired or not? Can the app remove the device from the paired list? That would allow us to have our own app that removed a pairing to the device to update.
Nordic employee - OM - 4 weeks ago No, security and bonding is handled completely transparent for iOS apps, and there is no way an app can know whether a device is bonded or not, nor delete the bond information. This must be done by a user, through the settings menu.
The only thing I can think of, if you absolutely need to have the bootloader completely separate is to change the address in bootloader mode. However, this would require the iOS app to do a scan for new devices instead of issuing a connect to an already known one, which may in some cases be a problem. I therefore do think you're better off doing as I suggested above.
Caylan
On Dec 31, 2013, at 2:32 AM, Caylan Larson < email@hidden> wrote: Hi,
I have a custom BTLE sensor (nordic chipset [1]) that works flawlessly when first paired. However, on subsequent app launches it never sends didUpdateValueForCharacteristic.
I can switch apps to Settings and "Forget" the sensor. Then, I can use the same workflow to trigger -peripheral:didUpdateNotificationStateForCharacteristic:error and it starts sending data. If I relaunch the app, the sensor doesn't work until I "Forget" it again.
Basically, it gets to here and continues once… and after that, silence:
[peripheral setNotifyValue:YES forCharacteristic:self.receiveCharacteristic];
Any ideas on why this is happening? I’ve stubbed out all of the delegate methods and nothing is out of the ordinary.
Thanks!
Caylan
References: [1] http://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822-Development-Kit |