Skip to content

I2C/Wire library: changes for issue #42 #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 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(uint16_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(uint16_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 uint16_t twi_timeout_us = 0;

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 > 0) && (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 > 0) && (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 > 0) && (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 > 0) && (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 > 0) && (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(uint16_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(uint16_t);
void twi_handleTimeout(void);

#endif