parent
201a038134
commit
f5216624bb
1 changed files with 41 additions and 62 deletions
|
@ -1,6 +1,5 @@
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_embedded_hal::SetConfig;
|
use embassy_embedded_hal::SetConfig;
|
||||||
|
@ -35,14 +34,12 @@ impl Default for Config {
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
waker: AtomicWaker,
|
waker: AtomicWaker,
|
||||||
chunks_transferred: AtomicUsize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub(crate) const fn new() -> Self {
|
pub(crate) const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
waker: AtomicWaker::new(),
|
waker: AtomicWaker::new(),
|
||||||
chunks_transferred: AtomicUsize::new(0),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,10 +127,7 @@ 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 state = T::state();
|
T::state().waker.wake();
|
||||||
let transferred = state.chunks_transferred.load(Ordering::Relaxed);
|
|
||||||
state.chunks_transferred.store(transferred + 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 flag can only be cleared by writting to nbytes, we won't do that here, so disable
|
||||||
// the interrupt
|
// the interrupt
|
||||||
|
@ -457,12 +451,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
TXDMA: crate::i2c::TxDma<T>,
|
TXDMA: crate::i2c::TxDma<T>,
|
||||||
{
|
{
|
||||||
let total_len = write.len();
|
let total_len = write.len();
|
||||||
let completed_chunks = total_len / 255;
|
|
||||||
let total_chunks = if completed_chunks * 255 == total_len {
|
|
||||||
completed_chunks
|
|
||||||
} else {
|
|
||||||
completed_chunks + 1
|
|
||||||
};
|
|
||||||
|
|
||||||
let dma_transfer = unsafe {
|
let dma_transfer = unsafe {
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
@ -480,7 +468,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let state = T::state();
|
let state = T::state();
|
||||||
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(|| {
|
||||||
|
@ -495,33 +482,31 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
|
|
||||||
if first_slice {
|
|
||||||
unsafe {
|
|
||||||
Self::master_write(
|
|
||||||
address,
|
|
||||||
total_len.min(255),
|
|
||||||
Stop::Software,
|
|
||||||
(total_chunks != 1) || !last_slice,
|
|
||||||
&check_timeout,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
Self::master_continue(total_len.min(255), (total_chunks != 1) || !last_slice, &check_timeout)?;
|
|
||||||
T::regs().cr1().modify(|w| w.set_tcie(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
state.waker.register(cx.waker());
|
state.waker.register(cx.waker());
|
||||||
let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
|
|
||||||
|
|
||||||
if chunks_transferred == total_chunks {
|
if remaining_len == total_len {
|
||||||
|
// NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
|
||||||
|
if first_slice {
|
||||||
|
unsafe {
|
||||||
|
Self::master_write(
|
||||||
|
address,
|
||||||
|
total_len.min(255),
|
||||||
|
Stop::Software,
|
||||||
|
(total_len > 255) || !last_slice,
|
||||||
|
&check_timeout,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?;
|
||||||
|
T::regs().cr1().modify(|w| w.set_tcie(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if remaining_len == 0 {
|
||||||
return Poll::Ready(Ok(()));
|
return Poll::Ready(Ok(()));
|
||||||
} else if chunks_transferred != 0 {
|
} else {
|
||||||
remaining_len = remaining_len.saturating_sub(255);
|
let last_piece = (remaining_len <= 255) && last_slice;
|
||||||
let last_piece = (chunks_transferred + 1 == total_chunks) && last_slice;
|
|
||||||
|
|
||||||
// NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
|
// NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -531,6 +516,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
T::regs().cr1().modify(|w| w.set_tcie(true));
|
T::regs().cr1().modify(|w| w.set_tcie(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remaining_len = remaining_len.saturating_sub(255);
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -559,12 +546,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
RXDMA: crate::i2c::RxDma<T>,
|
RXDMA: crate::i2c::RxDma<T>,
|
||||||
{
|
{
|
||||||
let total_len = buffer.len();
|
let total_len = buffer.len();
|
||||||
let completed_chunks = total_len / 255;
|
|
||||||
let total_chunks = if completed_chunks * 255 == total_len {
|
|
||||||
completed_chunks
|
|
||||||
} else {
|
|
||||||
completed_chunks + 1
|
|
||||||
};
|
|
||||||
|
|
||||||
let dma_transfer = unsafe {
|
let dma_transfer = unsafe {
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
@ -580,7 +561,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let state = T::state();
|
let state = T::state();
|
||||||
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(|| {
|
||||||
|
@ -593,27 +573,24 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
|
|
||||||
unsafe {
|
|
||||||
Self::master_read(
|
|
||||||
address,
|
|
||||||
total_len.min(255),
|
|
||||||
Stop::Software,
|
|
||||||
total_chunks != 1,
|
|
||||||
restart,
|
|
||||||
&check_timeout,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
state.waker.register(cx.waker());
|
state.waker.register(cx.waker());
|
||||||
let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
|
if remaining_len == total_len {
|
||||||
|
// NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
|
||||||
if chunks_transferred == total_chunks {
|
unsafe {
|
||||||
|
Self::master_read(
|
||||||
|
address,
|
||||||
|
total_len.min(255),
|
||||||
|
Stop::Software,
|
||||||
|
total_len > 255,
|
||||||
|
restart,
|
||||||
|
&check_timeout,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
} else if remaining_len == 0 {
|
||||||
return Poll::Ready(Ok(()));
|
return Poll::Ready(Ok(()));
|
||||||
} else if chunks_transferred != 0 {
|
} else {
|
||||||
remaining_len = remaining_len.saturating_sub(255);
|
let last_piece = remaining_len <= 255;
|
||||||
let last_piece = chunks_transferred + 1 == total_chunks;
|
|
||||||
|
|
||||||
// NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
|
// NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -623,6 +600,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
T::regs().cr1().modify(|w| w.set_tcie(true));
|
T::regs().cr1().modify(|w| w.set_tcie(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remaining_len = remaining_len.saturating_sub(255);
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
Loading…
Reference in a new issue