We currently have a solution that uses ~inboard DFU~ (edit: IAP) for firmware updates. While NOFU/ISP is also supported (for bootloader changes/partition resizes), we generally prefer IAP updates because of the possibility of user feedback. However, it’s quite slow, taking around 30 minutes or more to transfer a 1.1 MB binary from Notecard to the host once it’s downloaded.
Each request to notecard to retrieve 4KB of binary data takes about 7 seconds running over aux.serial at 115200 baud. (back of envelope math: 1100000 / 4096 = 269 chunks * 7s = 31 minutes.)
Is it possible to use the card.binary buffer with dfu.* requests? I imagine this would reduce the transfer time considerably and allow larger chunks of the binary to be received by the host.
1 Like
Hi @devElert
I’m sure we can help with this issue. Can you help me with a few questions?
- When you say IDFU, are you refering to In Application Programming (IAP)?
- Could you please clarify which Notecard APIs (in order) you are using to perform the IDFU transfer?
You can directly use card.binary to move a binary object (e.g. firmware image) from the Notecard into a buffer on your Host and then perform your DFU from within your host firmware. Although it will be easiest for you to handle the DFU via our intended APIs so let’s see if I can help get those working for you.
Thanks,
Alex
Hi @abucknall.
Thanks for offering to help. Yes, we’re using IAP for application updates, and ISP/NOFU for more significant updates (bootloader/partition updates.)
I’m currently using similar requests as used by the esp32 dfu example, note-tutorials/dfu-tutorials/esp32/esp32-dfu-v1.0.0.0 at master · blues/note-tutorials · GitHub , and from this PR, with some changes to account for changes in the notecard API that have happened in the interim https://github.com/blues/note-tutorials/pull/22 .
If there was a way to instruct dfu.get to put the data in the card.binary buffer, say, with a binary:true flag on the request, that would be ideal. (An optional “delete”:true flag would also be useful to avoid an additional request to clear the buffer beforehand.)
Thanks!
Hi @devElert
I did some digging and it seems that we had not documented the binary: true argument of dfu.get (a PR is pending this fix). You can use this to move your IAP image into the card.binary buffer for vastly faster transfers. If you are using the black V2 Notecards this will be staggeringly fast compared to the old green V1 Notecards.
Here’s an example of how you could use it:
// 1. Clear buffer (if needed from previous operation)
{“req”: “card.binary”, “delete”: true}
// 2. Load first chunk into binary buffer
{“req”: “dfu.get”, “binary”: true, “offset”: 0, “length”: 8192}
// Returns: {“cobs”: , “length”: 8192, “status”: “”}
// 3. Retrieve at desired baud using card.binary.get
{“req”: “card.binary.get”}
// 4. Continue with subsequent chunks
{“req”: “dfu.get”, “binary”: true, “offset”: 8192, “length”: 8192}
{“req”: “card.binary.get”}
Let me know if that helps and/or if you have any other questions!
Thanks,
Alex
1 Like
Hi @abucknall Thank you for digging in - that’s great news to hear it’s already supported, just undocumented. Looks like a simple change to implement in firmware.
We are exclusively using the black Notecards.
I have a few questions about the API:
-
What’s the minimum version of Notecard firmware that supports this?
-
I see the request for card.binary delete:true at the start, but not after that. Does card.binary.get delete the buffer contents automatically when it’s fully read out? I would guess not, since MD5 verification failures would require a retry.
-
Do you recommend using dfu.get and subsequent card.binary.get with the same length as done here, or would there be some performance improvement to increasing the dfu.get length so there’s a larger amount of data in the binary buffer which is then streamed to the host in chunks.
-
Is hub.set mode:dfu still required for this to work?
-
Will Blues be updating their IAP examples?
Thanks!
Thanks for these answers @abucknall - they are very helpful!
hub.set mode:dfu is not required when using binary:trueas this was designed for the older pull-based DFU mechanism. However, you may want to use mode:dfu if you expect long processing delays between chunks or if you want to explicitly signal a long running DFU operation.
Do you have more info on what hub.set mode:dfu actually does? In general, I’d prefer to keep Notecard in regular mode so all normal functionality is available, but if if there are specific cases where mode:dfu is required, then of course I’d use it when necessary. You mentioned long running operations, but I’m not sure what that really means. Anything you can share that would help guide me on when it’s needed or would be beneficial would be a great help.
For context, our app uses the binary buffer a shared, but exclusive resource (only one client at a time), which used to handle chunks of multiple upload streams, such as serial logs, and high-frequency sensor data, (via web.put), and later will be used as a download stream for IAP updates.
Thanks again!
@devElert
hub.set mode:dfu is a mechanism designed to pause Notehub syncing while DFU is underway and gracefully disconects any active sessions.
I don’t believe this mode is relevant to you as you are exclusively using black V2 Notecards; they have internal QSPI flash for storing binaries external to the modem, which are used with dfu.get to stream firmware images from the QSPI as opposed to the modem’s memory.
So the main use case would be if you explicitly wanted to restrict Notehub syncing during your IAP. With regards long running operations, this is specifically to do with pausing the modem for power consumption purposes but given that you are keen to keep the modem in regular mode and that your firmware image transfer speeds with card.binary should be short, I don’t believe this is relevant.
1 Like
Thanks for clarifying, that makes a lot of sense.
1 Like