Added guards to individual APIs

This commit is contained in:
Andres Oliva 2023-10-11 23:25:13 +02:00
parent b6c0ddb7df
commit cd68f85501
3 changed files with 86 additions and 12 deletions

View File

@ -5,7 +5,7 @@ use crate::interrupt;
// I2C V2 is gated on the `time` feature because timing facilities are necessary // I2C V2 is gated on the `time` feature because timing facilities are necessary
// to provide timeout functionality in order to prevent some APIs from stalling indefinitely // to provide timeout functionality in order to prevent some APIs from stalling indefinitely
#[cfg_attr(i2c_v1, path = "v1.rs")] #[cfg_attr(i2c_v1, path = "v1.rs")]
#[cfg_attr(all(i2c_v2, feature = "time"), path = "v2.rs")] #[cfg_attr(i2c_v2, path = "v2.rs")]
mod _version; mod _version;
pub use _version::*; pub use _version::*;

View File

@ -44,6 +44,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
pub struct Config { pub struct Config {
pub sda_pullup: bool, pub sda_pullup: bool,
pub scl_pullup: bool, pub scl_pullup: bool,
#[cfg(feature = "time")]
pub transaction_timeout: Duration, pub transaction_timeout: Duration,
} }
@ -52,6 +53,7 @@ impl Default for Config {
Self { Self {
sda_pullup: false, sda_pullup: false,
scl_pullup: false, scl_pullup: false,
#[cfg(feature = "time")]
transaction_timeout: Duration::from_millis(100), transaction_timeout: Duration::from_millis(100),
} }
} }
@ -74,6 +76,7 @@ pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
tx_dma: PeripheralRef<'d, TXDMA>, tx_dma: PeripheralRef<'d, TXDMA>,
#[allow(dead_code)] #[allow(dead_code)]
rx_dma: PeripheralRef<'d, RXDMA>, rx_dma: PeripheralRef<'d, RXDMA>,
#[cfg(feature = "time")]
timeout: Duration, timeout: Duration,
} }
@ -136,6 +139,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
_peri: peri, _peri: peri,
tx_dma, tx_dma,
rx_dma, rx_dma,
#[cfg(feature = "time")]
timeout: config.transaction_timeout, timeout: config.transaction_timeout,
} }
} }
@ -599,6 +603,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
// ========================= // =========================
// Async public API // Async public API
#[cfg(feature = "time")]
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 where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
@ -606,6 +611,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
self.write_timeout(address, write, self.timeout).await self.write_timeout(address, write, self.timeout).await
} }
#[cfg(feature = "time")]
pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error>
where where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
@ -622,6 +628,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
} }
#[cfg(feature = "time")]
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 where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
@ -629,6 +636,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
self.write_vectored_timeout(address, write, self.timeout).await self.write_vectored_timeout(address, write, self.timeout).await
} }
#[cfg(feature = "time")]
pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error> pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error>
where where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
@ -656,6 +664,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
Ok(()) Ok(())
} }
#[cfg(feature = "time")]
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 where
RXDMA: crate::i2c::RxDma<T>, RXDMA: crate::i2c::RxDma<T>,
@ -663,6 +672,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
self.read_timeout(address, buffer, self.timeout).await self.read_timeout(address, buffer, self.timeout).await
} }
#[cfg(feature = "time")]
pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error>
where where
RXDMA: crate::i2c::RxDma<T>, RXDMA: crate::i2c::RxDma<T>,
@ -679,6 +689,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
} }
#[cfg(feature = "time")]
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 where
TXDMA: super::TxDma<T>, TXDMA: super::TxDma<T>,
@ -687,6 +698,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
self.write_read_timeout(address, write, read, self.timeout).await self.write_read_timeout(address, write, read, self.timeout).await
} }
#[cfg(feature = "time")]
pub async fn write_read_timeout( pub async fn write_read_timeout(
&mut self, &mut self,
address: u8, address: u8,
@ -730,23 +742,43 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
// ========================= // =========================
// Blocking public API // Blocking public API
#[cfg(feature = "time")]
pub fn blocking_read_timeout(&mut self, address: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> { pub fn blocking_read_timeout(&mut self, address: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> {
self.read_internal(address, read, false, timeout_fn(timeout)) self.read_internal(address, read, false, timeout_fn(timeout))
// Automatic Stop // Automatic Stop
} }
pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { #[cfg(not(feature = "time"))]
self.blocking_read_timeout(address, read, self.timeout) pub fn blocking_read_timeout(&mut self, address: u8, read: &mut [u8], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
self.read_internal(address, read, false, check_timeout)
// Automatic Stop
} }
pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
#[cfg(feature = "time")]
self.blocking_read_timeout(address, read, self.timeout)
#[cfg(not(feature = "time"))]
self.blocking_read_timeout(address, read, || Ok(()))
}
#[cfg(feature = "time")]
pub fn blocking_write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> { pub fn blocking_write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> {
self.write_internal(address, write, true, timeout_fn(timeout)) self.write_internal(address, write, true, timeout_fn(timeout))
} }
pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { #[cfg(not(feature = "time"))]
self.blocking_write_timeout(address, write, self.timeout) pub fn blocking_write_timeout(&mut self, address: u8, write: &[u8], check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
self.write_internal(address, write, true, check_timeout)
} }
pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
#[cfg(feature = "time")]
self.blocking_write_timeout(address, write, self.timeout)
#[cfg(not(feature = "time"))]
self.blocking_write_timeout(address, write, || Ok(()))
}
#[cfg(feature = "time")]
pub fn blocking_write_read_timeout( pub fn blocking_write_read_timeout(
&mut self, &mut self,
address: u8, address: u8,
@ -760,21 +792,37 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
// Automatic Stop // Automatic Stop
} }
pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { #[cfg(not(feature = "time"))]
self.blocking_write_read_timeout(address, write, read, self.timeout) pub fn blocking_write_read_timeout(
&mut self,
address: u8,
write: &[u8],
read: &mut [u8],
check_timeout: impl Fn() -> Result<(), Error>,
) -> Result<(), Error> {
let check_timeout = timeout_fn(timeout);
self.write_internal(address, write, false, &check_timeout)?;
self.read_internal(address, read, true, &check_timeout)
// Automatic Stop
} }
pub fn blocking_write_vectored_timeout( pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
#[cfg(feature = "time")]
self.blocking_write_read_timeout(address, write, read, self.timeout)
#[cfg(not(feature = "time"))]
self.blocking_write_read_timeout(address, write, read, || Ok(()))
}
fn blocking_write_vectored_with_timeout(
&mut self, &mut self,
address: u8, address: u8,
write: &[&[u8]], write: &[&[u8]],
timeout: Duration, check_timeout: impl Fn() -> Result<(), Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
if write.is_empty() { if write.is_empty() {
return Err(Error::ZeroLengthTransfer); return Err(Error::ZeroLengthTransfer);
} }
let check_timeout = timeout_fn(timeout);
let first_length = write[0].len(); let first_length = write[0].len();
let last_slice_index = write.len() - 1; let last_slice_index = write.len() - 1;
@ -843,8 +891,32 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
result result
} }
#[cfg(feature = "time")]
pub fn blocking_write_vectored_timeout(
&mut self,
address: u8,
write: &[&[u8]],
timeout: Duration,
) -> Result<(), Error> {
let check_timeout = timeout_fn(timeout);
self.blocking_write_vectored_with_timeout(address, write, check_timeout)
}
#[cfg(not(feature = "time"))]
pub fn blocking_write_vectored_timeout(
&mut self,
address: u8,
write: &[&[u8]],
check_timeout: impl Fn() -> Result<(), Error>,
) -> Result<(), Error> {
self.blocking_write_vectored_with_timeout(address, write, check_timeout)
}
pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
#[cfg(feature = "time")]
self.blocking_write_vectored_timeout(address, write, self.timeout) self.blocking_write_vectored_timeout(address, write, self.timeout)
#[cfg(not(feature = "time"))]
self.blocking_write_vectored_timeout(address, write, || Ok(()))
} }
} }
@ -854,6 +926,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
} }
} }
#[cfg(feature = "time")]
mod eh02 { mod eh02 {
use super::*; use super::*;
@ -1053,7 +1126,7 @@ mod eh1 {
} }
} }
#[cfg(all(feature = "unstable-traits", feature = "nightly"))] #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "time"))]
mod eha { mod eha {
use super::super::{RxDma, TxDma}; use super::super::{RxDma, TxDma};
use super::*; use super::*;
@ -1100,6 +1173,7 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> {
} }
} }
#[cfg(feature = "time")]
fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> { fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
let deadline = Instant::now() + timeout; let deadline = Instant::now() + timeout;
move || { move || {

View File

@ -41,7 +41,7 @@ pub mod flash;
pub mod fmc; pub mod fmc;
#[cfg(hrtim)] #[cfg(hrtim)]
pub mod hrtim; pub mod hrtim;
#[cfg(all(i2c, any(i2c_v1, all(i2c_v2, feature = "time"))))] #[cfg(i2c)]
pub mod i2c; pub mod i2c;
#[cfg(all(spi_v1, rcc_f4))] #[cfg(all(spi_v1, rcc_f4))]
pub mod i2s; pub mod i2s;