add a translation layer for sub-GHz SPI comms, enabling the radio works now

This commit is contained in:
2026-02-25 14:56:42 +01:00
parent 2adface93b
commit 3efbbf8095
4 changed files with 72 additions and 13 deletions

View File

@@ -5,4 +5,4 @@ runner = "probe-rs run --chip STM32WLE5JC"
target = "thumbv7em-none-eabi" target = "thumbv7em-none-eabi"
[env] [env]
DEFMT_LOG = "debug" DEFMT_LOG = "trace"

1
Cargo.lock generated
View File

@@ -773,6 +773,7 @@ dependencies = [
"embassy-sync", "embassy-sync",
"embassy-time", "embassy-time",
"embedded-hal 1.0.0", "embedded-hal 1.0.0",
"embedded-hal-async",
"embedded-storage", "embedded-storage",
"heapless 0.9.2", "heapless 0.9.2",
"panic-probe", "panic-probe",

View File

@@ -16,6 +16,7 @@ defmt-rtt = "1.1.0"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0" cortex-m-rt = "0.7.0"
embedded-hal = "1.0.0" embedded-hal = "1.0.0"
embedded-hal-async = "1.0.0"
embedded-storage = "0.3.1" embedded-storage = "0.3.1"
panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-probe = { version = "1.0.0", features = ["print-defmt"] }
heapless = { version = "0.9", default-features = false } heapless = { version = "0.9", default-features = false }

View File

@@ -1,12 +1,71 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use defmt::*; use defmt::{debug, trace};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::{Config, gpio::{Level, Output, Speed}, rcc::{MSIRange, Sysclk, mux}}; use embassy_stm32::{Config, pac, rcc::{MSIRange, Sysclk, mux}, spi::Spi};
use embassy_time::Timer; use embassy_time::{Duration, Timer};
use embedded_hal_async::spi::{ErrorType, Operation, SpiBus, SpiDevice};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
/// Wrapper for the sub-GHz SPI device
struct SubGhzSpiDevice<T>(T);
impl<T: SpiBus> ErrorType for SubGhzSpiDevice<T> {
type Error = T::Error;
}
/// This works as a translation layer between normal SPI transactions and sub-GHz device SPI
/// transactions. Everything above this layer sees it like a normal SPI device!
impl<T: SpiBus> SpiDevice for SubGhzSpiDevice<T> {
/// Perform a transaction on the sub-GHz device
async fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> {
// Pull NSS low to allow SPI comms
pac::PWR.subghzspicr().modify(|w| w.set_nss(false));
trace!("NSS low");
for operation in operations {
match operation {
Operation::Read(buf) => {
self.0.read(buf).await?;
trace!("Read {:x}", buf);
},
Operation::Write(buf) => {
self.0.write(buf).await?;
trace!("Wrote {:x}", buf);
},
Operation::Transfer(read, write) => {
self.0.transfer(read, write).await?;
trace!("Read {:x} wrote {:x}", read, write);
},
Operation::TransferInPlace(buf) => {
self.0.transfer_in_place(buf).await?;
trace!("Read+wrote {:x}", buf);
},
Operation::DelayNs(_) => {}
}
}
// Pull NSS high
pac::PWR.subghzspicr().modify(|w| w.set_nss(true));
trace!("NSS high");
// Poll BUSY flag until it's done
while pac::PWR.sr2().read().rfbusys() {}
trace!("BUSY flag clear");
Ok(())
}
}
async fn reset_radio() {
debug!("Resetting the radio");
pac::RCC.csr().modify(|w| w.set_rfrst(true));
trace!("RFRST high");
Timer::after_millis(1).await;
pac::RCC.csr().modify(|w| w.set_rfrst(false));
trace!("RFRST low");
Timer::after_millis(1).await;
while pac::PWR.sr2().read().rfbusys() {}
debug!("Radio reset finished");
}
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
@@ -17,17 +76,15 @@ async fn main(_spawner: Spawner) {
config.enable_debug_during_sleep = true; config.enable_debug_during_sleep = true;
} }
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
info!("hiiiiiiii :3");
let mut led = Output::new(p.PB5, Level::High, Speed::Low); reset_radio().await;
let mut spi = SubGhzSpiDevice(Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2));
debug!("Writing SetStandby");
let _ = spi.write(&[0x80, 0x00]).await;
debug!("Radio in standby!");
loop { loop {
info!("high"); Timer::after(Duration::from_secs(1)).await;
led.set_high();
Timer::after_millis(50).await;
info!("low");
led.set_low();
Timer::after_millis(50).await;
} }
} }