1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-23 12:51:24 +01:00

Add option to suppress I2C retries.

I2CRB method suppressRetries() added to allow retries to be suppressed.
This commit is contained in:
Neil McKechnie 2023-01-14 18:58:06 +00:00
parent 6e69df2da8
commit 538519dd9d
4 changed files with 29 additions and 7 deletions

View File

@ -81,8 +81,13 @@ void I2CManagerClass::forceClock(uint32_t speed) {
// Check if specified I2C address is responding (blocking operation)
// Returns I2C_STATUS_OK (0) if OK, or error code.
// Suppress retries. If it doesn't respond first time it's out of the running.
uint8_t I2CManagerClass::checkAddress(uint8_t address) {
return write(address, NULL, 0);
I2CRB rb;
rb.setWriteParams(address, NULL, 0);
rb.suppressRetries(true);
queueRequest(&rb);
return rb.wait();
}
@ -244,3 +249,9 @@ void I2CRB::setWriteParams(uint8_t i2cAddress, const uint8_t *writeBuffer, uint8
this->status = I2C_STATUS_OK;
}
void I2CRB::suppressRetries(bool suppress) {
if (suppress)
this->operation |= OPERATION_NORETRY;
else
this->operation &= ~OPERATION_NORETRY;
}

View File

@ -157,6 +157,8 @@ typedef enum : uint8_t
OPERATION_REQUEST = 2,
OPERATION_SEND = 3,
OPERATION_SEND_P = 4,
OPERATION_NORETRY = 0x80, // OR with operation to suppress retries.
OPERATION_MASK = 0x7f, // mask for extracting the operation code
} OperationEnum;
@ -178,6 +180,7 @@ public:
void setReadParams(uint8_t i2cAddress, uint8_t *readBuffer, uint8_t readLen);
void setRequestParams(uint8_t i2cAddress, uint8_t *readBuffer, uint8_t readLen, const uint8_t *writeBuffer, uint8_t writeLen);
void setWriteParams(uint8_t i2cAddress, const uint8_t *writeBuffer, uint8_t writeLen);
void suppressRetries(bool suppress);
uint8_t writeLen;
uint8_t readLen;

View File

@ -105,7 +105,7 @@ void I2CManagerClass::startTransaction() {
currentRequest = queueHead;
rxCount = txCount = 0;
// Copy key fields to static data for speed.
operation = currentRequest->operation;
operation = currentRequest->operation & OPERATION_MASK;
// Start the I2C process going.
I2C_sendStart();
startTime = micros();
@ -227,8 +227,10 @@ void I2CManagerClass::handleInterrupt() {
// and state isn't active then state contains the completion status of the request.
if (state != I2C_STATE_ACTIVE && currentRequest != NULL) {
// Operation has completed.
if (state == I2C_STATUS_OK || ++retryCounter > MAX_I2C_RETRIES) {
// Status is OK, or has failed and retry count exceeded.
if (state == I2C_STATUS_OK || ++retryCounter > MAX_I2C_RETRIES
|| currentRequest->operation & OPERATION_NORETRY)
{
// Status is OK, or has failed and retry count exceeded, or retries disabled.
// Remove completed request from head of queue
I2CRB * t = queueHead;
if (t == currentRequest) {

View File

@ -51,11 +51,14 @@ void I2CManagerClass::_setClock(unsigned long i2cClockSpeed) {
uint8_t I2CManagerClass::write(uint8_t address, const uint8_t buffer[], uint8_t size, I2CRB *rb) {
uint8_t status = I2C_STATUS_OK;
uint8_t retryCount = 0;
// If request fails, retry up to the defined limit, unless the NORETRY flag is set
// in the request block.
do {
Wire.beginTransmission(address);
if (size > 0) Wire.write(buffer, size);
status = Wire.endTransmission();
} while (!(status == I2C_STATUS_OK || ++retryCount > MAX_I2C_RETRIES));
} while (!(status == I2C_STATUS_OK || ++retryCount > MAX_I2C_RETRIES
|| rb->operation & OPERATION_NORETRY));
rb->status = status;
return I2C_STATUS_OK;
}
@ -81,6 +84,8 @@ uint8_t I2CManagerClass::read(uint8_t address, uint8_t readBuffer[], uint8_t rea
uint8_t status = I2C_STATUS_OK;
uint8_t nBytes = 0;
uint8_t retryCount = 0;
// If request fails, retry up to the defined limit, unless the NORETRY flag is set
// in the request block.
do {
if (writeSize > 0) {
Wire.beginTransmission(address);
@ -93,7 +98,8 @@ uint8_t I2CManagerClass::read(uint8_t address, uint8_t readBuffer[], uint8_t rea
readBuffer[nBytes++] = Wire.read();
if (nBytes < readSize) status = I2C_STATUS_TRUNCATED;
}
} while (!(status == I2C_STATUS_OK || ++retryCount > MAX_I2C_RETRIES));
} while (!(status == I2C_STATUS_OK || ++retryCount > MAX_I2C_RETRIES
|| rb->operation & OPERATION_NORETRY));
rb->nBytes = nBytes;
rb->status = status;
@ -109,7 +115,7 @@ uint8_t I2CManagerClass::read(uint8_t address, uint8_t readBuffer[], uint8_t rea
* the non-blocking version.
***************************************************************************/
void I2CManagerClass::queueRequest(I2CRB *req) {
switch (req->operation) {
switch (req->operation & OPERATION_MASK) {
case OPERATION_READ:
read(req->i2cAddress, req->readBuffer, req->readLen, NULL, 0, req);
break;