add drop guard, clear interrupts, fix len return
This commit is contained in:
parent
8b50f2a58b
commit
c7b4a076cc
@ -162,19 +162,32 @@ pub enum SendStatus {
|
||||
LeftoverBytes(usize),
|
||||
}
|
||||
|
||||
struct I2CDropGuard<'d> {
|
||||
info: &'static Info,
|
||||
scl: Option<PeripheralRef<'d, AnyPin>>,
|
||||
sda: Option<PeripheralRef<'d, AnyPin>>,
|
||||
}
|
||||
impl<'d> Drop for I2CDropGuard<'d> {
|
||||
fn drop(&mut self) {
|
||||
self.scl.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.sda.as_ref().map(|x| x.set_as_disconnected());
|
||||
|
||||
self.info.rcc.disable();
|
||||
}
|
||||
}
|
||||
|
||||
/// I2C driver.
|
||||
pub struct I2c<'d, M: Mode, IM: MasterMode> {
|
||||
info: &'static Info,
|
||||
state: &'static State,
|
||||
kernel_clock: Hertz,
|
||||
scl: Option<PeripheralRef<'d, AnyPin>>,
|
||||
sda: Option<PeripheralRef<'d, AnyPin>>,
|
||||
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||
#[cfg(feature = "time")]
|
||||
timeout: Duration,
|
||||
_phantom: PhantomData<M>,
|
||||
_phantom2: PhantomData<IM>,
|
||||
drop_guard: I2CDropGuard<'d>,
|
||||
}
|
||||
|
||||
impl<'d> I2c<'d, Async, Master> {
|
||||
@ -242,14 +255,17 @@ impl<'d, M: Mode> I2c<'d, M, Master> {
|
||||
info: T::info(),
|
||||
state: T::state(),
|
||||
kernel_clock: T::frequency(),
|
||||
scl,
|
||||
sda,
|
||||
tx_dma,
|
||||
rx_dma,
|
||||
#[cfg(feature = "time")]
|
||||
timeout: config.timeout,
|
||||
_phantom: PhantomData,
|
||||
_phantom2: PhantomData,
|
||||
drop_guard: I2CDropGuard {
|
||||
info: T::info(),
|
||||
scl,
|
||||
sda,
|
||||
},
|
||||
};
|
||||
this.enable_and_init(freq, config);
|
||||
|
||||
@ -271,15 +287,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, M: Mode, IM: MasterMode> Drop for I2c<'d, M, IM> {
|
||||
fn drop(&mut self) {
|
||||
self.scl.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.sda.as_ref().map(|x| x.set_as_disconnected());
|
||||
|
||||
self.info.rcc.disable()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Timeout {
|
||||
#[cfg(feature = "time")]
|
||||
|
||||
@ -47,6 +47,8 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
|
||||
critical_section::with(|_| {
|
||||
regs.cr1().modify(|w| {
|
||||
w.set_addrie(false);
|
||||
w.set_stopie(false);
|
||||
w.set_tcie(false);
|
||||
// The flag can only be cleared by writting to nbytes, we won't do that here, so disable
|
||||
// the interrupt
|
||||
w.set_tcie(false);
|
||||
@ -725,14 +727,13 @@ impl<'d, M: Mode> I2c<'d, M, Master> {
|
||||
info: self.info,
|
||||
state: self.state,
|
||||
kernel_clock: self.kernel_clock,
|
||||
scl: self.scl.take(),
|
||||
sda: self.sda.take(),
|
||||
tx_dma: self.tx_dma.take(),
|
||||
rx_dma: self.rx_dma.take(),
|
||||
#[cfg(feature = "time")]
|
||||
timeout: self.timeout,
|
||||
_phantom: PhantomData,
|
||||
_phantom2: PhantomData,
|
||||
drop_guard: self.drop_guard,
|
||||
};
|
||||
slave.init_slave(slave_addr_config);
|
||||
slave
|
||||
@ -930,6 +931,8 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
|
||||
|
||||
impl<'d> I2c<'d, Async, MultiMaster> {
|
||||
/// Respond to a receive command.
|
||||
///
|
||||
/// Returns the total number of bytes received.
|
||||
pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
|
||||
let timeout = self.timeout();
|
||||
timeout.with(self.read_dma_internal_slave(buffer, timeout)).await
|
||||
@ -942,6 +945,8 @@ impl<'d> I2c<'d, Async, MultiMaster> {
|
||||
}
|
||||
|
||||
// for data reception in slave mode
|
||||
//
|
||||
// returns the total number of bytes received
|
||||
async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
|
||||
let total_len = buffer.len();
|
||||
let mut remaining_len = total_len;
|
||||
@ -988,7 +993,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
|
||||
Poll::Pending
|
||||
} else if isr.stopf() {
|
||||
regs.icr().write(|reg| reg.set_stopcf(true));
|
||||
let poll = Poll::Ready(Ok(remaining_len));
|
||||
let poll = Poll::Ready(Ok(total_len - remaining_len));
|
||||
poll
|
||||
} else {
|
||||
Poll::Pending
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user