From a5b0318817c6dcfa9d9ea1bce44d2b43ea85e623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirco=20Telth=C3=B6rster?= Date: Fri, 22 Jul 2022 11:07:16 +0200 Subject: [PATCH 1/6] write more than 255 bytes in a single transaction added --- src/i2c.rs | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/i2c.rs b/src/i2c.rs index 998ec765..8a64bd35 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -303,7 +303,7 @@ where fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { // TODO support transfers of more than 255 bytes - assert!(bytes.len() < 256); + // assert!(bytes.len() < 256); // Wait for any previous address sequence to end // automatically. This could be up to 50% of a bus @@ -322,17 +322,41 @@ where .clear_bit() .rd_wrn() .write() - .nbytes() - .bits(bytes.len() as u8) .autoend() .software() }); + let mut iterations: u8 = 0; + // Set RELOAD flag, if more than 255 bytes need to be send + if bytes.len() > 255 { + self.i2c + .cr2 + .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)); + iterations = (bytes.len() / 255) as u8 + } else { + self.i2c.cr2.write(|w| w.nbytes().bits(bytes.len() as u8)); + } + for byte in bytes { // Wait until we are allowed to send data // (START has been ACKed or last byte when // through) busy_wait!(self.i2c, txis, is_empty); + if self.i2c.isr.read().tcr().bit_is_set() && bytes.len() > 255 { + if iterations > 1 { + self.i2c + .cr2 + .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)); + //self.i2c.isr.write(|w| w.tc().clear_bit()); + iterations -= 1; + } else if iterations == 1 { + self.i2c + .cr2 + .write(|w| w.reload().clear_bit().nbytes().bits(bytes.len() as u8)); + //self.i2c.isr.write(|w| w.tc().clear_bit()); + iterations = 0; + } + } // Put byte on the wire self.i2c.txdr.write(|w| w.txdata().bits(*byte)); From 3e3ae2e42454ec6f9aaf74a076831f135316b8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirco=20Telth=C3=B6rster?= Date: Fri, 29 Jul 2022 14:35:12 +0200 Subject: [PATCH 2/6] first working 256 byte read --- src/i2c.rs | 154 +++++++++++++++++++++++------------------------------ 1 file changed, 68 insertions(+), 86 deletions(-) diff --git a/src/i2c.rs b/src/i2c.rs index 8a64bd35..8568c37d 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -326,39 +326,34 @@ where .software() }); - let mut iterations: u8 = 0; + let bytes_length = bytes.len(); // Set RELOAD flag, if more than 255 bytes need to be send - if bytes.len() > 255 { + if bytes_length > 255 { self.i2c .cr2 .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)); - iterations = (bytes.len() / 255) as u8 } else { self.i2c.cr2.write(|w| w.nbytes().bits(bytes.len() as u8)); } - for byte in bytes { - // Wait until we are allowed to send data - // (START has been ACKed or last byte when - // through) + for (index, byte) in bytes.iter().enumerate() { + // Wait until we have received something busy_wait!(self.i2c, txis, is_empty); - if self.i2c.isr.read().tcr().bit_is_set() && bytes.len() > 255 { - if iterations > 1 { - self.i2c - .cr2 - .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)); - //self.i2c.isr.write(|w| w.tc().clear_bit()); - iterations -= 1; - } else if iterations == 1 { + + if (index + 1) % 255 == 0 && bytes_length > 255 { + if bytes_length - index - 1 <= 255 { + self.i2c.cr2.write(|w| { + w.reload() + .clear_bit() + .nbytes() + .bits((bytes_length - index - 1) as u8) + }) + } else { self.i2c .cr2 - .write(|w| w.reload().clear_bit().nbytes().bits(bytes.len() as u8)); - //self.i2c.isr.write(|w| w.tc().clear_bit()); - iterations = 0; + .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)) } } - - // Put byte on the wire self.i2c.txdr.write(|w| w.txdata().bits(*byte)); } @@ -381,37 +376,70 @@ where fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { // TODO support transfers of more than 255 bytes - assert!(buffer.len() < 256 && buffer.len() > 0); + //assert!(buffer.len() < 256 && buffer.len() > 0); // Wait for any previous address sequence to end // automatically. This could be up to 50% of a bus // cycle (ie. up to 0.5/freq) while self.i2c.cr2.read().start().bit_is_set() {} + let buffer_length = buffer.len(); // Set START and prepare to receive bytes into // `buffer`. The START bit can be set even if the bus // is BUSY or I2C is in slave mode. - self.i2c.cr2.write(|w| { - w.sadd() - .bits((addr << 1 | 0) as u16) - .rd_wrn() - .read() - .nbytes() - .bits(buffer.len() as u8) - .start() - .set_bit() - .autoend() - .automatic() - }); + if buffer_length < 256 { + self.i2c.cr2.write(|w| { + w.sadd() + .bits((addr << 1 | 0) as u16) + .rd_wrn() + .read() + .nbytes() + .bits(buffer.len() as u8) + .start() + .set_bit() + .autoend() + .software() + }); + } else { + self.i2c.cr2.write(|w| { + w.sadd() + .bits((addr << 1 | 0) as u16) + .rd_wrn() + .read() + .nbytes() + .bits(255 as u8) + .reload() + .set_bit() + .start() + .set_bit() + .autoend() + .software() + }); + } - for byte in buffer { + for (index, byte) in buffer.iter_mut().enumerate() { // Wait until we have received something busy_wait!(self.i2c, rxne, is_not_empty); - *byte = self.i2c.rxdr.read().rxdata().bits(); + + if (index + 1) % 255 == 0 && buffer_length > 255 { + if buffer_length - index - 1 <= 255 { + self.i2c.cr2.write(|w| { + w.reload() + .clear_bit() + .nbytes() + .bits((buffer_length - index - 1) as u8) + }) + } else { + self.i2c + .cr2 + .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)) + } + } } - // automatic STOP + // Stop + self.i2c.cr2.write(|w| w.stop().set_bit()); Ok(()) // Rx::new(&self.i2c)?.read(addr, buffer) @@ -426,8 +454,8 @@ where fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { // TODO support transfers of more than 255 bytes - assert!(bytes.len() < 256 && bytes.len() > 0); - assert!(buffer.len() < 256 && buffer.len() > 0); + //assert!(bytes.len() < 256 && bytes.len() > 0); + //assert!(buffer.len() < 256 && buffer.len() > 0); // Wait for any previous address sequence to end // automatically. This could be up to 50% of a bus @@ -437,55 +465,9 @@ where // Set START and prepare to send `bytes`. The // START bit can be set even if the bus is BUSY or // I2C is in slave mode. - self.i2c.cr2.write(|w| { - w.start() - .set_bit() - .sadd() - .bits(u16(addr << 1 | 0)) - .add10() - .clear_bit() - .rd_wrn() - .write() - .nbytes() - .bits(bytes.len() as u8) - .autoend() - .software() - }); - - for byte in bytes { - // Wait until we are allowed to send data - // (START has been ACKed or last byte went through) - busy_wait!(self.i2c, txis, is_empty); - - // Put byte on the wire - self.i2c.txdr.write(|w| w.txdata().bits(*byte)); - } - - // Wait until the write finishes before beginning to read. - busy_wait!(self.i2c, tc, is_complete); + self.write(addr, bytes)?; - // reSTART and prepare to receive bytes into `buffer` - self.i2c.cr2.write(|w| { - w.sadd() - .bits(u16(addr << 1 | 1)) - .add10() - .clear_bit() - .rd_wrn() - .read() - .nbytes() - .bits(buffer.len() as u8) - .start() - .set_bit() - .autoend() - .automatic() - }); - - for byte in buffer { - // Wait until we have received something - busy_wait!(self.i2c, rxne, is_not_empty); - - *byte = self.i2c.rxdr.read().rxdata().bits(); - } + self.read(addr, buffer)?; Ok(()) } From 77223709167da298ee82f555210c231bde1dc6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirco=20Telth=C3=B6rster?= Date: Fri, 29 Jul 2022 15:32:02 +0200 Subject: [PATCH 3/6] final version read more than 255 Byte --- src/i2c.rs | 66 ++++++++++++++++++++---------------------------------- 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/src/i2c.rs b/src/i2c.rs index 8568c37d..6bd1ae4a 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -387,54 +387,36 @@ where // Set START and prepare to receive bytes into // `buffer`. The START bit can be set even if the bus // is BUSY or I2C is in slave mode. - if buffer_length < 256 { - self.i2c.cr2.write(|w| { - w.sadd() - .bits((addr << 1 | 0) as u16) - .rd_wrn() - .read() - .nbytes() - .bits(buffer.len() as u8) - .start() - .set_bit() - .autoend() - .software() - }); - } else { - self.i2c.cr2.write(|w| { - w.sadd() - .bits((addr << 1 | 0) as u16) - .rd_wrn() - .read() - .nbytes() - .bits(255 as u8) - .reload() - .set_bit() - .start() - .set_bit() - .autoend() - .software() - }); - } + self.i2c.cr2.write(|w| { + w.sadd() + .bits((addr << 1 | 0) as u16) + .rd_wrn() + .read() + .start() + .set_bit() + .autoend() + .software() + .reload() + .bit(buffer_length > 255) + .nbytes() + .bits(core::cmp::min(buffer_length, 255) as u8) + }); for (index, byte) in buffer.iter_mut().enumerate() { // Wait until we have received something busy_wait!(self.i2c, rxne, is_not_empty); *byte = self.i2c.rxdr.read().rxdata().bits(); - if (index + 1) % 255 == 0 && buffer_length > 255 { - if buffer_length - index - 1 <= 255 { - self.i2c.cr2.write(|w| { - w.reload() - .clear_bit() - .nbytes() - .bits((buffer_length - index - 1) as u8) - }) - } else { - self.i2c - .cr2 - .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)) - } + let bytes_received = index + 1; + let bytes_remaining = buffer_length - bytes_received; + + if bytes_received % 255 == 0 && bytes_remaining > 0 { + self.i2c.cr2.write(|w| { + w.reload() + .bit(bytes_remaining > 255) + .nbytes() + .bits(core::cmp::min(bytes_remaining, 255) as u8) + }) } } From 7fe14549d83026bcfde362bdbc2b62744d41f682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirco=20Telth=C3=B6rster?= Date: Fri, 5 Aug 2022 12:16:29 +0200 Subject: [PATCH 4/6] added write function with support for more than 255 Bytes (not tested) --- src/i2c.rs | 98 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 30 deletions(-) diff --git a/src/i2c.rs b/src/i2c.rs index 6bd1ae4a..c09c74b0 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -301,57 +301,50 @@ where { type Error = Error; + // Write function that supports transmission of more than 255 bytes. + // This function is not tested, so it has been deactivated + /* fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { - // TODO support transfers of more than 255 bytes - // assert!(bytes.len() < 256); - // Wait for any previous address sequence to end // automatically. This could be up to 50% of a bus // cycle (ie. up to 0.5/freq) while self.i2c.cr2.read().start().bit_is_set() {} + let bytes_length = bytes.len(); + // Set START and prepare to send `bytes`. The // START bit can be set even if the bus is BUSY or // I2C is in slave mode. self.i2c.cr2.write(|w| { - w.start() - .set_bit() - .sadd() - .bits(u16(addr << 1 | 0)) - .add10() - .clear_bit() + w.sadd() + .bits((addr << 1 | 0) as u16) .rd_wrn() .write() + .start() + .set_bit() .autoend() .software() + .reload() + .bit(buffer_length > 255) + .nbytes() + .bits(core::cmp::min(bytes_length, 255) as u8) }); - let bytes_length = bytes.len(); - // Set RELOAD flag, if more than 255 bytes need to be send - if bytes_length > 255 { - self.i2c - .cr2 - .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)); - } else { - self.i2c.cr2.write(|w| w.nbytes().bits(bytes.len() as u8)); - } - for (index, byte) in bytes.iter().enumerate() { - // Wait until we have received something + // Wait until last transmission is done busy_wait!(self.i2c, txis, is_empty); - if (index + 1) % 255 == 0 && bytes_length > 255 { + let bytes_send = index + 1; + let bytes_remaining = bytes_length - bytes_send; + + if bytes_send % 255 == 0 && bytes_remaining > 255 { if bytes_length - index - 1 <= 255 { self.i2c.cr2.write(|w| { w.reload() - .clear_bit() + .bit(bytes_remaining > 255) .nbytes() - .bits((bytes_length - index - 1) as u8) + .bits(core::cmp::min(bytes_remaining, 255) as u8) }) - } else { - self.i2c - .cr2 - .write(|w| w.reload().set_bit().nbytes().bits(255 as u8)) } } self.i2c.txdr.write(|w| w.txdata().bits(*byte)); @@ -363,6 +356,54 @@ where // Stop self.i2c.cr2.write(|w| w.stop().set_bit()); + Ok(()) + // Tx::new(&self.i2c)?.write(addr, bytes) + } + */ + + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { + // TODO support transfers of more than 255 bytes + assert!(bytes.len() < 256); + + // Wait for any previous address sequence to end + // automatically. This could be up to 50% of a bus + // cycle (ie. up to 0.5/freq) + while self.i2c.cr2.read().start().bit_is_set() {} + + // Set START and prepare to send `bytes`. The + // START bit can be set even if the bus is BUSY or + // I2C is in slave mode. + self.i2c.cr2.write(|w| { + w.start() + .set_bit() + .sadd() + .bits(u16(addr << 1 | 0)) + .add10() + .clear_bit() + .rd_wrn() + .write() + .nbytes() + .bits(bytes.len() as u8) + .autoend() + .software() + }); + + for byte in bytes { + // Wait until we are allowed to send data + // (START has been ACKed or last byte when + // through) + busy_wait!(self.i2c, txis, is_empty); + + // Put byte on the wire + self.i2c.txdr.write(|w| w.txdata().bits(*byte)); + } + + // Wait until the write finishes + busy_wait!(self.i2c, tc, is_complete); + + // Stop + self.i2c.cr2.write(|w| w.stop().set_bit()); + Ok(()) // Tx::new(&self.i2c)?.write(addr, bytes) } @@ -375,9 +416,6 @@ where type Error = Error; fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { - // TODO support transfers of more than 255 bytes - //assert!(buffer.len() < 256 && buffer.len() > 0); - // Wait for any previous address sequence to end // automatically. This could be up to 50% of a bus // cycle (ie. up to 0.5/freq) From e19cce37e00f3042a1c38dfd4323d3e31a82c396 Mon Sep 17 00:00:00 2001 From: Tobias Naumann Date: Fri, 5 Aug 2022 19:40:47 +0200 Subject: [PATCH 5/6] Wait for tcr flag before reloading the next i2c write chunk This uncomments the untested new i2c code to check that it compiles and additionally fixes some minor bugs. --- src/i2c.rs | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/i2c.rs b/src/i2c.rs index c09c74b0..c53c5c9b 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -303,7 +303,6 @@ where // Write function that supports transmission of more than 255 bytes. // This function is not tested, so it has been deactivated - /* fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { // Wait for any previous address sequence to end // automatically. This could be up to 50% of a bus @@ -325,7 +324,7 @@ where .autoend() .software() .reload() - .bit(buffer_length > 255) + .bit(bytes_length > 255) .nbytes() .bits(core::cmp::min(bytes_length, 255) as u8) }); @@ -333,21 +332,20 @@ where for (index, byte) in bytes.iter().enumerate() { // Wait until last transmission is done busy_wait!(self.i2c, txis, is_empty); + self.i2c.txdr.write(|w| w.txdata().bits(*byte)); - let bytes_send = index + 1; - let bytes_remaining = bytes_length - bytes_send; - - if bytes_send % 255 == 0 && bytes_remaining > 255 { - if bytes_length - index - 1 <= 255 { - self.i2c.cr2.write(|w| { - w.reload() - .bit(bytes_remaining > 255) - .nbytes() - .bits(core::cmp::min(bytes_remaining, 255) as u8) - }) - } + let bytes_sent = index + 1; + let bytes_remaining = bytes_length - bytes_sent; + + if bytes_sent % 255 == 0 && bytes_remaining > 255 { + busy_wait!(self.i2c, tcr, is_complete); + self.i2c.cr2.write(|w| { + w.reload() + .bit(bytes_remaining > 255) + .nbytes() + .bits(core::cmp::min(bytes_remaining, 255) as u8) + }) } - self.i2c.txdr.write(|w| w.txdata().bits(*byte)); } // Wait until the write finishes @@ -359,8 +357,8 @@ where Ok(()) // Tx::new(&self.i2c)?.write(addr, bytes) } - */ + /* fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { // TODO support transfers of more than 255 bytes assert!(bytes.len() < 256); @@ -407,6 +405,7 @@ where Ok(()) // Tx::new(&self.i2c)?.write(addr, bytes) } + */ } impl Read for I2c From 9e8aaff45793b069306e0499fbd002d369217d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirco=20Telth=C3=B6rster?= Date: Fri, 12 Aug 2022 11:02:03 +0200 Subject: [PATCH 6/6] warnings fixed --- src/i2c.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i2c.rs b/src/i2c.rs index c53c5c9b..f67f90fe 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -24,7 +24,7 @@ use crate::pac::{i2c1, I2C1, I2C2, I2C3}; use crate::rcc::{Clocks, Enable, RccBus, Reset}; use crate::time::Hertz; -use cast::{u16, u8}; +use cast::u8; use core::ops::Deref; /// I2C error