17
17
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
18
19
19
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
20
+
21
+ Modified in February, 2019 by MathWorks Inc. to include timeout for I2C read and write operations
20
22
*/
21
23
22
24
#include <math.h>
@@ -59,6 +61,8 @@ static volatile uint8_t twi_rxBufferIndex;
59
61
60
62
static volatile uint8_t twi_error ;
61
63
64
+ static volatile uint32_t twi_timer_count ; // Holds a number as timeout counter and it is increased gradually to trigger timeout
65
+
62
66
/*
63
67
* Function twi_init
64
68
* Desc readys twi pins and sets twi bitrate
@@ -72,9 +76,9 @@ void twi_init(void)
72
76
twi_sendStop = true; // default value
73
77
twi_inRepStart = false;
74
78
75
- // activate internal pullups for twi.
76
- digitalWrite (SDA , 1 );
77
- digitalWrite (SCL , 1 );
79
+ // Deactivate internal pullups for twi.
80
+ digitalWrite (SDA , 0 );
81
+ digitalWrite (SCL , 0 );
78
82
79
83
// initialize twi prescaler and bit rate
80
84
cbi (TWSR , TWPS0 );
@@ -154,7 +158,9 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
154
158
}
155
159
156
160
// wait until twi is ready, become master receiver
161
+ twi_timeout (1 );//Initialize TimeOut counter
157
162
while (TWI_READY != twi_state ){
163
+ if (twi_timeout (0 )) break ;
158
164
continue ;
159
165
}
160
166
twi_state = TWI_MRX ;
@@ -189,11 +195,13 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
189
195
TWCR = _BV (TWINT ) | _BV (TWEA ) | _BV (TWEN ) | _BV (TWIE ); // enable INTs, but not START
190
196
}
191
197
else
192
- // send start condition
193
- TWCR = _BV (TWEN ) | _BV (TWIE ) | _BV (TWEA ) | _BV (TWINT ) | _BV (TWSTA );
198
+ // send start condition
199
+ TWCR = _BV (TWEN ) | _BV (TWIE ) | _BV (TWEA ) | _BV (TWINT ) | _BV (TWSTA );
194
200
195
201
// wait for read operation to complete
202
+ twi_timeout (1 );
196
203
while (TWI_MRX == twi_state ){
204
+ if (twi_timeout (0 )) break ;
197
205
continue ;
198
206
}
199
207
@@ -222,6 +230,8 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
222
230
* 2 .. address send, NACK received
223
231
* 3 .. data send, NACK received
224
232
* 4 .. other twi error (lost bus arbitration, bus error, ..)
233
+ * 32 .. timed out while trying to become Bus Master
234
+ * 64 .. timed out while waiting for data to be sent
225
235
*/
226
236
uint8_t twi_writeTo (uint8_t address , uint8_t * data , uint8_t length , uint8_t wait , uint8_t sendStop )
227
237
{
@@ -233,7 +243,12 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
233
243
}
234
244
235
245
// wait until twi is ready, become master transmitter
246
+ twi_timeout (1 );
236
247
while (TWI_READY != twi_state ){
248
+ if (twi_timeout (0 ))
249
+ {
250
+ return 32 ;
251
+ }
237
252
continue ;
238
253
}
239
254
twi_state = TWI_MTX ;
@@ -271,11 +286,16 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
271
286
TWCR = _BV (TWINT ) | _BV (TWEA ) | _BV (TWEN ) | _BV (TWIE ); // enable INTs, but not START
272
287
}
273
288
else
274
- // send start condition
289
+ // send start condition
275
290
TWCR = _BV (TWINT ) | _BV (TWEA ) | _BV (TWEN ) | _BV (TWIE ) | _BV (TWSTA ); // enable INTs
276
291
277
292
// wait for write operation to complete
293
+ twi_timeout (1 );
278
294
while (wait && (TWI_MTX == twi_state )){
295
+ if (twi_timeout (0 ))
296
+ {
297
+ return 64 ;
298
+ }
279
299
continue ;
280
300
}
281
301
@@ -373,7 +393,9 @@ void twi_stop(void)
373
393
374
394
// wait for stop condition to be exectued on bus
375
395
// TWINT is not set after a stop condition!
396
+ twi_timeout (1 );
376
397
while (TWCR & _BV (TWSTO )){
398
+ if (twi_timeout (0 )) return ;
377
399
continue ;
378
400
}
379
401
@@ -396,7 +418,39 @@ void twi_releaseBus(void)
396
418
twi_state = TWI_READY ;
397
419
}
398
420
399
- ISR (TWI_vect )
421
+ /*
422
+ * Function twi_timeout
423
+ * Desc Increases the counter in a loop
424
+ * and if it reaches a maximum value,
425
+ the hardware is initialized and
426
+ the function returns true
427
+ * Input isInitializationRequired: If 1 the
428
+ timer resets the counter
429
+ * Output 1 Timeout occurred
430
+ * 0 No timeout occurred
431
+ */
432
+
433
+ uint8_t twi_timeout (uint8_t isInitializationRequired )
434
+ {
435
+ if (isInitializationRequired )
436
+ {
437
+ // reset the timeout counter
438
+ twi_timer_count = 0 ;
439
+ }
440
+ else
441
+ {
442
+ twi_timer_count ++ ;
443
+ }
444
+ if (twi_timer_count >=10000UL ) {
445
+ twi_timer_count = 0 ;
446
+ // reinitialize the hardware
447
+ twi_init ();
448
+ return 1 ;
449
+ }
450
+ return 0 ;
451
+ }
452
+
453
+ SIGNAL (TWI_vect )
400
454
{
401
455
switch (TW_STATUS ){
402
456
// All Master
@@ -558,4 +612,3 @@ ISR(TWI_vect)
558
612
break ;
559
613
}
560
614
}
561
-
0 commit comments