aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaleb Jamison <[email protected]>2023-09-10 02:05:58 -0400
committerDario Nieuwenhuis <[email protected]>2023-09-10 23:01:15 +0200
commit8201979d719f7f2647c7cb83b8e28bfc636b9d4a (patch)
tree3efb2b383bfefb9c10403df088457bc73e236f3b
parent2d9f50addc5f509f5549e69f594c382cebe739e6 (diff)
Add example, fix small bug in respond_and_fill
-rw-r--r--embassy-rp/src/i2c_slave.rs12
-rw-r--r--examples/rp/src/bin/i2c_slave.rs118
2 files changed, 130 insertions, 0 deletions
diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs
index a65250116..6136d69c6 100644
--- a/embassy-rp/src/i2c_slave.rs
+++ b/embassy-rp/src/i2c_slave.rs
@@ -287,6 +287,18 @@ impl<'d, T: Instance> I2cSlave<'d, T> {
287 } 287 }
288 } 288 }
289 289
290 /// Respond to a master read, then fill any remaining read bytes with `fill`
291 pub async fn respond_and_fill(&mut self, buffer: &[u8], fill: u8) -> Result<ReadStatus, Error> {
292 let resp_stat = self.respond_to_read(buffer).await?;
293
294 if resp_stat == ReadStatus::NeedMoreBytes {
295 self.respond_till_stop(fill).await?;
296 Ok(ReadStatus::Done)
297 } else {
298 Ok(resp_stat)
299 }
300 }
301
290 #[inline(always)] 302 #[inline(always)]
291 fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> { 303 fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> {
292 let p = T::regs(); 304 let p = T::regs();
diff --git a/examples/rp/src/bin/i2c_slave.rs b/examples/rp/src/bin/i2c_slave.rs
new file mode 100644
index 000000000..7de300fb8
--- /dev/null
+++ b/examples/rp/src/bin/i2c_slave.rs
@@ -0,0 +1,118 @@
1//! This example shows how to use the 2040 as an i2c slave.
2#![no_std]
3#![no_main]
4#![feature(type_alias_impl_trait)]
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_rp::peripherals::{I2C0, I2C1};
9use embassy_rp::{bind_interrupts, i2c, i2c_slave};
10use embassy_time::{Duration, Timer};
11use embedded_hal_async::i2c::I2c;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 I2C0_IRQ => i2c::InterruptHandler<I2C0>;
16 I2C1_IRQ => i2c::InterruptHandler<I2C1>;
17});
18
19const DEV_ADDR: u8 = 0x42;
20
21#[embassy_executor::task]
22async fn device_task(mut dev: i2c_slave::I2cSlave<'static, I2C1>) -> ! {
23 info!("Device start");
24
25 let mut state = 0;
26
27 loop {
28 let mut buf = [0u8; 128];
29 match dev.listen(&mut buf).await {
30 Ok(i2c_slave::Command::GeneralCall(len)) => info!("Device recieved general call write: {}", buf[..len]),
31 Ok(i2c_slave::Command::Read) => loop {
32 match dev.respond_to_read(&[state]).await {
33 Ok(x) => match x {
34 i2c_slave::ReadStatus::Done => break,
35 i2c_slave::ReadStatus::NeedMoreBytes => (),
36 i2c_slave::ReadStatus::LeftoverBytes(x) => {
37 info!("tried to write {} extra bytes", x);
38 break;
39 }
40 },
41 Err(e) => error!("error while responding {}", e),
42 }
43 },
44 Ok(i2c_slave::Command::Write(len)) => info!("Device recieved write: {}", buf[..len]),
45 Ok(i2c_slave::Command::WriteRead(len)) => {
46 info!("device recieved write read: {:x}", buf[..len]);
47 match buf[0] {
48 // Set the state
49 0xC2 => {
50 state = buf[1];
51 match dev.respond_and_fill(&[state], 0x00).await {
52 Ok(read_status) => info!("response read status {}", read_status),
53 Err(e) => error!("error while responding {}", e),
54 }
55 }
56 // Reset State
57 0xC8 => {
58 state = 0;
59 match dev.respond_and_fill(&[state], 0x00).await {
60 Ok(read_status) => info!("response read status {}", read_status),
61 Err(e) => error!("error while responding {}", e),
62 }
63 }
64 x => error!("Invalid Write Read {:x}", x),
65 }
66 }
67 Err(e) => error!("{}", e),
68 }
69 }
70}
71
72#[embassy_executor::task]
73async fn controller_task(mut con: i2c::I2c<'static, I2C0, i2c::Async>) {
74 info!("Controller start");
75
76 loop {
77 let mut resp_buff = [0u8; 2];
78 for i in 0..10 {
79 match con.write_read(DEV_ADDR, &[0xC2, i], &mut resp_buff).await {
80 Ok(_) => info!("write_read response: {}", resp_buff),
81 Err(e) => error!("Error writing {}", e),
82 }
83
84 Timer::after(Duration::from_millis(100)).await;
85 }
86 match con.read(DEV_ADDR, &mut resp_buff).await {
87 Ok(_) => info!("read response: {}", resp_buff),
88 Err(e) => error!("Error writing {}", e),
89 }
90 match con.write_read(DEV_ADDR, &[0xC8], &mut resp_buff).await {
91 Ok(_) => info!("write_read response: {}", resp_buff),
92 Err(e) => error!("Error writing {}", e),
93 }
94 Timer::after(Duration::from_millis(100)).await;
95 }
96}
97
98#[embassy_executor::main]
99async fn main(spawner: Spawner) {
100 let p = embassy_rp::init(Default::default());
101 info!("Hello World!");
102
103 let d_sda = p.PIN_3;
104 let d_scl = p.PIN_2;
105 let mut config = i2c_slave::Config::default();
106 config.addr = DEV_ADDR as u16;
107 let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config);
108
109 unwrap!(spawner.spawn(device_task(device)));
110
111 let c_sda = p.PIN_1;
112 let c_scl = p.PIN_0;
113 let mut config = i2c::Config::default();
114 config.frequency = 5_000;
115 let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config);
116
117 unwrap!(spawner.spawn(controller_task(controller)));
118}