Skip to content

Commit 275a6ec

Browse files
authored
Support the MakerDiary dongle using UF2 (#803)
1 parent f16579a commit 275a6ec

File tree

19 files changed

+86
-22
lines changed

19 files changed

+86
-22
lines changed

crates/runner-nordic/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ radio-ble = [
6969
"dep:wasefire-applet-api",
7070
"wasefire-scheduler/board-api-radio-ble",
7171
]
72+
test-vendor = []
7273
uart = ["wasefire-scheduler/board-api-uart"]
7374
usb-ctap = ["_usb", "dep:usbd-hid", "wasefire-scheduler/board-api-usb-ctap"]
7475
usb-serial = ["_usb", "dep:usbd-serial", "wasefire-scheduler/board-api-usb-serial"]
@@ -84,6 +85,7 @@ software-crypto-sha256 = ["_crypto", "wasefire-scheduler/software-crypto-sha256"
8485
# Exactly one is enabled by xtask.
8586
board-devkit = ["header/board-devkit"]
8687
board-dongle = ["header/board-dongle"]
88+
board-makerdiary = ["header/board-makerdiary"]
8789
# Exactly one is enabled by xtask.
8890
debug = [
8991
"dep:defmt",

crates/runner-nordic/build.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ fn main() {
1616
let out = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
1717
let board = if std::env::var_os("CARGO_FEATURE_BOARD_DEVKIT").is_some() {
1818
"devkit"
19-
} else if std::env::var_os("CARGO_FEATURE_BOARD_DONGLE").is_some() {
19+
} else if std::env::var_os("CARGO_FEATURE_BOARD_DONGLE").is_some()
20+
|| std::env::var_os("CARGO_FEATURE_BOARD_MAKERDIARY").is_some()
21+
{
2022
"dongle"
2123
} else {
22-
panic!("one of board-{{devkit,dongle}} must be enabled")
24+
panic!("one of board-{{devkit,dongle,makerdiary}} must be enabled")
2325
};
2426
std::fs::copy(format!("board-{board}.x"), out.join("board.x")).unwrap();
2527
println!("cargo::rerun-if-changed=board-{board}.x");

crates/runner-nordic/crates/bootloader/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ wasefire-one-of = { path = "../../../one-of" }
2020
# Exactly one is enabled by xtask.
2121
board-devkit = ["header/board-devkit"]
2222
board-dongle = ["header/board-dongle"]
23+
board-makerdiary = ["header/board-makerdiary"]
2324

2425
[profile.release]
2526
codegen-units = 1

crates/runner-nordic/crates/bootloader/build.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ fn main() {
1616
let out = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
1717
let board = if std::env::var_os("CARGO_FEATURE_BOARD_DEVKIT").is_some() {
1818
"devkit"
19-
} else if std::env::var_os("CARGO_FEATURE_BOARD_DONGLE").is_some() {
19+
} else if std::env::var_os("CARGO_FEATURE_BOARD_DONGLE").is_some()
20+
|| std::env::var_os("CARGO_FEATURE_BOARD_MAKERDIARY").is_some()
21+
{
2022
"dongle"
2123
} else {
22-
panic!("one of board-{{devkit,dongle}} must be enabled")
24+
panic!("one of board-{{devkit,dongle,makerdiary}} must be enabled")
2325
};
2426
std::fs::copy(format!("memory-{board}.x"), out.join("memory.x")).unwrap();
2527
println!("cargo::rerun-if-changed=memory-{board}.x");

crates/runner-nordic/crates/bootloader/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use panic_abort as _;
2525
use wasefire_common::platform::Side;
2626
use wasefire_one_of::exactly_one_of;
2727

28-
exactly_one_of!["board-devkit", "board-dongle"];
28+
exactly_one_of!["board-devkit", "board-dongle", "board-makerdiary"];
2929

3030
#[entry]
3131
fn main() -> ! {

crates/runner-nordic/crates/bootloader/test.sh

+1
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ test_helper
2222
cargo check --bin=bootloader --target=thumbv7em-none-eabi --features=board-devkit
2323
cargo check --bin=bootloader --target=thumbv7em-none-eabi --features=board-devkit --release
2424
cargo check --bin=bootloader --target=thumbv7em-none-eabi --features=board-dongle --release
25+
cargo check --bin=bootloader --target=thumbv7em-none-eabi --features=board-makerdiary --release

crates/runner-nordic/crates/header/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ wasefire-one-of = { path = "../../../one-of" }
1414
# Exactly one must be enabled.
1515
board-devkit = []
1616
board-dongle = []
17+
board-makerdiary = []
1718

1819
[lints]
1920
clippy.literal-string-with-formatting-args = "allow"

crates/runner-nordic/crates/header/src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use core::ptr::addr_of;
1919
use wasefire_common::platform::Side;
2020
use wasefire_one_of::exactly_one_of;
2121

22-
exactly_one_of!["board-devkit", "board-dongle"];
22+
exactly_one_of!["board-devkit", "board-dongle", "board-makerdiary"];
2323

2424
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
2525
pub struct Header(u32);
@@ -91,15 +91,15 @@ unsafe fn read(addr: u32) -> u32 {
9191
unsafe { (addr as *const u32).read_volatile() }
9292
}
9393

94-
// Keep those values in sync with the memory-{devkit,dongle}.x linker scripts.
94+
// Keep those values in sync with the memory-{devkit,dongle,makerdiary}.x linker scripts.
9595
const HEADER_LEN: u32 = 0x00000100;
9696

9797
#[cfg(feature = "board-devkit")]
9898
const FIRMWARE_A: u32 = 0x00010000;
9999
#[cfg(feature = "board-devkit")]
100100
const FIRMWARE_B: u32 = 0x00060000;
101101

102-
#[cfg(feature = "board-dongle")]
102+
#[cfg(any(feature = "board-dongle", feature = "board-makerdiary"))]
103103
const FIRMWARE_A: u32 = 0x00008000;
104-
#[cfg(feature = "board-dongle")]
104+
#[cfg(any(feature = "board-dongle", feature = "board-makerdiary"))]
105105
const FIRMWARE_B: u32 = 0x00050000;

crates/runner-nordic/crates/header/test.sh

+1
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ test_helper
2121

2222
cargo check --lib --target=thumbv7em-none-eabi --features=board-devkit
2323
cargo check --lib --target=thumbv7em-none-eabi --features=board-dongle
24+
cargo check --lib --target=thumbv7em-none-eabi --features=board-makerdiary

crates/runner-nordic/src/board.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ impl board::Api for Board {
5353
fn syscall(x1: u32, x2: u32, x3: u32, x4: u32) -> Option<Result<u32, Error>> {
5454
match (x1, x2, x3, x4) {
5555
// The syscall_test example relies on this.
56+
#[cfg(feature = "test-vendor")]
5657
(0, 0, 0, x) => Some(Error::decode(x as i32)),
5758
#[cfg(feature = "gpio")]
5859
(0x80000000, x, y, z) => Some(gpio::syscall(x, y, z)),

crates/runner-nordic/src/board/button.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub enum Impl {}
2424
impl Support<usize> for Impl {
2525
#[cfg(feature = "board-devkit")]
2626
const SUPPORT: usize = 4;
27-
#[cfg(feature = "board-dongle")]
27+
#[cfg(any(feature = "board-dongle", feature = "board-makerdiary"))]
2828
const SUPPORT: usize = 1;
2929
}
3030

crates/runner-nordic/src/board/led.rs

+3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ use crate::with_state;
2121
pub enum Impl {}
2222

2323
impl Support<usize> for Impl {
24+
#[cfg(any(feature = "board-devkit", feature = "board-dongle"))]
2425
const SUPPORT: usize = 4;
26+
#[cfg(feature = "board-makerdiary")]
27+
const SUPPORT: usize = 3;
2528
}
2629

2730
impl Api for Impl {

crates/runner-nordic/src/board/usb.rs

+19
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
// limitations under the License.
1414

1515
use alloc::boxed::Box;
16+
#[cfg(feature = "test-vendor")]
1617
use alloc::string::String;
18+
#[cfg(feature = "test-vendor")]
1719
use core::fmt::Write;
1820

1921
use nrf52840_hal::usbd::{UsbPeripheral, Usbd};
@@ -47,6 +49,12 @@ impl HasRpc<'static, Usb> for Impl {
4749
with_state(|state| f(&mut state.protocol))
4850
}
4951

52+
#[cfg(not(feature = "test-vendor"))]
53+
fn vendor(_: &[u8]) -> Result<Box<[u8]>, Error> {
54+
Err(Error::user(Code::NotImplemented))
55+
}
56+
57+
#[cfg(feature = "test-vendor")]
5058
fn vendor(request: &[u8]) -> Result<Box<[u8]>, Error> {
5159
if let Some(request) = request.strip_prefix(b"echo ") {
5260
let mut response = request.to_vec().into_boxed_slice();
@@ -73,6 +81,17 @@ impl HasRpc<'static, Usb> for Impl {
7381
writeln!(&mut response).unwrap();
7482
}
7583
Ok(response.into_bytes().into_boxed_slice())
84+
} else if let Some(range) = request.strip_prefix(b"dump ") {
85+
let range: Option<_> = try {
86+
let range = core::str::from_utf8(range).ok()?.trim_end();
87+
let (start, limit) = range.split_once("-")?;
88+
let start = u32::from_str_radix(start, 16).ok()?;
89+
let limit = u32::from_str_radix(limit, 16).ok()?;
90+
(start, limit.checked_sub(start)?)
91+
};
92+
let Some((ptr, len)) = range else { return Err(Error::user(Code::InvalidArgument)) };
93+
let slice = unsafe { core::slice::from_raw_parts(ptr as *const u8, len as usize) };
94+
Ok(slice.to_vec().into_boxed_slice())
7695
} else {
7796
Err(Error::user(Code::InvalidArgument))
7897
}

crates/runner-nordic/src/main.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ use crate::storage::Storage;
8383

8484
exactly_one_of!["debug", "release"];
8585
exactly_one_of!["native", "wasm"];
86-
exactly_one_of!["board-devkit", "board-dongle"];
86+
exactly_one_of!["board-devkit", "board-dongle", "board-makerdiary"];
8787

8888
#[cfg(feature = "debug")]
8989
#[defmt::panic_handler]
@@ -147,6 +147,8 @@ fn main() -> ! {
147147
];
148148
#[cfg(feature = "board-dongle")]
149149
let buttons = [Button::new(port1.p1_06.into_pullup_input().degrade())];
150+
#[cfg(feature = "board-makerdiary")]
151+
let buttons = [Button::new(port0.p0_18.into_pullup_input().degrade())];
150152
#[cfg(feature = "board-devkit")]
151153
let leds = [
152154
port0.p0_13.into_push_pull_output(Level::High).degrade(),
@@ -161,6 +163,12 @@ fn main() -> ! {
161163
port1.p1_09.into_push_pull_output(Level::High).degrade(),
162164
port0.p0_12.into_push_pull_output(Level::High).degrade(),
163165
];
166+
#[cfg(feature = "board-makerdiary")]
167+
let leds = [
168+
port0.p0_23.into_push_pull_output(Level::High).degrade(),
169+
port0.p0_22.into_push_pull_output(Level::High).degrade(),
170+
port0.p0_24.into_push_pull_output(Level::High).degrade(),
171+
];
164172
#[cfg(feature = "gpio")]
165173
let gpios = [
166174
Gpio::new(port1.p1_01.degrade(), 1, 1),

crates/runner-nordic/test.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ done
2828
test_helper
2929

3030
cargo check --bin=runner-nordic --target=thumbv7em-none-eabi \
31-
--features=wasm,debug,board-devkit,_full
31+
--features=wasm,debug,board-devkit,test-vendor,_full
3232
cargo check --bin=runner-nordic --target=thumbv7em-none-eabi --features=wasm,debug,board-devkit
3333
DEFMT_LOG=trace cargo check --bin=runner-nordic --target=thumbv7em-none-eabi \
3434
--features=wasm,debug,board-devkit
3535
cargo check --bin=runner-nordic --target=thumbv7em-none-eabi --features=wasm,release,board-dongle
3636
cargo check --bin=runner-nordic --target=thumbv7em-none-eabi --features=native,release,board-dongle
37+
cargo check --bin=runner-nordic --target=thumbv7em-none-eabi \
38+
--features=native,release,board-makerdiary

crates/runner-opentitan/test.sh

+1-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ ensure_applet
2222
test_helper
2323

2424
DEFMT_LOG=trace cargo check --bin=runner-opentitan --target=riscv32imc-unknown-none-elf \
25-
--features=wasm,debug
25+
--features=wasm,debug,test-vendor
2626
cargo check --bin=runner-opentitan --target=riscv32imc-unknown-none-elf --features=wasm,release
2727
cargo check --bin=runner-opentitan --target=riscv32imc-unknown-none-elf --features=native,debug
2828
cargo check --bin=runner-opentitan --target=riscv32imc-unknown-none-elf --features=native,release
29-
cargo check --bin=runner-opentitan --target=riscv32imc-unknown-none-elf \
30-
--features=wasm,debug,test-vendor

crates/xtask/src/main.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ struct RunnerOptions {
290290
///
291291
/// Each runner supports its own set of boards:
292292
/// - Host doesn't have a notion of board.
293-
/// - Nordic supports `devkit` (default) and `dongle`.
293+
/// - Nordic supports devkit (default), dongle, and makerdiary.
294294
/// - OpenTitan doesn't have a notion of board yet.
295295
#[clap(long)]
296296
board: Option<String>,
@@ -340,6 +340,9 @@ enum RunnerCommand {
340340
#[derive(clap::Args)]
341341
struct Flash {
342342
/// Resets the flash before running.
343+
///
344+
/// This is not supported by the following boards:
345+
/// - Nordic: dongle and makerdiary
343346
#[clap(long)]
344347
reset_flash: bool,
345348

@@ -803,14 +806,14 @@ impl RunnerOptions {
803806
// TODO(https://github.com/rust-lang/rust/issues/122105): Remove when fixed.
804807
cargo.env("RUSTFLAGS", "--allow=unused-crate-dependencies");
805808
cmd::execute(&mut cargo).await?;
806-
if board == "dongle" {
809+
if matches!(board, "dongle" | "makerdiary") {
807810
let runner = self.bundle(&elf, side).await?;
808811
let bootloader = "target/thumbv7em-none-eabi/release/bootloader";
809812
let mut objcopy = wrap_command().await?;
810813
objcopy.args(["rust-objcopy", bootloader]);
811814
objcopy.arg(format!("--update-section=.runner={runner}"));
812815
cmd::execute(&mut objcopy).await?;
813-
if flash.dongle_update_support {
816+
if board == "dongle" && flash.dongle_update_support {
814817
let mut nrfdfu = wrap_command().await?;
815818
nrfdfu.args(["nrfdfu", bootloader]);
816819
cmd::execute(&mut nrfdfu).await?;
@@ -823,9 +826,18 @@ impl RunnerOptions {
823826
objcopy.arg("--remove-section=.runner");
824827
cmd::execute(&mut objcopy).await?;
825828
}
826-
let mut nrfdfu = wrap_command().await?;
827-
nrfdfu.args(["nrfdfu", bootloader]);
828-
cmd::replace(nrfdfu);
829+
let mut flash = wrap_command().await?;
830+
if board == "dongle" {
831+
flash.args(["nrfdfu", bootloader]);
832+
} else {
833+
assert_eq!(board, "makerdiary");
834+
let hex = format!("{bootloader}.hex");
835+
let mut objcopy = wrap_command().await?;
836+
objcopy.args(["rust-objcopy", "--output-target=ihex", bootloader, &hex]);
837+
cmd::execute(&mut objcopy).await?;
838+
flash.args(["uf2conv.py", "--family=0xADA52840", &hex]);
839+
}
840+
cmd::replace(flash);
829841
}
830842
}
831843
if self.name == RunnerName::OpenTitan {

scripts/hwci.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ full() {
7777
case $1 in
7878
host) FLASH_ARGS=--protocol=unix full unix host ;;
7979
# P1.01, P1.02, and P1.03 must be connected together (gpio_test).
80-
nordic) full usb nordic ;;
80+
nordic) full usb nordic --features=test-vendor ;;
8181
opentitan) full usb opentitan --features=test-vendor ;;
8282
*) run --protocol=${1:-usb} "$2" ;;
8383
esac

scripts/wrapper.sh

+11
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ run() {
3333
exec "$@"
3434
}
3535

36+
if [ "$1" = uf2conv.py ]; then
37+
if [ ! -e "$CARGO_ROOT/bin/uf2conv.py" ]; then
38+
x curl https://raw.githubusercontent.com/microsoft/uf2/refs/heads/master/utils/uf2conv.py \
39+
-o "$CARGO_ROOT/bin/uf2conv.py"
40+
chmod +x "$CARGO_ROOT/bin/uf2conv.py"
41+
x curl https://raw.githubusercontent.com/microsoft/uf2/refs/heads/master/utils/uf2families.json \
42+
-o "$CARGO_ROOT/bin/uf2families.json"
43+
fi
44+
run "$@"
45+
fi
46+
3647
ensure_cargo() {
3748
local flags="$1@$2"
3849
{ cargo install --list --root="$CARGO_ROOT" | grep -q "^$1 v$2:\$"; } && return

0 commit comments

Comments
 (0)