diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 37b33fe9..2844d007 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -25,7 +25,6 @@ pub enum Error { BufferNotEmpty, BufferNotFilled, BufferSize, - OkBufferTransferred, // not really an error, but signalling that the slave does nack the last byte } pub(crate) mod sealed { diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index b4ff7e89..6d6b60d3 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -46,11 +46,10 @@ impl interrupt::typelevel::Handler for InterruptHandl regs.icr().modify(|w| { w.set_berrcf(true); }); - state_m.errors += 1; - state_m.result = Err(Error::Bus); + state_m.result = Some(Error::Bus); } else if isr.arlo() { regs.icr().write(|w| w.set_arlocf(true)); - state_m.result = Err(Error::Arbitration); + state_m.result = Some(Error::Arbitration); } else if isr.nackf() { regs.icr().write(|w| w.set_nackcf(true)); // Make one extra loop to wait on the stop condition @@ -58,16 +57,8 @@ impl interrupt::typelevel::Handler for InterruptHandl // send the next byte to the master, or NACK in case of error, then end transaction match state_m.read_byte() { Ok(b) => regs.txdr().write(|w| w.set_txdata(b)), - Err(Error::OkBufferTransferred) => { - state_m.result = Ok(()); - // Send a NACK, set nbytes to clear tcr flag - regs.cr2().modify(|w| { - w.set_nack(true); - }) - } Err(e) => { - state_m.result = Err(e); - state_m.errors += 1; + state_m.result = Some(e); // Send a NACK, set nbytes to clear tcr flag regs.cr2().modify(|w| { w.set_nack(true); @@ -80,8 +71,7 @@ impl interrupt::typelevel::Handler for InterruptHandl match state_m.write_byte(b) { Ok(()) => (), Err(e) => { - state_m.result = Err(e); - state_m.errors += 1; + state_m.result = Some(e); // Send a NACK, set nbytes to clear tcr flag regs.cr2().modify(|w| { w.set_nack(true); @@ -104,6 +94,8 @@ impl interrupt::typelevel::Handler for InterruptHandl // handle the slave is addressed case, first step in the transaction state_m.current_address = isr.addcode(); state_m.dir = isr.dir(); + state_m.result = None; + if state_m.dir == vals::Dir::READ { // Set the nbytes START and prepare to receive bytes into `buffer`. regs.cr2().modify(|w| { @@ -202,13 +194,12 @@ impl State { } struct I2cStateMachine { buffers: [[I2cBuffer; 2]; 2], - result: Result<(), Error>, + result: Option, slave_mode: bool, - dir: vals::Dir, address1: u16, - current_address: u8, - errors: u32, ready: bool, + current_address: u8, + dir: vals::Dir, } impl I2cStateMachine { pub(crate) const fn new() -> Self { @@ -218,12 +209,11 @@ impl I2cStateMachine { [I2cBuffer::new(), I2cBuffer::new()], [I2cBuffer::new(), I2cBuffer::new()], ], - result: Ok(()), + result: None, slave_mode: false, - dir: vals::Dir::READ, address1: 0, current_address: 0, - errors: 0, + dir: vals::Dir::READ, ready: false, } } @@ -290,7 +280,7 @@ impl I2cBuffer { Ok(b) } else { self.size = 0; // mark buffer empty - Err(Error::OkBufferTransferred) // not really an error, but to signal slave should send NACK + Err(Error::Overrun) // too many bytes asked } } /// master write slave read scenario. Master can write until buffer full @@ -1080,31 +1070,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } /// Prepare write data to master (master_read_slave_write) before transaction starts - /// Only possible if the buffer is empty, other wise error BufferNotEmpty error + /// Will return buffersize error in case the incoming buffer is too big pub fn slave_write_buffer(&mut self, buffer: &[u8], address_type: AddressType) -> Result<(), super::Error> { T::state().mutex.lock(|f| { let mut state_m = f.borrow_mut(); let buf = &mut state_m.buffers[address_type as usize][vals::Dir::READ as usize]; - if buf.size > 0 { - return Err(Error::BufferNotEmpty); - }; buf.from_buffer(buffer) }) } /// Read data from master (master_write_slave_read) after transaction is finished - /// Only possible if the buffer is not empty, other wise error BufferNotFilled error + /// Will fail if the size if the incoming buffer is smaller than the received bytes pub fn slave_read_buffer(&mut self, buffer: &mut [u8], address_type: AddressType) -> Result<(), super::Error> { T::state().mutex.lock(|f| { let mut state_m = f.borrow_mut(); let buf = &mut state_m.buffers[address_type as usize][vals::Dir::WRITE as usize]; - if buf.size == 0 { - return Err(Error::BufferEmpty); - }; buf.to_buffer(buffer) }) } - /// wait until a slave transaction is finished, and return tuple address, direction and data size - pub async fn slave_transaction(&mut self) -> Result<(u8, vals::Dir, u8), Error> { + /// wait until a slave transaction is finished, and return tuple address, direction, data size and error + pub async fn slave_transaction(&mut self) -> (u8, vals::Dir, u8, Option) { // async wait until addressed poll_fn(|cx| { T::state().waker.register(cx.waker()); @@ -1112,11 +1096,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let mut state_m = f.borrow_mut(); if state_m.ready { state_m.ready = false; - // if the dir bit is set it is a master write slave read operation - match state_m.result { - Ok(()) => return Poll::Ready(Ok((state_m.current_address, state_m.dir, state_m.get_size()))), - Err(e) => return Poll::Ready(Err(e)), - } + return Poll::Ready((state_m.current_address, state_m.dir, state_m.get_size(), state_m.result)); } else { return Poll::Pending; } diff --git a/examples/stm32g0/src/bin/i2c_master.rs b/examples/stm32g0/src/bin/i2c_master.rs index b8bed848..36f6794a 100644 --- a/examples/stm32g0/src/bin/i2c_master.rs +++ b/examples/stm32g0/src/bin/i2c_master.rs @@ -79,7 +79,7 @@ async fn main(_spawner: Spawner) { let mut buf_64 = [0_u8; 64]; let mut buf_65 = [0_u8; 65]; - writeln!(&mut writer, "Start of test").unwrap(); + writeln!(&mut writer, "Start of test\n\r").unwrap(); for i in 0..buf_20.len() { buf_20[i] = 0x20 + (i as u8) @@ -92,74 +92,80 @@ async fn main(_spawner: Spawner) { } // test 1: slave address 0x61 should not be addressable match i2c.blocking_write(0x61, &buf_20) { - Ok(_) => writeln!(&mut writer, "Test 1 Error: would expect nack").unwrap(), - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), - Err(err) => writeln!(&mut writer, "Test 1 OK: expected NACK error: {:?}", err).unwrap(), + Ok(_) => writeln!(&mut writer, "Test 1 failed: would expect nack\n\r").unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), + Err(err) => writeln!(&mut writer, "Test 1 passed: expected NACK error: {:?}", err).unwrap(), }; // 0x41 good case master write slave read: master does send 20 bytes slave receives 20 bytes match i2c.blocking_write(0x41, &buf_20) { - Ok(_) => writeln!(&mut writer, "Test 0x41 Ok").unwrap(), - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), - Err(err) => writeln!(&mut writer, "Test 0x41 Error: {:?}", err).unwrap(), + Ok(_) => writeln!(&mut writer, "Test 0x41 passed\n\r").unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), + Err(err) => writeln!(&mut writer, "Test 0x41 failed. Error: {:?}", err).unwrap(), }; + Timer::after(Duration::from_millis(10)).await; // 0x42 edge case master write exact 64 bytes: must succeed on master and slave match i2c.blocking_write(0x42, &buf_64) { - Ok(_) => writeln!(&mut writer, "Test 0x42 Ok. Master write exact 64 bytes").unwrap(), - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), - Err(err) => writeln!(&mut writer, "Test 0x42 error IncorrectFramesize: {:?}", err).unwrap(), + Ok(_) => writeln!(&mut writer, "Test 0x42 passed. Master write exact 64 bytes\n\r").unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), + Err(err) => writeln!(&mut writer, "Test 0x42 failed. Got error: {:?}\r\n", err).unwrap(), }; - // 0x43 edge case master write exact 65 bytes: 1 too manyu must fail on master and slave - match i2c.blocking_write(0x43, &buf_64) { - Ok(_) => writeln!(&mut writer, "Test 0x42 Failed. Expected a Nack").unwrap(), - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), + Timer::after(Duration::from_millis(10)).await; + // 0x43 edge case master write exact 65 bytes: 1 too many must fail on master and slave + match i2c.blocking_write(0x43, &buf_65) { + Ok(_) => writeln!(&mut writer, "Test 0x43 Failed. Expected a Nack\n\r").unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), Err(err) => writeln!( &mut writer, - "Test 0x43 Ok: Got error NACK du to buffer of 1 too big {:?}", + "Test 0x43 passed: Got error NACK du to buffer of 1 too big {:?}\r\n", err ) .unwrap(), }; + Timer::after(Duration::from_millis(10)).await; match i2c.blocking_read(0x48, &mut buf_20) { Ok(_) => { - writeln!(&mut writer, "Test 0x48 Read expected to fail!").unwrap(); + writeln!(&mut writer, "Test 0x48 failed. Read expected to fail!\n\r").unwrap(); } - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), Err(err) => writeln!( &mut writer, - "Test 0x48 Ok. First time, slave did not yet prepare a buffer Error: {:?}", + "Test 0x48 Ok. First time, slave did not yet prepare a buffer Error: {:?}\r\n", err ) .unwrap(), }; + Timer::after(Duration::from_millis(10)).await; match i2c.blocking_read(0x49, &mut buf_20) { Ok(_) => { - writeln!(&mut writer, "Test 0x49 Read Ok").unwrap(); + writeln!(&mut writer, "Test 0x49 Read Ok\n\r").unwrap(); print_buffer(&mut writer, &buf_20); } - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), - Err(err) => writeln!(&mut writer, "Test 0x49 Error: {:?}", err).unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), + Err(err) => writeln!(&mut writer, "Test 0x49 Error: {:?}\r\n", err).unwrap(), }; + Timer::after(Duration::from_millis(10)).await; match i2c.blocking_read(0x4A, &mut buf_64) { Ok(_) => { - writeln!(&mut writer, "Test 0x4A failed. Expected was a NACK error").unwrap(); + writeln!(&mut writer, "Test 0x4A failed. Expected was a NACK error\n\r").unwrap(); print_buffer(&mut writer, &buf_64); } - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), - Err(err) => writeln!(&mut writer, "Test 0x4A Ok. Expected to fail. Error: {:?}", err).unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), + Err(err) => writeln!(&mut writer, "Test 0x4A passed. Expected to fail. Error: {:?}\r\n", err).unwrap(), }; + Timer::after(Duration::from_millis(10)).await; match i2c.blocking_read(0x4B, &mut buf_64) { Ok(_) => { - writeln!(&mut writer, "Test 0x4B succeeded: edge case read exact the buffer size").unwrap(); + writeln!(&mut writer, "Test 0x4B passed\n\r").unwrap(); print_buffer(&mut writer, &buf_64); } - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), - Err(err) => writeln!(&mut writer, "Test 0x4B failed. Error: {:?}", err).unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), + Err(err) => writeln!(&mut writer, "Test 0x4B failed. Error: {:?}\r\n", err).unwrap(), }; /* match i2c.blocking_write_read(0x44, &buf_20, &mut buf_64) { Ok(_) => { - writeln!(&mut writer, "Test 0x44 Ok ").unwrap(); + writeln!(&mut writer, "Test 0x44 Ok \n\r").unwrap(); writeln!( &mut writer, "Uppercase input should be transformed to lowercase, A -> b " @@ -169,31 +175,32 @@ async fn main(_spawner: Spawner) { for i in 0..buf_rcv.len() { writeln!(&mut writer, "{}", buf_rcv[i]).unwrap(); } - writeln!(&mut writer, "").unwrap() + writeln!(&mut writer, "\n\r").unwrap() } - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), Err(err) => writeln!(&mut writer, "Test 0x44 error: {:?}", err).unwrap(), }; */ + Timer::after(Duration::from_millis(10)).await; // 0x4F test end and slave will present results let mut result: [u8; 2] = [0, 0]; match i2c.blocking_read(0x4F, &mut result) { Ok(_) => writeln!( &mut writer, - "Result of the whole test as reported by the slave count/errors: {}/{}\r", + "Result of the whole test as reported by the slave count/errors: {}/{}\r\n", result[0], result[1] ) .unwrap(), - Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out").unwrap(), - Err(err) => writeln!(&mut writer, "Test 0x4F unexpected error: {:?}", err).unwrap(), + Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(), + Err(err) => writeln!(&mut writer, "Test 0x4F unexpected error: {:?}\r\n", err).unwrap(), }; - writeln!(&mut writer, "").unwrap(); + writeln!(&mut writer, "\n\r").unwrap(); Timer::after(Duration::from_millis(10_000)).await; } fn print_buffer(writer: &mut SerialWriter, buf: &[u8]) { for i in 0..buf.len() { write!(writer, " {:2x} ", buf[i]).unwrap(); } - writeln!(writer, "\n\r").unwrap() + writeln!(writer, "\n\r\n\r").unwrap() } } diff --git a/examples/stm32g0/src/bin/i2c_slave.rs b/examples/stm32g0/src/bin/i2c_slave.rs index 48e91175..3a48b2ae 100644 --- a/examples/stm32g0/src/bin/i2c_slave.rs +++ b/examples/stm32g0/src/bin/i2c_slave.rs @@ -6,7 +6,7 @@ use core::fmt::{self, Write}; use embassy_executor::Spawner; use embassy_stm32::dma::NoDma; -use embassy_stm32::i2c::I2c; +use embassy_stm32::i2c::{Error, I2c}; use embassy_stm32::pac::i2c::vals; use embassy_stm32::time::Hertz; use embassy_stm32::usart::UartTx; @@ -95,7 +95,7 @@ async fn main(_spawner: Spawner) { let mut dir = vals::Dir::READ; let mut tcount = 0; let mut counter = 0; - let mut error = Ok((0, vals::Dir::READ, 0)); + let mut result: Option = None; // start of the actual test i2c.slave_start_listen().unwrap(); @@ -112,81 +112,92 @@ async fn main(_spawner: Spawner) { writeln!(&mut writer, "Waiting for master activity\r").unwrap(); - error = Ok((0, vals::Dir::WRITE, 0)); - match i2c.slave_transaction().await { - Ok((taddr, tdir, tsize)) => { - address = taddr; - dir = tdir; - writeln!( - &mut writer, - "Test ok. Address: x{:2x} dir: {:?} size: x{:2x}\r", - taddr, tdir as u8, tsize - ) - .unwrap(); - } - Err(e) => { - error = Err(e); - writeln!(&mut writer, "Test failed: Error: {:?}", e).unwrap() - } - } + // clear write buffers for sure + _ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::GenericAddress); + _ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::MainAddress); + + let (address, dir, size, result) = i2c.slave_transaction().await; + writeln!( + &mut writer, + "Address: x{:2x} dir: {:?} size: x{:2x}, Result:{:?}\r", + address, dir as u8, size, result + ) + .unwrap(); tcount += 1; match address { 0x41 => { - // 0x41 good case master write slave read: master does send 20 bytes slave receives 20 bytes + writeln!( + &mut writer, + "Start test 0x41. Master-write-slave-read 20 bytes. Should be ok\r\n" + ) + .unwrap(); checkIsWrite!(writer, dir); _ = i2c.slave_read_buffer(&mut buf_20, i2c::AddressType::GenericAddress); - match error { - Ok(_) => { - writeln!(&mut writer, "Test 0x41 Ok. send 20 bytes").unwrap(); + match result { + None => { + writeln!(&mut writer, "Test 0x41 passed\r\n").unwrap(); print_buffer(&mut writer, &buf_20); } - Err(err) => { + Some(err) => { errors += 1; - writeln!(&mut writer, "Test 0x41 failed. Error: {:?}\r", err).unwrap() + writeln!(&mut writer, "Test 0x41 failed. Error: {:?}\r\n", err).unwrap() } }; } 0x42 => { - // 0x42 good case edge case: exact 64 bytes master write slave read: + writeln!( + &mut writer, + "Start test 0x42. Master-write-slave-read 64 bytes. Should be ok\r\n" + ) + .unwrap(); checkIsWrite!(writer, dir); _ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::GenericAddress); - match error { - Ok(_) => { - writeln!(&mut writer, "Test 0x42 Ok. send 64 bytes").unwrap(); + match result { + None => { + writeln!(&mut writer, "Test 0x42 passed. send 64 bytes").unwrap(); print_buffer(&mut writer, &buf_64); } - Err(err) => { + Some(err) => { errors += 1; writeln!(&mut writer, "Test 0x42 failed. Error: {:?}\r", err).unwrap() } }; } 0x43 => { - // 0x43 bad case master write slave read: master does send more than 64 bytes, slave does NACK + writeln!( + &mut writer, + "Start test 0x43. Master-write-slave-read 65 bytes. Slave should NACK at 65 byte\r\n" + ) + .unwrap(); checkIsWrite!(writer, dir); _ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::GenericAddress); - match i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::GenericAddress) { - Ok(_) => { + match result { + None => { { - writeln!(&mut writer, "Test 0x43 failed. Expected to fail. with FrameError\r").unwrap() + writeln!(&mut writer, "Test 0x43 failed. Expected to fail Got Ok\r").unwrap() }; } - Err(err) => { + Some(err) => { errors += 1; - writeln!(&mut writer, "Test 0x43 Ok Expected error. Error: {:?}\r", err).unwrap() + writeln!(&mut writer, "Test 0x43 passed. Get expected error. Error: {:?}\r", err).unwrap() } }; } 0x48 => { // 0x48 master read slave write slave did not yet prepare a buffer, master will fail + writeln!( + &mut writer, + "Start test 0x48. Master-read-slave-write 20 bytes. Should first time (buffer empty)\r\n" + ) + .unwrap(); checkIsRead!(writer, dir); - match error { - Ok(_) => { - writeln!(&mut writer, "Test 0x48 fail expected to fail: \r").unwrap(); + match result { + None => { + writeln!(&mut writer, "Test 0x48 failed. Expected to fail: \r").unwrap(); errors += 1; } - Err(err) => writeln!(&mut writer, "Test 0x48 Ok. Expected error: {:?}\r", err).unwrap(), + Some(err) => writeln!(&mut writer, "Test 0x48 passed. Got expected error: {:?}\r", err).unwrap(), }; // prepare buffer for next round for i in 0..buf_20.len() { @@ -195,13 +206,17 @@ async fn main(_spawner: Spawner) { _ = i2c.slave_write_buffer(&buf_20, i2c::AddressType::GenericAddress); } 0x49 => { - // 0x49 master read slave write bad case: master expects 50 does slave does send 20 characters + writeln!( + &mut writer, + "Start test 0x49. Master-read-slave-write 20 bytes. Should be ok\r\n" + ) + .unwrap(); checkIsRead!(writer, dir); - match error { - Ok(_) => { - writeln!(&mut writer, "Test 0x49 Ok. master did read 20 bytes").unwrap(); + match result { + None => { + writeln!(&mut writer, "Test passed").unwrap(); } - Err(err) => { + Some(err) => { errors += 1; writeln!(&mut writer, "Test 0x49 failed. Error: {:?}\r", err).unwrap() } @@ -214,14 +229,19 @@ async fn main(_spawner: Spawner) { } 0x4A => { // 0x4A master read slave write bad case: master expects 64 does slave does prepare 20 characters + writeln!( + &mut writer, + "Start test 0x4A. Master-read-slave-write Master expects 64 bytes, slave sends 20.\r\n" + ) + .unwrap(); checkIsRead!(writer, dir); - match error { - Ok(_) => { - writeln!(&mut writer, "Test 0x4A failed . Expected an errpr").unwrap(); + match result { + None => { + writeln!(&mut writer, "Test 0x4A failed . Expected an error").unwrap(); } - Err(err) => { + Some(err) => { errors += 1; - writeln!(&mut writer, "Test 0x4A ok. Expected errore rror: {:?}\r", err).unwrap() + writeln!(&mut writer, "Test 0x4A passed. Expected errore rror: {:?}\r", err).unwrap() } } _ = i2c.slave_write_buffer(&buf_20, i2c::AddressType::GenericAddress); @@ -232,13 +252,17 @@ async fn main(_spawner: Spawner) { _ = i2c.slave_write_buffer(&buf_64, i2c::AddressType::GenericAddress); } 0x4B => { - // 0x4B master write_read good case each 20 chars + writeln!( + &mut writer, + "Start test 0x4B. Master-read-slave-write Master expects 64 bytes, Should be ok.\r\n" + ) + .unwrap(); checkIsRead!(writer, dir); - match error { - Ok(_) => { - writeln!(&mut writer, "Test 0x4B Ok\r").unwrap(); + match result { + None => { + writeln!(&mut writer, "Test 0x4B passed\r").unwrap(); } - Err(err) => { + Some(err) => { errors += 1; writeln!(&mut writer, "Test 0x4B failed. Error: {:?}\r", err).unwrap() } @@ -248,11 +272,16 @@ async fn main(_spawner: Spawner) { } 0x4F => { checkIsRead!(writer, dir); - match error { - Ok(_) => { + writeln!( + &mut writer, + "Start test 0x4B. Master-read-slave-write 2 bytes with test summary Should be ok.\r\n" + ) + .unwrap(); + match result { + None => { writeln!(&mut writer, "Test 0x4F Result send to master\r").unwrap(); } - Err(err) => { + Some(err) => { errors += 1; writeln!(&mut writer, "Test 0x4F failed. Error: {:?}\r", err).unwrap() }