feat(boards): RAK4631 WisBlock bring-up + build-system cleanup
RAK4631 board: - SX126X_POWER_EN on P1.05 driven HIGH at init (radio is power-gated; without this the chip has no power and SPI hangs) - HFXO + LFXO external crystals in embassy_nrf::Config (USB CDC-ACM needs +/- 500 ppm which the internal RC oscillator can't provide) - SoftwareVbusDetect(true, true) so USB enumerates without needing a CLOCK_POWER interrupt handler - Green LED on P1.03 via SimpleLed (RAK19007 Base LED1, active HIGH) - driver/mod.rs: open simple_led feature gate for rak_wisblock_4631 - Spim::new pin-order comment on SPI setup (arg order is sck/miso/mosi, not sck/mosi/miso — easy to get wrong) debug-checkpoint instrumentation (feature-gated, zero cost in release): - radio.rs: debug_blink::set(N) at each TX-phase boundary, filling in the long-aspirational blink-map doc - debug_blink.rs: checkpoint 19 between prepare_for_cad and cad(), so future bring-ups can distinguish modem-setup hang from DIO1-wait hang justfile + mise.toml: - set shell := ["mise", "exec", "--", "sh", "-c"] so recipes always resolve tools through mise, not whatever happens to be on PATH - replace per-board := vars + long if/elif _info chain with a single case statement — one place per board, two lists (names + metadata) - new flash-dfu recipe using adafruit-nrfutil via uvx, with VID:PID (239a:0029) port autodetect for the Adafruit nRF52 bootloader - mise.toml: rust pins now carry ARM targets + clippy, so 'mise install' is sufficient bootstrapping (no extra rustup target add steps) Verified TX on real hardware (RAK19007 Base + RAK4631 Core + RAK1921 OLED, US915 band): ADVERT round-trip with an external receiver.
This commit is contained in:
8 files changed
+116
-71
No files matched your search
@@ -1,43 +1,29 @@
|
|||||||
set shell := ["bash", "-c"]
|
# Run every recipe with mise's tool versions active — so `just` invocations
|
||||||
|
# of cargo, espflash, rust-objcopy, etc. always resolve to the pinned
|
||||||
# Board definitions: feature target chip
|
# versions in mise.toml, even if the user has a different version elsewhere
|
||||||
# Xtensa targets use the self-contained esp toolchain (espup-installed) with
|
# on PATH (e.g. a stray `cargo install espflash`).
|
||||||
# `-Zbuild-std=core,alloc`. Using `+esp` rather than `+nightly` keeps the
|
set shell := ["mise", "exec", "--", "sh", "-c"]
|
||||||
# compiler and rust-src versions aligned — the public nightly drifts ahead of
|
|
||||||
# the esp fork and breaks core-stdlib compilation otherwise.
|
|
||||||
# Tool versions are pinned in mise.toml; run `just setup` to install everything.
|
|
||||||
heltec_v3 := "heltec_v3 xtensa-esp32s3-none-elf esp32s3"
|
|
||||||
heltec_v3_uart := "heltec_v3_uart xtensa-esp32s3-none-elf esp32s3"
|
|
||||||
heltec_v4 := "heltec_v4 xtensa-esp32s3-none-elf esp32s3"
|
|
||||||
elecrow_thinknode_m2 := "elecrow_thinknode_m2 xtensa-esp32s3-none-elf esp32s3"
|
|
||||||
lilygo_tbeam := "lilygo_tbeam xtensa-esp32-none-elf esp32"
|
|
||||||
lilygo_tbeam_supreme := "lilygo_tbeam_supreme xtensa-esp32s3-none-elf esp32s3"
|
|
||||||
rak_wisblock_4631 := "rak_wisblock_4631 thumbv7em-none-eabihf nRF52840_xxAA"
|
|
||||||
wio_tracker_l1 := "wio_tracker_l1 thumbv7em-none-eabihf nRF52840_xxAA"
|
|
||||||
waveshare_rp2040_lora := "waveshare_rp2040_lora thumbv6m-none-eabi rp2040"
|
|
||||||
|
|
||||||
builds_dir := "builds"
|
builds_dir := "builds"
|
||||||
version := `sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml`
|
version := `sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml`
|
||||||
|
|
||||||
# All known boards
|
# All known boards. ADD A NEW BOARD HERE and in the `_info` case below.
|
||||||
|
#
|
||||||
|
# Board metadata ("feature target chip") lives in the `_info` recipe —
|
||||||
|
# Xtensa targets are built with `+esp` + `-Zbuild-std=core,alloc` (the
|
||||||
|
# self-contained esp toolchain ships its own rust-src; the public
|
||||||
|
# nightly drifts ahead and breaks core-stdlib compilation).
|
||||||
boards := "heltec_v3 heltec_v3_uart heltec_v4 elecrow_thinknode_m2 lilygo_tbeam lilygo_tbeam_supreme rak_wisblock_4631 waveshare_rp2040_lora wio_tracker_l1"
|
boards := "heltec_v3 heltec_v3_uart heltec_v4 elecrow_thinknode_m2 lilygo_tbeam lilygo_tbeam_supreme rak_wisblock_4631 waveshare_rp2040_lora wio_tracker_l1"
|
||||||
|
|
||||||
# Install all required tools and toolchains
|
# Install all required tools and toolchains
|
||||||
setup:
|
setup:
|
||||||
mise trust --yes
|
mise trust --yes
|
||||||
mise install
|
mise install
|
||||||
@# ESP Xtensa toolchain (not managed by mise)
|
@# ESP Xtensa toolchain (not a rustup component — installed out-of-band by espup)
|
||||||
@if ! rustup toolchain list | grep -q "^esp"; then \
|
@if ! rustup toolchain list | grep -q "^esp"; then \
|
||||||
echo "ESP toolchain not found, installing via espup (this may take a while)..."; \
|
echo "ESP toolchain not found, installing via espup (this may take a while)..."; \
|
||||||
espup install || { echo "error: espup install failed" >&2; exit 1; }; \
|
espup install || { echo "error: espup install failed" >&2; exit 1; }; \
|
||||||
fi
|
fi
|
||||||
@# nightly rust-src for -Zbuild-std
|
|
||||||
@if ! rustup component list --toolchain nightly --installed 2>/dev/null | grep -q "^rust-src"; then \
|
|
||||||
rustup component add rust-src --toolchain nightly; \
|
|
||||||
fi
|
|
||||||
@# ARM targets
|
|
||||||
@rustup target list --installed | grep -q "^thumbv6m-none-eabi$" || rustup target add thumbv6m-none-eabi
|
|
||||||
@rustup target list --installed | grep -q "^thumbv7em-none-eabihf$" || rustup target add thumbv7em-none-eabihf
|
|
||||||
|
|
||||||
# Build release firmware for all boards, installing toolchains as needed
|
# Build release firmware for all boards, installing toolchains as needed
|
||||||
build-all:
|
build-all:
|
||||||
@@ -76,7 +62,7 @@ build board profile="release":
|
|||||||
flash board:
|
flash board:
|
||||||
@just _ensure_tools
|
@just _ensure_tools
|
||||||
@just build {{board}} release
|
@just build {{board}} release
|
||||||
@read -r feat target chip <<< "$(just _info {{board}})"; \
|
@set -- $(just _info {{board}}); feat=$1; target=$2; chip=$3; \
|
||||||
case "$target" in \
|
case "$target" in \
|
||||||
xtensa-*) \
|
xtensa-*) \
|
||||||
port=$(just _find_port "303a:1001" "1209:5741" "10c4:ea60" "1a86:7522" "1a86:7523"); \
|
port=$(just _find_port "303a:1001" "1209:5741" "10c4:ea60" "1a86:7522" "1a86:7523"); \
|
||||||
@@ -94,7 +80,7 @@ flash board:
|
|||||||
flash-probe board:
|
flash-probe board:
|
||||||
@just _ensure_tools
|
@just _ensure_tools
|
||||||
@just build {{board}} release
|
@just build {{board}} release
|
||||||
@read -r feat target chip <<< "$(just _info {{board}})"; \
|
@set -- $(just _info {{board}}); feat=$1; target=$2; chip=$3; \
|
||||||
probe-rs run --chip $chip "{{builds_dir}}/donglora-{{board}}-v{{version}}.elf"
|
probe-rs run --chip $chip "{{builds_dir}}/donglora-{{board}}-v{{version}}.elf"
|
||||||
|
|
||||||
# Show binary size for a release build
|
# Show binary size for a release build
|
||||||
@@ -121,7 +107,7 @@ _ensure_tools:
|
|||||||
[private]
|
[private]
|
||||||
_cargo board cmd extra_args="":
|
_cargo board cmd extra_args="":
|
||||||
@just _ensure_tools
|
@just _ensure_tools
|
||||||
@read -r feat target chip <<< "$(just _info {{board}})"; \
|
@set -- $(just _info {{board}}); feat=$1; target=$2; chip=$3; \
|
||||||
extra=""; buildstd=""; \
|
extra=""; buildstd=""; \
|
||||||
case "$target" in xtensa-*) \
|
case "$target" in xtensa-*) \
|
||||||
just _require_esp_toolchain; \
|
just _require_esp_toolchain; \
|
||||||
@@ -133,7 +119,7 @@ _cargo board cmd extra_args="":
|
|||||||
# Ensure a board's toolchain is available, auto-installing if needed
|
# Ensure a board's toolchain is available, auto-installing if needed
|
||||||
[private]
|
[private]
|
||||||
_can_build board:
|
_can_build board:
|
||||||
@read -r feat target chip <<< "$(just _info {{board}})"; \
|
@set -- $(just _info {{board}}); feat=$1; target=$2; chip=$3; \
|
||||||
case "$target" in \
|
case "$target" in \
|
||||||
xtensa-*) just _require_esp_toolchain ;; \
|
xtensa-*) just _require_esp_toolchain ;; \
|
||||||
*) rustup target list --installed | grep -q "^$target$" || rustup target add "$target" ;; \
|
*) rustup target list --installed | grep -q "^$target$" || rustup target add "$target" ;; \
|
||||||
@@ -169,25 +155,25 @@ _find_port +vid_pids:
|
|||||||
[private]
|
[private]
|
||||||
_copy_firmware board profile:
|
_copy_firmware board profile:
|
||||||
@mkdir -p {{builds_dir}}
|
@mkdir -p {{builds_dir}}
|
||||||
@read -r feat target chip <<< "$(just _info {{board}})"; \
|
@set -- $(just _info {{board}}); feat=$1; target=$2; chip=$3; \
|
||||||
src="target/$target/{{profile}}/donglora"; \
|
src="target/$target/{{profile}}/donglora"; \
|
||||||
dst="{{builds_dir}}/donglora-{{board}}-v{{version}}"; \
|
dst="{{builds_dir}}/donglora-{{board}}-v{{version}}"; \
|
||||||
if [ -f "$src" ]; then \
|
if [ -f "$src" ]; then \
|
||||||
cp "$src" "$dst.elf"; echo "→ $dst.elf"; \
|
cp "$src" "$dst.elf"; echo "→ $dst.elf"; \
|
||||||
case "$target" in \
|
case "$target" in \
|
||||||
xtensa-*) \
|
xtensa-*) \
|
||||||
mise exec -- espflash save-image --chip "$chip" --merge --skip-padding "$src" "$dst.bin"; \
|
espflash save-image --chip "$chip" --merge --skip-padding "$src" "$dst.bin"; \
|
||||||
echo "→ $dst.bin"; \
|
echo "→ $dst.bin"; \
|
||||||
;; \
|
;; \
|
||||||
thumbv6m-*) \
|
thumbv6m-*) \
|
||||||
mise exec -- rust-objcopy -O ihex "$src" "$dst.hex"; \
|
rust-objcopy -O ihex "$src" "$dst.hex"; \
|
||||||
mise exec -- cargo-hex-to-uf2 hex-to-uf2 --input-path "$dst.hex" --output-path "$dst.uf2" --family rp2040; \
|
cargo-hex-to-uf2 hex-to-uf2 --input-path "$dst.hex" --output-path "$dst.uf2" --family rp2040; \
|
||||||
rm "$dst.hex"; \
|
rm "$dst.hex"; \
|
||||||
echo "→ $dst.uf2"; \
|
echo "→ $dst.uf2"; \
|
||||||
;; \
|
;; \
|
||||||
thumbv7em-*) \
|
thumbv7em-*) \
|
||||||
mise exec -- rust-objcopy -O ihex "$src" "$dst.hex"; \
|
rust-objcopy -O ihex "$src" "$dst.hex"; \
|
||||||
mise exec -- cargo-hex-to-uf2 hex-to-uf2 --input-path "$dst.hex" --output-path "$dst.uf2" --family nrf52840; \
|
cargo-hex-to-uf2 hex-to-uf2 --input-path "$dst.hex" --output-path "$dst.uf2" --family nrf52840; \
|
||||||
rm "$dst.hex"; \
|
rm "$dst.hex"; \
|
||||||
echo "→ $dst.uf2"; \
|
echo "→ $dst.uf2"; \
|
||||||
;; \
|
;; \
|
||||||
@@ -210,15 +196,19 @@ _flash_uf2 board:
|
|||||||
sync; \
|
sync; \
|
||||||
echo "Done — board will reboot automatically"
|
echo "Done — board will reboot automatically"
|
||||||
|
|
||||||
|
# Single source of truth for per-board metadata: "feature target chip".
|
||||||
|
# ADD A NEW BOARD HERE and in the `boards` list near the top of this file.
|
||||||
[private]
|
[private]
|
||||||
_info name:
|
_info name:
|
||||||
@if [ "{{name}}" == "heltec_v3" ]; then echo "{{heltec_v3}}"; \
|
@case "{{name}}" in \
|
||||||
elif [ "{{name}}" == "heltec_v3_uart" ]; then echo "{{heltec_v3_uart}}"; \
|
heltec_v3) echo "heltec_v3 xtensa-esp32s3-none-elf esp32s3" ;; \
|
||||||
elif [ "{{name}}" == "heltec_v4" ]; then echo "{{heltec_v4}}"; \
|
heltec_v3_uart) echo "heltec_v3_uart xtensa-esp32s3-none-elf esp32s3" ;; \
|
||||||
elif [ "{{name}}" == "elecrow_thinknode_m2" ]; then echo "{{elecrow_thinknode_m2}}"; \
|
heltec_v4) echo "heltec_v4 xtensa-esp32s3-none-elf esp32s3" ;; \
|
||||||
elif [ "{{name}}" == "lilygo_tbeam" ]; then echo "{{lilygo_tbeam}}"; \
|
elecrow_thinknode_m2) echo "elecrow_thinknode_m2 xtensa-esp32s3-none-elf esp32s3" ;; \
|
||||||
elif [ "{{name}}" == "lilygo_tbeam_supreme" ]; then echo "{{lilygo_tbeam_supreme}}"; \
|
lilygo_tbeam) echo "lilygo_tbeam xtensa-esp32-none-elf esp32" ;; \
|
||||||
elif [ "{{name}}" == "rak_wisblock_4631" ]; then echo "{{rak_wisblock_4631}}"; \
|
lilygo_tbeam_supreme) echo "lilygo_tbeam_supreme xtensa-esp32s3-none-elf esp32s3" ;; \
|
||||||
elif [ "{{name}}" == "waveshare_rp2040_lora" ]; then echo "{{waveshare_rp2040_lora}}"; \
|
rak_wisblock_4631) echo "rak_wisblock_4631 thumbv7em-none-eabihf nRF52840_xxAA" ;; \
|
||||||
elif [ "{{name}}" == "wio_tracker_l1" ]; then echo "{{wio_tracker_l1}}"; \
|
waveshare_rp2040_lora) echo "waveshare_rp2040_lora thumbv6m-none-eabi rp2040" ;; \
|
||||||
else echo "Unknown board: {{name}}" >&2; exit 1; fi
|
wio_tracker_l1) echo "wio_tracker_l1 thumbv7em-none-eabihf nRF52840_xxAA" ;; \
|
||||||
|
*) echo "Unknown board: {{name}}" >&2; exit 1 ;; \
|
||||||
|
esac
|
||||||
@@ -1,9 +1,22 @@
|
|||||||
[tools]
|
[tools]
|
||||||
rust = "1.94"
|
|
||||||
just = "latest"
|
just = "latest"
|
||||||
|
|
||||||
"cargo:cargo-binutils" = "latest" # `cargo size`, `cargo objdump`, etc.
|
# Cargo-installed tooling via mise's `cargo:` backend.
|
||||||
"cargo:cargo-hex-to-uf2" = "latest" # ELF → UF2 via Intel HEX for nRF52840 DFU
|
"cargo:cargo-binutils" = "latest" # rust-objcopy, rust-size
|
||||||
"cargo:espup" = "0.16"
|
"cargo:cargo-hex-to-uf2" = "latest" # ELF → UF2 for nRF52 / RP2040 DFU drives
|
||||||
"cargo:espflash" = "3" # 4.x has broken nix dependency on current stable Rust
|
"cargo:espup" = "0.16" # bootstraps the ESP Xtensa toolchain
|
||||||
"cargo:probe-rs-tools" = "0.31"
|
"cargo:espflash" = "3" # flash + save-image for ESP targets
|
||||||
|
"cargo:probe-rs-tools" = "0.31" # debug-probe flash/run for ARM targets
|
||||||
|
|
||||||
|
# Stable Rust + cross-compile targets. Targets land under $RUSTUP_HOME for
|
||||||
|
# the pinned toolchain, so they're always available under `mise exec` — no
|
||||||
|
# extra `rustup target add` step at setup time.
|
||||||
|
#
|
||||||
|
# Xtensa ESP targets are NOT listed here — they use the self-contained `esp`
|
||||||
|
# toolchain installed out-of-band by `espup` (see `just setup`). That
|
||||||
|
# toolchain ships its own rust-src for `-Zbuild-std`.
|
||||||
|
[tools.rust]
|
||||||
|
version = "1.94"
|
||||||
|
profile = "default"
|
||||||
|
components = "clippy"
|
||||||
|
targets = "thumbv6m-none-eabi,thumbv7em-none-eabihf"
|
||||||
+2
-2
@@ -86,8 +86,8 @@ pub fn init_radio(
|
|||||||
let reset = Output::new(reset_pin, Level::High, OutputConfig::default());
|
let reset = Output::new(reset_pin, Level::High, OutputConfig::default());
|
||||||
let dio0 = Input::new(dio0_pin, InputConfig::default().with_pull(Pull::Down));
|
let dio0 = Input::new(dio0_pin, InputConfig::default().with_pull(Pull::Down));
|
||||||
|
|
||||||
let iv = GenericSx127xInterfaceVariant::new(reset, dio0, None, None)
|
let iv =
|
||||||
.expect("SX1276 interface init");
|
GenericSx127xInterfaceVariant::new(reset, dio0, None, None).expect("SX1276 interface init");
|
||||||
|
|
||||||
let sx_config = sx127x::Config {
|
let sx_config = sx127x::Config {
|
||||||
chip: sx127x::Sx1276,
|
chip: sx127x::Sx1276,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type RadioSpiDevice = SpiDevice<'static, NoopRawMutex, mcu::SpiBus, Nss>;
|
|||||||
pub type RadioDriver = Sx126x<RadioSpiDevice, Iv, Sx1262>;
|
pub type RadioDriver = Sx126x<RadioSpiDevice, Iv, Sx1262>;
|
||||||
pub type UsbDriver = mcu::UsbNrfDriver;
|
pub type UsbDriver = mcu::UsbNrfDriver;
|
||||||
pub type DisplayI2c = mcu::I2cBus;
|
pub type DisplayI2c = mcu::I2cBus;
|
||||||
pub type LedDriver = ();
|
pub type LedDriver = crate::driver::simple_led::SimpleLed<Output<'static>>;
|
||||||
|
|
||||||
pub type DisplayDriver = ssd1306::Ssd1306Async<
|
pub type DisplayDriver = ssd1306::Ssd1306Async<
|
||||||
ssd1306::prelude::I2CInterface<DisplayI2c>,
|
ssd1306::prelude::I2CInterface<DisplayI2c>,
|
||||||
@@ -78,10 +78,14 @@ impl LoRaBoard for Board {
|
|||||||
type CommParts = UsbParts;
|
type CommParts = UsbParts;
|
||||||
type DisplayParts = DisplayParts;
|
type DisplayParts = DisplayParts;
|
||||||
type DisplayDriver = DisplayDriver;
|
type DisplayDriver = DisplayDriver;
|
||||||
type LedDriver = ();
|
type LedDriver = LedDriver;
|
||||||
|
|
||||||
fn init() -> Self {
|
fn init() -> Self {
|
||||||
let p = embassy_nrf::init(Default::default());
|
// USB requires the 32 MHz HFXO (±50 ppm); the RC oscillator is out of spec.
|
||||||
|
let mut config = embassy_nrf::config::Config::default();
|
||||||
|
config.hfclk_source = embassy_nrf::config::HfclkSource::ExternalXtal;
|
||||||
|
config.lfclk_source = embassy_nrf::config::LfclkSource::ExternalXtal;
|
||||||
|
let p = embassy_nrf::init(config);
|
||||||
Self { p }
|
Self { p }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,12 +93,18 @@ impl LoRaBoard for Board {
|
|||||||
mcu::mac_address()
|
mcu::mac_address()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_parts(self) -> BoardParts<RadioParts, UsbParts, DisplayParts, ()> {
|
fn into_parts(self) -> BoardParts<RadioParts, UsbParts, DisplayParts, LedDriver> {
|
||||||
let p = self.p;
|
let p = self.p;
|
||||||
|
|
||||||
|
// SX1262 is power-gated on P1.05 — must be HIGH before any SPI access.
|
||||||
|
let sx_power_en = Output::new(p.P1_05, Level::High, OutputDrive::Standard);
|
||||||
|
core::mem::forget(sx_power_en);
|
||||||
|
|
||||||
// ── SPI bus for SX1262 ──────────────────────────────────
|
// ── SPI bus for SX1262 ──────────────────────────────────
|
||||||
let mut spi_cfg = spim::Config::default();
|
let mut spi_cfg = spim::Config::default();
|
||||||
spi_cfg.frequency = spim::Frequency::M1;
|
spi_cfg.frequency = spim::Frequency::M1;
|
||||||
|
// embassy_nrf::spim::Spim::new args: (spim, irq, sck, miso, mosi, config).
|
||||||
|
// Per RAK4631 BSP: SCK=P1.11, MISO=P1.13, MOSI=P1.12.
|
||||||
let spi = Spim::new(p.SPI3, mcu::Irqs, p.P1_11, p.P1_13, p.P1_12, spi_cfg);
|
let spi = Spim::new(p.SPI3, mcu::Irqs, p.P1_11, p.P1_13, p.P1_12, spi_cfg);
|
||||||
let spi_bus = mcu::share_spi_bus(spi);
|
let spi_bus = mcu::share_spi_bus(spi);
|
||||||
|
|
||||||
@@ -121,7 +131,9 @@ impl LoRaBoard for Board {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ── USB ─────────────────────────────────────────────────
|
// ── USB ─────────────────────────────────────────────────
|
||||||
let vbus = mcu::alloc_vbus_detect(true, false);
|
// SoftwareVbusDetect(vbus_detected, power_ready). Mark both true so the
|
||||||
|
// driver doesn't block waiting for a power-ready signal we never raise.
|
||||||
|
let vbus = mcu::alloc_vbus_detect(true, true);
|
||||||
let host = UsbParts {
|
let host = UsbParts {
|
||||||
driver: Driver::new(p.USBD, mcu::Irqs, vbus),
|
driver: Driver::new(p.USBD, mcu::Irqs, vbus),
|
||||||
};
|
};
|
||||||
@@ -138,11 +150,15 @@ impl LoRaBoard for Board {
|
|||||||
);
|
);
|
||||||
let display = Some(DisplayParts { i2c });
|
let display = Some(DisplayParts { i2c });
|
||||||
|
|
||||||
|
// Green LED on P1.03 (RAK19007 Base, active HIGH).
|
||||||
|
let led_pin = Output::new(p.P1_03, Level::Low, OutputDrive::Standard);
|
||||||
|
let led = crate::driver::simple_led::SimpleLed(led_pin);
|
||||||
|
|
||||||
BoardParts {
|
BoardParts {
|
||||||
radio,
|
radio,
|
||||||
host,
|
host,
|
||||||
display,
|
display,
|
||||||
led: (),
|
led,
|
||||||
mac: Self::mac_address(),
|
mac: Self::mac_address(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-9
@@ -138,15 +138,16 @@ fn phase_depth(n: u8) -> u8 {
|
|||||||
match n {
|
match n {
|
||||||
18 => 1, // pre-TX: CmdTransmit just read from commands channel
|
18 => 1, // pre-TX: CmdTransmit just read from commands channel
|
||||||
6 => 2, // perform_tx entered
|
6 => 2, // perform_tx entered
|
||||||
7 => 3, // in CAD
|
7 => 3, // in CAD (before prepare_for_cad)
|
||||||
8 => 4, // in prepare_for_tx
|
19 => 4, // after prepare_for_cad (awaiting lora.cad IRQ)
|
||||||
9 => 5, // in tx().await
|
8 => 5, // in prepare_for_tx
|
||||||
10 => 6, // do_tx returned Ok
|
9 => 6, // in tx().await
|
||||||
11 => 7, // respond_tx_done entered
|
10 => 7, // do_tx returned Ok
|
||||||
12 => 8, // respond_tx_done: responses.send returned
|
11 => 8, // respond_tx_done entered
|
||||||
13 => 9, // host_task received response from channel
|
12 => 9, // respond_tx_done: responses.send returned
|
||||||
14 => 10, // host_task wrote response to UART (terminal success)
|
13 => 10, // host_task received response from channel
|
||||||
15 => 11, // TX errored (terminal error)
|
14 => 11, // host_task wrote response to UART (terminal success)
|
||||||
|
15 => 12, // TX errored (terminal error)
|
||||||
_ => 0, // not a TX phase
|
_ => 0, // not a TX phase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -37,8 +37,8 @@ use embassy_time::Timer;
|
|||||||
use hsmc::statechart;
|
use hsmc::statechart;
|
||||||
|
|
||||||
use crate::board::{self, Board, DisplayDriver, DisplayParts, LedDriver, LoRaBoard, RgbLed};
|
use crate::board::{self, Board, DisplayDriver, DisplayParts, LedDriver, LoRaBoard, RgbLed};
|
||||||
use crate::driver::DisplayBrightness;
|
|
||||||
use crate::channel::{DisplayCommand, DisplayCommandChannel, RadioEvent, RadioEventChannel};
|
use crate::channel::{DisplayCommand, DisplayCommandChannel, RadioEvent, RadioEventChannel};
|
||||||
|
use crate::driver::DisplayBrightness;
|
||||||
use crate::protocol::LoRaConfig;
|
use crate::protocol::LoRaConfig;
|
||||||
|
|
||||||
use render::{BoardInfo, RSSI_HISTORY_LEN};
|
use render::{BoardInfo, RSSI_HISTORY_LEN};
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ pub mod inverted_pin;
|
|||||||
feature = "elecrow_thinknode_m2",
|
feature = "elecrow_thinknode_m2",
|
||||||
feature = "lilygo_tbeam_supreme",
|
feature = "lilygo_tbeam_supreme",
|
||||||
feature = "lilygo_tbeam",
|
feature = "lilygo_tbeam",
|
||||||
|
feature = "rak_wisblock_4631",
|
||||||
feature = "wio_tracker_l1",
|
feature = "wio_tracker_l1",
|
||||||
feature = "waveshare_rp2040_lora"
|
feature = "waveshare_rp2040_lora"
|
||||||
))]
|
))]
|
||||||
|
|||||||
+25
-1
@@ -369,6 +369,8 @@ async fn next_packet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn perform_tx(lora: &mut LoRaDriver, pending: &mut Option<PendingTx>) -> RadioInput {
|
async fn perform_tx(lora: &mut LoRaDriver, pending: &mut Option<PendingTx>) -> RadioInput {
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(6);
|
||||||
let Some(tx) = pending.take() else {
|
let Some(tx) = pending.take() else {
|
||||||
return RadioInput::TransmitFailed;
|
return RadioInput::TransmitFailed;
|
||||||
};
|
};
|
||||||
@@ -378,7 +380,11 @@ async fn perform_tx(lora: &mut LoRaDriver, pending: &mut Option<PendingTx>) -> R
|
|||||||
airtime_us: Instant::now().duration_since(start).as_micros() as u32,
|
airtime_us: Instant::now().duration_since(start).as_micros() as u32,
|
||||||
},
|
},
|
||||||
Ok(TxOutcome::ChannelBusy) => RadioInput::ChannelBusy,
|
Ok(TxOutcome::ChannelBusy) => RadioInput::ChannelBusy,
|
||||||
Err(_) => RadioInput::TransmitFailed,
|
Err(_) => {
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(15);
|
||||||
|
RadioInput::TransmitFailed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,7 +711,13 @@ async fn do_tx(lora: &mut LoRaDriver, tx: &PendingTx) -> Result<TxOutcome, Radio
|
|||||||
let mdltn = to_lora_mod_params(lora, &tx.config)?;
|
let mdltn = to_lora_mod_params(lora, &tx.config)?;
|
||||||
|
|
||||||
if !tx.skip_cad {
|
if !tx.skip_cad {
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(7);
|
||||||
lora.prepare_for_cad(&mdltn).await?;
|
lora.prepare_for_cad(&mdltn).await?;
|
||||||
|
// Reaches here → prepare_for_cad (SPI setup) completed.
|
||||||
|
// Hang past here means lora.cad() is waiting on DIO1.
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(19);
|
||||||
let mut saw_activity = false;
|
let mut saw_activity = false;
|
||||||
for _ in 0..CAD_MAX_RETRIES {
|
for _ in 0..CAD_MAX_RETRIES {
|
||||||
if !lora.cad(&mdltn).await? {
|
if !lora.cad(&mdltn).await? {
|
||||||
@@ -728,9 +740,15 @@ async fn do_tx(lora: &mut LoRaDriver, tx: &PendingTx) -> Result<TxOutcome, Radio
|
|||||||
tx.config.iq_invert,
|
tx.config.iq_invert,
|
||||||
&mdltn,
|
&mdltn,
|
||||||
)?;
|
)?;
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(8);
|
||||||
lora.prepare_for_tx(&mdltn, &mut tx_pkt, tx.config.tx_power_dbm as i32, &tx.data)
|
lora.prepare_for_tx(&mdltn, &mut tx_pkt, tx.config.tx_power_dbm as i32, &tx.data)
|
||||||
.await?;
|
.await?;
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(9);
|
||||||
lora.tx().await?;
|
lora.tx().await?;
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(10);
|
||||||
Ok(TxOutcome::Transmitted)
|
Ok(TxOutcome::Transmitted)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -781,13 +799,19 @@ pub async fn radio_task(
|
|||||||
events: &'static RadioEventChannel,
|
events: &'static RadioEventChannel,
|
||||||
info: &'static Info,
|
info: &'static Info,
|
||||||
) {
|
) {
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(1);
|
||||||
let lora = match LoRa::new(parts.driver, false, parts.delay).await {
|
let lora = match LoRa::new(parts.driver, false, parts.delay).await {
|
||||||
Ok(l) => {
|
Ok(l) => {
|
||||||
info!("radio initialized");
|
info!("radio initialized");
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(2);
|
||||||
l
|
l
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("radio init failed: {}", e);
|
error!("radio init failed: {}", e);
|
||||||
|
#[cfg(feature = "debug-checkpoint")]
|
||||||
|
crate::debug_blink::set(16);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user