aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2025-06-11 05:09:08 +0000
committerGitHub <[email protected]>2025-06-11 05:09:08 +0000
commit56572ef0adffd6258adc10fb424e37a8b4ddc19c (patch)
tree5cacb71ceca12180e95031791c93c53e83bca307 /examples
parent6186d111a5c150946ee5b7e9e68d987a38c1a463 (diff)
parent4efb3b4f3f0178b98ea25f3957393ab6977c89de (diff)
Merge pull request #2909 from jrmoulton/i2c-slave-new
stm32 i2c slave
Diffstat (limited to 'examples')
-rw-r--r--examples/stm32g4/src/bin/i2c_slave.rs149
-rw-r--r--examples/stm32h7/src/bin/i2c_shared.rs6
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs2
3 files changed, 153 insertions, 4 deletions
diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs
new file mode 100644
index 000000000..a723a0e18
--- /dev/null
+++ b/examples/stm32g4/src/bin/i2c_slave.rs
@@ -0,0 +1,149 @@
1//! This example shows how to use an stm32 as both a master and a slave.
2#![no_std]
3#![no_main]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Address, OwnAddresses, SlaveCommandKind};
8use embassy_stm32::mode::Async;
9use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, i2c, peripherals};
11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
16 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
17 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
18 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
19});
20
21const DEV_ADDR: u8 = 0x42;
22
23#[embassy_executor::task]
24async fn device_task(mut dev: i2c::I2c<'static, Async, i2c::MultiMaster>) -> ! {
25 info!("Device start");
26
27 let mut state = 0;
28
29 loop {
30 let mut buf = [0u8; 128];
31 match dev.listen().await {
32 Ok(i2c::SlaveCommand {
33 kind: SlaveCommandKind::Read,
34 address: Address::SevenBit(DEV_ADDR),
35 }) => match dev.respond_to_read(&[state]).await {
36 Ok(i2c::SendStatus::LeftoverBytes(x)) => info!("tried to write {} extra bytes", x),
37 Ok(i2c::SendStatus::Done) => {}
38 Err(e) => error!("error while responding {}", e),
39 },
40 Ok(i2c::SlaveCommand {
41 kind: SlaveCommandKind::Write,
42 address: Address::SevenBit(DEV_ADDR),
43 }) => match dev.respond_to_write(&mut buf).await {
44 Ok(len) => {
45 info!("Device received write: {}", buf[..len]);
46
47 if match buf[0] {
48 // Set the state
49 0xC2 => {
50 state = buf[1];
51 true
52 }
53 // Reset State
54 0xC8 => {
55 state = 0;
56 true
57 }
58 x => {
59 error!("Invalid Write Read {:x}", x);
60 false
61 }
62 } {
63 match dev.respond_to_read(&[state]).await {
64 Ok(read_status) => info!(
65 "This read is part of a write/read transaction. The response read status {}",
66 read_status
67 ),
68 Err(i2c::Error::Timeout) => {
69 info!("The device only performed a write and it not also do a read")
70 }
71 Err(e) => error!("error while responding {}", e),
72 }
73 }
74 }
75 Err(e) => error!("error while receiving {}", e),
76 },
77 Ok(i2c::SlaveCommand { address, .. }) => {
78 defmt::unreachable!(
79 "The slave matched address: {}, which it was not configured for",
80 address
81 );
82 }
83 Err(e) => error!("{}", e),
84 }
85 }
86}
87
88#[embassy_executor::task]
89async fn controller_task(mut con: i2c::I2c<'static, Async, i2c::Master>) {
90 info!("Controller start");
91
92 loop {
93 let mut resp_buff = [0u8; 1];
94 for i in 0..10 {
95 match con.write_read(DEV_ADDR, &[0xC2, i], &mut resp_buff).await {
96 Ok(_) => {
97 info!("write_read response: {}", resp_buff);
98 defmt::assert_eq!(resp_buff[0], i);
99 }
100 Err(e) => error!("Error writing {}", e),
101 }
102
103 Timer::after_millis(100).await;
104 }
105 match con.read(DEV_ADDR, &mut resp_buff).await {
106 Ok(_) => {
107 info!("read response: {}", resp_buff);
108 // assert that the state is the last index that was written
109 defmt::assert_eq!(resp_buff[0], 9);
110 }
111 Err(e) => error!("Error writing {}", e),
112 }
113 match con.write_read(DEV_ADDR, &[0xC8], &mut resp_buff).await {
114 Ok(_) => {
115 info!("write_read response: {}", resp_buff);
116 // assert that the state has been reset
117 defmt::assert_eq!(resp_buff[0], 0);
118 }
119 Err(e) => error!("Error writing {}", e),
120 }
121 Timer::after_millis(100).await;
122 }
123}
124
125#[embassy_executor::main]
126async fn main(spawner: Spawner) {
127 let p = embassy_stm32::init(Default::default());
128 info!("Hello World!");
129
130 let speed = Hertz::khz(400);
131 let config = i2c::Config::default();
132
133 let d_addr_config = i2c::SlaveAddrConfig {
134 addr: OwnAddresses::OA1(Address::SevenBit(DEV_ADDR)),
135 general_call: false,
136 };
137 let d_sda = p.PA8;
138 let d_scl = p.PA9;
139 let device = i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, speed, config)
140 .into_slave_multimaster(d_addr_config);
141
142 unwrap!(spawner.spawn(device_task(device)));
143
144 let c_sda = p.PB8;
145 let c_scl = p.PB7;
146 let controller = i2c::I2c::new(p.I2C1, c_sda, c_scl, Irqs, p.DMA1_CH3, p.DMA1_CH4, speed, config);
147
148 unwrap!(spawner.spawn(controller_task(controller)));
149}
diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs
index 136b91eeb..655ff901f 100644
--- a/examples/stm32h7/src/bin/i2c_shared.rs
+++ b/examples/stm32h7/src/bin/i2c_shared.rs
@@ -25,7 +25,7 @@ const SHTC3_WAKEUP: [u8; 2] = [0x35, 0x17];
25const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24]; 25const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24];
26const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; 26const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98];
27 27
28static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async>>>> = StaticCell::new(); 28static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async, i2c::Master>>>> = StaticCell::new();
29 29
30bind_interrupts!(struct Irqs { 30bind_interrupts!(struct Irqs {
31 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; 31 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
@@ -33,7 +33,7 @@ bind_interrupts!(struct Irqs {
33}); 33});
34 34
35#[embassy_executor::task] 35#[embassy_executor::task]
36async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { 36async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) {
37 let mut data = [0u8; 2]; 37 let mut data = [0u8; 2];
38 38
39 loop { 39 loop {
@@ -50,7 +50,7 @@ async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Asyn
50} 50}
51 51
52#[embassy_executor::task] 52#[embassy_executor::task]
53async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { 53async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) {
54 let mut data = [0u8; 6]; 54 let mut data = [0u8; 6];
55 55
56 loop { 56 loop {
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 354ac90b2..dc90a3b85 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -59,7 +59,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
59pub type SpeInt = exti::ExtiInput<'static>; 59pub type SpeInt = exti::ExtiInput<'static>;
60pub type SpeRst = Output<'static>; 60pub type SpeRst = Output<'static>;
61pub type Adin1110T = ADIN1110<SpeSpiCs>; 61pub type Adin1110T = ADIN1110<SpeSpiCs>;
62pub type TempSensI2c = I2c<'static, Async>; 62pub type TempSensI2c = I2c<'static, Async, i2c::Master>;
63 63
64static TEMP: AtomicI32 = AtomicI32::new(0); 64static TEMP: AtomicI32 = AtomicI32::new(0);
65 65