38
38
#include "pins_arduino.h"
39
39
#include "twi.h"
40
40
41
+ #define BUSYWAIT_WITH_TIMEOUT_UNTIL (exit_condition , timedout_label ) \
42
+ do { \
43
+ uint32_t startMillis = millis(); \
44
+ while (!(exit_condition)) { \
45
+ if ((twi_timeout_ms > 0) && (millis() - startMillis > twi_timeout_ms)) { \
46
+ goto timedout_label; \
47
+ } \
48
+ } \
49
+ } while (0)
50
+
51
+ // Same as BUSYWAIT_WITH_TIMEOUT_UNTIL but intended to be used in code
52
+ // executed in interrupt service routines where millis() cannot be used.
53
+ // https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/:
54
+ // "millis() relies on interrupts to count, so it will never increment inside an ISR."
55
+ // TODO: Document calculations behind the 25000 upper counter limit.
56
+ // TODO: Make the upper counter limit reflect the twi_timeout_ms value.
57
+ #define IRS_BUSYWAIT_WITH_TIMEOUT_UNTIL (exit_condition , timedout_label ) \
58
+ do { \
59
+ uint32_t counter = 0; \
60
+ while (!(exit_condition)) { \
61
+ counter++; \
62
+ if ((twi_timeout_ms > 0) && (counter >= 25000)) { \
63
+ goto timedout_label; \
64
+ } \
65
+ } \
66
+ } while (0)
67
+
41
68
static volatile uint8_t twi_state ;
42
69
static volatile uint8_t twi_slarw ;
43
70
static volatile uint8_t twi_sendStop ; // should the transaction end with a stop
@@ -155,17 +182,8 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
155
182
}
156
183
157
184
// wait until twi is ready, become master receiver
158
- uint32_t startMillis = millis ();
159
- while (TWI_READY != twi_state ){
160
- if ((twi_timeout_ms > 0 ) && (millis () - startMillis > twi_timeout_ms )) {
161
- //timeout
162
- twi_disable ();
163
- twi_init ();
164
-
165
- return 0 ;
166
- }
167
- continue ;
168
- }
185
+ BUSYWAIT_WITH_TIMEOUT_UNTIL (twi_state == TWI_READY , waiting_timedout );
186
+
169
187
twi_state = TWI_MRX ;
170
188
twi_sendStop = sendStop ;
171
189
// reset error state (0xFF.. no error occured)
@@ -202,17 +220,7 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
202
220
TWCR = _BV (TWEN ) | _BV (TWIE ) | _BV (TWEA ) | _BV (TWINT ) | _BV (TWSTA );
203
221
204
222
// wait for read operation to complete
205
- startMillis = millis ();
206
- while (TWI_MRX == twi_state ){
207
- if ((twi_timeout_ms > 0 ) && (millis () - startMillis > twi_timeout_ms )) {
208
- //timeout
209
- twi_disable ();
210
- twi_init ();
211
-
212
- return 0 ;
213
- }
214
- continue ;
215
- }
223
+ BUSYWAIT_WITH_TIMEOUT_UNTIL (twi_state != TWI_MRX , waiting_timedout );
216
224
217
225
if (twi_masterBufferIndex < length )
218
226
length = twi_masterBufferIndex ;
@@ -223,6 +231,11 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
223
231
}
224
232
225
233
return length ;
234
+
235
+ waiting_timedout :
236
+ twi_disable ();
237
+ twi_init ();
238
+ return 0 ;
226
239
}
227
240
228
241
/*
@@ -250,17 +263,8 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
250
263
}
251
264
252
265
// wait until twi is ready, become master transmitter
253
- uint32_t startMillis = millis ();
254
- while (TWI_READY != twi_state ){
255
- if ((twi_timeout_ms > 0 ) && (millis () - startMillis > twi_timeout_ms )) {
256
- //timeout
257
- twi_disable ();
258
- twi_init ();
259
-
260
- return 4 ;
261
- }
262
- continue ;
263
- }
266
+ BUSYWAIT_WITH_TIMEOUT_UNTIL (twi_state == TWI_READY , waiting_timedout );
267
+
264
268
twi_state = TWI_MTX ;
265
269
twi_sendStop = sendStop ;
266
270
// reset error state (0xFF.. no error occured)
@@ -300,16 +304,8 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
300
304
TWCR = _BV (TWINT ) | _BV (TWEA ) | _BV (TWEN ) | _BV (TWIE ) | _BV (TWSTA ); // enable INTs
301
305
302
306
// wait for write operation to complete
303
- startMillis = millis ();
304
- while (wait && (TWI_MTX == twi_state )){
305
- if ((twi_timeout_ms > 0 ) && (millis () - startMillis > twi_timeout_ms )) {
306
- //timeout
307
- twi_disable ();
308
- twi_init ();
309
-
310
- return 4 ;
311
- }
312
- continue ;
307
+ if (wait ) {
308
+ BUSYWAIT_WITH_TIMEOUT_UNTIL (twi_state != TWI_MTX , waiting_timedout );
313
309
}
314
310
315
311
if (twi_error == 0xFF )
@@ -320,6 +316,11 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
320
316
return 3 ; // error: data send, nack received
321
317
else
322
318
return 4 ; // other twi error
319
+
320
+ waiting_timedout :
321
+ twi_disable ();
322
+ twi_init ();
323
+ return 4 ;
323
324
}
324
325
325
326
/*
@@ -406,22 +407,14 @@ void twi_stop(void)
406
407
407
408
// wait for stop condition to be exectued on bus
408
409
// TWINT is not set after a stop condition!
409
- uint32_t counter = 0 ;
410
- while (TWCR & _BV (TWSTO )){
411
- counter ++ ;
412
- if ((twi_timeout_ms > 0 ) && (counter >= 25000 )) {
413
- // timeout
414
- twi_disable ();
415
- twi_init ();
416
-
417
- return ;
418
- }
419
-
420
- continue ;
421
- }
410
+ IRS_BUSYWAIT_WITH_TIMEOUT_UNTIL ((TWCR & _BV (TWSTO )) == 0 , waiting_timedout );
422
411
423
412
// update twi state
424
413
twi_state = TWI_READY ;
414
+
415
+ waiting_timedout :
416
+ twi_disable ();
417
+ twi_init ();
425
418
}
426
419
427
420
/*
0 commit comments