Skip to content

Commit bdf0c84

Browse files
authored
Merge pull request #227 from OPEnSLab-OSU/master
Fix I2C SERCOM Hang (from Arduino SAMD core)
2 parents 52d793e + dad77cd commit bdf0c84

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

cores/arduino/SERCOM.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,18 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
537537
// 7-bits address + 1-bits R/W
538538
address = (address << 0x1ul) | flag;
539539

540-
// Wait idle or owner bus mode
541-
while ( !isBusIdleWIRE() && !isBusOwnerWIRE() );
540+
// If another master owns the bus or the last bus owner has not properly
541+
// sent a stop, return failure early. This will prevent some misbehaved
542+
// devices from deadlocking here at the cost of the caller being responsible
543+
// for retrying the failed transmission. See SercomWireBusState for the
544+
// possible bus states.
545+
if(!isBusOwnerWIRE())
546+
{
547+
if( isBusBusyWIRE() || (isArbLostWIRE() && !isBusIdleWIRE()) || isBusUnknownWIRE() )
548+
{
549+
return false;
550+
}
551+
}
542552

543553
// Send start and address
544554
sercom->I2CM.ADDR.bit.ADDR = address;
@@ -634,6 +644,21 @@ bool SERCOM::isBusOwnerWIRE( void )
634644
return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_OWNER_STATE;
635645
}
636646

647+
bool SERCOM::isBusUnknownWIRE( void )
648+
{
649+
return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_UNKNOWN_STATE;
650+
}
651+
652+
bool SERCOM::isArbLostWIRE( void )
653+
{
654+
return sercom->I2CM.STATUS.bit.ARBLOST == 1;
655+
}
656+
657+
bool SERCOM::isBusBusyWIRE( void )
658+
{
659+
return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_BUSY_STATE;
660+
}
661+
637662
bool SERCOM::isDataReadyWIRE( void )
638663
{
639664
return sercom->I2CS.INTFLAG.bit.DRDY;

cores/arduino/SERCOM.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ class SERCOM
225225
bool isSlaveWIRE( void ) ;
226226
bool isBusIdleWIRE( void ) ;
227227
bool isBusOwnerWIRE( void ) ;
228+
bool isBusUnknownWIRE( void ) ;
229+
bool isArbLostWIRE( void );
230+
bool isBusBusyWIRE( void );
228231
bool isDataReadyWIRE( void ) ;
229232
bool isStopDetectedWIRE( void ) ;
230233
bool isRestartDetectedWIRE( void ) ;

0 commit comments

Comments
 (0)