Merge pull request #1729 from mattico/i2c-async-timeout

stm32: add async timeout functions to I2c and TimeoutI2c
This commit is contained in:
Dario Nieuwenhuis 2023-08-01 08:20:48 +00:00 committed by GitHub
commit 0d8a9b1e7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 153 additions and 15 deletions

View File

@ -22,11 +22,93 @@ fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
} }
} }
impl<'a, 'd, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self { pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self {
Self { i2c, timeout } Self { i2c, timeout }
} }
// =========================
// Async public API
#[cfg(i2c_v2)]
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
self.write_timeout(address, write, self.timeout).await
}
#[cfg(i2c_v2)]
pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
self.i2c.write_timeout(address, write, timeout_fn(timeout)).await
}
#[cfg(i2c_v2)]
pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
self.write_vectored_timeout(address, write, self.timeout).await
}
#[cfg(i2c_v2)]
pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
self.i2c
.write_vectored_timeout(address, write, timeout_fn(timeout))
.await
}
#[cfg(i2c_v2)]
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
{
self.read_timeout(address, buffer, self.timeout).await
}
#[cfg(i2c_v2)]
pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
{
self.i2c.read_timeout(address, buffer, timeout_fn(timeout)).await
}
#[cfg(i2c_v2)]
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
where
TXDMA: super::TxDma<T>,
RXDMA: super::RxDma<T>,
{
self.write_read_timeout(address, write, read, self.timeout).await
}
#[cfg(i2c_v2)]
pub async fn write_read_timeout(
&mut self,
address: u8,
write: &[u8],
read: &mut [u8],
timeout: Duration,
) -> Result<(), Error>
where
TXDMA: super::TxDma<T>,
RXDMA: super::RxDma<T>,
{
self.i2c
.write_read_timeout(address, write, read, timeout_fn(timeout))
.await
}
// =========================
// Blocking public API
/// Blocking read with a custom timeout /// Blocking read with a custom timeout
pub fn blocking_read_timeout(&mut self, addr: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> { pub fn blocking_read_timeout(&mut self, addr: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> {
self.i2c.blocking_read_timeout(addr, read, timeout_fn(timeout)) self.i2c.blocking_read_timeout(addr, read, timeout_fn(timeout))
@ -65,7 +147,9 @@ impl<'a, 'd, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
} }
} }
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read
for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA>
{
type Error = Error; type Error = Error;
fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> { fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> {
@ -73,7 +157,9 @@ impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for
} }
} }
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write
for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA>
{
type Error = Error; type Error = Error;
fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> { fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> {
@ -81,7 +167,7 @@ impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write fo
} }
} }
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead
for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA>
{ {
type Error = Error; type Error = Error;
@ -95,11 +181,11 @@ impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRea
mod eh1 { mod eh1 {
use super::*; use super::*;
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
type Error = Error; type Error = Error;
} }
impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.blocking_read(address, read) self.blocking_read(address, read)
} }

View File

@ -595,17 +595,41 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
// Async public API // Async public API
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
self.write_timeout(address, write, || Ok(())).await
}
pub async fn write_timeout(
&mut self,
address: u8,
write: &[u8],
check_timeout: impl Fn() -> Result<(), Error>,
) -> Result<(), Error>
where where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
{ {
if write.is_empty() { if write.is_empty() {
self.write_internal(address, write, true, || Ok(())) self.write_internal(address, write, true, check_timeout)
} else { } else {
self.write_dma_internal(address, write, true, true, || Ok(())).await self.write_dma_internal(address, write, true, true, check_timeout).await
} }
} }
pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
self.write_vectored_timeout(address, write, || Ok(())).await
}
pub async fn write_vectored_timeout(
&mut self,
address: u8,
write: &[&[u8]],
check_timeout: impl Fn() -> Result<(), Error>,
) -> Result<(), Error>
where where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
{ {
@ -620,7 +644,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
let next = iter.next(); let next = iter.next();
let is_last = next.is_none(); let is_last = next.is_none();
self.write_dma_internal(address, c, first, is_last, || Ok(())).await?; self.write_dma_internal(address, c, first, is_last, || check_timeout())
.await?;
first = false; first = false;
current = next; current = next;
} }
@ -628,31 +653,58 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
{
self.read_timeout(address, buffer, || Ok(())).await
}
pub async fn read_timeout(
&mut self,
address: u8,
buffer: &mut [u8],
check_timeout: impl Fn() -> Result<(), Error>,
) -> Result<(), Error>
where where
RXDMA: crate::i2c::RxDma<T>, RXDMA: crate::i2c::RxDma<T>,
{ {
if buffer.is_empty() { if buffer.is_empty() {
self.read_internal(address, buffer, false, || Ok(())) self.read_internal(address, buffer, false, check_timeout)
} else { } else {
self.read_dma_internal(address, buffer, false, || Ok(())).await self.read_dma_internal(address, buffer, false, check_timeout).await
} }
} }
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
where
TXDMA: super::TxDma<T>,
RXDMA: super::RxDma<T>,
{
self.write_read_timeout(address, write, read, || Ok(())).await
}
pub async fn write_read_timeout(
&mut self,
address: u8,
write: &[u8],
read: &mut [u8],
check_timeout: impl Fn() -> Result<(), Error>,
) -> Result<(), Error>
where where
TXDMA: super::TxDma<T>, TXDMA: super::TxDma<T>,
RXDMA: super::RxDma<T>, RXDMA: super::RxDma<T>,
{ {
if write.is_empty() { if write.is_empty() {
self.write_internal(address, write, false, || Ok(()))?; self.write_internal(address, write, false, || check_timeout())?;
} else { } else {
self.write_dma_internal(address, write, true, true, || Ok(())).await?; self.write_dma_internal(address, write, true, true, || check_timeout())
.await?;
} }
if read.is_empty() { if read.is_empty() {
self.read_internal(address, read, true, || Ok(()))?; self.read_internal(address, read, true, check_timeout)?;
} else { } else {
self.read_dma_internal(address, read, true, || Ok(())).await?; self.read_dma_internal(address, read, true, check_timeout).await?;
} }
Ok(()) Ok(())