Skip to content

Commit 64b6fca

Browse files
authored
I2C rx+tx timeout
1 parent 63366dd commit 64b6fca

File tree

1 file changed

+32
-17
lines changed

1 file changed

+32
-17
lines changed

Diff for: cores/arduino/SERCOM.cpp

+32-17
Original file line numberDiff line numberDiff line change
@@ -524,28 +524,41 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
524524
// Address Transmitted
525525
if ( flag == WIRE_WRITE_FLAG ) // Write mode
526526
{
527-
while( !sercom->I2CM.INTFLAG.bit.MB )
527+
// The loop takes about 100us @ 100kHz baudrate.
528+
// Timeout: 20ms = 10000*2us
529+
for(uint16_t tmr = 10000; tmr; tmr--)
528530
{
531+
if(sercom->I2CM.INTFLAG.bit.MB) // byte is transmitted
532+
{
533+
// Check for loss of arbitration (multiple masters starting communication at the same time)
534+
if(!isBusOwnerWIRE())
535+
{
536+
// Restart communication
537+
sercom->I2CM.ADDR.bit.ADDR = address;
538+
}
539+
else
540+
{
541+
break;
542+
}
543+
}
529544
// Wait transmission complete
530-
}
531-
// Check for loss of arbitration (multiple masters starting communication at the same time)
532-
if(!isBusOwnerWIRE())
533-
{
534-
// Restart communication
535-
startTransmissionWIRE(address >> 1, flag);
545+
delayMicroseconds(2); // wait 2us
536546
}
537547
}
538548
else // Read mode
539549
{
540-
while( !sercom->I2CM.INTFLAG.bit.SB )
550+
// The loop takes about 200us @ 100kHz baudrate.
551+
// Timeout: 20ms = 10000*2us
552+
for(uint16_t tmr = 10000; tmr && !sercom->I2CM.INTFLAG.bit.SB; tmr--)
541553
{
542-
// If the slave NACKS the address, the MB bit will be set.
543-
// In that case, send a stop condition and return false.
544-
if (sercom->I2CM.INTFLAG.bit.MB) {
545-
sercom->I2CM.CTRLB.bit.CMD = 3; // Stop condition
546-
return false;
547-
}
554+
// If the slave NACKS the address, the MB bit will be set.
555+
// In that case, send a stop condition and return false.
556+
if (sercom->I2CM.INTFLAG.bit.MB) {
557+
sercom->I2CM.CTRLB.bit.CMD = 3; // Stop condition
558+
return false;
559+
}
548560
// Wait transmission complete
561+
delayMicroseconds(2); // wait 2us
549562
}
550563

551564
// Clean the 'Slave on Bus' flag, for further usage.
@@ -569,14 +582,16 @@ bool SERCOM::sendDataMasterWIRE(uint8_t data)
569582
//Send data
570583
sercom->I2CM.DATA.bit.DATA = data;
571584

572-
//Wait transmission successful
573-
while(!sercom->I2CM.INTFLAG.bit.MB) {
574-
585+
// Wait transmission successful
586+
// The loop takes about 100us @ 100kHz baudrate.
587+
// Timeout: 20ms = 10000*2us
588+
for(uint16_t tmr = 10000; tmr && !sercom->I2CM.INTFLAG.bit.MB; tmr--) {
575589
// If a bus error occurs, the MB bit may never be set.
576590
// Check the bus error bit and bail if it's set.
577591
if (sercom->I2CM.STATUS.bit.BUSERR) {
578592
return false;
579593
}
594+
delayMicroseconds(2); // wait 2us
580595
}
581596

582597
//Problems on line? nack received?

0 commit comments

Comments
 (0)