From 63366dddd6a6152187aa76971262fc5def1467a1 Mon Sep 17 00:00:00 2001
From: Andreas Watterott <1488433+awatterott@users.noreply.github.com>
Date: Sun, 28 Mar 2021 16:56:27 +0200
Subject: [PATCH 1/2] check I2C baudrate prescaler range

---
 cores/arduino/SERCOM.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp
index b9fbf05b9..bb7829188 100644
--- a/cores/arduino/SERCOM.cpp
+++ b/cores/arduino/SERCOM.cpp
@@ -458,7 +458,12 @@ void SERCOM::initMasterWIRE( uint32_t baudrate )
 //  sercom->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR ;
 
   // Synchronous arithmetic baudrate
-  sercom->I2CM.BAUD.bit.BAUD = SystemCoreClock / ( 2 * baudrate) - 5 - (((SystemCoreClock / 1000000) * WIRE_RISE_TIME_NANOSECONDS) / (2 * 1000));
+  baudrate = SystemCoreClock / ( 2 * baudrate) - 5 - (((SystemCoreClock / 1000000) * WIRE_RISE_TIME_NANOSECONDS) / (2 * 1000));
+  if(baudrate > 255) // I2C baud rate is 8bit
+  {
+    baudrate = 255;
+  }
+  sercom->I2CM.BAUD.bit.BAUD = baudrate;
 }
 
 void SERCOM::prepareNackBitWIRE( void )

From 64b6fca042eb2d72834af3c8e37ea9bf353ccfc3 Mon Sep 17 00:00:00 2001
From: Andreas Watterott <1488433+awatterott@users.noreply.github.com>
Date: Sun, 28 Mar 2021 17:01:33 +0200
Subject: [PATCH 2/2] I2C rx+tx timeout

---
 cores/arduino/SERCOM.cpp | 49 ++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp
index bb7829188..77f497017 100644
--- a/cores/arduino/SERCOM.cpp
+++ b/cores/arduino/SERCOM.cpp
@@ -524,28 +524,41 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
   // Address Transmitted
   if ( flag == WIRE_WRITE_FLAG ) // Write mode
   {
-    while( !sercom->I2CM.INTFLAG.bit.MB )
+    // The loop takes about 100us @ 100kHz baudrate.
+    // Timeout: 20ms = 10000*2us
+    for(uint16_t tmr = 10000; tmr; tmr--)
     {
+      if(sercom->I2CM.INTFLAG.bit.MB) // byte is transmitted
+      {
+        // Check for loss of arbitration (multiple masters starting communication at the same time)
+        if(!isBusOwnerWIRE())
+        {
+          // Restart communication
+          sercom->I2CM.ADDR.bit.ADDR = address;
+        }
+        else
+        {
+          break;
+        }
+      }
       // Wait transmission complete
-    }
-    // Check for loss of arbitration (multiple masters starting communication at the same time)
-    if(!isBusOwnerWIRE())
-    {
-      // Restart communication
-      startTransmissionWIRE(address >> 1, flag);
+      delayMicroseconds(2); // wait 2us
     }
   }
   else  // Read mode
   {
-    while( !sercom->I2CM.INTFLAG.bit.SB )
+    // The loop takes about 200us @ 100kHz baudrate.
+    // Timeout: 20ms = 10000*2us
+    for(uint16_t tmr = 10000; tmr && !sercom->I2CM.INTFLAG.bit.SB; tmr--)
     {
-        // If the slave NACKS the address, the MB bit will be set.
-        // In that case, send a stop condition and return false.
-        if (sercom->I2CM.INTFLAG.bit.MB) {
-            sercom->I2CM.CTRLB.bit.CMD = 3; // Stop condition
-            return false;
-        }
+      // If the slave NACKS the address, the MB bit will be set.
+      // In that case, send a stop condition and return false.
+      if (sercom->I2CM.INTFLAG.bit.MB) {
+        sercom->I2CM.CTRLB.bit.CMD = 3; // Stop condition
+        return false;
+      }
       // Wait transmission complete
+      delayMicroseconds(2); // wait 2us
     }
 
     // Clean the 'Slave on Bus' flag, for further usage.
@@ -569,14 +582,16 @@ bool SERCOM::sendDataMasterWIRE(uint8_t data)
   //Send data
   sercom->I2CM.DATA.bit.DATA = data;
 
-  //Wait transmission successful
-  while(!sercom->I2CM.INTFLAG.bit.MB) {
-
+  // Wait transmission successful
+  // The loop takes about 100us @ 100kHz baudrate.
+  // Timeout: 20ms = 10000*2us
+  for(uint16_t tmr = 10000; tmr && !sercom->I2CM.INTFLAG.bit.MB; tmr--) {
     // If a bus error occurs, the MB bit may never be set.
     // Check the bus error bit and bail if it's set.
     if (sercom->I2CM.STATUS.bit.BUSERR) {
       return false;
     }
+    delayMicroseconds(2); // wait 2us
   }
 
   //Problems on line? nack received?