use core::ptr;
pub use crate::hal::spi::{Mode, Phase, Polarity};
use nb;
use crate::pac::{SPI1, SPI2};
use crate::afio::MAPR;
use crate::gpio::gpioa::{PA5, PA6, PA7};
use crate::gpio::gpiob::{PB13, PB14, PB15, PB3, PB4, PB5};
use crate::gpio::{Alternate, Floating, Input, PushPull};
use crate::rcc::{Clocks, APB1, APB2};
use crate::time::Hertz;
#[derive(Debug)]
pub enum Error {
Overrun,
ModeFault,
Crc,
#[doc(hidden)]
_Extensible,
}
pub trait Pins<SPI> {
const REMAP: bool;
}
impl Pins<SPI1>
for (
PA5<Alternate<PushPull>>,
PA6<Input<Floating>>,
PA7<Alternate<PushPull>>,
)
{
const REMAP: bool = false;
}
impl Pins<SPI1>
for (
PB3<Alternate<PushPull>>,
PB4<Input<Floating>>,
PB5<Alternate<PushPull>>,
)
{
const REMAP: bool = true;
}
impl Pins<SPI2>
for (
PB13<Alternate<PushPull>>,
PB14<Input<Floating>>,
PB15<Alternate<PushPull>>,
)
{
const REMAP: bool = false;
}
pub struct Spi<SPI, PINS> {
spi: SPI,
pins: PINS,
}
impl<PINS> Spi<SPI1, PINS> {
pub fn spi1<F>(
spi: SPI1,
pins: PINS,
mapr: &mut MAPR,
mode: Mode,
freq: F,
clocks: Clocks,
apb: &mut APB2,
) -> Self
where
F: Into<Hertz>,
PINS: Pins<SPI1>,
{
mapr.mapr().modify(|_, w| w.spi1_remap().bit(PINS::REMAP));
Spi::_spi1(spi, pins, mode, freq.into(), clocks, apb)
}
}
impl<PINS> Spi<SPI2, PINS> {
pub fn spi2<F>(
spi: SPI2,
pins: PINS,
mode: Mode,
freq: F,
clocks: Clocks,
apb: &mut APB1,
) -> Self
where
F: Into<Hertz>,
PINS: Pins<SPI2>,
{
Spi::_spi2(spi, pins, mode, freq.into(), clocks, apb)
}
}
macro_rules! hal {
($($SPIX:ident: ($spiX:ident, $spiXen:ident, $spiXrst:ident, $APB:ident),)+) => {
$(
impl<PINS> Spi<$SPIX, PINS> {
fn $spiX(
spi: $SPIX,
pins: PINS,
mode: Mode,
freq: Hertz,
clocks: Clocks,
apb: &mut $APB,
) -> Self {
apb.enr().modify(|_, w| w.$spiXen().set_bit());
apb.rstr().modify(|_, w| w.$spiXrst().set_bit());
apb.rstr().modify(|_, w| w.$spiXrst().clear_bit());
spi.cr2.write(|w| w.ssoe().clear_bit());
let br = match clocks.pclk2().0 / freq.0 {
0 => unreachable!(),
1...2 => 0b000,
3...5 => 0b001,
6...11 => 0b010,
12...23 => 0b011,
24...47 => 0b100,
48...95 => 0b101,
96...191 => 0b110,
_ => 0b111,
};
spi.cr1.write(|w|
w.cpha()
.bit(mode.phase == Phase::CaptureOnSecondTransition)
.cpol()
.bit(mode.polarity == Polarity::IdleHigh)
.mstr()
.set_bit()
.br()
.bits(br)
.lsbfirst()
.clear_bit()
.ssm()
.set_bit()
.ssi()
.set_bit()
.rxonly()
.clear_bit()
.dff()
.clear_bit()
.bidimode()
.clear_bit()
.spe()
.set_bit()
);
Spi { spi, pins }
}
pub fn free(self) -> ($SPIX, PINS) {
(self.spi, self.pins)
}
}
impl<PINS> crate::hal::spi::FullDuplex<u8> for Spi<$SPIX, PINS> {
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Error> {
let sr = self.spi.sr.read();
Err(if sr.ovr().bit_is_set() {
nb::Error::Other(Error::Overrun)
} else if sr.modf().bit_is_set() {
nb::Error::Other(Error::ModeFault)
} else if sr.crcerr().bit_is_set() {
nb::Error::Other(Error::Crc)
} else if sr.rxne().bit_is_set() {
return Ok(unsafe {
ptr::read_volatile(&self.spi.dr as *const _ as *const u8)
});
} else {
nb::Error::WouldBlock
})
}
fn send(&mut self, byte: u8) -> nb::Result<(), Error> {
let sr = self.spi.sr.read();
Err(if sr.ovr().bit_is_set() {
nb::Error::Other(Error::Overrun)
} else if sr.modf().bit_is_set() {
nb::Error::Other(Error::ModeFault)
} else if sr.crcerr().bit_is_set() {
nb::Error::Other(Error::Crc)
} else if sr.txe().bit_is_set() {
unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }
return Ok(());
} else {
nb::Error::WouldBlock
})
}
}
impl<PINS> crate::hal::blocking::spi::transfer::Default<u8> for Spi<$SPIX, PINS> {}
impl<PINS> crate::hal::blocking::spi::write::Default<u8> for Spi<$SPIX, PINS> {}
)+
}
}
hal! {
SPI1: (_spi1, spi1en, spi1rst, APB2),
SPI2: (_spi2, spi2en, spi2rst, APB1),
}