diff options
| author | Ulf Lilleengen <[email protected]> | 2025-06-11 05:09:08 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-06-11 05:09:08 +0000 |
| commit | 56572ef0adffd6258adc10fb424e37a8b4ddc19c (patch) | |
| tree | 5cacb71ceca12180e95031791c93c53e83bca307 /examples | |
| parent | 6186d111a5c150946ee5b7e9e68d987a38c1a463 (diff) | |
| parent | 4efb3b4f3f0178b98ea25f3957393ab6977c89de (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.rs | 149 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/i2c_shared.rs | 6 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/spe_adin1110_http_server.rs | 2 |
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 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::i2c::{Address, OwnAddresses, SlaveCommandKind}; | ||
| 8 | use embassy_stm32::mode::Async; | ||
| 9 | use embassy_stm32::time::Hertz; | ||
| 10 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 11 | use embassy_time::Timer; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | bind_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 | |||
| 21 | const DEV_ADDR: u8 = 0x42; | ||
| 22 | |||
| 23 | #[embassy_executor::task] | ||
| 24 | async 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] | ||
| 89 | async 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] | ||
| 126 | async 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]; | |||
| 25 | const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24]; | 25 | const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24]; |
| 26 | const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; | 26 | const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; |
| 27 | 27 | ||
| 28 | static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async>>>> = StaticCell::new(); | 28 | static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async, i2c::Master>>>> = StaticCell::new(); |
| 29 | 29 | ||
| 30 | bind_interrupts!(struct Irqs { | 30 | bind_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] |
| 36 | async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { | 36 | async 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] |
| 53 | async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { | 53 | async 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>; | |||
| 59 | pub type SpeInt = exti::ExtiInput<'static>; | 59 | pub type SpeInt = exti::ExtiInput<'static>; |
| 60 | pub type SpeRst = Output<'static>; | 60 | pub type SpeRst = Output<'static>; |
| 61 | pub type Adin1110T = ADIN1110<SpeSpiCs>; | 61 | pub type Adin1110T = ADIN1110<SpeSpiCs>; |
| 62 | pub type TempSensI2c = I2c<'static, Async>; | 62 | pub type TempSensI2c = I2c<'static, Async, i2c::Master>; |
| 63 | 63 | ||
| 64 | static TEMP: AtomicI32 = AtomicI32::new(0); | 64 | static TEMP: AtomicI32 = AtomicI32::new(0); |
| 65 | 65 | ||
