Skip to content

Commit

Permalink
Enable LPSPI watermark change while enabled
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Finomnis and mciantyre committed May 9, 2024
1 parent 3a45814 commit b9a8245
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 23 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 4 additions & 6 deletions examples/rtic_spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
58 changes: 41 additions & 17 deletions src/common/lpspi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,21 @@ impl<P, const N: u8> Lpspi<P, N> {
// 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! {
Expand Down Expand Up @@ -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<N>,
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit b9a8245

Please sign in to comment.