Added a timeout value to the TWI_StartTransmission() function, within which the addressed device must respond.

Fixed TWI_StartTransmission() corrupting the contents of the GPIOR0 register.
pull/1469/head
Dean Camera 15 years ago
parent 14a5a94084
commit c0c982df7a

@ -56,6 +56,7 @@
#include <avr/io.h> #include <avr/io.h>
#include <stdbool.h> #include <stdbool.h>
#include <util/twi.h> #include <util/twi.h>
#include <util/delay.h>
/* Enable C linkage for C++ Compilers: */ /* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus) #if defined(__cplusplus)
@ -131,10 +132,11 @@
/** Begins a master mode TWI bus communication with the given slave device address. /** Begins a master mode TWI bus communication with the given slave device address.
* *
* \param[in] SlaveAddress Address of the slave TWI device to communicate with * \param[in] SlaveAddress Address of the slave TWI device to communicate with
* \param[in] TimeoutMS Timeout period within which the slave must respond, in milliseconds
* *
* \return Boolean true if the device is ready for data, false otherwise * \return Boolean true if the device is ready for data, false otherwise
*/ */
bool TWI_StartTransmission(uint8_t SlaveAddress); bool TWI_StartTransmission(uint8_t SlaveAddress, uint8_t TimeoutMS);
/* Disable C linkage for C++ Compilers: */ /* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus) #if defined(__cplusplus)

@ -7,39 +7,58 @@
#include "TWI.h" #include "TWI.h"
bool TWI_StartTransmission(uint8_t SlaveAddress) bool TWI_StartTransmission(uint8_t SlaveAddress, uint8_t TimeoutMS)
{ {
for (;;) for (;;)
{ {
uint8_t IterationsRemaining = 50; bool BusCaptured = false;
bool BusCaptured = false; uint16_t TimeoutRemaining;
while (IterationsRemaining-- && !BusCaptured) TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
{
TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
while (!(TWCR & (1 << TWINT)));
switch (TWSR & TW_STATUS_MASK) TimeoutRemaining = (TimeoutMS * 100);
while (TimeoutRemaining-- && !BusCaptured)
{
if (TWCR & (1 << TWINT))
{ {
case TW_START: switch (TWSR & TW_STATUS_MASK)
case TW_REP_START: {
BusCaptured = true; case TW_START:
break; case TW_REP_START:
case TW_MT_ARB_LOST: BusCaptured = true;
continue; break;
default: case TW_MT_ARB_LOST:
return false; TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
continue;
default:
TWCR = (1 << TWEN);
return false;
}
} }
_delay_us(10);
} }
if (!(BusCaptured)) if (!(BusCaptured))
return false; {
TWCR = (1 << TWEN);
return false;
}
TWDR = SlaveAddress; TWDR = SlaveAddress;
TWCR = ((1 << TWINT) | (1 << TWEN)); TWCR = ((1 << TWINT) | (1 << TWEN));
while (!(TWCR & (1 << TWINT)));
GPIOR0 = (TWSR & TW_STATUS_MASK); TimeoutRemaining = (TimeoutMS * 100);
while (TimeoutRemaining--)
{
if (TWCR & (1 << TWINT))
break;
_delay_us(10);
}
if (!(TimeoutRemaining))
return false;
switch (TWSR & TW_STATUS_MASK) switch (TWSR & TW_STATUS_MASK)
{ {

@ -15,9 +15,11 @@
* - AVRISP programmer project now has a more robust timeout system, allowing for a doubling of the software USART speed * - AVRISP programmer project now has a more robust timeout system, allowing for a doubling of the software USART speed
* for PDI and TPI programming * for PDI and TPI programming
* - Increased the speed of both software and hardware TPI/PDI programming modes of the AVRISP project * - Increased the speed of both software and hardware TPI/PDI programming modes of the AVRISP project
* - Added a timeout value to the TWI_StartTransmission() function, within which the addressed device must respond
* *
* <b>Fixed:</b> * <b>Fixed:</b>
* - Fixed software PDI/TPI programming mode in the AVRISP project not correctly toggling just the clock pin * - Fixed software PDI/TPI programming mode in the AVRISP project not correctly toggling just the clock pin
* - Fixed TWI_StartTransmission() corrupting the contents of the GPIOR0 register
* *
* \section Sec_ChangeLog100219 Version 100219 * \section Sec_ChangeLog100219 Version 100219
* *

@ -12,8 +12,11 @@
* *
* \section Sec_MigrationXXXXXX Migrating from 100219 to XXXXXX * \section Sec_MigrationXXXXXX Migrating from 100219 to XXXXXX
* *
* <b>Non-USB Library Components</b>
* - The \ref TWI_StartTransmission() function now takes in a timeout period, expressed in milliseconds, within which the addressed
* device must respond or the function will abort.
*
* \section Sec_Migration100219 Migrating from 091223 to 100219 * \section Sec_Migration100219 Migrating from 091223 to 100219
* - (None)
* *
* <b>Non-USB Library Components</b> * <b>Non-USB Library Components</b>
* - Due to some ADC channels not being identical to their ADC MUX selection masks for single-ended conversions on some AVR models, * - Due to some ADC channels not being identical to their ADC MUX selection masks for single-ended conversions on some AVR models,

@ -21,7 +21,7 @@ void DS1307_SetDate(uint8_t Day, uint8_t Month, uint8_t Year)
CurrentRTCDate.Byte3.TenYear = (Year / 10); CurrentRTCDate.Byte3.TenYear = (Year / 10);
CurrentRTCDate.Byte3.Year = (Year % 10); CurrentRTCDate.Byte3.Year = (Year % 10);
if (TWI_StartTransmission(DS1307_ADDRESS_WRITE)) if (TWI_StartTransmission(DS1307_ADDRESS_WRITE, 10))
{ {
TWI_SendByte(DS1307_DATEREG_START); TWI_SendByte(DS1307_DATEREG_START);
TWI_SendByte(CurrentRTCDate.Byte1.IntVal); TWI_SendByte(CurrentRTCDate.Byte1.IntVal);
@ -48,7 +48,7 @@ void DS1307_SetTime(uint8_t Hour, uint8_t Minute, uint8_t Second)
CurrentRTCTime.Byte3.Hour = (Hour % 10); CurrentRTCTime.Byte3.Hour = (Hour % 10);
CurrentRTCTime.Byte3.TwelveHourMode = false; CurrentRTCTime.Byte3.TwelveHourMode = false;
if (TWI_StartTransmission(DS1307_ADDRESS_WRITE)) if (TWI_StartTransmission(DS1307_ADDRESS_WRITE, 10))
{ {
TWI_SendByte(DS1307_TIMEREG_START); TWI_SendByte(DS1307_TIMEREG_START);
TWI_SendByte(CurrentRTCTime.Byte1.IntVal); TWI_SendByte(CurrentRTCTime.Byte1.IntVal);
@ -68,7 +68,7 @@ void DS1307_GetDate(uint8_t* Day, uint8_t* Month, uint8_t* Year)
return; return;
#endif #endif
if (TWI_StartTransmission(DS1307_ADDRESS_WRITE)) if (TWI_StartTransmission(DS1307_ADDRESS_WRITE, 10))
{ {
TWI_SendByte(DS1307_DATEREG_START); TWI_SendByte(DS1307_DATEREG_START);
@ -77,7 +77,7 @@ void DS1307_GetDate(uint8_t* Day, uint8_t* Month, uint8_t* Year)
DS1307_DateRegs_t CurrentRTCDate; DS1307_DateRegs_t CurrentRTCDate;
if (TWI_StartTransmission(DS1307_ADDRESS_READ)) if (TWI_StartTransmission(DS1307_ADDRESS_READ, 10))
{ {
TWI_ReceiveByte(&CurrentRTCDate.Byte1.IntVal, false); TWI_ReceiveByte(&CurrentRTCDate.Byte1.IntVal, false);
TWI_ReceiveByte(&CurrentRTCDate.Byte2.IntVal, false); TWI_ReceiveByte(&CurrentRTCDate.Byte2.IntVal, false);
@ -100,7 +100,7 @@ void DS1307_GetTime(uint8_t* Hour, uint8_t* Minute, uint8_t* Second)
return; return;
#endif #endif
if (TWI_StartTransmission(DS1307_ADDRESS_WRITE)) if (TWI_StartTransmission(DS1307_ADDRESS_WRITE, 10))
{ {
TWI_SendByte(DS1307_TIMEREG_START); TWI_SendByte(DS1307_TIMEREG_START);
@ -109,7 +109,7 @@ void DS1307_GetTime(uint8_t* Hour, uint8_t* Minute, uint8_t* Second)
DS1307_TimeRegs_t CurrentRTCTime; DS1307_TimeRegs_t CurrentRTCTime;
if (TWI_StartTransmission(DS1307_ADDRESS_READ)) if (TWI_StartTransmission(DS1307_ADDRESS_READ, 10))
{ {
TWI_ReceiveByte(&CurrentRTCTime.Byte1.IntVal, false); TWI_ReceiveByte(&CurrentRTCTime.Byte1.IntVal, false);
TWI_ReceiveByte(&CurrentRTCTime.Byte2.IntVal, false); TWI_ReceiveByte(&CurrentRTCTime.Byte2.IntVal, false);

@ -193,7 +193,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources # Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) $(LUFA_OPTS) CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) $(LUFA_OPTS)
CDEFS += -DDUMMY_RTC #CDEFS += -DDUMMY_RTC
# Place -D or -U options here for ASM sources # Place -D or -U options here for ASM sources

Loading…
Cancel
Save