Merge pull request #1637 from ShakenCodes/main

Ensure I2C master_stop() called after error
This commit is contained in:
Dario Nieuwenhuis 2023-07-12 15:46:28 +00:00 committed by GitHub
commit ed86fc175f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -382,13 +382,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
// I2C start // I2C start
// //
// ST SAD+W // ST SAD+W
Self::master_write( if let Err(err) = Self::master_write(
address, address,
write.len().min(255), write.len().min(255),
Stop::Software, Stop::Software,
last_chunk_idx != 0, last_chunk_idx != 0,
&check_timeout, &check_timeout,
)?; ) {
if send_stop {
self.master_stop();
}
return Err(err);
}
for (number, chunk) in write.chunks(255).enumerate() { for (number, chunk) in write.chunks(255).enumerate() {
if number != 0 { if number != 0 {
@ -399,18 +404,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
// Wait until we are allowed to send data // Wait until we are allowed to send data
// (START has been ACKed or last byte when // (START has been ACKed or last byte when
// through) // through)
self.wait_txe(&check_timeout)?; if let Err(err) = self.wait_txe(&check_timeout) {
if send_stop {
self.master_stop();
}
return Err(err);
}
T::regs().txdr().write(|w| w.set_txdata(*byte)); T::regs().txdr().write(|w| w.set_txdata(*byte));
} }
} }
// Wait until the write finishes // Wait until the write finishes
self.wait_tc(&check_timeout)?; let result = self.wait_tc(&check_timeout);
if send_stop { if send_stop {
self.master_stop(); self.master_stop();
} }
Ok(()) result
} }
async fn write_dma_internal( async fn write_dma_internal(
@ -707,13 +716,16 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
let first_length = write[0].len(); let first_length = write[0].len();
let last_slice_index = write.len() - 1; let last_slice_index = write.len() - 1;
Self::master_write( if let Err(err) = Self::master_write(
address, address,
first_length.min(255), first_length.min(255),
Stop::Software, Stop::Software,
(first_length > 255) || (last_slice_index != 0), (first_length > 255) || (last_slice_index != 0),
&check_timeout, &check_timeout,
)?; ) {
self.master_stop();
return Err(err);
}
for (idx, slice) in write.iter().enumerate() { for (idx, slice) in write.iter().enumerate() {
let slice_len = slice.len(); let slice_len = slice.len();
@ -726,27 +738,36 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
let last_chunk_idx = total_chunks.saturating_sub(1); let last_chunk_idx = total_chunks.saturating_sub(1);
if idx != 0 { if idx != 0 {
Self::master_continue( if let Err(err) = Self::master_continue(
slice_len.min(255), slice_len.min(255),
(idx != last_slice_index) || (slice_len > 255), (idx != last_slice_index) || (slice_len > 255),
&check_timeout, &check_timeout,
)?; ) {
self.master_stop();
return Err(err);
}
} }
for (number, chunk) in slice.chunks(255).enumerate() { for (number, chunk) in slice.chunks(255).enumerate() {
if number != 0 { if number != 0 {
Self::master_continue( if let Err(err) = Self::master_continue(
chunk.len(), chunk.len(),
(number != last_chunk_idx) || (idx != last_slice_index), (number != last_chunk_idx) || (idx != last_slice_index),
&check_timeout, &check_timeout,
)?; ) {
self.master_stop();
return Err(err);
}
} }
for byte in chunk { for byte in chunk {
// Wait until we are allowed to send data // Wait until we are allowed to send data
// (START has been ACKed or last byte when // (START has been ACKed or last byte when
// through) // through)
self.wait_txe(&check_timeout)?; if let Err(err) = self.wait_txe(&check_timeout) {
self.master_stop();
return Err(err);
}
// Put byte on the wire // Put byte on the wire
//self.i2c.txdr.write(|w| w.txdata().bits(*byte)); //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
@ -755,10 +776,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
} }
// Wait until the write finishes // Wait until the write finishes
self.wait_tc(&check_timeout)?; let result = self.wait_tc(&check_timeout);
self.master_stop(); self.master_stop();
result
Ok(())
} }
pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {