diff --git a/CHANGELOG.md b/CHANGELOG.md index b17782953..5f7d1ff19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed + - Optimized version of blocking SPI write - Support `u16` read/write for SPI - Use `bool` for BIDI mode type - `PwmHz::get_period`: fix computation of return value, prevent division by zero diff --git a/src/spi.rs b/src/spi.rs index 949c87c16..129649f0d 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -676,6 +676,40 @@ impl nb::Error::WouldBlock }) } + + // Implement write as per the "Transmit only procedure" + // RM SPI::3.5. This is more than twice as fast as the + // default Write<> implementation (which reads and drops each + // received value) + fn spi_write(&mut self, words: WI) -> Result<(), Error> + where + WI: IntoIterator, + { + if BIDI { + self.spi.cr1.modify(|_, w| w.bidioe().set_bit()); + } + // Write each word when the tx buffer is empty + for word in words { + loop { + let sr = self.spi.sr.read(); + if sr.txe().bit_is_set() { + self.write_data_reg(word); + if sr.modf().bit_is_set() { + return Err(Error::ModeFault); + } + break; + } + } + } + // Wait for final TXE + while !self.is_tx_empty() {} + // Wait for final !BSY + while self.is_busy() {} + // Clear OVR set due to dropped received values + let _ = self.read_data_reg(); + let _ = self.spi.sr.read(); + Ok(()) + } } // Spi DMA diff --git a/src/spi/hal_02.rs b/src/spi/hal_02.rs index b91e6de36..0bc113b65 100644 --- a/src/spi/hal_02.rs +++ b/src/spi/hal_02.rs @@ -97,7 +97,7 @@ mod blocking { type Error = Error; fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { - self.write_iter(words.iter().copied()) + self.spi_write(words.iter().copied()) } } @@ -111,14 +111,7 @@ mod blocking { where WI: IntoIterator, { - for word in words.into_iter() { - nb::block!(self.send(word))?; - if !BIDI { - nb::block!(self.read())?; - } - } - - Ok(()) + self.spi_write(words) } } diff --git a/src/spi/hal_1.rs b/src/spi/hal_1.rs index a2860dcb6..2654b5540 100644 --- a/src/spi/hal_1.rs +++ b/src/spi/hal_1.rs @@ -111,14 +111,7 @@ mod blocking { SPI: Instance, { fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { - for word in words { - nb::block!(>::write(self, *word))?; - if !BIDI { - nb::block!(>::read(self))?; - } - } - - Ok(()) + self.spi_write(words.iter().copied()) } }