From 9232f8594bc7bc7602e2dfbde0cb0bb48a7e5a9e Mon Sep 17 00:00:00 2001 From: lahiru Date: Thu, 22 Jan 2026 11:28:36 +0530 Subject: [PATCH] fix(critical): add timeout to DRDY wait functions to prevent infinite hang - waitForLowDRDY() and waitForHighDRDY() now accept timeout_ms parameter (default 1000ms) - Returns false if timeout occurs, true on success - Added _lastOpTimeout flag to track timeout state - Added hasTimeout() public method to check if last operation timed out - Prevents MCU from hanging indefinitely when hardware fails or disconnects --- src/ADS1256.cpp | 37 ++++++++++++++++++++++++++++++------- src/ADS1256.h | 8 ++++++-- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/ADS1256.cpp b/src/ADS1256.cpp index 3372b47..e0f7000 100644 --- a/src/ADS1256.cpp +++ b/src/ADS1256.cpp @@ -19,7 +19,7 @@ //Constructor ADS1256::ADS1256(const int8_t DRDY_pin, const int8_t RESET_pin, const int8_t SYNC_pin, const int8_t CS_pin,float VREF, SPIClass* spi): _spi(spi), - _DRDY_pin(DRDY_pin), _RESET_pin(RESET_pin), _SYNC_pin(SYNC_pin), _CS_pin(CS_pin), _VREF(VREF), _PGA(0) + _DRDY_pin(DRDY_pin), _RESET_pin(RESET_pin), _SYNC_pin(SYNC_pin), _CS_pin(CS_pin), _VREF(VREF), _PGA(0), _lastOpTimeout(false) { pinMode(_DRDY_pin, INPUT); @@ -94,16 +94,39 @@ void ADS1256::InitializeADC() _isAcquisitionRunning = false; //MCU will be waiting to start a continuous acquisition } -void ADS1256::waitForLowDRDY() -{ - while (digitalRead(_DRDY_pin) == HIGH) {} +bool ADS1256::waitForLowDRDY(unsigned long timeout_ms) +{ + unsigned long start = millis(); + while (digitalRead(_DRDY_pin) == HIGH) { + if (millis() - start >= timeout_ms) { + _lastOpTimeout = true; + return false; // Timeout occurred + } + } + return true; // DRDY went low } -void ADS1256::waitForHighDRDY() -{ +bool ADS1256::waitForHighDRDY(unsigned long timeout_ms) +{ #if F_CPU >= 48000000 //Fast MCUs need this protection to wait until DRDY goes high after a conversion - while (digitalRead(_DRDY_pin) == LOW) {} + unsigned long start = millis(); + while (digitalRead(_DRDY_pin) == LOW) { + if (millis() - start >= timeout_ms) { + _lastOpTimeout = true; + return false; // Timeout occurred + } + } +#else + (void)timeout_ms; // Suppress unused parameter warning on slow MCUs #endif + return true; // DRDY went high (or not needed on slow MCUs) +} + +bool ADS1256::hasTimeout() +{ + bool timeout = _lastOpTimeout; + _lastOpTimeout = false; // Clear flag after reading + return timeout; } void ADS1256::stopConversion() //Sending SDATAC to stop the continuous conversion diff --git a/src/ADS1256.h b/src/ADS1256.h index 1ded2e2..8a6f796 100644 --- a/src/ADS1256.h +++ b/src/ADS1256.h @@ -151,12 +151,15 @@ static constexpr int8_t PIN_UNUSED = -1; //Stop AD void stopConversion(); + //Check if last operation timed out waiting for DRDY + bool hasTimeout(); + private: SPIClass* _spi; //Pointer to an SPIClass object -void waitForLowDRDY(); // Block until DRDY is low -void waitForHighDRDY(); // Block until DRDY is high +bool waitForLowDRDY(unsigned long timeout_ms = 1000); // Block until DRDY is low, returns false on timeout +bool waitForHighDRDY(unsigned long timeout_ms = 1000); // Block until DRDY is high, returns false on timeout void updateMUX(uint8_t muxValue); inline void CS_LOW(); inline void CS_HIGH(); @@ -185,5 +188,6 @@ byte _outputBuffer[3]; //3-byte (24-bit) buffer for the fast acquisition - Singl long _outputValue; //Combined value of the _outputBuffer[3] bool _isAcquisitionRunning; //bool that keeps track of the acquisition (running or not) uint8_t _cycle; //Tracks the cycles as the MUX is cycling through the input channels +bool _lastOpTimeout; //Tracks if last DRDY wait timed out }; #endif \ No newline at end of file