aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorHybridChild <[email protected]>2025-11-12 21:55:20 +0100
committerHybridChild <[email protected]>2025-11-12 21:55:20 +0100
commit9e2a4161b32154f19963a222b3eb8f956b60d820 (patch)
tree258bb3d874202fe9f9bae73ac6ed743c9b862981 /tests
parent18a43908725366a230c990b8dee4a1d89fef11d0 (diff)
stm32/i2c: Fix v2 async transaction implementation
Diffstat (limited to 'tests')
-rw-r--r--tests/stm32/build.rs1
-rw-r--r--tests/stm32/src/bin/i2c_v2.rs238
-rw-r--r--tests/stm32/src/common.rs2
3 files changed, 210 insertions, 31 deletions
diff --git a/tests/stm32/build.rs b/tests/stm32/build.rs
index 556d77a20..34030c206 100644
--- a/tests/stm32/build.rs
+++ b/tests/stm32/build.rs
@@ -15,6 +15,7 @@ fn main() -> Result<(), Box<dyn Error>> {
15 feature = "stm32c071rb", // 24 kb 15 feature = "stm32c071rb", // 24 kb
16 feature = "stm32l073rz", // 20 kb 16 feature = "stm32l073rz", // 20 kb
17 feature = "stm32h503rb", // 32 kb 17 feature = "stm32h503rb", // 32 kb
18 feature = "stm32f072rb", // 16 kb - I2C v2 test with async too large for RAM
18 // no VTOR, so interrupts can't work when running from RAM 19 // no VTOR, so interrupts can't work when running from RAM
19 feature = "stm32f091rc", 20 feature = "stm32f091rc",
20 )) { 21 )) {
diff --git a/tests/stm32/src/bin/i2c_v2.rs b/tests/stm32/src/bin/i2c_v2.rs
index 9a23e28e1..087b8bbd9 100644
--- a/tests/stm32/src/bin/i2c_v2.rs
+++ b/tests/stm32/src/bin/i2c_v2.rs
@@ -7,7 +7,7 @@
7// - Connect to I2C slave device (e.g., Digilent Analog Discovery I2C slave, or EEPROM) 7// - Connect to I2C slave device (e.g., Digilent Analog Discovery I2C slave, or EEPROM)
8// - Default slave address: 0x50 8// - Default slave address: 0x50
9// - Pull-up resistors: 4.7kΩ on both SCL and SDA 9// - Pull-up resistors: 4.7kΩ on both SCL and SDA
10// - CN5 Pin 5 (PB8/SCL) and CN5 Pin 9 (PB9/SDA) 10// - CN5 Pin 10 (PB8/SCL) and CN5 Pin 9 (PB9/SDA)
11// 11//
12// Analog Discovery Setup: 12// Analog Discovery Setup:
13// - Configure as I2C Slave at address 0x50 13// - Configure as I2C Slave at address 0x50
@@ -21,9 +21,9 @@ mod common;
21use common::*; 21use common::*;
22use embassy_executor::Spawner; 22use embassy_executor::Spawner;
23use embassy_stm32::i2c::{Config, I2c, Master}; 23use embassy_stm32::i2c::{Config, I2c, Master};
24use embassy_stm32::mode::Blocking; 24use embassy_stm32::mode::{Async, Blocking};
25use embassy_stm32::time::Hertz; 25use embassy_stm32::time::Hertz;
26use embassy_time::block_for; 26use embassy_time::Timer;
27use embedded_hal_1::i2c::Operation; 27use embedded_hal_1::i2c::Operation;
28 28
29#[embassy_executor::main] 29#[embassy_executor::main]
@@ -38,42 +38,80 @@ async fn main(_spawner: Spawner) {
38 let mut config = Config::default(); 38 let mut config = Config::default();
39 config.frequency = Hertz(100_000); 39 config.frequency = Hertz(100_000);
40 40
41 let mut i2c = I2c::new_blocking(
42 i2c_peri.reborrow(),
43 scl.reborrow(),
44 sda.reborrow(),
45 config,
46 );
47
48 // I2C slave address for Analog Discovery or test EEPROM 41 // I2C slave address for Analog Discovery or test EEPROM
49 let slave_addr = 0x50u8; 42 let slave_addr = 0x50u8;
50 43
51 // Wait for slave device to be ready 44 // Wait for slave device to be ready
52 block_for(embassy_time::Duration::from_millis(100)); 45 Timer::after_millis(100).await;
46
47 // ========== BLOCKING TESTS ==========
48 info!("========== BLOCKING TRANSACTION TESTS ==========");
49 {
50 let mut i2c = I2c::new_blocking(
51 i2c_peri.reborrow(),
52 scl.reborrow(),
53 sda.reborrow(),
54 config,
55 );
56
57 info!("=== Test 1: Consecutive Writes (Should Merge) ===");
58 test_consecutive_writes_blocking(&mut i2c, slave_addr);
59
60 info!("=== Test 2: Consecutive Reads (Should Merge) ===");
61 test_consecutive_reads_blocking(&mut i2c, slave_addr);
62
63 info!("=== Test 3: Write then Read (RESTART) ===");
64 test_write_then_read_blocking(&mut i2c, slave_addr);
65
66 info!("=== Test 4: Read then Write (RESTART) ===");
67 test_read_then_write_blocking(&mut i2c, slave_addr);
68
69 info!("=== Test 5: Complex Mixed Sequence ===");
70 test_mixed_sequence_blocking(&mut i2c, slave_addr);
71
72 info!("=== Test 6: Single Operations ===");
73 test_single_operations_blocking(&mut i2c, slave_addr);
74
75 info!("Blocking tests OK");
76 }
77
78 Timer::after_millis(100).await;
79
80 // ========== ASYNC TESTS ==========
81 info!("========== ASYNC TRANSACTION TESTS (DMA) ==========");
82 {
83 let tx_dma = peri!(p, I2C_TX_DMA);
84 let rx_dma = peri!(p, I2C_RX_DMA);
85 let irq = irqs!(I2C);
53 86
54 info!("=== Test 1: Consecutive Writes (Should Merge) ==="); 87 let mut i2c = I2c::new(i2c_peri, scl, sda, irq, tx_dma, rx_dma, config);
55 test_consecutive_writes(&mut i2c, slave_addr);
56 88
57 info!("=== Test 2: Consecutive Reads (Should Merge) ==="); 89 info!("=== Test 1: Consecutive Writes (Should Merge) ===");
58 test_consecutive_reads(&mut i2c, slave_addr); 90 test_consecutive_writes_async(&mut i2c, slave_addr).await;
59 91
60 info!("=== Test 3: Write then Read (RESTART) ==="); 92 info!("=== Test 2: Consecutive Reads (Should Merge) ===");
61 test_write_then_read(&mut i2c, slave_addr); 93 test_consecutive_reads_async(&mut i2c, slave_addr).await;
62 94
63 info!("=== Test 4: Read then Write (RESTART) ==="); 95 info!("=== Test 3: Write then Read (RESTART) ===");
64 test_read_then_write(&mut i2c, slave_addr); 96 test_write_then_read_async(&mut i2c, slave_addr).await;
65 97
66 info!("=== Test 5: Complex Mixed Sequence ==="); 98 info!("=== Test 4: Read then Write (RESTART) ===");
67 test_mixed_sequence(&mut i2c, slave_addr); 99 test_read_then_write_async(&mut i2c, slave_addr).await;
68 100
69 info!("=== Test 6: Single Operations ==="); 101 info!("=== Test 5: Complex Mixed Sequence ===");
70 test_single_operations(&mut i2c, slave_addr); 102 test_mixed_sequence_async(&mut i2c, slave_addr).await;
71 103
72 info!("Test OK"); 104 info!("=== Test 6: Single Operations ===");
105 test_single_operations_async(&mut i2c, slave_addr).await;
106
107 info!("Async tests OK");
108 }
109
110 info!("All tests OK");
73 cortex_m::asm::bkpt(); 111 cortex_m::asm::bkpt();
74} 112}
75 113
76fn test_consecutive_writes(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { 114fn test_consecutive_writes_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
77 // Expected on bus: START, ADDR+W, data1, data2, data3, STOP 115 // Expected on bus: START, ADDR+W, data1, data2, data3, STOP
78 // NO intermediate RESTART/STOP between writes - they should be merged 116 // NO intermediate RESTART/STOP between writes - they should be merged
79 let data1 = [0x10, 0x11, 0x12]; 117 let data1 = [0x10, 0x11, 0x12];
@@ -95,7 +133,7 @@ fn test_consecutive_writes(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
95 } 133 }
96} 134}
97 135
98fn test_consecutive_reads(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { 136fn test_consecutive_reads_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
99 // Expected on bus: START, ADDR+R, data1, data2, data3, NACK, STOP 137 // Expected on bus: START, ADDR+R, data1, data2, data3, NACK, STOP
100 // NO intermediate RESTART/STOP between reads - they should be merged 138 // NO intermediate RESTART/STOP between reads - they should be merged
101 let mut buf1 = [0u8; 4]; 139 let mut buf1 = [0u8; 4];
@@ -122,7 +160,7 @@ fn test_consecutive_reads(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
122 } 160 }
123} 161}
124 162
125fn test_write_then_read(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { 163fn test_write_then_read_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
126 // Expected: START, ADDR+W, data, RESTART, ADDR+R, data, NACK, STOP 164 // Expected: START, ADDR+W, data, RESTART, ADDR+R, data, NACK, STOP
127 let write_data = [0xAA, 0xBB]; 165 let write_data = [0xAA, 0xBB];
128 let mut read_buf = [0u8; 4]; 166 let mut read_buf = [0u8; 4];
@@ -142,7 +180,7 @@ fn test_write_then_read(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
142 } 180 }
143} 181}
144 182
145fn test_read_then_write(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { 183fn test_read_then_write_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
146 // Expected: START, ADDR+R, data, NACK, RESTART, ADDR+W, data, STOP 184 // Expected: START, ADDR+R, data, NACK, RESTART, ADDR+W, data, STOP
147 let mut read_buf = [0u8; 3]; 185 let mut read_buf = [0u8; 3];
148 let write_data = [0xCC, 0xDD, 0xEE]; 186 let write_data = [0xCC, 0xDD, 0xEE];
@@ -162,7 +200,7 @@ fn test_read_then_write(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
162 } 200 }
163} 201}
164 202
165fn test_mixed_sequence(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { 203fn test_mixed_sequence_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
166 // Complex: W, W, R, R, W, R 204 // Complex: W, W, R, R, W, R
167 // Groups: [W,W] RESTART [R,R] RESTART [W] RESTART [R] 205 // Groups: [W,W] RESTART [R,R] RESTART [W] RESTART [R]
168 let w1 = [0x01, 0x02]; 206 let w1 = [0x01, 0x02];
@@ -193,7 +231,7 @@ fn test_mixed_sequence(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
193 } 231 }
194} 232}
195 233
196fn test_single_operations(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { 234fn test_single_operations_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
197 // Test single write 235 // Test single write
198 let write_data = [0xFF]; 236 let write_data = [0xFF];
199 let mut ops = [Operation::Write(&write_data)]; 237 let mut ops = [Operation::Write(&write_data)];
@@ -218,3 +256,143 @@ fn test_single_operations(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
218 } 256 }
219 } 257 }
220} 258}
259
260// ==================== ASYNC TEST FUNCTIONS ====================
261
262async fn test_consecutive_writes_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
263 let data1 = [0x10, 0x11, 0x12];
264 let data2 = [0x20, 0x21];
265 let data3 = [0x30, 0x31, 0x32, 0x33];
266
267 let mut ops = [
268 Operation::Write(&data1),
269 Operation::Write(&data2),
270 Operation::Write(&data3),
271 ];
272
273 match i2c.transaction(addr, &mut ops).await {
274 Ok(_) => info!("✓ Consecutive writes succeeded (merged 9 bytes)"),
275 Err(e) => {
276 error!("✗ Consecutive writes failed: {:?}", e);
277 defmt::panic!("Test failed: consecutive writes");
278 }
279 }
280}
281
282async fn test_consecutive_reads_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
283 let mut buf1 = [0u8; 4];
284 let mut buf2 = [0u8; 3];
285 let mut buf3 = [0u8; 2];
286
287 let mut ops = [
288 Operation::Read(&mut buf1),
289 Operation::Read(&mut buf2),
290 Operation::Read(&mut buf3),
291 ];
292
293 match i2c.transaction(addr, &mut ops).await {
294 Ok(_) => {
295 info!("✓ Consecutive reads succeeded (merged 9 bytes)");
296 info!(" buf1: {:02x}", buf1);
297 info!(" buf2: {:02x}", buf2);
298 info!(" buf3: {:02x}", buf3);
299 }
300 Err(e) => {
301 error!("✗ Consecutive reads failed: {:?}", e);
302 defmt::panic!("Test failed: consecutive reads");
303 }
304 }
305}
306
307async fn test_write_then_read_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
308 let write_data = [0xAA, 0xBB];
309 let mut read_buf = [0u8; 4];
310
311 let mut ops = [Operation::Write(&write_data), Operation::Read(&mut read_buf)];
312
313 match i2c.transaction(addr, &mut ops).await {
314 Ok(_) => {
315 info!("✓ Write-then-read succeeded with RESTART");
316 info!(" Written: {:02x}", write_data);
317 info!(" Read: {:02x}", read_buf);
318 }
319 Err(e) => {
320 error!("✗ Write-then-read failed: {:?}", e);
321 defmt::panic!("Test failed: write-then-read");
322 }
323 }
324}
325
326async fn test_read_then_write_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
327 let mut read_buf = [0u8; 3];
328 let write_data = [0xCC, 0xDD, 0xEE];
329
330 let mut ops = [Operation::Read(&mut read_buf), Operation::Write(&write_data)];
331
332 match i2c.transaction(addr, &mut ops).await {
333 Ok(_) => {
334 info!("✓ Read-then-write succeeded with RESTART");
335 info!(" Read: {:02x}", read_buf);
336 info!(" Written: {:02x}", write_data);
337 }
338 Err(e) => {
339 error!("✗ Read-then-write failed: {:?}", e);
340 defmt::panic!("Test failed: read-then-write");
341 }
342 }
343}
344
345async fn test_mixed_sequence_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
346 let w1 = [0x01, 0x02];
347 let w2 = [0x03, 0x04];
348 let mut r1 = [0u8; 2];
349 let mut r2 = [0u8; 2];
350 let w3 = [0x05];
351 let mut r3 = [0u8; 1];
352
353 let mut ops = [
354 Operation::Write(&w1),
355 Operation::Write(&w2),
356 Operation::Read(&mut r1),
357 Operation::Read(&mut r2),
358 Operation::Write(&w3),
359 Operation::Read(&mut r3),
360 ];
361
362 match i2c.transaction(addr, &mut ops).await {
363 Ok(_) => {
364 info!("✓ Mixed sequence succeeded");
365 info!(" Groups: [W4] RESTART [R4] RESTART [W1] RESTART [R1]");
366 }
367 Err(e) => {
368 error!("✗ Mixed sequence failed: {:?}", e);
369 defmt::panic!("Test failed: mixed sequence");
370 }
371 }
372}
373
374async fn test_single_operations_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
375 // Test single write
376 let write_data = [0xFF];
377 let mut ops = [Operation::Write(&write_data)];
378
379 match i2c.transaction(addr, &mut ops).await {
380 Ok(_) => info!("✓ Single write succeeded"),
381 Err(e) => {
382 error!("✗ Single write failed: {:?}", e);
383 defmt::panic!("Test failed: single write");
384 }
385 }
386
387 // Test single read
388 let mut read_buf = [0u8; 1];
389 let mut ops = [Operation::Read(&mut read_buf)];
390
391 match i2c.transaction(addr, &mut ops).await {
392 Ok(_) => info!("✓ Single read succeeded, data: 0x{:02x}", read_buf[0]),
393 Err(e) => {
394 error!("✗ Single read failed: {:?}", e);
395 defmt::panic!("Test failed: single read");
396 }
397 }
398}
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 07b667ade..de06cb267 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -109,7 +109,7 @@ define_peris!(
109define_peris!( 109define_peris!(
110 UART = USART1, UART_TX = PA9, UART_RX = PA10, UART_TX_DMA = DMA1_CH4, UART_RX_DMA = DMA1_CH5, 110 UART = USART1, UART_TX = PA9, UART_RX = PA10, UART_TX_DMA = DMA1_CH4, UART_RX_DMA = DMA1_CH5,
111 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2, 111 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2,
112 I2C = I2C1, I2C_SCL = PB8, I2C_SDA = PB9, 112 I2C = I2C1, I2C_SCL = PB8, I2C_SDA = PB9, I2C_TX_DMA = DMA1_CH6, I2C_RX_DMA = DMA1_CH7,
113 @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;}, 113 @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;},
114 @irq I2C = {I2C1 => embassy_stm32::i2c::EventInterruptHandler<embassy_stm32::peripherals::I2C1>, embassy_stm32::i2c::ErrorInterruptHandler<embassy_stm32::peripherals::I2C1>;}, 114 @irq I2C = {I2C1 => embassy_stm32::i2c::EventInterruptHandler<embassy_stm32::peripherals::I2C1>, embassy_stm32::i2c::ErrorInterruptHandler<embassy_stm32::peripherals::I2C1>;},
115); 115);