@@ -2,54 +2,67 @@ use core::ops::Deref;
2
2
3
3
use crate :: gpio;
4
4
use crate :: i2c:: { Error , NoAcknowledgeSource } ;
5
- use crate :: pac:: { fmpi2c1, FMPI2C1 , RCC } ;
6
- use crate :: rcc:: { Enable , Reset } ;
5
+ use crate :: pac:: fmpi2c1 as i2c1;
6
+ use crate :: pac:: { self , RCC } ;
7
+ use crate :: rcc:: { BusClock , Enable , Reset } ;
7
8
use fugit:: { HertzU32 as Hertz , RateExtU32 } ;
8
9
10
+ // Old names
11
+ pub use I2c as FmpI2c ;
12
+ pub use Mode as FmpMode ;
13
+
9
14
mod hal_02;
10
15
mod hal_1;
11
16
12
17
pub trait Instance :
13
18
crate :: Sealed
14
- + crate :: Ptr < RB = fmpi2c1 :: RegisterBlock >
19
+ + crate :: Ptr < RB = i2c1 :: RegisterBlock >
15
20
+ Deref < Target = Self :: RB >
16
21
+ Enable
17
22
+ Reset
23
+ + BusClock
18
24
+ gpio:: alt:: I2cCommon
19
25
{
20
26
fn clock_hsi ( rcc : & crate :: pac:: rcc:: RegisterBlock ) ;
21
27
}
22
28
23
- impl Instance for FMPI2C1 {
24
- fn clock_hsi ( rcc : & crate :: pac:: rcc:: RegisterBlock ) {
25
- rcc. dckcfgr2 ( ) . modify ( |_, w| w. fmpi2c1sel ( ) . hsi ( ) ) ;
26
- }
27
- }
29
+ macro_rules! i2c {
30
+ ( $I2C: ty, $i2csel: ident, $I2Calias: ident) => {
31
+ pub type $I2Calias = I2c <$I2C>;
28
32
29
- impl crate :: Ptr for FMPI2C1 {
30
- type RB = fmpi2c1:: RegisterBlock ;
31
- #[ inline( always) ]
32
- fn ptr ( ) -> * const Self :: RB {
33
- Self :: ptr ( )
34
- }
33
+ impl Instance for $I2C {
34
+ fn clock_hsi( rcc: & crate :: pac:: rcc:: RegisterBlock ) {
35
+ rcc. dckcfgr2( ) . modify( |_, w| w. $i2csel( ) . hsi( ) ) ;
36
+ }
37
+ }
38
+
39
+ impl crate :: Ptr for $I2C {
40
+ type RB = i2c1:: RegisterBlock ;
41
+ #[ inline( always) ]
42
+ fn ptr( ) -> * const Self :: RB {
43
+ Self :: ptr( )
44
+ }
45
+ }
46
+ } ;
35
47
}
36
48
49
+ #[ cfg( feature = "fmpi2c1" ) ]
50
+ i2c ! ( pac:: FMPI2C1 , fmpi2c1sel, FMPI2c1 ) ;
51
+
37
52
/// I2C FastMode+ abstraction
38
- pub struct FMPI2c < I2C : Instance > {
53
+ pub struct I2c < I2C : Instance > {
39
54
i2c : I2C ,
40
55
pins : ( I2C :: Scl , I2C :: Sda ) ,
41
56
}
42
57
43
- pub type FMPI2c1 = FMPI2c < FMPI2C1 > ;
44
-
45
- #[ derive( Debug , PartialEq ) ]
46
- pub enum FmpMode {
58
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
59
+ pub enum Mode {
47
60
Standard { frequency : Hertz } ,
48
61
Fast { frequency : Hertz } ,
49
62
FastPlus { frequency : Hertz } ,
50
63
}
51
64
52
- impl FmpMode {
65
+ impl Mode {
53
66
pub fn standard ( frequency : Hertz ) -> Self {
54
67
Self :: Standard { frequency }
55
68
}
@@ -71,7 +84,7 @@ impl FmpMode {
71
84
}
72
85
}
73
86
74
- impl From < Hertz > for FmpMode {
87
+ impl From < Hertz > for Mode {
75
88
fn from ( frequency : Hertz ) -> Self {
76
89
let k100: Hertz = 100 . kHz ( ) ;
77
90
let k400: Hertz = 400 . kHz ( ) ;
@@ -85,26 +98,39 @@ impl From<Hertz> for FmpMode {
85
98
}
86
99
}
87
100
88
- impl < I2C : Instance > FMPI2c < I2C > {
101
+ pub trait I2cExt : Sized + Instance {
102
+ fn i2c < ' a > (
103
+ self ,
104
+ pins : ( impl Into < Self :: Scl > , impl Into < Self :: Sda > ) ,
105
+ mode : impl Into < Mode > ,
106
+ ) -> I2c < Self > ;
107
+ }
108
+
109
+ impl < I2C : Instance > I2cExt for I2C {
110
+ fn i2c < ' a > (
111
+ self ,
112
+ pins : ( impl Into < Self :: Scl > , impl Into < Self :: Sda > ) ,
113
+ mode : impl Into < Mode > ,
114
+ ) -> I2c < Self > {
115
+ I2c :: new ( self , pins, mode)
116
+ }
117
+ }
118
+
119
+ impl < I2C : Instance > I2c < I2C > {
89
120
pub fn new (
90
121
i2c : I2C ,
91
122
pins : ( impl Into < I2C :: Scl > , impl Into < I2C :: Sda > ) ,
92
- mode : impl Into < FmpMode > ,
123
+ mode : impl Into < Mode > ,
93
124
) -> Self {
94
125
unsafe {
95
- // NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
96
- let rcc = & ( * RCC :: ptr ( ) ) ;
97
-
98
126
// Enable and reset clock.
99
- I2C :: enable ( rcc) ;
100
- I2C :: reset ( rcc) ;
101
-
102
- I2C :: clock_hsi ( rcc) ;
127
+ I2C :: enable_unchecked ( ) ;
128
+ I2C :: reset_unchecked ( ) ;
103
129
}
104
130
105
131
let pins = ( pins. 0 . into ( ) , pins. 1 . into ( ) ) ;
106
132
107
- let i2c = FMPI2c { i2c, pins } ;
133
+ let i2c = I2c { i2c, pins } ;
108
134
i2c. i2c_init ( mode) ;
109
135
i2c
110
136
}
@@ -114,14 +140,18 @@ impl<I2C: Instance> FMPI2c<I2C> {
114
140
}
115
141
}
116
142
117
- impl < I2C : Instance > FMPI2c < I2C > {
118
- fn i2c_init < M : Into < FmpMode > > ( & self , mode : M ) {
143
+ impl < I2C : Instance > I2c < I2C > {
144
+ fn i2c_init ( & self , mode : impl Into < Mode > ) {
119
145
let mode = mode. into ( ) ;
120
146
use core:: cmp;
121
147
122
148
// Make sure the I2C unit is disabled so we can configure it
123
149
self . i2c . cr1 ( ) . modify ( |_, w| w. pe ( ) . clear_bit ( ) ) ;
124
150
151
+ // NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
152
+ let rcc = unsafe { & ( * RCC :: ptr ( ) ) } ;
153
+ I2C :: clock_hsi ( rcc) ;
154
+
125
155
// Calculate settings for I2C speed modes
126
156
let presc;
127
157
let scldel;
@@ -135,21 +165,21 @@ impl<I2C: Instance> FMPI2c<I2C> {
135
165
// Normal I2C speeds use a different scaling than fast mode below and fast mode+ even more
136
166
// below
137
167
match mode {
138
- FmpMode :: Standard { frequency } => {
168
+ Mode :: Standard { frequency } => {
139
169
presc = 3 ;
140
170
scll = cmp:: max ( ( ( ( FREQ >> presc) >> 1 ) / frequency. raw ( ) ) - 1 , 255 ) as u8 ;
141
171
sclh = scll - 4 ;
142
172
sdadel = 2 ;
143
173
scldel = 4 ;
144
174
}
145
- FmpMode :: Fast { frequency } => {
175
+ Mode :: Fast { frequency } => {
146
176
presc = 1 ;
147
177
scll = cmp:: max ( ( ( ( FREQ >> presc) >> 1 ) / frequency. raw ( ) ) - 1 , 255 ) as u8 ;
148
178
sclh = scll - 6 ;
149
179
sdadel = 2 ;
150
180
scldel = 3 ;
151
181
}
152
- FmpMode :: FastPlus { frequency } => {
182
+ Mode :: FastPlus { frequency } => {
153
183
presc = 0 ;
154
184
scll = cmp:: max ( ( ( ( FREQ >> presc) >> 1 ) / frequency. raw ( ) ) - 4 , 255 ) as u8 ;
155
185
sclh = scll - 2 ;
@@ -171,7 +201,8 @@ impl<I2C: Instance> FMPI2c<I2C> {
171
201
self . i2c . cr1 ( ) . modify ( |_, w| w. pe ( ) . set_bit ( ) ) ;
172
202
}
173
203
174
- fn check_and_clear_error_flags ( & self , isr : & fmpi2c1:: isr:: R ) -> Result < ( ) , Error > {
204
+ #[ inline( always) ]
205
+ fn check_and_clear_error_flags ( & self , isr : & i2c1:: isr:: R ) -> Result < ( ) , Error > {
175
206
// If we received a NACK, then this is an error
176
207
if isr. nackf ( ) . bit_is_set ( ) {
177
208
self . i2c
@@ -183,6 +214,7 @@ impl<I2C: Instance> FMPI2c<I2C> {
183
214
Ok ( ( ) )
184
215
}
185
216
217
+ #[ inline( always) ]
186
218
fn end_transaction ( & self ) -> Result < ( ) , Error > {
187
219
// Check and clear flags if they somehow ended up set
188
220
self . check_and_clear_error_flags ( & self . i2c . isr ( ) . read ( ) )
0 commit comments