nrf/saadc: switch to new interrupt binding.

This commit is contained in:
Dario Nieuwenhuis 2023-03-05 21:56:22 +01:00
parent d113fcfe32
commit 2dc5608203
3 changed files with 46 additions and 32 deletions

View File

@ -6,6 +6,7 @@ use core::future::poll_fn;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll; use core::task::Poll;
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
use embassy_hal_common::drop::OnDrop; use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
@ -17,7 +18,6 @@ use saadc::oversample::OVERSAMPLE_A;
use saadc::resolution::VAL_A; use saadc::resolution::VAL_A;
use self::sealed::Input as _; use self::sealed::Input as _;
use crate::interrupt::InterruptExt;
use crate::ppi::{ConfigurableChannel, Event, Ppi, Task}; use crate::ppi::{ConfigurableChannel, Event, Ppi, Task};
use crate::timer::{Frequency, Instance as TimerInstance, Timer}; use crate::timer::{Frequency, Instance as TimerInstance, Timer};
use crate::{interrupt, pac, peripherals, Peripheral}; use crate::{interrupt, pac, peripherals, Peripheral};
@ -28,9 +28,30 @@ use crate::{interrupt, pac, peripherals, Peripheral};
#[non_exhaustive] #[non_exhaustive]
pub enum Error {} pub enum Error {}
/// One-shot and continuous SAADC. /// Interrupt handler.
pub struct Saadc<'d, const N: usize> { pub struct InterruptHandler {
_p: PeripheralRef<'d, peripherals::SAADC>, _private: (),
}
impl interrupt::Handler<interrupt::SAADC> for InterruptHandler {
unsafe fn on_interrupt() {
let r = unsafe { &*SAADC::ptr() };
if r.events_calibratedone.read().bits() != 0 {
r.intenclr.write(|w| w.calibratedone().clear());
WAKER.wake();
}
if r.events_end.read().bits() != 0 {
r.intenclr.write(|w| w.end().clear());
WAKER.wake();
}
if r.events_started.read().bits() != 0 {
r.intenclr.write(|w| w.started().clear());
WAKER.wake();
}
}
} }
static WAKER: AtomicWaker = AtomicWaker::new(); static WAKER: AtomicWaker = AtomicWaker::new();
@ -114,15 +135,20 @@ pub enum CallbackResult {
Stop, Stop,
} }
/// One-shot and continuous SAADC.
pub struct Saadc<'d, const N: usize> {
_p: PeripheralRef<'d, peripherals::SAADC>,
}
impl<'d, const N: usize> Saadc<'d, N> { impl<'d, const N: usize> Saadc<'d, N> {
/// Create a new SAADC driver. /// Create a new SAADC driver.
pub fn new( pub fn new(
saadc: impl Peripheral<P = peripherals::SAADC> + 'd, saadc: impl Peripheral<P = peripherals::SAADC> + 'd,
irq: impl Peripheral<P = interrupt::SAADC> + 'd, _irq: impl interrupt::Binding<interrupt::SAADC, InterruptHandler> + 'd,
config: Config, config: Config,
channel_configs: [ChannelConfig; N], channel_configs: [ChannelConfig; N],
) -> Self { ) -> Self {
into_ref!(saadc, irq); into_ref!(saadc);
let r = unsafe { &*SAADC::ptr() }; let r = unsafe { &*SAADC::ptr() };
@ -163,32 +189,12 @@ impl<'d, const N: usize> Saadc<'d, N> {
// Disable all events interrupts // Disable all events interrupts
r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) });
irq.set_handler(Self::on_interrupt); unsafe { interrupt::SAADC::steal() }.unpend();
irq.unpend(); unsafe { interrupt::SAADC::steal() }.enable();
irq.enable();
Self { _p: saadc } Self { _p: saadc }
} }
fn on_interrupt(_ctx: *mut ()) {
let r = Self::regs();
if r.events_calibratedone.read().bits() != 0 {
r.intenclr.write(|w| w.calibratedone().clear());
WAKER.wake();
}
if r.events_end.read().bits() != 0 {
r.intenclr.write(|w| w.end().clear());
WAKER.wake();
}
if r.events_started.read().bits() != 0 {
r.intenclr.write(|w| w.started().clear());
WAKER.wake();
}
}
fn regs() -> &'static saadc::RegisterBlock { fn regs() -> &'static saadc::RegisterBlock {
unsafe { &*SAADC::ptr() } unsafe { &*SAADC::ptr() }
} }

View File

@ -4,17 +4,21 @@
use defmt::info; use defmt::info;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_nrf::interrupt;
use embassy_nrf::saadc::{ChannelConfig, Config, Saadc}; use embassy_nrf::saadc::{ChannelConfig, Config, Saadc};
use embassy_nrf::{bind_interrupts, saadc};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
SAADC => saadc::InterruptHandler;
});
#[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());
let config = Config::default(); let config = Config::default();
let channel_config = ChannelConfig::single_ended(&mut p.P0_02); let channel_config = ChannelConfig::single_ended(&mut p.P0_02);
let mut saadc = Saadc::new(p.SAADC, interrupt::take!(SAADC), config, [channel_config]); let mut saadc = Saadc::new(p.SAADC, Irqs, config, [channel_config]);
loop { loop {
let mut buf = [0; 1]; let mut buf = [0; 1];

View File

@ -4,14 +4,18 @@
use defmt::info; use defmt::info;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_nrf::interrupt;
use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc}; use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc};
use embassy_nrf::timer::Frequency; use embassy_nrf::timer::Frequency;
use embassy_nrf::{bind_interrupts, saadc};
use embassy_time::Duration; use embassy_time::Duration;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
// Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer // Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer
bind_interrupts!(struct Irqs {
SAADC => saadc::InterruptHandler;
});
#[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());
@ -21,7 +25,7 @@ async fn main(_p: Spawner) {
let channel_3_config = ChannelConfig::single_ended(&mut p.P0_04); let channel_3_config = ChannelConfig::single_ended(&mut p.P0_04);
let mut saadc = Saadc::new( let mut saadc = Saadc::new(
p.SAADC, p.SAADC,
interrupt::take!(SAADC), Irqs,
config, config,
[channel_1_config, channel_2_config, channel_3_config], [channel_1_config, channel_2_config, channel_3_config],
); );