update to remove dma generics
This commit is contained in:
parent
ea70b440cd
commit
3e399a9690
1 changed files with 478 additions and 421 deletions
|
@ -5,13 +5,16 @@
|
||||||
|
|
||||||
pub mod enums;
|
pub mod enums;
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embassy_embedded_hal::{GetConfig, SetConfig};
|
use embassy_embedded_hal::{GetConfig, SetConfig};
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
pub use enums::*;
|
pub use enums::*;
|
||||||
use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits};
|
use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits};
|
||||||
|
|
||||||
use crate::dma::{word, Transfer};
|
use crate::dma::{word, ChannelAndRequest};
|
||||||
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _};
|
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
|
||||||
|
use crate::mode::{Async, Blocking, Mode as PeriMode};
|
||||||
use crate::pac::octospi::{vals, Octospi as Regs};
|
use crate::pac::octospi::{vals, Octospi as Regs};
|
||||||
use crate::rcc::RccPeripheral;
|
use crate::rcc::RccPeripheral;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{peripherals, Peripheral};
|
||||||
|
@ -154,7 +157,7 @@ pub enum OspiError {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// OSPI driver.
|
/// OSPI driver.
|
||||||
pub struct Ospi<'d, T: Instance, Dma> {
|
pub struct Ospi<'d, T: Instance, M: PeriMode> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
d0: Option<PeripheralRef<'d, AnyPin>>,
|
d0: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
|
@ -167,259 +170,13 @@ pub struct Ospi<'d, T: Instance, Dma> {
|
||||||
d7: Option<PeripheralRef<'d, AnyPin>>,
|
d7: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
nss: Option<PeripheralRef<'d, AnyPin>>,
|
nss: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
dqs: Option<PeripheralRef<'d, AnyPin>>,
|
dqs: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
dma: PeripheralRef<'d, Dma>,
|
dma: Option<ChannelAndRequest<'d>>,
|
||||||
|
_phantom: PhantomData<M>,
|
||||||
config: Config,
|
config: Config,
|
||||||
width: OspiWidth,
|
width: OspiWidth,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> {
|
||||||
/// Create new OSPI driver for a single spi external chip
|
|
||||||
pub fn new_singlespi(
|
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
|
||||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
|
||||||
config: Config,
|
|
||||||
) -> Self {
|
|
||||||
into_ref!(peri, sck, d0, d1, nss);
|
|
||||||
|
|
||||||
sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
|
|
||||||
nss.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d0.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d1.set_as_af_pull(d1.af_num(), AFType::Input, Pull::None);
|
|
||||||
d1.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
|
|
||||||
Self::new_inner(
|
|
||||||
peri,
|
|
||||||
Some(d0.map_into()),
|
|
||||||
Some(d1.map_into()),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Some(sck.map_into()),
|
|
||||||
Some(nss.map_into()),
|
|
||||||
None,
|
|
||||||
dma,
|
|
||||||
config,
|
|
||||||
OspiWidth::SING,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create new OSPI driver for a dualspi external chip
|
|
||||||
pub fn new_dualspi(
|
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
|
||||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
|
||||||
config: Config,
|
|
||||||
) -> Self {
|
|
||||||
into_ref!(peri, sck, d0, d1, nss);
|
|
||||||
|
|
||||||
sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
|
|
||||||
nss.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d0.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d1.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
|
|
||||||
Self::new_inner(
|
|
||||||
peri,
|
|
||||||
Some(d0.map_into()),
|
|
||||||
Some(d1.map_into()),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Some(sck.map_into()),
|
|
||||||
Some(nss.map_into()),
|
|
||||||
None,
|
|
||||||
dma,
|
|
||||||
config,
|
|
||||||
OspiWidth::DUAL,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create new OSPI driver for a quadspi external chip
|
|
||||||
pub fn new_quadspi(
|
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
|
||||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
|
||||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
|
||||||
config: Config,
|
|
||||||
) -> Self {
|
|
||||||
into_ref!(peri, sck, d0, d1, d2, d3, nss);
|
|
||||||
|
|
||||||
sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
|
|
||||||
nss.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d0.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d1.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d2.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d3.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
|
|
||||||
Self::new_inner(
|
|
||||||
peri,
|
|
||||||
Some(d0.map_into()),
|
|
||||||
Some(d1.map_into()),
|
|
||||||
Some(d2.map_into()),
|
|
||||||
Some(d3.map_into()),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Some(sck.map_into()),
|
|
||||||
Some(nss.map_into()),
|
|
||||||
None,
|
|
||||||
dma,
|
|
||||||
config,
|
|
||||||
OspiWidth::QUAD,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create new OSPI driver for two quadspi external chips
|
|
||||||
pub fn new_dualquadspi(
|
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
|
||||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
|
||||||
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
|
||||||
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
|
||||||
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
|
||||||
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
|
||||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
|
||||||
config: Config,
|
|
||||||
) -> Self {
|
|
||||||
into_ref!(peri, sck, d0, d1, d2, d3, d4, d5, d6, d7, nss);
|
|
||||||
|
|
||||||
sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
|
|
||||||
nss.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d0.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d1.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d2.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d3.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d4.set_as_af_pull(d4.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d4.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d5.set_as_af_pull(d5.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d5.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d6.set_as_af_pull(d6.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d6.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d7.set_as_af_pull(d7.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d7.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
|
|
||||||
Self::new_inner(
|
|
||||||
peri,
|
|
||||||
Some(d0.map_into()),
|
|
||||||
Some(d1.map_into()),
|
|
||||||
Some(d2.map_into()),
|
|
||||||
Some(d3.map_into()),
|
|
||||||
Some(d4.map_into()),
|
|
||||||
Some(d5.map_into()),
|
|
||||||
Some(d6.map_into()),
|
|
||||||
Some(d7.map_into()),
|
|
||||||
Some(sck.map_into()),
|
|
||||||
Some(nss.map_into()),
|
|
||||||
None,
|
|
||||||
dma,
|
|
||||||
config,
|
|
||||||
OspiWidth::QUAD,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create new OSPI driver for octospi external chips
|
|
||||||
pub fn new_octospi(
|
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
|
||||||
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
|
||||||
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
|
||||||
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
|
||||||
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
|
||||||
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
|
||||||
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
|
||||||
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
|
||||||
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
|
||||||
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
|
||||||
config: Config,
|
|
||||||
) -> Self {
|
|
||||||
into_ref!(peri, sck, d0, d1, d2, d3, d4, d5, d6, d7, nss);
|
|
||||||
|
|
||||||
sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
|
|
||||||
nss.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d0.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d1.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d2.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d3.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d4.set_as_af_pull(d4.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d4.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d5.set_as_af_pull(d5.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d5.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d6.set_as_af_pull(d6.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d6.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
d7.set_as_af_pull(d7.af_num(), AFType::OutputPushPull, Pull::None);
|
|
||||||
d7.set_speed(crate::gpio::Speed::VeryHigh);
|
|
||||||
|
|
||||||
Self::new_inner(
|
|
||||||
peri,
|
|
||||||
Some(d0.map_into()),
|
|
||||||
Some(d1.map_into()),
|
|
||||||
Some(d2.map_into()),
|
|
||||||
Some(d3.map_into()),
|
|
||||||
Some(d4.map_into()),
|
|
||||||
Some(d5.map_into()),
|
|
||||||
Some(d6.map_into()),
|
|
||||||
Some(d7.map_into()),
|
|
||||||
Some(sck.map_into()),
|
|
||||||
Some(nss.map_into()),
|
|
||||||
None,
|
|
||||||
dma,
|
|
||||||
config,
|
|
||||||
OspiWidth::OCTO,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
d0: Option<PeripheralRef<'d, AnyPin>>,
|
d0: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
|
@ -433,12 +190,12 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
nss: Option<PeripheralRef<'d, AnyPin>>,
|
nss: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
dqs: Option<PeripheralRef<'d, AnyPin>>,
|
dqs: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
dma: impl Peripheral<P = Dma> + 'd,
|
dma: Option<ChannelAndRequest<'d>>,
|
||||||
config: Config,
|
config: Config,
|
||||||
width: OspiWidth,
|
width: OspiWidth,
|
||||||
dual_quad: bool,
|
dual_quad: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, dma);
|
into_ref!(peri);
|
||||||
|
|
||||||
// System configuration
|
// System configuration
|
||||||
T::enable_and_reset();
|
T::enable_and_reset();
|
||||||
|
@ -519,6 +276,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
nss,
|
nss,
|
||||||
dqs,
|
dqs,
|
||||||
dma,
|
dma,
|
||||||
|
_phantom: PhantomData,
|
||||||
config,
|
config,
|
||||||
width,
|
width,
|
||||||
}
|
}
|
||||||
|
@ -702,170 +460,6 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking read with DMA transfer
|
|
||||||
pub fn blocking_read_dma<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError>
|
|
||||||
where
|
|
||||||
Dma: OctoDma<T>,
|
|
||||||
{
|
|
||||||
if buf.is_empty() {
|
|
||||||
return Err(OspiError::EmptyBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for peripheral to be free
|
|
||||||
while T::REGS.sr().read().busy() {}
|
|
||||||
|
|
||||||
self.configure_command(&transaction, Some(buf.len()))?;
|
|
||||||
|
|
||||||
let current_address = T::REGS.ar().read().address();
|
|
||||||
let current_instruction = T::REGS.ir().read().instruction();
|
|
||||||
|
|
||||||
// For a indirect read transaction, the transaction begins when the instruction/address is set
|
|
||||||
T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
|
|
||||||
if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
|
|
||||||
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
|
|
||||||
} else {
|
|
||||||
T::REGS.ar().write(|v| v.set_address(current_address));
|
|
||||||
}
|
|
||||||
|
|
||||||
let request = self.dma.request();
|
|
||||||
let transfer = unsafe {
|
|
||||||
Transfer::new_read(
|
|
||||||
&mut self.dma,
|
|
||||||
request,
|
|
||||||
T::REGS.dr().as_ptr() as *mut W,
|
|
||||||
buf,
|
|
||||||
Default::default(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
T::REGS.cr().modify(|w| w.set_dmaen(true));
|
|
||||||
|
|
||||||
transfer.blocking_wait();
|
|
||||||
|
|
||||||
finish_dma(T::REGS);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Blocking write with DMA transfer
|
|
||||||
pub fn blocking_write_dma<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError>
|
|
||||||
where
|
|
||||||
Dma: OctoDma<T>,
|
|
||||||
{
|
|
||||||
if buf.is_empty() {
|
|
||||||
return Err(OspiError::EmptyBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for peripheral to be free
|
|
||||||
while T::REGS.sr().read().busy() {}
|
|
||||||
|
|
||||||
self.configure_command(&transaction, Some(buf.len()))?;
|
|
||||||
T::REGS
|
|
||||||
.cr()
|
|
||||||
.modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
|
|
||||||
|
|
||||||
let request = self.dma.request();
|
|
||||||
let transfer = unsafe {
|
|
||||||
Transfer::new_write(
|
|
||||||
&mut self.dma,
|
|
||||||
request,
|
|
||||||
buf,
|
|
||||||
T::REGS.dr().as_ptr() as *mut W,
|
|
||||||
Default::default(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
T::REGS.cr().modify(|w| w.set_dmaen(true));
|
|
||||||
|
|
||||||
transfer.blocking_wait();
|
|
||||||
|
|
||||||
finish_dma(T::REGS);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asynchronous read from external device
|
|
||||||
pub async fn read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError>
|
|
||||||
where
|
|
||||||
Dma: OctoDma<T>,
|
|
||||||
{
|
|
||||||
if buf.is_empty() {
|
|
||||||
return Err(OspiError::EmptyBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for peripheral to be free
|
|
||||||
while T::REGS.sr().read().busy() {}
|
|
||||||
|
|
||||||
self.configure_command(&transaction, Some(buf.len()))?;
|
|
||||||
|
|
||||||
let current_address = T::REGS.ar().read().address();
|
|
||||||
let current_instruction = T::REGS.ir().read().instruction();
|
|
||||||
|
|
||||||
// For a indirect read transaction, the transaction begins when the instruction/address is set
|
|
||||||
T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
|
|
||||||
if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
|
|
||||||
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
|
|
||||||
} else {
|
|
||||||
T::REGS.ar().write(|v| v.set_address(current_address));
|
|
||||||
}
|
|
||||||
|
|
||||||
let request = self.dma.request();
|
|
||||||
let transfer = unsafe {
|
|
||||||
Transfer::new_read(
|
|
||||||
&mut self.dma,
|
|
||||||
request,
|
|
||||||
T::REGS.dr().as_ptr() as *mut W,
|
|
||||||
buf,
|
|
||||||
Default::default(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
T::REGS.cr().modify(|w| w.set_dmaen(true));
|
|
||||||
|
|
||||||
transfer.await;
|
|
||||||
|
|
||||||
finish_dma(T::REGS);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asynchronous write to external device
|
|
||||||
pub async fn write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError>
|
|
||||||
where
|
|
||||||
Dma: OctoDma<T>,
|
|
||||||
{
|
|
||||||
if buf.is_empty() {
|
|
||||||
return Err(OspiError::EmptyBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for peripheral to be free
|
|
||||||
while T::REGS.sr().read().busy() {}
|
|
||||||
|
|
||||||
self.configure_command(&transaction, Some(buf.len()))?;
|
|
||||||
T::REGS
|
|
||||||
.cr()
|
|
||||||
.modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
|
|
||||||
|
|
||||||
let request = self.dma.request();
|
|
||||||
let transfer = unsafe {
|
|
||||||
Transfer::new_write(
|
|
||||||
&mut self.dma,
|
|
||||||
request,
|
|
||||||
buf,
|
|
||||||
T::REGS.dr().as_ptr() as *mut W,
|
|
||||||
Default::default(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
T::REGS.cr().modify(|w| w.set_dmaen(true));
|
|
||||||
|
|
||||||
transfer.await;
|
|
||||||
|
|
||||||
finish_dma(T::REGS);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set new bus configuration
|
/// Set new bus configuration
|
||||||
pub fn set_config(&mut self, config: &Config) {
|
pub fn set_config(&mut self, config: &Config) {
|
||||||
// Wait for busy flag to clear
|
// Wait for busy flag to clear
|
||||||
|
@ -942,7 +536,470 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, Dma> Drop for Ospi<'d, T, Dma> {
|
impl<'d, T: Instance> Ospi<'d, T, Blocking> {
|
||||||
|
/// Create new blocking OSPI driver for a single spi external chip
|
||||||
|
pub fn new_blocking_singlespi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::Input, Speed::VeryHigh),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
config,
|
||||||
|
OspiWidth::SING,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new blocking OSPI driver for a dualspi external chip
|
||||||
|
pub fn new_blocking_dualspi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
config,
|
||||||
|
OspiWidth::DUAL,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new blocking OSPI driver for a quadspi external chip
|
||||||
|
pub fn new_blocking_quadspi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
|
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
config,
|
||||||
|
OspiWidth::QUAD,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new blocking OSPI driver for two quadspi external chips
|
||||||
|
pub fn new_blocking_dualquadspi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
|
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||||
|
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||||
|
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||||
|
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||||
|
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
config,
|
||||||
|
OspiWidth::QUAD,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new blocking OSPI driver for octospi external chips
|
||||||
|
pub fn new_blocking_octospi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
|
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||||
|
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||||
|
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||||
|
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||||
|
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
config,
|
||||||
|
OspiWidth::OCTO,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> Ospi<'d, T, Async> {
|
||||||
|
/// Create new blocking OSPI driver for a single spi external chip
|
||||||
|
pub fn new_singlespi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::Input, Speed::VeryHigh),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
new_dma!(dma),
|
||||||
|
config,
|
||||||
|
OspiWidth::SING,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new blocking OSPI driver for a dualspi external chip
|
||||||
|
pub fn new_dualspi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
new_dma!(dma),
|
||||||
|
config,
|
||||||
|
OspiWidth::DUAL,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new blocking OSPI driver for a quadspi external chip
|
||||||
|
pub fn new_quadspi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
|
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
new_dma!(dma),
|
||||||
|
config,
|
||||||
|
OspiWidth::QUAD,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new blocking OSPI driver for two quadspi external chips
|
||||||
|
pub fn new_dualquadspi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
|
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||||
|
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||||
|
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||||
|
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||||
|
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
new_dma!(dma),
|
||||||
|
config,
|
||||||
|
OspiWidth::QUAD,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new blocking OSPI driver for octospi external chips
|
||||||
|
pub fn new_octospi(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
|
d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
|
||||||
|
d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
|
||||||
|
d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
|
||||||
|
d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
|
||||||
|
d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
|
||||||
|
d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
|
||||||
|
d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
|
||||||
|
d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
|
||||||
|
nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
|
||||||
|
dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_inner(
|
||||||
|
peri,
|
||||||
|
new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
|
new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
|
||||||
|
None,
|
||||||
|
new_dma!(dma),
|
||||||
|
config,
|
||||||
|
OspiWidth::OCTO,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Blocking read with DMA transfer
|
||||||
|
pub fn blocking_read_dma<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> {
|
||||||
|
if buf.is_empty() {
|
||||||
|
return Err(OspiError::EmptyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for peripheral to be free
|
||||||
|
while T::REGS.sr().read().busy() {}
|
||||||
|
|
||||||
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
|
|
||||||
|
let current_address = T::REGS.ar().read().address();
|
||||||
|
let current_instruction = T::REGS.ir().read().instruction();
|
||||||
|
|
||||||
|
// For a indirect read transaction, the transaction begins when the instruction/address is set
|
||||||
|
T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
|
||||||
|
if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
|
||||||
|
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
|
||||||
|
} else {
|
||||||
|
T::REGS.ar().write(|v| v.set_address(current_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
let transfer = unsafe {
|
||||||
|
self.dma
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default())
|
||||||
|
};
|
||||||
|
|
||||||
|
T::REGS.cr().modify(|w| w.set_dmaen(true));
|
||||||
|
|
||||||
|
transfer.blocking_wait();
|
||||||
|
|
||||||
|
finish_dma(T::REGS);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Blocking write with DMA transfer
|
||||||
|
pub fn blocking_write_dma<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> {
|
||||||
|
if buf.is_empty() {
|
||||||
|
return Err(OspiError::EmptyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for peripheral to be free
|
||||||
|
while T::REGS.sr().read().busy() {}
|
||||||
|
|
||||||
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
|
T::REGS
|
||||||
|
.cr()
|
||||||
|
.modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
|
||||||
|
|
||||||
|
let transfer = unsafe {
|
||||||
|
self.dma
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default())
|
||||||
|
};
|
||||||
|
|
||||||
|
T::REGS.cr().modify(|w| w.set_dmaen(true));
|
||||||
|
|
||||||
|
transfer.blocking_wait();
|
||||||
|
|
||||||
|
finish_dma(T::REGS);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asynchronous read from external device
|
||||||
|
pub async fn read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> {
|
||||||
|
if buf.is_empty() {
|
||||||
|
return Err(OspiError::EmptyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for peripheral to be free
|
||||||
|
while T::REGS.sr().read().busy() {}
|
||||||
|
|
||||||
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
|
|
||||||
|
let current_address = T::REGS.ar().read().address();
|
||||||
|
let current_instruction = T::REGS.ir().read().instruction();
|
||||||
|
|
||||||
|
// For a indirect read transaction, the transaction begins when the instruction/address is set
|
||||||
|
T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
|
||||||
|
if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
|
||||||
|
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
|
||||||
|
} else {
|
||||||
|
T::REGS.ar().write(|v| v.set_address(current_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
let transfer = unsafe {
|
||||||
|
self.dma
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default())
|
||||||
|
};
|
||||||
|
|
||||||
|
T::REGS.cr().modify(|w| w.set_dmaen(true));
|
||||||
|
|
||||||
|
transfer.await;
|
||||||
|
|
||||||
|
finish_dma(T::REGS);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asynchronous write to external device
|
||||||
|
pub async fn write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> {
|
||||||
|
if buf.is_empty() {
|
||||||
|
return Err(OspiError::EmptyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for peripheral to be free
|
||||||
|
while T::REGS.sr().read().busy() {}
|
||||||
|
|
||||||
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
|
T::REGS
|
||||||
|
.cr()
|
||||||
|
.modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
|
||||||
|
|
||||||
|
let transfer = unsafe {
|
||||||
|
self.dma
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default())
|
||||||
|
};
|
||||||
|
|
||||||
|
T::REGS.cr().modify(|w| w.set_dmaen(true));
|
||||||
|
|
||||||
|
transfer.await;
|
||||||
|
|
||||||
|
finish_dma(T::REGS);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, M: PeriMode> Drop for Ospi<'d, T, M> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.sck.as_ref().map(|x| x.set_as_disconnected());
|
self.sck.as_ref().map(|x| x.set_as_disconnected());
|
||||||
self.d0.as_ref().map(|x| x.set_as_disconnected());
|
self.d0.as_ref().map(|x| x.set_as_disconnected());
|
||||||
|
@ -1005,7 +1062,7 @@ foreach_peripheral!(
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<'d, T: Instance, Dma> SetConfig for Ospi<'d, T, Dma> {
|
impl<'d, T: Instance, M: PeriMode> SetConfig for Ospi<'d, T, M> {
|
||||||
type Config = Config;
|
type Config = Config;
|
||||||
type ConfigError = ();
|
type ConfigError = ();
|
||||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
||||||
|
@ -1014,7 +1071,7 @@ impl<'d, T: Instance, Dma> SetConfig for Ospi<'d, T, Dma> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, Dma> GetConfig for Ospi<'d, T, Dma> {
|
impl<'d, T: Instance, M: PeriMode> GetConfig for Ospi<'d, T, M> {
|
||||||
type Config = Config;
|
type Config = Config;
|
||||||
fn get_config(&self) -> Self::Config {
|
fn get_config(&self) -> Self::Config {
|
||||||
self.get_config()
|
self.get_config()
|
||||||
|
|
Loading…
Reference in a new issue