@@ -109,10 +109,11 @@ pins_impl!(
109109 ( MISO , SCK , MOSI ) , ( Miso , Sck , Mosi ) , ( _Miso, _Sck, _Mosi) ;
110110) ;
111111
112- pub struct Spi < SPI , REMAP , PINS > {
112+ pub struct Spi < SPI , REMAP , PINS , FRAMESIZE > {
113113 spi : SPI ,
114114 pins : PINS ,
115115 _remap : PhantomData < REMAP > ,
116+ _framesize : PhantomData < FRAMESIZE > ,
116117}
117118
118119/// A filler type for when the SCK pin is unnecessary
@@ -147,9 +148,9 @@ remap!(Spi3NoRemap, SPI3, false, PB3, PB4, PB5);
147148#[ cfg( feature = "connectivity" ) ]
148149remap ! ( Spi3Remap , SPI3 , true , PC10 , PC11 , PC12 ) ;
149150
150- impl < REMAP , PINS > Spi < SPI1 , REMAP , PINS > {
151+ impl < REMAP , PINS > Spi < SPI1 , REMAP , PINS , u8 > {
151152 /**
152- Constructs an SPI instance using SPI1.
153+ Constructs an SPI instance using SPI1 in 8bit dataframe mode .
153154
154155 The pin parameter tuple (sck, miso, mosi) should be `(PA5, PA6, PA7)` or `(PB3, PB4, PB5)` configured as `(Alternate<PushPull>, Input<Floating>, Alternate<PushPull>)`.
155156
@@ -170,13 +171,13 @@ impl<REMAP, PINS> Spi<SPI1, REMAP, PINS> {
170171 PINS : Pins < REMAP , POS > ,
171172 {
172173 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)
174175 }
175176}
176177
177- impl < REMAP , PINS > Spi < SPI2 , REMAP , PINS > {
178+ impl < REMAP , PINS > Spi < SPI2 , REMAP , PINS , u8 > {
178179 /**
179- Constructs an SPI instance using SPI2.
180+ Constructs an SPI instance using SPI2 in 8bit dataframe mode .
180181
181182 The pin parameter tuple (sck, miso, mosi) should be `(PB13, PB14, PB15)` configured as `(Alternate<PushPull>, Input<Floating>, Alternate<PushPull>)`.
182183
@@ -195,14 +196,14 @@ impl<REMAP, PINS> Spi<SPI2, REMAP, PINS> {
195196 REMAP : Remap < Periph = SPI2 > ,
196197 PINS : Pins < REMAP , POS > ,
197198 {
198- Spi :: < SPI2 , _ , _ > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
199+ Spi :: < SPI2 , _ , _ , u8 > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
199200 }
200201}
201202
202203#[ cfg( any( feature = "high" , feature = "connectivity" ) ) ]
203- impl < REMAP , PINS > Spi < SPI3 , REMAP , PINS > {
204+ impl < REMAP , PINS > Spi < SPI3 , REMAP , PINS , u8 > {
204205 /**
205- Constructs an SPI instance using SPI3.
206+ Constructs an SPI instance using SPI3 in 8bit dataframe mode .
206207
207208 The pin parameter tuple (sck, miso, mosi) should be `(PB3, PB4, PB5)` or `(PC10, PC11, PC12)` configured as `(Alternate<PushPull>, Input<Floating>, Alternate<PushPull>)`.
208209
@@ -221,13 +222,94 @@ impl<REMAP, PINS> Spi<SPI3, REMAP, PINS> {
221222 REMAP : Remap < Periph = SPI3 > ,
222223 PINS : Pins < REMAP , POS > ,
223224 {
224- Spi :: < SPI3 , _ , _ > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
225+ Spi :: < SPI3 , _ , _ , u8 > :: _spi ( spi, pins, mode, freq. into ( ) , clocks, apb)
225226 }
226227}
227228
228229pub type SpiRegisterBlock = crate :: pac:: spi1:: RegisterBlock ;
229230
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 >
231313where
232314 SPI : Deref < Target = SpiRegisterBlock > + Enable + Reset ,
233315 SPI :: Bus : GetBusFreq ,
@@ -300,25 +382,50 @@ where
300382 spi,
301383 pins,
302384 _remap : PhantomData ,
385+ _framesize : PhantomData ,
303386 }
304387 }
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+ }
309399 }
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+ }
312417 }
313418}
314419
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 >
316422where
317423 SPI : Deref < Target = SpiRegisterBlock > ,
424+ FrameSize : Copy ,
318425{
319426 type Error = Error ;
320427
321- fn read ( & mut self ) -> nb:: Result < u8 , Error > {
428+ fn read ( & mut self ) -> nb:: Result < FrameSize , Error > {
322429 let sr = self . spi . sr . read ( ) ;
323430
324431 Err ( if sr. ovr ( ) . bit_is_set ( ) {
@@ -330,13 +437,13 @@ where
330437 } else if sr. rxne ( ) . bit_is_set ( ) {
331438 // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
332439 // 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 ( ) ) ;
334441 } else {
335442 nb:: Error :: WouldBlock
336443 } )
337444 }
338445
339- fn send ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Error > {
446+ fn send ( & mut self , data : FrameSize ) -> nb:: Result < ( ) , Error > {
340447 let sr = self . spi . sr . read ( ) ;
341448
342449 Err ( if sr. ovr ( ) . bit_is_set ( ) {
@@ -347,20 +454,23 @@ where
347454 nb:: Error :: Other ( Error :: Crc )
348455 } else if sr. txe ( ) . bit_is_set ( ) {
349456 // 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 ) ;
351458 return Ok ( ( ) ) ;
352459 } else {
353460 nb:: Error :: WouldBlock
354461 } )
355462 }
356463}
357464
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 ,
360470{
361471}
362472
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 >
364474where
365475 SPI : Deref < Target = SpiRegisterBlock > ,
366476{
@@ -371,48 +481,25 @@ where
371481 // default Write<> implementation (which reads and drops each
372482 // received value)
373483 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)
409496 }
410497}
411498
412499// DMA
413500
414501pub struct SpiPayload < SPI , REMAP , PINS > {
415- spi : Spi < SPI , REMAP , PINS > ,
502+ spi : Spi < SPI , REMAP , PINS , u8 > ,
416503}
417504
418505pub type SpiTxDma < SPI , REMAP , PINS , CHANNEL > = TxDma < SpiPayload < SPI , REMAP , PINS > , CHANNEL > ;
@@ -424,7 +511,7 @@ macro_rules! spi_dma {
424511 type ReceivedWord = u8 ;
425512 }
426513
427- impl <REMAP , PINS > Spi <$SPIi, REMAP , PINS > {
514+ impl <REMAP , PINS > Spi <$SPIi, REMAP , PINS , u8 > {
428515 pub fn with_tx_dma( self , channel: $TCi) -> SpiTxDma <$SPIi, REMAP , PINS , $TCi> {
429516 let payload = SpiPayload { spi: self } ;
430517 SpiTxDma { payload, channel }
0 commit comments