Notecard API Requests for DFU
Notecard provides a set of APIs to help you monitor and manage both host MCU and Notecard firmware updates. Based on the Notecard's own firmware update protocols, these APIs offload a significant part of the burden of implementing over-the-air firmware updates.
Certain API requests below are only available for IAP host MCU firmware updates, Notecard Outboard Firmware Update, and/or Notecard firmware updates and are identified on a per-API basis.
NOFU Only: Enabling Notecard Outboard Firmware Update
The
card.dfu
API is only relevant for Notecard Outboard Firmware Update.
The card.dfu API is used to configure a Notecard to enable or disable Notecard Outboard Firmware Update.
For example, to allow the Notecard to flash the host MCU with a downloaded
binary on an STM32-based host, set "name"
to "stm32"
and "on"
to true
:
{
"req": "card.dfu",
"name": "stm32",
"on": true
}
J *req = NoteNewRequest("card.dfu");
JAddStringToObject(req, "name", "stm32");
JAddBoolToObject(req, "on", true);
NoteRequest(req);
req = {"req": "card.dfu"}
req["name"] = "stm32"
req["on"] = True
card.Transaction(req)
Obtaining Firmware Download Status
The
dfu.status
API works with all types of firmware updates.
The dfu.status API is used to determine the status of the background download of firmware, and locally control whether the Notecard will allow a background firmware download.
When called with no arguments, a dfu.status
request returns an object
indicating the current mode
(on
or off
) to indicate whether local firmware
updates are allowed. The default mode is idle
which indicates that no firmware
download is in progress and no data has been downloaded. In addition, on
is
true
by default to indicate that the Notecard can receive firmware updates.
Use the "name"
argument to specify the type of firmware update you want to
check:
"user"
for IAP or Notecard Outboard Firmware Update host MCU updates."card"
for Notecard firmware updates.
{
"req": "dfu.status",
"name": "user"
}
J *req = NoteNewRequest("dfu.status");
JAddStringToObject(req, "name", "user");
NoteRequest(req);
req = {"req": "dfu.status"}
req["name"] = "user"
rsp = card.Transaction(req)
{
"mode": "idle",
"on": true
}
To disable firmware downloads to the Notecard, set the off
argument to true
:
{
"req": "dfu.status",
"off": true,
"name": "user"
}
J *req = NoteNewRequest("dfu.status");
JAddBoolToObject(req, "off", true);
JAddStringToObject(req, "name", "user");
NoteRequest(req);
req = {"req": "dfu.status"}
req["off"] = True
req["name"] = "user"
rsp = card.Transaction(req)
To turn it back on, set the on
argument to true
:
{
"req": "dfu.status",
"on": true,
"name": "user"
}
J *req = NoteNewRequest("dfu.status");
JAddBoolToObject(req, "on", true);
JAddStringToObject(req, "name", "user");
NoteRequest(req);
req = {"req": "dfu.status"}
req["on"] = True
req["name"] = "user"
rsp = card.Transaction(req)
You can also use a voltage-variable value to control whether or not firmware
updates are allowed, based on the battery level of the device, by using the
vvalue
argument. This argument expects semicolon-delimited string values of on
or off values that correspond to a battery state. The pre-defined Notecard
battery states are:
usb
high
normal
low
dead
When the Notecard's power source is in a given state, it will adjust whether a firmware download is allowed based on the values in that string. For instance, if you want to allow firmware updates when the battery is full or high, but NOT when the voltage is lower, send a request like this:
{
"req": "dfu.status",
"vvalue": "usb:1;high:1;normal:0;low:0;dead:0",
"name": "user"
}
J *req = NoteNewRequest("dfu.status");
JAddStringToObject(req, "vvalue", "usb:1;high:1;normal:0;low:0;dead:0");
JAddStringToObject(req, "name", "user");
NoteRequest(req);
req = {"req": "dfu.status"}
req["vvalue"] = "usb:1;high:1;normal:0;low:0;dead:0"
req["name"] = "user"
rsp = card.Transaction(req)
In addition to idle
mode, dfu.status
will return one of the following mode
values after a device firmware update has been activated:
downloading
ready
error
completed
The downloading
mode indicates that the Notecard detected the presence of new
firmware on a previous sync and is in the process of downloading it. When in
this mode, a status
string is included in the response with additional details
about download progress.
{
"mode": "downloading",
"status": "downloaded 66% (28672/42892)",
"on": true
}
Once the download is complete, the mode
changes to ready
to indicate that
the firmware binary is fully downloaded and verified. When in this mode, a
status
string is included, as well as a body
JSON object that includes
essential details about the firmware binary, including the length
of the
binary, its md5
hash, and more.
{
"mode": "ready",
"status": "successfully downloaded",
"on": true,
"body": {
"crc32": 2525287425,
"created": 1599163431,
"info": {},
"length": 42892,
"md5": "5a3f73a7f1b4bc8917b12b36c2532969",
"modified": 1599163431,
"name": "stm32-new-firmware$20200903200351.bin",
"notes": "Latest prod firmware",
"source": "stm32-new-firmware.bin",
"type": "firmware"
}
}
If the Notecard encounters an error during the download, the mode
reports as
error
and the status
field will provide a reason for the error.
{
"mode": "error",
"status": "DFU did not complete",
"on": true
}
IAP Only: Entering Host DFU Mode on the Notecard
The
hub.set
API's"mode":"dfu"
argument is only relevant for IAP host MCU firmware updates.
Once the firmware binary is available, Notecard should be put into DFU mode by
setting the
hub.set API's
mode
argument to dfu
. This request halts all Notecard communications
activity and allows the host to access downloaded host MCU firmware from
internal storage.
{
"req": "hub.set",
"mode": "dfu"
}
J *req = NoteNewRequest("hub.set");
JAddStringToObject(req, "mode", "dfu");
NoteRequest(req);
req = {"req": "hub.set"}
req["mode"] = "dfu"
rsp = card.Transaction(req)
IAP Only: Ensuring Host DFU Mode is Active
The
dfu.get
API is only relevant for IAP host MCU firmware updates.
Depending on in-progress communications on the Notecard, it may take up to 30
seconds after setting the device to "dfu"
mode before it is ready to
retrieve host MCU firmware. To ensure that the Notecard is in DFU mode, use the
dfu.get API to set
the length
argument to 0
. This will verify that the device is in DFU mode
without attempting to retrieve firmware.
{
"req": "dfu.get",
"length": 0
}
J *req = NoteNewRequest("dfu.get");
JAddNumberToObject(req, "length", 0);
NoteRequest(req);
req = {"req": "dfu.get"}
req["length"] = 0
rsp = card.Transaction(req)
IAP Only: Retrieving Host Firmware from the Notecard
The
dfu.get
API is only relevant for IAP host MCU firmware updates.
Once the Notecard is in dfu
mode, use the
dfu.get API to
retrieve the downloaded host MCU firmware. This is typically done in successive
chunks of length n
until the entire binary has been delivered to the host. Use
the length
argument to provide a number of bytes to read for each request, and
offset
on each successive request to skip to the next available chunk.
For instance, if you wanted to read the binary 32 bytes at a time, the first
request to dfu.get
would look like this:
{
"req": "dfu.get",
"length": 32
}
J *req = NoteNewRequest("dfu.get");
JAddNumberToObject(req, "length", 32);
NoteRequest(req);
req = {"req": "dfu.get"}
req["length"] = 32
rsp = card.Transaction(req)
And each subsequent request would add an offset value that increments by the previously-requested length, each time:
{
"req": "dfu.get",
"length": 32,
"offset": 32
}
J *req = NoteNewRequest("dfu.get");
JAddNumberToObject(req, "length", 32);
JAddNumberToObject(req, "offset", 32);
NoteRequest(req);
req = {"req": "dfu.get"}
req["length"] = 32
req["offset"] = 32
rsp = card.Transaction(req)
The first request to dfu.get
returns the same body
returned by dfu.status
after a successful download. The first and subsequent requests also return a
payload
string containing the portion of the binary of the requested length
and offset
.
{
"payload": "AAAAAAAAAAAAAAAAcy8ACIEvAAgAAAAAjy8ACJ0vAAg="
}
Clearing DFU State
The
dfu.status
API works with all types of firmware updates.
After a host MCU or Notecard firmware update is complete, you can clear the
Notecard's DFU state with a
dfu.status request
and the stop
argument. You can optionally supply a status
message that will
be sent to Notehub to indicate the final update status.
Use the "name"
argument to specify the type of firmware update to clear:
"user"
for host MCU updates."card"
for Notecard updates.
{
"req": "dfu.status",
"stop": true,
"status": "firmware update successful",
"name": "user"
}
J *req = NoteNewRequest("dfu.status");
JAddBoolToObject(req, "stop", true);
JAddStringToObject(req, "status", "firmware update successful");
JAddStringToObject(req, "name", "user");
NoteRequest(req);
req = {"req": "dfu.status"}
req["stop"] = True
req["status"] = "firmware update successful"
req["name"] = "user"
rsp = card.Transaction(req)
This request will set the dfu.status
mode
to completed
and set the
status
field to the string value provided.
Don't forget to exit DFU mode if performing an IAP host MCU firmware update!
Once the IAP host DFU process is completed, be sure to return the Notecard to
periodic
or continuous
mode after the firmware update is complete with
another hub.set
request.
If you don't do this, the device will remain in dfu
mode, unable to sync with
Notehub.
{
"req": "hub.set",
"mode": "periodic"
}
J *req = NoteNewRequest("hub.set");
JAddStringToObject(req, "mode", "periodic");
NoteRequest(req);
req = {"req": "hub.set"}
req["mode"] = "periodic"
card.Transaction(req)