feat(nrf/spim): erase Instance type from Spim

This commit is contained in:
Abraham Hamidi 2025-09-19 16:13:34 -05:00
parent 56019ba197
commit 987009df7b
6 changed files with 41 additions and 32 deletions

View File

@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- next-header -->
## Unreleased - ReleaseDate
- changed: erase Instance type from Spim
- changed: nrf54l: Disable glitch detection and enable DC/DC in init.
- changed: Add embassy-net-driver-channel implementation for IEEE 802.15.4
- changed: add persist() method for gpio and ppi

View File

@ -99,13 +99,16 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
}
/// SPIM driver.
pub struct Spim<'d, T: Instance> {
_p: Peri<'d, T>,
pub struct Spim<'d> {
r: pac::spim::Spim,
irq: interrupt::Interrupt,
state: &'static State,
_p: PhantomData<&'d ()>,
}
impl<'d, T: Instance> Spim<'d, T> {
impl<'d> Spim<'d> {
/// Create a new SPIM driver.
pub fn new(
pub fn new<T: Instance>(
spim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: Peri<'d, impl GpioPin>,
@ -117,7 +120,7 @@ impl<'d, T: Instance> Spim<'d, T> {
}
/// Create a new SPIM driver, capable of TX only (MOSI only).
pub fn new_txonly(
pub fn new_txonly<T: Instance>(
spim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: Peri<'d, impl GpioPin>,
@ -128,7 +131,7 @@ impl<'d, T: Instance> Spim<'d, T> {
}
/// Create a new SPIM driver, capable of RX only (MISO only).
pub fn new_rxonly(
pub fn new_rxonly<T: Instance>(
spim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: Peri<'d, impl GpioPin>,
@ -139,7 +142,7 @@ impl<'d, T: Instance> Spim<'d, T> {
}
/// Create a new SPIM driver, capable of TX only (MOSI only), without SCK pin.
pub fn new_txonly_nosck(
pub fn new_txonly_nosck<T: Instance>(
spim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
mosi: Peri<'d, impl GpioPin>,
@ -148,8 +151,8 @@ impl<'d, T: Instance> Spim<'d, T> {
Self::new_inner(spim, None, None, Some(mosi.into()), config)
}
fn new_inner(
spim: Peri<'d, T>,
fn new_inner<T: Instance>(
_spim: Peri<'d, T>,
sck: Option<Peri<'d, AnyPin>>,
miso: Option<Peri<'d, AnyPin>>,
mosi: Option<Peri<'d, AnyPin>>,
@ -201,7 +204,12 @@ impl<'d, T: Instance> Spim<'d, T> {
// Enable SPIM instance.
r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
let mut spim = Self { _p: spim };
let mut spim = Self {
r: T::regs(),
irq: T::Interrupt::IRQ,
state: T::state(),
_p: PhantomData {},
};
// Apply runtime peripheral configuration
Self::set_config(&mut spim, &config).unwrap();
@ -218,7 +226,7 @@ impl<'d, T: Instance> Spim<'d, T> {
fn prepare_dma_transfer(&mut self, rx: *mut [u8], tx: *const [u8], offset: usize, length: usize) {
compiler_fence(Ordering::SeqCst);
let r = T::regs();
let r = self.r;
fn xfer_params(ptr: u32, total: usize, offset: usize, length: usize) -> (u32, usize) {
if total > offset {
@ -246,7 +254,7 @@ impl<'d, T: Instance> Spim<'d, T> {
#[cfg(feature = "_nrf52832_anomaly_109")]
if offset == 0 {
let s = T::state();
let s = self.state;
r.events_started().write_value(0);
@ -279,7 +287,7 @@ impl<'d, T: Instance> Spim<'d, T> {
}
// Wait for 'end' event.
while T::regs().events_end().read() == 0 {}
while self.r.events_end().read() == 0 {}
compiler_fence(Ordering::SeqCst);
}
@ -315,7 +323,7 @@ impl<'d, T: Instance> Spim<'d, T> {
#[cfg(feature = "_nrf52832_anomaly_109")]
if offset == 0 {
poll_fn(|cx| {
let s = T::state();
let s = self.state;
s.waker.register(cx.waker());
@ -326,8 +334,8 @@ impl<'d, T: Instance> Spim<'d, T> {
// Wait for 'end' event.
poll_fn(|cx| {
T::state().waker.register(cx.waker());
if T::regs().events_end().read() != 0 {
self.state.waker.register(cx.waker());
if self.r.events_end().read() != 0 {
return Poll::Ready(());
}
@ -430,9 +438,9 @@ impl<'d, T: Instance> Spim<'d, T> {
#[cfg(feature = "_nrf52832_anomaly_109")]
fn nrf52832_dma_workaround_status(&mut self) -> Poll<()> {
let r = T::regs();
let r = self.r;
if r.events_started().read() != 0 {
let s = T::state();
let s = self.state;
// Handle the first "fake" transmission
r.events_started().write_value(0);
@ -451,14 +459,14 @@ impl<'d, T: Instance> Spim<'d, T> {
}
}
impl<'d, T: Instance> Drop for Spim<'d, T> {
impl<'d> Drop for Spim<'d> {
fn drop(&mut self) {
trace!("spim drop");
// TODO check for abort, wait for xxxstopped
// disable!
let r = T::regs();
let r = self.r;
r.enable().write(|w| w.set_enable(vals::Enable::DISABLED));
gpio::deconfigure_pin(r.psel().sck().read());
@ -466,7 +474,7 @@ impl<'d, T: Instance> Drop for Spim<'d, T> {
gpio::deconfigure_pin(r.psel().mosi().read());
// Disable all events interrupts
T::Interrupt::disable();
cortex_m::peripheral::NVIC::mask(self.irq);
trace!("spim drop: done");
}
@ -526,7 +534,7 @@ macro_rules! impl_spim {
mod eh02 {
use super::*;
impl<'d, T: Instance> embedded_hal_02::blocking::spi::Transfer<u8> for Spim<'d, T> {
impl<'d> embedded_hal_02::blocking::spi::Transfer<u8> for Spim<'d> {
type Error = Error;
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
self.blocking_transfer_in_place(words)?;
@ -534,7 +542,7 @@ mod eh02 {
}
}
impl<'d, T: Instance> embedded_hal_02::blocking::spi::Write<u8> for Spim<'d, T> {
impl<'d> embedded_hal_02::blocking::spi::Write<u8> for Spim<'d> {
type Error = Error;
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
@ -551,11 +559,11 @@ impl embedded_hal_1::spi::Error for Error {
}
}
impl<'d, T: Instance> embedded_hal_1::spi::ErrorType for Spim<'d, T> {
impl<'d> embedded_hal_1::spi::ErrorType for Spim<'d> {
type Error = Error;
}
impl<'d, T: Instance> embedded_hal_1::spi::SpiBus<u8> for Spim<'d, T> {
impl<'d> embedded_hal_1::spi::SpiBus<u8> for Spim<'d> {
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
@ -577,7 +585,7 @@ impl<'d, T: Instance> embedded_hal_1::spi::SpiBus<u8> for Spim<'d, T> {
}
}
impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spim<'d, T> {
impl<'d> embedded_hal_async::spi::SpiBus<u8> for Spim<'d> {
async fn flush(&mut self) -> Result<(), Error> {
Ok(())
}
@ -599,11 +607,11 @@ impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spim<'d, T> {
}
}
impl<'d, T: Instance> SetConfig for Spim<'d, T> {
impl<'d> SetConfig for Spim<'d> {
type Config = Config;
type ConfigError = ();
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
let r = T::regs();
let r = self.r;
// Configure mode.
let mode = config.mode;
r.config().write(|w| {

View File

@ -25,7 +25,7 @@ bind_interrupts!(struct Irqs {
async fn net_task(
mut runner: embassy_net::Runner<
'static,
Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>,
Enc28j60<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Output<'static>>,
>,
) -> ! {
runner.run().await

View File

@ -27,7 +27,7 @@ bind_interrupts!(struct Irqs {
async fn wifi_task(
runner: hosted::Runner<
'static,
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>,
ExclusiveDevice<Spim<'static>, Output<'static>, Delay>,
Input<'static>,
Output<'static>,
>,

View File

@ -22,7 +22,7 @@ bind_interrupts!(struct Irqs {
RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>;
});
type MyDriver = Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>;
type MyDriver = Enc28j60<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Output<'static>>;
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, MyDriver>) -> ! {

View File

@ -29,7 +29,7 @@ const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud";
async fn wifi_task(
runner: hosted::Runner<
'static,
ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>,
ExclusiveDevice<Spim<'static>, Output<'static>, Delay>,
Input<'static>,
Output<'static>,
>,