Skip to content

Commit 85851d1

Browse files
timbod7TheZoq2
authored andcommitted
Replace default blocking spi Write implementation with an optimized one
1 parent 914ef01 commit 85851d1

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
- Replace default blocking spi Write implementation with an optimized one
1011
- Use `Deref` for SPI generic implementations instead of macros
1112
- Make traits `rcc::Enable` and `rcc::Reset` public, but `RccBus` sealed
1213
- Add `QeiOptions` struct to configure slave mode and auto reload value of QEI interface

src/spi.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use core::ptr;
3535

3636
use nb;
3737

38-
pub use crate::hal::spi::{Mode, Phase, Polarity};
38+
pub use crate::hal::spi::{Mode, Phase, Polarity, FullDuplex};
3939
#[cfg(feature = "high")]
4040
use crate::pac::SPI3;
4141
use crate::pac::{SPI1, SPI2};
@@ -334,9 +334,52 @@ impl<SPI, REMAP, PINS> crate::hal::blocking::spi::transfer::Default<u8> for Spi<
334334
{
335335
}
336336

337-
impl<SPI, REMAP, PINS> crate::hal::blocking::spi::write::Default<u8> for Spi<SPI, REMAP, PINS> where
337+
impl<SPI, REMAP, PINS> crate::hal::blocking::spi::Write<u8> for Spi<SPI, REMAP, PINS> where
338338
SPI: Deref<Target = SpiRegisterBlock>
339339
{
340+
type Error = Error;
341+
342+
// Implement write as per the "Transmit only procedure" page 712
343+
// of RM0008 Rev 20. This is more than twice as fast as the
344+
// default Write<> implementation (which reads and drops each
345+
// received value)
346+
fn write(&mut self, words: &[u8]) -> Result<(), Error> {
347+
// Write each word when the tx buffer is empty
348+
for word in words {
349+
loop {
350+
let sr = self.spi.sr.read();
351+
if sr.txe().bit_is_set() {
352+
// NOTE(write_volatile) see note above
353+
unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, *word) }
354+
if sr.modf().bit_is_set() {
355+
return Err(Error::ModeFault);
356+
}
357+
break;
358+
}
359+
}
360+
}
361+
// Wait for final TXE
362+
loop {
363+
let sr = self.spi.sr.read();
364+
if sr.txe().bit_is_set() {
365+
break;
366+
}
367+
}
368+
// Wait for final !BSY
369+
loop {
370+
let sr = self.spi.sr.read();
371+
if !sr.bsy().bit_is_set() {
372+
break;
373+
}
374+
}
375+
// Clear OVR set due to dropped received values
376+
// NOTE(read_volatile) see note aboev
377+
unsafe {
378+
let _ = ptr::read_volatile(&self.spi.dr as *const _ as *const u8);
379+
}
380+
let _ = self.spi.sr.read();
381+
Ok(())
382+
}
340383
}
341384

342385
// DMA

0 commit comments

Comments
 (0)