diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 211c4af44..a9b81dc36 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -31,6 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed features `psram-quad` and `psram-octal` - replaced by `psram` and the `ESP_HAL_CONFIG_PSRAM_MODE` (`quad`/`octal`) (#3001) +- I2C: Async functions are postfixed with `_async`, non-async functions are available in async-mode (#3056) + ### Fixed - `DmaDescriptor` is now `#[repr(C)]` (#2988) diff --git a/esp-hal/MIGRATING-0.23.md b/esp-hal/MIGRATING-0.23.md index 97696bb9a..acf5f4df8 100644 --- a/esp-hal/MIGRATING-0.23.md +++ b/esp-hal/MIGRATING-0.23.md @@ -200,3 +200,12 @@ The OutputOpenDrain driver has been removed. You can use `Output` instead with .with_drive_mode(DriveMode::OpenDrain), ); ``` + +## I2C Changes + +All async functions now include the `_async` postfix. Additionally the non-async functions are now available in async-mode. + +```diff +- let result = i2c.write_read(0x77, &[0xaa], &mut data).await; ++ let result = i2c.write_read_async(0x77, &[0xaa], &mut data).await; +``` diff --git a/esp-hal/src/i2c/master/mod.rs b/esp-hal/src/i2c/master/mod.rs index a754c223e..1530817cb 100644 --- a/esp-hal/src/i2c/master/mod.rs +++ b/esp-hal/src/i2c/master/mod.rs @@ -596,101 +596,6 @@ impl<'d, Dm: DriverMode> I2c<'d, Dm> { *guard = OutputConnection::connect_with_guard(pin, output); } -} - -impl<'d> I2c<'d, Blocking> { - /// Create a new I2C instance. - /// - /// # Errors - /// - /// A [`ConfigError`] variant will be returned if bus frequency or timeout - /// passed in config is invalid. - pub fn new( - i2c: impl Peripheral

+ 'd, - config: Config, - ) -> Result { - crate::into_mapped_ref!(i2c); - - let guard = PeripheralGuard::new(i2c.info().peripheral); - - let sda_pin = PinGuard::new_unconnected(i2c.info().sda_output); - let scl_pin = PinGuard::new_unconnected(i2c.info().scl_output); - - let i2c = I2c { - i2c, - phantom: PhantomData, - config, - guard, - sda_pin, - scl_pin, - }; - - i2c.driver().setup(&i2c.config)?; - - Ok(i2c) - } - - #[cfg_attr( - not(multi_core), - doc = "Registers an interrupt handler for the peripheral." - )] - #[cfg_attr( - multi_core, - doc = "Registers an interrupt handler for the peripheral on the current core." - )] - #[doc = ""] - /// Note that this will replace any previously registered interrupt - /// handlers. - /// - /// You can restore the default/unhandled interrupt handler by using - /// [crate::DEFAULT_INTERRUPT_HANDLER] - /// - /// # Panics - /// - /// Panics if passed interrupt handler is invalid (e.g. has priority - /// `None`) - #[instability::unstable] - pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { - self.i2c.info().set_interrupt_handler(handler); - } - - /// Listen for the given interrupts - #[instability::unstable] - pub fn listen(&mut self, interrupts: impl Into>) { - self.i2c.info().enable_listen(interrupts.into(), true) - } - - /// Unlisten the given interrupts - #[instability::unstable] - pub fn unlisten(&mut self, interrupts: impl Into>) { - self.i2c.info().enable_listen(interrupts.into(), false) - } - - /// Gets asserted interrupts - #[instability::unstable] - pub fn interrupts(&mut self) -> EnumSet { - self.i2c.info().interrupts() - } - - /// Resets asserted interrupts - #[instability::unstable] - pub fn clear_interrupts(&mut self, interrupts: EnumSet) { - self.i2c.info().clear_interrupts(interrupts) - } - - /// Configures the I2C peripheral to operate in asynchronous mode. - pub fn into_async(mut self) -> I2c<'d, Async> { - self.set_interrupt_handler(self.driver().info.async_handler); - - I2c { - i2c: self.i2c, - phantom: PhantomData, - config: self.config, - guard: self.guard, - sda_pin: self.sda_pin, - scl_pin: self.scl_pin, - } - } /// Writes bytes to slave with address `address` /// ```rust, no_run @@ -826,6 +731,101 @@ impl<'d> I2c<'d, Blocking> { } } +impl<'d> I2c<'d, Blocking> { + /// Create a new I2C instance. + /// + /// # Errors + /// + /// A [`ConfigError`] variant will be returned if bus frequency or timeout + /// passed in config is invalid. + pub fn new( + i2c: impl Peripheral

+ 'd, + config: Config, + ) -> Result { + crate::into_mapped_ref!(i2c); + + let guard = PeripheralGuard::new(i2c.info().peripheral); + + let sda_pin = PinGuard::new_unconnected(i2c.info().sda_output); + let scl_pin = PinGuard::new_unconnected(i2c.info().scl_output); + + let i2c = I2c { + i2c, + phantom: PhantomData, + config, + guard, + sda_pin, + scl_pin, + }; + + i2c.driver().setup(&i2c.config)?; + + Ok(i2c) + } + + #[cfg_attr( + not(multi_core), + doc = "Registers an interrupt handler for the peripheral." + )] + #[cfg_attr( + multi_core, + doc = "Registers an interrupt handler for the peripheral on the current core." + )] + #[doc = ""] + /// Note that this will replace any previously registered interrupt + /// handlers. + /// + /// You can restore the default/unhandled interrupt handler by using + /// [crate::DEFAULT_INTERRUPT_HANDLER] + /// + /// # Panics + /// + /// Panics if passed interrupt handler is invalid (e.g. has priority + /// `None`) + #[instability::unstable] + pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { + self.i2c.info().set_interrupt_handler(handler); + } + + /// Listen for the given interrupts + #[instability::unstable] + pub fn listen(&mut self, interrupts: impl Into>) { + self.i2c.info().enable_listen(interrupts.into(), true) + } + + /// Unlisten the given interrupts + #[instability::unstable] + pub fn unlisten(&mut self, interrupts: impl Into>) { + self.i2c.info().enable_listen(interrupts.into(), false) + } + + /// Gets asserted interrupts + #[instability::unstable] + pub fn interrupts(&mut self) -> EnumSet { + self.i2c.info().interrupts() + } + + /// Resets asserted interrupts + #[instability::unstable] + pub fn clear_interrupts(&mut self, interrupts: EnumSet) { + self.i2c.info().clear_interrupts(interrupts) + } + + /// Configures the I2C peripheral to operate in asynchronous mode. + pub fn into_async(mut self) -> I2c<'d, Async> { + self.set_interrupt_handler(self.driver().info.async_handler); + + I2c { + i2c: self.i2c, + phantom: PhantomData, + config: self.config, + guard: self.guard, + sda_pin: self.sda_pin, + scl_pin: self.scl_pin, + } + } +} + impl private::Sealed for I2c<'_, Blocking> {} impl InterruptConfigurable for I2c<'_, Blocking> { @@ -959,7 +959,7 @@ impl<'d> I2c<'d, Async> { } /// Writes bytes to slave with address `address` - pub async fn write>( + pub async fn write_async>( &mut self, address: A, buffer: &[u8], @@ -976,7 +976,7 @@ impl<'d> I2c<'d, Async> { /// /// The corresponding error variant from [`Error`] will be returned if the /// passed buffer has zero length. - pub async fn read>( + pub async fn read_async>( &mut self, address: A, buffer: &mut [u8], @@ -994,7 +994,7 @@ impl<'d> I2c<'d, Async> { /// /// The corresponding error variant from [`Error`] will be returned if the /// passed buffer has zero length. - pub async fn write_read>( + pub async fn write_read_async>( &mut self, address: A, write_buffer: &[u8], @@ -1039,7 +1039,7 @@ impl<'d> I2c<'d, Async> { /// /// The corresponding error variant from [`Error`] will be returned if the /// buffer passed to an [`Operation`] has zero length. - pub async fn transaction<'a, A: Into>( + pub async fn transaction_async<'a, A: Into>( &mut self, address: A, operations: impl IntoIterator>, diff --git a/qa-test/src/bin/embassy_i2c_bmp180_calibration_data.rs b/qa-test/src/bin/embassy_i2c_bmp180_calibration_data.rs index 38870dd8b..181e5988e 100644 --- a/qa-test/src/bin/embassy_i2c_bmp180_calibration_data.rs +++ b/qa-test/src/bin/embassy_i2c_bmp180_calibration_data.rs @@ -44,7 +44,9 @@ async fn main(_spawner: Spawner) { loop { let mut data = [0u8; 22]; - i2c.write_read(0x77, &[0xaa], &mut data).await.unwrap(); + i2c.write_read_async(0x77, &[0xaa], &mut data) + .await + .unwrap(); esp_println::println!("direct: {:02x?}", data); read_data(&mut i2c).await; Timer::after(Duration::from_millis(1000)).await;