Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add non-breaking LPSPI rework #156

Merged
merged 8 commits into from
May 9, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rework LPSPI clock settings
- Make sure we never get a baud rate faster than specified (slower is
  pretty much always ok for peripherals)
- Configure PCSSCK and SCKPCS properly for contiguous transfers
  • Loading branch information
Finomnis authored and mciantyre committed May 9, 2024
commit 49d534f07a9973858b7f814d753905fcbced5ee7
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ Add embedded-hal 1 implementations for the following drivers:
Introduce LPSPI improvements:

- Add additional checks for LPSPI frame sizes.
- Rework LPSPI clock settings.

## [0.5.4] 2023-11-26

39 changes: 21 additions & 18 deletions src/common/lpspi.rs
Original file line number Diff line number Diff line change
@@ -306,24 +306,27 @@ impl Transaction {
///
/// This should only happen when the LPSPI peripheral is disabled.
fn set_spi_clock(source_clock_hz: u32, spi_clock_hz: u32, reg: &ral::lpspi::RegisterBlock) {
let mut div = source_clock_hz / spi_clock_hz;

if source_clock_hz / div > spi_clock_hz {
div += 1;
}

// 0 <= div <= 255, and the true coefficient is really div + 2
let div = div.saturating_sub(2).clamp(0, 255);
ral::write_reg!(
ral::lpspi,
reg,
CCR,
SCKDIV: div,
// Both of these delays are arbitrary choices, and they should
// probably be configurable by the end-user.
DBT: div / 2,
SCKPCS: 0x1F,
PCSSCK: 0x1F
// Round up, so we always get a resulting SPI clock that is
// equal or less than the requested frequency.
let half_div =
u32::try_from(1 + u64::from(source_clock_hz - 1) / (u64::from(spi_clock_hz) * 2)).unwrap();

// Make sure SCKDIV is between 0 and 255
// For some reason SCK starts to misbehave in between frames
// if half_div is less than 3.
let half_div = half_div.clamp(3, 128);
// Because half_div is in range [3,128], sckdiv is in range [4, 254].
let sckdiv = 2 * (half_div - 1);

ral::write_reg!(ral::lpspi, reg, CCR,
// Delay between two clock transitions of two consecutive transfers
// is exactly sckdiv/2, which causes the transfer to be seamless.
DBT: half_div - 1,
// Add one sckdiv/2 setup and hold time before and after the transfer,
// to make sure the signal is stable at sample time
PCSSCK: half_div - 1,
SCKPCS: half_div - 1,
SCKDIV: sckdiv
);
}