diff options
| author | Ulf Lilleengen <[email protected]> | 2024-07-01 06:38:33 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-07-01 06:38:33 +0000 |
| commit | 2a38787a8375675a7c3b8d7d7dc4ca6505734bca (patch) | |
| tree | 1439a57e9769809b74250685526db3e5f0c95e4e | |
| parent | e0c0a618bd97f6a14075c5bb972c72bf2a6d6082 (diff) | |
| parent | 96cdf9c9e046300b76969c39ac950d512e0184ce (diff) | |
Merge pull request #3130 from kkrolczyk/kk/i2c-addr-flexibility
rp/i2c: add address flexibility and example
| -rw-r--r-- | embassy-rp/src/i2c.rs | 38 | ||||
| -rw-r--r-- | examples/rp/src/bin/i2c_async_embassy.rs | 85 |
2 files changed, 101 insertions, 22 deletions
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 10ccca674..10d3c86b3 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs | |||
| @@ -313,25 +313,29 @@ impl<'d, T: Instance> I2c<'d, T, Async> { | |||
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | /// Read from address into buffer using DMA. | 315 | /// Read from address into buffer using DMA. |
| 316 | pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> { | 316 | pub async fn read_async(&mut self, addr: impl Into<u16>, buffer: &mut [u8]) -> Result<(), Error> { |
| 317 | Self::setup(addr)?; | 317 | Self::setup(addr.into())?; |
| 318 | self.read_async_internal(buffer, true, true).await | 318 | self.read_async_internal(buffer, true, true).await |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | /// Write to address from buffer using DMA. | 321 | /// Write to address from buffer using DMA. |
| 322 | pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> { | 322 | pub async fn write_async( |
| 323 | Self::setup(addr)?; | 323 | &mut self, |
| 324 | addr: impl Into<u16>, | ||
| 325 | bytes: impl IntoIterator<Item = u8>, | ||
| 326 | ) -> Result<(), Error> { | ||
| 327 | Self::setup(addr.into())?; | ||
| 324 | self.write_async_internal(bytes, true).await | 328 | self.write_async_internal(bytes, true).await |
| 325 | } | 329 | } |
| 326 | 330 | ||
| 327 | /// Write to address from bytes and read from address into buffer using DMA. | 331 | /// Write to address from bytes and read from address into buffer using DMA. |
| 328 | pub async fn write_read_async( | 332 | pub async fn write_read_async( |
| 329 | &mut self, | 333 | &mut self, |
| 330 | addr: u16, | 334 | addr: impl Into<u16>, |
| 331 | bytes: impl IntoIterator<Item = u8>, | 335 | bytes: impl IntoIterator<Item = u8>, |
| 332 | buffer: &mut [u8], | 336 | buffer: &mut [u8], |
| 333 | ) -> Result<(), Error> { | 337 | ) -> Result<(), Error> { |
| 334 | Self::setup(addr)?; | 338 | Self::setup(addr.into())?; |
| 335 | self.write_async_internal(bytes, false).await?; | 339 | self.write_async_internal(bytes, false).await?; |
| 336 | self.read_async_internal(buffer, true, true).await | 340 | self.read_async_internal(buffer, true, true).await |
| 337 | } | 341 | } |
| @@ -595,20 +599,20 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { | |||
| 595 | // ========================= | 599 | // ========================= |
| 596 | 600 | ||
| 597 | /// Read from address into buffer blocking caller until done. | 601 | /// Read from address into buffer blocking caller until done. |
| 598 | pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { | 602 | pub fn blocking_read(&mut self, address: impl Into<u16>, read: &mut [u8]) -> Result<(), Error> { |
| 599 | Self::setup(address.into())?; | 603 | Self::setup(address.into())?; |
| 600 | self.read_blocking_internal(read, true, true) | 604 | self.read_blocking_internal(read, true, true) |
| 601 | // Automatic Stop | 605 | // Automatic Stop |
| 602 | } | 606 | } |
| 603 | 607 | ||
| 604 | /// Write to address from buffer blocking caller until done. | 608 | /// Write to address from buffer blocking caller until done. |
| 605 | pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { | 609 | pub fn blocking_write(&mut self, address: impl Into<u16>, write: &[u8]) -> Result<(), Error> { |
| 606 | Self::setup(address.into())?; | 610 | Self::setup(address.into())?; |
| 607 | self.write_blocking_internal(write, true) | 611 | self.write_blocking_internal(write, true) |
| 608 | } | 612 | } |
| 609 | 613 | ||
| 610 | /// Write to address from bytes and read from address into buffer blocking caller until done. | 614 | /// Write to address from bytes and read from address into buffer blocking caller until done. |
| 611 | pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | 615 | pub fn blocking_write_read(&mut self, address: impl Into<u16>, write: &[u8], read: &mut [u8]) -> Result<(), Error> { |
| 612 | Self::setup(address.into())?; | 616 | Self::setup(address.into())?; |
| 613 | self.write_blocking_internal(write, false)?; | 617 | self.write_blocking_internal(write, false)?; |
| 614 | self.read_blocking_internal(read, true, true) | 618 | self.read_blocking_internal(read, true, true) |
| @@ -719,25 +723,15 @@ where | |||
| 719 | T: Instance + 'd, | 723 | T: Instance + 'd, |
| 720 | { | 724 | { |
| 721 | async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { | 725 | async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { |
| 722 | let addr: u16 = address.into(); | 726 | self.read_async(address, read).await |
| 723 | |||
| 724 | Self::setup(addr)?; | ||
| 725 | self.read_async_internal(read, false, true).await | ||
| 726 | } | 727 | } |
| 727 | 728 | ||
| 728 | async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { | 729 | async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { |
| 729 | let addr: u16 = address.into(); | 730 | self.write_async(address, write.iter().copied()).await |
| 730 | |||
| 731 | Self::setup(addr)?; | ||
| 732 | self.write_async_internal(write.iter().copied(), true).await | ||
| 733 | } | 731 | } |
| 734 | 732 | ||
| 735 | async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { | 733 | async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { |
| 736 | let addr: u16 = address.into(); | 734 | self.write_read_async(address, write.iter().copied(), read).await |
| 737 | |||
| 738 | Self::setup(addr)?; | ||
| 739 | self.write_async_internal(write.iter().cloned(), false).await?; | ||
| 740 | self.read_async_internal(read, true, true).await | ||
| 741 | } | 735 | } |
| 742 | 736 | ||
| 743 | async fn transaction( | 737 | async fn transaction( |
diff --git a/examples/rp/src/bin/i2c_async_embassy.rs b/examples/rp/src/bin/i2c_async_embassy.rs new file mode 100644 index 000000000..a65b71b9f --- /dev/null +++ b/examples/rp/src/bin/i2c_async_embassy.rs | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | //! This example shows how to communicate asynchronous using i2c with external chip. | ||
| 2 | //! | ||
| 3 | //! It's using embassy's functions directly instead of traits from embedded_hal_async::i2c::I2c. | ||
| 4 | //! While most of i2c devices are addressed using 7 bits, an extension allows 10 bits too. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_rp::i2c::InterruptHandler; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | // Our anonymous hypotetical temperature sensor could be: | ||
| 14 | // a 12-bit sensor, with 100ms startup time, range of -40*C - 125*C, and precision 0.25*C | ||
| 15 | // It requires no configuration or calibration, works with all i2c bus speeds, | ||
| 16 | // never stretches clock or does anything complicated. Replies with one u16. | ||
| 17 | // It requires only one write to take it out of suspend mode, and stays on. | ||
| 18 | // Often result would be just on 12 bits, but here we'll simplify it to 16. | ||
| 19 | |||
| 20 | enum UncomplicatedSensorId { | ||
| 21 | A(UncomplicatedSensorU8), | ||
| 22 | B(UncomplicatedSensorU16), | ||
| 23 | } | ||
| 24 | enum UncomplicatedSensorU8 { | ||
| 25 | First = 0x48, | ||
| 26 | } | ||
| 27 | enum UncomplicatedSensorU16 { | ||
| 28 | Other = 0x0049, | ||
| 29 | } | ||
| 30 | |||
| 31 | impl Into<u16> for UncomplicatedSensorU16 { | ||
| 32 | fn into(self) -> u16 { | ||
| 33 | self as u16 | ||
| 34 | } | ||
| 35 | } | ||
| 36 | impl Into<u16> for UncomplicatedSensorU8 { | ||
| 37 | fn into(self) -> u16 { | ||
| 38 | 0x48 | ||
| 39 | } | ||
| 40 | } | ||
| 41 | impl From<UncomplicatedSensorId> for u16 { | ||
| 42 | fn from(t: UncomplicatedSensorId) -> Self { | ||
| 43 | match t { | ||
| 44 | UncomplicatedSensorId::A(x) => x.into(), | ||
| 45 | UncomplicatedSensorId::B(x) => x.into(), | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | embassy_rp::bind_interrupts!(struct Irqs { | ||
| 51 | I2C1_IRQ => InterruptHandler<embassy_rp::peripherals::I2C1>; | ||
| 52 | }); | ||
| 53 | |||
| 54 | #[embassy_executor::main] | ||
| 55 | async fn main(_task_spawner: embassy_executor::Spawner) { | ||
| 56 | let p = embassy_rp::init(Default::default()); | ||
| 57 | let sda = p.PIN_14; | ||
| 58 | let scl = p.PIN_15; | ||
| 59 | let config = embassy_rp::i2c::Config::default(); | ||
| 60 | let mut bus = embassy_rp::i2c::I2c::new_async(p.I2C1, scl, sda, Irqs, config); | ||
| 61 | |||
| 62 | const WAKEYWAKEY: u16 = 0xBABE; | ||
| 63 | let mut result: [u8; 2] = [0, 0]; | ||
| 64 | // wait for sensors to initialize | ||
| 65 | embassy_time::Timer::after(embassy_time::Duration::from_millis(100)).await; | ||
| 66 | |||
| 67 | let _res_1 = bus | ||
| 68 | .write_async(UncomplicatedSensorU8::First, WAKEYWAKEY.to_be_bytes()) | ||
| 69 | .await; | ||
| 70 | let _res_2 = bus | ||
| 71 | .write_async(UncomplicatedSensorU16::Other, WAKEYWAKEY.to_be_bytes()) | ||
| 72 | .await; | ||
| 73 | |||
| 74 | loop { | ||
| 75 | let s1 = UncomplicatedSensorId::A(UncomplicatedSensorU8::First); | ||
| 76 | let s2 = UncomplicatedSensorId::B(UncomplicatedSensorU16::Other); | ||
| 77 | let sensors = [s1, s2]; | ||
| 78 | for sensor in sensors { | ||
| 79 | if bus.read_async(sensor, &mut result).await.is_ok() { | ||
| 80 | info!("Result {}", u16::from_be_bytes(result.into())); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | embassy_time::Timer::after(embassy_time::Duration::from_millis(200)).await; | ||
| 84 | } | ||
| 85 | } | ||
