nrf/twim: switch to new interrupt binding.

This commit is contained in:
Dario Nieuwenhuis 2023-03-05 22:12:34 +01:00
parent 9f5762d365
commit 9e58d9274c
3 changed files with 39 additions and 26 deletions

View file

@ -3,6 +3,7 @@
#![macro_use] #![macro_use]
use core::future::{poll_fn, Future}; use core::future::{poll_fn, Future};
use core::marker::PhantomData;
use core::sync::atomic::compiler_fence; use core::sync::atomic::compiler_fence;
use core::sync::atomic::Ordering::SeqCst; use core::sync::atomic::Ordering::SeqCst;
use core::task::Poll; use core::task::Poll;
@ -15,7 +16,7 @@ use embassy_time::{Duration, Instant};
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
use crate::gpio::Pin as GpioPin; use crate::gpio::Pin as GpioPin;
use crate::interrupt::{Interrupt, InterruptExt}; use crate::interrupt::{self, Interrupt, InterruptExt};
use crate::util::{slice_in_ram, slice_in_ram_or}; use crate::util::{slice_in_ram, slice_in_ram_or};
use crate::{gpio, pac, Peripheral}; use crate::{gpio, pac, Peripheral};
@ -92,6 +93,27 @@ pub enum Error {
Timeout, Timeout,
} }
/// Interrupt handler.
pub struct InterruptHandler<T: Instance> {
_phantom: PhantomData<T>,
}
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() {
let r = T::regs();
let s = T::state();
if r.events_stopped.read().bits() != 0 {
s.end_waker.wake();
r.intenclr.write(|w| w.stopped().clear());
}
if r.events_error.read().bits() != 0 {
s.end_waker.wake();
r.intenclr.write(|w| w.error().clear());
}
}
}
/// TWI driver. /// TWI driver.
pub struct Twim<'d, T: Instance> { pub struct Twim<'d, T: Instance> {
_p: PeripheralRef<'d, T>, _p: PeripheralRef<'d, T>,
@ -101,12 +123,12 @@ impl<'d, T: Instance> Twim<'d, T> {
/// Create a new TWI driver. /// Create a new TWI driver.
pub fn new( pub fn new(
twim: impl Peripheral<P = T> + 'd, twim: impl Peripheral<P = T> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sda: impl Peripheral<P = impl GpioPin> + 'd, sda: impl Peripheral<P = impl GpioPin> + 'd,
scl: impl Peripheral<P = impl GpioPin> + 'd, scl: impl Peripheral<P = impl GpioPin> + 'd,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(twim, irq, sda, scl); into_ref!(twim, sda, scl);
let r = T::regs(); let r = T::regs();
@ -152,27 +174,12 @@ impl<'d, T: Instance> Twim<'d, T> {
// Disable all events interrupts // Disable all events interrupts
r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
irq.set_handler(Self::on_interrupt); unsafe { T::Interrupt::steal() }.unpend();
irq.unpend(); unsafe { T::Interrupt::steal() }.enable();
irq.enable();
Self { _p: twim } Self { _p: twim }
} }
fn on_interrupt(_: *mut ()) {
let r = T::regs();
let s = T::state();
if r.events_stopped.read().bits() != 0 {
s.end_waker.wake();
r.intenclr.write(|w| w.stopped().clear());
}
if r.events_error.read().bits() != 0 {
s.end_waker.wake();
r.intenclr.write(|w| w.error().clear());
}
}
/// Set TX buffer, checking that it is in RAM and has suitable length. /// Set TX buffer, checking that it is in RAM and has suitable length.
unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> { unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
slice_in_ram_or(buffer, Error::BufferNotInRAM)?; slice_in_ram_or(buffer, Error::BufferNotInRAM)?;

View file

@ -8,19 +8,22 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_nrf::interrupt;
use embassy_nrf::twim::{self, Twim}; use embassy_nrf::twim::{self, Twim};
use embassy_nrf::{bind_interrupts, peripherals};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
const ADDRESS: u8 = 0x50; const ADDRESS: u8 = 0x50;
bind_interrupts!(struct Irqs {
SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twim::InterruptHandler<peripherals::TWISPI0>;
});
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let p = embassy_nrf::init(Default::default()); let p = embassy_nrf::init(Default::default());
info!("Initializing TWI..."); info!("Initializing TWI...");
let config = twim::Config::default(); let config = twim::Config::default();
let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); let mut twi = Twim::new(p.TWISPI0, Irqs, p.P0_03, p.P0_04, config);
let mut twi = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config);
info!("Reading..."); info!("Reading...");

View file

@ -12,25 +12,28 @@ use core::mem;
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_nrf::interrupt;
use embassy_nrf::twim::{self, Twim}; use embassy_nrf::twim::{self, Twim};
use embassy_nrf::{bind_interrupts, peripherals};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
const ADDRESS: u8 = 0x50; const ADDRESS: u8 = 0x50;
bind_interrupts!(struct Irqs {
SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twim::InterruptHandler<peripherals::TWISPI0>;
});
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_p: Spawner) { async fn main(_p: Spawner) {
let mut p = embassy_nrf::init(Default::default()); let mut p = embassy_nrf::init(Default::default());
info!("Started!"); info!("Started!");
let mut irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
loop { loop {
info!("Initializing TWI..."); info!("Initializing TWI...");
let config = twim::Config::default(); let config = twim::Config::default();
// Create the TWIM instance with borrowed singletons, so they're not consumed. // Create the TWIM instance with borrowed singletons, so they're not consumed.
let mut twi = Twim::new(&mut p.TWISPI0, &mut irq, &mut p.P0_03, &mut p.P0_04, config); let mut twi = Twim::new(&mut p.TWISPI0, Irqs, &mut p.P0_03, &mut p.P0_04, config);
info!("Reading..."); info!("Reading...");