1
- #[ cfg( feature = "stm32f042" ) ]
2
- use crate :: stm32:: { I2C1 , RCC } ;
1
+ use core:: ops:: Deref ;
3
2
3
+ use crate :: stm32;
4
4
use embedded_hal:: blocking:: i2c:: { Write , WriteRead } ;
5
5
6
- use core:: cmp;
7
- #[ cfg( feature = "stm32f042" ) ]
8
- use crate :: gpio:: gpioa:: { PA10 , PA11 , PA12 , PA9 } ;
9
- #[ cfg( feature = "stm32f042" ) ]
10
- use crate :: gpio:: gpiob:: { PB10 , PB11 , PB13 , PB14 , PB6 , PB7 , PB8 , PB9 } ;
11
- #[ cfg( feature = "stm32f042" ) ]
12
- use crate :: gpio:: gpiof:: { PF0 , PF1 } ;
13
- #[ cfg( feature = "stm32f042" ) ]
14
- use crate :: gpio:: { Alternate , AF1 , AF4 , AF5 } ;
6
+ use crate :: gpio:: * ;
15
7
use crate :: time:: { KiloHertz , U32Ext } ;
8
+ use core:: cmp;
16
9
17
10
/// I2C abstraction
18
- pub struct I2c < I2C , PINS > {
11
+ pub struct I2c < I2C , SCLPIN , SDAPIN > {
19
12
i2c : I2C ,
20
- pins : PINS ,
13
+ pins : ( SCLPIN , SDAPIN ) ,
21
14
}
22
15
23
- pub trait Pins < I2c > { }
24
-
25
- #[ cfg( feature = "stm32f042" ) ]
26
- impl Pins < I2C1 > for ( PA9 < Alternate < AF4 > > , PA10 < Alternate < AF4 > > ) { }
27
- #[ cfg( feature = "stm32f042" ) ]
28
- impl Pins < I2C1 > for ( PA11 < Alternate < AF5 > > , PA12 < Alternate < AF5 > > ) { }
29
- #[ cfg( feature = "stm32f042" ) ]
30
- impl Pins < I2C1 > for ( PB6 < Alternate < AF1 > > , PB7 < Alternate < AF1 > > ) { }
31
- #[ cfg( feature = "stm32f042" ) ]
32
- impl Pins < I2C1 > for ( PB8 < Alternate < AF1 > > , PB9 < Alternate < AF1 > > ) { }
33
- #[ cfg( feature = "stm32f042" ) ]
34
- impl Pins < I2C1 > for ( PB10 < Alternate < AF1 > > , PB11 < Alternate < AF1 > > ) { }
35
- #[ cfg( feature = "stm32f042" ) ]
36
- impl Pins < I2C1 > for ( PB13 < Alternate < AF5 > > , PB14 < Alternate < AF5 > > ) { }
37
- #[ cfg( feature = "stm32f042" ) ]
38
- impl Pins < I2C1 > for ( PF1 < Alternate < AF1 > > , PF0 < Alternate < AF1 > > ) { }
16
+ pub trait SclPin < I2C > { }
17
+ pub trait SdaPin < I2C > { }
18
+
19
+ macro_rules! i2c_pins {
20
+ ( $( $I2C: ident => {
21
+ scl => [ $( $scl: ty) ,+ $( , ) * ] ,
22
+ sda => [ $( $sda: ty) ,+ $( , ) * ] ,
23
+ } ) +) => {
24
+ $(
25
+ $(
26
+ impl SclPin <stm32:: $I2C> for $scl { }
27
+ ) +
28
+ $(
29
+ impl SdaPin <stm32:: $I2C> for $sda { }
30
+ ) +
31
+ ) +
32
+ }
33
+ }
34
+
35
+ #[ cfg( any( feature = "stm32f042" , feature = "stm32f030" ) ) ]
36
+ i2c_pins ! {
37
+ I2C1 => {
38
+ scl => [ gpioa:: PA11 <Alternate <AF5 >>, gpiob:: PB6 <Alternate <AF1 >>, gpiob:: PB8 <Alternate <AF1 >>] ,
39
+ sda => [ gpioa:: PA12 <Alternate <AF5 >>, gpiob:: PB7 <Alternate <AF1 >>, gpiob:: PB9 <Alternate <AF1 >>] ,
40
+ }
41
+ }
42
+ #[ cfg( any(
43
+ feature = "stm32f042" ,
44
+ feature = "stm32f030x6" ,
45
+ feature = "stm32f030xc"
46
+ ) ) ]
47
+ i2c_pins ! {
48
+ I2C1 => {
49
+ scl => [ gpioa:: PA9 <Alternate <AF4 >>] ,
50
+ sda => [ gpioa:: PA10 <Alternate <AF4 >>] ,
51
+ }
52
+ }
53
+ #[ cfg( any( feature = "stm32f042" , feature = "stm32f030x6" ) ) ]
54
+ i2c_pins ! {
55
+ I2C1 => {
56
+ scl => [ gpiob:: PB10 <Alternate <AF1 >>] ,
57
+ sda => [ gpiob:: PB11 <Alternate <AF1 >>] ,
58
+ }
59
+ }
60
+ #[ cfg( any( feature = "stm32f042" , feature = "stm32f030xc" ) ) ]
61
+ i2c_pins ! {
62
+ I2C1 => {
63
+ scl => [ gpiob:: PB13 <Alternate <AF5 >>, gpiof:: PF1 <Alternate <AF1 >>] ,
64
+ sda => [ gpiob:: PB14 <Alternate <AF5 >>, gpiof:: PF0 <Alternate <AF1 >>] ,
65
+ }
66
+ }
67
+ #[ cfg( any( feature = "stm32f030x8" , feature = "stm32f030xc" ) ) ]
68
+ i2c_pins ! {
69
+ I2C2 => {
70
+ scl => [ gpiob:: PB10 <Alternate <AF1 >>] ,
71
+ sda => [ gpiob:: PB11 <Alternate <AF1 >>] ,
72
+ }
73
+ }
74
+ #[ cfg( feature = "stm32f030xc" ) ]
75
+ i2c_pins ! {
76
+ I2C2 => {
77
+ scl => [ gpiob:: PB13 <Alternate <AF5 >>] ,
78
+ sda => [ gpiob:: PB14 <Alternate <AF5 >>] ,
79
+ }
80
+ }
39
81
40
82
#[ derive( Debug ) ]
41
83
pub enum Error {
42
84
OVERRUN ,
43
85
NACK ,
44
86
}
45
87
46
- #[ cfg( feature = "stm32f042" ) ]
47
- impl < PINS > I2c < I2C1 , PINS > {
48
- pub fn i2c1 ( i2c : I2C1 , pins : PINS , speed : KiloHertz ) -> Self
49
- where
50
- PINS : Pins < I2C1 > ,
51
- {
52
- // NOTE(unsafe) This executes only during initialisation
53
- let rcc = unsafe { & ( * RCC :: ptr ( ) ) } ;
54
-
55
- /* Enable clock for I2C1 */
56
- rcc. apb1enr . modify ( |_, w| w. i2c1en ( ) . set_bit ( ) ) ;
57
-
58
- /* Reset I2C1 */
59
- rcc. apb1rstr . modify ( |_, w| w. i2c1rst ( ) . set_bit ( ) ) ;
60
- rcc. apb1rstr . modify ( |_, w| w. i2c1rst ( ) . clear_bit ( ) ) ;
88
+ macro_rules! i2c {
89
+ ( $( $I2C: ident: ( $i2c: ident, $i2cXen: ident, $i2cXrst: ident, $apbenr: ident, $apbrstr: ident) , ) +) => {
90
+ $(
91
+ use crate :: stm32:: $I2C;
92
+ impl <SCLPIN , SDAPIN > I2c <$I2C, SCLPIN , SDAPIN > {
93
+ pub fn $i2c( i2c: $I2C, pins: ( SCLPIN , SDAPIN ) , speed: KiloHertz ) -> Self
94
+ where
95
+ SCLPIN : SclPin <$I2C>,
96
+ SDAPIN : SdaPin <$I2C>,
97
+ {
98
+ // NOTE(unsafe) This executes only during initialisation
99
+ let rcc = unsafe { & ( * stm32:: RCC :: ptr( ) ) } ;
100
+
101
+ /* Enable clock for I2C */
102
+ rcc. $apbenr. modify( |_, w| w. $i2cXen( ) . set_bit( ) ) ;
103
+
104
+ /* Reset I2C */
105
+ rcc. $apbrstr. modify( |_, w| w. $i2cXrst( ) . set_bit( ) ) ;
106
+ rcc. $apbrstr. modify( |_, w| w. $i2cXrst( ) . clear_bit( ) ) ;
107
+ I2c { i2c, pins } . i2c_init( speed)
108
+ }
109
+ }
110
+ ) +
111
+ }
112
+ }
113
+ #[ cfg( any( feature = "stm32f042" , feature = "stm32f030" ) ) ]
114
+ i2c ! {
115
+ I2C1 : ( i2c1, i2c1en, i2c1rst, apb1enr, apb1rstr) ,
116
+ }
117
+ #[ cfg( any( feature = "stm32f030xc" , feature = "stm32f030xc" ) ) ]
118
+ i2c ! {
119
+ I2C2 : ( i2c2, i2c2en, i2c2rst, apb1enr, apb1rstr) ,
120
+ }
61
121
122
+ // It's s needed for the impls, but rustc doesn't recognize that
123
+ #[ allow( dead_code) ]
124
+ type I2cRegisterBlock = stm32:: i2c1:: RegisterBlock ;
125
+ impl < I2C , SCLPIN , SDAPIN > I2c < I2C , SCLPIN , SDAPIN >
126
+ where
127
+ I2C : Deref < Target = I2cRegisterBlock > ,
128
+ {
129
+ fn i2c_init ( self : Self , speed : KiloHertz ) -> Self {
62
130
/* Make sure the I2C unit is disabled so we can configure it */
63
- i2c. cr1 . modify ( |_, w| w. pe ( ) . clear_bit ( ) ) ;
131
+ self . i2c . cr1 . modify ( |_, w| w. pe ( ) . clear_bit ( ) ) ;
64
132
65
133
// Calculate settings for I2C speed modes
66
134
let presc;
@@ -88,7 +156,7 @@ impl<PINS> I2c<I2C1, PINS> {
88
156
}
89
157
90
158
/* Enable I2C signal generator, and configure I2C for 400KHz full speed */
91
- i2c. timingr . write ( |w| {
159
+ self . i2c . timingr . write ( |w| {
92
160
w. presc ( )
93
161
. bits ( presc)
94
162
. scldel ( )
@@ -102,12 +170,12 @@ impl<PINS> I2c<I2C1, PINS> {
102
170
} ) ;
103
171
104
172
/* Enable the I2C processing */
105
- i2c. cr1 . modify ( |_, w| w. pe ( ) . set_bit ( ) ) ;
173
+ self . i2c . cr1 . modify ( |_, w| w. pe ( ) . set_bit ( ) ) ;
106
174
107
- I2c { i2c , pins }
175
+ self
108
176
}
109
177
110
- pub fn release ( self ) -> ( I2C1 , PINS ) {
178
+ pub fn release ( self ) -> ( I2C , ( SCLPIN , SDAPIN ) ) {
111
179
( self . i2c , self . pins )
112
180
}
113
181
@@ -136,8 +204,10 @@ impl<PINS> I2c<I2C1, PINS> {
136
204
}
137
205
}
138
206
139
- #[ cfg( feature = "stm32f042" ) ]
140
- impl < PINS > WriteRead for I2c < I2C1 , PINS > {
207
+ impl < I2C , SCLPIN , SDAPIN > WriteRead for I2c < I2C , SCLPIN , SDAPIN >
208
+ where
209
+ I2C : Deref < Target = I2cRegisterBlock > ,
210
+ {
141
211
type Error = Error ;
142
212
143
213
fn write_read ( & mut self , addr : u8 , bytes : & [ u8 ] , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
@@ -214,8 +284,10 @@ impl<PINS> WriteRead for I2c<I2C1, PINS> {
214
284
}
215
285
}
216
286
217
- #[ cfg( feature = "stm32f042" ) ]
218
- impl < PINS > Write for I2c < I2C1 , PINS > {
287
+ impl < I2C , SCLPIN , SDAPIN > Write for I2c < I2C , SCLPIN , SDAPIN >
288
+ where
289
+ I2C : Deref < Target = I2cRegisterBlock > ,
290
+ {
219
291
type Error = Error ;
220
292
221
293
fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
0 commit comments