Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9360c28ba
|
||
|
|
d7a1ee86d0
|
||
|
|
0b9f9ee882
|
||
|
|
04dc58c943
|
No files matched your search
@@ -7,6 +7,64 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [1.5.1] - 2026-05-11
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **`LoRaConfig.sync_word` is now actually applied to the SX126x.**
|
||||||
|
`reconfigure_radio` accepted the host's `sync_word` field in name
|
||||||
|
only — the value was stored in `self.config` but never written to
|
||||||
|
the chip's `LoRaSyncwordMSB`/`LoRaSyncwordLSB` register pair
|
||||||
|
(0x0740/0x0741, SX1261/2 datasheet Rev 2.2 §13.4.4). The chip sat
|
||||||
|
on whatever `LoRa::new(_, false, _)` set at cold init —
|
||||||
|
`LORAWAN_PRIVATE_SYNCWORD` (byte `0x12`, register pair `0x1424`).
|
||||||
|
Everyone got byte `0x12` regardless of the requested value. Worked
|
||||||
|
by accident for MeshCore (which uses byte `0x12`); silently broke
|
||||||
|
any host trying to talk to a non-MeshCore network. Fix wires
|
||||||
|
`cfg.sync_word` through to `lora.set_lora_sync_word(byte)` after
|
||||||
|
`enter_standby`, using the new lora-phy API from
|
||||||
|
[lora-rs/lora-rs#433](https://github.com/lora-rs/lora-rs/pull/433).
|
||||||
|
The `u16` protocol field is decoded back to its underlying byte
|
||||||
|
(`byte = (hi & 0xF0) | (lo >> 4)` after `to_be_bytes()`), the
|
||||||
|
inverse of lora-phy's `convert_sync_word` nibble-expansion. Honors
|
||||||
|
SX1261/2 §8.3.1 (BUSY-low precondition) via the existing
|
||||||
|
`ensure_ready + conditional set_standby` preamble in
|
||||||
|
`LoRa::set_lora_sync_word`.
|
||||||
|
- **First TX after `SET_CONFIG` no longer fails with `ERR(ERadio)` on
|
||||||
|
a freshly-booted chip.** The chart's `prep_for_cad_act`
|
||||||
|
(`TxCadPrep` entry) and `prep_for_tx_act` (`TxPrep` entry) both
|
||||||
|
read `ctx.mdltn` and emit `TransmitFailed` → `ERR(ERadio)` if it's
|
||||||
|
`None`. But `ctx.mdltn` was only ever assigned on the RX path —
|
||||||
|
`try_start_rx_hw` (`RxArming` entry) and `cache_rx_pkt`
|
||||||
|
(`RxSession` entry). `reconfigure_radio` already called
|
||||||
|
`to_lora_mod_params(lora, cfg)` during `SET_CONFIG` but discarded
|
||||||
|
the result via `let _ = …?;` (the dropped comment claimed image
|
||||||
|
calibration; the function is pure compute on SX126x). Hidden in
|
||||||
|
practice by any prior `RX_START` (ai-bot, `ping_pong --role rx`,
|
||||||
|
etc.) leaving `ctx.mdltn` populated until the next reflash. Fix
|
||||||
|
threads the `ModulationParams` out of `reconfigure_radio` as its
|
||||||
|
return value, and `apply_set_config` caches it in `self.mdltn`
|
||||||
|
alongside `self.config`. First TX on a fresh boot now works
|
||||||
|
without a preceding `RX_START`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **`lora-phy` `swaits/lora-rs#fixed` bumped from `e8a52ebd` →
|
||||||
|
`043d7659`.** The fork's `fixed` merge now includes a new
|
||||||
|
`feat/set-sync-word` branch alongside the three pre-existing
|
||||||
|
`fix/*` branches.
|
||||||
|
[lora-rs/lora-rs#433](https://github.com/lora-rs/lora-rs/pull/433)
|
||||||
|
adds the runtime `LoRa::set_lora_sync_word(u8)` API the radio fix
|
||||||
|
above depends on (was unavailable in stock lora-phy; the only
|
||||||
|
public sync-word entry points were `with_syncword` /
|
||||||
|
`new(_, public_network: bool, _)` at construction time). Strictly
|
||||||
|
additive in lora-phy: pure addition, no behavioral change to
|
||||||
|
`init_lora` / `with_syncword` / any existing path.
|
||||||
|
- **`hsmc` 0.5 → 0.6.** Patch bump tracked via `cargo update -p
|
||||||
|
hsmc`; no behavior change in this crate's usage. Pulled in
|
||||||
|
separately from the radio fixes so the dep churn doesn't blur the
|
||||||
|
fix commits.
|
||||||
|
|
||||||
## [1.5.0] - 2026-04-30
|
## [1.5.0] - 2026-04-30
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
Generated
+10
-10
@@ -586,7 +586,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "donglora"
|
name = "donglora"
|
||||||
version = "1.5.0"
|
version = "1.5.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
@@ -1592,9 +1592,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hsmc"
|
name = "hsmc"
|
||||||
version = "0.5.1"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "497ed9593e4baf6ef120b24aff80cb898f6832d32cdf01be9d90be0c06624e77"
|
checksum = "18bb06fda289e60e17bc7483a222fc6d9d6865b92648f836242b7a79115cc91d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt 0.3.100",
|
"defmt 0.3.100",
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
@@ -1606,9 +1606,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hsmc-macros"
|
name = "hsmc-macros"
|
||||||
version = "0.5.1"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49d0b1413ed69ba168f9d0edbf4a8ea21569eaf352edf4e11335ae3d765ba004"
|
checksum = "289a7c9f1b677168229c8ad4e992380c3951d0908b52b1d2bfae8ff3c980c35d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1812,7 +1812,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "lora-modulation"
|
name = "lora-modulation"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#e8a52ebd35352ce0267148fd392a0b1956d7735f"
|
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#043d7659dfe2148913f16b2f7ea3e9241642b770"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt 0.3.100",
|
"defmt 0.3.100",
|
||||||
]
|
]
|
||||||
@@ -1820,7 +1820,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "lora-phy"
|
name = "lora-phy"
|
||||||
version = "3.0.2-alpha"
|
version = "3.0.2-alpha"
|
||||||
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#e8a52ebd35352ce0267148fd392a0b1956d7735f"
|
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#043d7659dfe2148913f16b2f7ea3e9241642b770"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt 0.3.100",
|
"defmt 0.3.100",
|
||||||
"document-features",
|
"document-features",
|
||||||
@@ -1834,7 +1834,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "lorawan"
|
name = "lorawan"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#e8a52ebd35352ce0267148fd392a0b1956d7735f"
|
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#043d7659dfe2148913f16b2f7ea3e9241642b770"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"cmac",
|
"cmac",
|
||||||
@@ -1846,7 +1846,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "lorawan-device"
|
name = "lorawan-device"
|
||||||
version = "0.12.2"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#e8a52ebd35352ce0267148fd392a0b1956d7735f"
|
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#043d7659dfe2148913f16b2f7ea3e9241642b770"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt 0.3.100",
|
"defmt 0.3.100",
|
||||||
"document-features",
|
"document-features",
|
||||||
@@ -1861,7 +1861,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "lorawan-macros"
|
name = "lorawan-macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#e8a52ebd35352ce0267148fd392a0b1956d7735f"
|
source = "git+https://github.com/swaits/lora-rs.git?branch=fixed#043d7659dfe2148913f16b2f7ea3e9241642b770"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@ members = ["."]
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "donglora"
|
name = "donglora"
|
||||||
version = "1.5.0"
|
version = "1.5.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
authors = ["Stephen Waits <steve@waits.net>"]
|
authors = ["Stephen Waits <steve@waits.net>"]
|
||||||
@@ -29,7 +29,7 @@ embassy-usb-driver = "0.2"
|
|||||||
ucobs = { version = "0.3", features = ["legacy-msrv"] }
|
ucobs = { version = "0.3", features = ["legacy-msrv"] }
|
||||||
heapless = "0.9"
|
heapless = "0.9"
|
||||||
donglora-protocol = "1"
|
donglora-protocol = "1"
|
||||||
hsmc = { version = "0.5", default-features = false, features = ["embassy", "trace-defmt"] }
|
hsmc = { version = "0.6", default-features = false, features = ["embassy", "trace-defmt"] }
|
||||||
# Fork branch carrying CAD IRQ-clear / standby-after-CAD fixes awaiting upstream PRs.
|
# Fork branch carrying CAD IRQ-clear / standby-after-CAD fixes awaiting upstream PRs.
|
||||||
# Switch back to crates.io once changes are upstreamed.
|
# Switch back to crates.io once changes are upstreamed.
|
||||||
lora-phy = { git = "https://github.com/swaits/lora-rs.git", branch = "fixed", features = ["defmt-03"] }
|
lora-phy = { git = "https://github.com/swaits/lora-rs.git", branch = "fixed", features = ["defmt-03"] }
|
||||||
|
|||||||
+46
-26
@@ -1252,29 +1252,33 @@ impl RadioActions for RadioActionContext<'_> {
|
|||||||
Some(lora) => reconfigure_radio(lora, &cfg).await,
|
Some(lora) => reconfigure_radio(lora, &cfg).await,
|
||||||
None => Err(RadioError::Busy),
|
None => Err(RadioError::Busy),
|
||||||
};
|
};
|
||||||
if recfg_result.is_err() {
|
let mdltn = match recfg_result {
|
||||||
// Hardware failure: drop to Unconfigured (spec §6.3).
|
Ok(m) => m,
|
||||||
// Clear all per-session state — including any in-flight
|
Err(_) => {
|
||||||
// RxStart tag — so the next CmdRxStart in Unconfigured
|
// Hardware failure: drop to Unconfigured (spec §6.3).
|
||||||
// is rejected cleanly (rather than racing a stale tag
|
// Clear all per-session state — including any in-flight
|
||||||
// through respond_err_start_rx on an unrelated path).
|
// RxStart tag — so the next CmdRxStart in Unconfigured
|
||||||
self.config = None;
|
// is rejected cleanly (rather than racing a stale tag
|
||||||
self.cad_retry_delay_us = 0;
|
// through respond_err_start_rx on an unrelated path).
|
||||||
self.pending_rx_start_tag = None;
|
self.config = None;
|
||||||
info!("config cleared (apply_set_config failure tag={=u16})", tag);
|
self.cad_retry_delay_us = 0;
|
||||||
self.send(tag, DeviceMessage::Err(ErrorCode::ERadio)).await;
|
self.pending_rx_start_tag = None;
|
||||||
// Wedge takes precedence over ConfigFailedRadio so the
|
info!("config cleared (apply_set_config failure tag={=u16})", tag);
|
||||||
// chart enters Recovering (NRESET + lora.init()) instead
|
self.send(tag, DeviceMessage::Err(ErrorCode::ERadio)).await;
|
||||||
// of bouncing back to Unconfigured with a still-wedged
|
// Wedge takes precedence over ConfigFailedRadio so the
|
||||||
// chip that the next SET_CONFIG would also fail on.
|
// chart enters Recovering (NRESET + lora.init()) instead
|
||||||
if take_wedge_flag() {
|
// of bouncing back to Unconfigured with a still-wedged
|
||||||
let _ = self.emit(RadioInput::WedgeDetected);
|
// chip that the next SET_CONFIG would also fail on.
|
||||||
} else {
|
if take_wedge_flag() {
|
||||||
let _ = self.emit(RadioInput::ConfigFailedRadio);
|
let _ = self.emit(RadioInput::WedgeDetected);
|
||||||
|
} else {
|
||||||
|
let _ = self.emit(RadioInput::ConfigFailedRadio);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
self.config = Some(cfg);
|
self.config = Some(cfg);
|
||||||
|
self.mdltn = Some(mdltn);
|
||||||
info!("config set (apply_set_config success tag={=u16})", tag);
|
info!("config set (apply_set_config success tag={=u16})", tag);
|
||||||
self.cad_retry_delay_us = toa_us(&cfg, CAD_ASSUMED_PEER_PAYLOAD_B);
|
self.cad_retry_delay_us = toa_us(&cfg, CAD_ASSUMED_PEER_PAYLOAD_B);
|
||||||
if self.cad_retry_delay_us > CAD_BUDGET_US {
|
if self.cad_retry_delay_us > CAD_BUDGET_US {
|
||||||
@@ -2094,12 +2098,28 @@ fn to_lora_mod_params(
|
|||||||
lora.create_modulation_params(sf, bw, cr, cfg.freq_hz)
|
lora.create_modulation_params(sf, bw, cr, cfg.freq_hz)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn reconfigure_radio(lora: &mut LoRaDriver, cfg: &LoRaConfig) -> Result<(), RadioError> {
|
async fn reconfigure_radio(
|
||||||
|
lora: &mut LoRaDriver,
|
||||||
|
cfg: &LoRaConfig,
|
||||||
|
) -> Result<lora_phy::mod_params::ModulationParams, RadioError> {
|
||||||
lora_setup("reconfigure_radio.enter_standby", lora.enter_standby()).await?;
|
lora_setup("reconfigure_radio.enter_standby", lora.enter_standby()).await?;
|
||||||
// Calibrate image etc. via a throwaway create_modulation_params call
|
// Apply the host-supplied LoRa sync word. The protocol field is a
|
||||||
// — inside the SET_CONFIG OK window so first TX/RX is fast.
|
// u16 holding the SX126x register pair in big-endian order
|
||||||
let _ = to_lora_mod_params(lora, cfg)?;
|
// (RadioLib convention: 0x1424 == byte 0x12 == LoRa "private" /
|
||||||
Ok(())
|
// MeshCore; 0x3444 == byte 0x34 == LoRaWAN "public"). lora-phy's
|
||||||
|
// set_lora_sync_word takes the underlying single-byte form, so
|
||||||
|
// undo the nibble encoding: convert_sync_word(byte) puts the
|
||||||
|
// chip's mandatory 0x4 in the low nibble of each register byte,
|
||||||
|
// and the high nibble of each register byte holds the original
|
||||||
|
// byte's high/low nibble respectively.
|
||||||
|
let [hi, lo] = cfg.sync_word.to_be_bytes();
|
||||||
|
let sync_byte = (hi & 0xF0) | (lo >> 4);
|
||||||
|
lora_setup(
|
||||||
|
"reconfigure_radio.set_lora_sync_word",
|
||||||
|
lora.set_lora_sync_word(sync_byte),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
to_lora_mod_params(lora, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_lora(cfg: &LoRaConfig, info: &Info) -> Result<(), ErrorCode> {
|
fn validate_lora(cfg: &LoRaConfig, info: &Info) -> Result<(), ErrorCode> {
|
||||||
|
|||||||
Reference in new issue
Block a user