Add transfer config, trait, functional initial configuration and read from memory

This commit is contained in:
Karun 2024-02-05 21:23:03 -05:00
parent f3609f2842
commit 9ed8d01b11

View file

@ -3,12 +3,17 @@
#![macro_use]
pub mod enums;
use core::ops::Add;
use core::ptr;
use embassy_embedded_hal::SetConfig;
use embassy_futures::join::join;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embedded_hal_02::blocking::i2c::Operation;
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
use enums::*;
use crate::dma::{slice_ptr_parts, word, Transfer};
use crate::gpio::sealed::{AFType, Pin as _};
@ -18,8 +23,109 @@ use crate::rcc::RccPeripheral;
use crate::time::Hertz;
use crate::{peripherals, Peripheral};
/// OPSI driver config.
pub struct Config;
/// OSPI transfer configuration.
pub struct TransferConfig {
/// Instruction width (IMODE)
pub iwidth: OspiWidth,
/// Instruction Id
pub instruction: Option<u32>,
/// Number of Instruction Bytes
pub isize: AddressSize,
/// Instruction Double Transfer rate enable
pub idtr: bool,
/// Address width (ADMODE)
pub adwidth: OspiWidth,
/// Device memory address
pub address: Option<u32>,
/// Number of Address Bytes
pub adsize: AddressSize,
/// Address Double Transfer rate enable
pub addtr: bool,
/// Alternate bytes width (ABMODE)
pub abwidth: OspiWidth,
/// Alternate Bytes
pub alternate_bytes: Option<u32>,
/// Number of Alternate Bytes
pub absize: AddressSize,
/// Alternate Bytes Double Transfer rate enable
pub abdtr: bool,
/// Data width (DMODE)
pub dwidth: OspiWidth,
/// Length of data
pub data_len: Option<usize>,
/// Data buffer
pub ddtr: bool,
/// Number of dummy cycles (DCYC)
pub dummy: DummyCycles,
}
impl Default for TransferConfig {
fn default() -> Self {
Self {
iwidth: OspiWidth::NONE,
instruction: None,
isize: AddressSize::_8Bit,
idtr: false,
adwidth: OspiWidth::NONE,
address: None,
adsize: AddressSize::_8Bit,
addtr: false,
abwidth: OspiWidth::NONE,
alternate_bytes: None,
absize: AddressSize::_8Bit,
abdtr: false,
dwidth: OspiWidth::NONE,
data_len: None,
ddtr: false,
dummy: DummyCycles::_0,
}
}
}
pub enum OspiError {
Test,
}
pub trait Error {}
pub trait ErrorType {
type Error: Error;
}
impl<T: ErrorType + ?Sized> ErrorType for &mut T {
type Error = T::Error;
}
/// MultiSpi interface trait
pub trait MultiSpi: ErrorType {
/// Transaction configuration for specific multispi implementation
type Config;
/// Command function used for a configuration operation, when no user data is
/// supplied to or read from the target device.
async fn command(&mut self, config: Self::Config) -> Result<(), Self::Error>;
/// Read function used to read data from the target device following the supplied transaction
/// configuration.
async fn read(&mut self, data: &mut [u8], config: Self::Config) -> Result<(), Self::Error>;
/// Write function used to send data to the target device following the supplied transaction
/// configuration.
async fn write(&mut self, data: &mut [u8], config: Self::Config) -> Result<(), Self::Error>;
}
/// OSPI driver.
pub struct Ospi<'d, T: Instance, Dma> {
_peri: PeripheralRef<'d, T>,
sck: Option<PeripheralRef<'d, AnyPin>>,
@ -37,6 +143,28 @@ pub struct Ospi<'d, T: Instance, Dma> {
config: Config,
}
impl Error for OspiError {}
impl<'d, T: Instance, Dma> ErrorType for Ospi<'d, T, Dma> {
type Error = OspiError;
}
impl<'d, T: Instance, Dma: OctoDma<T>> MultiSpi for Ospi<'d, T, Dma> {
type Config = TransferConfig;
async fn command(&mut self, config: Self::Config) -> Result<(), Self::Error> {
Ok(())
}
async fn read(&mut self, data: &mut [u8], config: Self::Config) -> Result<(), Self::Error> {
Ok(())
}
async fn write(&mut self, data: &mut [u8], config: Self::Config) -> Result<(), Self::Error> {
Ok(())
}
}
impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
/// Create new OSPI driver for a dualspi external chip
pub fn new_dualspi(
@ -54,11 +182,29 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
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);
// nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Down);
// 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);
#[cfg(octospi_v1)]
{
T::REGS.ccr().modify(|w| {
w.set_imode(vals::PhaseMode::TWOLINES);
w.set_admode(vals::PhaseMode::TWOLINES);
w.set_abmode(vals::PhaseMode::TWOLINES);
w.set_dmode(vals::PhaseMode::TWOLINES);
});
T::REGS.wccr().modify(|w| {
w.set_imode(vals::PhaseMode::TWOLINES);
w.set_admode(vals::PhaseMode::TWOLINES);
w.set_abmode(vals::PhaseMode::TWOLINES);
w.set_dmode(vals::PhaseMode::TWOLINES);
});
}
Self::new_inner(
peri,
Some(d0.map_into()),
@ -96,31 +242,18 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
into_ref!(peri, dma);
T::enable_and_reset();
T::REGS.sr().read().busy();
while T::REGS.sr().read().busy() {}
T::REGS.cr().modify(|w| {
w.set_en(true);
});
#[cfg(octospi_v1)]
{
T::REGS.ccr().modify(|w| {
w.set_imode(vals::PhaseMode::TWOLINES);
w.set_admode(vals::PhaseMode::TWOLINES);
w.set_abmode(vals::PhaseMode::TWOLINES);
w.set_dmode(vals::PhaseMode::TWOLINES);
});
T::REGS.wccr().modify(|w| {
w.set_imode(vals::PhaseMode::TWOLINES);
w.set_admode(vals::PhaseMode::TWOLINES);
w.set_abmode(vals::PhaseMode::TWOLINES);
w.set_dmode(vals::PhaseMode::TWOLINES);
});
}
//
// while T::REGS::sr().read().busy() {}
T::REGS.dcr1().modify(|w| {
w.set_devsize(23);
w.set_mtyp(vals::MemType::MACRONIX);
w.set_ckmode(false);
// w.se
});
Self {
_peri: peri,
@ -139,6 +272,51 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
config,
}
}
pub fn blocking_read(&mut self, transaction: TransferConfig) -> Result<(), ()> {
Ok(())
}
fn configure_command(&mut self, command: &TransferConfig) -> Result<(), ()> {
Ok(())
}
/// Poor attempt to read data from memory
pub fn receive(&mut self, buf: &mut [u8], intruction: u8, data_len: usize) -> Result<(), ()> {
T::REGS.cr().modify(|w| {
w.set_fmode(vals::FunctionalMode::INDIRECTREAD);
});
T::REGS.ccr().modify(|w| {
w.set_imode(vals::PhaseMode::ONELINE);
w.set_admode(vals::PhaseMode::NONE);
w.set_abmode(vals::PhaseMode::NONE);
w.set_dmode(vals::PhaseMode::ONELINE);
});
T::REGS.dlr().modify(|w| {
w.set_dl((data_len - 1) as u32);
});
// set instruction
T::REGS.ir().modify(|w| w.set_instruction(intruction as u32));
// read bytes
// for idx in 0..data_len {
// while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
// buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() };
// }
// wait for finish
while !T::REGS.sr().read().tcf() {}
let fifo_count = T::REGS.sr().read().flevel();
for idx in 0..(fifo_count as usize) {
buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() };
}
Ok(())
}
}
pub(crate) mod sealed {