123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- use core::ptr;
- use hal;
- pub use hal::spi::{Mode, Phase, Polarity};
- use nb;
- use stm32::{SPI1, SPI2};
- use afio::MAPR;
- use gpio::gpioa::{PA5, PA6, PA7};
- use gpio::gpiob::{PB13, PB14, PB15, PB3, PB4, PB5};
- use gpio::{Alternate, Floating, Input, PushPull};
- use rcc::{APB1, APB2, Clocks};
- use time::Hertz;
- /// SPI error
- #[derive(Debug)]
- pub enum Error {
- /// Overrun occurred
- Overrun,
- /// Mode fault occurred
- ModeFault,
- /// CRC error
- 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 {
- // enable or reset $SPIX
- apb.enr().modify(|_, w| w.$spiXen().set_bit());
- apb.rstr().modify(|_, w| w.$spiXrst().set_bit());
- apb.rstr().modify(|_, w| w.$spiXrst().clear_bit());
- // disable SS output
- 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,
- };
- // mstr: master configuration
- // lsbfirst: MSB first
- // ssm: enable software slave management (NSS pin free for other uses)
- // ssi: set nss high = master mode
- // dff: 8 bit frames
- // bidimode: 2-line unidirectional
- // spe: enable the SPI bus
- 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> 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() {
- // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
- // reading a half-word)
- 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() {
- // NOTE(write_volatile) see note above
- unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }
- return Ok(());
- } else {
- nb::Error::WouldBlock
- })
- }
- }
- impl<PINS> ::hal::blocking::spi::transfer::Default<u8> for Spi<$SPIX, PINS> {}
- impl<PINS> ::hal::blocking::spi::write::Default<u8> for Spi<$SPIX, PINS> {}
- )+
- }
- }
- hal! {
- SPI1: (_spi1, spi1en, spi1rst, APB2),
- SPI2: (_spi2, spi2en, spi2rst, APB1),
- }
|