From 61c666212fa04571a74c27f649526459a376aa8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Fri, 24 Jun 2022 14:31:30 +0200 Subject: [PATCH 01/16] stm32wl: Do not require external SPI pins for SUBGHZ For the Seeed Studio Lora-E5 those pins conflict with the radio frontend control GPIOS (PA4 and PA5). --- embassy-stm32/src/spi/mod.rs | 12 ++++++++++++ embassy-stm32/src/subghz/mod.rs | 7 ++----- examples/stm32wl/src/bin/lorawan.rs | 2 +- examples/stm32wl/src/bin/subghz.rs | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 26fb392e..1a00f418 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -179,6 +179,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { ) } + /// Useful for on chip peripherals like SUBGHZ which are hardwired. + /// The bus can optionally be exposed externally with `Spi::new()` still. + pub fn new_internal( + peri: impl Peripheral

+ 'd, + txdma: impl Peripheral

+ 'd, + rxdma: impl Peripheral

+ 'd, + freq: Hertz, + config: Config, + ) -> Self { + Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config) + } + fn new_inner( peri: impl Peripheral

+ 'd, sck: Option>, diff --git a/embassy-stm32/src/subghz/mod.rs b/embassy-stm32/src/subghz/mod.rs index a74f9a6d..33398fa1 100644 --- a/embassy-stm32/src/subghz/mod.rs +++ b/embassy-stm32/src/subghz/mod.rs @@ -81,7 +81,7 @@ pub use value_error::ValueError; use crate::dma::NoDma; use crate::peripherals::SUBGHZSPI; use crate::rcc::sealed::RccPeripheral; -use crate::spi::{BitOrder, Config as SpiConfig, MisoPin, MosiPin, SckPin, Spi, MODE_0}; +use crate::spi::{BitOrder, Config as SpiConfig, Spi, MODE_0}; use crate::time::Hertz; use crate::{pac, Peripheral}; @@ -212,9 +212,6 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> { /// clock. pub fn new( peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - mosi: impl Peripheral

> + 'd, - miso: impl Peripheral

> + 'd, txdma: impl Peripheral

+ 'd, rxdma: impl Peripheral

+ 'd, ) -> Self { @@ -227,7 +224,7 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> { let mut config = SpiConfig::default(); config.mode = MODE_0; config.bit_order = BitOrder::MsbFirst; - let spi = Spi::new(peri, sck, mosi, miso, txdma, rxdma, clk, config); + let spi = Spi::new_internal(peri, txdma, rxdma, clk, config); unsafe { wakeup() }; diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs index 7e8a8946..fdd7eb8c 100644 --- a/examples/stm32wl/src/bin/lorawan.rs +++ b/examples/stm32wl/src/bin/lorawan.rs @@ -31,7 +31,7 @@ async fn main(_spawner: Spawner) { let ctrl3 = Output::new(p.PC5.degrade(), Level::High, Speed::High); let rfs = RadioSwitch::new(ctrl1, ctrl2, ctrl3); - let radio = SubGhz::new(p.SUBGHZSPI, p.PA5, p.PA7, p.PA6, NoDma, NoDma); + let radio = SubGhz::new(p.SUBGHZSPI, NoDma, NoDma); let irq = interrupt::take!(SUBGHZ_RADIO); static mut RADIO_STATE: SubGhzState<'static> = SubGhzState::new(); diff --git a/examples/stm32wl/src/bin/subghz.rs b/examples/stm32wl/src/bin/subghz.rs index c5e9bb59..8f674d79 100644 --- a/examples/stm32wl/src/bin/subghz.rs +++ b/examples/stm32wl/src/bin/subghz.rs @@ -72,7 +72,7 @@ async fn main(_spawner: Spawner) { unsafe { interrupt::SUBGHZ_RADIO::steal() }.disable(); }); - let mut radio = SubGhz::new(p.SUBGHZSPI, p.PA5, p.PA7, p.PA6, NoDma, NoDma); + let mut radio = SubGhz::new(p.SUBGHZSPI, NoDma, NoDma); defmt::info!("Radio ready for use"); From 8e8106ef555373f8b0f04fe1f67684efef435a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Sat, 25 Jun 2022 07:01:31 +0200 Subject: [PATCH 02/16] lora: Improve IRQ handling * Interrupt handler only triggers a waker: Do the actual interrupt processing which involves SUBGHZ SPI coms in the task. * Do not require a static state for the constructor. * Remove unsafe from construcor. --- embassy-lora/src/stm32wl/mod.rs | 126 ++++++++++++---------------- examples/stm32wl/src/bin/lorawan.rs | 5 +- 2 files changed, 54 insertions(+), 77 deletions(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 7822d015..5e1773d5 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -1,18 +1,18 @@ //! A radio driver integration for the radio found on STM32WL family devices. use core::future::Future; -use core::mem::MaybeUninit; +use core::task::Poll; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::dma::NoDma; use embassy_stm32::gpio::{AnyPin, Output}; -use embassy_stm32::interrupt::{InterruptExt, SUBGHZ_RADIO}; +use embassy_stm32::interrupt::{Interrupt, InterruptExt, SUBGHZ_RADIO}; use embassy_stm32::subghz::{ CalibrateImage, CfgIrq, CodingRate, Error, HeaderType, Irq, LoRaBandwidth, LoRaModParams, LoRaPacketParams, LoRaSyncWord, Ocp, PaConfig, PaSel, PacketType, RampTime, RegMode, RfFreq, SpreadingFactor as SF, StandbyClk, Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, }; -use embassy_stm32::Peripheral; -use embassy_sync::signal::Signal; +use embassy_sync::waitqueue::AtomicWaker; +use futures::future::poll_fn; use lorawan_device::async_device::radio::{Bandwidth, PhyRxTx, RfConfig, RxQuality, SpreadingFactor, TxConfig}; use lorawan_device::async_device::Timings; @@ -28,65 +28,43 @@ pub enum State { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RadioError; -static IRQ: Signal<(Status, u16)> = Signal::new(); - -struct StateInner<'d> { - radio: SubGhz<'d, NoDma, NoDma>, - switch: RadioSwitch<'d>, -} - -/// External state storage for the radio state -pub struct SubGhzState<'a>(MaybeUninit>); -impl<'d> SubGhzState<'d> { - pub const fn new() -> Self { - Self(MaybeUninit::uninit()) - } -} +static IRQ_WAKER: AtomicWaker = AtomicWaker::new(); /// The radio peripheral keeping the radio state and owning the radio IRQ. -pub struct SubGhzRadio<'d> { - state: *mut StateInner<'d>, - _irq: PeripheralRef<'d, SUBGHZ_RADIO>, +pub struct SubGhzRadio<'d, RS> { + radio: SubGhz<'d, NoDma, NoDma>, + switch: RS, + irq: PeripheralRef<'d, SUBGHZ_RADIO>, } -impl<'d> SubGhzRadio<'d> { +#[derive(Default)] +#[non_exhaustive] +pub struct SubGhzRadioConfig { + pub reg_mode: RegMode, + pub calibrate_image: CalibrateImage, +} + +impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { /// Create a new instance of a SubGhz radio for LoRaWAN. - /// - /// # Safety - /// Do not leak self or futures - pub unsafe fn new( - state: &'d mut SubGhzState<'d>, - radio: SubGhz<'d, NoDma, NoDma>, - switch: RadioSwitch<'d>, + pub fn new( + mut radio: SubGhz<'d, NoDma, NoDma>, + switch: RS, irq: impl Peripheral

+ 'd, - ) -> Self { + config: SubGhzRadioConfig, + ) -> Result { into_ref!(irq); - let mut inner = StateInner { radio, switch }; - inner.radio.reset(); - - let state_ptr = state.0.as_mut_ptr(); - state_ptr.write(inner); + radio.reset(); irq.disable(); - irq.set_handler(|p| { - // This is safe because we only get interrupts when configured for, so - // the radio will be awaiting on the signal at this point. If not, the ISR will - // anyway only adjust the state in the IRQ signal state. - let state = &mut *(p as *mut StateInner<'d>); - state.on_interrupt(); + irq.set_handler(|_| { + IRQ_WAKER.wake(); + unsafe { SUBGHZ_RADIO::steal().disable() }; }); - irq.set_handler_context(state_ptr as *mut ()); - irq.enable(); - Self { - state: state_ptr, - _irq: irq, - } + Self { radio, switch, irq } } -} -impl<'d> StateInner<'d> { /// Configure radio settings in preparation for TX or RX pub(crate) fn configure(&mut self) -> Result<(), RadioError> { trace!("Configuring STM32WL SUBGHZ radio"); @@ -151,8 +129,7 @@ impl<'d> StateInner<'d> { self.radio.set_tx(Timeout::DISABLED)?; loop { - let (_status, irq_status) = IRQ.wait().await; - IRQ.reset(); + let (_status, irq_status) = self.irq_wait().await; if irq_status & Irq::TxDone.mask() != 0 { let stats = self.radio.lora_stats()?; @@ -214,8 +191,8 @@ impl<'d> StateInner<'d> { trace!("RX started"); loop { - let (status, irq_status) = IRQ.wait().await; - IRQ.reset(); + let (status, irq_status) = self.irq_wait().await; + trace!("RX IRQ {:?}, {:?}", status, irq_status); if irq_status & Irq::RxDone.mask() != 0 { let (status, len, ptr) = self.radio.rx_buffer_status()?; @@ -238,17 +215,24 @@ impl<'d> StateInner<'d> { } } - /// Read interrupt status and store in global signal - fn on_interrupt(&mut self) { - let (status, irq_status) = self.radio.irq_status().expect("error getting irq status"); - self.radio - .clear_irq_status(irq_status) - .expect("error clearing irq status"); - if irq_status & Irq::PreambleDetected.mask() != 0 { - trace!("Preamble detected, ignoring"); - } else { - IRQ.signal((status, irq_status)); - } + async fn irq_wait(&mut self) -> (Status, u16) { + poll_fn(|cx| { + self.irq.unpend(); + self.irq.enable(); + IRQ_WAKER.register(cx.waker()); + + let (status, irq_status) = self.radio.irq_status().expect("error getting irq status"); + self.radio + .clear_irq_status(irq_status) + .expect("error clearing irq status"); + trace!("IRQ status: {=u16:b}", irq_status); + if irq_status == 0 { + Poll::Pending + } else { + Poll::Ready((status, irq_status)) + } + }) + .await } } @@ -257,18 +241,12 @@ impl PhyRxTx for SubGhzRadio<'static> { type TxFuture<'m> = impl Future> + 'm; fn tx<'m>(&'m mut self, config: TxConfig, buf: &'m [u8]) -> Self::TxFuture<'m> { - async move { - let inner = unsafe { &mut *self.state }; - inner.do_tx(config, buf).await - } + async move { self.do_tx(config, buf).await } } type RxFuture<'m> = impl Future> + 'm; fn rx<'m>(&'m mut self, config: RfConfig, buf: &'m mut [u8]) -> Self::RxFuture<'m> { - async move { - let inner = unsafe { &mut *self.state }; - inner.do_rx(config, buf).await - } + async move { self.do_rx(config, buf).await } } } @@ -278,7 +256,7 @@ impl From for RadioError { } } -impl<'d> Timings for SubGhzRadio<'d> { +impl<'d, RS> Timings for SubGhzRadio<'d, RS> { fn get_rx_window_offset_ms(&self) -> i32 { -200 } diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs index fdd7eb8c..9c390bdf 100644 --- a/examples/stm32wl/src/bin/lorawan.rs +++ b/examples/stm32wl/src/bin/lorawan.rs @@ -32,10 +32,9 @@ async fn main(_spawner: Spawner) { let rfs = RadioSwitch::new(ctrl1, ctrl2, ctrl3); let radio = SubGhz::new(p.SUBGHZSPI, NoDma, NoDma); - let irq = interrupt::take!(SUBGHZ_RADIO); - static mut RADIO_STATE: SubGhzState<'static> = SubGhzState::new(); - let radio = unsafe { SubGhzRadio::new(&mut RADIO_STATE, radio, rfs, irq) }; + + let radio = SubGhzRadio::new(radio, rfs, irq); let mut region: region::Configuration = region::EU868::default().into(); From 6ee29ff0bd4d8cbd2da547dfdf631332cda551d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Sat, 25 Jun 2022 10:06:00 +0200 Subject: [PATCH 03/16] lora: Propagate "defmt" feature to lora crates --- embassy-lora/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml index 9d5e7aed..25d8c667 100644 --- a/embassy-lora/Cargo.toml +++ b/embassy-lora/Cargo.toml @@ -18,6 +18,7 @@ flavors = [ sx127x = [] stm32wl = ["embassy-stm32", "embassy-stm32/subghz"] time = [] +defmt = ["dep:defmt", "lorawan/defmt", "lorawan-device/defmt"] [dependencies] From 69d80c086d2f22f66aa25fafb55918cb1c5e3bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Sat, 25 Jun 2022 10:10:59 +0200 Subject: [PATCH 04/16] lora: Use a trait for RF frontend switching The Seeed Studio Lora-E5 module only has two control pins. With the `RadioSwitch` trait the user can implement any method required by the module/board to control the TX/RX direction of the radio frontend. --- embassy-lora/src/stm32wl/mod.rs | 42 +++++------------------------ examples/stm32wl/src/bin/lorawan.rs | 28 ++++++++++++++++++- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 5e1773d5..7502dc37 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -4,7 +4,6 @@ use core::task::Poll; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::dma::NoDma; -use embassy_stm32::gpio::{AnyPin, Output}; use embassy_stm32::interrupt::{Interrupt, InterruptExt, SUBGHZ_RADIO}; use embassy_stm32::subghz::{ CalibrateImage, CfgIrq, CodingRate, Error, HeaderType, Irq, LoRaBandwidth, LoRaModParams, LoRaPacketParams, @@ -100,7 +99,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result { //trace!("TX Request: {}", config); trace!("TX START"); - self.switch.set_tx_lp(); + self.switch.set_tx(); self.configure()?; self.radio @@ -236,15 +235,15 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { } } -impl PhyRxTx for SubGhzRadio<'static> { +impl PhyRxTx for SubGhzRadio<'static, RS> { type PhyError = RadioError; - type TxFuture<'m> = impl Future> + 'm; + type TxFuture<'m> = impl Future> + 'm where RS: 'm; fn tx<'m>(&'m mut self, config: TxConfig, buf: &'m [u8]) -> Self::TxFuture<'m> { async move { self.do_tx(config, buf).await } } - type RxFuture<'m> = impl Future> + 'm; + type RxFuture<'m> = impl Future> + 'm where RS: 'm; fn rx<'m>(&'m mut self, config: RfConfig, buf: &'m mut [u8]) -> Self::RxFuture<'m> { async move { self.do_rx(config, buf).await } } @@ -265,36 +264,9 @@ impl<'d, RS> Timings for SubGhzRadio<'d, RS> { } } -/// Represents the radio switch found on STM32WL based boards, used to control the radio for transmission or reception. -pub struct RadioSwitch<'d> { - ctrl1: Output<'d, AnyPin>, - ctrl2: Output<'d, AnyPin>, - ctrl3: Output<'d, AnyPin>, -} - -impl<'d> RadioSwitch<'d> { - pub fn new(ctrl1: Output<'d, AnyPin>, ctrl2: Output<'d, AnyPin>, ctrl3: Output<'d, AnyPin>) -> Self { - Self { ctrl1, ctrl2, ctrl3 } - } - - pub(crate) fn set_rx(&mut self) { - self.ctrl1.set_high(); - self.ctrl2.set_low(); - self.ctrl3.set_high(); - } - - pub(crate) fn set_tx_lp(&mut self) { - self.ctrl1.set_high(); - self.ctrl2.set_high(); - self.ctrl3.set_high(); - } - - #[allow(dead_code)] - pub(crate) fn set_tx_hp(&mut self) { - self.ctrl2.set_high(); - self.ctrl1.set_low(); - self.ctrl3.set_high(); - } +pub trait RadioSwitch { + fn set_rx(&mut self); + fn set_tx(&mut self); } fn convert_spreading_factor(sf: SpreadingFactor) -> SF { diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs index 9c390bdf..0ef13354 100644 --- a/examples/stm32wl/src/bin/lorawan.rs +++ b/examples/stm32wl/src/bin/lorawan.rs @@ -9,7 +9,7 @@ use embassy_executor::Spawner; use embassy_lora::stm32wl::*; use embassy_lora::LoraTimer; use embassy_stm32::dma::NoDma; -use embassy_stm32::gpio::{Level, Output, Pin, Speed}; +use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed}; use embassy_stm32::rng::Rng; use embassy_stm32::subghz::*; use embassy_stm32::{interrupt, pac}; @@ -17,6 +17,32 @@ use lorawan::default_crypto::DefaultFactory as Crypto; use lorawan_device::async_device::{region, Device, JoinMode}; use {defmt_rtt as _, panic_probe as _}; +struct RadioSwitch<'a> { + ctrl1: Output<'a, AnyPin>, + ctrl2: Output<'a, AnyPin>, + ctrl3: Output<'a, AnyPin>, +} + +impl<'a> RadioSwitch<'a> { + fn new(ctrl1: Output<'a, AnyPin>, ctrl2: Output<'a, AnyPin>, ctrl3: Output<'a, AnyPin>) -> Self { + Self { ctrl1, ctrl2, ctrl3 } + } +} + +impl<'a> embassy_lora::stm32wl::RadioSwitch for RadioSwitch<'a> { + fn set_rx(&mut self) { + self.ctrl1.set_high(); + self.ctrl2.set_low(); + self.ctrl3.set_high(); + } + + fn set_tx(&mut self) { + self.ctrl1.set_low(); + self.ctrl2.set_high(); + self.ctrl3.set_high(); + } +} + #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); From f31116cafaeea7746aec19903fb1c73adaea9ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Sat, 25 Jun 2022 11:59:07 +0200 Subject: [PATCH 05/16] lora: Make some options configurable Call `config()` only once at construction not with every RX and TX operation. The Lora-E5 only supports HP mode, use that instead. The nucleo board supports both HP and LP and should continue to work. --- embassy-lora/src/stm32wl/mod.rs | 75 ++++++++++++++--------------- examples/stm32wl/src/bin/lorawan.rs | 4 +- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 7502dc37..5170b261 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -6,9 +6,9 @@ use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::dma::NoDma; use embassy_stm32::interrupt::{Interrupt, InterruptExt, SUBGHZ_RADIO}; use embassy_stm32::subghz::{ - CalibrateImage, CfgIrq, CodingRate, Error, HeaderType, Irq, LoRaBandwidth, LoRaModParams, LoRaPacketParams, - LoRaSyncWord, Ocp, PaConfig, PaSel, PacketType, RampTime, RegMode, RfFreq, SpreadingFactor as SF, StandbyClk, - Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, + CalibrateImage, CfgIrq, CodingRate, Error, HeaderType, HseTrim, Irq, LoRaBandwidth, LoRaModParams, + LoRaPacketParams, LoRaSyncWord, Ocp, PaConfig, PacketType, RampTime, RegMode, RfFreq, SpreadingFactor as SF, + StandbyClk, Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, }; use embassy_sync::waitqueue::AtomicWaker; use futures::future::poll_fn; @@ -61,46 +61,17 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { unsafe { SUBGHZ_RADIO::steal().disable() }; }); - Self { radio, switch, irq } - } + configure_radio(&mut radio, config)?; - /// Configure radio settings in preparation for TX or RX - pub(crate) fn configure(&mut self) -> Result<(), RadioError> { - trace!("Configuring STM32WL SUBGHZ radio"); - self.radio.set_standby(StandbyClk::Rc)?; - let tcxo_mode = TcxoMode::new() - .set_txco_trim(TcxoTrim::Volts1pt7) - .set_timeout(Timeout::from_duration_sat(core::time::Duration::from_millis(40))); - - self.radio.set_tcxo_mode(&tcxo_mode)?; - self.radio.set_regulator_mode(RegMode::Ldo)?; - - self.radio.calibrate_image(CalibrateImage::ISM_863_870)?; - - self.radio.set_buffer_base_address(0, 0)?; - - self.radio - .set_pa_config(&PaConfig::new().set_pa_duty_cycle(0x1).set_hp_max(0x0).set_pa(PaSel::Lp))?; - - self.radio.set_pa_ocp(Ocp::Max140m)?; - - // let tx_params = TxParams::LP_14.set_ramp_time(RampTime::Micros40); - self.radio - .set_tx_params(&TxParams::new().set_ramp_time(RampTime::Micros40).set_power(0x0A))?; - - self.radio.set_packet_type(PacketType::LoRa)?; - self.radio.set_lora_sync_word(LoRaSyncWord::Public)?; - trace!("Done initializing STM32WL SUBGHZ radio"); - Ok(()) + Ok(Self { radio, switch, irq }) } /// Perform a transmission with the given parameters and payload. Returns any time adjustements needed form /// the upcoming RX window start. async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result { - //trace!("TX Request: {}", config); - trace!("TX START"); + trace!("TX Request: {}", config); + //trace!("TX START"); self.switch.set_tx(); - self.configure()?; self.radio .set_rf_frequency(&RfFreq::from_frequency(config.rf.frequency))?; @@ -164,7 +135,6 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { trace!("RX START"); // trace!("Starting RX: {}", config); self.switch.set_rx(); - self.configure()?; self.radio.set_rf_frequency(&RfFreq::from_frequency(config.frequency))?; @@ -180,7 +150,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { let irq_cfg = CfgIrq::new() .irq_enable_all(Irq::RxDone) - .irq_enable_all(Irq::PreambleDetected) + //.irq_enable_all(Irq::PreambleDetected) .irq_enable_all(Irq::HeaderErr) .irq_enable_all(Irq::Timeout) .irq_enable_all(Irq::Err); @@ -235,6 +205,35 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { } } +fn configure_radio(radio: &mut SubGhz<'_, NoDma, NoDma>, config: SubGhzRadioConfig) -> Result<(), RadioError> { + trace!("Configuring STM32WL SUBGHZ radio"); + + radio.set_regulator_mode(config.reg_mode)?; + radio.set_standby(StandbyClk::Rc)?; + + let tcxo_mode = TcxoMode::new() + .set_txco_trim(TcxoTrim::Volts1pt7) + .set_timeout(Timeout::from_duration_sat(core::time::Duration::from_millis(100))); + radio.set_tcxo_mode(&tcxo_mode)?; + // Reduce input capacitance as shown in Reference Manual "Figure 23. HSE32 TCXO control". + // The STM32CUBE C driver also does this. + radio.set_hse_in_trim(HseTrim::MIN)?; + + // Re-calibrate everything after setting the TXCO config. + radio.calibrate(0x7F)?; + radio.calibrate_image(config.calibrate_image)?; + + radio.set_pa_config(&PaConfig::HP_14)?; + radio.set_tx_params(&TxParams::HP.set_ramp_time(RampTime::Micros40))?; + radio.set_pa_ocp(Ocp::Max140m)?; + + radio.set_packet_type(PacketType::LoRa)?; + radio.set_lora_sync_word(LoRaSyncWord::Public)?; + + trace!("Done initializing STM32WL SUBGHZ radio"); + Ok(()) +} + impl PhyRxTx for SubGhzRadio<'static, RS> { type PhyError = RadioError; diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs index 0ef13354..83df0188 100644 --- a/examples/stm32wl/src/bin/lorawan.rs +++ b/examples/stm32wl/src/bin/lorawan.rs @@ -60,7 +60,9 @@ async fn main(_spawner: Spawner) { let radio = SubGhz::new(p.SUBGHZSPI, NoDma, NoDma); let irq = interrupt::take!(SUBGHZ_RADIO); - let radio = SubGhzRadio::new(radio, rfs, irq); + let mut radio_config = SubGhzRadioConfig::default(); + radio_config.calibrate_image = CalibrateImage::ISM_863_870; + let radio = SubGhzRadio::new(radio, rfs, irq, radio_config).unwrap(); let mut region: region::Configuration = region::EU868::default().into(); From 84240d49eaf208691d0785e060ee13a7a14f0671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Sun, 26 Jun 2022 22:59:39 +0200 Subject: [PATCH 06/16] stm32wl: Fix RCC * `MSIRGSEL = 1` was required for MSI accept the updated MSI range * Reorder enable and clock switching to properly handle the jump from the default 4MHz MSI to a higher MSI freuquency --- embassy-stm32/src/rcc/wl.rs | 116 ++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 57 deletions(-) diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 69c192c6..34767491 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -202,54 +202,11 @@ impl Default for Config { pub(crate) unsafe fn init(config: Config) { let (sys_clk, sw, vos) = match config.mux { - ClockSrc::HSI16 => { - // Enable HSI16 - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - - (HSI_FREQ.0, 0x01, VoltageScale::Range2) - } - ClockSrc::HSE32 => { - // Enable HSE32 - RCC.cr().write(|w| { - w.set_hsebyppwr(true); - w.set_hseon(true); - }); - while !RCC.cr().read().hserdy() {} - - (HSE32_FREQ.0, 0x02, VoltageScale::Range1) - } - ClockSrc::MSI(range) => { - RCC.cr().write(|w| { - w.set_msirange(range.into()); - w.set_msion(true); - }); - - while !RCC.cr().read().msirdy() {} - - (range.freq(), 0x00, range.vos()) - } + ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2), + ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::Range1), + ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()), }; - RCC.cfgr().modify(|w| { - w.set_sw(sw.into()); - if config.ahb_pre == AHBPrescaler::NotDivided { - w.set_hpre(0); - } else { - w.set_hpre(config.ahb_pre.into()); - } - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); - }); - - RCC.extcfgr().modify(|w| { - if config.shd_ahb_pre == AHBPrescaler::NotDivided { - w.set_shdhpre(0); - } else { - w.set_shdhpre(config.shd_ahb_pre.into()); - } - }); - let ahb_freq: u32 = match config.ahb_pre { AHBPrescaler::NotDivided => sys_clk, pre => { @@ -288,16 +245,6 @@ pub(crate) unsafe fn init(config: Config) { } }; - let apb3_freq = shd_ahb_freq; - - if config.enable_lsi { - let csr = RCC.csr().read(); - if !csr.lsion() { - RCC.csr().modify(|w| w.set_lsion(true)); - while !RCC.csr().read().lsirdy() {} - } - } - // Adjust flash latency let flash_clk_src_freq: u32 = shd_ahb_freq; let ws = match vos { @@ -319,6 +266,61 @@ pub(crate) unsafe fn init(config: Config) { while FLASH.acr().read().latency() != ws {} + match config.mux { + ClockSrc::HSI16 => { + // Enable HSI16 + RCC.cr().write(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + } + ClockSrc::HSE32 => { + // Enable HSE32 + RCC.cr().write(|w| { + w.set_hsebyppwr(true); + w.set_hseon(true); + }); + while !RCC.cr().read().hserdy() {} + } + ClockSrc::MSI(range) => { + let cr = RCC.cr().read(); + assert!(!cr.msion() || cr.msirdy()); + RCC.cr().write(|w| { + w.set_msirgsel(true); + w.set_msirange(range.into()); + w.set_msion(true); + }); + while !RCC.cr().read().msirdy() {} + } + } + + RCC.extcfgr().modify(|w| { + if config.shd_ahb_pre == AHBPrescaler::NotDivided { + w.set_shdhpre(0); + } else { + w.set_shdhpre(config.shd_ahb_pre.into()); + } + }); + + RCC.cfgr().modify(|w| { + w.set_sw(sw.into()); + if config.ahb_pre == AHBPrescaler::NotDivided { + w.set_hpre(0); + } else { + w.set_hpre(config.ahb_pre.into()); + } + w.set_ppre1(config.apb1_pre.into()); + w.set_ppre2(config.apb2_pre.into()); + }); + + // TODO: switch voltage range + + if config.enable_lsi { + let csr = RCC.csr().read(); + if !csr.lsion() { + RCC.csr().modify(|w| w.set_lsion(true)); + while !RCC.csr().read().lsirdy() {} + } + } + set_freqs(Clocks { sys: Hertz(sys_clk), ahb1: Hertz(ahb_freq), @@ -326,7 +328,7 @@ pub(crate) unsafe fn init(config: Config) { ahb3: Hertz(shd_ahb_freq), apb1: Hertz(apb1_freq), apb2: Hertz(apb2_freq), - apb3: Hertz(apb3_freq), + apb3: Hertz(shd_ahb_freq), apb1_tim: Hertz(apb1_tim_freq), apb2_tim: Hertz(apb2_tim_freq), }); From 60ca5e8479e951b220299ea32bfc48b1909edd1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Mon, 27 Jun 2022 20:52:37 +0200 Subject: [PATCH 07/16] lora: Improve TX/RX parameters Match the settings used in the C driver --- embassy-lora/src/stm32wl/mod.rs | 82 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 5170b261..c142353b 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -69,8 +69,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { /// Perform a transmission with the given parameters and payload. Returns any time adjustements needed form /// the upcoming RX window start. async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result { - trace!("TX Request: {}", config); - //trace!("TX START"); + trace!("TX request: {}", config); self.switch.set_tx(); self.radio @@ -87,33 +86,26 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { self.radio.set_lora_packet_params(&packet_params)?; - let irq_cfg = CfgIrq::new() - .irq_enable_all(Irq::TxDone) - .irq_enable_all(Irq::RxDone) - .irq_enable_all(Irq::Timeout); + let irq_cfg = CfgIrq::new().irq_enable_all(Irq::TxDone).irq_enable_all(Irq::Timeout); self.radio.set_irq_cfg(&irq_cfg)?; self.radio.set_buffer_base_address(0, 0)?; self.radio.write_buffer(0, buf)?; - self.radio.set_tx(Timeout::DISABLED)?; + // The maximum airtime for any LoRaWAN package is 2793.5ms. + // The value of 4000ms is copied from C driver and gives us a good safety margin. + self.radio.set_tx(Timeout::from_millis_sat(4000))?; + trace!("TX started"); loop { let (_status, irq_status) = self.irq_wait().await; if irq_status & Irq::TxDone.mask() != 0 { - let stats = self.radio.lora_stats()?; - let (status, error_mask) = self.radio.op_error()?; - trace!( - "TX done. Stats: {:?}. OP error: {:?}, mask {:?}", - stats, - status, - error_mask - ); - + trace!("TX done"); return Ok(0); - } else if irq_status & Irq::Timeout.mask() != 0 { - trace!("TX timeout"); + } + + if irq_status & Irq::Timeout.mask() != 0 { return Err(RadioError); } } @@ -121,10 +113,15 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { fn set_lora_mod_params(&mut self, config: RfConfig) -> Result<(), Error> { let mod_params = LoRaModParams::new() - .set_sf(convert_spreading_factor(config.spreading_factor)) - .set_bw(convert_bandwidth(config.bandwidth)) + .set_sf(convert_spreading_factor(&config.spreading_factor)) + .set_bw(convert_bandwidth(&config.bandwidth)) .set_cr(CodingRate::Cr45) - .set_ldro_en(true); + .set_ldro_en(matches!( + (config.spreading_factor, config.bandwidth), + (SpreadingFactor::_12, Bandwidth::_125KHz) + | (SpreadingFactor::_12, Bandwidth::_250KHz) + | (SpreadingFactor::_11, Bandwidth::_125KHz) + )); self.radio.set_lora_mod_params(&mod_params) } @@ -132,8 +129,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { /// be able to hold a single LoRaWAN packet. async fn do_rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), RadioError> { assert!(buf.len() >= 255); - trace!("RX START"); - // trace!("Starting RX: {}", config); + trace!("RX request: {}", config); self.switch.set_rx(); self.radio.set_rf_frequency(&RfFreq::from_frequency(config.frequency))?; @@ -144,41 +140,41 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { .set_preamble_len(8) .set_header_type(HeaderType::Variable) .set_payload_len(0xFF) - .set_crc_en(true) + .set_crc_en(false) .set_invert_iq(true); self.radio.set_lora_packet_params(&packet_params)?; let irq_cfg = CfgIrq::new() .irq_enable_all(Irq::RxDone) - //.irq_enable_all(Irq::PreambleDetected) + .irq_enable_all(Irq::PreambleDetected) + .irq_enable_all(Irq::HeaderValid) .irq_enable_all(Irq::HeaderErr) - .irq_enable_all(Irq::Timeout) - .irq_enable_all(Irq::Err); + .irq_enable_all(Irq::Err) + .irq_enable_all(Irq::Timeout); self.radio.set_irq_cfg(&irq_cfg)?; - self.radio.set_rx(Timeout::DISABLED)?; + self.radio.set_buffer_base_address(0, 0)?; + + self.radio + .set_rx(Timeout::from_millis_sat(self.get_rx_window_duration_ms()))?; trace!("RX started"); loop { - let (status, irq_status) = self.irq_wait().await; + let (_status, irq_status) = self.irq_wait().await; - trace!("RX IRQ {:?}, {:?}", status, irq_status); if irq_status & Irq::RxDone.mask() != 0 { - let (status, len, ptr) = self.radio.rx_buffer_status()?; - + let (_status, len, ptr) = self.radio.rx_buffer_status()?; let packet_status = self.radio.lora_packet_status()?; let rssi = packet_status.rssi_pkt().to_integer(); let snr = packet_status.snr_pkt().to_integer(); - trace!( - "RX done. Received {} bytes. RX status: {:?}. Pkt status: {:?}", - len, - status.cmd(), - packet_status, - ); self.radio.read_buffer(ptr, &mut buf[..len as usize])?; self.radio.set_standby(StandbyClk::Rc)?; + + trace!("RX done: {=[u8]:#02X}", &mut buf[..len as usize]); return Ok((len as usize, RxQuality::new(rssi, snr as i8))); - } else if irq_status & (Irq::Timeout.mask() | Irq::TxDone.mask()) != 0 { + } + + if irq_status & Irq::Timeout.mask() != 0 { return Err(RadioError); } } @@ -194,7 +190,9 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { self.radio .clear_irq_status(irq_status) .expect("error clearing irq status"); - trace!("IRQ status: {=u16:b}", irq_status); + + trace!("SUGHZ IRQ 0b{=u16:b}, {:?}", irq_status, status); + if irq_status == 0 { Poll::Pending } else { @@ -268,7 +266,7 @@ pub trait RadioSwitch { fn set_tx(&mut self); } -fn convert_spreading_factor(sf: SpreadingFactor) -> SF { +fn convert_spreading_factor(sf: &SpreadingFactor) -> SF { match sf { SpreadingFactor::_7 => SF::Sf7, SpreadingFactor::_8 => SF::Sf8, @@ -279,7 +277,7 @@ fn convert_spreading_factor(sf: SpreadingFactor) -> SF { } } -fn convert_bandwidth(bw: Bandwidth) -> LoRaBandwidth { +fn convert_bandwidth(bw: &Bandwidth) -> LoRaBandwidth { match bw { Bandwidth::_125KHz => LoRaBandwidth::Bw125, Bandwidth::_250KHz => LoRaBandwidth::Bw250, From 308ca4b8e3c4a4ef6c1711528dd7561b75c61aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Mon, 8 Aug 2022 19:25:50 +0200 Subject: [PATCH 08/16] Use `pub(crate)` visibility for internal SPI SubGhz provides a public interface for the radio connected to internal SPI `#[allow(dead_code)]` is required for CI to succeed --- embassy-stm32/src/spi/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 1a00f418..77609bd0 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -181,7 +181,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { /// Useful for on chip peripherals like SUBGHZ which are hardwired. /// The bus can optionally be exposed externally with `Spi::new()` still. - pub fn new_internal( + #[allow(dead_code)] + pub(crate) fn new_internal( peri: impl Peripheral

+ 'd, txdma: impl Peripheral

+ 'd, rxdma: impl Peripheral

+ 'd, From af845b7d44228665dffc4432ba509fd80e8400b2 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 9 Aug 2022 12:17:30 +0200 Subject: [PATCH 09/16] Add impl for offset radio interface --- embassy-lora/src/lib.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/embassy-lora/src/lib.rs b/embassy-lora/src/lib.rs index 1b2dd45c..2483dcb2 100644 --- a/embassy-lora/src/lib.rs +++ b/embassy-lora/src/lib.rs @@ -11,13 +11,35 @@ pub mod stm32wl; #[cfg(feature = "sx127x")] pub mod sx127x; +#[cfg(feature = "time")] +use embassy_time::{Duration, Instant, Timer}; + /// A convenience timer to use with the LoRaWAN crate -pub struct LoraTimer; +#[cfg(feature = "time")] +pub struct LoraTimer { + start: Instant, +} + +#[cfg(feature = "time")] +impl LoraTimer { + pub fn new() -> Self { + Self { start: Instant::now() } + } +} #[cfg(feature = "time")] impl lorawan_device::async_device::radio::Timer for LoraTimer { + fn reset(&mut self) { + self.start = Instant::now(); + } + + type AtFuture<'m> = impl core::future::Future + 'm; + fn at<'m>(&'m mut self, millis: u64) -> Self::AtFuture<'m> { + Timer::at(self.start + Duration::from_millis(millis)) + } + type DelayFuture<'m> = impl core::future::Future + 'm; fn delay_ms<'m>(&'m mut self, millis: u64) -> Self::DelayFuture<'m> { - embassy_time::Timer::after(embassy_time::Duration::from_millis(millis)) + Timer::after(Duration::from_millis(millis)) } } From 1f36da5ca6d8bf70bba5d237b1c699ae8eae48e4 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 9 Aug 2022 12:18:07 +0200 Subject: [PATCH 10/16] Make settings configurable --- embassy-lora/src/stm32wl/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index c142353b..b428e81b 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -41,6 +41,8 @@ pub struct SubGhzRadio<'d, RS> { pub struct SubGhzRadioConfig { pub reg_mode: RegMode, pub calibrate_image: CalibrateImage, + pub pa_config: PaConfig, + pub tx_params: TxParams, } impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { @@ -155,8 +157,10 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { self.radio.set_buffer_base_address(0, 0)?; + // NOTE: Upper layer handles timeout by cancelling the future self.radio - .set_rx(Timeout::from_millis_sat(self.get_rx_window_duration_ms()))?; + .set_rx(Timeout::DISABLED)?; + trace!("RX started"); loop { @@ -221,8 +225,8 @@ fn configure_radio(radio: &mut SubGhz<'_, NoDma, NoDma>, config: SubGhzRadioConf radio.calibrate(0x7F)?; radio.calibrate_image(config.calibrate_image)?; - radio.set_pa_config(&PaConfig::HP_14)?; - radio.set_tx_params(&TxParams::HP.set_ramp_time(RampTime::Micros40))?; + radio.set_pa_config(&config.pa_config)?; + radio.set_tx_params(&config.tx_params)?; radio.set_pa_ocp(Ocp::Max140m)?; radio.set_packet_type(PacketType::LoRa)?; From 5d114479ff1b123441725ff202744f80387dc731 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 9 Aug 2022 12:18:20 +0200 Subject: [PATCH 11/16] Adjust timings after offset calculation fix --- embassy-lora/src/stm32wl/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index b428e81b..6013c2d9 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -258,10 +258,10 @@ impl From for RadioError { impl<'d, RS> Timings for SubGhzRadio<'d, RS> { fn get_rx_window_offset_ms(&self) -> i32 { - -200 + -500 } fn get_rx_window_duration_ms(&self) -> u32 { - 800 + 3000 } } From 6dab322c5819f89b41977bf4bad66bb8445af5f9 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 9 Aug 2022 12:18:39 +0200 Subject: [PATCH 12/16] Use LP as default --- examples/stm32wl/src/bin/lorawan.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs index 83df0188..9143e64d 100644 --- a/examples/stm32wl/src/bin/lorawan.rs +++ b/examples/stm32wl/src/bin/lorawan.rs @@ -37,7 +37,7 @@ impl<'a> embassy_lora::stm32wl::RadioSwitch for RadioSwitch<'a> { } fn set_tx(&mut self) { - self.ctrl1.set_low(); + self.ctrl1.set_high(); self.ctrl2.set_high(); self.ctrl3.set_high(); } @@ -69,7 +69,7 @@ async fn main(_spawner: Spawner) { // NOTE: This is specific for TTN, as they have a special RX1 delay region.set_receive_delay1(5000); - let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer, Rng::new(p.RNG)); + let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG)); // Depending on network, this might be part of JOIN device.set_datarate(region::DR::_0); // SF12 From 2636a8dc2e82afde0fb4e8952bb7f7014e11e5de Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 26 Aug 2022 12:44:33 +0200 Subject: [PATCH 13/16] Use released rust-lorawan with radio fixes --- embassy-lora/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml index 25d8c667..a80557a8 100644 --- a/embassy-lora/Cargo.toml +++ b/embassy-lora/Cargo.toml @@ -35,5 +35,5 @@ futures = { version = "0.3.17", default-features = false, features = [ "async-aw embedded-hal = { version = "0.2", features = ["unproven"] } bit_field = { version = "0.10" } -lorawan-device = { version = "0.7.1", default-features = false, features = ["async"] } +lorawan-device = { version = "0.8.0", default-features = false, features = ["async"] } lorawan = { version = "0.7.1", default-features = false } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 11751a21..6358fe86 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -14,7 +14,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true} -lorawan-device = { version = "0.7.1", default-features = false, features = ["async"], optional = true } +lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true } lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true } defmt = "0.3" diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 5f6679f4..e2e7d407 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -10,7 +10,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "subghz", "unstable-pac", "exti"] } embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] } -lorawan-device = { version = "0.7.1", default-features = false, features = ["async"] } +lorawan-device = { version = "0.8.0", default-features = false, features = ["async"] } lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"] } defmt = "0.3" From c30b38586a7663ad4c4654739364e36139c7217e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Fri, 26 Aug 2022 15:34:54 +0200 Subject: [PATCH 14/16] lora: Fix unused import warning --- embassy-lora/src/stm32wl/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 6013c2d9..9307cdeb 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -7,7 +7,7 @@ use embassy_stm32::dma::NoDma; use embassy_stm32::interrupt::{Interrupt, InterruptExt, SUBGHZ_RADIO}; use embassy_stm32::subghz::{ CalibrateImage, CfgIrq, CodingRate, Error, HeaderType, HseTrim, Irq, LoRaBandwidth, LoRaModParams, - LoRaPacketParams, LoRaSyncWord, Ocp, PaConfig, PacketType, RampTime, RegMode, RfFreq, SpreadingFactor as SF, + LoRaPacketParams, LoRaSyncWord, Ocp, PaConfig, PacketType, RegMode, RfFreq, SpreadingFactor as SF, StandbyClk, Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, }; use embassy_sync::waitqueue::AtomicWaker; From 47069dfbe18df268966bc3526f515dc944d43021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Fri, 26 Aug 2022 15:37:20 +0200 Subject: [PATCH 15/16] lora: Fix for stm32l0 exampe to build --- examples/stm32l0/src/bin/lorawan.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/stm32l0/src/bin/lorawan.rs b/examples/stm32l0/src/bin/lorawan.rs index 303558b9..00ff67f3 100644 --- a/examples/stm32l0/src/bin/lorawan.rs +++ b/examples/stm32l0/src/bin/lorawan.rs @@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) { let radio = Sx127xRadio::new(spi, cs, reset, ready_pin, DummySwitch).await.unwrap(); let region = region::EU868::default().into(); - let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer, Rng::new(p.RNG)); + let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG)); defmt::info!("Joining LoRaWAN network"); From 6cdff72d6d2becb3f8a4659571fd5e6a339cbefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Sat, 3 Sep 2022 20:36:18 +0200 Subject: [PATCH 16/16] run `cargo fmt` --- embassy-lora/src/stm32wl/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 9307cdeb..4d11244b 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -7,8 +7,8 @@ use embassy_stm32::dma::NoDma; use embassy_stm32::interrupt::{Interrupt, InterruptExt, SUBGHZ_RADIO}; use embassy_stm32::subghz::{ CalibrateImage, CfgIrq, CodingRate, Error, HeaderType, HseTrim, Irq, LoRaBandwidth, LoRaModParams, - LoRaPacketParams, LoRaSyncWord, Ocp, PaConfig, PacketType, RegMode, RfFreq, SpreadingFactor as SF, - StandbyClk, Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, + LoRaPacketParams, LoRaSyncWord, Ocp, PaConfig, PacketType, RegMode, RfFreq, SpreadingFactor as SF, StandbyClk, + Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, }; use embassy_sync::waitqueue::AtomicWaker; use futures::future::poll_fn; @@ -158,8 +158,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { self.radio.set_buffer_base_address(0, 0)?; // NOTE: Upper layer handles timeout by cancelling the future - self.radio - .set_rx(Timeout::DISABLED)?; + self.radio.set_rx(Timeout::DISABLED)?; trace!("RX started");