#![macro_use]
pub mod enums;
use core::marker::PhantomData;
use embassy_embedded_hal::{GetConfig, SetConfig};
use embassy_hal_internal::PeripheralType;
pub use enums::*;
use crate::dma::{ChannelAndRequest, word};
use crate::gpio::{AfType, Flex, OutputType, Pull, Speed};
use crate::mode::{Async, Blocking, Mode as PeriMode};
use crate::pac::xspi::Xspi as Regs;
use crate::pac::xspi::vals::*;
#[cfg(xspim_v1)]
use crate::pac::xspim::Xspim;
use crate::rcc::{self, RccPeripheral};
use crate::{Peri, peripherals};
#[derive(Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Config {
pub fifo_threshold: FIFOThresholdLevel,
pub memory_type: MemoryType, pub device_size: MemorySize,
pub chip_select_high_time: ChipSelectHighTime,
pub free_running_clock: bool,
pub clock_mode: bool,
pub wrap_size: WrapSize,
pub clock_prescaler: u8,
pub sample_shifting: bool,
pub delay_hold_quarter_cycle: bool,
pub chip_select_boundary: u8,
pub max_transfer: u8,
pub refresh: u32,
}
impl Default for Config {
fn default() -> Self {
Self {
fifo_threshold: FIFOThresholdLevel::_16Bytes, memory_type: MemoryType::Micron,
device_size: MemorySize::Other(0),
chip_select_high_time: ChipSelectHighTime::_5Cycle,
free_running_clock: false,
clock_mode: false,
wrap_size: WrapSize::None,
clock_prescaler: 0,
sample_shifting: false,
delay_hold_quarter_cycle: false,
chip_select_boundary: 0, max_transfer: 0,
refresh: 0,
}
}
}
#[derive(Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct TransferConfig {
pub iwidth: XspiWidth,
pub instruction: Option<u32>,
pub isize: AddressSize,
pub idtr: bool,
pub adwidth: XspiWidth,
pub address: Option<u32>,
pub adsize: AddressSize,
pub addtr: bool,
pub abwidth: XspiWidth,
pub alternate_bytes: Option<u32>,
pub absize: AddressSize,
pub abdtr: bool,
pub dwidth: XspiWidth,
pub ddtr: bool,
pub dummy: DummyCycles,
pub dqse: bool,
}
impl Default for TransferConfig {
fn default() -> Self {
Self {
iwidth: XspiWidth::NONE,
instruction: None,
isize: AddressSize::_8bit,
idtr: false,
adwidth: XspiWidth::NONE,
address: None,
adsize: AddressSize::_8bit,
addtr: false,
abwidth: XspiWidth::NONE,
alternate_bytes: None,
absize: AddressSize::_8bit,
abdtr: false,
dwidth: XspiWidth::NONE,
ddtr: false,
dummy: DummyCycles::_0,
dqse: false,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum XspiError {
InvalidConfiguration,
InvalidCommand,
EmptyBuffer,
}
pub struct Xspi<'d, T: Instance, M: PeriMode> {
_peri: Peri<'d, T>,
_clk: Option<Flex<'d>>,
_d0: Option<Flex<'d>>,
_d1: Option<Flex<'d>>,
_d2: Option<Flex<'d>>,
_d3: Option<Flex<'d>>,
_d4: Option<Flex<'d>>,
_d5: Option<Flex<'d>>,
_d6: Option<Flex<'d>>,
_d7: Option<Flex<'d>>,
_d8: Option<Flex<'d>>,
_d9: Option<Flex<'d>>,
_d10: Option<Flex<'d>>,
_d11: Option<Flex<'d>>,
_d12: Option<Flex<'d>>,
_d13: Option<Flex<'d>>,
_d14: Option<Flex<'d>>,
_d15: Option<Flex<'d>>,
_ncs: Option<Flex<'d>>,
_ncs_alt: Option<Flex<'d>>,
_cssel_swap: bool,
_dqs0: Option<Flex<'d>>,
_dqs1: Option<Flex<'d>>,
dma: Option<ChannelAndRequest<'d>>,
_phantom: PhantomData<M>,
config: Config,
width: XspiWidth,
}
impl<'d, T: Instance, M: PeriMode> Xspi<'d, T, M> {
pub fn enable_memory_mapped_mode(
&mut self,
read_config: TransferConfig,
write_config: TransferConfig,
) -> Result<(), XspiError> {
let reg = T::REGS;
while reg.sr().read().busy() {}
reg.wccr().write(|w| {
w.set_imode(WccrImode::from_bits(write_config.iwidth.into()));
w.set_idtr(write_config.idtr);
w.set_isize(WccrIsize::from_bits(write_config.isize.into()));
w.set_admode(WccrAdmode::from_bits(write_config.adwidth.into()));
w.set_addtr(write_config.addtr);
w.set_adsize(WccrAdsize::from_bits(write_config.adsize.into()));
w.set_abmode(WccrAbmode::from_bits(write_config.abwidth.into()));
w.set_abdtr(write_config.abdtr);
w.set_absize(WccrAbsize::from_bits(write_config.absize.into()));
w.set_dmode(WccrDmode::from_bits(write_config.dwidth.into()));
w.set_ddtr(write_config.ddtr);
w.set_dqse(write_config.dqse);
});
reg.wtcr().write(|w| w.set_dcyc(write_config.dummy.into()));
if let Some(instruction) = write_config.instruction {
reg.wir().write(|w| w.set_instruction(instruction));
}
if let Some(ab) = write_config.alternate_bytes {
reg.wabr().write(|w| w.set_alternate(ab));
}
self.configure_command(&read_config, None)?;
while reg.sr().read().busy() {}
reg.ccr().modify(|r| {
r.set_dqse(read_config.dqse);
});
reg.cr().modify(|r| {
r.set_fmode(Fmode::B_0X3);
r.set_tcen(false);
});
Ok(())
}
pub fn disable_memory_mapped_mode(&mut self) {
let reg = T::REGS;
reg.cr().modify(|r| {
r.set_fmode(Fmode::B_0X0);
r.set_abort(true);
r.set_dmaen(false);
r.set_en(false);
});
reg.fcr().write(|w| w.set_ctcf(true));
reg.cr().modify(|r| {
r.set_en(true);
});
}
pub fn set_clock_prescaler(&mut self, prescaler: u8) {
T::REGS.cr().modify(|w| w.set_en(false));
while T::REGS.sr().read().busy() {}
T::REGS.dcr2().modify(|w| w.set_prescaler(prescaler));
T::REGS.cr().modify(|w| w.set_en(true));
self.config.clock_prescaler = prescaler;
}
fn new_inner(
peri: Peri<'d, T>,
_d0: Option<Flex<'d>>,
_d1: Option<Flex<'d>>,
_d2: Option<Flex<'d>>,
_d3: Option<Flex<'d>>,
_d4: Option<Flex<'d>>,
_d5: Option<Flex<'d>>,
_d6: Option<Flex<'d>>,
_d7: Option<Flex<'d>>,
_d8: Option<Flex<'d>>,
_d9: Option<Flex<'d>>,
_d10: Option<Flex<'d>>,
_d11: Option<Flex<'d>>,
_d12: Option<Flex<'d>>,
_d13: Option<Flex<'d>>,
_d14: Option<Flex<'d>>,
_d15: Option<Flex<'d>>,
_clk: Option<Flex<'d>>,
ncs_cssel: u8,
_ncs: Option<Flex<'d>>,
_ncs_alt: Option<Flex<'d>>,
_dqs0: Option<Flex<'d>>,
_dqs1: Option<Flex<'d>>,
dma: Option<ChannelAndRequest<'d>>,
config: Config,
width: XspiWidth,
dual_quad: bool,
) -> Self {
#[cfg(pwr_h7rs)]
match T::SPI_IDX {
1 => crate::pac::PWR.csr2().modify(|r| r.set_en_xspim1(true)),
2 => crate::pac::PWR.csr2().modify(|r| r.set_en_xspim2(true)),
_ => unreachable!(),
};
#[cfg(xspim_v1)]
{
debug!("XSPI init: enabling XSPIM clock");
#[cfg(rcc_h7rs)]
crate::pac::RCC.ahb5enr().modify(|w| w.set_iomngren(true));
#[cfg(rcc_n6)]
crate::pac::RCC.ahb5enr().modify(|w| w.set_xspimen(true));
#[cfg(rcc_n6)]
rcc::enable_and_reset::<T>();
T::REGS.cr().modify(|w| {
w.set_en(false);
});
T::SPIM_REGS.cr().modify(|w| {
w.set_muxen(false);
w.set_req2ack_time(1); #[cfg(stm32n6)]
w.set_cssel_ovr_en(true);
match T::SPI_IDX {
1 => w.set_cssel_ovr_o1(ncs_cssel != 0),
2 => w.set_cssel_ovr_o2(ncs_cssel != 0),
_ => {} }
});
debug!("XSPI init: XSPIM configured");
#[cfg(rcc_h7rs)]
rcc::enable_and_reset::<T>();
}
#[cfg(not(xspim_v1))]
rcc::enable_and_reset::<T>();
while T::REGS.sr().read().busy() {}
T::REGS.dcr1().modify(|w| {
w.set_devsize(config.device_size.into());
w.set_mtyp(Mtyp::from_bits(config.memory_type.into()));
w.set_csht(Csht::from_bits(config.chip_select_high_time.into()));
w.set_frck(false);
w.set_ckmode(Ckmode::from_bits(config.clock_mode.into()));
});
T::REGS.dcr2().modify(|w| {
w.set_wrapsize(Wrapsize::from_bits(config.wrap_size.into()));
});
T::REGS.dcr3().modify(|w| {
w.set_csbound(Csbound::from_bits(config.chip_select_boundary.into()));
#[cfg(xspi_v1)]
{
w.set_maxtran(Maxtran::from_bits(config.max_transfer.into()));
}
});
T::REGS.dcr4().modify(|w| {
w.set_refresh(Refresh::from_bits(config.refresh.into()));
});
T::REGS.cr().modify(|w| {
w.set_fthres(Fthres::from_bits(config.fifo_threshold.into()));
});
while T::REGS.sr().read().busy() {}
T::REGS.dcr2().modify(|w| {
w.set_prescaler(config.clock_prescaler);
});
while T::REGS.sr().read().busy() {}
T::REGS.cr().modify(|w| {
w.set_dmm(dual_quad);
assert!(_ncs_alt.is_none(), "ncs_alt TODO");
let cssel = if ncs_cssel == 0 { Cssel::B_0X0 } else { Cssel::B_0X1 };
w.set_cssel(cssel);
});
T::REGS.tcr().modify(|w| {
w.set_sshift(config.sample_shifting);
w.set_dhqc(config.delay_hold_quarter_cycle);
});
T::REGS.cr().modify(|w| {
w.set_en(true);
});
if config.free_running_clock {
T::REGS.dcr1().modify(|w| {
w.set_frck(config.free_running_clock);
});
}
Self {
_peri: peri,
_clk,
_d0,
_d1,
_d2,
_d3,
_d4,
_d5,
_d6,
_d7,
_d8,
_d9,
_d10,
_d11,
_d12,
_d13,
_d14,
_d15,
_ncs,
_ncs_alt,
_cssel_swap: ncs_cssel == 1,
_dqs0,
_dqs1,
dma,
_phantom: PhantomData,
config,
width,
}
}
fn configure_command(&mut self, command: &TransferConfig, data_len: Option<usize>) -> Result<(), XspiError> {
if <enums::XspiWidth as Into<u8>>::into(command.iwidth) > <enums::XspiWidth as Into<u8>>::into(self.width)
|| <enums::XspiWidth as Into<u8>>::into(command.adwidth) > <enums::XspiWidth as Into<u8>>::into(self.width)
|| <enums::XspiWidth as Into<u8>>::into(command.abwidth) > <enums::XspiWidth as Into<u8>>::into(self.width)
|| <enums::XspiWidth as Into<u8>>::into(command.dwidth) > <enums::XspiWidth as Into<u8>>::into(self.width)
{
return Err(XspiError::InvalidCommand);
}
T::REGS
.cr()
.modify(|w| w.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into())));
if let Some(ab) = command.alternate_bytes {
T::REGS.abr().write(|v| v.set_alternate(ab));
} else {
T::REGS.ccr().modify(|w| {
w.set_abmode(CcrAbmode::B_0X0);
})
}
T::REGS.tcr().modify(|w| {
w.set_dcyc(command.dummy.into());
});
#[cfg(stm32n6)]
if command.ddtr {
T::REGS.tcr().modify(|w| {
w.set_sshift(false);
});
}
if let Some(data_length) = data_len {
T::REGS.dlr().write(|v| {
v.set_dl((data_length - 1) as u32);
});
} else {
T::REGS.dlr().write(|v| {
v.set_dl((0) as u32);
});
}
T::REGS.ccr().modify(|w| {
w.set_imode(CcrImode::from_bits(command.iwidth.into()));
w.set_idtr(command.idtr);
w.set_isize(CcrIsize::from_bits(command.isize.into()));
w.set_admode(CcrAdmode::from_bits(command.adwidth.into()));
w.set_addtr(command.addtr);
w.set_adsize(CcrAdsize::from_bits(command.adsize.into()));
w.set_abmode(CcrAbmode::from_bits(command.abwidth.into()));
w.set_abdtr(command.abdtr);
w.set_absize(CcrAbsize::from_bits(command.absize.into()));
w.set_dmode(CcrDmode::from_bits(command.dwidth.into()));
w.set_ddtr(command.ddtr);
w.set_dqse(command.dqse);
});
if let Some(instruction) = command.instruction {
if let Some(address) = command.address {
T::REGS.ir().write(|v| {
v.set_instruction(instruction);
});
T::REGS.ar().write(|v| {
v.set_address(address);
});
} else {
#[cfg(stm32n6)]
if data_len.is_none() && self.config.delay_hold_quarter_cycle && command.idtr {
T::REGS.ccr().modify(|w| {
w.set_ddtr(true);
});
}
T::REGS.ir().write(|v| {
v.set_instruction(instruction);
});
}
} else {
if let Some(address) = command.address {
T::REGS.ar().write(|v| {
v.set_address(address);
});
} else {
return Err(XspiError::InvalidCommand);
}
}
Ok(())
}
pub fn blocking_command(&mut self, command: &TransferConfig) -> Result<(), XspiError> {
while T::REGS.sr().read().busy() {}
self.configure_command(command, None)?;
while !T::REGS.sr().read().tcf() {}
T::REGS.fcr().write(|w| {
w.set_ctcf(true);
});
Ok(())
}
pub fn blocking_read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), XspiError> {
if buf.is_empty() {
return Err(XspiError::EmptyBuffer);
}
while T::REGS.sr().read().busy() {}
T::REGS.cr().modify(|w| {
w.set_dmaen(false);
});
let transfer_size_bytes = buf.len() * W::size().bytes();
self.configure_command(&transaction, Some(transfer_size_bytes))?;
let current_address = T::REGS.ar().read().address();
let current_instruction = T::REGS.ir().read().instruction();
T::REGS
.cr()
.modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectRead.into())));
if T::REGS.ccr().read().admode() == CcrAdmode::B_0X0 {
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
} else {
T::REGS.ar().write(|v| v.set_address(current_address));
}
for idx in 0..buf.len() {
while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut W).read_volatile() };
}
while !T::REGS.sr().read().tcf() {}
T::REGS.fcr().write(|v| v.set_ctcf(true));
Ok(())
}
pub fn blocking_write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), XspiError> {
if buf.is_empty() {
return Err(XspiError::EmptyBuffer);
}
while T::REGS.sr().read().busy() {}
T::REGS.cr().modify(|w| {
w.set_dmaen(false);
});
let transfer_size_bytes = buf.len() * W::size().bytes();
self.configure_command(&transaction, Some(transfer_size_bytes))?;
T::REGS
.cr()
.modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into())));
for idx in 0..buf.len() {
while !T::REGS.sr().read().ftf() {}
unsafe { (T::REGS.dr().as_ptr() as *mut W).write_volatile(buf[idx]) };
}
while !T::REGS.sr().read().tcf() {}
T::REGS.fcr().write(|v| v.set_ctcf(true));
Ok(())
}
pub fn set_config(&mut self, config: &Config) {
while T::REGS.sr().read().busy() {}
T::REGS.cr().modify(|w| {
w.set_dmaen(false);
});
T::REGS.dcr1().modify(|w| {
w.set_devsize(config.device_size.into());
w.set_mtyp(Mtyp::from_bits(config.memory_type.into()));
w.set_csht(Csht::from_bits(config.chip_select_high_time.into()));
w.set_frck(false);
w.set_ckmode(match config.clock_mode {
true => Ckmode::B_0X1,
false => Ckmode::B_0X0,
});
});
T::REGS.dcr2().modify(|w| {
w.set_wrapsize(Wrapsize::from_bits(config.wrap_size.into()));
});
T::REGS.dcr3().modify(|w| {
w.set_csbound(Csbound::from_bits(config.chip_select_boundary.into()));
#[cfg(xspi_v1)]
{
w.set_maxtran(Maxtran::from_bits(config.max_transfer.into()));
}
});
T::REGS.dcr4().modify(|w| {
w.set_refresh(Refresh::from_bits(config.refresh.into()));
});
T::REGS.cr().modify(|w| {
w.set_fthres(Fthres::from_bits(config.fifo_threshold.into()));
});
while T::REGS.sr().read().busy() {}
T::REGS.dcr2().modify(|w| {
w.set_prescaler(config.clock_prescaler);
});
T::REGS.tcr().modify(|w| {
w.set_sshift(config.sample_shifting);
w.set_dhqc(config.delay_hold_quarter_cycle);
});
T::REGS.cr().modify(|w| {
w.set_en(true);
});
if config.free_running_clock {
T::REGS.dcr1().modify(|w| {
w.set_frck(config.free_running_clock);
});
}
self.config = *config;
}
pub fn get_config(&self) -> Config {
self.config
}
}
impl<'d, T: Instance> Xspi<'d, T, Blocking> {
pub fn new_blocking_singlespi(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::input(Pull::None)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
None,
config,
XspiWidth::SING,
false,
)
}
pub fn new_blocking_dualspi(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
None,
config,
XspiWidth::DUAL,
false,
)
}
pub fn new_blocking_quadspi(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
None,
config,
XspiWidth::QUAD,
false,
)
}
pub fn new_blocking_dualquadspi(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
None,
config,
XspiWidth::QUAD,
true,
)
}
pub fn new_blocking_xspi(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
None,
config,
XspiWidth::OCTO,
false,
)
}
pub fn new_blocking_xspi_dqs(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dqs0: Peri<'d, impl DQS0Pin<T>>,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_pin!(dqs0, AfType::input(Pull::None)),
None,
None,
config,
XspiWidth::OCTO,
false,
)
}
pub fn new_blocking_xspi_hexa(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
d8: Peri<'d, impl D8Pin<T>>,
d9: Peri<'d, impl D9Pin<T>>,
d10: Peri<'d, impl D10Pin<T>>,
d11: Peri<'d, impl D11Pin<T>>,
d12: Peri<'d, impl D12Pin<T>>,
d13: Peri<'d, impl D13Pin<T>>,
d14: Peri<'d, impl D14Pin<T>>,
d15: Peri<'d, impl D15Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d8, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d9, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d10, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d11, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d12, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d13, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d14, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d15, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
None,
config,
XspiWidth::HEXA,
false,
)
}
#[cfg(xspim_v1)]
pub fn new_blocking_xspi_hexa_dqs(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
d8: Peri<'d, impl D8Pin<T>>,
d9: Peri<'d, impl D9Pin<T>>,
d10: Peri<'d, impl D10Pin<T>>,
d11: Peri<'d, impl D11Pin<T>>,
d12: Peri<'d, impl D12Pin<T>>,
d13: Peri<'d, impl D13Pin<T>>,
d14: Peri<'d, impl D14Pin<T>>,
d15: Peri<'d, impl D15Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dqs0: Peri<'d, impl DQS0Pin<T>>,
config: Config,
) -> Self {
debug!("XSPI hexa_dqs: starting, about to configure pins");
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d8, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d9, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d10, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d11, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d12, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d13, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d14, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d15, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_pin!(dqs0, AfType::input(Pull::None)),
None,
None,
config,
XspiWidth::HEXA,
false,
)
}
#[cfg(xspim_v1)]
pub fn new_blocking_xspi_hexa_dqs_dual(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
d8: Peri<'d, impl D8Pin<T>>,
d9: Peri<'d, impl D9Pin<T>>,
d10: Peri<'d, impl D10Pin<T>>,
d11: Peri<'d, impl D11Pin<T>>,
d12: Peri<'d, impl D12Pin<T>>,
d13: Peri<'d, impl D13Pin<T>>,
d14: Peri<'d, impl D14Pin<T>>,
d15: Peri<'d, impl D15Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dqs0: Peri<'d, impl DQS0Pin<T>>,
dqs1: Peri<'d, impl DQS1Pin<T>>,
config: Config,
) -> Self {
debug!("XSPI hexa_dqs_dual: starting, about to configure pins");
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d8, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d9, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d10, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d11, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d12, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d13, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d14, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d15, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_pin!(dqs0, AfType::input(Pull::None)),
new_pin!(dqs1, AfType::input(Pull::None)),
None,
config,
XspiWidth::HEXA,
false,
)
}
}
impl<'d, T: Instance> Xspi<'d, T, Async> {
pub fn new_singlespi<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::input(Pull::None)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
new_dma!(dma, _irq),
config,
XspiWidth::SING,
false,
)
}
pub fn new_dualspi<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
new_dma!(dma, _irq),
config,
XspiWidth::DUAL,
false,
)
}
pub fn new_quadspi<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
new_dma!(dma, _irq),
config,
XspiWidth::QUAD,
false,
)
}
pub fn new_dualquadspi<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
new_dma!(dma, _irq),
config,
XspiWidth::QUAD,
true,
)
}
pub fn new_xspi<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
new_dma!(dma, _irq),
config,
XspiWidth::OCTO,
false,
)
}
pub fn new_xspi_dqs<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dqs0: Peri<'d, impl DQS0Pin<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
None,
None,
None,
None,
None,
None,
None,
None,
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_pin!(dqs0, AfType::input(Pull::None)),
None,
new_dma!(dma, _irq),
config,
XspiWidth::OCTO,
false,
)
}
pub fn new_xspi_hexa<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
d8: Peri<'d, impl D8Pin<T>>,
d9: Peri<'d, impl D9Pin<T>>,
d10: Peri<'d, impl D10Pin<T>>,
d11: Peri<'d, impl D11Pin<T>>,
d12: Peri<'d, impl D12Pin<T>>,
d13: Peri<'d, impl D13Pin<T>>,
d14: Peri<'d, impl D14Pin<T>>,
d15: Peri<'d, impl D15Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d8, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d9, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d10, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d11, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d12, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d13, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d14, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d15, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
None,
None,
new_dma!(dma, _irq),
config,
XspiWidth::HEXA,
false,
)
}
#[cfg(xspim_v1)]
pub fn new_xspi_hexa_dqs<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
d8: Peri<'d, impl D8Pin<T>>,
d9: Peri<'d, impl D9Pin<T>>,
d10: Peri<'d, impl D10Pin<T>>,
d11: Peri<'d, impl D11Pin<T>>,
d12: Peri<'d, impl D12Pin<T>>,
d13: Peri<'d, impl D13Pin<T>>,
d14: Peri<'d, impl D14Pin<T>>,
d15: Peri<'d, impl D15Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dqs0: Peri<'d, impl DQS0Pin<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d8, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d9, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d10, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d11, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d12, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d13, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d14, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d15, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_pin!(dqs0, AfType::input(Pull::None)),
None,
new_dma!(dma, _irq),
config,
XspiWidth::HEXA,
false,
)
}
#[cfg(xspim_v1)]
pub fn new_xspi_hexa_dqs_dual<D: XDma<T>>(
peri: Peri<'d, T>,
clk: Peri<'d, impl CLKPin<T>>,
d0: Peri<'d, impl D0Pin<T>>,
d1: Peri<'d, impl D1Pin<T>>,
d2: Peri<'d, impl D2Pin<T>>,
d3: Peri<'d, impl D3Pin<T>>,
d4: Peri<'d, impl D4Pin<T>>,
d5: Peri<'d, impl D5Pin<T>>,
d6: Peri<'d, impl D6Pin<T>>,
d7: Peri<'d, impl D7Pin<T>>,
d8: Peri<'d, impl D8Pin<T>>,
d9: Peri<'d, impl D9Pin<T>>,
d10: Peri<'d, impl D10Pin<T>>,
d11: Peri<'d, impl D11Pin<T>>,
d12: Peri<'d, impl D12Pin<T>>,
d13: Peri<'d, impl D13Pin<T>>,
d14: Peri<'d, impl D14Pin<T>>,
d15: Peri<'d, impl D15Pin<T>>,
ncs: Peri<'d, impl NCSEither<T>>,
dqs0: Peri<'d, impl DQS0Pin<T>>,
dqs1: Peri<'d, impl DQS1Pin<T>>,
dma: Peri<'d, D>,
_irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'd,
config: Config,
) -> Self {
Self::new_inner(
peri,
new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d8, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d9, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d10, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d11, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d12, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d13, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d14, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(d15, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
new_pin!(clk, AfType::output(OutputType::PushPull, Speed::VeryHigh)),
ncs.sel(),
new_pin!(
ncs,
AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)
),
None,
new_pin!(dqs0, AfType::input(Pull::None)),
new_pin!(dqs1, AfType::input(Pull::None)),
new_dma!(dma, _irq),
config,
XspiWidth::HEXA,
false,
)
}
pub fn blocking_read_dma<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), XspiError> {
if buf.is_empty() {
return Err(XspiError::EmptyBuffer);
}
while T::REGS.sr().read().busy() {}
let transfer_size_bytes = buf.len() * W::size().bytes();
self.configure_command(&transaction, Some(transfer_size_bytes))?;
let current_address = T::REGS.ar().read().address();
let current_instruction = T::REGS.ir().read().instruction();
T::REGS
.cr()
.modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectRead.into())));
if T::REGS.ccr().read().admode() == CcrAdmode::B_0X0 {
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
} else {
T::REGS.ar().write(|v| v.set_address(current_address));
}
for chunk in buf.chunks_mut(0xFFFF / W::size().bytes()) {
let transfer = unsafe {
self.dma
.as_mut()
.unwrap()
.read(T::REGS.dr().as_ptr() as *mut W, chunk, Default::default())
};
T::REGS.cr().modify(|w| w.set_dmaen(true));
transfer.blocking_wait();
}
finish_dma(T::REGS);
Ok(())
}
pub fn blocking_write_dma<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), XspiError> {
if buf.is_empty() {
return Err(XspiError::EmptyBuffer);
}
while T::REGS.sr().read().busy() {}
let transfer_size_bytes = buf.len() * W::size().bytes();
self.configure_command(&transaction, Some(transfer_size_bytes))?;
T::REGS
.cr()
.modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into())));
for chunk in buf.chunks(0xFFFF / W::size().bytes()) {
let transfer = unsafe {
self.dma
.as_mut()
.unwrap()
.write(chunk, 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(())
}
pub async fn read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), XspiError> {
if buf.is_empty() {
return Err(XspiError::EmptyBuffer);
}
while T::REGS.sr().read().busy() {}
let transfer_size_bytes = buf.len() * W::size().bytes();
self.configure_command(&transaction, Some(transfer_size_bytes))?;
let current_address = T::REGS.ar().read().address();
let current_instruction = T::REGS.ir().read().instruction();
T::REGS
.cr()
.modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectRead.into())));
if T::REGS.ccr().read().admode() == CcrAdmode::B_0X0 {
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
} else {
T::REGS.ar().write(|v| v.set_address(current_address));
}
for chunk in buf.chunks_mut(0xFFFF / W::size().bytes()) {
let transfer = unsafe {
self.dma
.as_mut()
.unwrap()
.read(T::REGS.dr().as_ptr() as *mut W, chunk, Default::default())
};
T::REGS.cr().modify(|w| w.set_dmaen(true));
transfer.await;
}
finish_dma(T::REGS);
Ok(())
}
pub async fn write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), XspiError> {
if buf.is_empty() {
return Err(XspiError::EmptyBuffer);
}
while T::REGS.sr().read().busy() {}
let transfer_size_bytes = buf.len() * W::size().bytes();
self.configure_command(&transaction, Some(transfer_size_bytes))?;
T::REGS
.cr()
.modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into())));
for chunk in buf.chunks(0xFFFF / W::size().bytes()) {
let transfer = unsafe {
self.dma
.as_mut()
.unwrap()
.write(chunk, 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 Xspi<'d, T, M> {
fn drop(&mut self) {
rcc::disable::<T>();
}
}
fn finish_dma(regs: Regs) {
while !regs.sr().read().tcf() {}
regs.fcr().write(|v| v.set_ctcf(true));
regs.cr().modify(|w| {
w.set_dmaen(false);
});
}
#[cfg(xspim_v1)]
pub(crate) trait SealedXspimInstance {
const SPIM_REGS: Xspim;
const SPI_IDX: u8;
}
pub(crate) trait SealedInstance {
const REGS: Regs;
}
#[cfg(xspim_v1)]
#[allow(private_bounds)]
pub trait Instance: SealedInstance + PeripheralType + RccPeripheral + SealedXspimInstance {}
#[cfg(not(xspim_v1))]
#[allow(private_bounds)]
pub trait Instance: SealedInstance + PeripheralType + RccPeripheral {}
pin_trait!(D0Pin, Instance);
pin_trait!(D1Pin, Instance);
pin_trait!(D2Pin, Instance);
pin_trait!(D3Pin, Instance);
pin_trait!(D4Pin, Instance);
pin_trait!(D5Pin, Instance);
pin_trait!(D6Pin, Instance);
pin_trait!(D7Pin, Instance);
pin_trait!(D8Pin, Instance);
pin_trait!(D9Pin, Instance);
pin_trait!(D10Pin, Instance);
pin_trait!(D11Pin, Instance);
pin_trait!(D12Pin, Instance);
pin_trait!(D13Pin, Instance);
pin_trait!(D14Pin, Instance);
pin_trait!(D15Pin, Instance);
pin_trait!(DQS0Pin, Instance);
pin_trait!(DQS1Pin, Instance);
pin_trait!(NCSPin, Instance);
pin_trait!(CLKPin, Instance);
pin_trait!(NCLKPin, Instance);
dma_trait!(XDma, Instance);
pub trait NCSEither<T: Instance>: NCSPin<T> {
fn sel(&self) -> u8;
}
#[cfg(xspim_v1)]
impl SealedXspimInstance for peripherals::XSPI1 {
const SPIM_REGS: Xspim = crate::pac::XSPIM;
const SPI_IDX: u8 = 1;
}
#[cfg(all(xspim_v1, peri_xspi2))]
impl SealedXspimInstance for peripherals::XSPI2 {
const SPIM_REGS: Xspim = crate::pac::XSPIM;
const SPI_IDX: u8 = 2;
}
#[cfg(all(xspim_v1, stm32n6))]
impl SealedXspimInstance for peripherals::XSPI3 {
const SPIM_REGS: Xspim = crate::pac::XSPIM;
const SPI_IDX: u8 = 3;
}
#[cfg(xspim_v1)]
foreach_peripheral!(
(xspi, $inst:ident) => {
impl SealedInstance for peripherals::$inst {
const REGS: Regs = crate::pac::$inst;
}
impl Instance for peripherals::$inst {}
};
);
#[cfg(not(xspim_v1))]
foreach_peripheral!(
(xspi, $inst:ident) => {
impl SealedInstance for peripherals::$inst {
const REGS: Regs = crate::pac::$inst;
}
impl Instance for peripherals::$inst {}
};
);
impl<'d, T: Instance, M: PeriMode> SetConfig for Xspi<'d, T, M> {
type Config = Config;
type ConfigError = ();
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
self.set_config(config);
Ok(())
}
}
impl<'d, T: Instance, M: PeriMode> GetConfig for Xspi<'d, T, M> {
type Config = Config;
fn get_config(&self) -> Self::Config {
self.get_config()
}
}
#[allow(private_bounds)]
pub trait Word: word::Word {}
macro_rules! impl_word {
($T:ty) => {
impl Word for $T {}
};
}
impl_word!(u8);
impl_word!(u16);
impl_word!(u32);