drone-sd-stm32 0.2.2

Secure Digital cards driver for Drone STM32.
use drone_core::drv::Resource;
use drone_core::fib;
use drone_plat::drv::dma::{Dma, DmaRes, DmaTransferError};
use drone_plat::drv::spi::{Spi, SpiDmaRxRes, SpiDmaTxRes, SpiIntRes, SpiRes};
use drone_plat::drv::timer::{Timer, TimerRes};
use drone_plat::reg::prelude::*;
use drone_sd_core::errors::{CmdError, DmaError};
use drone_sd_core::{SdSpi, SdSpiRes, SdSpiSessResCore};
use futures::prelude::*;

/// SD SPI session platform driver.
#[derive(Driver, Resource)]
pub struct SdSpiSessPlat<T: SdSpiSessResPlat>(Option<T>);

/// SD SPI session platform resource.
pub trait SdSpiSessResPlat: Resource<Source = Self> {
  /// SD resource.
  type SdRes: SdSpiRes;

  /// SPI resource.
  type SpiRes: SpiIntRes
    + SpiDmaRxRes<Self::DmaRxRes>
    + SpiDmaTxRes<Self::DmaTxRes>;

  /// Reciever DMA resource.
  type DmaRxRes: DmaRes;

  /// Transmitter DMA resource.
  type DmaTxRes: DmaRes;

  /// Timer resource.
  type TimerRes: TimerRes;

  /// Returns a reference to the SD driver.
  fn sd(&self) -> &SdSpi<Self::SdRes>;

  /// Returns a mutable reference to the SD driver.
  fn sd_mut(&mut self) -> &mut SdSpi<Self::SdRes>;

  /// Returns a reference to the SPI driver.
  fn spi(&self) -> &Spi<Self::SpiRes>;

  /// Returns a mutable reference to the SPI driver.
  fn spi_mut(&mut self) -> &mut Spi<Self::SpiRes>;

  /// Returns a reference to the transmitter DMA driver.
  fn dma_rx(&self) -> &Dma<Self::DmaRxRes>;

  /// Returns a mutable reference to the transmitter DMA driver.
  fn dma_rx_mut(&mut self) -> &mut Dma<Self::DmaRxRes>;

  /// Returns a reference to the reciever DMA driver.
  fn dma_tx(&self) -> &Dma<Self::DmaTxRes>;

  /// Returns a mutable reference to the reciever DMA driver.
  fn dma_tx_mut(&mut self) -> &mut Dma<Self::DmaTxRes>;

  /// Returns a reference to the timer driver.
  fn tim(&self) -> &Timer<Self::TimerRes>;

  /// Returns a mutable reference to the timer driver.
  fn tim_mut(&mut self) -> &mut Timer<Self::TimerRes>;

  /// Returns an initial value of the SPI's CR1 register.
  fn spi_cr1(spi: &Spi<Self::SpiRes>) -> <Self::SpiRes as SpiRes>::Cr1Val;

  /// Returns an initial value of the SPI's CR2 register.
  fn spi_cr2(spi: &Spi<Self::SpiRes>) -> <Self::SpiRes as SpiRes>::Cr2Val;

  /// Returns an initial value of the reciever DMA's CCR register.
  fn dma_rx_ccr(
    dma_rx: &Dma<Self::DmaRxRes>,
  ) -> <Self::DmaRxRes as DmaRes>::CcrVal;

  /// Returns an initial value of the transmitter DMA's CCR register.
  fn dma_tx_ccr(
    dma_tx: &Dma<Self::DmaTxRes>,
  ) -> <Self::DmaTxRes as DmaRes>::CcrVal;

  /// Returns an initial value of the timer's control register.
  fn tim_ctrl(
    tim: &Timer<Self::TimerRes>,
  ) -> <Self::TimerRes as TimerRes>::CtrlVal;

  /// Returns a 1 ms duration in timer's duration unit.
  fn startup_dur(
    &self,
    ctrl_val: <Self::TimerRes as TimerRes>::CtrlVal,
  ) -> <Self::TimerRes as TimerRes>::Duration;
}

impl<T: SdSpiSessResPlat> SdSpiSessResCore for SdSpiSessPlat<T> {
  type SdRes = T::SdRes;
  type SpiInt = <T::SpiRes as SpiIntRes>::Int;

  #[inline(always)]
  fn sd(&self) -> &SdSpi<Self::SdRes> {
    self.0.as_ref().unwrap().sd()
  }

  #[inline(always)]
  fn sd_mut(&mut self) -> &mut SdSpi<Self::SdRes> {
    self.0.as_mut().unwrap().sd_mut()
  }

  #[inline(always)]
  fn spi_open(&self) {
    let res = self.0.as_ref().unwrap();
    res.spi().cr1().store_val({
      let mut cr1 = Self::spi_cr1(res.spi());
      res.spi().cr1_spe().set(&mut cr1);
      cr1
    });
  }

  #[inline(always)]
  fn spi_close(&self) {
    let res = self.0.as_ref().unwrap();
    res.spi().busy_wait();
    res.spi().cr1().store_val(Self::spi_cr1(res.spi()));
  }

  #[inline(always)]
  unsafe fn dma_exchange<'sess>(
    &'sess mut self,
    rx_ptr: *mut u8,
    rx_inc: bool,
    rx_len: usize,
    tx_ptr: *const u8,
    tx_inc: bool,
    tx_len: usize,
  ) -> Box<Future<Item = (), Error = DmaError> + 'sess> {
    struct Finalizer<'sess, T: SdSpiSessResPlat>(&'sess SdSpiSessPlat<T>);
    impl<'sess, T: SdSpiSessResPlat> Drop for Finalizer<'sess, T> {
      fn drop(&mut self) {
        let sess = self.0;
        let res = &sess.0.as_ref().unwrap();
        let dma_rx_ccr = SdSpiSessPlat::<T>::dma_rx_ccr(res.dma_rx());
        let dma_tx_ccr = SdSpiSessPlat::<T>::dma_tx_ccr(res.dma_tx());
        res.dma_rx().ccr().store_val(dma_rx_ccr);
        res.dma_tx().ccr().store_val(dma_tx_ccr);
        res.spi().busy_wait();
        let cr2 = SdSpiSessPlat::<T>::spi_cr2(res.spi());
        res.spi().cr2().store_val(cr2);
      }
    }
    let (dma_rx, dma_tx) = {
      let res = self.0.as_mut().unwrap();
      res.dma_rx().set_maddr(rx_ptr as usize);
      res.dma_rx().set_size(rx_len);
      res.dma_rx().ccr().store_val({
        let mut rx_ccr = Self::dma_rx_ccr(res.dma_rx());
        if rx_inc {
          res.dma_rx().ccr_minc().set(&mut rx_ccr);
        }
        res.dma_rx().ccr_en().set(&mut rx_ccr);
        rx_ccr
      });
      res.dma_tx().set_maddr(tx_ptr as usize);
      res.dma_tx().set_size(tx_len);
      res.dma_tx().ccr().store_val({
        let mut tx_ccr = Self::dma_tx_ccr(res.dma_tx());
        if tx_inc {
          res.dma_tx().ccr_minc().set(&mut tx_ccr);
        }
        res.dma_tx().ccr_en().set(&mut tx_ccr);
        tx_ccr
      });
      let dma_rx = res.dma_rx_mut().transfer_complete();
      let dma_tx = res.dma_tx_mut().transfer_complete();
      res.spi().cr2().store_val({
        let mut cr2 = Self::spi_cr2(res.spi());
        res.spi().cr2_rxdmaen().set(&mut cr2);
        res.spi().cr2_txdmaen().set(&mut cr2);
        cr2
      });
      (dma_rx, dma_tx)
    };
    let finalizer = Finalizer(self);
    Box::new(async(move || {
      let dma_rx = await!(dma_rx);
      let dma_tx = await!(dma_tx);
      drop(finalizer);
      match (dma_rx, dma_tx) {
        (Ok(()), Ok(())) => Ok(()),
        (Err(DmaTransferError), _) => Err(DmaError::Rx),
        (_, Err(DmaTransferError)) => Err(DmaError::Tx),
      }
    }))
  }

  #[inline(always)]
  fn wait_byte<'sess, R, F>(
    &'sess mut self,
    first_byte: u8,
    mut max_skip: usize,
    mut f: F,
  ) -> Box<Future<Item = R, Error = CmdError> + 'sess>
  where
    R: Send + 'static,
    F: FnMut(u8) -> Option<R> + Send + 'static,
  {
    let mut res = self.0.take().unwrap();
    res.spi().cr2().store_val({
      let mut cr2 = Self::spi_cr2(res.spi());
      res.spi().cr2_rxneie().set(&mut cr2);
      res.spi().cr2_errie().set(&mut cr2);
      cr2
    });
    let send_byte = res.spi_mut().send_byte_fn();
    let fut = fib::add_future(
      res.spi().int(),
      fib::new(move || loop {
        let sr = res.spi().sr().load_val();
        if res.spi().sr_rxne().read(&sr) {
          if let Some(val) = f(res.spi().recv_byte()) {
            res.spi().cr2().store_val(Self::spi_cr2(res.spi()));
            break Ok((res, val));
          } else if max_skip > 0 {
            res.spi().send_byte(0xFF);
            max_skip -= 1;
          } else {
            break Err((res, CmdError::Timeout));
          }
        } else if res.spi().spi_errck(&sr).is_err() {
          break Err((res, CmdError::Spi));
        }
        yield;
      }),
    );
    send_byte(first_byte);
    Box::new(async(move || match await!(fut) {
      Ok((res, val)) => {
        self.0.get_or_insert(res);
        Ok(val)
      }
      Err((res, err)) => {
        self.0.get_or_insert(res);
        Err(err)
      }
    }))
  }

  #[inline(always)]
  fn send_byte(&mut self, value: u8) {
    self.0.take().unwrap().spi().send_byte(value);
  }

  #[inline(always)]
  fn startup_delay(&mut self) -> Box<Future<Item = (), Error = !>> {
    let res = self.0.as_mut().unwrap();
    let ctrl = T::tim_ctrl(res.tim());
    let dur = res.startup_dur(ctrl);
    Box::new(res.tim_mut().sleep(dur, ctrl))
  }
}

impl<T: SdSpiSessResPlat> SdSpiSessPlat<T> {
  #[inline(always)]
  fn spi_cr1(spi: &Spi<T::SpiRes>) -> <T::SpiRes as SpiRes>::Cr1Val {
    let mut cr1 = T::spi_cr1(spi);
    spi.cr1_bidimode().clear(&mut cr1);
    spi.cr1_rxonly().clear(&mut cr1);
    spi.cr1_lsbfirst().clear(&mut cr1);
    spi.cr1_spe().clear(&mut cr1);
    spi.cr1_mstr().set(&mut cr1);
    spi.cr1_cpol().clear(&mut cr1);
    spi.cr1_cpha().clear(&mut cr1);
    cr1
  }

  #[inline(always)]
  fn spi_cr2(spi: &Spi<T::SpiRes>) -> <T::SpiRes as SpiRes>::Cr2Val {
    let mut cr2 = T::spi_cr2(spi);
    spi.cr2_txeie().clear(&mut cr2);
    spi.cr2_rxneie().clear(&mut cr2);
    spi.cr2_errie().clear(&mut cr2);
    spi.cr2_txdmaen().clear(&mut cr2);
    spi.cr2_rxdmaen().clear(&mut cr2);
    spi.set_frame_8(&mut cr2);
    cr2
  }

  #[inline(always)]
  fn dma_rx_ccr(dma_rx: &Dma<T::DmaRxRes>) -> <T::DmaRxRes as DmaRes>::CcrVal {
    let mut ccr = T::dma_rx_ccr(dma_rx);
    dma_rx.ccr_mem2mem().clear(&mut ccr);
    dma_rx.ccr_msize().write(&mut ccr, 0b00);
    dma_rx.ccr_psize().write(&mut ccr, 0b00);
    dma_rx.ccr_minc().clear(&mut ccr);
    dma_rx.ccr_pinc().clear(&mut ccr);
    dma_rx.ccr_circ().clear(&mut ccr);
    dma_rx.ccr_dir().clear(&mut ccr);
    dma_rx.ccr_teie().set(&mut ccr);
    dma_rx.ccr_htie().clear(&mut ccr);
    dma_rx.ccr_tcie().set(&mut ccr);
    dma_rx.ccr_en().clear(&mut ccr);
    ccr
  }

  #[inline(always)]
  fn dma_tx_ccr(dma_tx: &Dma<T::DmaTxRes>) -> <T::DmaTxRes as DmaRes>::CcrVal {
    let mut ccr = T::dma_tx_ccr(dma_tx);
    dma_tx.ccr_mem2mem().clear(&mut ccr);
    dma_tx.ccr_msize().write(&mut ccr, 0b00);
    dma_tx.ccr_psize().write(&mut ccr, 0b00);
    dma_tx.ccr_minc().clear(&mut ccr);
    dma_tx.ccr_pinc().clear(&mut ccr);
    dma_tx.ccr_circ().clear(&mut ccr);
    dma_tx.ccr_dir().set(&mut ccr);
    dma_tx.ccr_teie().set(&mut ccr);
    dma_tx.ccr_htie().clear(&mut ccr);
    dma_tx.ccr_tcie().set(&mut ccr);
    dma_tx.ccr_en().clear(&mut ccr);
    ccr
  }
}