Fix build errors
Add empty checks/peripheral busy waits
This commit is contained in:
parent
80aeea93fd
commit
4ea7dfce17
1 changed files with 62 additions and 31 deletions
|
@ -7,7 +7,6 @@ pub mod enums;
|
||||||
|
|
||||||
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};
|
||||||
use embedded_hal_1::spi::ErrorKind;
|
|
||||||
pub use enums::*;
|
pub use enums::*;
|
||||||
use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits};
|
use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits};
|
||||||
|
|
||||||
|
@ -144,11 +143,14 @@ impl Default for TransferConfig {
|
||||||
|
|
||||||
/// Error used for Octospi implementation
|
/// Error used for Octospi implementation
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum OspiError {
|
pub enum OspiError {
|
||||||
/// Peripheral configuration is invalid
|
/// Peripheral configuration is invalid
|
||||||
InvalidConfiguration,
|
InvalidConfiguration,
|
||||||
/// Operation configuration is invalid
|
/// Operation configuration is invalid
|
||||||
InvalidCommand,
|
InvalidCommand,
|
||||||
|
/// Size zero buffer passed to instruction
|
||||||
|
EmptyBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// OSPI driver.
|
/// OSPI driver.
|
||||||
|
@ -627,10 +629,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
|
|
||||||
/// Function used to control or configure the target device without data transfer
|
/// Function used to control or configure the target device without data transfer
|
||||||
pub async fn command(&mut self, command: &TransferConfig) -> Result<(), OspiError> {
|
pub async fn command(&mut self, command: &TransferConfig) -> Result<(), OspiError> {
|
||||||
// Prevent a transaction from being set with expected data transmission or reception
|
// Wait for peripheral to be free
|
||||||
if let Some(_) = command.data_len {
|
|
||||||
return Err(OspiError::InvalidCommand);
|
|
||||||
};
|
|
||||||
while T::REGS.sr().read().busy() {}
|
while T::REGS.sr().read().busy() {}
|
||||||
|
|
||||||
// Need additional validation that command configuration doesn't have data set
|
// Need additional validation that command configuration doesn't have data set
|
||||||
|
@ -647,6 +646,10 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
|
|
||||||
/// Blocking read with byte by byte data transfer
|
/// Blocking read with byte by byte data transfer
|
||||||
pub fn blocking_read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> {
|
pub fn blocking_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
|
// Wait for peripheral to be free
|
||||||
while T::REGS.sr().read().busy() {}
|
while T::REGS.sr().read().busy() {}
|
||||||
|
|
||||||
|
@ -657,22 +660,20 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
|
|
||||||
self.configure_command(&transaction, Some(buf.len()))?;
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
|
|
||||||
if let Some(len) = transaction.data_len {
|
let current_address = T::REGS.ar().read().address();
|
||||||
let current_address = T::REGS.ar().read().address();
|
let current_instruction = T::REGS.ir().read().instruction();
|
||||||
let current_instruction = T::REGS.ir().read().instruction();
|
|
||||||
|
|
||||||
// For a indirect read transaction, the transaction begins when the instruction/address is set
|
// 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));
|
T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
|
||||||
if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
|
if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
|
||||||
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
|
T::REGS.ir().write(|v| v.set_instruction(current_instruction));
|
||||||
} else {
|
} else {
|
||||||
T::REGS.ar().write(|v| v.set_address(current_address));
|
T::REGS.ar().write(|v| v.set_address(current_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx in 0..len {
|
for idx in 0..buf.len() {
|
||||||
while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
|
while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
|
||||||
buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut W).read_volatile() };
|
buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut W).read_volatile() };
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while !T::REGS.sr().read().tcf() {}
|
while !T::REGS.sr().read().tcf() {}
|
||||||
|
@ -683,20 +684,26 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
|
|
||||||
/// Blocking write with byte by byte data transfer
|
/// Blocking write with byte by byte data transfer
|
||||||
pub fn blocking_write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> {
|
pub fn blocking_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() {}
|
||||||
|
|
||||||
T::REGS.cr().modify(|w| {
|
T::REGS.cr().modify(|w| {
|
||||||
w.set_dmaen(false);
|
w.set_dmaen(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.configure_command(&transaction, Some(buf.len()))?;
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
|
|
||||||
if let Some(len) = transaction.data_len {
|
T::REGS
|
||||||
T::REGS
|
.cr()
|
||||||
.cr()
|
.modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
|
||||||
.modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
|
|
||||||
|
|
||||||
for idx in 0..len {
|
for idx in 0..buf.len() {
|
||||||
while !T::REGS.sr().read().ftf() {}
|
while !T::REGS.sr().read().ftf() {}
|
||||||
unsafe { (T::REGS.dr().as_ptr() as *mut W).write_volatile(buf[idx]) };
|
unsafe { (T::REGS.dr().as_ptr() as *mut W).write_volatile(buf[idx]) };
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while !T::REGS.sr().read().tcf() {}
|
while !T::REGS.sr().read().tcf() {}
|
||||||
|
@ -710,6 +717,13 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
where
|
where
|
||||||
Dma: OctoDma<T>,
|
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()))?;
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
|
|
||||||
let current_address = T::REGS.ar().read().address();
|
let current_address = T::REGS.ar().read().address();
|
||||||
|
@ -748,6 +762,13 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
where
|
where
|
||||||
Dma: OctoDma<T>,
|
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()))?;
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
T::REGS
|
T::REGS
|
||||||
.cr()
|
.cr()
|
||||||
|
@ -778,6 +799,13 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
where
|
where
|
||||||
Dma: OctoDma<T>,
|
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()))?;
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
|
|
||||||
let current_address = T::REGS.ar().read().address();
|
let current_address = T::REGS.ar().read().address();
|
||||||
|
@ -816,6 +844,13 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
where
|
where
|
||||||
Dma: OctoDma<T>,
|
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()))?;
|
self.configure_command(&transaction, Some(buf.len()))?;
|
||||||
T::REGS
|
T::REGS
|
||||||
.cr()
|
.cr()
|
||||||
|
@ -888,10 +923,6 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
|
||||||
w.set_prescaler(config.clock_prescaler);
|
w.set_prescaler(config.clock_prescaler);
|
||||||
});
|
});
|
||||||
|
|
||||||
T::REGS.cr().modify(|w| {
|
|
||||||
w.set_dmm(config.dual_quad);
|
|
||||||
});
|
|
||||||
|
|
||||||
T::REGS.tcr().modify(|w| {
|
T::REGS.tcr().modify(|w| {
|
||||||
w.set_sshift(match config.sample_shifting {
|
w.set_sshift(match config.sample_shifting {
|
||||||
true => vals::SampleShift::HALFCYCLE,
|
true => vals::SampleShift::HALFCYCLE,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue