diff options
| author | Karun <[email protected]> | 2024-02-05 21:23:03 -0500 |
|---|---|---|
| committer | Karun <[email protected]> | 2024-03-07 14:30:53 -0500 |
| commit | 9ed8d01b1102c574e23ffb4994a0b377fb762af2 (patch) | |
| tree | fe92032450c69cd9a837bf15ec4f008504e5d261 /embassy-stm32/src/ospi | |
| parent | f3609f2842d95bf1408e3bef108e0bd30f87f9d5 (diff) | |
Add transfer config, trait, functional initial configuration and read from memory
Diffstat (limited to 'embassy-stm32/src/ospi')
| -rw-r--r-- | embassy-stm32/src/ospi/mod.rs | 218 |
1 files changed, 198 insertions, 20 deletions
diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index 44824e42a..547de65d9 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs | |||
| @@ -3,12 +3,17 @@ | |||
| 3 | 3 | ||
| 4 | #![macro_use] | 4 | #![macro_use] |
| 5 | 5 | ||
| 6 | pub mod enums; | ||
| 7 | |||
| 8 | use core::ops::Add; | ||
| 6 | use core::ptr; | 9 | use core::ptr; |
| 7 | 10 | ||
| 8 | use embassy_embedded_hal::SetConfig; | 11 | use embassy_embedded_hal::SetConfig; |
| 9 | use embassy_futures::join::join; | 12 | use embassy_futures::join::join; |
| 10 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 13 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 14 | use embedded_hal_02::blocking::i2c::Operation; | ||
| 11 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 15 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 16 | use enums::*; | ||
| 12 | 17 | ||
| 13 | use crate::dma::{slice_ptr_parts, word, Transfer}; | 18 | use crate::dma::{slice_ptr_parts, word, Transfer}; |
| 14 | use crate::gpio::sealed::{AFType, Pin as _}; | 19 | use crate::gpio::sealed::{AFType, Pin as _}; |
| @@ -18,8 +23,109 @@ use crate::rcc::RccPeripheral; | |||
| 18 | use crate::time::Hertz; | 23 | use crate::time::Hertz; |
| 19 | use crate::{peripherals, Peripheral}; | 24 | use crate::{peripherals, Peripheral}; |
| 20 | 25 | ||
| 26 | /// OPSI driver config. | ||
| 21 | pub struct Config; | 27 | pub struct Config; |
| 22 | 28 | ||
| 29 | /// OSPI transfer configuration. | ||
| 30 | pub struct TransferConfig { | ||
| 31 | /// Instruction width (IMODE) | ||
| 32 | pub iwidth: OspiWidth, | ||
| 33 | /// Instruction Id | ||
| 34 | pub instruction: Option<u32>, | ||
| 35 | /// Number of Instruction Bytes | ||
| 36 | pub isize: AddressSize, | ||
| 37 | /// Instruction Double Transfer rate enable | ||
| 38 | pub idtr: bool, | ||
| 39 | |||
| 40 | /// Address width (ADMODE) | ||
| 41 | pub adwidth: OspiWidth, | ||
| 42 | /// Device memory address | ||
| 43 | pub address: Option<u32>, | ||
| 44 | /// Number of Address Bytes | ||
| 45 | pub adsize: AddressSize, | ||
| 46 | /// Address Double Transfer rate enable | ||
| 47 | pub addtr: bool, | ||
| 48 | |||
| 49 | /// Alternate bytes width (ABMODE) | ||
| 50 | pub abwidth: OspiWidth, | ||
| 51 | /// Alternate Bytes | ||
| 52 | pub alternate_bytes: Option<u32>, | ||
| 53 | /// Number of Alternate Bytes | ||
| 54 | pub absize: AddressSize, | ||
| 55 | /// Alternate Bytes Double Transfer rate enable | ||
| 56 | pub abdtr: bool, | ||
| 57 | |||
| 58 | /// Data width (DMODE) | ||
| 59 | pub dwidth: OspiWidth, | ||
| 60 | /// Length of data | ||
| 61 | pub data_len: Option<usize>, | ||
| 62 | /// Data buffer | ||
| 63 | pub ddtr: bool, | ||
| 64 | |||
| 65 | /// Number of dummy cycles (DCYC) | ||
| 66 | pub dummy: DummyCycles, | ||
| 67 | } | ||
| 68 | |||
| 69 | impl Default for TransferConfig { | ||
| 70 | fn default() -> Self { | ||
| 71 | Self { | ||
| 72 | iwidth: OspiWidth::NONE, | ||
| 73 | instruction: None, | ||
| 74 | isize: AddressSize::_8Bit, | ||
| 75 | idtr: false, | ||
| 76 | |||
| 77 | adwidth: OspiWidth::NONE, | ||
| 78 | address: None, | ||
| 79 | adsize: AddressSize::_8Bit, | ||
| 80 | addtr: false, | ||
| 81 | |||
| 82 | abwidth: OspiWidth::NONE, | ||
| 83 | alternate_bytes: None, | ||
| 84 | absize: AddressSize::_8Bit, | ||
| 85 | abdtr: false, | ||
| 86 | |||
| 87 | dwidth: OspiWidth::NONE, | ||
| 88 | data_len: None, | ||
| 89 | ddtr: false, | ||
| 90 | |||
| 91 | dummy: DummyCycles::_0, | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | pub enum OspiError { | ||
| 97 | Test, | ||
| 98 | } | ||
| 99 | |||
| 100 | pub trait Error {} | ||
| 101 | |||
| 102 | pub trait ErrorType { | ||
| 103 | type Error: Error; | ||
| 104 | } | ||
| 105 | |||
| 106 | impl<T: ErrorType + ?Sized> ErrorType for &mut T { | ||
| 107 | type Error = T::Error; | ||
| 108 | } | ||
| 109 | |||
| 110 | /// MultiSpi interface trait | ||
| 111 | pub trait MultiSpi: ErrorType { | ||
| 112 | /// Transaction configuration for specific multispi implementation | ||
| 113 | type Config; | ||
| 114 | |||
| 115 | /// Command function used for a configuration operation, when no user data is | ||
| 116 | /// supplied to or read from the target device. | ||
| 117 | async fn command(&mut self, config: Self::Config) -> Result<(), Self::Error>; | ||
| 118 | |||
| 119 | /// Read function used to read data from the target device following the supplied transaction | ||
| 120 | /// configuration. | ||
| 121 | async fn read(&mut self, data: &mut [u8], config: Self::Config) -> Result<(), Self::Error>; | ||
| 122 | |||
| 123 | /// Write function used to send data to the target device following the supplied transaction | ||
| 124 | /// configuration. | ||
| 125 | async fn write(&mut self, data: &mut [u8], config: Self::Config) -> Result<(), Self::Error>; | ||
| 126 | } | ||
| 127 | |||
| 128 | /// OSPI driver. | ||
| 23 | pub struct Ospi<'d, T: Instance, Dma> { | 129 | pub struct Ospi<'d, T: Instance, Dma> { |
| 24 | _peri: PeripheralRef<'d, T>, | 130 | _peri: PeripheralRef<'d, T>, |
| 25 | sck: Option<PeripheralRef<'d, AnyPin>>, | 131 | sck: Option<PeripheralRef<'d, AnyPin>>, |
| @@ -37,6 +143,28 @@ pub struct Ospi<'d, T: Instance, Dma> { | |||
| 37 | config: Config, | 143 | config: Config, |
| 38 | } | 144 | } |
| 39 | 145 | ||
| 146 | impl Error for OspiError {} | ||
| 147 | |||
| 148 | impl<'d, T: Instance, Dma> ErrorType for Ospi<'d, T, Dma> { | ||
| 149 | type Error = OspiError; | ||
| 150 | } | ||
| 151 | |||
| 152 | impl<'d, T: Instance, Dma: OctoDma<T>> MultiSpi for Ospi<'d, T, Dma> { | ||
| 153 | type Config = TransferConfig; | ||
| 154 | |||
| 155 | async fn command(&mut self, config: Self::Config) -> Result<(), Self::Error> { | ||
| 156 | Ok(()) | ||
| 157 | } | ||
| 158 | |||
| 159 | async fn read(&mut self, data: &mut [u8], config: Self::Config) -> Result<(), Self::Error> { | ||
| 160 | Ok(()) | ||
| 161 | } | ||
| 162 | |||
| 163 | async fn write(&mut self, data: &mut [u8], config: Self::Config) -> Result<(), Self::Error> { | ||
| 164 | Ok(()) | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 40 | impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { | 168 | impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { |
| 41 | /// Create new OSPI driver for a dualspi external chip | 169 | /// Create new OSPI driver for a dualspi external chip |
| 42 | pub fn new_dualspi( | 170 | pub fn new_dualspi( |
| @@ -54,11 +182,29 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { | |||
| 54 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 182 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 55 | nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); | 183 | nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); |
| 56 | nss.set_speed(crate::gpio::Speed::VeryHigh); | 184 | nss.set_speed(crate::gpio::Speed::VeryHigh); |
| 185 | // nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Down); | ||
| 186 | // nss.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 57 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); | 187 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); |
| 58 | d0.set_speed(crate::gpio::Speed::VeryHigh); | 188 | d0.set_speed(crate::gpio::Speed::VeryHigh); |
| 59 | d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); | 189 | d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); |
| 60 | d1.set_speed(crate::gpio::Speed::VeryHigh); | 190 | d1.set_speed(crate::gpio::Speed::VeryHigh); |
| 61 | 191 | ||
| 192 | #[cfg(octospi_v1)] | ||
| 193 | { | ||
| 194 | T::REGS.ccr().modify(|w| { | ||
| 195 | w.set_imode(vals::PhaseMode::TWOLINES); | ||
| 196 | w.set_admode(vals::PhaseMode::TWOLINES); | ||
| 197 | w.set_abmode(vals::PhaseMode::TWOLINES); | ||
| 198 | w.set_dmode(vals::PhaseMode::TWOLINES); | ||
| 199 | }); | ||
| 200 | T::REGS.wccr().modify(|w| { | ||
| 201 | w.set_imode(vals::PhaseMode::TWOLINES); | ||
| 202 | w.set_admode(vals::PhaseMode::TWOLINES); | ||
| 203 | w.set_abmode(vals::PhaseMode::TWOLINES); | ||
| 204 | w.set_dmode(vals::PhaseMode::TWOLINES); | ||
| 205 | }); | ||
| 206 | } | ||
| 207 | |||
| 62 | Self::new_inner( | 208 | Self::new_inner( |
| 63 | peri, | 209 | peri, |
| 64 | Some(d0.map_into()), | 210 | Some(d0.map_into()), |
| @@ -96,31 +242,18 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { | |||
| 96 | into_ref!(peri, dma); | 242 | into_ref!(peri, dma); |
| 97 | 243 | ||
| 98 | T::enable_and_reset(); | 244 | T::enable_and_reset(); |
| 99 | T::REGS.sr().read().busy(); | 245 | while T::REGS.sr().read().busy() {} |
| 100 | 246 | ||
| 101 | T::REGS.cr().modify(|w| { | 247 | T::REGS.cr().modify(|w| { |
| 102 | w.set_en(true); | 248 | w.set_en(true); |
| 103 | }); | 249 | }); |
| 104 | 250 | ||
| 105 | #[cfg(octospi_v1)] | 251 | T::REGS.dcr1().modify(|w| { |
| 106 | { | 252 | w.set_devsize(23); |
| 107 | T::REGS.ccr().modify(|w| { | 253 | w.set_mtyp(vals::MemType::MACRONIX); |
| 108 | w.set_imode(vals::PhaseMode::TWOLINES); | 254 | w.set_ckmode(false); |
| 109 | w.set_admode(vals::PhaseMode::TWOLINES); | 255 | // w.se |
| 110 | w.set_abmode(vals::PhaseMode::TWOLINES); | 256 | }); |
| 111 | w.set_dmode(vals::PhaseMode::TWOLINES); | ||
| 112 | }); | ||
| 113 | T::REGS.wccr().modify(|w| { | ||
| 114 | w.set_imode(vals::PhaseMode::TWOLINES); | ||
| 115 | w.set_admode(vals::PhaseMode::TWOLINES); | ||
| 116 | w.set_abmode(vals::PhaseMode::TWOLINES); | ||
| 117 | w.set_dmode(vals::PhaseMode::TWOLINES); | ||
| 118 | }); | ||
| 119 | } | ||
| 120 | |||
| 121 | // | ||
| 122 | |||
| 123 | // while T::REGS::sr().read().busy() {} | ||
| 124 | 257 | ||
| 125 | Self { | 258 | Self { |
| 126 | _peri: peri, | 259 | _peri: peri, |
| @@ -139,6 +272,51 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { | |||
| 139 | config, | 272 | config, |
| 140 | } | 273 | } |
| 141 | } | 274 | } |
| 275 | |||
| 276 | pub fn blocking_read(&mut self, transaction: TransferConfig) -> Result<(), ()> { | ||
| 277 | Ok(()) | ||
| 278 | } | ||
| 279 | |||
| 280 | fn configure_command(&mut self, command: &TransferConfig) -> Result<(), ()> { | ||
| 281 | Ok(()) | ||
| 282 | } | ||
| 283 | |||
| 284 | /// Poor attempt to read data from memory | ||
| 285 | pub fn receive(&mut self, buf: &mut [u8], intruction: u8, data_len: usize) -> Result<(), ()> { | ||
| 286 | T::REGS.cr().modify(|w| { | ||
| 287 | w.set_fmode(vals::FunctionalMode::INDIRECTREAD); | ||
| 288 | }); | ||
| 289 | |||
| 290 | T::REGS.ccr().modify(|w| { | ||
| 291 | w.set_imode(vals::PhaseMode::ONELINE); | ||
| 292 | w.set_admode(vals::PhaseMode::NONE); | ||
| 293 | w.set_abmode(vals::PhaseMode::NONE); | ||
| 294 | |||
| 295 | w.set_dmode(vals::PhaseMode::ONELINE); | ||
| 296 | }); | ||
| 297 | |||
| 298 | T::REGS.dlr().modify(|w| { | ||
| 299 | w.set_dl((data_len - 1) as u32); | ||
| 300 | }); | ||
| 301 | |||
| 302 | // set instruction | ||
| 303 | T::REGS.ir().modify(|w| w.set_instruction(intruction as u32)); | ||
| 304 | |||
| 305 | // read bytes | ||
| 306 | // for idx in 0..data_len { | ||
| 307 | // while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} | ||
| 308 | // buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; | ||
| 309 | // } | ||
| 310 | // wait for finish | ||
| 311 | while !T::REGS.sr().read().tcf() {} | ||
| 312 | |||
| 313 | let fifo_count = T::REGS.sr().read().flevel(); | ||
| 314 | for idx in 0..(fifo_count as usize) { | ||
| 315 | buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; | ||
| 316 | } | ||
| 317 | |||
| 318 | Ok(()) | ||
| 319 | } | ||
| 142 | } | 320 | } |
| 143 | 321 | ||
| 144 | pub(crate) mod sealed { | 322 | pub(crate) mod sealed { |
