Skip to content

Commit 0f5cdc8

Browse files
committed
optimized Spi::write
1 parent df01d0d commit 0f5cdc8

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
@@ -676,6 +676,40 @@ impl<SPI: Instance, PINS, const BIDI: bool, W: FrameSize, OPERATION>
676676
nb::Error::WouldBlock
677677
})
678678
}
679+
680+
// Implement write as per the "Transmit only procedure"
681+
// RM SPI::3.5. This is more than twice as fast as the
682+
// default Write<> implementation (which reads and drops each
683+
// received value)
684+
fn spi_write<WI>(&mut self, words: WI) -> Result<(), Error>
685+
where
686+
WI: IntoIterator<Item = W>,
687+
{
688+
if BIDI {
689+
self.spi.cr1.modify(|_, w| w.bidioe().set_bit());
690+
}
691+
// Write each word when the tx buffer is empty
692+
for word in words {
693+
loop {
694+
let sr = self.spi.sr.read();
695+
if sr.txe().bit_is_set() {
696+
self.write_data_reg(word);
697+
if sr.modf().bit_is_set() {
698+
return Err(Error::ModeFault);
699+
}
700+
break;
701+
}
702+
}
703+
}
704+
// Wait for final TXE
705+
while !self.is_tx_empty() {}
706+
// Wait for final !BSY
707+
while self.is_busy() {}
708+
// Clear OVR set due to dropped received values
709+
let _ = self.read_data_reg();
710+
let _ = self.spi.sr.read();
711+
Ok(())
712+
}
679713
}
680714

681715
// 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)