aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarun <[email protected]>2024-02-05 21:23:03 -0500
committerKarun <[email protected]>2024-03-07 14:30:53 -0500
commit9ed8d01b1102c574e23ffb4994a0b377fb762af2 (patch)
treefe92032450c69cd9a837bf15ec4f008504e5d261
parentf3609f2842d95bf1408e3bef108e0bd30f87f9d5 (diff)
Add transfer config, trait, functional initial configuration and read from memory
-rw-r--r--embassy-stm32/src/ospi/mod.rs218
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
6pub mod enums;
7
8use core::ops::Add;
6use core::ptr; 9use core::ptr;
7 10
8use embassy_embedded_hal::SetConfig; 11use embassy_embedded_hal::SetConfig;
9use embassy_futures::join::join; 12use embassy_futures::join::join;
10use embassy_hal_internal::{into_ref, PeripheralRef}; 13use embassy_hal_internal::{into_ref, PeripheralRef};
14use embedded_hal_02::blocking::i2c::Operation;
11pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 15pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
16use enums::*;
12 17
13use crate::dma::{slice_ptr_parts, word, Transfer}; 18use crate::dma::{slice_ptr_parts, word, Transfer};
14use crate::gpio::sealed::{AFType, Pin as _}; 19use crate::gpio::sealed::{AFType, Pin as _};
@@ -18,8 +23,109 @@ use crate::rcc::RccPeripheral;
18use crate::time::Hertz; 23use crate::time::Hertz;
19use crate::{peripherals, Peripheral}; 24use crate::{peripherals, Peripheral};
20 25
26/// OPSI driver config.
21pub struct Config; 27pub struct Config;
22 28
29/// OSPI transfer configuration.
30pub 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
69impl 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
96pub enum OspiError {
97 Test,
98}
99
100pub trait Error {}
101
102pub trait ErrorType {
103 type Error: Error;
104}
105
106impl<T: ErrorType + ?Sized> ErrorType for &mut T {
107 type Error = T::Error;
108}
109
110/// MultiSpi interface trait
111pub 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.
23pub struct Ospi<'d, T: Instance, Dma> { 129pub 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
146impl Error for OspiError {}
147
148impl<'d, T: Instance, Dma> ErrorType for Ospi<'d, T, Dma> {
149 type Error = OspiError;
150}
151
152impl<'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
40impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { 168impl<'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
144pub(crate) mod sealed { 322pub(crate) mod sealed {