diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-12-23 15:53:59 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-12-23 15:53:59 +0000 |
| commit | 40ef66cdfb03ceef9671bd95c7dbe46a5155df73 (patch) | |
| tree | ed1b8999e0760b2e526c8635e9919b4de8985fd1 | |
| parent | 1bd6c954c23b16041b382243a844a53727f6cc9c (diff) | |
| parent | 47a0769fc287afa8c982514ea34de0d4f18a3f99 (diff) | |
Merge #1124
1124: Fix two SPI bugs for stm32 r=Dirbaio a=rmja
This PR fixes two bugs:
* It fixes #1095 by ensuring that pin speed is VeryHigh for all spi versions. I am on stm32f429 which seems to be spi_v1, and it also needs the VeryHigh pin speed. Otherwise bit errors on the "last bit in every byte" can happen.
* It also fixes a lifetime bug for the tx buffer when sending "write_repeated". The issue can be seen when doing spi.write where the clock byte changes during a transmission because the buffer handled to the dma must live throughout the entire transfer.
Co-authored-by: Rasmus Melchior Jacobsen <[email protected]>
| -rw-r--r-- | embassy-stm32/src/dma/bdma.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/dma.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/gpdma.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 12 |
5 files changed, 12 insertions, 19 deletions
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index e6ce05b7b..6160b9f40 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs | |||
| @@ -78,8 +78,7 @@ foreach_dma_channel! { | |||
| 78 | ); | 78 | ); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | unsafe fn start_write_repeated<W: Word>(&mut self, _request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) { | 81 | unsafe fn start_write_repeated<W: Word>(&mut self, _request: Request, repeated: *const W, count: usize, reg_addr: *mut W, options: TransferOptions) { |
| 82 | let buf = [repeated]; | ||
| 83 | low_level_api::start_transfer( | 82 | low_level_api::start_transfer( |
| 84 | pac::$dma_peri, | 83 | pac::$dma_peri, |
| 85 | $channel_num, | 84 | $channel_num, |
| @@ -87,7 +86,7 @@ foreach_dma_channel! { | |||
| 87 | _request, | 86 | _request, |
| 88 | vals::Dir::FROMMEMORY, | 87 | vals::Dir::FROMMEMORY, |
| 89 | reg_addr as *const u32, | 88 | reg_addr as *const u32, |
| 90 | buf.as_ptr() as *mut u32, | 89 | repeated as *mut u32, |
| 91 | count, | 90 | count, |
| 92 | false, | 91 | false, |
| 93 | vals::Size::from(W::bits()), | 92 | vals::Size::from(W::bits()), |
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 97a3df088..fec60f708 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs | |||
| @@ -102,15 +102,14 @@ foreach_dma_channel! { | |||
| 102 | ) | 102 | ) |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) { | 105 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: *const W, count: usize, reg_addr: *mut W, options: TransferOptions) { |
| 106 | let buf = [repeated]; | ||
| 107 | low_level_api::start_transfer( | 106 | low_level_api::start_transfer( |
| 108 | pac::$dma_peri, | 107 | pac::$dma_peri, |
| 109 | $channel_num, | 108 | $channel_num, |
| 110 | request, | 109 | request, |
| 111 | vals::Dir::MEMORYTOPERIPHERAL, | 110 | vals::Dir::MEMORYTOPERIPHERAL, |
| 112 | reg_addr as *const u32, | 111 | reg_addr as *const u32, |
| 113 | buf.as_ptr() as *mut u32, | 112 | repeated as *mut u32, |
| 114 | count, | 113 | count, |
| 115 | false, | 114 | false, |
| 116 | vals::Size::from(W::bits()), | 115 | vals::Size::from(W::bits()), |
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index bde8c3ef3..d252cef3e 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs | |||
| @@ -75,15 +75,14 @@ foreach_dma_channel! { | |||
| 75 | ) | 75 | ) |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) { | 78 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: *const W, count: usize, reg_addr: *mut W, options: TransferOptions) { |
| 79 | let buf = [repeated]; | ||
| 80 | low_level_api::start_transfer( | 79 | low_level_api::start_transfer( |
| 81 | pac::$dma_peri, | 80 | pac::$dma_peri, |
| 82 | $channel_num, | 81 | $channel_num, |
| 83 | request, | 82 | request, |
| 84 | low_level_api::Dir::MemoryToPeripheral, | 83 | low_level_api::Dir::MemoryToPeripheral, |
| 85 | reg_addr as *const u32, | 84 | reg_addr as *const u32, |
| 86 | buf.as_ptr() as *mut u32, | 85 | repeated as *mut u32, |
| 87 | count, | 86 | count, |
| 88 | false, | 87 | false, |
| 89 | W::bits(), | 88 | W::bits(), |
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 74bce6aa9..b51e0d40b 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -59,7 +59,7 @@ pub(crate) mod sealed { | |||
| 59 | unsafe fn start_write_repeated<W: super::Word>( | 59 | unsafe fn start_write_repeated<W: super::Word>( |
| 60 | &mut self, | 60 | &mut self, |
| 61 | request: Request, | 61 | request: Request, |
| 62 | repeated: W, | 62 | repeated: *const W, |
| 63 | count: usize, | 63 | count: usize, |
| 64 | reg_addr: *mut W, | 64 | reg_addr: *mut W, |
| 65 | options: TransferOptions, | 65 | options: TransferOptions, |
| @@ -246,7 +246,7 @@ mod transfers { | |||
| 246 | pub fn write_repeated<'a, W: Word>( | 246 | pub fn write_repeated<'a, W: Word>( |
| 247 | channel: impl Peripheral<P = impl Channel> + 'a, | 247 | channel: impl Peripheral<P = impl Channel> + 'a, |
| 248 | request: Request, | 248 | request: Request, |
| 249 | repeated: W, | 249 | repeated: *const W, |
| 250 | count: usize, | 250 | count: usize, |
| 251 | reg_addr: *mut W, | 251 | reg_addr: *mut W, |
| 252 | ) -> impl Future<Output = ()> + 'a { | 252 | ) -> impl Future<Output = ()> + 'a { |
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index ab4352a5c..5b81c791a 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -95,13 +95,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 95 | into_ref!(peri, sck, mosi, miso); | 95 | into_ref!(peri, sck, mosi, miso); |
| 96 | unsafe { | 96 | unsafe { |
| 97 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | 97 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); |
| 98 | #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||
| 99 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 98 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 100 | mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); | 99 | mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); |
| 101 | #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||
| 102 | mosi.set_speed(crate::gpio::Speed::VeryHigh); | 100 | mosi.set_speed(crate::gpio::Speed::VeryHigh); |
| 103 | miso.set_as_af(miso.af_num(), AFType::Input); | 101 | miso.set_as_af(miso.af_num(), AFType::Input); |
| 104 | #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||
| 105 | miso.set_speed(crate::gpio::Speed::VeryHigh); | 102 | miso.set_speed(crate::gpio::Speed::VeryHigh); |
| 106 | } | 103 | } |
| 107 | 104 | ||
| @@ -129,10 +126,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 129 | into_ref!(sck, miso); | 126 | into_ref!(sck, miso); |
| 130 | unsafe { | 127 | unsafe { |
| 131 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | 128 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); |
| 132 | #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||
| 133 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 129 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 134 | miso.set_as_af(miso.af_num(), AFType::Input); | 130 | miso.set_as_af(miso.af_num(), AFType::Input); |
| 135 | #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||
| 136 | miso.set_speed(crate::gpio::Speed::VeryHigh); | 131 | miso.set_speed(crate::gpio::Speed::VeryHigh); |
| 137 | } | 132 | } |
| 138 | 133 | ||
| @@ -160,10 +155,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 160 | into_ref!(sck, mosi); | 155 | into_ref!(sck, mosi); |
| 161 | unsafe { | 156 | unsafe { |
| 162 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | 157 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); |
| 163 | #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||
| 164 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 158 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 165 | mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); | 159 | mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); |
| 166 | #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||
| 167 | mosi.set_speed(crate::gpio::Speed::VeryHigh); | 160 | mosi.set_speed(crate::gpio::Speed::VeryHigh); |
| 168 | } | 161 | } |
| 169 | 162 | ||
| @@ -474,7 +467,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | |||
| 474 | let tx_request = self.txdma.request(); | 467 | let tx_request = self.txdma.request(); |
| 475 | let tx_dst = T::REGS.tx_ptr(); | 468 | let tx_dst = T::REGS.tx_ptr(); |
| 476 | let clock_byte = 0x00u8; | 469 | let clock_byte = 0x00u8; |
| 477 | let tx_f = crate::dma::write_repeated(&mut self.txdma, tx_request, clock_byte, clock_byte_count, tx_dst); | 470 | let tx_f = crate::dma::write_repeated(&mut self.txdma, tx_request, &clock_byte, clock_byte_count, tx_dst); |
| 478 | 471 | ||
| 479 | unsafe { | 472 | unsafe { |
| 480 | set_txdmaen(T::REGS, true); | 473 | set_txdmaen(T::REGS, true); |
| @@ -772,10 +765,13 @@ fn finish_dma(regs: Regs) { | |||
| 772 | #[cfg(not(any(spi_v3, spi_v4)))] | 765 | #[cfg(not(any(spi_v3, spi_v4)))] |
| 773 | while regs.sr().read().bsy() {} | 766 | while regs.sr().read().bsy() {} |
| 774 | 767 | ||
| 768 | // Disable the spi peripheral | ||
| 775 | regs.cr1().modify(|w| { | 769 | regs.cr1().modify(|w| { |
| 776 | w.set_spe(false); | 770 | w.set_spe(false); |
| 777 | }); | 771 | }); |
| 778 | 772 | ||
| 773 | // The peripheral automatically disables the DMA stream on completion without error, | ||
| 774 | // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. | ||
| 779 | #[cfg(not(any(spi_v3, spi_v4)))] | 775 | #[cfg(not(any(spi_v3, spi_v4)))] |
| 780 | regs.cr2().modify(|reg| { | 776 | regs.cr2().modify(|reg| { |
| 781 | reg.set_txdmaen(false); | 777 | reg.set_txdmaen(false); |
