Skip to content

Commit a13a6b7

Browse files
bors[bot]mattico
andauthored
Merge #125
125: Add SPI enable disable r=richardeoin a=mattico With the addition of these functions, it becomes quite easy to share an SPI peripheral between multiple devices which require different configuration. You can `disable()`, `free()`, then pass ownership between the different devices which can then configure the SPI peripheral. Co-authored-by: Matt Ickstadt <[email protected]>
2 parents 1179d0c + 23dc77e commit a13a6b7

File tree

1 file changed

+65
-17
lines changed

1 file changed

+65
-17
lines changed

src/spi.rs

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ pub enum Error {
9999
_Extensible,
100100
}
101101

102+
/// Enabled SPI peripheral (type state)
103+
pub struct Enabled;
104+
/// Disabled SPI peripheral (type state)
105+
pub struct Disabled;
106+
102107
pub trait Pins<SPI> {}
103108
pub trait PinSck<SPI> {}
104109
pub trait PinMiso<SPI> {}
@@ -333,9 +338,10 @@ pub enum Event {
333338
}
334339

335340
#[derive(Debug)]
336-
pub struct Spi<SPI, WORD = u8> {
341+
pub struct Spi<SPI, ED, WORD = u8> {
337342
spi: SPI,
338343
_word: PhantomData<WORD>,
344+
_ed: PhantomData<ED>,
339345
}
340346

341347
pub trait SpiExt<SPI, WORD>: Sized {
@@ -348,7 +354,7 @@ pub trait SpiExt<SPI, WORD>: Sized {
348354
freq: T,
349355
prec: Self::Rec,
350356
clocks: &CoreClocks,
351-
) -> Spi<SPI, WORD>
357+
) -> Spi<SPI, Enabled, WORD>
352358
where
353359
PINS: Pins<SPI>,
354360
T: Into<Hertz>,
@@ -360,7 +366,7 @@ pub trait SpiExt<SPI, WORD>: Sized {
360366
freq: T,
361367
prec: Self::Rec,
362368
clocks: &CoreClocks,
363-
) -> Spi<SPI, WORD>
369+
) -> Spi<SPI, Enabled, WORD>
364370
where
365371
T: Into<Hertz>,
366372
CONFIG: Into<Config>;
@@ -384,7 +390,7 @@ macro_rules! spi {
384390
$(
385391
// For each $TY
386392
$(
387-
impl Spi<$SPIX, $TY> {
393+
impl Spi<$SPIX, Enabled, $TY> {
388394
pub fn $spiX<T, CONFIG>(
389395
spi: $SPIX,
390396
config: CONFIG,
@@ -476,9 +482,49 @@ macro_rules! spi {
476482
// spe: enable the SPI bus
477483
spi.cr1.write(|w| w.ssi().slave_not_selected().spe().enabled());
478484

479-
Spi { spi, _word: PhantomData }
485+
Spi { spi, _word: PhantomData, _ed: PhantomData }
486+
}
487+
488+
/// Disables the SPI peripheral. Any SPI operation is
489+
/// stopped and disabled, the internal state machine is
490+
/// reset, all the FIFOs content is flushed, the MODF
491+
/// flag is cleared, the SSI flag is cleared, and the
492+
/// CRC calculation is re-initialized. Clocks are not
493+
/// disabled.
494+
pub fn disable(self) -> Spi<$SPIX, Disabled, $TY> {
495+
// Master communication must be suspended before the peripheral is disabled
496+
self.spi.cr1.modify(|_, w| w.csusp().requested());
497+
while self.spi.sr.read().eot().is_completed() {}
498+
self.spi.cr1.write(|w| w.ssi().slave_not_selected().spe().disabled());
499+
Spi {
500+
spi: self.spi,
501+
_word: PhantomData,
502+
_ed: PhantomData,
503+
}
504+
}
505+
}
506+
507+
impl Spi<$SPIX, Disabled, $TY> {
508+
/// Enables the SPI peripheral.
509+
/// Clears the MODF flag, the SSI flag, and sets the SPE bit.
510+
pub fn enable(mut self) -> Spi<$SPIX, Enabled, $TY> {
511+
self.clear_modf(); // SPE cannot be set when MODF is set
512+
self.spi.cr1.write(|w| w.ssi().slave_not_selected().spe().enabled());
513+
Spi {
514+
spi: self.spi,
515+
_word: PhantomData,
516+
_ed: PhantomData,
517+
}
480518
}
481519

520+
/// Deconstructs the SPI peripheral and returns the component parts.
521+
pub fn free(self) -> ($SPIX, rec::$Rec) {
522+
(self.spi, rec::$Rec { _marker: PhantomData })
523+
}
524+
}
525+
526+
impl<EN> Spi<$SPIX, EN, $TY>
527+
{
482528
/// Enable interrupts for the given `event`:
483529
/// - Received data ready to be read (RXP)
484530
/// - Transmit data register empty (TXP)
@@ -551,8 +597,10 @@ macro_rules! spi {
551597
self.spi.sr.read().ovr().is_overrun()
552598
}
553599

554-
pub fn free(self) -> ($SPIX, rec::$Rec) {
555-
(self.spi, rec::$Rec { _marker: PhantomData })
600+
/// Clears the MODF flag, which indicates that a
601+
/// mode fault has occurred.
602+
pub fn clear_modf(&mut self) {
603+
self.spi.ifcr.write(|w| w.modfc().clear());
556604
}
557605
}
558606

@@ -564,29 +612,29 @@ macro_rules! spi {
564612
config: CONFIG,
565613
freq: T,
566614
prec: rec::$Rec,
567-
clocks: &CoreClocks) -> Spi<$SPIX, $TY>
615+
clocks: &CoreClocks) -> Spi<$SPIX, Enabled, $TY>
568616
where
569617
PINS: Pins<$SPIX>,
570618
T: Into<Hertz>,
571619
CONFIG: Into<Config>,
572620
{
573-
Spi::<$SPIX, $TY>::$spiX(self, config, freq, prec, clocks)
621+
Spi::<$SPIX, Enabled, $TY>::$spiX(self, config, freq, prec, clocks)
574622
}
575623

576624
fn spi_unchecked<T, CONFIG>(self,
577625
config: CONFIG,
578626
freq: T,
579627
prec: rec::$Rec,
580-
clocks: &CoreClocks) -> Spi<$SPIX, $TY>
628+
clocks: &CoreClocks) -> Spi<$SPIX, Enabled, $TY>
581629
where
582630
T: Into<Hertz>,
583631
CONFIG: Into<Config>,
584632
{
585-
Spi::<$SPIX, $TY>::$spiX(self, config, freq, prec, clocks)
633+
Spi::<$SPIX, Enabled, $TY>::$spiX(self, config, freq, prec, clocks)
586634
}
587635
}
588636

589-
impl hal::spi::FullDuplex<$TY> for Spi<$SPIX, $TY> {
637+
impl hal::spi::FullDuplex<$TY> for Spi<$SPIX, Enabled, $TY> {
590638
type Error = Error;
591639

592640
fn read(&mut self) -> nb::Result<$TY, Error> {
@@ -641,10 +689,10 @@ macro_rules! spi {
641689
}
642690

643691
impl hal::blocking::spi::transfer::Default<$TY>
644-
for Spi<$SPIX, $TY> {}
692+
for Spi<$SPIX, Enabled, $TY> {}
645693

646694
impl hal::blocking::spi::write::Default<$TY>
647-
for Spi<$SPIX, $TY> {}
695+
for Spi<$SPIX, Enabled, $TY> {}
648696
)+
649697
)+
650698
}
@@ -653,7 +701,7 @@ macro_rules! spi {
653701
macro_rules! spi123sel {
654702
($($SPIX:ident,)+) => {
655703
$(
656-
impl<WORD> Spi<$SPIX, WORD> {
704+
impl<WORD> Spi<$SPIX, Enabled, WORD> {
657705
/// Returns the frequency of the current kernel clock
658706
/// for SPI1, SPI2, SPI3
659707
fn kernel_clk(clocks: &CoreClocks) -> Option<Hertz> {
@@ -676,7 +724,7 @@ macro_rules! spi123sel {
676724
macro_rules! spi45sel {
677725
($($SPIX:ident,)+) => {
678726
$(
679-
impl<WORD> Spi<$SPIX, WORD> {
727+
impl<WORD> Spi<$SPIX, Enabled, WORD> {
680728
/// Returns the frequency of the current kernel clock
681729
/// for SPI4, SPI5
682730
fn kernel_clk(clocks: &CoreClocks) -> Option<Hertz> {
@@ -699,7 +747,7 @@ macro_rules! spi45sel {
699747
macro_rules! spi6sel {
700748
($($SPIX:ident,)+) => {
701749
$(
702-
impl<WORD> Spi<$SPIX, WORD> {
750+
impl<WORD> Spi<$SPIX, Enabled, WORD> {
703751
/// Returns the frequency of the current kernel clock
704752
/// for SPI6
705753
fn kernel_clk(clocks: &CoreClocks) -> Option<Hertz> {

0 commit comments

Comments
 (0)