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 <rmja@laesoe.org>
This commit is contained in:
		| @@ -78,8 +78,7 @@ foreach_dma_channel! { | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             unsafe fn start_write_repeated<W: Word>(&mut self, _request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) { | ||||
|                 let buf = [repeated]; | ||||
|             unsafe fn start_write_repeated<W: Word>(&mut self, _request: Request, repeated: *const W, count: usize, reg_addr: *mut W, options: TransferOptions) { | ||||
|                 low_level_api::start_transfer( | ||||
|                     pac::$dma_peri, | ||||
|                     $channel_num, | ||||
| @@ -87,7 +86,7 @@ foreach_dma_channel! { | ||||
|                     _request, | ||||
|                     vals::Dir::FROMMEMORY, | ||||
|                     reg_addr as *const u32, | ||||
|                     buf.as_ptr() as *mut u32, | ||||
|                     repeated as *mut u32, | ||||
|                     count, | ||||
|                     false, | ||||
|                     vals::Size::from(W::bits()), | ||||
|   | ||||
| @@ -102,15 +102,14 @@ foreach_dma_channel! { | ||||
|                 ) | ||||
|             } | ||||
|  | ||||
|             unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) { | ||||
|                 let buf = [repeated]; | ||||
|             unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: *const W, count: usize, reg_addr: *mut W, options: TransferOptions) { | ||||
|                 low_level_api::start_transfer( | ||||
|                     pac::$dma_peri, | ||||
|                     $channel_num, | ||||
|                     request, | ||||
|                     vals::Dir::MEMORYTOPERIPHERAL, | ||||
|                     reg_addr as *const u32, | ||||
|                     buf.as_ptr() as *mut u32, | ||||
|                     repeated as *mut u32, | ||||
|                     count, | ||||
|                     false, | ||||
|                     vals::Size::from(W::bits()), | ||||
|   | ||||
| @@ -75,15 +75,14 @@ foreach_dma_channel! { | ||||
|                 ) | ||||
|             } | ||||
|  | ||||
|             unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) { | ||||
|                 let buf = [repeated]; | ||||
|             unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: *const W, count: usize, reg_addr: *mut W, options: TransferOptions) { | ||||
|                 low_level_api::start_transfer( | ||||
|                     pac::$dma_peri, | ||||
|                     $channel_num, | ||||
|                     request, | ||||
|                     low_level_api::Dir::MemoryToPeripheral, | ||||
|                     reg_addr as *const u32, | ||||
|                     buf.as_ptr() as *mut u32, | ||||
|                     repeated as *mut u32, | ||||
|                     count, | ||||
|                     false, | ||||
|                     W::bits(), | ||||
|   | ||||
| @@ -59,7 +59,7 @@ pub(crate) mod sealed { | ||||
|         unsafe fn start_write_repeated<W: super::Word>( | ||||
|             &mut self, | ||||
|             request: Request, | ||||
|             repeated: W, | ||||
|             repeated: *const W, | ||||
|             count: usize, | ||||
|             reg_addr: *mut W, | ||||
|             options: TransferOptions, | ||||
| @@ -246,7 +246,7 @@ mod transfers { | ||||
|     pub fn write_repeated<'a, W: Word>( | ||||
|         channel: impl Peripheral<P = impl Channel> + 'a, | ||||
|         request: Request, | ||||
|         repeated: W, | ||||
|         repeated: *const W, | ||||
|         count: usize, | ||||
|         reg_addr: *mut W, | ||||
|     ) -> impl Future<Output = ()> + 'a { | ||||
|   | ||||
| @@ -95,13 +95,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||||
|         into_ref!(peri, sck, mosi, miso); | ||||
|         unsafe { | ||||
|             sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||||
|             sck.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||||
|             mosi.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             miso.set_as_af(miso.af_num(), AFType::Input); | ||||
|             #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||||
|             miso.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|         } | ||||
|  | ||||
| @@ -129,10 +126,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||||
|         into_ref!(sck, miso); | ||||
|         unsafe { | ||||
|             sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||||
|             sck.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             miso.set_as_af(miso.af_num(), AFType::Input); | ||||
|             #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||||
|             miso.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|         } | ||||
|  | ||||
| @@ -160,10 +155,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||||
|         into_ref!(sck, mosi); | ||||
|         unsafe { | ||||
|             sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||||
|             sck.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3, spi_v4))] | ||||
|             mosi.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|         } | ||||
|  | ||||
| @@ -474,7 +467,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||||
|         let tx_request = self.txdma.request(); | ||||
|         let tx_dst = T::REGS.tx_ptr(); | ||||
|         let clock_byte = 0x00u8; | ||||
|         let tx_f = crate::dma::write_repeated(&mut self.txdma, tx_request, clock_byte, clock_byte_count, tx_dst); | ||||
|         let tx_f = crate::dma::write_repeated(&mut self.txdma, tx_request, &clock_byte, clock_byte_count, tx_dst); | ||||
|  | ||||
|         unsafe { | ||||
|             set_txdmaen(T::REGS, true); | ||||
| @@ -772,10 +765,13 @@ fn finish_dma(regs: Regs) { | ||||
|         #[cfg(not(any(spi_v3, spi_v4)))] | ||||
|         while regs.sr().read().bsy() {} | ||||
|  | ||||
|         // Disable the spi peripheral | ||||
|         regs.cr1().modify(|w| { | ||||
|             w.set_spe(false); | ||||
|         }); | ||||
|  | ||||
|         // The peripheral automatically disables the DMA stream on completion without error, | ||||
|         // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. | ||||
|         #[cfg(not(any(spi_v3, spi_v4)))] | ||||
|         regs.cr2().modify(|reg| { | ||||
|             reg.set_txdmaen(false); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user