aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshakencodes <[email protected]>2023-07-10 16:40:18 -0700
committershakencodes <[email protected]>2023-07-10 16:40:33 -0700
commit29f3d5b68d3b5949de35227359bf631661613b14 (patch)
tree238196daafb7c7dd9eca5e3e21bf4851d10b01b4
parent8a811cfcf75b25fe81168134bf0cf8a8d387c391 (diff)
Ensure I2C master_stop() called after error
-rw-r--r--embassy-stm32/src/i2c/v2.rs52
1 files changed, 36 insertions, 16 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 1f036d55c..208d1527d 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -382,13 +382,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
382 // I2C start 382 // I2C start
383 // 383 //
384 // ST SAD+W 384 // ST SAD+W
385 Self::master_write( 385 if let Err(err) = Self::master_write(
386 address, 386 address,
387 write.len().min(255), 387 write.len().min(255),
388 Stop::Software, 388 Stop::Software,
389 last_chunk_idx != 0, 389 last_chunk_idx != 0,
390 &check_timeout, 390 &check_timeout,
391 )?; 391 ) {
392 if send_stop {
393 self.master_stop();
394 }
395 return Err(err);
396 }
392 397
393 for (number, chunk) in write.chunks(255).enumerate() { 398 for (number, chunk) in write.chunks(255).enumerate() {
394 if number != 0 { 399 if number != 0 {
@@ -399,18 +404,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
399 // Wait until we are allowed to send data 404 // Wait until we are allowed to send data
400 // (START has been ACKed or last byte when 405 // (START has been ACKed or last byte when
401 // through) 406 // through)
402 self.wait_txe(&check_timeout)?; 407 if let Err(err) = self.wait_txe(&check_timeout) {
408 if send_stop {
409 self.master_stop();
410 }
411 return Err(err);
412 }
403 413
404 T::regs().txdr().write(|w| w.set_txdata(*byte)); 414 T::regs().txdr().write(|w| w.set_txdata(*byte));
405 } 415 }
406 } 416 }
407 // Wait until the write finishes 417 // Wait until the write finishes
408 self.wait_tc(&check_timeout)?; 418 let result = self.wait_tc(&check_timeout);
409
410 if send_stop { 419 if send_stop {
411 self.master_stop(); 420 self.master_stop();
412 } 421 }
413 Ok(()) 422 result
414 } 423 }
415 424
416 async fn write_dma_internal( 425 async fn write_dma_internal(
@@ -707,13 +716,16 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
707 let first_length = write[0].len(); 716 let first_length = write[0].len();
708 let last_slice_index = write.len() - 1; 717 let last_slice_index = write.len() - 1;
709 718
710 Self::master_write( 719 if let Err(err) = Self::master_write(
711 address, 720 address,
712 first_length.min(255), 721 first_length.min(255),
713 Stop::Software, 722 Stop::Software,
714 (first_length > 255) || (last_slice_index != 0), 723 (first_length > 255) || (last_slice_index != 0),
715 &check_timeout, 724 &check_timeout,
716 )?; 725 ) {
726 self.master_stop();
727 return Err(err);
728 }
717 729
718 for (idx, slice) in write.iter().enumerate() { 730 for (idx, slice) in write.iter().enumerate() {
719 let slice_len = slice.len(); 731 let slice_len = slice.len();
@@ -726,27 +738,36 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
726 let last_chunk_idx = total_chunks.saturating_sub(1); 738 let last_chunk_idx = total_chunks.saturating_sub(1);
727 739
728 if idx != 0 { 740 if idx != 0 {
729 Self::master_continue( 741 if let Err(err) = Self::master_continue(
730 slice_len.min(255), 742 slice_len.min(255),
731 (idx != last_slice_index) || (slice_len > 255), 743 (idx != last_slice_index) || (slice_len > 255),
732 &check_timeout, 744 &check_timeout,
733 )?; 745 ) {
746 self.master_stop();
747 return Err(err);
748 }
734 } 749 }
735 750
736 for (number, chunk) in slice.chunks(255).enumerate() { 751 for (number, chunk) in slice.chunks(255).enumerate() {
737 if number != 0 { 752 if number != 0 {
738 Self::master_continue( 753 if let Err(err) = Self::master_continue(
739 chunk.len(), 754 chunk.len(),
740 (number != last_chunk_idx) || (idx != last_slice_index), 755 (number != last_chunk_idx) || (idx != last_slice_index),
741 &check_timeout, 756 &check_timeout,
742 )?; 757 ) {
758 self.master_stop();
759 return Err(err);
760 }
743 } 761 }
744 762
745 for byte in chunk { 763 for byte in chunk {
746 // Wait until we are allowed to send data 764 // Wait until we are allowed to send data
747 // (START has been ACKed or last byte when 765 // (START has been ACKed or last byte when
748 // through) 766 // through)
749 self.wait_txe(&check_timeout)?; 767 if let Err(err) = self.wait_txe(&check_timeout) {
768 self.master_stop();
769 return Err(err);
770 }
750 771
751 // Put byte on the wire 772 // Put byte on the wire
752 //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); 773 //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
@@ -755,10 +776,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
755 } 776 }
756 } 777 }
757 // Wait until the write finishes 778 // Wait until the write finishes
758 self.wait_tc(&check_timeout)?; 779 let result = self.wait_tc(&check_timeout);
759 self.master_stop(); 780 self.master_stop();
760 781 result
761 Ok(())
762 } 782 }
763 783
764 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { 784 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {