From e4c2b2aa9a61e5135d2e129705c9bdc3b4cb73ae Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 16 Oct 2022 18:00:23 -0700 Subject: rp i2c: have separate wakers for each i2c unit If they both share one waker, there's the possibility that some wakeups could get lost. --- embassy-rp/src/i2c.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 68cfc653..b9e4382c 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -70,7 +70,7 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> { } } -static I2C_WAKER: AtomicWaker = AtomicWaker::new(); +static I2C_WAKER: [AtomicWaker; 2] = [AtomicWaker::new(), AtomicWaker::new()]; impl<'d, T: Instance> I2c<'d, T, Async> { pub fn new_async( @@ -109,7 +109,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let r = f(self); if r.is_pending() { - I2C_WAKER.register(cx.waker()); + I2C_WAKER[T::IDX].register(cx.waker()); g(self); } r @@ -122,7 +122,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let i2c = T::regs(); i2c.ic_intr_mask().write_value(pac::i2c::regs::IcIntrMask::default()); - I2C_WAKER.wake(); + I2C_WAKER[T::IDX].wake(); } async fn read_async_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> { @@ -813,6 +813,7 @@ mod sealed { pub trait Instance { const TX_DREQ: u8; const RX_DREQ: u8; + const IDX: usize; type Interrupt: Interrupt; @@ -844,10 +845,11 @@ impl_mode!(Async); pub trait Instance: sealed::Instance {} macro_rules! impl_instance { - ($type:ident, $irq:ident, $reset:ident, $tx_dreq:expr, $rx_dreq:expr) => { + ($type:ident, $idx:expr, $irq:ident, $reset:ident, $tx_dreq:expr, $rx_dreq:expr) => { impl sealed::Instance for peripherals::$type { const TX_DREQ: u8 = $tx_dreq; const RX_DREQ: u8 = $rx_dreq; + const IDX: usize = $idx; type Interrupt = crate::interrupt::$irq; @@ -867,8 +869,8 @@ macro_rules! impl_instance { }; } -impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33); -impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35); +impl_instance!(I2C0, 0, I2C0_IRQ, set_i2c0, 32, 33); +impl_instance!(I2C1, 1, I2C1_IRQ, set_i2c1, 34, 35); pub trait SdaPin: sealed::SdaPin + crate::gpio::Pin {} pub trait SclPin: sealed::SclPin + crate::gpio::Pin {} -- cgit v1.2.3 From 02a3cdb507d535908bc0668a31526c05b5d01005 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 17 Oct 2022 21:50:40 -0700 Subject: Associate state with the instance rather than having a separate array --- embassy-rp/src/i2c.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index b9e4382c..d6742f6a 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -70,8 +70,6 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> { } } -static I2C_WAKER: [AtomicWaker; 2] = [AtomicWaker::new(), AtomicWaker::new()]; - impl<'d, T: Instance> I2c<'d, T, Async> { pub fn new_async( peri: impl Peripheral

+ 'd, @@ -109,7 +107,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let r = f(self); if r.is_pending() { - I2C_WAKER[T::IDX].register(cx.waker()); + T::waker().register(cx.waker()); g(self); } r @@ -122,7 +120,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let i2c = T::regs(); i2c.ic_intr_mask().write_value(pac::i2c::regs::IcIntrMask::default()); - I2C_WAKER[T::IDX].wake(); + T::waker().wake(); } async fn read_async_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> { @@ -809,16 +807,17 @@ fn i2c_reserved_addr(addr: u16) -> bool { mod sealed { use embassy_cortex_m::interrupt::Interrupt; + use embassy_sync::waitqueue::AtomicWaker; pub trait Instance { const TX_DREQ: u8; const RX_DREQ: u8; - const IDX: usize; type Interrupt: Interrupt; fn regs() -> crate::pac::i2c::I2c; fn reset() -> crate::pac::resets::regs::Peripherals; + fn waker() -> &'static AtomicWaker; } pub trait Mode {} @@ -845,11 +844,10 @@ impl_mode!(Async); pub trait Instance: sealed::Instance {} macro_rules! impl_instance { - ($type:ident, $idx:expr, $irq:ident, $reset:ident, $tx_dreq:expr, $rx_dreq:expr) => { + ($type:ident, $irq:ident, $reset:ident, $tx_dreq:expr, $rx_dreq:expr) => { impl sealed::Instance for peripherals::$type { const TX_DREQ: u8 = $tx_dreq; const RX_DREQ: u8 = $rx_dreq; - const IDX: usize = $idx; type Interrupt = crate::interrupt::$irq; @@ -864,13 +862,20 @@ macro_rules! impl_instance { ret.$reset(true); ret } + + #[inline] + fn waker() -> &'static AtomicWaker { + static WAKER: AtomicWaker = AtomicWaker::new(); + + &WAKER + } } impl Instance for peripherals::$type {} }; } -impl_instance!(I2C0, 0, I2C0_IRQ, set_i2c0, 32, 33); -impl_instance!(I2C1, 1, I2C1_IRQ, set_i2c1, 34, 35); +impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33); +impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35); pub trait SdaPin: sealed::SdaPin + crate::gpio::Pin {} pub trait SclPin: sealed::SclPin + crate::gpio::Pin {} -- cgit v1.2.3