aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/ospi/mod.rs91
1 files changed, 16 insertions, 75 deletions
diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs
index 59c73c24d..bcdffc266 100644
--- a/embassy-stm32/src/ospi/mod.rs
+++ b/embassy-stm32/src/ospi/mod.rs
@@ -113,8 +113,6 @@ pub struct TransferConfig {
113 113
114 /// Data width (DMODE) 114 /// Data width (DMODE)
115 pub dwidth: OspiWidth, 115 pub dwidth: OspiWidth,
116 /// Length of data
117 pub data_len: Option<usize>,
118 /// Data buffer 116 /// Data buffer
119 pub ddtr: bool, 117 pub ddtr: bool,
120 118
@@ -141,7 +139,6 @@ impl Default for TransferConfig {
141 abdtr: false, 139 abdtr: false,
142 140
143 dwidth: OspiWidth::NONE, 141 dwidth: OspiWidth::NONE,
144 data_len: None,
145 ddtr: false, 142 ddtr: false,
146 143
147 dummy: DummyCycles::_0, 144 dummy: DummyCycles::_0,
@@ -158,40 +155,6 @@ pub enum OspiError {
158 InvalidCommand, 155 InvalidCommand,
159} 156}
160 157
161/// MultiSpi interface trait
162pub trait MultiSpiBus<Word: Copy + 'static = u8>: embedded_hal_1::spi::ErrorType {
163 /// Transaction configuration for specific multispi implementation
164 type Config;
165
166 /// Command function used for a configuration operation, when no user data is
167 /// supplied to or read from the target device.
168 async fn command(&mut self, config: Self::Config) -> Result<(), Self::Error>;
169
170 /// Read function used to read data from the target device following the supplied transaction
171 /// configuration.
172 async fn read(&mut self, data: &mut [Word], config: Self::Config) -> Result<(), Self::Error>;
173
174 /// Write function used to send data to the target device following the supplied transaction
175 /// configuration.
176 async fn write(&mut self, data: &[Word], config: Self::Config) -> Result<(), Self::Error>;
177}
178
179impl<T: MultiSpiBus<Word> + ?Sized, Word: Copy + 'static> MultiSpiBus<Word> for &mut T {
180 type Config = T::Config;
181 #[inline]
182 async fn command(&mut self, config: Self::Config) -> Result<(), Self::Error> {
183 T::command(self, config).await
184 }
185
186 async fn read(&mut self, data: &mut [Word], config: Self::Config) -> Result<(), Self::Error> {
187 T::read(self, data, config).await
188 }
189
190 async fn write(&mut self, data: &[Word], config: Self::Config) -> Result<(), Self::Error> {
191 T::write(self, data, config).await
192 }
193}
194
195/// OSPI driver. 158/// OSPI driver.
196pub struct Ospi<'d, T: Instance, Dma> { 159pub struct Ospi<'d, T: Instance, Dma> {
197 _peri: PeripheralRef<'d, T>, 160 _peri: PeripheralRef<'d, T>,
@@ -211,35 +174,9 @@ pub struct Ospi<'d, T: Instance, Dma> {
211 width: OspiWidth, 174 width: OspiWidth,
212} 175}
213 176
214impl embedded_hal_1::spi::Error for OspiError {
215 fn kind(&self) -> ErrorKind {
216 ErrorKind::Other
217 }
218}
219
220impl<'d, T: Instance, Dma> embedded_hal_1::spi::ErrorType for Ospi<'d, T, Dma> {
221 type Error = OspiError;
222}
223
224impl<'d, T: Instance, Dma: OctoDma<T>, W: Word> MultiSpiBus<W> for Ospi<'d, T, Dma> {
225 type Config = TransferConfig;
226
227 async fn command(&mut self, config: Self::Config) -> Result<(), Self::Error> {
228 self.command(&config).await
229 }
230
231 async fn read(&mut self, data: &mut [W], config: Self::Config) -> Result<(), Self::Error> {
232 self.read(data, config).await
233 }
234
235 async fn write(&mut self, data: &[W], config: Self::Config) -> Result<(), Self::Error> {
236 self.write(data, config).await
237 }
238}
239
240impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { 177impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
241 /// Create new OSPI driver for a dualspi external chip 178 /// Create new OSPI driver for a single spi external chip
242 pub fn new_spi( 179 pub fn new_singlespi(
243 peri: impl Peripheral<P = T> + 'd, 180 peri: impl Peripheral<P = T> + 'd,
244 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 181 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
245 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 182 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
@@ -422,7 +359,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
422 ) 359 )
423 } 360 }
424 361
425 /// Create new OSPI driver for two quadspi external chips 362 /// Create new OSPI driver for octospi external chips
426 pub fn new_octospi( 363 pub fn new_octospi(
427 peri: impl Peripheral<P = T> + 'd, 364 peri: impl Peripheral<P = T> + 'd,
428 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 365 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
@@ -584,7 +521,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
584 } 521 }
585 522
586 // Function to configure the peripheral for the requested command 523 // Function to configure the peripheral for the requested command
587 fn configure_command(&mut self, command: &TransferConfig) -> Result<(), OspiError> { 524 fn configure_command(&mut self, command: &TransferConfig, data_len: Option<usize>) -> Result<(), OspiError> {
588 // Check that transaction doesn't use more than hardware initialized pins 525 // Check that transaction doesn't use more than hardware initialized pins
589 if <enums::OspiWidth as Into<u8>>::into(command.iwidth) > <enums::OspiWidth as Into<u8>>::into(self.width) 526 if <enums::OspiWidth as Into<u8>>::into(command.iwidth) > <enums::OspiWidth as Into<u8>>::into(self.width)
590 || <enums::OspiWidth as Into<u8>>::into(command.adwidth) > <enums::OspiWidth as Into<u8>>::into(self.width) 527 || <enums::OspiWidth as Into<u8>>::into(command.adwidth) > <enums::OspiWidth as Into<u8>>::into(self.width)
@@ -614,10 +551,14 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
614 }); 551 });
615 552
616 // Configure data 553 // Configure data
617 if let Some(data_length) = command.data_len { 554 if let Some(data_length) = data_len {
618 T::REGS.dlr().write(|v| { 555 T::REGS.dlr().write(|v| {
619 v.set_dl((data_length - 1) as u32); 556 v.set_dl((data_length - 1) as u32);
620 }) 557 })
558 } else {
559 T::REGS.dlr().write(|v| {
560 v.set_dl((0) as u32);
561 })
621 } 562 }
622 563
623 // Configure instruction/address/data modes 564 // Configure instruction/address/data modes
@@ -681,7 +622,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
681 while T::REGS.sr().read().busy() {} 622 while T::REGS.sr().read().busy() {}
682 623
683 // Need additional validation that command configuration doesn't have data set 624 // Need additional validation that command configuration doesn't have data set
684 self.configure_command(command)?; 625 self.configure_command(command, None)?;
685 626
686 // Transaction initiated by setting final configuration, i.e the instruction register 627 // Transaction initiated by setting final configuration, i.e the instruction register
687 while !T::REGS.sr().read().tcf() {} 628 while !T::REGS.sr().read().tcf() {}
@@ -702,7 +643,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
702 w.set_dmaen(false); 643 w.set_dmaen(false);
703 }); 644 });
704 645
705 self.configure_command(&transaction)?; 646 self.configure_command(&transaction, Some(buf.len()))?;
706 647
707 if let Some(len) = transaction.data_len { 648 if let Some(len) = transaction.data_len {
708 let current_address = T::REGS.ar().read().address(); 649 let current_address = T::REGS.ar().read().address();
@@ -733,7 +674,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
733 T::REGS.cr().modify(|w| { 674 T::REGS.cr().modify(|w| {
734 w.set_dmaen(false); 675 w.set_dmaen(false);
735 }); 676 });
736 self.configure_command(&transaction)?; 677 self.configure_command(&transaction, Some(buf.len()))?;
737 678
738 if let Some(len) = transaction.data_len { 679 if let Some(len) = transaction.data_len {
739 T::REGS 680 T::REGS
@@ -757,7 +698,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
757 where 698 where
758 Dma: OctoDma<T>, 699 Dma: OctoDma<T>,
759 { 700 {
760 self.configure_command(&transaction)?; 701 self.configure_command(&transaction, Some(buf.len()))?;
761 702
762 let current_address = T::REGS.ar().read().address(); 703 let current_address = T::REGS.ar().read().address();
763 let current_instruction = T::REGS.ir().read().instruction(); 704 let current_instruction = T::REGS.ir().read().instruction();
@@ -795,7 +736,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
795 where 736 where
796 Dma: OctoDma<T>, 737 Dma: OctoDma<T>,
797 { 738 {
798 self.configure_command(&transaction)?; 739 self.configure_command(&transaction, Some(buf.len()))?;
799 T::REGS 740 T::REGS
800 .cr() 741 .cr()
801 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); 742 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
@@ -825,7 +766,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
825 where 766 where
826 Dma: OctoDma<T>, 767 Dma: OctoDma<T>,
827 { 768 {
828 self.configure_command(&transaction)?; 769 self.configure_command(&transaction, Some(buf.len()))?;
829 770
830 let current_address = T::REGS.ar().read().address(); 771 let current_address = T::REGS.ar().read().address();
831 let current_instruction = T::REGS.ir().read().instruction(); 772 let current_instruction = T::REGS.ir().read().instruction();
@@ -863,7 +804,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
863 where 804 where
864 Dma: OctoDma<T>, 805 Dma: OctoDma<T>,
865 { 806 {
866 self.configure_command(&transaction)?; 807 self.configure_command(&transaction, Some(buf.len()))?;
867 T::REGS 808 T::REGS
868 .cr() 809 .cr()
869 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); 810 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));