Skip to content

Commit 8b79ff5

Browse files
kb-kb-
kb-
authored and
kb-
committed
handle multi-master arbitration loss
seems to be too many "NACK on transmit of address" (1 for 2 ok transfers)
1 parent 2facbf6 commit 8b79ff5

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

Diff for: cores/arduino/SERCOM.cpp

+18-4
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,8 @@ void SERCOM::resetWIRE()
374374

375375
void SERCOM::enableWIRE()
376376
{
377+
// Set inactive time-out (prevent bus hang in multi-master set-up)
378+
sercom->I2CM.CTRLA.bit.INACTOUT = 3 ;
377379
// I2C Master and Slave modes share the ENABLE bit function.
378380

379381
// Enable the I2C master mode
@@ -494,7 +496,13 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
494496
address = (address << 0x1ul) | flag;
495497

496498
// Wait idle or owner bus mode
497-
while ( !isBusIdleWIRE() && !isBusOwnerWIRE() );
499+
while ( !isBusIdleWIRE() && !isBusOwnerWIRE() )
500+
{
501+
// Check the bus error bit and the arbitration loss bit, restart if set.
502+
if (sercom->I2CM.STATUS.bit.ARBLOST) {
503+
return false;
504+
}
505+
}
498506

499507
// Send start and address
500508
sercom->I2CM.ADDR.bit.ADDR = address;
@@ -506,6 +514,12 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
506514
{
507515
// Wait transmission complete
508516
}
517+
// Check for loss of arbitration (multiple masters starting communication at the same time)
518+
if(!isBusOwnerWIRE())
519+
{
520+
// Restart communication
521+
startTransmissionWIRE(address >> 1, flag);
522+
}
509523
}
510524
else // Read mode
511525
{
@@ -544,9 +558,9 @@ bool SERCOM::sendDataMasterWIRE(uint8_t data)
544558
//Wait transmission successful
545559
while(!sercom->I2CM.INTFLAG.bit.MB) {
546560

547-
// If a bus error occurs, the MB bit may never be set.
548-
// Check the bus error bit and bail if it's set.
549-
if (sercom->I2CM.STATUS.bit.BUSERR) {
561+
// If a bus error or loss of arbitration occurs, the MB bit may never be set.
562+
// Check the bus error bit and the arbitration loss bit, bail if set.
563+
if (sercom->I2CM.STATUS.bit.BUSERR || sercom->I2CM.STATUS.bit.ARBLOST) {
550564
return false;
551565
}
552566
}

0 commit comments

Comments
 (0)