1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-01-11 13:21:01 +01:00

Remove blocking behaviour?

This commit is contained in:
travis-farmer 2024-11-30 05:41:29 -05:00
parent 9e5b864055
commit a85fa6d9c2
No known key found for this signature in database
GPG Key ID: 0BC296791D14CB35
2 changed files with 54 additions and 36 deletions

View File

@ -222,9 +222,17 @@ void ModbusRTUComm::setTimeout(unsigned long timeout) {
ModbusRTUCommError ModbusRTUComm::readAdu(ModbusADU& adu) { ModbusRTUCommError ModbusRTUComm::readAdu(ModbusADU& adu) {
adu.setRtuLen(0); adu.setRtuLen(0);
unsigned long startMillis = millis(); unsigned long startMillis = millis();
while (!_serial.available()) { if (!_serial.available()) {
if (millis() - startMillis >= _readTimeout) return MODBUS_RTU_COMM_TIMEOUT; //if (millis() - startMillis >= _readTimeout) return MODBUS_RTU_COMM_TIMEOUT;
_waiting_for_read = true;
if (millis() - startMillis >= _readTimeout) {
return MODBUS_RTU_COMM_TIMEOUT;
} else {
return MODBUS_RTU_COMM_WAITING;
}
} }
_waiting_for_read = false;
uint16_t len = 0; uint16_t len = 0;
unsigned long startMicros = micros(); unsigned long startMicros = micros();
do { do {
@ -323,7 +331,7 @@ ModbusRTUMasterError Modbus::writeMultipleCoils(uint8_t id, uint16_t startAddres
bitClear(adu.data[5 + (i >> 3)], i & 7); bitClear(adu.data[5 + (i >> 3)], i & 7);
} }
adu.setDataLen(5 + byteCount); adu.setDataLen(5 + byteCount);
_rtuComm.writeAdu(adu); if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
if (id == 0) return MODBUS_RTU_MASTER_SUCCESS; if (id == 0) return MODBUS_RTU_MASTER_SUCCESS;
ModbusRTUCommError commError = _rtuComm.readAdu(adu); ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError); if (commError) return _translateCommError(commError);
@ -355,7 +363,7 @@ ModbusRTUMasterError Modbus::writeMultipleHoldingRegisters(uint8_t id, uint16_t
adu.setDataRegister(5 + (i * 2), buf[i]); adu.setDataRegister(5 + (i * 2), buf[i]);
} }
adu.setDataLen(5 + byteCount); adu.setDataLen(5 + byteCount);
_rtuComm.writeAdu(adu); if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
if (id == 0) return MODBUS_RTU_MASTER_SUCCESS; if (id == 0) return MODBUS_RTU_MASTER_SUCCESS;
ModbusRTUCommError commError = _rtuComm.readAdu(adu); ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError); if (commError) return _translateCommError(commError);
@ -389,7 +397,7 @@ ModbusRTUMasterError Modbus::_readValues(uint8_t id, uint8_t functionCode, uint1
adu.setDataRegister(0, startAddress); adu.setDataRegister(0, startAddress);
adu.setDataRegister(2, quantity); adu.setDataRegister(2, quantity);
adu.setDataLen(4); adu.setDataLen(4);
_rtuComm.writeAdu(adu); if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
ModbusRTUCommError commError = _rtuComm.readAdu(adu); ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError); if (commError) return _translateCommError(commError);
if (adu.getUnitId() != id) return MODBUS_RTU_MASTER_UNEXPECTED_ID; if (adu.getUnitId() != id) return MODBUS_RTU_MASTER_UNEXPECTED_ID;
@ -417,7 +425,7 @@ ModbusRTUMasterError Modbus::_readValues(uint8_t id, uint8_t functionCode, uint1
adu.setDataRegister(0, startAddress); adu.setDataRegister(0, startAddress);
adu.setDataRegister(2, quantity); adu.setDataRegister(2, quantity);
adu.setDataLen(4); adu.setDataLen(4);
_rtuComm.writeAdu(adu); if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
ModbusRTUCommError commError = _rtuComm.readAdu(adu); ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError); if (commError) return _translateCommError(commError);
if (adu.getUnitId() != id) return MODBUS_RTU_MASTER_UNEXPECTED_ID; if (adu.getUnitId() != id) return MODBUS_RTU_MASTER_UNEXPECTED_ID;
@ -443,7 +451,7 @@ ModbusRTUMasterError Modbus::_writeSingleValue(uint8_t id, uint8_t functionCode,
adu.setDataRegister(0, address); adu.setDataRegister(0, address);
adu.setDataRegister(2, value); adu.setDataRegister(2, value);
adu.setDataLen(4); adu.setDataLen(4);
_rtuComm.writeAdu(adu); if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
if (id == 0) return MODBUS_RTU_MASTER_SUCCESS; if (id == 0) return MODBUS_RTU_MASTER_SUCCESS;
ModbusRTUCommError commError = _rtuComm.readAdu(adu); ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError); if (commError) return _translateCommError(commError);
@ -471,6 +479,8 @@ ModbusRTUMasterError Modbus::_translateCommError(ModbusRTUCommError commError) {
return MODBUS_RTU_MASTER_FRAME_ERROR; return MODBUS_RTU_MASTER_FRAME_ERROR;
case MODBUS_RTU_COMM_CRC_ERROR: case MODBUS_RTU_COMM_CRC_ERROR:
return MODBUS_RTU_MASTER_CRC_ERROR; return MODBUS_RTU_MASTER_CRC_ERROR;
case MODBUS_RTU_COMM_WAITING:
return MODBUS_RTU_MASTER_WAITING;
default: default:
return MODBUS_RTU_MASTER_UNKNOWN_COMM_ERROR; return MODBUS_RTU_MASTER_UNKNOWN_COMM_ERROR;
} }
@ -521,31 +531,36 @@ void Modbus::_loop(unsigned long currentMicros) {
#endif #endif
uint8_t error; uint8_t error;
// send reads and writes, DIAG on errors other than 0 (Success), or 3 (Invalid Quantity) // send reads and writes, DIAG on errors other than 0 (Success), or 3 (Invalid Quantity)
error = writeMultipleHoldingRegisters(_currentNode->getNodeID(), 0, (uint16_t*) _currentNode->holdingRegisters, _currentNode->getNumHoldingRegisters()); switch (_operationCount) {
if (error != 0 && error != 3) DIAG(F("ModbusHR: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumHoldingRegisters(), errorStrings[error]); case 0:
#ifdef DIAG_IO error = writeMultipleHoldingRegisters(_currentNode->getNodeID(), 0, (uint16_t*) _currentNode->holdingRegisters, _currentNode->getNumHoldingRegisters());
if (error == 0) DIAG(F("ModbusHR: T%d Success!"), _currentNode->getNodeID()); if (error != 0 && error != 3) DIAG(F("ModbusHR: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumHoldingRegisters(), errorStrings[error]);
#endif if (error != 0 && error != 3) flagOK = false;
if (error != 0 && error != 3) flagOK = false; break;
error = writeMultipleCoils(_currentNode->getNodeID(), 0, (int*) _currentNode->coils, _currentNode->getNumCoils()); case 1:
if (error != 0 && error != 3) DIAG(F("ModbusMC: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumCoils(), errorStrings[error]); error = writeMultipleCoils(_currentNode->getNodeID(), 0, (int*) _currentNode->coils, _currentNode->getNumCoils());
#ifdef DIAG_IO if (error != 0 && error != 3) DIAG(F("ModbusMC: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumCoils(), errorStrings[error]);
if (error == 0) DIAG(F("ModbusMC: T%d Success!"), _currentNode->getNodeID()); if (error != 0 && error != 3) flagOK = false;
#endif break;
if (error != 0 && error != 3) flagOK = false; case 2:
error = readDiscreteInputs(_currentNode->getNodeID(), 0, (int*) _currentNode->discreteInputs, _currentNode->getNumDiscreteInputs()); error = readDiscreteInputs(_currentNode->getNodeID(), 0, (int*) _currentNode->discreteInputs, _currentNode->getNumDiscreteInputs());
if (error != 0 && error != 3) DIAG(F("ModbusDI: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumDiscreteInputs(), errorStrings[error]); if (error != 0 && error != 3) DIAG(F("ModbusDI: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumDiscreteInputs(), errorStrings[error]);
#ifdef DIAG_IO if (error != 0 && error != 3) flagOK = false;
if (error == 0) DIAG(F("ModbusDI: T%d Success!"), _currentNode->getNodeID()); break;
#endif case 3:
if (error != 0 && error != 3) flagOK = false; error = readInputRegisters(_currentNode->getNodeID(), 0, (uint16_t*) _currentNode->inputRegisters, _currentNode->getNumInputRegisters());
error = readInputRegisters(_currentNode->getNodeID(), 0, (uint16_t*) _currentNode->inputRegisters, _currentNode->getNumInputRegisters()); if (error != 0 && error != 3) DIAG(F("ModbusIR: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumInputRegisters(), errorStrings[error]);
if (error != 0 && error != 3) DIAG(F("ModbusIR: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumInputRegisters(), errorStrings[error]); if (error != 0 && error != 3) flagOK = false;
#ifdef DIAG_IO break;
if (error == 0) DIAG(F("ModbusIR: T%d Success!"), _currentNode->getNodeID()); }
#endif if (error != MODBUS_RTU_MASTER_WAITING) {
if (error != 0 && error != 3) flagOK = false; if (_operationCount < 3) {
_operationCount++;
} else {
_operationCount = 0;
_currentNode = _currentNode->getNext();
}
}
#if defined(MODBUS_STM_OK) #if defined(MODBUS_STM_OK)
if (flagOK == true) { if (flagOK == true) {
ArduinoPins::fastWriteDigital(MODBUS_STM_OK,HIGH); ArduinoPins::fastWriteDigital(MODBUS_STM_OK,HIGH);
@ -563,7 +578,7 @@ void Modbus::_loop(unsigned long currentMicros) {
#if defined(MODBUS_STM_COMM) #if defined(MODBUS_STM_COMM)
ArduinoPins::fastWriteDigital(MODBUS_STM_COMM,LOW); ArduinoPins::fastWriteDigital(MODBUS_STM_COMM,LOW);
#endif #endif
_currentNode = _currentNode->getNext();
} }
// Link to chain of Modbus instances // Link to chain of Modbus instances

View File

@ -102,7 +102,8 @@ enum ModbusRTUCommError : uint8_t {
MODBUS_RTU_COMM_SUCCESS = 0, MODBUS_RTU_COMM_SUCCESS = 0,
MODBUS_RTU_COMM_TIMEOUT = 1, MODBUS_RTU_COMM_TIMEOUT = 1,
MODBUS_RTU_COMM_FRAME_ERROR = 2, MODBUS_RTU_COMM_FRAME_ERROR = 2,
MODBUS_RTU_COMM_CRC_ERROR = 3 MODBUS_RTU_COMM_CRC_ERROR = 3,
MODBUS_RTU_COMM_WAITING = 4
}; };
class ModbusRTUComm { class ModbusRTUComm {
@ -111,6 +112,7 @@ class ModbusRTUComm {
void begin(unsigned long baud, uint32_t config = SERIAL_8N1); void begin(unsigned long baud, uint32_t config = SERIAL_8N1);
void setTimeout(unsigned long timeout); void setTimeout(unsigned long timeout);
ModbusRTUCommError readAdu(ModbusADU& adu); ModbusRTUCommError readAdu(ModbusADU& adu);
bool _waiting_for_read = false;
void writeAdu(ModbusADU& adu); void writeAdu(ModbusADU& adu);
void clearRxBuffer(); void clearRxBuffer();
Stream& _serial; Stream& _serial;
@ -140,7 +142,8 @@ enum ModbusRTUMasterError : uint8_t {
MODBUS_RTU_MASTER_UNEXPECTED_BYTE_COUNT = 12, MODBUS_RTU_MASTER_UNEXPECTED_BYTE_COUNT = 12,
MODBUS_RTU_MASTER_UNEXPECTED_ADDRESS = 13, MODBUS_RTU_MASTER_UNEXPECTED_ADDRESS = 13,
MODBUS_RTU_MASTER_UNEXPECTED_VALUE = 14, MODBUS_RTU_MASTER_UNEXPECTED_VALUE = 14,
MODBUS_RTU_MASTER_UNEXPECTED_QUANTITY = 15 MODBUS_RTU_MASTER_UNEXPECTED_QUANTITY = 15,
MODBUS_RTU_MASTER_WAITING = 16
}; };
@ -307,7 +310,7 @@ private:
unsigned long _currentMicros; // last value of micros() from _loop function. unsigned long _currentMicros; // last value of micros() from _loop function.
unsigned long _postDelay; // delay time after transmission before switching off transmitter (in us) unsigned long _postDelay; // delay time after transmission before switching off transmitter (in us)
unsigned long _byteTransmitTime; // time in us for transmission of one byte unsigned long _byteTransmitTime; // time in us for transmission of one byte
int _operationCount = 0;
static Modbus *_busList; // linked list of defined bus instances static Modbus *_busList; // linked list of defined bus instances
ModbusRTUMasterError _readValues(uint8_t id, uint8_t functionCode, uint16_t startAddress, int buf[], uint16_t quantity); ModbusRTUMasterError _readValues(uint8_t id, uint8_t functionCode, uint16_t startAddress, int buf[], uint16_t quantity);
ModbusRTUMasterError _readValues(uint8_t id, uint8_t functionCode, uint16_t startAddress, uint16_t buf[], uint16_t quantity); ModbusRTUMasterError _readValues(uint8_t id, uint8_t functionCode, uint16_t startAddress, uint16_t buf[], uint16_t quantity);