stm32/i2c: use one static per instance instead of an array.

This commit is contained in:
Dario Nieuwenhuis 2022-02-26 01:23:17 +01:00
parent 8d46d31824
commit e6299549a0
3 changed files with 29 additions and 45 deletions

View File

@ -21,9 +21,10 @@ pub enum Error {
} }
pub(crate) mod sealed { pub(crate) mod sealed {
use super::*;
pub trait Instance: crate::rcc::RccPeripheral { pub trait Instance: crate::rcc::RccPeripheral {
fn regs() -> crate::pac::i2c::I2c; 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!(RxDma, Instance);
dma_trait!(TxDma, Instance); dma_trait!(TxDma, Instance);
macro_rules! i2c_state {
(I2C1) => {
0
};
(I2C2) => {
1
};
(I2C3) => {
2
};
(I2C4) => {
3
};
(I2C5) => {
4
};
}
crate::pac::interrupts!( crate::pac::interrupts!(
($inst:ident, i2c, $block:ident, EV, $irq:ident) => { ($inst:ident, i2c, $block:ident, EV, $irq:ident) => {
impl sealed::Instance for peripherals::$inst { impl sealed::Instance for peripherals::$inst {
@ -61,8 +44,9 @@ crate::pac::interrupts!(
crate::pac::$inst crate::pac::$inst
} }
fn state_number() -> usize { fn state() -> &'static State {
i2c_state!($inst) static STATE: State = State::new();
&STATE
} }
} }

View File

@ -7,6 +7,14 @@ use crate::i2c::{Error, Instance, SclPin, SdaPin};
use crate::pac::i2c; use crate::pac::i2c;
use crate::time::Hertz; use crate::time::Hertz;
pub struct State {}
impl State {
pub(crate) const fn new() -> Self {
Self {}
}
}
pub struct I2c<'d, T: Instance> { pub struct I2c<'d, T: Instance> {
phantom: PhantomData<&'d mut T>, phantom: PhantomData<&'d mut T>,
} }

View File

@ -13,31 +13,23 @@ use futures::future::poll_fn;
use crate::dma::NoDma; use crate::dma::NoDma;
use crate::gpio::sealed::AFType; use crate::gpio::sealed::AFType;
use crate::i2c::{Error, Instance, SclPin, SdaPin}; use crate::i2c::{Error, Instance, SclPin, SdaPin};
use crate::pac;
use crate::pac::i2c; use crate::pac::i2c;
use crate::time::Hertz; use crate::time::Hertz;
const I2C_COUNT: usize = pac::peripheral_count!(i2c);
pub struct State { pub struct State {
waker: [AtomicWaker; I2C_COUNT], waker: AtomicWaker,
chunks_transferred: [AtomicUsize; I2C_COUNT], chunks_transferred: AtomicUsize,
} }
impl State { impl State {
const fn new() -> Self { pub(crate) const fn new() -> Self {
const AW: AtomicWaker = AtomicWaker::new();
const CT: AtomicUsize = AtomicUsize::new(0);
Self { Self {
waker: [AW; I2C_COUNT], waker: AtomicWaker::new(),
chunks_transferred: [CT; I2C_COUNT], chunks_transferred: AtomicUsize::new(0),
} }
} }
} }
static STATE: State = State::new();
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> { pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
phantom: PhantomData<&'d mut T>, phantom: PhantomData<&'d mut T>,
tx_dma: TXDMA, tx_dma: TXDMA,
@ -108,9 +100,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
let isr = regs.isr().read(); let isr = regs.isr().read();
if isr.tcr() || isr.tc() { if isr.tcr() || isr.tc() {
let n = T::state_number(); let state = T::state();
STATE.chunks_transferred[n].fetch_add(1, Ordering::Relaxed); state.chunks_transferred.fetch_add(1, Ordering::Relaxed);
STATE.waker[n].wake(); state.waker.wake();
} }
// The flag can only be cleared by writting to nbytes, we won't do that here, so disable // The flag can only be cleared by writting to nbytes, we won't do that here, so disable
// the interrupt // the interrupt
@ -411,8 +403,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
crate::dma::write(ch, request, bytes, dst) crate::dma::write(ch, request, bytes, dst)
}; };
let state_number = T::state_number(); let state = T::state();
STATE.chunks_transferred[state_number].store(0, Ordering::Relaxed); state.chunks_transferred.store(0, Ordering::Relaxed);
let mut remaining_len = total_len; let mut remaining_len = total_len;
let _on_drop = OnDrop::new(|| { let _on_drop = OnDrop::new(|| {
@ -445,8 +437,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
poll_fn(|cx| { poll_fn(|cx| {
STATE.waker[state_number].register(cx.waker()); state.waker.register(cx.waker());
let chunks_transferred = STATE.chunks_transferred[state_number].load(Ordering::Relaxed); let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
if chunks_transferred == total_chunks { if chunks_transferred == total_chunks {
return Poll::Ready(()); 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) crate::dma::read(ch, request, src, buffer)
}; };
let state_number = T::state_number(); let state = T::state();
STATE.chunks_transferred[state_number].store(0, Ordering::Relaxed); state.chunks_transferred.store(0, Ordering::Relaxed);
let mut remaining_len = total_len; let mut remaining_len = total_len;
let _on_drop = OnDrop::new(|| { let _on_drop = OnDrop::new(|| {
@ -530,8 +522,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
poll_fn(|cx| { poll_fn(|cx| {
STATE.waker[state_number].register(cx.waker()); state.waker.register(cx.waker());
let chunks_transferred = STATE.chunks_transferred[state_number].load(Ordering::Relaxed); let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
if chunks_transferred == total_chunks { if chunks_transferred == total_chunks {
return Poll::Ready(()); return Poll::Ready(());