From b9a82455ffa967b5612ec5ecee52c2b11d45e6cc Mon Sep 17 00:00:00 2001 From: Finomnis Date: Sat, 27 Apr 2024 16:17:56 -0400 Subject: [PATCH] Enable LPSPI watermark change while enabled Unlike LPUART, there's no requirement to be disabled while changing this. Keep the existing API, and point users towards the new method. Co-authored-by: Ian McIntyre --- CHANGELOG.md | 2 ++ examples/rtic_spi.rs | 10 +++----- src/common/lpspi.rs | 58 +++++++++++++++++++++++++++++++------------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9df8a898..e1faed3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Introduce LPSPI improvements: - Add `soft_reset()` method. - Allow users to change the mode while enabled. Deprecate the corresponding method on the `Disabled` helper. +- Allow users to change the watermark while enabled. Deprecate the corresponding + method on the `Disabled` helper. ## [0.5.4] 2023-11-26 diff --git a/examples/rtic_spi.rs b/examples/rtic_spi.rs index 29fe5faa..8a50c4c0 100644 --- a/examples/rtic_spi.rs +++ b/examples/rtic_spi.rs @@ -25,12 +25,10 @@ mod app { #[init] fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { let (_, board::Specifics { mut spi, .. }) = board::new(); - spi.disabled(|spi| { - // Trigger when the TX FIFO is empty. - spi.set_watermark(Direction::Tx, 0); - // Wait to receive at least 2 u32s. - spi.set_watermark(Direction::Rx, 1); - }); + // Trigger when the TX FIFO is empty. + spi.set_watermark(Direction::Tx, 0); + // Wait to receive at least 2 u32s. + spi.set_watermark(Direction::Rx, 1); // Starts the I/O as soon as we're done initializing, since // the TX FIFO is empty. spi.set_interrupts(Interrupts::TRANSMIT_DATA); diff --git a/src/common/lpspi.rs b/src/common/lpspi.rs index 72a2d33e..c2c03115 100644 --- a/src/common/lpspi.rs +++ b/src/common/lpspi.rs @@ -898,6 +898,21 @@ impl Lpspi { // Restore enabled state self.set_enable(enabled); } + + /// Set the watermark level for a given direction. + /// + /// Returns the watermark level committed to the hardware. This may be different + /// than the supplied `watermark`, since it's limited by the hardware. + /// + /// When `direction == Direction::Rx`, the receive data flag is set whenever the + /// number of words in the receive FIFO is greater than `watermark`. + /// + /// When `direction == Direction::Tx`, the transmit data flag is set whenever the + /// the number of words in the transmit FIFO is less than, or equal, to `watermark`. + #[inline] + pub fn set_watermark(&mut self, direction: Direction, watermark: u8) -> u8 { + set_watermark(&self.lpspi, direction, watermark) + } } bitflags::bitflags! { @@ -1029,6 +1044,27 @@ bitflags::bitflags! { } } +#[inline] +fn set_watermark(lpspi: &ral::lpspi::RegisterBlock, direction: Direction, watermark: u8) -> u8 { + let max_watermark = match direction { + Direction::Rx => 1 << ral::read_reg!(ral::lpspi, lpspi, PARAM, RXFIFO), + Direction::Tx => 1 << ral::read_reg!(ral::lpspi, lpspi, PARAM, TXFIFO), + }; + + let watermark = watermark.min(max_watermark - 1); + + match direction { + Direction::Rx => { + ral::modify_reg!(ral::lpspi, lpspi, FCR, RXWATER: watermark as u32) + } + Direction::Tx => { + ral::modify_reg!(ral::lpspi, lpspi, FCR, TXWATER: watermark as u32) + } + } + + watermark +} + /// An LPSPI peripheral which is temporarily disabled. pub struct Disabled<'a, const N: u8> { lpspi: &'a ral::lpspi::Instance, @@ -1076,24 +1112,12 @@ impl<'a, const N: u8> Disabled<'a, N> { /// When `direction == Direction::Tx`, the transmit data flag is set whenever the /// the number of words in the transmit FIFO is less than, or equal, to `watermark`. #[inline] + #[deprecated( + since = "0.5.5", + note = "Use Lpspi::set_watermark to change watermark while enabled" + )] pub fn set_watermark(&mut self, direction: Direction, watermark: u8) -> u8 { - let max_watermark = match direction { - Direction::Rx => 1 << ral::read_reg!(ral::lpspi, self.lpspi, PARAM, RXFIFO), - Direction::Tx => 1 << ral::read_reg!(ral::lpspi, self.lpspi, PARAM, TXFIFO), - }; - - let watermark = watermark.min(max_watermark - 1); - - match direction { - Direction::Rx => { - ral::modify_reg!(ral::lpspi, self.lpspi, FCR, RXWATER: watermark as u32) - } - Direction::Tx => { - ral::modify_reg!(ral::lpspi, self.lpspi, FCR, TXWATER: watermark as u32) - } - } - - watermark + set_watermark(self.lpspi, direction, watermark) } /// Set the sampling point of the LPSPI peripheral.