Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions libraries/Wire/src/Wire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ void TwoWire::setClock(uint32_t clock)
twi_setFrequency(clock);
}

void TwoWire::setTimeoutInMicros(uint32_t timeout)
{
twi_setTimeoutInMicros(timeout);
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)
{
if (isize > 0) {
Expand Down
1 change: 1 addition & 0 deletions libraries/Wire/src/Wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class TwoWire : public Stream
void begin(int);
void end();
void setClock(uint32_t);
void setTimeoutInMicros(uint32_t);
void beginTransmission(uint8_t);
void beginTransmission(int);
uint8_t endTransmission(void);
Expand Down
64 changes: 63 additions & 1 deletion libraries/Wire/src/utility/twi.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <compat/twi.h>
#include "Arduino.h" // for digitalWrite
#include "Arduino.h" // for digitalWrite and micros

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
Expand All @@ -42,6 +42,7 @@ static volatile uint8_t twi_state;
static volatile uint8_t twi_slarw;
static volatile uint8_t twi_sendStop; // should the transaction end with a stop
static volatile uint8_t twi_inRepStart; // in the middle of a repeated start
static volatile uint32_t twi_timeout_us = 0ul;

static void (*twi_onSlaveTransmit)(void);
static void (*twi_onSlaveReceive)(uint8_t*, int);
Expand Down Expand Up @@ -154,7 +155,12 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
}

// wait until twi is ready, become master receiver
uint32_t startMicros = micros();
while(TWI_READY != twi_state){
if((twi_timeout_us > 0ul) && (micros() - startMicros > twi_timeout_us)) {
twi_handleTimeout();
return 0;
}
continue;
}
twi_state = TWI_MRX;
Expand Down Expand Up @@ -193,7 +199,12 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);

// wait for read operation to complete
startMicros = micros();
while(TWI_MRX == twi_state){
if((twi_timeout_us > 0ul) && (micros() - startMicros > twi_timeout_us)) {
twi_handleTimeout();
return 0;
}
continue;
}

Expand Down Expand Up @@ -233,7 +244,12 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
}

// wait until twi is ready, become master transmitter
uint32_t startMicros = micros();
while(TWI_READY != twi_state){
if((twi_timeout_us > 0ul) && (micros() - startMicros > twi_timeout_us)) {
twi_handleTimeout();
return 4;
}
continue;
}
twi_state = TWI_MTX;
Expand Down Expand Up @@ -275,7 +291,12 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs

// wait for write operation to complete
startMicros = micros();
while(wait && (TWI_MTX == twi_state)){
if((twi_timeout_us > 0ul) && (micros() - startMicros > twi_timeout_us)) {
twi_handleTimeout();
return 4;
}
continue;
}

Expand Down Expand Up @@ -373,7 +394,14 @@ void twi_stop(void)

// wait for stop condition to be exectued on bus
// TWINT is not set after a stop condition!
uint32_t counter = 0;
while(TWCR & _BV(TWSTO)){
counter++;
if((twi_timeout_us > 0ul) && (counter >= 25000)) {
twi_handleTimeout();
return;
}

continue;
}

Expand All @@ -396,6 +424,40 @@ void twi_releaseBus(void)
twi_state = TWI_READY;
}

/*
* Function twi_setTimeoutInMicros
* Desc set a global timeout for while loops that we might get stuck in
* Input timeout value in microseconds
* Output none
*/
void twi_setTimeoutInMicros(uint32_t timeout)
{
twi_timeout_us = timeout;
}

/*
* Function twi_handleTimeout
* Desc do this stuff when a while loop here has run for longer than twi_timeout_us microseconds
* Input none
* Output none
*/
void twi_handleTimeout(void)
{
// remember the bitrate register value
uint8_t previous_TWBR = TWBR;

// remember the address register value
uint8_t previous_TWAR = TWBR;

// reset the interface
twi_disable();
twi_init();

// reapply the previous register values
TWAR = previous_TWAR;
TWBR = previous_TWAR;
}

ISR(TWI_vect)
{
switch(TW_STATUS){
Expand Down
2 changes: 2 additions & 0 deletions libraries/Wire/src/utility/twi.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
void twi_reply(uint8_t);
void twi_stop(void);
void twi_releaseBus(void);
void twi_setTimeoutInMicros(uint32_t);
void twi_handleTimeout(void);

#endif