mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-29 21:30:39 +00:00
I2c addr (#2864)
* I2C: prepare to support 10-bit addresses later * Introduce I2C Timeout enum * Migration guide * CHANGELOG.md * Timeout::Maximum * Internal Enum * Check timeout * Address review comments * Timeout -> SclTimeout * Remove `as_u8` * Implement idea from review * Review * Renaming * Fix migration guide --------- Co-authored-by: Juraj Sadel <juraj.sadel@espressif.com>
This commit is contained in:
parent
2da7cbc812
commit
5e05402e98
@ -104,6 +104,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- `ClockSource` enums are now `#[non_exhaustive]` (#2912)
|
||||
- `macros` module is now private (#2900)
|
||||
- `gpio::{Input, Flex}::wakeup_enable` now returns an error instead of panicking. (#2916)
|
||||
- I2C: Have a dedicated enum to specify the timeout (#2864)
|
||||
- Removed the `I` prefix from `DriveStrength` enum variants. (#2922)
|
||||
- Removed the `Attenuation` prefix from `Attenuation` enum variants. (#2922)
|
||||
- Renamed / changed some I2C error variants (#2844, #2862)
|
||||
|
@ -333,6 +333,26 @@ The `AckCheckFailed` variant changed to `AcknowledgeCheckFailed(AcknowledgeCheck
|
||||
+ Err(Error::AcknowledgeCheckFailed(reason))
|
||||
```
|
||||
|
||||
## I2C Configuration changes
|
||||
|
||||
The timeout field in `Config` changed from `Option<u32>` to a dedicated `BusTimeout` enum.
|
||||
|
||||
```diff
|
||||
- timeout: Some(10)
|
||||
+ timeout: BusTimeout::BusCycles(10)
|
||||
```
|
||||
|
||||
```diff
|
||||
- timeout: None
|
||||
+ timeout: BusTimeout::Max
|
||||
```
|
||||
|
||||
(Disabled isn't supported on ESP32 / ESP32-S2)
|
||||
```diff
|
||||
- timeout: None
|
||||
+ timeout: BusTimeout::Disabled
|
||||
```
|
||||
|
||||
## The crate prelude has been removed
|
||||
|
||||
The reexports that were previously part of the prelude are available through other paths:
|
||||
|
@ -85,6 +85,83 @@ const I2C_CHUNK_SIZE: usize = 254;
|
||||
// on ESP32 there is a chance to get trapped in `wait_for_completion` forever
|
||||
const MAX_ITERATIONS: u32 = 1_000_000;
|
||||
|
||||
/// Representation of I2C address.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum I2cAddress {
|
||||
/// 7-bit address mode type.
|
||||
///
|
||||
/// Note that 7-bit addresses defined by drivers should be specified in
|
||||
/// **right-aligned** form, e.g. in the range `0x00..=0x7F`.
|
||||
///
|
||||
/// For example, a device that has the seven bit address of `0b011_0010`,
|
||||
/// and therefore is addressed on the wire using:
|
||||
///
|
||||
/// * `0b0110010_0` or `0x64` for *writes*
|
||||
/// * `0b0110010_1` or `0x65` for *reads*
|
||||
SevenBit(u8),
|
||||
}
|
||||
|
||||
impl From<u8> for I2cAddress {
|
||||
fn from(value: u8) -> Self {
|
||||
I2cAddress::SevenBit(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// I2C SCL timeout period.
|
||||
///
|
||||
/// When the level of SCL remains unchanged for more than `timeout` bus
|
||||
/// clock cycles, the bus goes to idle state.
|
||||
///
|
||||
/// Default value is `BusCycles(10)`.
|
||||
#[doc = ""]
|
||||
#[cfg_attr(
|
||||
not(esp32),
|
||||
doc = "Note that the effective timeout may be longer than the value configured here."
|
||||
)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, strum::Display)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
// TODO: when supporting interrupts, document that SCL = high also triggers an
|
||||
// interrupt.
|
||||
pub enum BusTimeout {
|
||||
/// Use the maximum timeout value.
|
||||
Maximum,
|
||||
|
||||
/// Disable timeout control.
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
Disabled,
|
||||
|
||||
/// Timeout in bus clock cycles.
|
||||
BusCycles(u32),
|
||||
}
|
||||
|
||||
impl BusTimeout {
|
||||
fn cycles(&self) -> u32 {
|
||||
match self {
|
||||
#[cfg(esp32)]
|
||||
BusTimeout::Maximum => 0xF_FFFF,
|
||||
|
||||
#[cfg(esp32s2)]
|
||||
BusTimeout::Maximum => 0xFF_FFFF,
|
||||
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
BusTimeout::Maximum => 0x1F,
|
||||
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
BusTimeout::Disabled => 1,
|
||||
|
||||
BusTimeout::BusCycles(cycles) => *cycles,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(esp32))]
|
||||
fn is_set(&self) -> bool {
|
||||
matches!(self, BusTimeout::BusCycles(_) | BusTimeout::Maximum)
|
||||
}
|
||||
}
|
||||
|
||||
/// I2C-specific transmission errors
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@ -178,6 +255,8 @@ impl core::fmt::Display for Error {
|
||||
pub enum ConfigError {
|
||||
/// Provided bus frequency is invalid for the current configuration.
|
||||
FrequencyInvalid,
|
||||
/// Provided timeout is invalid for the current configuration.
|
||||
TimeoutInvalid,
|
||||
}
|
||||
|
||||
impl core::error::Error for ConfigError {}
|
||||
@ -189,6 +268,10 @@ impl core::fmt::Display for ConfigError {
|
||||
f,
|
||||
"Provided bus frequency is invalid for the current configuration"
|
||||
),
|
||||
ConfigError::TimeoutInvalid => write!(
|
||||
f,
|
||||
"Provided timeout is invalid for the current configuration"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -329,20 +412,7 @@ pub struct Config {
|
||||
pub frequency: HertzU32,
|
||||
|
||||
/// I2C SCL timeout period.
|
||||
///
|
||||
/// When the level of SCL remains unchanged for more than `timeout` bus
|
||||
/// clock cycles, the bus goes to idle state.
|
||||
///
|
||||
/// The default value is about 10 bus clock cycles.
|
||||
#[doc = ""]
|
||||
#[cfg_attr(
|
||||
not(esp32),
|
||||
doc = "Note that the effective timeout may be longer than the value configured here."
|
||||
)]
|
||||
#[cfg_attr(not(esp32), doc = "Configuring `None` disables timeout control.")]
|
||||
#[cfg_attr(esp32, doc = "Configuring `None` equals to the maximum timeout value.")]
|
||||
// TODO: when supporting interrupts, document that SCL = high also triggers an interrupt.
|
||||
pub timeout: Option<u32>,
|
||||
pub timeout: BusTimeout,
|
||||
}
|
||||
|
||||
impl core::hash::Hash for Config {
|
||||
@ -357,7 +427,7 @@ impl Default for Config {
|
||||
use fugit::RateExtU32;
|
||||
Config {
|
||||
frequency: 100.kHz(),
|
||||
timeout: Some(10),
|
||||
timeout: BusTimeout::BusCycles(10),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -393,8 +463,11 @@ impl<Dm: DriverMode> embedded_hal::i2c::I2c for I2c<'_, Dm> {
|
||||
address: u8,
|
||||
operations: &mut [embedded_hal::i2c::Operation<'_>],
|
||||
) -> Result<(), Self::Error> {
|
||||
self.transaction_impl(address, operations.iter_mut().map(Operation::from))
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
self.transaction_impl(
|
||||
I2cAddress::SevenBit(address),
|
||||
operations.iter_mut().map(Operation::from),
|
||||
)
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,7 +497,7 @@ impl<'d, Dm: DriverMode> I2c<'d, Dm> {
|
||||
|
||||
fn transaction_impl<'a>(
|
||||
&mut self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
operations: impl Iterator<Item = Operation<'a>>,
|
||||
) -> Result<(), Error> {
|
||||
let mut last_op: Option<OpKind> = None;
|
||||
@ -567,27 +640,33 @@ impl<'d> I2c<'d, Blocking> {
|
||||
}
|
||||
|
||||
/// Writes bytes to slave with address `address`
|
||||
pub fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
|
||||
pub fn write<A: Into<I2cAddress>>(&mut self, address: A, buffer: &[u8]) -> Result<(), Error> {
|
||||
self.driver()
|
||||
.write_blocking(address, buffer, true, true)
|
||||
.write_blocking(address.into(), buffer, true, true)
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
}
|
||||
|
||||
/// Reads enough bytes from slave with `address` to fill `buffer`
|
||||
pub fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn read<A: Into<I2cAddress>>(
|
||||
&mut self,
|
||||
address: A,
|
||||
buffer: &mut [u8],
|
||||
) -> Result<(), Error> {
|
||||
self.driver()
|
||||
.read_blocking(address, buffer, true, true, false)
|
||||
.read_blocking(address.into(), buffer, true, true, false)
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
}
|
||||
|
||||
/// Writes bytes to slave with address `address` and then reads enough bytes
|
||||
/// to fill `buffer` *in a single transaction*
|
||||
pub fn write_read(
|
||||
pub fn write_read<A: Into<I2cAddress>>(
|
||||
&mut self,
|
||||
address: u8,
|
||||
address: A,
|
||||
write_buffer: &[u8],
|
||||
read_buffer: &mut [u8],
|
||||
) -> Result<(), Error> {
|
||||
let address = address.into();
|
||||
|
||||
self.driver()
|
||||
.write_blocking(address, write_buffer, true, read_buffer.is_empty())
|
||||
.inspect_err(|_| self.internal_recover())?;
|
||||
@ -617,12 +696,12 @@ impl<'d> I2c<'d, Blocking> {
|
||||
/// to indicate writing
|
||||
/// - `SR` = repeated start condition
|
||||
/// - `SP` = stop condition
|
||||
pub fn transaction<'a>(
|
||||
pub fn transaction<'a, A: Into<I2cAddress>>(
|
||||
&mut self,
|
||||
address: u8,
|
||||
address: A,
|
||||
operations: impl IntoIterator<Item = &'a mut Operation<'a>>,
|
||||
) -> Result<(), Error> {
|
||||
self.transaction_impl(address, operations.into_iter().map(Operation::from))
|
||||
self.transaction_impl(address.into(), operations.into_iter().map(Operation::from))
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
}
|
||||
}
|
||||
@ -765,29 +844,39 @@ impl<'d> I2c<'d, Async> {
|
||||
}
|
||||
|
||||
/// Writes bytes to slave with address `address`
|
||||
pub async fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
|
||||
pub async fn write<A: Into<I2cAddress>>(
|
||||
&mut self,
|
||||
address: A,
|
||||
buffer: &[u8],
|
||||
) -> Result<(), Error> {
|
||||
self.driver()
|
||||
.write(address, buffer, true, true)
|
||||
.write(address.into(), buffer, true, true)
|
||||
.await
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
}
|
||||
|
||||
/// Reads enough bytes from slave with `address` to fill `buffer`
|
||||
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
pub async fn read<A: Into<I2cAddress>>(
|
||||
&mut self,
|
||||
address: A,
|
||||
buffer: &mut [u8],
|
||||
) -> Result<(), Error> {
|
||||
self.driver()
|
||||
.read(address, buffer, true, true, false)
|
||||
.read(address.into(), buffer, true, true, false)
|
||||
.await
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
}
|
||||
|
||||
/// Writes bytes to slave with address `address` and then reads enough
|
||||
/// bytes to fill `buffer` *in a single transaction*
|
||||
pub async fn write_read(
|
||||
pub async fn write_read<A: Into<I2cAddress>>(
|
||||
&mut self,
|
||||
address: u8,
|
||||
address: A,
|
||||
write_buffer: &[u8],
|
||||
read_buffer: &mut [u8],
|
||||
) -> Result<(), Error> {
|
||||
let address = address.into();
|
||||
|
||||
self.driver()
|
||||
.write(address, write_buffer, true, read_buffer.is_empty())
|
||||
.await
|
||||
@ -820,19 +909,19 @@ impl<'d> I2c<'d, Async> {
|
||||
/// to indicate writing
|
||||
/// - `SR` = repeated start condition
|
||||
/// - `SP` = stop condition
|
||||
pub async fn transaction<'a>(
|
||||
pub async fn transaction<'a, A: Into<I2cAddress>>(
|
||||
&mut self,
|
||||
address: u8,
|
||||
address: A,
|
||||
operations: impl IntoIterator<Item = &'a mut Operation<'a>>,
|
||||
) -> Result<(), Error> {
|
||||
self.transaction_impl_async(address, operations.into_iter().map(Operation::from))
|
||||
self.transaction_impl_async(address.into(), operations.into_iter().map(Operation::from))
|
||||
.await
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
}
|
||||
|
||||
async fn transaction_impl_async<'a>(
|
||||
&mut self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
operations: impl Iterator<Item = Operation<'a>>,
|
||||
) -> Result<(), Error> {
|
||||
let mut last_op: Option<OpKind> = None;
|
||||
@ -888,7 +977,7 @@ impl embedded_hal_async::i2c::I2c for I2c<'_, Async> {
|
||||
address: u8,
|
||||
operations: &mut [EhalOperation<'_>],
|
||||
) -> Result<(), Self::Error> {
|
||||
self.transaction_impl_async(address, operations.iter_mut().map(Operation::from))
|
||||
self.transaction_impl_async(address.into(), operations.iter_mut().map(Operation::from))
|
||||
.await
|
||||
.inspect_err(|_| self.internal_recover())
|
||||
}
|
||||
@ -961,7 +1050,7 @@ fn configure_clock(
|
||||
scl_stop_setup_time: u32,
|
||||
scl_start_hold_time: u32,
|
||||
scl_stop_hold_time: u32,
|
||||
timeout: Option<u32>,
|
||||
timeout: BusTimeout,
|
||||
) -> Result<(), ConfigError> {
|
||||
unsafe {
|
||||
// divider
|
||||
@ -1017,13 +1106,13 @@ fn configure_clock(
|
||||
if #[cfg(esp32)] {
|
||||
register_block
|
||||
.to()
|
||||
.write(|w| w.time_out().bits(unwrap!(timeout)));
|
||||
.write(|w| w.time_out().bits(timeout.cycles()));
|
||||
} else {
|
||||
register_block
|
||||
.to()
|
||||
.write(|w| w.time_out_en().bit(timeout.is_some())
|
||||
.write(|w| w.time_out_en().bit(timeout.is_set())
|
||||
.time_out_value()
|
||||
.bits(timeout.unwrap_or(1) as _)
|
||||
.bits(timeout.cycles() as _)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1240,7 +1329,7 @@ impl Driver<'_> {
|
||||
&self,
|
||||
source_clk: HertzU32,
|
||||
bus_freq: HertzU32,
|
||||
timeout: Option<u32>,
|
||||
timeout: BusTimeout,
|
||||
) -> Result<(), ConfigError> {
|
||||
let source_clk = source_clk.raw();
|
||||
let bus_freq = bus_freq.raw();
|
||||
@ -1252,8 +1341,9 @@ impl Driver<'_> {
|
||||
let sda_sample = scl_high / 2;
|
||||
let setup = half_cycle;
|
||||
let hold = half_cycle;
|
||||
let timeout = timeout.map_or(Some(0xF_FFFF), |to_bus| {
|
||||
Some((to_bus * 2 * half_cycle).min(0xF_FFFF))
|
||||
let timeout = BusTimeout::BusCycles(match timeout {
|
||||
BusTimeout::Maximum => 0xF_FFFF,
|
||||
BusTimeout::BusCycles(cycles) => check_timeout(cycles * 2 * half_cycle, 0xF_FFFF)?,
|
||||
});
|
||||
|
||||
// SCL period. According to the TRM, we should always subtract 1 to SCL low
|
||||
@ -1321,7 +1411,7 @@ impl Driver<'_> {
|
||||
&self,
|
||||
source_clk: HertzU32,
|
||||
bus_freq: HertzU32,
|
||||
timeout: Option<u32>,
|
||||
timeout: BusTimeout,
|
||||
) -> Result<(), ConfigError> {
|
||||
let source_clk = source_clk.raw();
|
||||
let bus_freq = bus_freq.raw();
|
||||
@ -1352,6 +1442,11 @@ impl Driver<'_> {
|
||||
let scl_start_hold_time = hold - 1;
|
||||
let scl_stop_hold_time = hold;
|
||||
|
||||
let timeout = BusTimeout::BusCycles(match timeout {
|
||||
BusTimeout::Maximum => 0xFF_FFFF,
|
||||
BusTimeout::BusCycles(cycles) => check_timeout(cycles * 2 * half_cycle, 0xFF_FFFF)?,
|
||||
});
|
||||
|
||||
configure_clock(
|
||||
self.register_block(),
|
||||
0,
|
||||
@ -1364,7 +1459,7 @@ impl Driver<'_> {
|
||||
scl_stop_setup_time,
|
||||
scl_start_hold_time,
|
||||
scl_stop_hold_time,
|
||||
timeout.map(|to_bus| (to_bus * 2 * half_cycle).min(0xFF_FFFF)),
|
||||
timeout,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@ -1378,7 +1473,7 @@ impl Driver<'_> {
|
||||
&self,
|
||||
source_clk: HertzU32,
|
||||
bus_freq: HertzU32,
|
||||
timeout: Option<u32>,
|
||||
timeout: BusTimeout,
|
||||
) -> Result<(), ConfigError> {
|
||||
let source_clk = source_clk.raw();
|
||||
let bus_freq = bus_freq.raw();
|
||||
@ -1423,6 +1518,18 @@ impl Driver<'_> {
|
||||
let scl_start_hold_time = hold - 1;
|
||||
let scl_stop_hold_time = hold - 1;
|
||||
|
||||
let timeout = match timeout {
|
||||
BusTimeout::Maximum => BusTimeout::BusCycles(0x1F),
|
||||
BusTimeout::Disabled => BusTimeout::Disabled,
|
||||
BusTimeout::BusCycles(cycles) => {
|
||||
let to_peri = (cycles * 2 * half_cycle).max(1);
|
||||
let log2 = to_peri.ilog2();
|
||||
// Round up so that we don't shorten timeouts.
|
||||
let raw = if to_peri != 1 << log2 { log2 + 1 } else { log2 };
|
||||
BusTimeout::BusCycles(check_timeout(raw, 0x1F)?)
|
||||
}
|
||||
};
|
||||
|
||||
configure_clock(
|
||||
self.register_block(),
|
||||
clkm_div,
|
||||
@ -1435,13 +1542,7 @@ impl Driver<'_> {
|
||||
scl_stop_setup_time,
|
||||
scl_start_hold_time,
|
||||
scl_stop_hold_time,
|
||||
timeout.map(|to_bus| {
|
||||
let to_peri = (to_bus * 2 * half_cycle).max(1);
|
||||
let log2 = to_peri.ilog2();
|
||||
// Round up so that we don't shorten timeouts.
|
||||
let raw = if to_peri != 1 << log2 { log2 + 1 } else { log2 };
|
||||
raw.min(0x1F)
|
||||
}),
|
||||
timeout,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@ -1475,7 +1576,7 @@ impl Driver<'_> {
|
||||
/// - `cmd_iterator` is an iterator over the command registers.
|
||||
fn setup_write<'a, I>(
|
||||
&self,
|
||||
addr: u8,
|
||||
addr: I2cAddress,
|
||||
bytes: &[u8],
|
||||
start: bool,
|
||||
cmd_iterator: &mut I,
|
||||
@ -1509,10 +1610,14 @@ impl Driver<'_> {
|
||||
|
||||
if start {
|
||||
// Load address and R/W bit into FIFO
|
||||
write_fifo(
|
||||
self.register_block(),
|
||||
addr << 1 | OperationType::Write as u8,
|
||||
);
|
||||
match addr {
|
||||
I2cAddress::SevenBit(addr) => {
|
||||
write_fifo(
|
||||
self.register_block(),
|
||||
addr << 1 | OperationType::Write as u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -1527,7 +1632,7 @@ impl Driver<'_> {
|
||||
/// - `cmd_iterator` is an iterator over the command registers.
|
||||
fn setup_read<'a, I>(
|
||||
&self,
|
||||
addr: u8,
|
||||
addr: I2cAddress,
|
||||
buffer: &mut [u8],
|
||||
start: bool,
|
||||
will_continue: bool,
|
||||
@ -1588,7 +1693,11 @@ impl Driver<'_> {
|
||||
|
||||
if start {
|
||||
// Load address and R/W bit into FIFO
|
||||
write_fifo(self.register_block(), addr << 1 | OperationType::Read as u8);
|
||||
match addr {
|
||||
I2cAddress::SevenBit(addr) => {
|
||||
write_fifo(self.register_block(), addr << 1 | OperationType::Read as u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -2023,7 +2132,7 @@ impl Driver<'_> {
|
||||
|
||||
fn start_write_operation(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
bytes: &[u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2060,7 +2169,7 @@ impl Driver<'_> {
|
||||
/// - `cmd_iterator` is an iterator over the command registers.
|
||||
fn start_read_operation(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
buffer: &mut [u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2095,7 +2204,7 @@ impl Driver<'_> {
|
||||
/// - `cmd_iterator` is an iterator over the command registers.
|
||||
fn write_operation_blocking(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
bytes: &[u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2127,7 +2236,7 @@ impl Driver<'_> {
|
||||
/// - `cmd_iterator` is an iterator over the command registers.
|
||||
fn read_operation_blocking(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
buffer: &mut [u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2157,7 +2266,7 @@ impl Driver<'_> {
|
||||
/// - `cmd_iterator` is an iterator over the command registers.
|
||||
async fn write_operation(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
bytes: &[u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2189,7 +2298,7 @@ impl Driver<'_> {
|
||||
/// - `cmd_iterator` is an iterator over the command registers.
|
||||
async fn read_operation(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
buffer: &mut [u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2211,7 +2320,7 @@ impl Driver<'_> {
|
||||
|
||||
fn read_blocking(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
buffer: &mut [u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2233,7 +2342,7 @@ impl Driver<'_> {
|
||||
|
||||
fn write_blocking(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
buffer: &[u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2256,7 +2365,7 @@ impl Driver<'_> {
|
||||
|
||||
async fn read(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
buffer: &mut [u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2279,7 +2388,7 @@ impl Driver<'_> {
|
||||
|
||||
async fn write(
|
||||
&self,
|
||||
address: u8,
|
||||
address: I2cAddress,
|
||||
buffer: &[u8],
|
||||
start: bool,
|
||||
stop: bool,
|
||||
@ -2302,6 +2411,14 @@ impl Driver<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_timeout(v: u32, max: u32) -> Result<u32, ConfigError> {
|
||||
if v <= max {
|
||||
Ok(v)
|
||||
} else {
|
||||
Err(ConfigError::TimeoutInvalid)
|
||||
}
|
||||
}
|
||||
|
||||
/// Peripheral state for an I2C instance.
|
||||
#[doc(hidden)]
|
||||
#[non_exhaustive]
|
||||
|
Loading…
x
Reference in New Issue
Block a user