diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-11-24 23:08:47 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-11-24 23:08:47 +0000 |
| commit | f5c9e3baa6615928f948cf9ae4c03123d2d84cbc (patch) | |
| tree | d753f3aa382534b952c23d39ece6821146439105 /examples | |
| parent | 47bac9df70492cd9c1b1f8617c1abc1209ee3338 (diff) | |
| parent | 3efc3eee5700d2a39e397f1b1b821885301c0862 (diff) | |
Merge pull request #2200 from barnabywalters/asynci2cv1
Implemented async I2C for v1
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/stm32f4/src/bin/i2c.rs | 3 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/i2c_async.rs | 62 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/i2c_comparison.rs | 135 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/i2c.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/camera.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/i2c.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/i2c.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/i2c_blocking_async.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/i2c_dma.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/spe_adin1110_http_server.rs | 3 |
10 files changed, 213 insertions, 8 deletions
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs index 032bd97ee..4f4adde28 100644 --- a/examples/stm32f4/src/bin/i2c.rs +++ b/examples/stm32f4/src/bin/i2c.rs | |||
| @@ -14,7 +14,8 @@ const ADDRESS: u8 = 0x5F; | |||
| 14 | const WHOAMI: u8 = 0x0F; | 14 | const WHOAMI: u8 = 0x0F; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | 16 | bind_interrupts!(struct Irqs { |
| 17 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | 17 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; |
| 18 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 18 | }); | 19 | }); |
| 19 | 20 | ||
| 20 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
diff --git a/examples/stm32f4/src/bin/i2c_async.rs b/examples/stm32f4/src/bin/i2c_async.rs new file mode 100644 index 000000000..9f59e4d41 --- /dev/null +++ b/examples/stm32f4/src/bin/i2c_async.rs | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | // Example originally designed for stm32f411ceu6 reading an A1454 hall effect sensor on I2C1 | ||
| 6 | // DMA peripherals changed to compile for stm32f429zi, for the CI. | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_stm32::i2c::I2c; | ||
| 11 | use embassy_stm32::time::Hertz; | ||
| 12 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | const ADDRESS: u8 = 96; | ||
| 16 | |||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; | ||
| 19 | I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>; | ||
| 20 | }); | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(_spawner: Spawner) { | ||
| 24 | info!("Hello world!"); | ||
| 25 | let p = embassy_stm32::init(Default::default()); | ||
| 26 | |||
| 27 | let mut i2c = I2c::new( | ||
| 28 | p.I2C1, | ||
| 29 | p.PB8, | ||
| 30 | p.PB7, | ||
| 31 | Irqs, | ||
| 32 | p.DMA1_CH6, | ||
| 33 | p.DMA1_CH0, | ||
| 34 | Hertz(100_000), | ||
| 35 | Default::default(), | ||
| 36 | ); | ||
| 37 | |||
| 38 | loop { | ||
| 39 | let a1454_read_sensor_command = [0x1F]; | ||
| 40 | let mut sensor_data_buffer: [u8; 4] = [0, 0, 0, 0]; | ||
| 41 | |||
| 42 | match i2c | ||
| 43 | .write_read(ADDRESS, &a1454_read_sensor_command, &mut sensor_data_buffer) | ||
| 44 | .await | ||
| 45 | { | ||
| 46 | Ok(()) => { | ||
| 47 | // Convert 12-bit signed integer into 16-bit signed integer. | ||
| 48 | // Is the 12 bit number negative? | ||
| 49 | if (sensor_data_buffer[2] & 0b00001000) == 0b0001000 { | ||
| 50 | sensor_data_buffer[2] = sensor_data_buffer[2] | 0b11110000; | ||
| 51 | } | ||
| 52 | |||
| 53 | let mut sensor_value_raw: u16 = sensor_data_buffer[3].into(); | ||
| 54 | sensor_value_raw |= (sensor_data_buffer[2] as u16) << 8; | ||
| 55 | let sensor_value: u16 = sensor_value_raw.into(); | ||
| 56 | let sensor_value = sensor_value as i16; | ||
| 57 | info!("Data: {}", sensor_value); | ||
| 58 | } | ||
| 59 | Err(e) => error!("I2C Error during read: {:?}", e), | ||
| 60 | } | ||
| 61 | } | ||
| 62 | } | ||
diff --git a/examples/stm32f4/src/bin/i2c_comparison.rs b/examples/stm32f4/src/bin/i2c_comparison.rs new file mode 100644 index 000000000..6d23c0ed8 --- /dev/null +++ b/examples/stm32f4/src/bin/i2c_comparison.rs | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | // Example originally designed for stm32f411ceu6 with three A1454 hall effect sensors, connected to I2C1, 2 and 3 | ||
| 6 | // on the pins referenced in the peripheral definitions. | ||
| 7 | // Pins and DMA peripherals changed to compile for stm32f429zi, to work with the CI. | ||
| 8 | // MUST be compiled in release mode to see actual performance, otherwise the async transactions take 2x | ||
| 9 | // as long to complete as the blocking ones! | ||
| 10 | |||
| 11 | use defmt::*; | ||
| 12 | use embassy_executor::Spawner; | ||
| 13 | use embassy_stm32::i2c::I2c; | ||
| 14 | use embassy_stm32::time::Hertz; | ||
| 15 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 16 | use embassy_time::Instant; | ||
| 17 | use futures::future::try_join3; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | |||
| 20 | const ADDRESS: u8 = 96; | ||
| 21 | |||
| 22 | bind_interrupts!(struct Irqs { | ||
| 23 | I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; | ||
| 24 | I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>; | ||
| 25 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; | ||
| 26 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 27 | I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>; | ||
| 28 | I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>; | ||
| 29 | }); | ||
| 30 | |||
| 31 | /// Convert 12-bit signed integer within a 4 byte long buffer into 16-bit signed integer. | ||
| 32 | fn a1454_buf_to_i16(buffer: &[u8; 4]) -> i16 { | ||
| 33 | let lower = buffer[3]; | ||
| 34 | let mut upper = buffer[2]; | ||
| 35 | // Fill in additional 1s if the 12 bit number is negative. | ||
| 36 | if (upper & 0b00001000) == 0b0001000 { | ||
| 37 | upper = upper | 0b11110000; | ||
| 38 | } | ||
| 39 | |||
| 40 | let mut sensor_value_raw: u16 = lower.into(); | ||
| 41 | sensor_value_raw |= (upper as u16) << 8; | ||
| 42 | let sensor_value: u16 = sensor_value_raw.into(); | ||
| 43 | let sensor_value = sensor_value as i16; | ||
| 44 | sensor_value | ||
| 45 | } | ||
| 46 | |||
| 47 | #[embassy_executor::main] | ||
| 48 | async fn main(_spawner: Spawner) { | ||
| 49 | info!("Setting up peripherals."); | ||
| 50 | let p = embassy_stm32::init(Default::default()); | ||
| 51 | |||
| 52 | let mut i2c1 = I2c::new( | ||
| 53 | p.I2C1, | ||
| 54 | p.PB8, | ||
| 55 | p.PB7, | ||
| 56 | Irqs, | ||
| 57 | p.DMA1_CH6, | ||
| 58 | p.DMA1_CH0, | ||
| 59 | Hertz(100_000), | ||
| 60 | Default::default(), | ||
| 61 | ); | ||
| 62 | |||
| 63 | let mut i2c2 = I2c::new( | ||
| 64 | p.I2C2, | ||
| 65 | p.PB10, | ||
| 66 | p.PB11, | ||
| 67 | Irqs, | ||
| 68 | p.DMA1_CH7, | ||
| 69 | p.DMA1_CH3, | ||
| 70 | Hertz(100_000), | ||
| 71 | Default::default(), | ||
| 72 | ); | ||
| 73 | |||
| 74 | let mut i2c3 = I2c::new( | ||
| 75 | p.I2C3, | ||
| 76 | p.PA8, | ||
| 77 | p.PC9, | ||
| 78 | Irqs, | ||
| 79 | p.DMA1_CH4, | ||
| 80 | p.DMA1_CH2, | ||
| 81 | Hertz(100_000), | ||
| 82 | Default::default(), | ||
| 83 | ); | ||
| 84 | |||
| 85 | let a1454_read_sensor_command = [0x1F]; | ||
| 86 | let mut i2c1_buffer: [u8; 4] = [0, 0, 0, 0]; | ||
| 87 | let mut i2c2_buffer: [u8; 4] = [0, 0, 0, 0]; | ||
| 88 | let mut i2c3_buffer: [u8; 4] = [0, 0, 0, 0]; | ||
| 89 | loop { | ||
| 90 | // Blocking reads one after the other. Completes in about 2000us. | ||
| 91 | let blocking_read_start_us = Instant::now().as_micros(); | ||
| 92 | match i2c1.blocking_write_read(ADDRESS, &a1454_read_sensor_command, &mut i2c1_buffer) { | ||
| 93 | Ok(()) => {} | ||
| 94 | Err(e) => error!("I2C Error: {:?}", e), | ||
| 95 | } | ||
| 96 | match i2c2.blocking_write_read(ADDRESS, &a1454_read_sensor_command, &mut i2c2_buffer) { | ||
| 97 | Ok(()) => {} | ||
| 98 | Err(e) => error!("I2C Error: {:?}", e), | ||
| 99 | } | ||
| 100 | match i2c3.blocking_write_read(ADDRESS, &a1454_read_sensor_command, &mut i2c3_buffer) { | ||
| 101 | Ok(()) => {} | ||
| 102 | Err(e) => error!("I2C Error: {:?}", e), | ||
| 103 | } | ||
| 104 | let blocking_read_total_us = Instant::now().as_micros() - blocking_read_start_us; | ||
| 105 | info!( | ||
| 106 | "Blocking reads completed in {}us: i2c1: {} i2c2: {} i2c3: {}", | ||
| 107 | blocking_read_total_us, | ||
| 108 | a1454_buf_to_i16(&i2c1_buffer), | ||
| 109 | a1454_buf_to_i16(&i2c2_buffer), | ||
| 110 | a1454_buf_to_i16(&i2c3_buffer) | ||
| 111 | ); | ||
| 112 | |||
| 113 | // Async reads overlapping. Completes in about 1000us. | ||
| 114 | let async_read_start_us = Instant::now().as_micros(); | ||
| 115 | |||
| 116 | let i2c1_result = i2c1.write_read(ADDRESS, &a1454_read_sensor_command, &mut i2c1_buffer); | ||
| 117 | let i2c2_result = i2c2.write_read(ADDRESS, &a1454_read_sensor_command, &mut i2c2_buffer); | ||
| 118 | let i2c3_result = i2c3.write_read(ADDRESS, &a1454_read_sensor_command, &mut i2c3_buffer); | ||
| 119 | |||
| 120 | // Wait for all three transactions to finish, or any one of them to fail. | ||
| 121 | match try_join3(i2c1_result, i2c2_result, i2c3_result).await { | ||
| 122 | Ok(_) => { | ||
| 123 | let async_read_total_us = Instant::now().as_micros() - async_read_start_us; | ||
| 124 | info!( | ||
| 125 | "Async reads completed in {}us: i2c1: {} i2c2: {} i2c3: {}", | ||
| 126 | async_read_total_us, | ||
| 127 | a1454_buf_to_i16(&i2c1_buffer), | ||
| 128 | a1454_buf_to_i16(&i2c2_buffer), | ||
| 129 | a1454_buf_to_i16(&i2c3_buffer) | ||
| 130 | ); | ||
| 131 | } | ||
| 132 | Err(e) => error!("I2C Error during async write-read: {}", e), | ||
| 133 | }; | ||
| 134 | } | ||
| 135 | } | ||
diff --git a/examples/stm32h5/src/bin/i2c.rs b/examples/stm32h5/src/bin/i2c.rs index 8b1662f39..31783a2bf 100644 --- a/examples/stm32h5/src/bin/i2c.rs +++ b/examples/stm32h5/src/bin/i2c.rs | |||
| @@ -13,7 +13,8 @@ const ADDRESS: u8 = 0x5F; | |||
| 13 | const WHOAMI: u8 = 0x0F; | 13 | const WHOAMI: u8 = 0x0F; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
| 16 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | 16 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; |
| 17 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 17 | }); | 18 | }); |
| 18 | 19 | ||
| 19 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 23ece1c38..489fb03dd 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs | |||
| @@ -19,7 +19,8 @@ const HEIGHT: usize = 100; | |||
| 19 | static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2]; | 19 | static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2]; |
| 20 | 20 | ||
| 21 | bind_interrupts!(struct Irqs { | 21 | bind_interrupts!(struct Irqs { |
| 22 | I2C1_EV => i2c::InterruptHandler<peripherals::I2C1>; | 22 | I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; |
| 23 | I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>; | ||
| 23 | DCMI => dcmi::InterruptHandler<peripherals::DCMI>; | 24 | DCMI => dcmi::InterruptHandler<peripherals::DCMI>; |
| 24 | }); | 25 | }); |
| 25 | 26 | ||
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs index 9aa0ca08b..aea21ec6f 100644 --- a/examples/stm32h7/src/bin/i2c.rs +++ b/examples/stm32h7/src/bin/i2c.rs | |||
| @@ -13,7 +13,8 @@ const ADDRESS: u8 = 0x5F; | |||
| 13 | const WHOAMI: u8 = 0x0F; | 13 | const WHOAMI: u8 = 0x0F; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
| 16 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | 16 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; |
| 17 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 17 | }); | 18 | }); |
| 18 | 19 | ||
| 19 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
diff --git a/examples/stm32l4/src/bin/i2c.rs b/examples/stm32l4/src/bin/i2c.rs index d0060d20c..07dc12e8c 100644 --- a/examples/stm32l4/src/bin/i2c.rs +++ b/examples/stm32l4/src/bin/i2c.rs | |||
| @@ -14,7 +14,8 @@ const ADDRESS: u8 = 0x5F; | |||
| 14 | const WHOAMI: u8 = 0x0F; | 14 | const WHOAMI: u8 = 0x0F; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | 16 | bind_interrupts!(struct Irqs { |
| 17 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | 17 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; |
| 18 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 18 | }); | 19 | }); |
| 19 | 20 | ||
| 20 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
diff --git a/examples/stm32l4/src/bin/i2c_blocking_async.rs b/examples/stm32l4/src/bin/i2c_blocking_async.rs index eca59087b..60a4e2eb3 100644 --- a/examples/stm32l4/src/bin/i2c_blocking_async.rs +++ b/examples/stm32l4/src/bin/i2c_blocking_async.rs | |||
| @@ -16,7 +16,8 @@ const ADDRESS: u8 = 0x5F; | |||
| 16 | const WHOAMI: u8 = 0x0F; | 16 | const WHOAMI: u8 = 0x0F; |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | 18 | bind_interrupts!(struct Irqs { |
| 19 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | 19 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; |
| 20 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 20 | }); | 21 | }); |
| 21 | 22 | ||
| 22 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
diff --git a/examples/stm32l4/src/bin/i2c_dma.rs b/examples/stm32l4/src/bin/i2c_dma.rs index cf6f3da67..4c2c224a6 100644 --- a/examples/stm32l4/src/bin/i2c_dma.rs +++ b/examples/stm32l4/src/bin/i2c_dma.rs | |||
| @@ -13,7 +13,8 @@ const ADDRESS: u8 = 0x5F; | |||
| 13 | const WHOAMI: u8 = 0x0F; | 13 | const WHOAMI: u8 = 0x0F; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
| 16 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | 16 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; |
| 17 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 17 | }); | 18 | }); |
| 18 | 19 | ||
| 19 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 3a7e5370c..4826e0bed 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs | |||
| @@ -40,7 +40,8 @@ use static_cell::make_static; | |||
| 40 | use {embassy_stm32 as hal, panic_probe as _}; | 40 | use {embassy_stm32 as hal, panic_probe as _}; |
| 41 | 41 | ||
| 42 | bind_interrupts!(struct Irqs { | 42 | bind_interrupts!(struct Irqs { |
| 43 | I2C3_EV => i2c::InterruptHandler<peripherals::I2C3>; | 43 | I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>; |
| 44 | I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>; | ||
| 44 | RNG => rng::InterruptHandler<peripherals::RNG>; | 45 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 45 | }); | 46 | }); |
| 46 | 47 | ||
