13
13
* See the License for the specific language governing permissions and
14
14
* limitations under the License.
15
15
*/
16
+
16
17
#include " drivers/I2C.h"
18
+ #include " drivers/DigitalInOut.h"
19
+ #include " platform/mbed_wait_api.h"
17
20
18
21
#if DEVICE_I2C
19
22
@@ -32,13 +35,15 @@ I2C::I2C(PinName sda, PinName scl) :
32
35
#endif
33
36
_i2c (), _hz(100000 )
34
37
{
35
- // No lock needed in the constructor
36
-
38
+ lock ();
37
39
// The init function also set the frequency to 100000
38
- i2c_init (&_i2c, sda, scl);
39
-
40
+ _sda = sda;
41
+ _scl = scl;
42
+ recover (sda, scl);
43
+ i2c_init (&_i2c, _sda, _scl);
40
44
// Used to avoid unnecessary frequency updates
41
45
_owner = this ;
46
+ unlock ();
42
47
}
43
48
44
49
void I2C::frequency (int hz)
@@ -135,6 +140,53 @@ void I2C::unlock()
135
140
_mutex->unlock ();
136
141
}
137
142
143
+ int I2C::recover (PinName sda, PinName scl)
144
+ {
145
+ DigitalInOut pin_sda (sda, PIN_INPUT, PullNone, 1 );
146
+ DigitalInOut pin_scl (scl, PIN_INPUT, PullNone, 1 );
147
+
148
+ // Read and verify if recovery is required
149
+ if (pin_scl == 1 ) {
150
+ if (pin_sda == 1 ) {
151
+ // Return successfuly as SDA and SCL is high
152
+ return 0 ;
153
+ }
154
+ } else {
155
+ // Return as SCL is low and no access to become master.
156
+ return I2C_ERROR_BUS_BUSY;
157
+ }
158
+
159
+ // Send clock pulses, for device to recover 9
160
+ pin_scl.mode (PullNone);
161
+ pin_scl.output ();
162
+ int count = 9 ;
163
+ while (count--) {
164
+ pin_scl.mode (PullNone);
165
+ pin_scl = 0 ;
166
+ wait_us (5 );
167
+ pin_scl.mode (PullUp);
168
+ pin_scl = 1 ;
169
+ wait_us (5 );
170
+ }
171
+
172
+ // Send Stop
173
+ pin_sda.output ();
174
+ pin_sda = 0 ;
175
+ wait_us (5 );
176
+ pin_scl = 1 ;
177
+ wait_us (5 );
178
+ pin_sda = 1 ;
179
+ wait_us (5 );
180
+
181
+ pin_sda.input ();
182
+ pin_scl.input ();
183
+ if ((pin_scl == 0 ) || (pin_sda == 0 )) {
184
+ // Return as SCL is low and no access to become master.
185
+ return I2C_ERROR_BUS_BUSY;
186
+ }
187
+ return 0 ;
188
+ }
189
+
138
190
#if DEVICE_I2C_ASYNCH
139
191
140
192
int I2C::transfer (int address, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, const event_callback_t &callback, int event, bool repeated)
@@ -169,10 +221,10 @@ void I2C::irq_handler_asynch(void)
169
221
if (_callback && event) {
170
222
_callback.call (event);
171
223
}
224
+
172
225
if (event) {
173
226
unlock_deep_sleep ();
174
227
}
175
-
176
228
}
177
229
178
230
void I2C::lock_deep_sleep ()
0 commit comments