From 4feb74e4a604c6d843daa57e1504cca303e37fd8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 21 Nov 2021 20:14:56 +0100 Subject: [PATCH] SPI improvements / Clock passing update 1. Using `impl Into` instead of Hertz now to increase usability for users 2. Update for SPI API to increase usability --- CHANGELOG.md | 4 +++ examples/spi.rs | 15 +++++------ src/clock.rs | 4 +-- src/spi.rs | 72 ++++++++++++++++++++++++++++++++++++++----------- src/uart.rs | 2 +- 5 files changed, 71 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0769efe..8dc9081 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - DelayUs and DelayMs trait implementations for timer - SPI implementation for blocking API, supports blockmode as well +### Changed + +- API which expects values in Hertz now uses `impl Into` as input parameter + ## [0.2.1] ### Added diff --git a/examples/spi.rs b/examples/spi.rs index e1c31cc..c43df89 100644 --- a/examples/spi.rs +++ b/examples/spi.rs @@ -62,10 +62,10 @@ fn main() -> ! { pinsa.pa29.into_funsel_1(), ); spia_ref.borrow_mut().replace( - Spi::spia::( + Spi::spia( dp.SPIA, (sck, miso, mosi), - 50.mhz().into(), + 50.mhz(), spi_cfg, Some(&mut dp.SYSCONFIG), None, @@ -80,10 +80,10 @@ fn main() -> ! { pinsb.pb7.into_funsel_2(), ); spia_ref.borrow_mut().replace( - Spi::spia::( + Spi::spia( dp.SPIA, (sck, miso, mosi), - 50.mhz().into(), + 50.mhz(), spi_cfg, Some(&mut dp.SYSCONFIG), None, @@ -98,10 +98,10 @@ fn main() -> ! { pinsb.pb3.into_funsel_1(), ); spib_ref.borrow_mut().replace( - Spi::spib::( + Spi::spib( dp.SPIB, (sck, miso, mosi), - 50.mhz().into(), + 50.mhz(), spi_cfg, Some(&mut dp.SYSCONFIG), None, @@ -114,10 +114,9 @@ fn main() -> ! { match SPI_BUS_SEL { SpiBusSelect::SpiAPortA | SpiBusSelect::SpiAPortB => { if let Some(ref mut spi) = *spia_ref.borrow_mut() { - let transfer_cfg = TransferConfig::::new( + let transfer_cfg = TransferConfig::new_no_hw_cs( SPI_SPEED_KHZ.khz().into(), SPI_MODE, - None, BLOCKMODE, false, ); diff --git a/src/clock.rs b/src/clock.rs index 857ac72..c18aee5 100644 --- a/src/clock.rs +++ b/src/clock.rs @@ -40,9 +40,9 @@ pub enum FilterClkSel { /// The Vorago in powered by an external clock which might have different frequencies. /// The clock can be set here so it can be used by other software components as well. /// The clock can be set exactly once -pub fn set_sys_clock(freq: Hertz) { +pub fn set_sys_clock(freq: impl Into) { interrupt::free(|cs| { - SYS_CLOCK.borrow(cs).set(freq).ok(); + SYS_CLOCK.borrow(cs).set(freq.into()).ok(); }) } diff --git a/src/spi.rs b/src/spi.rs index e0016c5..a4f70f5 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -54,26 +54,28 @@ pub trait PinSck: Sealed {} pub trait PinMosi: Sealed {} pub trait PinMiso: Sealed {} -pub trait OptionalHwCs: Sealed { +pub trait HwCs: Sealed { const CS_ID: HwChipSelectId; } +pub trait OptionalHwCs: HwCs + Sealed {} macro_rules! hw_cs_pin { ($SPIx:ident, $PXx:ident, $AFx:ident, $HwCsIdent:path, $typedef:ident) => { - impl OptionalHwCs<$SPIx> for Pin<$PXx, $AFx> { + impl HwCs for Pin<$PXx, $AFx> { const CS_ID: HwChipSelectId = $HwCsIdent; } + impl OptionalHwCs<$SPIx> for Pin<$PXx, $AFx> {} pub type $typedef = Pin<$PXx, $AFx>; }; } -impl OptionalHwCs for NoneT { - const CS_ID: HwChipSelectId = HwChipSelectId::Invalid; -} -impl OptionalHwCs for NoneT { +impl HwCs for NoneT { const CS_ID: HwChipSelectId = HwChipSelectId::Invalid; } +impl OptionalHwCs for NoneT {} +impl OptionalHwCs for NoneT {} + // SPIA impl PinSck for Pin {} @@ -183,6 +185,7 @@ pub trait GenericTransferConfig { fn blockmode(&mut self, blockmode: bool); fn mode(&mut self, mode: Mode); fn frequency(&mut self, spi_clk: Hertz); + fn hw_cs_id(&self) -> u8; } /// This struct contains all configuration parameter which are transfer specific @@ -201,7 +204,32 @@ pub struct TransferConfig { pub blockmode: bool, } -impl TransferConfig { +/// Type erased variant of the transfer configuration. This is required to avoid generics in +/// the SPI constructor. +pub struct ReducedTransferConfig { + pub spi_clk: Hertz, + pub mode: Mode, + pub sod: bool, + /// If this is enabled, all data in the FIFO is transmitted in a single frame unless + /// the BMSTOP bit is set on a dataword. A frame is defined as CSn being active for the + /// duration of multiple data words + pub blockmode: bool, + pub hw_cs: HwChipSelectId, +} + +impl TransferConfig { + pub fn new_no_hw_cs(spi_clk: Hertz, mode: Mode, blockmode: bool, sod: bool) -> Self { + TransferConfig { + spi_clk, + mode, + hw_cs: None, + sod, + blockmode, + } + } +} + +impl TransferConfig { pub fn new( spi_clk: Hertz, mode: Mode, @@ -217,9 +245,19 @@ impl TransferConfig { blockmode, } } + + pub fn downgrade(self) -> ReducedTransferConfig { + ReducedTransferConfig { + spi_clk: self.spi_clk, + mode: self.mode, + sod: self.sod, + blockmode: self.blockmode, + hw_cs: HWCS::CS_ID, + } + } } -impl GenericTransferConfig for TransferConfig { +impl GenericTransferConfig for TransferConfig { /// Slave Output Disable fn sod(&mut self, sod: bool) { self.sod = sod; @@ -236,6 +274,10 @@ impl GenericTransferConfig for TransferConfig { fn frequency(&mut self, spi_clk: Hertz) { self.spi_clk = spi_clk; } + + fn hw_cs_id(&self) -> u8 { + HWCS::CS_ID as u8 + } } #[derive(Default)] @@ -341,13 +383,13 @@ macro_rules! spi { /// If only one device is connected, this configuration only needs to be done /// once. /// * `syscfg` - Can be passed optionally to enable the peripheral clock - pub fn $spix>( + pub fn $spix( spi: $SPIX, pins: (Sck, Miso, Mosi), - sys_clk: Hertz, + sys_clk: impl Into + Copy, spi_cfg: SpiConfig, syscfg: Option<&mut SYSCONFIG>, - transfer_cfg: Option<&TransferConfig>, + transfer_cfg: Option<&ReducedTransferConfig>, ) -> Self { if let Some(syscfg) = syscfg { enable_peripheral_clock(syscfg, $clk_enb); @@ -365,9 +407,9 @@ macro_rules! spi { let mut init_blockmode = false; if let Some(transfer_cfg) = transfer_cfg { mode = transfer_cfg.mode; - clk_prescale = sys_clk.0 / (transfer_cfg.spi_clk.0 * (scrdv as u32 + 1)); - if transfer_cfg.hw_cs.is_some() { - ss = HwCs::CS_ID as u8; + clk_prescale = sys_clk.into().0 / (transfer_cfg.spi_clk.0 * (scrdv as u32 + 1)); + if transfer_cfg.hw_cs != HwChipSelectId::Invalid { + ss = transfer_cfg.hw_cs as u8; } init_blockmode = transfer_cfg.blockmode; } @@ -408,7 +450,7 @@ macro_rules! spi { spi_base: SpiBase { spi, cfg: spi_cfg, - sys_clk, + sys_clk: sys_clk.into(), blockmode: init_blockmode, _word: PhantomData, }, diff --git a/src/uart.rs b/src/uart.rs index bc1de14..5451c49 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -46,7 +46,7 @@ pub enum Error { BreakCondition, } -#[derive(Copy, Clone, PartialEq)] +#[derive(Debug, PartialEq, Copy, Clone)] pub enum Event { // Receiver FIFO interrupt enable. Generates interrupt // when FIFO is at least half full. Half full is defined as FIFO