From 6a802c47083e4f6bb7b7c6c06fd2ef3e291a5212 Mon Sep 17 00:00:00 2001 From: Mateusz Butkiewicz Date: Wed, 22 Mar 2023 08:44:58 +0100 Subject: [PATCH 1/2] feat(stm32:qspi): add support for QSPI in stm32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented with help of Tomasz GrzeĊ› . --- embassy-stm32/build.rs | 7 + embassy-stm32/src/lib.rs | 3 +- embassy-stm32/src/qspi/mod.rs | 342 ++++++++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 embassy-stm32/src/qspi/mod.rs diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index dbfc1370..3780c5a4 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -427,6 +427,12 @@ fn main() { (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)), (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)), (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)), + (("quadspi", "BK1_IO0"), quote!(crate::qspi::D0Pin)), + (("quadspi", "BK1_IO1"), quote!(crate::qspi::D1Pin)), + (("quadspi", "BK1_IO2"), quote!(crate::qspi::D2Pin)), + (("quadspi", "BK1_IO3"), quote!(crate::qspi::D3Pin)), + (("quadspi", "CLK"), quote!(crate::qspi::SckPin)), + (("quadspi", "BK1_NCS"), quote!(crate::qspi::NSSPin)), ].into(); for p in METADATA.peripherals { @@ -507,6 +513,7 @@ fn main() { (("dcmi", "PSSI"), quote!(crate::dcmi::FrameDma)), // SDMMCv1 uses the same channel for both directions, so just implement for RX (("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)), + (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), ] .into(); diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index eeaa04f6..8dc4df2d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -48,6 +48,8 @@ pub mod crc; ))] pub mod flash; pub mod pwm; +#[cfg(quadspi)] +pub mod qspi; #[cfg(rng)] pub mod rng; #[cfg(sdmmc)] @@ -60,7 +62,6 @@ pub mod usart; pub mod usb; #[cfg(otg)] pub mod usb_otg; - #[cfg(iwdg)] pub mod wdg; diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs new file mode 100644 index 00000000..f375d1b4 --- /dev/null +++ b/embassy-stm32/src/qspi/mod.rs @@ -0,0 +1,342 @@ +#![macro_use] + +use embassy_hal_common::{into_ref, PeripheralRef}; + +use crate::dma::TransferOptions; +use crate::gpio::sealed::AFType; +use crate::gpio::AnyPin; +use crate::pac::quadspi::Quadspi as Regs; +use crate::rcc::RccPeripheral; +use crate::{peripherals, Peripheral}; + +pub struct QspiWidth; + +#[allow(dead_code)] +impl QspiWidth { + pub const NONE: u8 = 0b00; + pub const SING: u8 = 0b01; + pub const DUAL: u8 = 0b10; + pub const QUAD: u8 = 0b11; +} + +struct QspiMode; + +#[allow(dead_code)] +impl QspiMode { + pub const INDIRECT_WRITE: u8 = 0b00; + pub const INDIRECT_READ: u8 = 0b01; + pub const AUTO_POLLING: u8 = 0b10; + pub const MEMORY_MAPPED: u8 = 0b11; +} + +pub struct QspiTransaction { + pub iwidth: u8, + pub awidth: u8, + pub dwidth: u8, + pub instruction: u8, + pub address: Option, + pub dummy: u8, + pub data_len: Option, +} + +impl Default for QspiTransaction { + fn default() -> Self { + Self { + iwidth: QspiWidth::NONE, + awidth: QspiWidth::NONE, + dwidth: QspiWidth::NONE, + instruction: 0, + address: None, + dummy: 0, + data_len: None, + } + } +} + +pub struct Config { + pub memory_size: u8, + pub address_size: u8, + pub prescaler: u8, + pub fifo_threshold: u8, + pub cs_high_time: u8, +} + +impl Default for Config { + fn default() -> Self { + Self { + memory_size: 0, + address_size: 2, + prescaler: 128, + fifo_threshold: 16, + cs_high_time: 4, + } + } +} + +#[allow(dead_code)] +pub struct Qspi<'d, T: Instance, Dma> { + _peri: PeripheralRef<'d, T>, + sck: Option>, + d0: Option>, + d1: Option>, + d2: Option>, + d3: Option>, + nss: Option>, + dma: PeripheralRef<'d, Dma>, + config: Config, +} + +impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { + pub fn new( + peri: impl Peripheral

+ 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + sck: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(peri, d0, d1, d2, d3, sck, nss); + + unsafe { + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + nss.set_as_af(nss.af_num(), AFType::OutputPushPull); + nss.set_speed(crate::gpio::Speed::VeryHigh); + d0.set_as_af(d0.af_num(), AFType::OutputPushPull); + d0.set_speed(crate::gpio::Speed::VeryHigh); + d1.set_as_af(d1.af_num(), AFType::OutputPushPull); + d1.set_speed(crate::gpio::Speed::VeryHigh); + d2.set_as_af(d2.af_num(), AFType::OutputPushPull); + d2.set_speed(crate::gpio::Speed::VeryHigh); + d3.set_as_af(d3.af_num(), AFType::OutputPushPull); + 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()), + Some(sck.map_into()), + Some(nss.map_into()), + dma, + config, + ) + } + + fn new_inner( + peri: impl Peripheral

+ 'd, + d0: Option>, + d1: Option>, + d2: Option>, + d3: Option>, + sck: Option>, + nss: Option>, + dma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(peri, dma); + + T::enable(); + unsafe { + T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold)); + + while T::REGS.sr().read().busy() {} + + T::REGS.cr().write(|w| { + w.set_prescaler(config.prescaler); + w.set_en(true); + }); + T::REGS.dcr().write(|w| { + w.set_fsize(config.memory_size); + w.set_csht(config.cs_high_time); + w.set_ckmode(false); + }); + } + + Self { + _peri: peri, + sck, + d0, + d1, + d2, + d3, + nss, + dma, + config, + } + } + + pub fn command(&mut self, transaction: QspiTransaction) { + unsafe { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + } + + pub fn read(&mut self, buf: &mut [u8], transaction: QspiTransaction) { + unsafe { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + + if let Some(len) = transaction.data_len { + let current_ar = T::REGS.ar().read().address(); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::INDIRECT_READ); + }); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); + + for idx in 0..len { + while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} + buf[idx] = *(T::REGS.dr().ptr() as *mut u8); + } + } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + } + + pub fn write(&mut self, buf: &[u8], transaction: QspiTransaction) { + unsafe { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + + if let Some(len) = transaction.data_len { + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::INDIRECT_WRITE); + }); + + for idx in 0..len { + while !T::REGS.sr().read().ftf() {} + *(T::REGS.dr().ptr() as *mut u8) = buf[idx]; + } + } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + } + + pub fn read_dma(&mut self, buf: &mut [u8], transaction: QspiTransaction) + where + Dma: QuadDma, + { + unsafe { + self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + + let request = self.dma.request(); + let options = TransferOptions::default(); + + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::INDIRECT_READ); + }); + let current_ar = T::REGS.ar().read().address(); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); + + self.dma + .start_read(request, T::REGS.dr().ptr() as *mut u8, buf, options); + + T::REGS.cr().modify(|v| v.set_dmaen(true)); + + while self.dma.is_running() {} + } + } + + pub fn write_dma(&mut self, buf: &[u8], transaction: QspiTransaction) + where + Dma: QuadDma, + { + unsafe { + self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + + let request = self.dma.request(); + let options = TransferOptions::default(); + + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::INDIRECT_WRITE); + }); + + self.dma + .start_write(request, buf, T::REGS.dr().ptr() as *mut u8, options); + + T::REGS.cr().modify(|v| v.set_dmaen(true)); + + while self.dma.is_running() {} + } + } + + fn setup_transaction(&mut self, fmode: u8, transaction: &QspiTransaction) { + unsafe { + T::REGS.fcr().modify(|v| { + v.set_csmf(true); + v.set_ctcf(true); + v.set_ctef(true); + v.set_ctof(true); + }); + + while T::REGS.sr().read().busy() {} + + if let Some(len) = transaction.data_len { + T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); + } + + T::REGS.ccr().write(|v| { + v.set_fmode(fmode); + v.set_imode(transaction.iwidth); + v.set_instruction(transaction.instruction); + v.set_admode(transaction.awidth); + v.set_adsize(self.config.address_size); + v.set_dmode(transaction.dwidth); + v.set_abmode(QspiWidth::NONE); + v.set_dcyc(transaction.dummy); + }); + + if let Some(addr) = transaction.address { + T::REGS.ar().write(|v| { + v.set_address(addr); + }); + } + } + } +} + +pub(crate) mod sealed { + use super::*; + + pub trait Instance { + const REGS: Regs; + } +} + +pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} + +pin_trait!(SckPin, Instance); +pin_trait!(D0Pin, Instance); +pin_trait!(D1Pin, Instance); +pin_trait!(D2Pin, Instance); +pin_trait!(D3Pin, Instance); +pin_trait!(NSSPin, Instance); + +dma_trait!(QuadDma, Instance); + +foreach_peripheral!( + (quadspi, $inst:ident) => { + impl sealed::Instance for peripherals::$inst { + const REGS: Regs = crate::pac::$inst; + } + + impl Instance for peripherals::$inst {} + }; +); From 87898501a2f66ee179562fa88bfc9a1b4a2ada9b Mon Sep 17 00:00:00 2001 From: Mateusz Butkiewicz Date: Wed, 29 Mar 2023 13:27:20 +0200 Subject: [PATCH 2/2] feat(stm32:qspi): convert some u8 to enum variants --- embassy-stm32/src/qspi/enums.rs | 294 ++++++++++++++++++++++++++++++++ embassy-stm32/src/qspi/mod.rs | 116 ++++++------- 2 files changed, 350 insertions(+), 60 deletions(-) create mode 100644 embassy-stm32/src/qspi/enums.rs diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs new file mode 100644 index 00000000..2dbe2b06 --- /dev/null +++ b/embassy-stm32/src/qspi/enums.rs @@ -0,0 +1,294 @@ +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum QspiMode { + IndirectWrite, + IndirectRead, + AutoPolling, + MemoryMapped, +} + +impl Into for QspiMode { + fn into(self) -> u8 { + match self { + QspiMode::IndirectWrite => 0b00, + QspiMode::IndirectRead => 0b01, + QspiMode::AutoPolling => 0b10, + QspiMode::MemoryMapped => 0b11, + } + } +} + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub enum QspiWidth { + NONE, + SING, + DUAL, + QUAD, +} + +impl Into for QspiWidth { + fn into(self) -> u8 { + match self { + QspiWidth::NONE => 0b00, + QspiWidth::SING => 0b01, + QspiWidth::DUAL => 0b10, + QspiWidth::QUAD => 0b11, + } + } +} + +#[derive(Copy, Clone)] +pub enum MemorySize { + _1KiB, + _2KiB, + _4KiB, + _8KiB, + _16KiB, + _32KiB, + _64KiB, + _128KiB, + _256KiB, + _512KiB, + _1MiB, + _2MiB, + _4MiB, + _8MiB, + _16MiB, + _32MiB, + _64MiB, + _128MiB, + _256MiB, + _512MiB, + _1GiB, + _2GiB, + _4GiB, + Other(u8), +} + +impl Into for MemorySize { + fn into(self) -> u8 { + match self { + MemorySize::_1KiB => 9, + MemorySize::_2KiB => 10, + MemorySize::_4KiB => 11, + MemorySize::_8KiB => 12, + MemorySize::_16KiB => 13, + MemorySize::_32KiB => 14, + MemorySize::_64KiB => 15, + MemorySize::_128KiB => 16, + MemorySize::_256KiB => 17, + MemorySize::_512KiB => 18, + MemorySize::_1MiB => 19, + MemorySize::_2MiB => 20, + MemorySize::_4MiB => 21, + MemorySize::_8MiB => 22, + MemorySize::_16MiB => 23, + MemorySize::_32MiB => 24, + MemorySize::_64MiB => 25, + MemorySize::_128MiB => 26, + MemorySize::_256MiB => 27, + MemorySize::_512MiB => 28, + MemorySize::_1GiB => 29, + MemorySize::_2GiB => 30, + MemorySize::_4GiB => 31, + MemorySize::Other(val) => val, + } + } +} + +#[derive(Copy, Clone)] +pub enum AddressSize { + _8Bit, + _16Bit, + _24bit, + _32bit, +} + +impl Into for AddressSize { + fn into(self) -> u8 { + match self { + AddressSize::_8Bit => 0b00, + AddressSize::_16Bit => 0b01, + AddressSize::_24bit => 0b10, + AddressSize::_32bit => 0b11, + } + } +} + +#[derive(Copy, Clone)] +pub enum ChipSelectHightTime { + _1Cycle, + _2Cycle, + _3Cycle, + _4Cycle, + _5Cycle, + _6Cycle, + _7Cycle, + _8Cycle, +} + +impl Into for ChipSelectHightTime { + fn into(self) -> u8 { + match self { + ChipSelectHightTime::_1Cycle => 0, + ChipSelectHightTime::_2Cycle => 1, + ChipSelectHightTime::_3Cycle => 2, + ChipSelectHightTime::_4Cycle => 3, + ChipSelectHightTime::_5Cycle => 4, + ChipSelectHightTime::_6Cycle => 5, + ChipSelectHightTime::_7Cycle => 6, + ChipSelectHightTime::_8Cycle => 7, + } + } +} + +#[derive(Copy, Clone)] +pub enum FIFOThresholdLevel { + _1Bytes, + _2Bytes, + _3Bytes, + _4Bytes, + _5Bytes, + _6Bytes, + _7Bytes, + _8Bytes, + _9Bytes, + _10Bytes, + _11Bytes, + _12Bytes, + _13Bytes, + _14Bytes, + _15Bytes, + _16Bytes, + _17Bytes, + _18Bytes, + _19Bytes, + _20Bytes, + _21Bytes, + _22Bytes, + _23Bytes, + _24Bytes, + _25Bytes, + _26Bytes, + _27Bytes, + _28Bytes, + _29Bytes, + _30Bytes, + _31Bytes, + _32Bytes, +} + +impl Into for FIFOThresholdLevel { + fn into(self) -> u8 { + match self { + FIFOThresholdLevel::_1Bytes => 0, + FIFOThresholdLevel::_2Bytes => 1, + FIFOThresholdLevel::_3Bytes => 2, + FIFOThresholdLevel::_4Bytes => 3, + FIFOThresholdLevel::_5Bytes => 4, + FIFOThresholdLevel::_6Bytes => 5, + FIFOThresholdLevel::_7Bytes => 6, + FIFOThresholdLevel::_8Bytes => 7, + FIFOThresholdLevel::_9Bytes => 8, + FIFOThresholdLevel::_10Bytes => 9, + FIFOThresholdLevel::_11Bytes => 10, + FIFOThresholdLevel::_12Bytes => 11, + FIFOThresholdLevel::_13Bytes => 12, + FIFOThresholdLevel::_14Bytes => 13, + FIFOThresholdLevel::_15Bytes => 14, + FIFOThresholdLevel::_16Bytes => 15, + FIFOThresholdLevel::_17Bytes => 16, + FIFOThresholdLevel::_18Bytes => 17, + FIFOThresholdLevel::_19Bytes => 18, + FIFOThresholdLevel::_20Bytes => 19, + FIFOThresholdLevel::_21Bytes => 20, + FIFOThresholdLevel::_22Bytes => 21, + FIFOThresholdLevel::_23Bytes => 22, + FIFOThresholdLevel::_24Bytes => 23, + FIFOThresholdLevel::_25Bytes => 24, + FIFOThresholdLevel::_26Bytes => 25, + FIFOThresholdLevel::_27Bytes => 26, + FIFOThresholdLevel::_28Bytes => 27, + FIFOThresholdLevel::_29Bytes => 28, + FIFOThresholdLevel::_30Bytes => 29, + FIFOThresholdLevel::_31Bytes => 30, + FIFOThresholdLevel::_32Bytes => 31, + } + } +} + +#[derive(Copy, Clone)] +pub enum DummyCycles { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + _16, + _17, + _18, + _19, + _20, + _21, + _22, + _23, + _24, + _25, + _26, + _27, + _28, + _29, + _30, + _31, +} + +impl Into for DummyCycles { + fn into(self) -> u8 { + match self { + DummyCycles::_0 => 0, + DummyCycles::_1 => 1, + DummyCycles::_2 => 2, + DummyCycles::_3 => 3, + DummyCycles::_4 => 4, + DummyCycles::_5 => 5, + DummyCycles::_6 => 6, + DummyCycles::_7 => 7, + DummyCycles::_8 => 8, + DummyCycles::_9 => 9, + DummyCycles::_10 => 10, + DummyCycles::_11 => 11, + DummyCycles::_12 => 12, + DummyCycles::_13 => 13, + DummyCycles::_14 => 14, + DummyCycles::_15 => 15, + DummyCycles::_16 => 16, + DummyCycles::_17 => 17, + DummyCycles::_18 => 18, + DummyCycles::_19 => 19, + DummyCycles::_20 => 20, + DummyCycles::_21 => 21, + DummyCycles::_22 => 22, + DummyCycles::_23 => 23, + DummyCycles::_24 => 24, + DummyCycles::_25 => 25, + DummyCycles::_26 => 26, + DummyCycles::_27 => 27, + DummyCycles::_28 => 28, + DummyCycles::_29 => 29, + DummyCycles::_30 => 30, + DummyCycles::_31 => 31, + } + } +} diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index f375d1b4..f3331962 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -1,6 +1,9 @@ #![macro_use] +pub mod enums; + use embassy_hal_common::{into_ref, PeripheralRef}; +use enums::*; use crate::dma::TransferOptions; use crate::gpio::sealed::AFType; @@ -9,37 +12,24 @@ use crate::pac::quadspi::Quadspi as Regs; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; -pub struct QspiWidth; - -#[allow(dead_code)] -impl QspiWidth { - pub const NONE: u8 = 0b00; - pub const SING: u8 = 0b01; - pub const DUAL: u8 = 0b10; - pub const QUAD: u8 = 0b11; -} - -struct QspiMode; - -#[allow(dead_code)] -impl QspiMode { - pub const INDIRECT_WRITE: u8 = 0b00; - pub const INDIRECT_READ: u8 = 0b01; - pub const AUTO_POLLING: u8 = 0b10; - pub const MEMORY_MAPPED: u8 = 0b11; -} - -pub struct QspiTransaction { - pub iwidth: u8, - pub awidth: u8, - pub dwidth: u8, +pub struct TransferConfig { + /// Instraction width (IMODE) + pub iwidth: QspiWidth, + /// Address width (ADMODE) + pub awidth: QspiWidth, + /// Data width (DMODE) + pub dwidth: QspiWidth, + /// Instruction Id pub instruction: u8, + /// Flash memory address pub address: Option, - pub dummy: u8, + /// Number of dummy cycles (DCYC) + pub dummy: DummyCycles, + /// Length of data pub data_len: Option, } -impl Default for QspiTransaction { +impl Default for TransferConfig { fn default() -> Self { Self { iwidth: QspiWidth::NONE, @@ -47,28 +37,34 @@ impl Default for QspiTransaction { dwidth: QspiWidth::NONE, instruction: 0, address: None, - dummy: 0, + dummy: DummyCycles::_0, data_len: None, } } } pub struct Config { - pub memory_size: u8, - pub address_size: u8, + /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. + /// If you need other value the whose predefined use `Other` variant. + pub memory_size: MemorySize, + /// Address size (8/16/24/32-bit) + pub address_size: AddressSize, + /// Scalar factor for generating CLK [0-255] pub prescaler: u8, - pub fifo_threshold: u8, - pub cs_high_time: u8, + /// Number of bytes to trigger FIFO threshold flag. + pub fifo_threshold: FIFOThresholdLevel, + /// Minimum number of cycles that chip select must be high between issued commands + pub cs_high_time: ChipSelectHightTime, } impl Default for Config { fn default() -> Self { Self { - memory_size: 0, - address_size: 2, + memory_size: MemorySize::Other(0), + address_size: AddressSize::_24bit, prescaler: 128, - fifo_threshold: 16, - cs_high_time: 4, + fifo_threshold: FIFOThresholdLevel::_17Bytes, + cs_high_time: ChipSelectHightTime::_5Cycle, } } } @@ -143,7 +139,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { T::enable(); unsafe { - T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold)); + T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); while T::REGS.sr().read().busy() {} @@ -152,8 +148,8 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { w.set_en(true); }); T::REGS.dcr().write(|w| { - w.set_fsize(config.memory_size); - w.set_csht(config.cs_high_time); + w.set_fsize(config.memory_size.into()); + w.set_csht(config.cs_high_time.into()); w.set_ckmode(false); }); } @@ -171,25 +167,25 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } } - pub fn command(&mut self, transaction: QspiTransaction) { + pub fn command(&mut self, transaction: TransferConfig) { unsafe { T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); while !T::REGS.sr().read().tcf() {} T::REGS.fcr().modify(|v| v.set_ctcf(true)); } } - pub fn read(&mut self, buf: &mut [u8], transaction: QspiTransaction) { + pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { unsafe { T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); if let Some(len) = transaction.data_len { let current_ar = T::REGS.ar().read().address(); T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::INDIRECT_READ); + v.set_fmode(QspiMode::IndirectRead.into()); }); T::REGS.ar().write(|v| { v.set_address(current_ar); @@ -206,14 +202,14 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } } - pub fn write(&mut self, buf: &[u8], transaction: QspiTransaction) { + pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { unsafe { T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); if let Some(len) = transaction.data_len { T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::INDIRECT_WRITE); + v.set_fmode(QspiMode::IndirectWrite.into()); }); for idx in 0..len { @@ -227,18 +223,18 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } } - pub fn read_dma(&mut self, buf: &mut [u8], transaction: QspiTransaction) + pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) where Dma: QuadDma, { unsafe { - self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); let request = self.dma.request(); let options = TransferOptions::default(); T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::INDIRECT_READ); + v.set_fmode(QspiMode::IndirectRead.into()); }); let current_ar = T::REGS.ar().read().address(); T::REGS.ar().write(|v| { @@ -254,18 +250,18 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } } - pub fn write_dma(&mut self, buf: &[u8], transaction: QspiTransaction) + pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) where Dma: QuadDma, { unsafe { - self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); let request = self.dma.request(); let options = TransferOptions::default(); T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::INDIRECT_WRITE); + v.set_fmode(QspiMode::IndirectWrite.into()); }); self.dma @@ -277,7 +273,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } } - fn setup_transaction(&mut self, fmode: u8, transaction: &QspiTransaction) { + fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { unsafe { T::REGS.fcr().modify(|v| { v.set_csmf(true); @@ -293,14 +289,14 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } T::REGS.ccr().write(|v| { - v.set_fmode(fmode); - v.set_imode(transaction.iwidth); + v.set_fmode(fmode.into()); + v.set_imode(transaction.iwidth.into()); v.set_instruction(transaction.instruction); - v.set_admode(transaction.awidth); - v.set_adsize(self.config.address_size); - v.set_dmode(transaction.dwidth); - v.set_abmode(QspiWidth::NONE); - v.set_dcyc(transaction.dummy); + v.set_admode(transaction.awidth.into()); + v.set_adsize(self.config.address_size.into()); + v.set_dmode(transaction.dwidth.into()); + v.set_abmode(QspiWidth::NONE.into()); + v.set_dcyc(transaction.dummy.into()); }); if let Some(addr) = transaction.address {