101
101
//! interface. Automatic polling or memory-mapped modes are not supported,
102
102
//! except for the OCTOSPI Hyperbus mode.
103
103
//!
104
- //! Using different operational modes (1-bit/2-bit/4-bit etc.) for different
105
- //! phases of a single transaction is not supported. It is possible to change
106
- //! operational mode between transactions by calling
107
- //! [`configure_mode`](#method.configure_mode).
104
+ //! It is possible to change operational mode between transactions by
105
+ //! calling [`configure_mode`](#method.configure_mode) or
106
+ //! [`configure_modes`](#method.configure_modes)
108
107
109
108
// Parts of the Quad and Octo SPI support are shared (this file), but they are
110
109
// different enough to require different initialisation routines and pin
@@ -117,7 +116,7 @@ mod qspi;
117
116
#[ cfg( any( feature = "rm0433" , feature = "rm0399" ) ) ]
118
117
pub use common:: {
119
118
Bank , BankError , BankSelect , Xspi as Qspi , XspiError as QspiError ,
120
- XspiMode as QspiMode , XspiWord as QspiWord ,
119
+ XspiMode as QspiMode , XspiModes as QspiModes , XspiWord as QspiWord ,
121
120
} ;
122
121
#[ cfg( any( feature = "rm0433" , feature = "rm0399" ) ) ]
123
122
pub use qspi:: QspiExt as XspiExt ;
@@ -128,7 +127,7 @@ mod octospi;
128
127
#[ cfg( any( feature = "rm0455" , feature = "rm0468" ) ) ]
129
128
pub use common:: {
130
129
Xspi as Octospi , XspiError as OctospiError , XspiMode as OctospiMode ,
131
- XspiWord as OctospiWord ,
130
+ XspiModes as OctospiModes , XspiWord as OctospiWord ,
132
131
} ;
133
132
#[ cfg( any( feature = "rm0455" , feature = "rm0468" ) ) ]
134
133
pub use octospi:: { Hyperbus , HyperbusConfig , OctospiExt as XspiExt } ;
@@ -176,6 +175,28 @@ mod common {
176
175
}
177
176
}
178
177
}
178
+ #[ derive( Debug , Copy , Clone ) ]
179
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
180
+ pub struct XspiModes {
181
+ /// IO lines used for the instruction phase.
182
+ pub instruction : XspiMode ,
183
+ /// IO lines used for the address phase.
184
+ pub address : XspiMode ,
185
+ /// IO lines used for the alternate byte phase.
186
+ pub alt_byte : XspiMode ,
187
+ /// IO lines used for the data phase.
188
+ pub data : XspiMode ,
189
+ }
190
+ impl XspiModes {
191
+ pub fn new ( mode : XspiMode ) -> Self {
192
+ Self {
193
+ instruction : mode,
194
+ address : mode,
195
+ alt_byte : mode,
196
+ data : mode,
197
+ }
198
+ }
199
+ }
179
200
/// Indicates an error with the XSPI peripheral.
180
201
#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
181
202
#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
@@ -308,7 +329,7 @@ mod common {
308
329
/// ```
309
330
#[ derive( Copy , Clone ) ]
310
331
pub struct Config {
311
- pub ( super ) mode : XspiMode ,
332
+ pub ( super ) modes : XspiModes ,
312
333
pub ( super ) frequency : Hertz ,
313
334
pub ( super ) dummy_cycles : u8 ,
314
335
pub ( super ) sampling_edge : SamplingEdge ,
@@ -323,21 +344,32 @@ mod common {
323
344
/// * Sample on falling edge
324
345
pub fn new ( frequency : Hertz ) -> Self {
325
346
Config {
326
- mode : XspiMode :: OneBit ,
347
+ modes : XspiModes :: new ( XspiMode :: OneBit ) ,
327
348
frequency,
328
349
dummy_cycles : 0 ,
329
350
sampling_edge : SamplingEdge :: Falling ,
330
351
fifo_threshold : 1 ,
331
352
}
332
353
}
333
354
334
- /// Specify the operating mode of the XSPI bus. Can be 1-bit, 2-bit or
335
- /// 4-bit for Quadspi; 1-bit, 2-bit, 4-bit or 8-bit for Octospi.
355
+ /// Specify the operating mode for all phases of the XSPI bus
356
+ /// operation. Can be 1-bit, 2-bit or 4-bit for Quadspi;
357
+ /// 1-bit, 2-bit, 4-bit or 8-bit for Octospi.
336
358
///
337
359
/// The operating mode can also be changed using the
338
360
/// [`configure_mode`](Xspi#method.configure_mode) method
339
- pub fn mode ( mut self , mode : XspiMode ) -> Self {
340
- self . mode = mode;
361
+ pub fn mode ( self , mode : XspiMode ) -> Self {
362
+ self . modes ( XspiModes :: new ( mode) )
363
+ }
364
+
365
+ /// Specify the operating mode separately for each phase of
366
+ /// the XSPI bus operation. Can be 1-bit, 2-bit or 4-bit for
367
+ /// Quadspi; 1-bit, 2-bit, 4-bit or 8-bit for Octospi.
368
+ ///
369
+ /// The operating modes can also be changed using the
370
+ /// [`configure_modes`](Xspi#method.configure_modes) method
371
+ pub fn modes ( mut self , modes : XspiModes ) -> Self {
372
+ self . modes = modes;
341
373
self
342
374
}
343
375
@@ -406,10 +438,10 @@ mod common {
406
438
pub struct Xspi < XSPI > {
407
439
pub ( super ) rb : XSPI ,
408
440
409
- /// We store the current mode here because for extended transactions
441
+ /// We store the current modes here because for extended transactions
410
442
/// various phases may be removed. Therefore we need to restore them
411
443
/// after each transaction.
412
- pub ( super ) mode : XspiMode ,
444
+ pub ( super ) modes : XspiModes ,
413
445
}
414
446
415
447
#[ cfg( any( feature = "rm0433" , feature = "rm0399" ) ) ]
@@ -514,17 +546,29 @@ mod common {
514
546
}
515
547
}
516
548
517
- /// Configure the operational mode (number of bits) of the XSPI
518
- /// interface .
549
+ /// Configure the common mode (number of bits) for all phases of the XSPI
550
+ /// operation .
519
551
///
520
552
/// # Args
521
- /// * `mode` - The newly desired mode of the interface .
553
+ /// * `mode` - The newly desired mode for the operation .
522
554
///
523
555
/// # Errors
524
556
/// Returns XspiError::Busy if an operation is ongoing
525
557
pub fn configure_mode( & mut self , mode: XspiMode ) -> Result <( ) , XspiError > {
558
+ self . configure_modes( XspiModes :: new( mode) )
559
+ }
560
+
561
+ /// Configure the operational mode (number of bits), separately for each phase
562
+ /// of the XSPI interface.
563
+ ///
564
+ /// # Args
565
+ /// * `modes` - The newly desired modes for each phase of the operation.
566
+ ///
567
+ /// # Errors
568
+ /// Returns XspiError::Busy if an operation is ongoing
569
+ pub fn configure_modes( & mut self , modes: XspiModes ) -> Result <( ) , XspiError > {
526
570
self . is_busy( ) ?;
527
- self . mode = mode ;
571
+ self . modes = modes ;
528
572
self . set_mode_address_data_only( ) ;
529
573
530
574
Ok ( ( ) )
@@ -537,13 +581,13 @@ mod common {
537
581
w. imode( ) // NO instruction phase
538
582
. bits( 0 )
539
583
. admode( ) // address phase
540
- . bits( self . mode . reg_value( ) )
584
+ . bits( self . modes . address . reg_value( ) )
541
585
. adsize( )
542
586
. bits( 0 ) // 8-bit address
543
587
. abmode( ) // NO alternate-bytes phase
544
588
. bits( 0 )
545
589
. dmode( ) // data phase
546
- . bits( self . mode . reg_value( ) )
590
+ . bits( self . modes . data . reg_value( ) )
547
591
} ) ;
548
592
}
549
593
@@ -560,11 +604,10 @@ mod common {
560
604
alternate_bytes: XspiWord , dummy_cycles: u8 , data: bool , read: bool ) {
561
605
562
606
let fmode = if read { 0b01 } else { 0b00 } ;
563
- let mode = self . mode. reg_value( ) ;
564
- let imode = if instruction != XspiWord :: None { mode } else { 0 } ;
565
- let admode = if address != XspiWord :: None { mode } else { 0 } ;
566
- let abmode = if alternate_bytes != XspiWord :: None { mode } else { 0 } ;
567
- let dmode = if data { mode } else { 0 } ;
607
+ let imode = if instruction != XspiWord :: None { self . modes. instruction. reg_value( ) } else { 0 } ;
608
+ let admode = if address != XspiWord :: None { self . modes. address. reg_value( ) } else { 0 } ;
609
+ let abmode = if alternate_bytes != XspiWord :: None { self . modes. alt_byte. reg_value( ) } else { 0 } ;
610
+ let dmode = if data { self . modes. data. reg_value( ) } else { 0 } ;
568
611
569
612
//writing to ccr will trigger the start of a transaction if there is no address or
570
613
//data rm0433 pg 894, so we do it all in one go
0 commit comments