diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-07-12 15:46:28 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-07-12 15:46:28 +0000 |
| commit | ed86fc175fdf44ec69146decee2949046a191dbc (patch) | |
| tree | c302e8d06a430683e95d50068dbb29dcadfc8ab6 | |
| parent | 132327a40d7d0f1f270d73178feb8653bd0aab49 (diff) | |
| parent | 29f3d5b68d3b5949de35227359bf631661613b14 (diff) | |
Merge pull request #1637 from ShakenCodes/main
Ensure I2C master_stop() called after error
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 52 |
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> { |
