rp/pio: move irq flag handling to own struct

this way we can share irq handling between state machines and common
without having to duplicate the methods. it also lets us give irq flag
access to places without having to dedicate a state machine or the
common instance to those places, which can be very useful to eg trigger
an event and wait for a confirmation using an irq wait object.
This commit is contained in:
pennae 2023-05-03 10:51:50 +02:00
parent 909a5fe2e5
commit 77f7830da3

View File

@ -811,28 +811,6 @@ impl<'d, PIO: PioInstance> PioCommon<'d, PIO> {
self.instructions_used &= !instrs.used_mask; self.instructions_used &= !instrs.used_mask;
} }
pub fn is_irq_set(&self, irq_no: u8) -> bool {
assert!(irq_no < 8);
unsafe {
let irq_flags = PIO::PIO.irq();
irq_flags.read().0 & (1 << irq_no) != 0
}
}
pub fn clear_irq(&mut self, irq_no: usize) {
assert!(irq_no < 8);
unsafe { PIO::PIO.irq().write(|w| w.set_irq(1 << irq_no)) }
}
pub fn clear_irqs(&mut self, mask: u8) {
unsafe { PIO::PIO.irq().write(|w| w.set_irq(mask)) }
}
pub fn force_irq(&mut self, irq_no: usize) {
assert!(irq_no < 8);
unsafe { PIO::PIO.irq_force().write(|w| w.set_irq_force(1 << irq_no)) }
}
pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) {
unsafe { unsafe {
// this can interfere with per-pin bypass functions. splitting the // this can interfere with per-pin bypass functions. splitting the
@ -878,8 +856,47 @@ impl<'d, PIO: PioInstance, const N: usize> PioIrq<'d, PIO, N> {
} }
} }
#[derive(Clone)]
pub struct PioIrqFlags<'d, PIO: PioInstance> {
pio: PhantomData<&'d PIO>,
}
impl<'d, PIO: PioInstance> PioIrqFlags<'d, PIO> {
pub fn check(&self, irq_no: u8) -> bool {
assert!(irq_no < 8);
self.check_any(1 << irq_no)
}
pub fn check_any(&self, irqs: u8) -> bool {
unsafe { PIO::PIO.irq().read().irq() & irqs != 0 }
}
pub fn check_all(&self, irqs: u8) -> bool {
unsafe { PIO::PIO.irq().read().irq() & irqs == irqs }
}
pub fn clear(&self, irq_no: usize) {
assert!(irq_no < 8);
self.clear_all(1 << irq_no);
}
pub fn clear_all(&self, irqs: u8) {
unsafe { PIO::PIO.irq().write(|w| w.set_irq(irqs)) }
}
pub fn set(&self, irq_no: usize) {
assert!(irq_no < 8);
self.set_all(1 << irq_no);
}
pub fn set_all(&self, irqs: u8) {
unsafe { PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs)) }
}
}
pub struct Pio<'d, PIO: PioInstance> { pub struct Pio<'d, PIO: PioInstance> {
pub common: PioCommon<'d, PIO>, pub common: PioCommon<'d, PIO>,
pub irq_flags: PioIrqFlags<'d, PIO>,
pub irq0: PioIrq<'d, PIO, 0>, pub irq0: PioIrq<'d, PIO, 0>,
pub irq1: PioIrq<'d, PIO, 1>, pub irq1: PioIrq<'d, PIO, 1>,
pub irq2: PioIrq<'d, PIO, 2>, pub irq2: PioIrq<'d, PIO, 2>,
@ -899,6 +916,7 @@ impl<'d, PIO: PioInstance> Pio<'d, PIO> {
instructions_used: 0, instructions_used: 0,
pio: PhantomData, pio: PhantomData,
}, },
irq_flags: PioIrqFlags { pio: PhantomData },
irq0: PioIrq { pio: PhantomData }, irq0: PioIrq { pio: PhantomData },
irq1: PioIrq { pio: PhantomData }, irq1: PioIrq { pio: PhantomData },
irq2: PioIrq { pio: PhantomData }, irq2: PioIrq { pio: PhantomData },