aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorKarun <[email protected]>2024-04-03 16:36:02 -0400
committerKarun <[email protected]>2024-04-03 16:36:02 -0400
commit4ea7dfce176cf588fe0bc37efbca44e229bd6e0e (patch)
treeda82d5f9f07d76611936d8fd83b2b9d728a05b1d /embassy-stm32
parent80aeea93fd9d34b95441b6900e658e86b5b18b03 (diff)
Fix build errors
Add empty checks/peripheral busy waits
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/ospi/mod.rs93
1 files changed, 62 insertions, 31 deletions
diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs
index 7020cf9ad..4a89cd810 100644
--- a/embassy-stm32/src/ospi/mod.rs
+++ b/embassy-stm32/src/ospi/mod.rs
@@ -7,7 +7,6 @@ pub mod enums;
7 7
8use embassy_embedded_hal::{GetConfig, SetConfig}; 8use embassy_embedded_hal::{GetConfig, SetConfig};
9use embassy_hal_internal::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10use embedded_hal_1::spi::ErrorKind;
11pub use enums::*; 10pub use enums::*;
12use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits}; 11use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits};
13 12
@@ -144,11 +143,14 @@ impl Default for TransferConfig {
144 143
145/// Error used for Octospi implementation 144/// Error used for Octospi implementation
146#[derive(Debug)] 145#[derive(Debug)]
146#[cfg_attr(feature = "defmt", derive(defmt::Format))]
147pub enum OspiError { 147pub enum OspiError {
148 /// Peripheral configuration is invalid 148 /// Peripheral configuration is invalid
149 InvalidConfiguration, 149 InvalidConfiguration,
150 /// Operation configuration is invalid 150 /// Operation configuration is invalid
151 InvalidCommand, 151 InvalidCommand,
152 /// Size zero buffer passed to instruction
153 EmptyBuffer,
152} 154}
153 155
154/// OSPI driver. 156/// OSPI driver.
@@ -627,10 +629,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
627 629
628 /// Function used to control or configure the target device without data transfer 630 /// Function used to control or configure the target device without data transfer
629 pub async fn command(&mut self, command: &TransferConfig) -> Result<(), OspiError> { 631 pub async fn command(&mut self, command: &TransferConfig) -> Result<(), OspiError> {
630 // Prevent a transaction from being set with expected data transmission or reception 632 // Wait for peripheral to be free
631 if let Some(_) = command.data_len {
632 return Err(OspiError::InvalidCommand);
633 };
634 while T::REGS.sr().read().busy() {} 633 while T::REGS.sr().read().busy() {}
635 634
636 // Need additional validation that command configuration doesn't have data set 635 // Need additional validation that command configuration doesn't have data set
@@ -647,6 +646,10 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
647 646
648 /// Blocking read with byte by byte data transfer 647 /// Blocking read with byte by byte data transfer
649 pub fn blocking_read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> { 648 pub fn blocking_read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> {
649 if buf.is_empty() {
650 return Err(OspiError::EmptyBuffer);
651 }
652
650 // Wait for peripheral to be free 653 // Wait for peripheral to be free
651 while T::REGS.sr().read().busy() {} 654 while T::REGS.sr().read().busy() {}
652 655
@@ -657,22 +660,20 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
657 660
658 self.configure_command(&transaction, Some(buf.len()))?; 661 self.configure_command(&transaction, Some(buf.len()))?;
659 662
660 if let Some(len) = transaction.data_len { 663 let current_address = T::REGS.ar().read().address();
661 let current_address = T::REGS.ar().read().address(); 664 let current_instruction = T::REGS.ir().read().instruction();
662 let current_instruction = T::REGS.ir().read().instruction();
663 665
664 // For a indirect read transaction, the transaction begins when the instruction/address is set 666 // For a indirect read transaction, the transaction begins when the instruction/address is set
665 T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD)); 667 T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
666 if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE { 668 if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
667 T::REGS.ir().write(|v| v.set_instruction(current_instruction)); 669 T::REGS.ir().write(|v| v.set_instruction(current_instruction));
668 } else { 670 } else {
669 T::REGS.ar().write(|v| v.set_address(current_address)); 671 T::REGS.ar().write(|v| v.set_address(current_address));
670 } 672 }
671 673
672 for idx in 0..len { 674 for idx in 0..buf.len() {
673 while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} 675 while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
674 buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut W).read_volatile() }; 676 buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut W).read_volatile() };
675 }
676 } 677 }
677 678
678 while !T::REGS.sr().read().tcf() {} 679 while !T::REGS.sr().read().tcf() {}
@@ -683,20 +684,26 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
683 684
684 /// Blocking write with byte by byte data transfer 685 /// Blocking write with byte by byte data transfer
685 pub fn blocking_write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> { 686 pub fn blocking_write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> {
687 if buf.is_empty() {
688 return Err(OspiError::EmptyBuffer);
689 }
690
691 // Wait for peripheral to be free
692 while T::REGS.sr().read().busy() {}
693
686 T::REGS.cr().modify(|w| { 694 T::REGS.cr().modify(|w| {
687 w.set_dmaen(false); 695 w.set_dmaen(false);
688 }); 696 });
697
689 self.configure_command(&transaction, Some(buf.len()))?; 698 self.configure_command(&transaction, Some(buf.len()))?;
690 699
691 if let Some(len) = transaction.data_len { 700 T::REGS
692 T::REGS 701 .cr()
693 .cr() 702 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
694 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
695 703
696 for idx in 0..len { 704 for idx in 0..buf.len() {
697 while !T::REGS.sr().read().ftf() {} 705 while !T::REGS.sr().read().ftf() {}
698 unsafe { (T::REGS.dr().as_ptr() as *mut W).write_volatile(buf[idx]) }; 706 unsafe { (T::REGS.dr().as_ptr() as *mut W).write_volatile(buf[idx]) };
699 }
700 } 707 }
701 708
702 while !T::REGS.sr().read().tcf() {} 709 while !T::REGS.sr().read().tcf() {}
@@ -710,6 +717,13 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
710 where 717 where
711 Dma: OctoDma<T>, 718 Dma: OctoDma<T>,
712 { 719 {
720 if buf.is_empty() {
721 return Err(OspiError::EmptyBuffer);
722 }
723
724 // Wait for peripheral to be free
725 while T::REGS.sr().read().busy() {}
726
713 self.configure_command(&transaction, Some(buf.len()))?; 727 self.configure_command(&transaction, Some(buf.len()))?;
714 728
715 let current_address = T::REGS.ar().read().address(); 729 let current_address = T::REGS.ar().read().address();
@@ -748,6 +762,13 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
748 where 762 where
749 Dma: OctoDma<T>, 763 Dma: OctoDma<T>,
750 { 764 {
765 if buf.is_empty() {
766 return Err(OspiError::EmptyBuffer);
767 }
768
769 // Wait for peripheral to be free
770 while T::REGS.sr().read().busy() {}
771
751 self.configure_command(&transaction, Some(buf.len()))?; 772 self.configure_command(&transaction, Some(buf.len()))?;
752 T::REGS 773 T::REGS
753 .cr() 774 .cr()
@@ -778,6 +799,13 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
778 where 799 where
779 Dma: OctoDma<T>, 800 Dma: OctoDma<T>,
780 { 801 {
802 if buf.is_empty() {
803 return Err(OspiError::EmptyBuffer);
804 }
805
806 // Wait for peripheral to be free
807 while T::REGS.sr().read().busy() {}
808
781 self.configure_command(&transaction, Some(buf.len()))?; 809 self.configure_command(&transaction, Some(buf.len()))?;
782 810
783 let current_address = T::REGS.ar().read().address(); 811 let current_address = T::REGS.ar().read().address();
@@ -816,6 +844,13 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
816 where 844 where
817 Dma: OctoDma<T>, 845 Dma: OctoDma<T>,
818 { 846 {
847 if buf.is_empty() {
848 return Err(OspiError::EmptyBuffer);
849 }
850
851 // Wait for peripheral to be free
852 while T::REGS.sr().read().busy() {}
853
819 self.configure_command(&transaction, Some(buf.len()))?; 854 self.configure_command(&transaction, Some(buf.len()))?;
820 T::REGS 855 T::REGS
821 .cr() 856 .cr()
@@ -888,10 +923,6 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
888 w.set_prescaler(config.clock_prescaler); 923 w.set_prescaler(config.clock_prescaler);
889 }); 924 });
890 925
891 T::REGS.cr().modify(|w| {
892 w.set_dmm(config.dual_quad);
893 });
894
895 T::REGS.tcr().modify(|w| { 926 T::REGS.tcr().modify(|w| {
896 w.set_sshift(match config.sample_shifting { 927 w.set_sshift(match config.sample_shifting {
897 true => vals::SampleShift::HALFCYCLE, 928 true => vals::SampleShift::HALFCYCLE,