feat(stm32:qspi): convert some u8 to enum variants

This commit is contained in:
Mateusz Butkiewicz 2023-03-29 13:27:20 +02:00
parent 6a802c4708
commit 87898501a2
2 changed files with 350 additions and 60 deletions

View file

@ -0,0 +1,294 @@
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub(crate) enum QspiMode {
IndirectWrite,
IndirectRead,
AutoPolling,
MemoryMapped,
}
impl Into<u8> 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<u8> 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<u8> 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<u8> 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<u8> 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<u8> 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<u8> 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,
}
}
}

View file

@ -1,6 +1,9 @@
#![macro_use] #![macro_use]
pub mod enums;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use enums::*;
use crate::dma::TransferOptions; use crate::dma::TransferOptions;
use crate::gpio::sealed::AFType; use crate::gpio::sealed::AFType;
@ -9,37 +12,24 @@ use crate::pac::quadspi::Quadspi as Regs;
use crate::rcc::RccPeripheral; use crate::rcc::RccPeripheral;
use crate::{peripherals, Peripheral}; use crate::{peripherals, Peripheral};
pub struct QspiWidth; pub struct TransferConfig {
/// Instraction width (IMODE)
#[allow(dead_code)] pub iwidth: QspiWidth,
impl QspiWidth { /// Address width (ADMODE)
pub const NONE: u8 = 0b00; pub awidth: QspiWidth,
pub const SING: u8 = 0b01; /// Data width (DMODE)
pub const DUAL: u8 = 0b10; pub dwidth: QspiWidth,
pub const QUAD: u8 = 0b11; /// Instruction Id
}
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 instruction: u8,
/// Flash memory address
pub address: Option<u32>, pub address: Option<u32>,
pub dummy: u8, /// Number of dummy cycles (DCYC)
pub dummy: DummyCycles,
/// Length of data
pub data_len: Option<usize>, pub data_len: Option<usize>,
} }
impl Default for QspiTransaction { impl Default for TransferConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
iwidth: QspiWidth::NONE, iwidth: QspiWidth::NONE,
@ -47,28 +37,34 @@ impl Default for QspiTransaction {
dwidth: QspiWidth::NONE, dwidth: QspiWidth::NONE,
instruction: 0, instruction: 0,
address: None, address: None,
dummy: 0, dummy: DummyCycles::_0,
data_len: None, data_len: None,
} }
} }
} }
pub struct Config { pub struct Config {
pub memory_size: u8, /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen.
pub address_size: u8, /// 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 prescaler: u8,
pub fifo_threshold: u8, /// Number of bytes to trigger FIFO threshold flag.
pub cs_high_time: u8, 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 { impl Default for Config {
fn default() -> Self { fn default() -> Self {
Self { Self {
memory_size: 0, memory_size: MemorySize::Other(0),
address_size: 2, address_size: AddressSize::_24bit,
prescaler: 128, prescaler: 128,
fifo_threshold: 16, fifo_threshold: FIFOThresholdLevel::_17Bytes,
cs_high_time: 4, cs_high_time: ChipSelectHightTime::_5Cycle,
} }
} }
} }
@ -143,7 +139,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
T::enable(); T::enable();
unsafe { 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() {} while T::REGS.sr().read().busy() {}
@ -152,8 +148,8 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
w.set_en(true); w.set_en(true);
}); });
T::REGS.dcr().write(|w| { T::REGS.dcr().write(|w| {
w.set_fsize(config.memory_size); w.set_fsize(config.memory_size.into());
w.set_csht(config.cs_high_time); w.set_csht(config.cs_high_time.into());
w.set_ckmode(false); 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 { unsafe {
T::REGS.cr().modify(|v| v.set_dmaen(false)); 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() {} while !T::REGS.sr().read().tcf() {}
T::REGS.fcr().modify(|v| v.set_ctcf(true)); 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 { unsafe {
T::REGS.cr().modify(|v| v.set_dmaen(false)); 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 { if let Some(len) = transaction.data_len {
let current_ar = T::REGS.ar().read().address(); let current_ar = T::REGS.ar().read().address();
T::REGS.ccr().modify(|v| { T::REGS.ccr().modify(|v| {
v.set_fmode(QspiMode::INDIRECT_READ); v.set_fmode(QspiMode::IndirectRead.into());
}); });
T::REGS.ar().write(|v| { T::REGS.ar().write(|v| {
v.set_address(current_ar); 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 { unsafe {
T::REGS.cr().modify(|v| v.set_dmaen(false)); 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 { if let Some(len) = transaction.data_len {
T::REGS.ccr().modify(|v| { T::REGS.ccr().modify(|v| {
v.set_fmode(QspiMode::INDIRECT_WRITE); v.set_fmode(QspiMode::IndirectWrite.into());
}); });
for idx in 0..len { 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 where
Dma: QuadDma<T>, Dma: QuadDma<T>,
{ {
unsafe { unsafe {
self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); self.setup_transaction(QspiMode::IndirectWrite, &transaction);
let request = self.dma.request(); let request = self.dma.request();
let options = TransferOptions::default(); let options = TransferOptions::default();
T::REGS.ccr().modify(|v| { 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(); let current_ar = T::REGS.ar().read().address();
T::REGS.ar().write(|v| { 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 where
Dma: QuadDma<T>, Dma: QuadDma<T>,
{ {
unsafe { unsafe {
self.setup_transaction(QspiMode::INDIRECT_WRITE, &transaction); self.setup_transaction(QspiMode::IndirectWrite, &transaction);
let request = self.dma.request(); let request = self.dma.request();
let options = TransferOptions::default(); let options = TransferOptions::default();
T::REGS.ccr().modify(|v| { T::REGS.ccr().modify(|v| {
v.set_fmode(QspiMode::INDIRECT_WRITE); v.set_fmode(QspiMode::IndirectWrite.into());
}); });
self.dma 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 { unsafe {
T::REGS.fcr().modify(|v| { T::REGS.fcr().modify(|v| {
v.set_csmf(true); v.set_csmf(true);
@ -293,14 +289,14 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
} }
T::REGS.ccr().write(|v| { T::REGS.ccr().write(|v| {
v.set_fmode(fmode); v.set_fmode(fmode.into());
v.set_imode(transaction.iwidth); v.set_imode(transaction.iwidth.into());
v.set_instruction(transaction.instruction); v.set_instruction(transaction.instruction);
v.set_admode(transaction.awidth); v.set_admode(transaction.awidth.into());
v.set_adsize(self.config.address_size); v.set_adsize(self.config.address_size.into());
v.set_dmode(transaction.dwidth); v.set_dmode(transaction.dwidth.into());
v.set_abmode(QspiWidth::NONE); v.set_abmode(QspiWidth::NONE.into());
v.set_dcyc(transaction.dummy); v.set_dcyc(transaction.dummy.into());
}); });
if let Some(addr) = transaction.address { if let Some(addr) = transaction.address {