Skip to content

Commit 84d3336

Browse files
committed
optimized Spi::write
1 parent 087043e commit 84d3336

File tree

4 files changed

+38
-17
lines changed

4 files changed

+38
-17
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Changed
1111

12+
- Optimized version of blocking SPI write
1213
- Support `u16` read/write for SPI
1314
- Use `bool` for BIDI mode type
1415
- `PwmHz::get_period`: fix computation of return value, prevent division by zero

src/spi.rs

+34
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,40 @@ impl<SPI: Instance, PINS, const BIDI: bool, W: FrameSize, OPERATION>
659659
nb::Error::WouldBlock
660660
})
661661
}
662+
663+
// Implement write as per the "Transmit only procedure"
664+
// RM SPI::3.5. This is more than twice as fast as the
665+
// default Write<> implementation (which reads and drops each
666+
// received value)
667+
fn spi_write<WI>(&mut self, words: WI) -> Result<(), Error>
668+
where
669+
WI: IntoIterator<Item = W>,
670+
{
671+
if BIDI {
672+
self.spi.cr1.modify(|_, w| w.bidioe().set_bit());
673+
}
674+
// Write each word when the tx buffer is empty
675+
for word in words {
676+
loop {
677+
let sr = self.spi.sr.read();
678+
if sr.txe().bit_is_set() {
679+
self.write_data_reg(word);
680+
if sr.modf().bit_is_set() {
681+
return Err(Error::ModeFault);
682+
}
683+
break;
684+
}
685+
}
686+
}
687+
// Wait for final TXE
688+
while !self.is_tx_empty() {}
689+
// Wait for final !BSY
690+
while self.is_busy() {}
691+
// Clear OVR set due to dropped received values
692+
let _ = self.read_data_reg();
693+
let _ = self.spi.sr.read();
694+
Ok(())
695+
}
662696
}
663697

664698
// Spi DMA

src/spi/hal_02.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ mod blocking {
9797
type Error = Error;
9898

9999
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
100-
self.write_iter(words.iter().copied())
100+
self.spi_write(words.iter().copied())
101101
}
102102
}
103103

@@ -111,14 +111,7 @@ mod blocking {
111111
where
112112
WI: IntoIterator<Item = u8>,
113113
{
114-
for word in words.into_iter() {
115-
nb::block!(self.send(word))?;
116-
if !BIDI {
117-
nb::block!(self.read())?;
118-
}
119-
}
120-
121-
Ok(())
114+
self.spi_write(words)
122115
}
123116
}
124117

src/spi/hal_1.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,7 @@ mod blocking {
111111
SPI: Instance,
112112
{
113113
fn write(&mut self, words: &[W]) -> Result<(), Self::Error> {
114-
for word in words {
115-
nb::block!(<Self as FullDuplex<W>>::write(self, *word))?;
116-
if !BIDI {
117-
nb::block!(<Self as FullDuplex<W>>::read(self))?;
118-
}
119-
}
120-
121-
Ok(())
114+
self.spi_write(words.iter().copied())
122115
}
123116
}
124117

0 commit comments

Comments
 (0)