From dad77cd8cc2c767f51aeacda868ce54df111cf02 Mon Sep 17 00:00:00 2001 From: Noah Laptop Date: Thu, 28 May 2020 17:20:30 -0700 Subject: [PATCH] add SERCOM patch from arduino SAMD core --- cores/arduino/SERCOM.cpp | 29 +++++++++++++++++++++++++++-- cores/arduino/SERCOM.h | 3 +++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index d993ca040..9a75730fd 100644 --- a/cores/arduino/SERCOM.cpp +++ b/cores/arduino/SERCOM.cpp @@ -537,8 +537,18 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag // 7-bits address + 1-bits R/W address = (address << 0x1ul) | flag; - // Wait idle or owner bus mode - while ( !isBusIdleWIRE() && !isBusOwnerWIRE() ); + // If another master owns the bus or the last bus owner has not properly + // sent a stop, return failure early. This will prevent some misbehaved + // devices from deadlocking here at the cost of the caller being responsible + // for retrying the failed transmission. See SercomWireBusState for the + // possible bus states. + if(!isBusOwnerWIRE()) + { + if( isBusBusyWIRE() || (isArbLostWIRE() && !isBusIdleWIRE()) || isBusUnknownWIRE() ) + { + return false; + } + } // Send start and address sercom->I2CM.ADDR.bit.ADDR = address; @@ -634,6 +644,21 @@ bool SERCOM::isBusOwnerWIRE( void ) return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_OWNER_STATE; } +bool SERCOM::isBusUnknownWIRE( void ) +{ + return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_UNKNOWN_STATE; +} + +bool SERCOM::isArbLostWIRE( void ) +{ + return sercom->I2CM.STATUS.bit.ARBLOST == 1; +} + +bool SERCOM::isBusBusyWIRE( void ) +{ + return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_BUSY_STATE; +} + bool SERCOM::isDataReadyWIRE( void ) { return sercom->I2CS.INTFLAG.bit.DRDY; diff --git a/cores/arduino/SERCOM.h b/cores/arduino/SERCOM.h index 4b392989e..b60c245f9 100644 --- a/cores/arduino/SERCOM.h +++ b/cores/arduino/SERCOM.h @@ -225,6 +225,9 @@ class SERCOM bool isSlaveWIRE( void ) ; bool isBusIdleWIRE( void ) ; bool isBusOwnerWIRE( void ) ; + bool isBusUnknownWIRE( void ) ; + bool isArbLostWIRE( void ); + bool isBusBusyWIRE( void ); bool isDataReadyWIRE( void ) ; bool isStopDetectedWIRE( void ) ; bool isRestartDetectedWIRE( void ) ;