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::*;
#[derive(Driver, Resource)]
pub struct SdSpiSessPlat<T: SdSpiSessResPlat>(Option<T>);
pub trait SdSpiSessResPlat: Resource<Source = Self> {
type SdRes: SdSpiRes;
type SpiRes: SpiIntRes
+ SpiDmaRxRes<Self::DmaRxRes>
+ SpiDmaTxRes<Self::DmaTxRes>;
type DmaRxRes: DmaRes;
type DmaTxRes: DmaRes;
type TimerRes: TimerRes;
fn sd(&self) -> &SdSpi<Self::SdRes>;
fn sd_mut(&mut self) -> &mut SdSpi<Self::SdRes>;
fn spi(&self) -> &Spi<Self::SpiRes>;
fn spi_mut(&mut self) -> &mut Spi<Self::SpiRes>;
fn dma_rx(&self) -> &Dma<Self::DmaRxRes>;
fn dma_rx_mut(&mut self) -> &mut Dma<Self::DmaRxRes>;
fn dma_tx(&self) -> &Dma<Self::DmaTxRes>;
fn dma_tx_mut(&mut self) -> &mut Dma<Self::DmaTxRes>;
fn tim(&self) -> &Timer<Self::TimerRes>;
fn tim_mut(&mut self) -> &mut Timer<Self::TimerRes>;
fn spi_cr1(spi: &Spi<Self::SpiRes>) -> <Self::SpiRes as SpiRes>::Cr1Val;
fn spi_cr2(spi: &Spi<Self::SpiRes>) -> <Self::SpiRes as SpiRes>::Cr2Val;
fn dma_rx_ccr(
dma_rx: &Dma<Self::DmaRxRes>,
) -> <Self::DmaRxRes as DmaRes>::CcrVal;
fn dma_tx_ccr(
dma_tx: &Dma<Self::DmaTxRes>,
) -> <Self::DmaTxRes as DmaRes>::CcrVal;
fn tim_ctrl(
tim: &Timer<Self::TimerRes>,
) -> <Self::TimerRes as TimerRes>::CtrlVal;
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
}
}