@@ -58,56 +58,18 @@ pub struct I2c<I2C, PINS> {
58
58
pins : PINS ,
59
59
}
60
60
61
- macro_rules! hal {
62
- ( $i2c_type: ident, $enr: ident, $rstr: ident, $i2cX: ident, $i2cXen: ident, $i2cXrst: ident) => {
63
- impl <SCL , SDA > I2c <$i2c_type, ( SCL , SDA ) > {
64
- pub fn $i2cX<F >(
65
- i2c: $i2c_type,
66
- pins: ( SCL , SDA ) ,
67
- freq: F ,
68
- clocks: Clocks ,
69
- apb1: & mut APB1R1 ,
70
- ) -> Self
71
- where
72
- F : Into <Hertz >,
73
- SCL : SclPin <$i2c_type>,
74
- SDA : SdaPin <$i2c_type>,
75
- {
76
- apb1. $enr( ) . modify( |_, w| w. $i2cXen( ) . set_bit( ) ) ;
77
- apb1. $rstr( ) . modify( |_, w| w. $i2cXrst( ) . set_bit( ) ) ;
78
- apb1. $rstr( ) . modify( |_, w| w. $i2cXrst( ) . clear_bit( ) ) ;
79
- Self :: new( i2c, pins, freq, clocks)
80
- }
81
- }
82
- } ;
61
+ pub struct Config {
62
+ presc : u8 ,
63
+ sclh : u8 ,
64
+ scll : u8 ,
65
+ scldel : u8 ,
66
+ sdadel : u8 ,
83
67
}
84
68
85
- hal ! ( I2C1 , enr, rstr, i2c1, i2c1en, i2c1rst) ;
86
- hal ! ( I2C2 , enr, rstr, i2c2, i2c2en, i2c2rst) ;
87
- hal ! ( I2C3 , enr, rstr, i2c3, i2c3en, i2c3rst) ;
88
-
89
- // This peripheral is not present on
90
- // STM32L471XX and STM32L431XX
91
- // STM32L432XX and STM32l442XX
92
- // STM32L486XX and STM32L476XX
93
- #[ cfg( any( feature = "stm32l4x1" , feature = "stm32l4x2" , feature = "stm32l4x6" ) ) ]
94
- hal ! ( I2C4 , enr2, rstr2, i2c4, i2c4en, i2c4rst) ;
95
-
96
- impl < SCL , SDA , I2C > I2c < I2C , ( SCL , SDA ) >
97
- where
98
- I2C : Deref < Target = i2c1:: RegisterBlock > ,
99
- {
100
- /// Configures the I2C peripheral to work in master mode
101
- fn new < F > ( i2c : I2C , pins : ( SCL , SDA ) , freq : F , clocks : Clocks ) -> Self
102
- where
103
- F : Into < Hertz > ,
104
- SCL : SclPin < I2C > ,
105
- SDA : SdaPin < I2C > ,
106
- {
69
+ impl Config {
70
+ pub fn new < F : Into < Hertz > > ( freq : F , clocks : Clocks ) -> Self {
107
71
let freq = freq. into ( ) . 0 ;
108
72
assert ! ( freq <= 1_000_000 ) ;
109
- // Make sure the I2C unit is disabled so we can configure it
110
- i2c. cr1 . modify ( |_, w| w. pe ( ) . clear_bit ( ) ) ;
111
73
112
74
// TODO review compliance with the timing requirements of I2C
113
75
// t_I2CCLK = 1 / PCLK1
@@ -177,18 +139,84 @@ where
177
139
let sclh = u8_or_panic ! ( sclh, "I2C sclh" ) ;
178
140
let scll = u8_or_panic ! ( scll, "I2C scll" ) ;
179
141
142
+ Self {
143
+ presc,
144
+ sclh,
145
+ scll,
146
+ scldel,
147
+ sdadel,
148
+ }
149
+ }
150
+
151
+ /// For the layout of `timing_bits`, see RM0394 section 37.7.5.
152
+ pub fn with_timing ( timing_bits : u32 ) -> Self {
153
+ Self {
154
+ presc : ( ( timing_bits >> 28 ) & 0xf ) as u8 ,
155
+ scldel : ( ( timing_bits >> 20 ) & 0xf ) as u8 ,
156
+ sdadel : ( ( timing_bits >> 16 ) & 0xf ) as u8 ,
157
+ sclh : ( ( timing_bits >> 8 ) & 0xff ) as u8 ,
158
+ scll : ( timing_bits & 0xff ) as u8 ,
159
+ }
160
+ }
161
+ }
162
+
163
+ macro_rules! hal {
164
+ ( $i2c_type: ident, $enr: ident, $rstr: ident, $i2cX: ident, $i2cXen: ident, $i2cXrst: ident) => {
165
+ impl <SCL , SDA > I2c <$i2c_type, ( SCL , SDA ) > {
166
+ pub fn $i2cX(
167
+ i2c: $i2c_type,
168
+ pins: ( SCL , SDA ) ,
169
+ config: Config ,
170
+ apb1: & mut APB1R1 ,
171
+ ) -> Self
172
+ where
173
+ SCL : SclPin <$i2c_type>,
174
+ SDA : SdaPin <$i2c_type>,
175
+ {
176
+ apb1. $enr( ) . modify( |_, w| w. $i2cXen( ) . set_bit( ) ) ;
177
+ apb1. $rstr( ) . modify( |_, w| w. $i2cXrst( ) . set_bit( ) ) ;
178
+ apb1. $rstr( ) . modify( |_, w| w. $i2cXrst( ) . clear_bit( ) ) ;
179
+ Self :: new( i2c, pins, config)
180
+ }
181
+ }
182
+ } ;
183
+ }
184
+
185
+ hal ! ( I2C1 , enr, rstr, i2c1, i2c1en, i2c1rst) ;
186
+ hal ! ( I2C2 , enr, rstr, i2c2, i2c2en, i2c2rst) ;
187
+ hal ! ( I2C3 , enr, rstr, i2c3, i2c3en, i2c3rst) ;
188
+
189
+ // This peripheral is not present on
190
+ // STM32L471XX and STM32L431XX
191
+ // STM32L432XX and STM32l442XX
192
+ // STM32L486XX and STM32L476XX
193
+ #[ cfg( any( feature = "stm32l4x1" , feature = "stm32l4x2" , feature = "stm32l4x6" ) ) ]
194
+ hal ! ( I2C4 , enr2, rstr2, i2c4, i2c4en, i2c4rst) ;
195
+
196
+ impl < SCL , SDA , I2C > I2c < I2C , ( SCL , SDA ) >
197
+ where
198
+ I2C : Deref < Target = i2c1:: RegisterBlock > ,
199
+ {
200
+ /// Configures the I2C peripheral to work in master mode
201
+ fn new ( i2c : I2C , pins : ( SCL , SDA ) , config : Config ) -> Self
202
+ where
203
+ SCL : SclPin < I2C > ,
204
+ SDA : SdaPin < I2C > ,
205
+ {
206
+ // Make sure the I2C unit is disabled so we can configure it
207
+ i2c. cr1 . modify ( |_, w| w. pe ( ) . clear_bit ( ) ) ;
180
208
// Configure for "fast mode" (400 KHz)
181
209
i2c. timingr . write ( |w| {
182
210
w. presc ( )
183
- . bits ( presc)
211
+ . bits ( config . presc )
184
212
. scll ( )
185
- . bits ( scll)
213
+ . bits ( config . scll )
186
214
. sclh ( )
187
- . bits ( sclh)
215
+ . bits ( config . sclh )
188
216
. sdadel ( )
189
- . bits ( sdadel)
217
+ . bits ( config . sdadel )
190
218
. scldel ( )
191
- . bits ( scldel)
219
+ . bits ( config . scldel )
192
220
} ) ;
193
221
194
222
// Enable the peripheral
0 commit comments