diff options
| author | Karun <[email protected]> | 2024-04-03 16:36:02 -0400 |
|---|---|---|
| committer | Karun <[email protected]> | 2024-04-03 16:36:02 -0400 |
| commit | 4ea7dfce176cf588fe0bc37efbca44e229bd6e0e (patch) | |
| tree | da82d5f9f07d76611936d8fd83b2b9d728a05b1d /embassy-stm32 | |
| parent | 80aeea93fd9d34b95441b6900e658e86b5b18b03 (diff) | |
Fix build errors
Add empty checks/peripheral busy waits
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/ospi/mod.rs | 93 |
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 | ||
| 8 | use embassy_embedded_hal::{GetConfig, SetConfig}; | 8 | use embassy_embedded_hal::{GetConfig, SetConfig}; |
| 9 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 9 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 10 | use embedded_hal_1::spi::ErrorKind; | ||
| 11 | pub use enums::*; | 10 | pub use enums::*; |
| 12 | use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits}; | 11 | use 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))] | ||
| 147 | pub enum OspiError { | 147 | pub 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, |
