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

Detailed DFU Application Interface Documentation

I need to implement DFU in a Unity3D application. I have tried to integrate the Android SDK library that you have on github. They are not integrating very well.

I have a lot of BLE experience and if I understand exactly the steps to implement sending a ZIP file payload over the DFU service and characteristics then I could probably do it without your library. This would also be good because I need this to work on iOS as well and being able to do it myself in C# code would be great because then I don't have to do native code for each.

The problem is that the documentation all assumes you are using the library you have provided.

Is there anything special that the library does? Does it actually break open the ZIP file and send the different parts over or does it just open a connection and send the ZIP file and have the firmware on the Nordic part do the work? If the previous then I would like to know the simple commands to implement that.

Parents
  • A detailed description of the DFU protocol can be found in the bootloader section of the infocenter.

    Here is a very coarse overview:

    The app opens the zip file and sends the meta information first (which the bootloader can choose to say "nope" to), then the binary firmware data in chunks, checked via CRC32. Once the last checksum is OK, the command to "execute" the update is sent.

  • I have been reading through the bootloader section in infocenter and am still not clear on exactly what to do.

    Maybe I am looking in the wrong place. Just to be clear I am working on SDK 15.3.

    Most of the information I am finding looks to be from the device side and not the mobile app.

    Can you give me some specific pointers? It would be nice to have a detailed description of 1. send these bytes, 2. expect this response or 2, 3. Now send these bytes, etc.

  • Also, my device is set up with the Buttonless DFU characteristic. I don't have the other 2. So how do I use that one? I notice there is a Control Point Characteristic and a Packet Characteristic. Since I don't have those and only have the buttonless, how does this work for me? Where do I send what?

  • The buttonless service is used to reboot your device into DFU bootloader mode. In that mode you device will only have DFU service and DFU Control Point and DFU Packet characteristics inside (except from Generic Attribute and Generic Access, of course).

    How to use this service is explained here: Buttonless Secure DFU Service

    For non-bonded devices, the bootloader will advertise with a different MAC address (+1). The phone needs to scan for it to connect to it. Our libraries take care of it automatically, but you need to make sure you connect to the proper device. Remember, that on iOS you don't have MAC address, so you can't compare it with the previous one. iOS DFU Library is using peripheralSelector, and the selection (starting from DFU from SDK 14) is using "Set advertisement name" feature (see the first link, command 0x02).

    After you jumped to bootloader mode successfully, you need to check in what state your device is. You do this by setting the object to COMMAND. You will get the offset and CRC32 of the object. For fresh update both will be 0. If an update has started and may be resumed, they'll contain the proper values for you to compare (if cry doesn't match, or you don't want to resume, you always may start again by creating new COMMAND object). Then you need to follow the BLE Transport: Device Firmware Update process.

    Regarding your question about the ZIP file. ZIP file contains 3 or 5 files. One is always the manifest.json, which specifies the names of 2 or 4 other files. In one ZIP file there may be an update for App only, or SoftDevice+Bootloader and App. Or any of them alone. The dat file is generated using nrfutil tool. The same tool may be used to read the content for the zip file, including decoding the dat files. The dat files are using Protobuf to encode the firmware size, type, hw type, required soft device(s), signature, crc, etc. They are to be sent prior to the firmware for validation. Bootloader may reject the firmware based on the init packet.

    I would recommend first trying the bootloader using nRF Connect for Android or iOS. Check if your ZIP file is working. Then examine the log. All packets are logged there in a semi-human-readable way. This should give you more momentum. Good luck.

    When you're done, and you'd like to contribute you project, we can always link to your implementation, just like we already have react-native and Flutter wrappers.

    BR, Aleksander

  • Thank you for the detailed response.

    I have been able to implement DFU in my code with some success, but not final success. I am doing this by trying to follow the Android code and a lot of trial and error.

    First I have to thank whoever wrote the DFU firmware. It is awesome that when I mess up the process the device just times out after a little bit and returns to normal operation. THANK YOU!!!

    I have 2 .zip files with different versions of my firmware that I can verify the version when it is in normal operation.

    I am able to use the iOS DFU app from Nordic to update my device with both of these files and verify that the version is changing when I check it.

    When I do the same thing using my own app, everything seems to work because I don't get any errors and the CRC values all match at every step.

    I do the dat file with no errors. I then do the bin file with no errors. I execute each object at the end with no errors. The offsets are all what I expect.

    When I send the last execute command on the last packet the device response correctly and then automatically reboots all by itself as expected.

    The device then enters normal operation, but when I check the version it is not the one I think I just sent. I have tried both versions of my .zip and the reported version during normal operation never changes.

    What could be going wrong and how do I figure that out?

  • If you get a success from the last execute, when the offset is equal to the fw size, and the device reboots, it should swap banks. You may verify that they were swapped by downloading the fw using nRF Connect for PC and comparing hex files. If they were swapped, try resetting Bluetooth in iPhone. Maybe it's cache? Do you read values to verify, or check services?

  • The other option I can see is that you flash incorrect versions of fw. On version A you flash A again, and on B - B. When doing dfu in our app you flash the right versions.

Reply Children
  • I have 2 versions of my fw. The only difference is this internal version I have. One I have hard coded version 110 and the other is hard coded version 111.

    If I use the Nordic app to flash 110 in and then use my characteristic to get the version using my app I get 110. If I then flash in 111 using Nordic it changes to 111.

    If I use my own app to do it then the version doesn't change even though I don't get any errors.

  • Here is the last bit of interaction between my app and the device:

    04-06 09:01:55.880 16705-16726/? I/UnityBluetoothLE: Checksumming from 0 for 37852 bytes
    04-06 09:01:55.881 16705-16726/? I/UnityBluetoothLE: Data object sent (CRC = B9E9FA25).
    04-06 09:01:55.882 16705-16726/? I/UnityBluetoothLE: Sending Calculate Checksum command (Op Code = 3)
    04-06 09:01:55.929 16705-16726/? I/UnityBluetoothLE: control bytes received: 60-03-01-DC-93-00-00-25-FA-E9-B9
    04-06 09:01:55.929 16705-16726/? I/UnityBluetoothLE: Checksum received (Offset = 37852, CRC = B9E9FA25)
    04-06 09:01:55.929 16705-16726/? I/UnityBluetoothLE: Executing firmware packet (Op Code = 4)
    04-06 09:01:56.285 16705-16726/? I/UnityBluetoothLE: control bytes received: 60-04-01
    04-06 09:01:56.285 16705-16726/? I/UnityBluetoothLE: Bytes remaining in firmware: 0
    04-06 09:01:56.287 16705-16726/? I/UnityBluetoothLE: Firmware Sent
    04-06 09:01:56.560 16705-16758/? I/UnityBluetoothLE: onConnectionStateChange
    04-06 09:01:57.573 16705-16726/? I/UnityBluetoothLE: Scanning for MYDEVICE
    04-06 09:01:57.574 16705-16726/? I/UnityBluetoothLE: Using api21scan
    04-06 09:01:57.574 16705-16726/? I/UnityBluetoothLE: Scan mode: 1
    04-06 09:01:58.093 16705-16726/? I/UnityBluetoothLE: Found MYDEVICE

    As you can see the final checksum matches what I calculated. You can also see that I send the Op Code 4 and get back 60-04-01 which indicates success.

    The next thing that happens is the device disconnects as you can see from my debug message of onConnectionStateChange. I then start scanning and find my normal device name instead of MYDEVICE DFU like I see when in DFU bootloader mode.

    I am not sure where to go from here. Does anyone have any suggestions?

  • The only reason why this could happen is that you flash 111 on 111 and expect 110, or flash 110 on 110 and expect 111. Perhaps can help from the fw side, but from mobile side receiving success at the end with correct CRC should mean the DFU worked.

  • Not sure what to say. I know I have 2 different versions and verify that because the final checksum is different between the 2. When I flash the same files using your mobile app it works. I thought maybe there was some step I was missing maybe, but couldn't find anything else to do by reviewing the Android source code.

    What all gets compared and verified by the DFU system? If the checksum matches, what else might be not matching? Is there some other step I have to take?

    Currently I upload the Init file and that checksum matches then I execute it and get a good response.

    Then I upload the bin file and that checksum matches and execute each block and get no errors and on the last one the device reboots all on its own.

    Is there maybe another step I missed that I should have seen by looking at the source code?

Related