aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2024-07-01 06:38:33 +0000
committerGitHub <[email protected]>2024-07-01 06:38:33 +0000
commit2a38787a8375675a7c3b8d7d7dc4ca6505734bca (patch)
tree1439a57e9769809b74250685526db3e5f0c95e4e
parente0c0a618bd97f6a14075c5bb972c72bf2a6d6082 (diff)
parent96cdf9c9e046300b76969c39ac950d512e0184ce (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.rs38
-rw-r--r--examples/rp/src/bin/i2c_async_embassy.rs85
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
9use defmt::*;
10use embassy_rp::i2c::InterruptHandler;
11use {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
20enum UncomplicatedSensorId {
21 A(UncomplicatedSensorU8),
22 B(UncomplicatedSensorU16),
23}
24enum UncomplicatedSensorU8 {
25 First = 0x48,
26}
27enum UncomplicatedSensorU16 {
28 Other = 0x0049,
29}
30
31impl Into<u16> for UncomplicatedSensorU16 {
32 fn into(self) -> u16 {
33 self as u16
34 }
35}
36impl Into<u16> for UncomplicatedSensorU8 {
37 fn into(self) -> u16 {
38 0x48
39 }
40}
41impl 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
50embassy_rp::bind_interrupts!(struct Irqs {
51 I2C1_IRQ => InterruptHandler<embassy_rp::peripherals::I2C1>;
52});
53
54#[embassy_executor::main]
55async 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}