1
- //! # Serial Peripheral Interface
1
+ /*!
2
+ # Serial Peripheral Interface
3
+
4
+ ## Alternate function remapping
5
+
6
+ ### SPI1
7
+
8
+ | Function | Spi1NoRemap | Spi1Remap |
9
+ |:----:|:-----------:|:---------:|
10
+ | SCK | PA5 | PB3 |
11
+ | MISO | PA6 | PB4 |
12
+ | MOSI | PA7 | PB5 |
13
+
14
+ ### SPI2
15
+
16
+ | Function | Spi2NoRemap |
17
+ |:----:|:-----------:|
18
+ | SCK | PB13 |
19
+ | MISO | PB14 |
20
+ | MOSI | PB15 |
21
+
22
+ ### SPI3
23
+
24
+ Available only on high density devices.
25
+
26
+ | Function | Spi3NoRemap | Spi3Remap |
27
+ |:----:|:-----------:|:---------:|
28
+ | SCK | PB3 | PC10 |
29
+ | MISO | PB4 | PC11 |
30
+ | MOSI | PB5 | PC12 |
31
+ */
2
32
3
33
use core:: ptr;
4
34
5
35
use nb;
6
36
7
37
pub use crate :: hal:: spi:: { Mode , Phase , Polarity } ;
8
38
use crate :: pac:: { SPI1 , SPI2 } ;
39
+ #[ cfg( feature="high" ) ]
40
+ use crate :: pac:: SPI3 ;
9
41
10
42
use crate :: afio:: MAPR ;
11
43
use crate :: gpio:: gpioa:: { PA5 , PA6 , PA7 } ;
@@ -33,47 +65,88 @@ pub enum Error {
33
65
_Extensible,
34
66
}
35
67
36
- pub trait Pins < SPI > {
37
- const REMAP : bool ;
38
- }
68
+ use core:: marker:: PhantomData ;
39
69
40
- impl Pins < SPI1 >
41
- for (
42
- PA5 < Alternate < PushPull > > ,
43
- PA6 < Input < Floating > > ,
44
- PA7 < Alternate < PushPull > > ,
45
- )
46
- {
47
- const REMAP : bool = false ;
70
+ mod sealed {
71
+ pub trait Remap {
72
+ type Periph ;
73
+ const REMAP : bool ;
74
+ }
75
+ pub trait Sck < REMAP > { }
76
+ pub trait Miso < REMAP > { }
77
+ pub trait Mosi < REMAP > { }
78
+ pub struct _Sck ;
79
+ pub struct _Miso ;
80
+ pub struct _Mosi ;
48
81
}
82
+ use sealed:: { Remap , Sck , Miso , Mosi } ;
49
83
50
- impl Pins < SPI1 >
51
- for (
52
- PB3 < Alternate < PushPull > > ,
53
- PB4 < Input < Floating > > ,
54
- PB5 < Alternate < PushPull > > ,
55
- )
56
- {
57
- const REMAP : bool = true ;
84
+ pub trait Pins < SPI , P > {
85
+ type _Pos ;
58
86
}
59
-
60
- impl Pins < SPI2 >
61
- for (
62
- PB13 < Alternate < PushPull > > ,
63
- PB14 < Input < Floating > > ,
64
- PB15 < Alternate < PushPull > > ,
65
- )
66
- {
67
- const REMAP : bool = false ;
87
+ macro_rules! pins_impl {
88
+ ( $( ( $( $PINX: ident) ,+ ) , ( $( $TRAIT: ident) ,+ ) , ( $( $POS: ident) ,* ) ; ) + ) => {
89
+ $(
90
+ #[ allow( unused_parens) ]
91
+ impl <REMAP , $( $PINX, ) +> Pins <REMAP , ( $( sealed:: $POS) ,+) > for ( $( $PINX) ,+)
92
+ where
93
+ $( $PINX: $TRAIT<REMAP >, ) +
94
+ {
95
+ type _Pos = ( $( sealed:: $POS) ,+) ;
96
+ }
97
+ ) +
98
+ } ;
68
99
}
69
100
70
- pub struct Spi < SPI , PINS > {
101
+ pins_impl ! (
102
+ ( SCK , MISO , MOSI ) , ( Sck , Miso , Mosi ) , ( _Sck, _Miso, _Mosi) ;
103
+ ( SCK , MOSI , MISO ) , ( Sck , Mosi , Miso ) , ( _Sck, _Mosi, _Miso) ;
104
+ ( MOSI , SCK , MISO ) , ( Mosi , Sck , Miso ) , ( _Mosi, _Sck, _Miso) ;
105
+ ( MOSI , MISO , SCK ) , ( Mosi , Miso , Sck ) , ( _Mosi, _Miso, _Sck) ;
106
+ ( MISO , MOSI , SCK ) , ( Miso , Mosi , Sck ) , ( _Miso, _Mosi, _Sck) ;
107
+ ( MISO , SCK , MOSI ) , ( Miso , Sck , Mosi ) , ( _Miso, _Sck, _Mosi) ;
108
+ ) ;
109
+
110
+ pub struct Spi < SPI , REMAP , PINS > {
71
111
spi : SPI ,
72
112
pins : PINS ,
113
+ _remap : PhantomData < REMAP > ,
73
114
}
74
115
75
- impl < PINS > Spi < SPI1 , PINS > {
76
- pub fn spi1 < F > (
116
+ /// A filler type for when the SCK pin is unnecessary
117
+ pub struct NoSck ;
118
+ /// A filler type for when the Miso pin is unnecessary
119
+ pub struct NoMiso ;
120
+ /// A filler type for when the Mosi pin is unnecessary
121
+ pub struct NoMosi ;
122
+
123
+ impl < REMAP > Sck < REMAP > for NoSck { }
124
+ impl < REMAP > Miso < REMAP > for NoMiso { }
125
+ impl < REMAP > Mosi < REMAP > for NoMosi { }
126
+
127
+ macro_rules! remap {
128
+ ( $name: ident, $SPIX: ident, $state: literal, $SCK: ident, $MISO: ident, $MOSI: ident) => {
129
+ pub struct $name;
130
+ impl Remap for $name {
131
+ type Periph = $SPIX;
132
+ const REMAP : bool = $state;
133
+ }
134
+ impl Sck <$name> for $SCK<Alternate <PushPull >> { }
135
+ impl Miso <$name> for $MISO<Input <Floating >> { }
136
+ impl Mosi <$name> for $MOSI<Alternate <PushPull >> { }
137
+ }
138
+ }
139
+
140
+ remap ! ( Spi1NoRemap , SPI1 , false , PA5 , PA6 , PA7 ) ;
141
+ remap ! ( Spi1Remap , SPI1 , true , PB3 , PB4 , PB5 ) ;
142
+ remap ! ( Spi2NoRemap , SPI2 , false , PB13 , PB14 , PB15 ) ;
143
+ #[ cfg( feature="high" ) ]
144
+ remap ! ( Spi3NoRemap , SPI3 , false , PB3 , PB4 , PB5 ) ;
145
+ #[ cfg( feature = "stm32f105" ) ]
146
+ remap ! ( Spi3Remap , SPI3 , true , PC10 , PC11 , PC12 ) ;
147
+
148
+ impl < REMAP , PINS > Spi < SPI1 , REMAP , PINS > {
149
+ pub fn spi1 < F , POS > (
77
150
spi : SPI1 ,
78
151
pins : PINS ,
79
152
mapr : & mut MAPR ,
@@ -84,15 +157,16 @@ impl<PINS> Spi<SPI1, PINS> {
84
157
) -> Self
85
158
where
86
159
F : Into < Hertz > ,
87
- PINS : Pins < SPI1 > ,
160
+ REMAP : Remap < Periph = SPI1 > ,
161
+ PINS : Pins < REMAP , POS > ,
88
162
{
89
- mapr. modify_mapr ( |_, w| w. spi1_remap ( ) . bit ( PINS :: REMAP ) ) ;
163
+ mapr. modify_mapr ( |_, w| w. spi1_remap ( ) . bit ( REMAP :: REMAP ) ) ;
90
164
Spi :: _spi1 ( spi, pins, mode, freq. into ( ) , clocks, apb)
91
165
}
92
166
}
93
167
94
- impl < PINS > Spi < SPI2 , PINS > {
95
- pub fn spi2 < F > (
168
+ impl < REMAP , PINS > Spi < SPI2 , REMAP , PINS > {
169
+ pub fn spi2 < F , POS > (
96
170
spi : SPI2 ,
97
171
pins : PINS ,
98
172
mode : Mode ,
@@ -102,16 +176,36 @@ impl<PINS> Spi<SPI2, PINS> {
102
176
) -> Self
103
177
where
104
178
F : Into < Hertz > ,
105
- PINS : Pins < SPI2 > ,
179
+ REMAP : Remap < Periph = SPI2 > ,
180
+ PINS : Pins < REMAP , POS > ,
106
181
{
107
182
Spi :: _spi2 ( spi, pins, mode, freq. into ( ) , clocks, apb)
108
183
}
109
184
}
110
185
186
+ #[ cfg( feature="high" ) ]
187
+ impl < REMAP , PINS > Spi < SPI3 , REMAP , PINS > {
188
+ pub fn spi3 < F , POS > (
189
+ spi : SPI3 ,
190
+ pins : PINS ,
191
+ mode : Mode ,
192
+ freq : F ,
193
+ clocks : Clocks ,
194
+ apb : & mut <SPI3 as RccBus >:: Bus ,
195
+ ) -> Self
196
+ where
197
+ F : Into < Hertz > ,
198
+ REMAP : Remap < Periph = SPI3 > ,
199
+ PINS : Pins < REMAP , POS > ,
200
+ {
201
+ Spi :: _spi3 ( spi, pins, mode, freq. into ( ) , clocks, apb)
202
+ }
203
+ }
204
+
111
205
macro_rules! hal {
112
206
( $( $SPIX: ident: ( $spiX: ident) , ) +) => {
113
207
$(
114
- impl <PINS > Spi <$SPIX, PINS > {
208
+ impl <REMAP , PINS > Spi <$SPIX, REMAP , PINS > {
115
209
fn $spiX(
116
210
spi: $SPIX,
117
211
pins: PINS ,
@@ -171,15 +265,15 @@ macro_rules! hal {
171
265
. set_bit( )
172
266
) ;
173
267
174
- Spi { spi, pins }
268
+ Spi { spi, pins, _remap : PhantomData }
175
269
}
176
270
177
271
pub fn free( self ) -> ( $SPIX, PINS ) {
178
272
( self . spi, self . pins)
179
273
}
180
274
}
181
275
182
- impl <PINS > crate :: hal:: spi:: FullDuplex <u8 > for Spi <$SPIX, PINS > {
276
+ impl <REMAP , PINS > crate :: hal:: spi:: FullDuplex <u8 > for Spi <$SPIX, REMAP , PINS > {
183
277
type Error = Error ;
184
278
185
279
fn read( & mut self ) -> nb:: Result <u8 , Error > {
@@ -222,9 +316,9 @@ macro_rules! hal {
222
316
223
317
}
224
318
225
- impl <PINS > crate :: hal:: blocking:: spi:: transfer:: Default <u8 > for Spi <$SPIX, PINS > { }
319
+ impl <REMAP , PINS > crate :: hal:: blocking:: spi:: transfer:: Default <u8 > for Spi <$SPIX, REMAP , PINS > { }
226
320
227
- impl <PINS > crate :: hal:: blocking:: spi:: write:: Default <u8 > for Spi <$SPIX, PINS > { }
321
+ impl <REMAP , PINS > crate :: hal:: blocking:: spi:: write:: Default <u8 > for Spi <$SPIX, REMAP , PINS > { }
228
322
) +
229
323
}
230
324
}
@@ -233,32 +327,36 @@ hal! {
233
327
SPI1 : ( _spi1) ,
234
328
SPI2 : ( _spi2) ,
235
329
}
330
+ #[ cfg( feature="high" ) ]
331
+ hal ! {
332
+ SPI3 : ( _spi3) ,
333
+ }
236
334
237
335
// DMA
238
336
239
- pub struct SpiPayload < SPI , PINS > {
240
- spi : Spi < SPI , PINS >
337
+ pub struct SpiPayload < SPI , REMAP , PINS > {
338
+ spi : Spi < SPI , REMAP , PINS >
241
339
}
242
340
243
- pub type SpiTxDma < SPI , PINS , CHANNEL > = TxDma < SpiPayload < SPI , PINS > , CHANNEL > ;
341
+ pub type SpiTxDma < SPI , REMAP , PINS , CHANNEL > = TxDma < SpiPayload < SPI , REMAP , PINS > , CHANNEL > ;
244
342
245
343
macro_rules! spi_dma {
246
344
( $SPIi: ident, $TCi: ident) => {
247
- impl <PINS > Transmit for SpiTxDma <$SPIi, PINS , $TCi> {
345
+ impl <REMAP , PINS > Transmit for SpiTxDma <$SPIi, REMAP , PINS , $TCi> {
248
346
type TxChannel = $TCi;
249
347
type ReceivedWord = u8 ;
250
348
}
251
349
252
- impl <PINS > Spi <$SPIi, PINS > {
253
- pub fn with_tx_dma( self , channel: $TCi) -> SpiTxDma <$SPIi, PINS , $TCi> {
350
+ impl <REMAP , PINS > Spi <$SPIi, REMAP , PINS > {
351
+ pub fn with_tx_dma( self , channel: $TCi) -> SpiTxDma <$SPIi, REMAP , PINS , $TCi> {
254
352
let payload = SpiPayload {
255
353
spi: self
256
354
} ;
257
355
SpiTxDma { payload, channel}
258
356
}
259
357
}
260
358
261
- impl <PINS > TransferPayload for SpiTxDma <$SPIi, PINS , $TCi> {
359
+ impl <REMAP , PINS > TransferPayload for SpiTxDma <$SPIi, REMAP , PINS , $TCi> {
262
360
fn start( & mut self ) {
263
361
self . payload. spi. spi. cr2. modify( |_, w| w. txdmaen( ) . set_bit( ) ) ;
264
362
self . channel. start( ) ;
@@ -269,7 +367,7 @@ macro_rules! spi_dma {
269
367
}
270
368
}
271
369
272
- impl <A , B , PIN > crate :: dma:: WriteDma <A , B , u8 > for SpiTxDma <$SPIi, PIN , $TCi>
370
+ impl <A , B , REMAP , PIN > crate :: dma:: WriteDma <A , B , u8 > for SpiTxDma <$SPIi, REMAP , PIN , $TCi>
273
371
where
274
372
A : AsSlice <Element =u8 >,
275
373
B : Static <A >
0 commit comments