@@ -4,7 +4,10 @@ use core::ptr;
44
55use crate :: hal:: spi:: FullDuplex ;
66pub use crate :: hal:: spi:: { Mode , Phase , Polarity } ;
7- use crate :: pac:: { SPI1 , SPI2 , SPI3 } ;
7+ use crate :: pac:: {
8+ spi1:: cr2:: { DS_A , FRXTH_A } ,
9+ SPI1 , SPI2 , SPI3 ,
10+ } ;
811use crate :: stm32:: spi1;
912
1013use crate :: gpio:: gpioa:: { PA5 , PA6 , PA7 } ;
@@ -47,6 +50,7 @@ use crate::rcc::APB1;
4750) ) ]
4851use crate :: rcc:: APB2 ;
4952use crate :: time:: Hertz ;
53+ use core:: marker:: PhantomData ;
5054
5155/// SPI error
5256#[ derive( Debug ) ]
@@ -104,16 +108,33 @@ unsafe impl MosiPin<SPI2> for PB15<AF5> {}
104108unsafe impl MosiPin < SPI3 > for PB5 < AF6 > { }
105109unsafe impl MosiPin < SPI3 > for PC12 < AF6 > { }
106110
111+ pub trait Word {
112+ fn register_config ( ) -> ( FRXTH_A , DS_A ) ;
113+ }
114+
115+ impl Word for u8 {
116+ fn register_config ( ) -> ( FRXTH_A , DS_A ) {
117+ ( FRXTH_A :: QUARTER , DS_A :: EIGHTBIT )
118+ }
119+ }
120+
121+ impl Word for u16 {
122+ fn register_config ( ) -> ( FRXTH_A , DS_A ) {
123+ ( FRXTH_A :: HALF , DS_A :: SIXTEENBIT )
124+ }
125+ }
126+
107127/// SPI peripheral operating in full duplex master mode
108- pub struct Spi < SPI , PINS > {
128+ pub struct Spi < SPI , PINS , WORD = u8 > {
109129 spi : SPI ,
110130 pins : PINS ,
131+ _word : PhantomData < WORD > ,
111132}
112133
113134macro_rules! hal {
114135 ( $( $SPIX: ident: ( $spiX: ident, $APBX: ident, $spiXen: ident, $spiXrst: ident, $pclkX: ident) , ) +) => {
115136 $(
116- impl <SCK , MISO , MOSI > Spi <$SPIX, ( SCK , MISO , MOSI ) > {
137+ impl <SCK , MISO , MOSI , WORD > Spi <$SPIX, ( SCK , MISO , MOSI ) , WORD > {
117138 /// Configures the SPI peripheral to operate in full duplex master mode
118139 pub fn $spiX<F >(
119140 spi: $SPIX,
@@ -128,17 +149,20 @@ macro_rules! hal {
128149 SCK : SckPin <$SPIX>,
129150 MISO : MisoPin <$SPIX>,
130151 MOSI : MosiPin <$SPIX>,
152+ WORD : Word ,
131153 {
132154 // enable or reset $SPIX
133155 apb2. enr( ) . modify( |_, w| w. $spiXen( ) . enabled( ) ) ;
134156 apb2. rstr( ) . modify( |_, w| w. $spiXrst( ) . reset( ) ) ;
135157 apb2. rstr( ) . modify( |_, w| w. $spiXrst( ) . clear_bit( ) ) ;
136158
137- // FRXTH: RXNE event is generated if the FIFO level is greater than or equal to
138- // 8-bit
139- // DS: 8-bit data size
140- // SSOE: Slave Select output disabled
141- spi. cr2. write( |w| w. frxth( ) . quarter( ) . ds( ) . eight_bit( ) . ssoe( ) . disabled( ) ) ;
159+ let ( frxth, ds) = WORD :: register_config( ) ;
160+ spi. cr2. write( |w| {
161+ w. frxth( ) . variant( frxth) ;
162+ w. ds( ) . variant( ds) ;
163+ // Slave Select output disabled
164+ w. ssoe( ) . disabled( )
165+ } ) ;
142166
143167 // CPHA: phase
144168 // CPOL: polarity
@@ -179,7 +203,7 @@ macro_rules! hal {
179203 . unidirectional( )
180204 } ) ;
181205
182- Spi { spi, pins }
206+ Spi { spi, pins, _word : PhantomData }
183207 }
184208
185209 /// Releases the SPI peripheral and associated pins
@@ -216,10 +240,10 @@ macro_rules! hal {
216240
217241 }
218242
219- impl <PINS > FullDuplex <u8 > for Spi <$SPIX, PINS > {
243+ impl <PINS , WORD > FullDuplex <WORD > for Spi <$SPIX, PINS , WORD > {
220244 type Error = Error ;
221245
222- fn read( & mut self ) -> nb:: Result <u8 , Error > {
246+ fn read( & mut self ) -> nb:: Result <WORD , Error > {
223247 let sr = self . spi. sr. read( ) ;
224248
225249 Err ( if sr. ovr( ) . is_overrun( ) {
@@ -229,17 +253,16 @@ macro_rules! hal {
229253 } else if sr. crcerr( ) . is_no_match( ) {
230254 nb:: Error :: Other ( Error :: Crc )
231255 } else if sr. rxne( ) . is_not_empty( ) {
232- // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
233- // reading a half-word)
234- return Ok ( unsafe {
235- ptr:: read_volatile( & self . spi. dr as * const _ as * const u8 )
236- } ) ;
256+ let read_ptr = & self . spi. dr as * const _ as * const WORD ;
257+ // NOTE(unsafe) read from register owned by this Spi struct
258+ let value = unsafe { ptr:: read_volatile( read_ptr) } ;
259+ return Ok ( value) ;
237260 } else {
238261 nb:: Error :: WouldBlock
239262 } )
240263 }
241264
242- fn send( & mut self , byte : u8 ) -> nb:: Result <( ) , Error > {
265+ fn send( & mut self , word : WORD ) -> nb:: Result <( ) , Error > {
243266 let sr = self . spi. sr. read( ) ;
244267
245268 Err ( if sr. ovr( ) . is_overrun( ) {
@@ -249,18 +272,18 @@ macro_rules! hal {
249272 } else if sr. crcerr( ) . is_no_match( ) {
250273 nb:: Error :: Other ( Error :: Crc )
251274 } else if sr. txe( ) . is_empty( ) {
252- // NOTE(write_volatile) see note above
253- unsafe { ptr:: write_volatile( & self . spi. dr as * const _ as * mut u8 , byte) }
275+ let write_ptr = & self . spi. dr as * const _ as * mut WORD ;
276+ // NOTE(unsafe) write to register owned by this Spi struct
277+ unsafe { ptr:: write_volatile( write_ptr, word) } ;
254278 return Ok ( ( ) ) ;
255279 } else {
256280 nb:: Error :: WouldBlock
257281 } )
258282 }
259283 }
260284
261- impl <PINS > crate :: hal:: blocking:: spi:: transfer:: Default <u8 > for Spi <$SPIX, PINS > { }
262-
263- impl <PINS > crate :: hal:: blocking:: spi:: write:: Default <u8 > for Spi <$SPIX, PINS > { }
285+ impl <PINS , WORD > crate :: hal:: blocking:: spi:: transfer:: Default <WORD > for Spi <$SPIX, PINS , WORD > { }
286+ impl <PINS , WORD > crate :: hal:: blocking:: spi:: write:: Default <WORD > for Spi <$SPIX, PINS , WORD > { }
264287 ) +
265288 }
266289}
0 commit comments