Skip to content

Commit

Permalink
optimized Spi::write & move BSY to Spi::disable
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Jul 27, 2024
1 parent d4e41b1 commit 54408f1
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 15 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Use `stm32f4-staging` until `stm32f4` is released [#706]
- RTIC2 monotonics fix: CC1 instead of CC3
- Allow different lengths of buffers in hal_1 SpiBus impl [#566]
- Clean SPI write impls
- Optimized version of blocking SPI write [#523]
- `steal` UART peripheral on `Rx::new`

[#248]: https://github.com/stm32-rs/stm32f4xx-hal/pull/248
[#523]: https://github.com/stm32-rs/stm32f4xx-hal/pull/523
[#566]: https://github.com/stm32-rs/stm32f4xx-hal/pull/566
[#706]: https://github.com/stm32-rs/stm32f4xx-hal/pull/706
[#731]: https://github.com/stm32-rs/stm32f4xx-hal/pull/731
Expand Down
66 changes: 52 additions & 14 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ impl<SPI: Instance, const BIDI: bool, W> Spi<SPI, BIDI, W> {
/// Convert the spi to another mode.
fn into_mode<const BIDI2: bool, W2: FrameSize>(self) -> Spi<SPI, BIDI2, W2> {
let mut spi = Spi::_new(self.inner.spi, self.pins);
spi.enable(false);
spi.disable();
spi.init()
}
}
Expand All @@ -606,7 +606,7 @@ impl<SPI: Instance, const BIDI: bool, W> SpiSlave<SPI, BIDI, W> {
/// Convert the spi to another mode.
fn into_mode<const BIDI2: bool, W2: FrameSize>(self) -> SpiSlave<SPI, BIDI2, W2> {
let mut spi = SpiSlave::_new(self.inner.spi, self.pins);
spi.enable(false);
spi.disable();
spi.init()
}
}
Expand Down Expand Up @@ -685,11 +685,21 @@ impl<SPI: Instance> Inner<SPI> {
Self { spi }
}

/// Enable/disable spi
pub fn enable(&mut self, enable: bool) {
/// Enable SPI
pub fn enable(&mut self) {
self.spi.cr1().modify(|_, w| {
// spe: enable the SPI bus
w.spe().bit(enable)
w.spe().set_bit()
});
}

/// Disable SPI
pub fn disable(&mut self) {
// Wait for !BSY
while self.is_busy() {}
self.spi.cr1().modify(|_, w| {
// spe: enable the SPI bus
w.spe().clear_bit()
});
}

Expand Down Expand Up @@ -734,6 +744,19 @@ impl<SPI: Instance> Inner<SPI> {
self.spi.sr().read().ovr().bit_is_set()
}

fn check_errors(&self) -> Result<(), Error> {
let sr = self.spi.sr().read();
if sr.ovr().bit_is_set() {
Err(Error::Overrun)
} else if sr.modf().bit_is_set() {
Err(Error::ModeFault)
} else if sr.crcerr().bit_is_set() {
Err(Error::Crc)
} else {
Ok(())
}
}

#[inline]
fn bidi_output(&mut self) {
self.spi.cr1().modify(|_, w| w.bidioe().set_bit());
Expand Down Expand Up @@ -798,23 +821,38 @@ impl<SPI: Instance> Inner<SPI> {
})
}

// 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<const BIDI: bool, W: FrameSize>(
&mut self,
words: impl IntoIterator<Item = W>,
) -> Result<(), Error> {
if BIDI {
self.bidi_output();
for word in words.into_iter() {
nb::block!(self.check_send(word))?;
}
} else {
for word in words.into_iter() {
nb::block!(self.check_send(word))?;
nb::block!(self.check_read::<W>())?;
}
// 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;
}
}
}

Ok(())
// Wait for final TXE
while !self.is_tx_empty() {}
if !BIDI {
// Clear OVR set due to dropped received values
let _: W = self.read_data_reg();
}
let _ = self.spi.sr().read();
self.check_errors()
}

fn listen_event(&mut self, disable: Option<BitFlags<Event>>, enable: Option<BitFlags<Event>>) {
Expand Down

0 comments on commit 54408f1

Please sign in to comment.