Skip to content

Commit bcaccd6

Browse files
authored
add ODFU example from note-outboard-dfu repo (#166)
1 parent 124eca3 commit bcaccd6

3 files changed

Lines changed: 148 additions & 0 deletions

File tree

.github/workflows/note-arduino-ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ jobs:
122122
- ./examples/Example7_PowerControl/Example7_PowerControl.ino
123123
- ./examples/Example8_BinarySendReceive/Example8_BinarySendReceive.ino
124124
- ./examples/Example9_BinarySendReceiveChunked/Example9_BinarySendReceiveChunked.ino
125+
- ./examples/Example10_OutboardFirmwareUpdate/Example10_OutboardFirmwareUpdate.ino
125126
board:
126127
# Order: fqbn, extra-flags (matches build_example.sh parameter order)
127128
# Note: index URLs are pre-configured in Dockerfile, no need to specify here

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ with:
102102
- [Using Note templates](examples/Example5_UsingTemplates/Example5_UsingTemplates.ino)
103103
- [Sensor tutorial](examples/Example6_SensorTutorial/Example6_SensorTutorial.ino)
104104
- [Power control](examples/Example7_PowerControl/Example7_PowerControl.ino)
105+
- [Notecard Outboard Firmware Update](examples/Example10_OutboardFirmwareUpdate/Example10_OutboardFirmwareUpdate.ino)
105106

106107
Before running an example, you will need to set the Product Identifier, either
107108
in code or on your connected Notecard. Steps on how to do this can be found at
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright 2026 Blues Inc. All rights reserved.
2+
//
3+
// Use of this source code is governed by licenses granted by the
4+
// copyright holder including that found in the LICENSE file.
5+
//
6+
// This example demonstrates Notecard Outboard Firmware Update, which lets you
7+
// update this host MCU's firmware over-the-air from Notehub, with no host code
8+
// required to perform the download. The Notecard receives the new firmware
9+
// image and reprograms the host over the DFU signals on a Notecarrier F.
10+
//
11+
// The sketch does two things:
12+
//
13+
// 1. In setup(), it configures the Notecard to enable Outboard Firmware
14+
// Update (see the `card.dfu`, `card.aux` and `dfu.status` requests below).
15+
// 2. In loop(), it blinks the built-in LED with a recognizable pattern and
16+
// reports a firmware version. This is the "payload" you will update: build
17+
// and upload a new version of this sketch to Notehub, apply it to the
18+
// host, and watch the blink pattern (and reported version) change.
19+
//
20+
// This example targets STM32-based Blues hosts on a Notecarrier F, such as the
21+
// Swan and Cygnet Feathers and the STM32F405 Feather. See DFU_MCU_TYPE below
22+
// for hosts (like the SparkFun MicroMod STM32) whose boot pin is inverted.
23+
//
24+
// For the full walkthrough, see:
25+
// https://dev.blues.io/notehub/host-firmware-updates/notecard-outboard-firmware-update/
26+
27+
// Include the Arduino library for the Notecard
28+
#include <Notecard.h>
29+
30+
// If the Notecard is connected to a serial port, define it here. For example,
31+
// if you are using the Adafruit Feather NRF52840 Express, the RX/TX pins (and
32+
// thus the Notecard) are on Serial1. However, if you are using an M5Stack Basic
33+
// Core IoT Development Kit, you would connect the R2 pin to the Notecard's TX
34+
// pin, and the M5Stack's T2 pin to the Notecard's RX pin, and then would use
35+
// Serial2.
36+
//
37+
// Also, you may define a debug output port where you can watch transactions as
38+
// they are sent to and from the Notecard. When using the Arduino IDE this is
39+
// typically "Serial", but you can use any available port.
40+
//
41+
// Note that both of these definitions are optional; just prefix either line
42+
// with `//` to remove it.
43+
//
44+
// - Remove `txRxPinsSerial` if you wired your Notecard using I2C SDA/SCL pins,
45+
// instead of serial RX/TX.
46+
// - Remove `usbSerial` if you don't want the Notecard library to output debug
47+
// information.
48+
49+
// #define txRxPinsSerial Serial1
50+
#define usbSerial Serial
51+
52+
// This is the unique Product Identifier for your device
53+
#ifndef PRODUCT_UID
54+
#define PRODUCT_UID "" // "com.my-company.my-name:my-project"
55+
#pragma message "PRODUCT_UID is not defined in this example. Please ensure your Notecard has a product identifier set before running this example or define it in code here. More details at https://dev.blues.io/tools-and-sdks/samples/product-uid"
56+
#endif
57+
58+
#define myProductID PRODUCT_UID
59+
60+
// The host MCU type reported to the Notecard via `card.dfu`. Use "stm32" for
61+
// most STM32 hosts (Swan, Cygnet, STM32F405 Feather). Use "stm32-bi" for hosts
62+
// whose boot pin is active LOW / inverted, such as the SparkFun MicroMod STM32.
63+
#ifndef DFU_MCU_TYPE
64+
#define DFU_MCU_TYPE "stm32"
65+
#endif
66+
67+
// The firmware version reported to Notehub via `dfu.status`. Bump this (and
68+
// change the blink pattern below) when you build a new image to update to.
69+
#define FIRMWARE_VERSION "1.0.0"
70+
71+
Notecard notecard;
72+
73+
// One-time Arduino initialization
74+
void setup()
75+
{
76+
// Set up the built-in LED so loop() can show a recognizable running pattern.
77+
pinMode(LED_BUILTIN, OUTPUT);
78+
79+
// Set up for debug output (if available).
80+
#ifdef usbSerial
81+
// If you open Arduino's serial terminal window, you'll be able to watch
82+
// JSON objects being transferred to and from the Notecard for each request.
83+
usbSerial.begin(115200);
84+
const size_t usb_timeout_ms = 3000;
85+
for (const size_t start_ms = millis(); !usbSerial && (millis() - start_ms) < usb_timeout_ms;)
86+
;
87+
88+
// For low-memory platforms, don't turn on internal Notecard logs.
89+
#ifndef NOTE_C_LOW_MEM
90+
notecard.setDebugOutputStream(usbSerial);
91+
#else
92+
#pragma message("INFO: Notecard debug logs disabled. (non-fatal)")
93+
#endif // !NOTE_C_LOW_MEM
94+
#endif // usbSerial
95+
96+
// Initialize the physical I/O channel to the Notecard
97+
#ifdef txRxPinsSerial
98+
notecard.begin(txRxPinsSerial, 9600);
99+
#else
100+
notecard.begin();
101+
#endif
102+
103+
// Put the Notecard in continuous mode so it maintains a live session with
104+
// Notehub. Outboard Firmware Update requires the Notecard to be in
105+
// "continuous" or "periodic" mode. `sendRequestWithRetry()` is important on
106+
// the first message after a cold boot, to handle the hardware race
107+
// condition while the Notecard becomes ready.
108+
J *req = notecard.newRequest("hub.set");
109+
if (myProductID[0])
110+
{
111+
JAddStringToObject(req, "product", myProductID);
112+
}
113+
JAddStringToObject(req, "mode", "continuous");
114+
notecard.sendRequestWithRetry(req, 5); // 5 seconds
115+
116+
// Enable Outboard Firmware Update for this host and tell the Notecard which
117+
// MCU type it is driving. On a Notecarrier F the DFU signals are routed over
118+
// the Notecard's shared AUX pins, so we set `mode` to "aux" here.
119+
req = notecard.newRequest("card.dfu");
120+
JAddStringToObject(req, "name", DFU_MCU_TYPE);
121+
JAddBoolToObject(req, "on", true);
122+
JAddStringToObject(req, "mode", "aux");
123+
notecard.sendRequest(req);
124+
125+
// Free the AUX pins so they can be used for Outboard Firmware Update.
126+
req = notecard.newRequest("card.aux");
127+
JAddStringToObject(req, "mode", "off");
128+
notecard.sendRequest(req);
129+
130+
// Enable host DFU and report the running firmware version to Notehub.
131+
req = notecard.newRequest("dfu.status");
132+
JAddBoolToObject(req, "on", true);
133+
JAddStringToObject(req, "version", FIRMWARE_VERSION);
134+
notecard.sendRequest(req);
135+
}
136+
137+
// In the Arduino main loop, blink the built-in LED with a recognizable pattern.
138+
// After an Outboard Firmware Update, change this pattern (and bump
139+
// FIRMWARE_VERSION above) so you can visually confirm the update was applied.
140+
void loop()
141+
{
142+
digitalWrite(LED_BUILTIN, HIGH);
143+
delay(500);
144+
digitalWrite(LED_BUILTIN, LOW);
145+
delay(500);
146+
}

0 commit comments

Comments
 (0)