Skip to content

Commit 282faf0

Browse files
committed
Reduce code duplication with BUSYWAIT_WITH_TIMEOUT_UNTIL macro
1 parent 7fcb4d4 commit 282faf0

File tree

1 file changed

+49
-56
lines changed
  • libraries/Wire/src/utility

1 file changed

+49
-56
lines changed

libraries/Wire/src/utility/twi.c

Lines changed: 49 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,33 @@
3838
#include "pins_arduino.h"
3939
#include "twi.h"
4040

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+
4168
static volatile uint8_t twi_state;
4269
static volatile uint8_t twi_slarw;
4370
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
155182
}
156183

157184
// 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+
169187
twi_state = TWI_MRX;
170188
twi_sendStop = sendStop;
171189
// 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
202220
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
203221

204222
// 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);
216224

217225
if (twi_masterBufferIndex < length)
218226
length = twi_masterBufferIndex;
@@ -223,6 +231,11 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
223231
}
224232

225233
return length;
234+
235+
waiting_timedout:
236+
twi_disable();
237+
twi_init();
238+
return 0;
226239
}
227240

228241
/*
@@ -250,17 +263,8 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
250263
}
251264

252265
// 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+
264268
twi_state = TWI_MTX;
265269
twi_sendStop = sendStop;
266270
// 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
300304
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
301305

302306
// 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);
313309
}
314310

315311
if (twi_error == 0xFF)
@@ -320,6 +316,11 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
320316
return 3; // error: data send, nack received
321317
else
322318
return 4; // other twi error
319+
320+
waiting_timedout:
321+
twi_disable();
322+
twi_init();
323+
return 4;
323324
}
324325

325326
/*
@@ -406,22 +407,14 @@ void twi_stop(void)
406407

407408
// wait for stop condition to be exectued on bus
408409
// 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);
422411

423412
// update twi state
424413
twi_state = TWI_READY;
414+
415+
waiting_timedout:
416+
twi_disable();
417+
twi_init();
425418
}
426419

427420
/*

0 commit comments

Comments
 (0)