From 6c98f9015119bc54a5f72a5081ffe5f0f478f233 Mon Sep 17 00:00:00 2001 From: Neil McKechnie Date: Mon, 15 Nov 2021 14:30:27 +0000 Subject: [PATCH] Reduce I2C interrupt time Reduce the time spent with interrupts disabled in I2CManager response code by enabling interrupts after the state machine has finished. Also, some comment changes. --- I2CManager.h | 7 ++++++- I2CManager_NonBlocking.h | 12 +++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/I2CManager.h b/I2CManager.h index 25ab004..1163261 100644 --- a/I2CManager.h +++ b/I2CManager.h @@ -107,11 +107,16 @@ * the loop() function is called, and may be adequate under some circumstances. * The advantage of NOT using interrupts is that the impact of I2C upon the DCC waveform (when accurate timing mode isn't in use) * becomes almost zero. - * This mechanism is under evaluation and should not be relied upon as yet. * */ +// Uncomment following line to enable Wire library instead of native I2C drivers //#define I2C_USE_WIRE + +// Uncomment following line to disable the use of interrupts by the native I2C drivers. +//#define I2C_NO_INTERRUPTS + +// Default to use interrupts within the native I2C drivers. #ifndef I2C_NO_INTERRUPTS #define I2C_USE_INTERRUPTS #endif diff --git a/I2CManager_NonBlocking.h b/I2CManager_NonBlocking.h index 3bdfc38..112e51e 100644 --- a/I2CManager_NonBlocking.h +++ b/I2CManager_NonBlocking.h @@ -129,6 +129,10 @@ uint8_t I2CManagerClass::read(uint8_t i2cAddress, uint8_t *readBuffer, uint8_t r /*************************************************************************** * checkForTimeout() function, called from isBusy() and wait() to cancel * requests that are taking too long to complete. + * This function doesn't fully work as intended so is not currently called. + * Instead we check for an I2C hang-up and report an error from + * I2CRB::wait(), but we aren't able to recover from the hang-up. Such faults + * may be caused by an I2C wire short for example. ***************************************************************************/ void I2CManagerClass::checkForTimeout() { unsigned long currentMicros = micros(); @@ -163,7 +167,10 @@ void I2CManagerClass::loop() { #if !defined(I2C_USE_INTERRUPTS) handleInterrupt(); #endif - checkForTimeout(); + // Timeout is now reported in I2CRB::wait(), not here. + // I've left the code, commented out, as a reminder to look at this again + // in the future. + //checkForTimeout(); } /*************************************************************************** @@ -175,6 +182,9 @@ void I2CManagerClass::handleInterrupt() { // Update hardware state machine I2C_handleInterrupt(); + // Enable interrupts to minimise effect on other interrupt code + interrupts(); + // Check if current request has completed. If there's a current request // and state isn't active then state contains the completion status of the request. if (state != I2C_STATE_ACTIVE && currentRequest != NULL) {