fix: eliminate panics, validate config, handle all errors in radio/USB tasks

Radio task:
- Remove all .unwrap() — start_rx/rx_once now take &RadioConfig directly
- Validate RadioConfig on SetConfig and Transmit (freq, SF, CR, power)
- Notify host when RX restart fails (was silently going Idle)
- Clamp payload length with warning instead of silent truncation
- Extract modulation_params() helper, eliminating 3x duplication
- Name all magic numbers (PREAMBLE_LEN, CRC_ON, etc.)
- Add comprehensive module documentation

USB task:
- Log serialization and write failures instead of silently dropping
- Break chunk loop on write error
- Add compile-time buffer size assertion

Protocol:
- Add RadioConfig::validate() with SX1262 hardware limits
- Document all field ranges
This commit is contained in:
swaits committed 2026-03-29 20:42:57 -06:00
1 parent ece7cbc8ab
commit a60c18a8bf
3 files changed
+212 -77

No files matched your search

+21
View File
@@ -23,6 +23,7 @@ pub enum Bandwidth {
/// Complete LoRa radio configuration.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
pub struct RadioConfig {
/// Frequency in Hz (150_000_000 - 960_000_000 for SX1262).
pub freq_hz: u32,
pub bw: Bandwidth,
/// Spreading factor (5-12).
@@ -30,9 +31,29 @@ pub struct RadioConfig {
/// Coding rate denominator (5-8). E.g. 5 = CR 4/5, 8 = CR 4/8.
pub cr: u8,
pub sync_word: u16,
/// Transmit power in dBm (-9 to +22 for SX1262).
pub tx_power_dbm: i8,
}
impl RadioConfig {
/// Validate all fields are within SX1262 hardware limits.
pub fn validate(&self) -> Result<(), &'static str> {
if !(150_000_000..=960_000_000).contains(&self.freq_hz) {
return Err("frequency out of range (150-960 MHz)");
}
if !(5..=12).contains(&self.sf) {
return Err("spreading factor out of range (5-12)");
}
if !(5..=8).contains(&self.cr) {
return Err("coding rate out of range (5-8)");
}
if !(-9..=22).contains(&self.tx_power_dbm) {
return Err("TX power out of range (-9 to +22 dBm)");
}
Ok(())
}
}
/// Host → firmware commands.
// Payload variant is intentionally large (inline heapless::Vec) — no allocator available.
#[allow(clippy::large_enum_variant)]