stm32/i2c: use one static per instance instead of an array.
This commit is contained in:
		| @@ -21,9 +21,10 @@ pub enum Error { | ||||
| } | ||||
|  | ||||
| pub(crate) mod sealed { | ||||
|     use super::*; | ||||
|     pub trait Instance: crate::rcc::RccPeripheral { | ||||
|         fn regs() -> crate::pac::i2c::I2c; | ||||
|         fn state_number() -> usize; | ||||
|         fn state() -> &'static State; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -36,24 +37,6 @@ pin_trait!(SdaPin, Instance); | ||||
| dma_trait!(RxDma, Instance); | ||||
| dma_trait!(TxDma, Instance); | ||||
|  | ||||
| macro_rules! i2c_state { | ||||
|     (I2C1) => { | ||||
|         0 | ||||
|     }; | ||||
|     (I2C2) => { | ||||
|         1 | ||||
|     }; | ||||
|     (I2C3) => { | ||||
|         2 | ||||
|     }; | ||||
|     (I2C4) => { | ||||
|         3 | ||||
|     }; | ||||
|     (I2C5) => { | ||||
|         4 | ||||
|     }; | ||||
| } | ||||
|  | ||||
| crate::pac::interrupts!( | ||||
|     ($inst:ident, i2c, $block:ident, EV, $irq:ident) => { | ||||
|         impl sealed::Instance for peripherals::$inst { | ||||
| @@ -61,8 +44,9 @@ crate::pac::interrupts!( | ||||
|                 crate::pac::$inst | ||||
|             } | ||||
|  | ||||
|             fn state_number() -> usize { | ||||
|                 i2c_state!($inst) | ||||
|             fn state() -> &'static State { | ||||
|                 static STATE: State = State::new(); | ||||
|                 &STATE | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,14 @@ use crate::i2c::{Error, Instance, SclPin, SdaPin}; | ||||
| use crate::pac::i2c; | ||||
| use crate::time::Hertz; | ||||
|  | ||||
| pub struct State {} | ||||
|  | ||||
| impl State { | ||||
|     pub(crate) const fn new() -> Self { | ||||
|         Self {} | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct I2c<'d, T: Instance> { | ||||
|     phantom: PhantomData<&'d mut T>, | ||||
| } | ||||
|   | ||||
| @@ -13,31 +13,23 @@ use futures::future::poll_fn; | ||||
| use crate::dma::NoDma; | ||||
| use crate::gpio::sealed::AFType; | ||||
| use crate::i2c::{Error, Instance, SclPin, SdaPin}; | ||||
| use crate::pac; | ||||
| use crate::pac::i2c; | ||||
| use crate::time::Hertz; | ||||
|  | ||||
| const I2C_COUNT: usize = pac::peripheral_count!(i2c); | ||||
|  | ||||
| pub struct State { | ||||
|     waker: [AtomicWaker; I2C_COUNT], | ||||
|     chunks_transferred: [AtomicUsize; I2C_COUNT], | ||||
|     waker: AtomicWaker, | ||||
|     chunks_transferred: AtomicUsize, | ||||
| } | ||||
|  | ||||
| impl State { | ||||
|     const fn new() -> Self { | ||||
|         const AW: AtomicWaker = AtomicWaker::new(); | ||||
|         const CT: AtomicUsize = AtomicUsize::new(0); | ||||
|  | ||||
|     pub(crate) const fn new() -> Self { | ||||
|         Self { | ||||
|             waker: [AW; I2C_COUNT], | ||||
|             chunks_transferred: [CT; I2C_COUNT], | ||||
|             waker: AtomicWaker::new(), | ||||
|             chunks_transferred: AtomicUsize::new(0), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static STATE: State = State::new(); | ||||
|  | ||||
| pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> { | ||||
|     phantom: PhantomData<&'d mut T>, | ||||
|     tx_dma: TXDMA, | ||||
| @@ -108,9 +100,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|         let isr = regs.isr().read(); | ||||
|  | ||||
|         if isr.tcr() || isr.tc() { | ||||
|             let n = T::state_number(); | ||||
|             STATE.chunks_transferred[n].fetch_add(1, Ordering::Relaxed); | ||||
|             STATE.waker[n].wake(); | ||||
|             let state = T::state(); | ||||
|             state.chunks_transferred.fetch_add(1, Ordering::Relaxed); | ||||
|             state.waker.wake(); | ||||
|         } | ||||
|         // The flag can only be cleared by writting to nbytes, we won't do that here, so disable | ||||
|         // the interrupt | ||||
| @@ -411,8 +403,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|             crate::dma::write(ch, request, bytes, dst) | ||||
|         }; | ||||
|  | ||||
|         let state_number = T::state_number(); | ||||
|         STATE.chunks_transferred[state_number].store(0, Ordering::Relaxed); | ||||
|         let state = T::state(); | ||||
|         state.chunks_transferred.store(0, Ordering::Relaxed); | ||||
|         let mut remaining_len = total_len; | ||||
|  | ||||
|         let _on_drop = OnDrop::new(|| { | ||||
| @@ -445,8 +437,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|         } | ||||
|  | ||||
|         poll_fn(|cx| { | ||||
|             STATE.waker[state_number].register(cx.waker()); | ||||
|             let chunks_transferred = STATE.chunks_transferred[state_number].load(Ordering::Relaxed); | ||||
|             state.waker.register(cx.waker()); | ||||
|             let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed); | ||||
|  | ||||
|             if chunks_transferred == total_chunks { | ||||
|                 return Poll::Ready(()); | ||||
| @@ -504,8 +496,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|             crate::dma::read(ch, request, src, buffer) | ||||
|         }; | ||||
|  | ||||
|         let state_number = T::state_number(); | ||||
|         STATE.chunks_transferred[state_number].store(0, Ordering::Relaxed); | ||||
|         let state = T::state(); | ||||
|         state.chunks_transferred.store(0, Ordering::Relaxed); | ||||
|         let mut remaining_len = total_len; | ||||
|  | ||||
|         let _on_drop = OnDrop::new(|| { | ||||
| @@ -530,8 +522,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|         } | ||||
|  | ||||
|         poll_fn(|cx| { | ||||
|             STATE.waker[state_number].register(cx.waker()); | ||||
|             let chunks_transferred = STATE.chunks_transferred[state_number].load(Ordering::Relaxed); | ||||
|             state.waker.register(cx.waker()); | ||||
|             let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed); | ||||
|  | ||||
|             if chunks_transferred == total_chunks { | ||||
|                 return Poll::Ready(()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user