@@ -109,10 +109,11 @@ pins_impl!(
109
109
( MISO , SCK , MOSI ) , ( Miso , Sck , Mosi ) , ( _Miso, _Sck, _Mosi) ;
110
110
) ;
111
111
112
- pub struct Spi < SPI , REMAP , PINS > {
112
+ pub struct Spi < SPI , REMAP , PINS , FRAMESIZE > {
113
113
spi : SPI ,
114
114
pins : PINS ,
115
115
_remap : PhantomData < REMAP > ,
116
+ _framesize : PhantomData < FRAMESIZE > ,
116
117
}
117
118
118
119
/// A filler type for when the SCK pin is unnecessary
@@ -147,9 +148,9 @@ remap!(Spi3NoRemap, SPI3, false, PB3, PB4, PB5);
147
148
#[ cfg( feature = "connectivity" ) ]
148
149
remap ! ( Spi3Remap , SPI3 , true , PC10 , PC11 , PC12 ) ;
149
150
150
- impl < REMAP , PINS > Spi < SPI1 , REMAP , PINS > {
151
+ impl < REMAP , PINS > Spi < SPI1 , REMAP , PINS , u8 > {
151
152
/**
152
- Constructs an SPI instance using SPI1.
153
+ Constructs an SPI instance using SPI1 in 8bit dataframe mode .
153
154
154
155
The pin parameter tuple (sck, miso, mosi) should be `(PA5, PA6, PA7)` or `(PB3, PB4, PB5)` configured as `(Alternate<PushPull>, Input<Floating>, Alternate<PushPull>)`.
155
156
@@ -170,13 +171,13 @@ impl<REMAP, PINS> Spi<SPI1, REMAP, PINS> {
170
171
PINS : Pins < REMAP , POS > ,
171
172
{
172
173
mapr. modify_mapr ( |_, w| w. spi1_remap ( ) . bit ( REMAP :: REMAP ) ) ;
173
- Spi :: < SPI1 , _ , _ > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
174
+ Spi :: < SPI1 , _ , _ , u8 > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
174
175
}
175
176
}
176
177
177
- impl < REMAP , PINS > Spi < SPI2 , REMAP , PINS > {
178
+ impl < REMAP , PINS > Spi < SPI2 , REMAP , PINS , u8 > {
178
179
/**
179
- Constructs an SPI instance using SPI2.
180
+ Constructs an SPI instance using SPI2 in 8bit dataframe mode .
180
181
181
182
The pin parameter tuple (sck, miso, mosi) should be `(PB13, PB14, PB15)` configured as `(Alternate<PushPull>, Input<Floating>, Alternate<PushPull>)`.
182
183
@@ -195,14 +196,14 @@ impl<REMAP, PINS> Spi<SPI2, REMAP, PINS> {
195
196
REMAP : Remap < Periph = SPI2 > ,
196
197
PINS : Pins < REMAP , POS > ,
197
198
{
198
- Spi :: < SPI2 , _ , _ > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
199
+ Spi :: < SPI2 , _ , _ , u8 > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
199
200
}
200
201
}
201
202
202
203
#[ cfg( any( feature = "high" , feature = "connectivity" ) ) ]
203
- impl < REMAP , PINS > Spi < SPI3 , REMAP , PINS > {
204
+ impl < REMAP , PINS > Spi < SPI3 , REMAP , PINS , u8 > {
204
205
/**
205
- Constructs an SPI instance using SPI3.
206
+ Constructs an SPI instance using SPI3 in 8bit dataframe mode .
206
207
207
208
The pin parameter tuple (sck, miso, mosi) should be `(PB3, PB4, PB5)` or `(PC10, PC11, PC12)` configured as `(Alternate<PushPull>, Input<Floating>, Alternate<PushPull>)`.
208
209
@@ -221,13 +222,94 @@ impl<REMAP, PINS> Spi<SPI3, REMAP, PINS> {
221
222
REMAP : Remap < Periph = SPI3 > ,
222
223
PINS : Pins < REMAP , POS > ,
223
224
{
224
- Spi :: < SPI3 , _ , _ > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
225
+ Spi :: < SPI3 , _ , _ , u8 > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
225
226
}
226
227
}
227
228
228
229
pub type SpiRegisterBlock = crate :: pac:: spi1:: RegisterBlock ;
229
230
230
- impl < SPI , REMAP , PINS > Spi < SPI , REMAP , PINS >
231
+ pub trait SpiReadWrite < T > {
232
+ fn read_data_reg ( & mut self ) -> T ;
233
+ fn write_data_reg ( & mut self , data : T ) ;
234
+ fn spi_write ( & mut self , words : & [ T ] ) -> Result < ( ) , Error > ;
235
+ }
236
+
237
+ impl < SPI , REMAP , PINS , FrameSize > SpiReadWrite < FrameSize > for Spi < SPI , REMAP , PINS , FrameSize >
238
+ where
239
+ SPI : Deref < Target = SpiRegisterBlock > ,
240
+ FrameSize : Copy ,
241
+ {
242
+ fn read_data_reg ( & mut self ) -> FrameSize {
243
+ // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
244
+ // reading a half-word)
245
+ return unsafe { ptr:: read_volatile ( & self . spi . dr as * const _ as * const FrameSize ) } ;
246
+ }
247
+
248
+ fn write_data_reg ( & mut self , data : FrameSize ) {
249
+ // NOTE(write_volatile) see note above
250
+ unsafe { ptr:: write_volatile ( & self . spi . dr as * const _ as * mut FrameSize , data) }
251
+ }
252
+
253
+ // Implement write as per the "Transmit only procedure" page 712
254
+ // of RM0008 Rev 20. This is more than twice as fast as the
255
+ // default Write<> implementation (which reads and drops each
256
+ // received value)
257
+ fn spi_write ( & mut self , words : & [ FrameSize ] ) -> Result < ( ) , Error > {
258
+ // Write each word when the tx buffer is empty
259
+ for word in words {
260
+ loop {
261
+ let sr = self . spi . sr . read ( ) ;
262
+ if sr. txe ( ) . bit_is_set ( ) {
263
+ // NOTE(write_volatile) see note above
264
+ // unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, *word) }
265
+ self . write_data_reg ( * word) ;
266
+ if sr. modf ( ) . bit_is_set ( ) {
267
+ return Err ( Error :: ModeFault ) ;
268
+ }
269
+ break ;
270
+ }
271
+ }
272
+ }
273
+ // Wait for final TXE
274
+ loop {
275
+ let sr = self . spi . sr . read ( ) ;
276
+ if sr. txe ( ) . bit_is_set ( ) {
277
+ break ;
278
+ }
279
+ }
280
+ // Wait for final !BSY
281
+ loop {
282
+ let sr = self . spi . sr . read ( ) ;
283
+ if !sr. bsy ( ) . bit_is_set ( ) {
284
+ break ;
285
+ }
286
+ }
287
+ // Clear OVR set due to dropped received values
288
+ // NOTE(read_volatile) see note above
289
+ // unsafe {
290
+ // let _ = ptr::read_volatile(&self.spi.dr as *const _ as *const u8);
291
+ // }
292
+ let _ = self . read_data_reg ( ) ;
293
+ let _ = self . spi . sr . read ( ) ;
294
+ Ok ( ( ) )
295
+ }
296
+ }
297
+
298
+ impl < SPI , REMAP , PINS , FrameSize > Spi < SPI , REMAP , PINS , FrameSize >
299
+ where
300
+ SPI : Deref < Target = SpiRegisterBlock > ,
301
+ FrameSize : Copy ,
302
+ {
303
+ #[ deprecated( since = "0.6.0" , note = "Please use release instead" ) ]
304
+ pub fn free ( self ) -> ( SPI , PINS ) {
305
+ self . release ( )
306
+ }
307
+ pub fn release ( self ) -> ( SPI , PINS ) {
308
+ ( self . spi , self . pins )
309
+ }
310
+ }
311
+
312
+ impl < SPI , REMAP , PINS > Spi < SPI , REMAP , PINS , u8 >
231
313
where
232
314
SPI : Deref < Target = SpiRegisterBlock > + Enable + Reset ,
233
315
SPI :: Bus : GetBusFreq ,
@@ -300,25 +382,50 @@ where
300
382
spi,
301
383
pins,
302
384
_remap : PhantomData ,
385
+ _framesize : PhantomData ,
303
386
}
304
387
}
305
-
306
- #[ deprecated( since = "0.6.0" , note = "Please use release instead" ) ]
307
- pub fn free ( self ) -> ( SPI , PINS ) {
308
- self . release ( )
388
+ /// Converts from 8bit dataframe to 16bit.
389
+ pub fn frame_size_16bit ( self ) -> Spi < SPI , REMAP , PINS , u16 > {
390
+ self . spi . cr1 . modify ( |_, w| w. spe ( ) . clear_bit ( ) ) ;
391
+ self . spi . cr1 . modify ( |_, w| w. dff ( ) . set_bit ( ) ) ;
392
+ self . spi . cr1 . modify ( |_, w| w. spe ( ) . set_bit ( ) ) ;
393
+ Spi {
394
+ spi : self . spi ,
395
+ pins : self . pins ,
396
+ _remap : PhantomData ,
397
+ _framesize : PhantomData ,
398
+ }
309
399
}
310
- pub fn release ( self ) -> ( SPI , PINS ) {
311
- ( self . spi , self . pins )
400
+ }
401
+
402
+ impl < SPI , REMAP , PINS > Spi < SPI , REMAP , PINS , u16 >
403
+ where
404
+ SPI : Deref < Target = SpiRegisterBlock > ,
405
+ {
406
+ /// Converts from 16bit dataframe to 8bit.
407
+ pub fn frame_size_8bit ( self ) -> Spi < SPI , REMAP , PINS , u8 > {
408
+ self . spi . cr1 . modify ( |_, w| w. spe ( ) . clear_bit ( ) ) ;
409
+ self . spi . cr1 . modify ( |_, w| w. dff ( ) . clear_bit ( ) ) ;
410
+ self . spi . cr1 . modify ( |_, w| w. spe ( ) . set_bit ( ) ) ;
411
+ Spi {
412
+ spi : self . spi ,
413
+ pins : self . pins ,
414
+ _remap : PhantomData ,
415
+ _framesize : PhantomData ,
416
+ }
312
417
}
313
418
}
314
419
315
- impl < SPI , REMAP , PINS > crate :: hal:: spi:: FullDuplex < u8 > for Spi < SPI , REMAP , PINS >
420
+ impl < SPI , REMAP , PINS , FrameSize > crate :: hal:: spi:: FullDuplex < FrameSize >
421
+ for Spi < SPI , REMAP , PINS , FrameSize >
316
422
where
317
423
SPI : Deref < Target = SpiRegisterBlock > ,
424
+ FrameSize : Copy ,
318
425
{
319
426
type Error = Error ;
320
427
321
- fn read ( & mut self ) -> nb:: Result < u8 , Error > {
428
+ fn read ( & mut self ) -> nb:: Result < FrameSize , Error > {
322
429
let sr = self . spi . sr . read ( ) ;
323
430
324
431
Err ( if sr. ovr ( ) . bit_is_set ( ) {
@@ -330,13 +437,13 @@ where
330
437
} else if sr. rxne ( ) . bit_is_set ( ) {
331
438
// NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
332
439
// reading a half-word)
333
- return Ok ( unsafe { ptr :: read_volatile ( & self . spi . dr as * const _ as * const u8 ) } ) ;
440
+ return Ok ( self . read_data_reg ( ) ) ;
334
441
} else {
335
442
nb:: Error :: WouldBlock
336
443
} )
337
444
}
338
445
339
- fn send ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Error > {
446
+ fn send ( & mut self , data : FrameSize ) -> nb:: Result < ( ) , Error > {
340
447
let sr = self . spi . sr . read ( ) ;
341
448
342
449
Err ( if sr. ovr ( ) . bit_is_set ( ) {
@@ -347,20 +454,23 @@ where
347
454
nb:: Error :: Other ( Error :: Crc )
348
455
} else if sr. txe ( ) . bit_is_set ( ) {
349
456
// NOTE(write_volatile) see note above
350
- unsafe { ptr :: write_volatile ( & self . spi . dr as * const _ as * mut u8 , byte ) }
457
+ self . write_data_reg ( data ) ;
351
458
return Ok ( ( ) ) ;
352
459
} else {
353
460
nb:: Error :: WouldBlock
354
461
} )
355
462
}
356
463
}
357
464
358
- impl < SPI , REMAP , PINS > crate :: hal:: blocking:: spi:: transfer:: Default < u8 > for Spi < SPI , REMAP , PINS > where
359
- SPI : Deref < Target = SpiRegisterBlock >
465
+ impl < SPI , REMAP , PINS , FrameSize > crate :: hal:: blocking:: spi:: transfer:: Default < FrameSize >
466
+ for Spi < SPI , REMAP , PINS , FrameSize >
467
+ where
468
+ SPI : Deref < Target = SpiRegisterBlock > ,
469
+ FrameSize : Copy ,
360
470
{
361
471
}
362
472
363
- impl < SPI , REMAP , PINS > crate :: hal:: blocking:: spi:: Write < u8 > for Spi < SPI , REMAP , PINS >
473
+ impl < SPI , REMAP , PINS > crate :: hal:: blocking:: spi:: Write < u8 > for Spi < SPI , REMAP , PINS , u8 >
364
474
where
365
475
SPI : Deref < Target = SpiRegisterBlock > ,
366
476
{
@@ -371,48 +481,25 @@ where
371
481
// default Write<> implementation (which reads and drops each
372
482
// received value)
373
483
fn write ( & mut self , words : & [ u8 ] ) -> Result < ( ) , Error > {
374
- // Write each word when the tx buffer is empty
375
- for word in words {
376
- loop {
377
- let sr = self . spi . sr . read ( ) ;
378
- if sr. txe ( ) . bit_is_set ( ) {
379
- // NOTE(write_volatile) see note above
380
- unsafe { ptr:: write_volatile ( & self . spi . dr as * const _ as * mut u8 , * word) }
381
- if sr. modf ( ) . bit_is_set ( ) {
382
- return Err ( Error :: ModeFault ) ;
383
- }
384
- break ;
385
- }
386
- }
387
- }
388
- // Wait for final TXE
389
- loop {
390
- let sr = self . spi . sr . read ( ) ;
391
- if sr. txe ( ) . bit_is_set ( ) {
392
- break ;
393
- }
394
- }
395
- // Wait for final !BSY
396
- loop {
397
- let sr = self . spi . sr . read ( ) ;
398
- if !sr. bsy ( ) . bit_is_set ( ) {
399
- break ;
400
- }
401
- }
402
- // Clear OVR set due to dropped received values
403
- // NOTE(read_volatile) see note above
404
- unsafe {
405
- let _ = ptr:: read_volatile ( & self . spi . dr as * const _ as * const u8 ) ;
406
- }
407
- let _ = self . spi . sr . read ( ) ;
408
- Ok ( ( ) )
484
+ self . spi_write ( words)
485
+ }
486
+ }
487
+
488
+ impl < SPI , REMAP , PINS > crate :: hal:: blocking:: spi:: Write < u16 > for Spi < SPI , REMAP , PINS , u16 >
489
+ where
490
+ SPI : Deref < Target = SpiRegisterBlock > ,
491
+ {
492
+ type Error = Error ;
493
+
494
+ fn write ( & mut self , words : & [ u16 ] ) -> Result < ( ) , Error > {
495
+ self . spi_write ( words)
409
496
}
410
497
}
411
498
412
499
// DMA
413
500
414
501
pub struct SpiPayload < SPI , REMAP , PINS > {
415
- spi : Spi < SPI , REMAP , PINS > ,
502
+ spi : Spi < SPI , REMAP , PINS , u8 > ,
416
503
}
417
504
418
505
pub type SpiTxDma < SPI , REMAP , PINS , CHANNEL > = TxDma < SpiPayload < SPI , REMAP , PINS > , CHANNEL > ;
@@ -424,7 +511,7 @@ macro_rules! spi_dma {
424
511
type ReceivedWord = u8 ;
425
512
}
426
513
427
- impl <REMAP , PINS > Spi <$SPIi, REMAP , PINS > {
514
+ impl <REMAP , PINS > Spi <$SPIi, REMAP , PINS , u8 > {
428
515
pub fn with_tx_dma( self , channel: $TCi) -> SpiTxDma <$SPIi, REMAP , PINS , $TCi> {
429
516
let payload = SpiPayload { spi: self } ;
430
517
SpiTxDma { payload, channel }
0 commit comments