@@ -374,6 +374,8 @@ void SERCOM::resetWIRE()
374
374
375
375
void SERCOM::enableWIRE ()
376
376
{
377
+ // Set inactive time-out (prevent bus hang in multi-master set-up)
378
+ sercom->I2CM .CTRLA .bit .INACTOUT = 3 ;
377
379
// I2C Master and Slave modes share the ENABLE bit function.
378
380
379
381
// Enable the I2C master mode
@@ -494,7 +496,13 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
494
496
address = (address << 0x1ul ) | flag;
495
497
496
498
// 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
+ }
498
506
499
507
// Send start and address
500
508
sercom->I2CM .ADDR .bit .ADDR = address;
@@ -506,6 +514,12 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
506
514
{
507
515
// Wait transmission complete
508
516
}
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
+ }
509
523
}
510
524
else // Read mode
511
525
{
@@ -544,9 +558,9 @@ bool SERCOM::sendDataMasterWIRE(uint8_t data)
544
558
// Wait transmission successful
545
559
while (!sercom->I2CM .INTFLAG .bit .MB ) {
546
560
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 ) {
550
564
return false ;
551
565
}
552
566
}
0 commit comments