diff --git a/src/ebusd/baseloop.cpp b/src/ebusd/baseloop.cpp index a6f56a89..3f408c79 100644 --- a/src/ebusd/baseloop.cpp +++ b/src/ebusd/baseloop.cpp @@ -52,7 +52,7 @@ BaseLoop::BaseLoop() L.log(bas, event, " polling DB: %d ", m_commands->sizePollDB());*/ m_ownAddress = A.getOptVal("address") & 0xff; - bool answer = A.getOptVal("answer"); + const bool answer = A.getOptVal("answer"); const bool logRaw = A.getOptVal("lograwdata"); @@ -60,6 +60,12 @@ BaseLoop::BaseLoop() const char* dumpRawFile = A.getOptVal("dumpfile"); const long dumpRawMaxSize = A.getOptVal("dumpsize"); + const unsigned int busLostRetries = A.getOptVal("lockretries"); + const unsigned int failedSendRetries = A.getOptVal("sendretries"); + const unsigned int busAcquireWaitTime = A.getOptVal("acquiretimeout"); + const unsigned int slaveRecvTimeout = A.getOptVal("recvtimeout"); + const unsigned int lockCount = A.getOptVal("lockcounter"); + // create Port m_port = new Port(A.getOptVal("device"), A.getOptVal("nodevicecheck"), logRaw, &BaseLoop::logRaw, dumpRaw, dumpRawFile, dumpRawMaxSize); m_port->open(); @@ -68,7 +74,11 @@ BaseLoop::BaseLoop() L.log(bus, error, "can't open %s", A.getOptVal("device")); // create BusHandler - m_busHandler = new BusHandler(m_port, m_messages, answer ? m_ownAddress : SYN, answer ? (m_ownAddress+5)&0xff : SYN); + m_busHandler = new BusHandler(m_port, m_messages, + answer ? m_ownAddress : SYN, answer ? (m_ownAddress+5)&0xff : SYN, + busLostRetries, failedSendRetries, + busAcquireWaitTime, slaveRecvTimeout, + lockCount); m_busHandler->start("bushandler"); // create network @@ -167,9 +177,17 @@ void BaseLoop::start() return; } } +static unsigned char _lastRecvSymbol = SYN; -void BaseLoop::logRaw(const unsigned char byte) { - L.log(bus, event, "%02x", byte); +void BaseLoop::logRaw(const unsigned char byte, bool received) { + if (received == true) { + if (byte != SYN || byte !=_lastRecvSymbol) + L.log(bus, event, "<%02x", byte); + _lastRecvSymbol = byte; + } else { + L.log(bus, event, ">%02x", byte); + _lastRecvSymbol = ESC; + } } string BaseLoop::decodeMessage(const string& data) diff --git a/src/ebusd/baseloop.h b/src/ebusd/baseloop.h index 0c1662e5..73f6407b 100644 --- a/src/ebusd/baseloop.h +++ b/src/ebusd/baseloop.h @@ -79,10 +79,11 @@ public: void addMessage(NetMessage* message) { m_netQueue.add(message); } /** - * @brief Create a log message for a retrieved raw data byte. - * @param param byte the retrieved raw data byte. + * @brief Create a log message for a received/sent raw data byte. + * @param param byte the raw data byte. + * @param received true if the byte was received, false if it was sent. */ - static void logRaw(const unsigned char byte); + static void logRaw(const unsigned char byte, bool received); private: diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 0373e3ba..f66e562f 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -73,6 +73,8 @@ BusRequest::~BusRequest() bool BusRequest::wait(int timeout) { + m_finished = false; + m_result = RESULT_SYN; struct timespec t; clock_gettime(CLOCK_REALTIME, &t); t.tv_sec += timeout; @@ -105,16 +107,33 @@ void BusRequest::notify(result_t result) result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) { + result_t result = RESULT_SYN; BusRequest* request = new BusRequest(master, slave); - m_requests.add(request); - bool success = request->wait(5); - if (success == false) - m_requests.remove(request); - result_t result = request->m_result; + for (int sendRetries=m_failedSendRetries+1, lostRetries=m_busLostRetries+1; sendRetries>=0; sendRetries--) { + m_requests.add(request); + bool success = request->wait(5); + if (success == false) + m_requests.remove(request); + result = success == true ? request->m_result : RESULT_ERR_TIMEOUT; + + if (result == RESULT_OK) + break; + + if (result == RESULT_ERR_BUS_LOST) { + if (--lostRetries > 0) { + sendRetries++; // try to get lock again, do not decrement send retries + L.log(bus, error, " %s, retry bus loss", getResultCode(result)); + continue; + } + lostRetries = m_busLostRetries+1; // send retry: reset lock retries + } + L.log(bus, error, " %s, %s", getResultCode(result), sendRetries>0 ? "retry send" : "give up"); + } + delete request; - return success == true ? result : RESULT_ERR_TIMEOUT; + return result; } void BusHandler::run() @@ -149,10 +168,14 @@ result_t BusHandler::handleSymbol() break; case bs_ready: - m_request = m_requests.next(false); - if (m_request != NULL) { // initiate arbitration - sendSymbol = m_request->m_master[0]; - sending = true; + if (m_request != NULL) + setState(bs_ready, RESULT_ERR_TIMEOUT); // just to be sure an old BusRequest is cleaned up + if (m_remainLockCount == 0) { + m_request = m_requests.next(false); + if (m_request != NULL) { // initiate arbitration + sendSymbol = m_request->m_master[0]; + sending = true; + } } break; @@ -160,7 +183,7 @@ result_t BusHandler::handleSymbol() case bs_recvCmdAck: case bs_recvRes: case bs_recvResAck: - timeout = SLAVE_RECV_TIMEOUT; + timeout = m_slaveRecvTimeout; break; case bs_sendCmd: @@ -186,7 +209,10 @@ result_t BusHandler::handleSymbol() // send symbol if necessary if (sending == true) { if (m_port->send(&sendSymbol, 1) == 1) - timeout = SEND_TIMEOUT; + if (m_state == bs_ready) + timeout = m_busAcquireTimeout; + else + timeout = SEND_TIMEOUT; else { sending = false; timeout = 0; @@ -195,26 +221,18 @@ result_t BusHandler::handleSymbol() } // receive next symbol (optionally check reception of sent symbol) - ssize_t count = m_port->recv(timeout, 1); + unsigned char recvSymbol; + ssize_t count = m_port->recv(timeout, 1, &recvSymbol); - if (count <= 0 && m_state == bs_ready && sending == false) - return RESULT_OK; // TODO keep "no signal" within auto-syn state + if (count < 0) // count < 0 is a RESULT_ERR_ code + return setState(bs_skip, count); // TODO keep "no signal" within auto-syn state - if (count < 0) { // count < 0 is a RESULT_ERR_ code - if (m_request != NULL) - return setState(bs_sendSyn, count); - return setState(bs_skip, count); - } - - if (count == 0) { - if (m_request != NULL) - return setState(bs_sendSyn, RESULT_ERR_TIMEOUT); - return setState(bs_skip, RESULT_ERR_TIMEOUT); - } - - unsigned char recvSymbol = m_port->byte(); - if (recvSymbol == SYN) + //unsigned char recvSymbol = m_port->byte(); // TODO remove me + if (recvSymbol == SYN) { + if (sending == false && m_remainLockCount > 0) + m_remainLockCount--; return setState(bs_ready, RESULT_SYN); + } unsigned char headerLen, crcPos; result_t result; @@ -228,8 +246,7 @@ result_t BusHandler::handleSymbol() if (m_request != NULL && sending == true) { if (m_requests.remove(m_request) == false) { // request already timed out - m_request = NULL; - return setState(bs_sendSyn, RESULT_ERR_TIMEOUT); + return setState(bs_skip, RESULT_ERR_TIMEOUT); } // check arbitration if (recvSymbol == sendSymbol) { // arbitration successful @@ -237,8 +254,12 @@ result_t BusHandler::handleSymbol() m_repeat = false; return setState(bs_sendCmd, RESULT_OK); } - // arbitration lost - m_request = NULL; + // arbitration lost. if same priority class found, try again after next AUTO-SYN + m_remainLockCount = isMaster(recvSymbol) ? 2 : 1; + if ((recvSymbol & 0x0f) != (sendSymbol & 0x0f) + && m_lockCount > m_remainLockCount) + // if different priority class found, try again after N AUTO-SYN symbols (at least next AUTO-SYN) + m_remainLockCount = m_lockCount; setState(m_state, RESULT_ERR_BUS_LOST); // try again later } result = m_command.push_back(recvSymbol, false); // expect no escaping for master address @@ -263,7 +284,7 @@ result_t BusHandler::handleSymbol() m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC(); if (m_commandCrcValid) { if (dstAddress == BROADCAST) { - transferCompleted(tt_broadcast); + receiveCompleted(); return setState(bs_skip, RESULT_OK); } //if (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress) @@ -289,11 +310,10 @@ result_t BusHandler::handleSymbol() if (m_request != NULL) { if (isMaster(m_request->m_master[1]) == true) { - transferCompleted(tt_masterMaster); return setState(bs_sendSyn, RESULT_OK); } } else if (isMaster(m_command[1]) == true) { - transferCompleted(tt_masterMaster); + receiveCompleted(); return setState(bs_skip, RESULT_OK); } @@ -311,12 +331,12 @@ result_t BusHandler::handleSymbol() return setState(bs_recvCmd, RESULT_ERR_NAK); } if (m_request != NULL) - return setState(bs_sendSyn, RESULT_ERR_NAK); + return setState(bs_skip, RESULT_ERR_NAK); return setState(bs_skip, RESULT_ERR_NAK); } if (m_request != NULL) - return setState(bs_sendSyn, RESULT_ERR_ACK); + return setState(bs_skip, RESULT_ERR_ACK); return setState(bs_skip, RESULT_ERR_ACK); @@ -326,7 +346,7 @@ result_t BusHandler::handleSymbol() result = m_response.push_back(recvSymbol, true, m_response.size() < crcPos); if (result < RESULT_OK) { if (m_request != NULL) - return setState(bs_sendSyn, result); + return setState(bs_skip, result); return setState(bs_skip, result); } @@ -340,7 +360,7 @@ result_t BusHandler::handleSymbol() } if (m_repeat == true) { if (m_request != NULL) - return setState(bs_sendSyn, RESULT_ERR_CRC); + return setState(bs_skip, RESULT_ERR_CRC); return setState(bs_skip, RESULT_ERR_CRC); } @@ -356,7 +376,7 @@ result_t BusHandler::handleSymbol() if (m_responseCrcValid == false) return setState(bs_skip, RESULT_ERR_ACK); - transferCompleted(tt_masterSlave); + receiveCompleted(); return setState(bs_skip, RESULT_OK); } if (recvSymbol == NAK) { @@ -385,7 +405,7 @@ result_t BusHandler::handleSymbol() return RESULT_OK; } } - return setState(bs_sendSyn, RESULT_ERR_INVALID_ARG); + return setState(bs_skip, RESULT_ERR_INVALID_ARG); case bs_sendResAck: if (m_request != NULL && sending == true) { @@ -394,7 +414,7 @@ result_t BusHandler::handleSymbol() return setState(bs_sendSyn, RESULT_OK); } } - return setState(bs_sendSyn, RESULT_ERR_INVALID_ARG); + return setState(bs_skip, RESULT_ERR_INVALID_ARG); case bs_sendSyn: if (sending == true) { @@ -412,25 +432,26 @@ result_t BusHandler::handleSymbol() result_t BusHandler::setState(BusState state, result_t result) { - if (state == m_state) - return result; - - if (result < RESULT_OK || (result != RESULT_OK && state == bs_skip)) - L.log(bus, error, " %s during %s, switching to %s", getResultCode(result), getStateCode(m_state), getStateCode(state)); - else if (m_request != NULL || state == bs_sendCmd || state==bs_sendResAck || state==bs_sendSyn) - L.log(bus, trace, " switching from %s to %s", getStateCode(m_state), getStateCode(state)); if (m_request != NULL) { - if (state == bs_sendSyn) { -// L.log(bus, trace, "notify request (syn): %s", getResultCode(result)); - m_request->m_slave = m_response; // TODO nicer + if (result != RESULT_OK) { + L.log(bus, debug, "notify request: %s", getResultCode(result)); m_request->notify(result); m_request = NULL; - } else if (result != RESULT_OK) { -// L.log(bus, trace, "notify request: %s", getResultCode(result)); + } else if (state == bs_sendSyn) { + L.log(bus, debug, "notify request (syn): %s", getResultCode(result)); + m_request->m_slave = m_response; // TODO nicer m_request->notify(result); m_request = NULL; } } + + if (state == m_state) + return result; + + if (result < RESULT_OK || (result != RESULT_OK && state == bs_skip)) + L.log(bus, debug, " %s during %s, switching to %s", getResultCode(result), getStateCode(m_state), getStateCode(state)); + else if (m_request != NULL || state == bs_sendCmd || state==bs_sendResAck || state==bs_sendSyn) + L.log(bus, debug, " switching from %s to %s", getStateCode(m_state), getStateCode(state)); m_state = state; if (state == bs_ready || state == bs_skip) { @@ -444,7 +465,7 @@ result_t BusHandler::setState(BusState state, result_t result) return result; } -void BusHandler::transferCompleted(TransferType type) +void BusHandler::receiveCompleted() { Message* msg = m_messages->find(m_command); if (msg != NULL) { @@ -458,16 +479,10 @@ void BusHandler::transferCompleted(TransferType type) L.log(bus, trace, "%s %s: %s", msg->getClass().c_str(), msg->getName().c_str(), output.str().c_str()); return; } - switch (type) - { - case tt_broadcast: + if (m_command[1] == BROADCAST) L.log(bus, trace, "received broadcast %s", m_command.getDataStr().c_str()); - break; - case tt_masterMaster: - L.log(bus, trace, "received master %s", m_command.getDataStr().c_str()); - break; - case tt_masterSlave: - L.log(bus, trace, "received master %s, slave %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); - break; - } + else if (isMaster(m_command[1]) == true) + L.log(bus, trace, "received master-master %s", m_command.getDataStr().c_str()); + else + L.log(bus, trace, "received master-slave %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); } diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index 299abb67..d77eba91 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -35,13 +35,13 @@ using namespace std; /** the maximum allowed time [us] for retrieving a symbol from an addressed slave. */ -#define SLAVE_RECV_TIMEOUT 10000 -/** the maximum allowed time [us] for retrieving the AUTO-SYN symbol (should be generated in <45ms). */ -#define SYN_TIMEOUT 50000 -/** the maximum duration [us] of a single symbol. */ -#define SYMBOL_DURATION 5100 -/** the maximum allowed time [us] for retrieving back a sent symbol. */ -#define SEND_TIMEOUT 6000 +//#define SLAVE_RECV_TIMEOUT 10000 +/** the maximum allowed time [us] for retrieving the AUTO-SYN symbol (45ms + 2*1,2% + 1 Symbol). */ +#define SYN_TIMEOUT 50800 +/** the maximum duration [us] of a single symbol (Start+8Bit+Stop+Extra @ 2400Bd-2*1,2%). */ +#define SYMBOL_DURATION 4700 +/** the maximum allowed time [us] for retrieving back a sent symbol (2x symbol duration). */ +#define SEND_TIMEOUT (2*SYMBOL_DURATION) /** the possible bus states. */ enum BusState { @@ -58,13 +58,6 @@ enum BusState { bs_sendSyn, // send SYN for completed transfer [active set+get] }; -/** the possible message transfer types. */ -enum TransferType { - tt_broadcast, // broadcast transfer - tt_masterMaster, // master to master transfer - tt_masterSlave // master to slave transfer -}; - /** the possible combinations of participants in a single message exchange. */ enum MessageDirection { md_thisToAll, // message from us to all (broadcast) @@ -147,11 +140,23 @@ public: * @param messages the @a MessageMap instance with all known @a Message instances. * @param ownMasterAddress the own master address to react on master-master messages, or @a SYN to ignore. * @param ownSlaveAddress the own slave address to react on master-slave messages, or @a SYN to ignore. + * @param busLostRetries the number of times a send is repeated due to lost arbitration. + * @param failedSendRetries the number of times a failed send is repeated (other than lost arbitration). + * @param slaveRecvTimeout the maximum time in microseconds an addressed slave is expected to acknowledge. + * @param busAcquireTimeout the maximum time in microseconds for bus acquisition. + * @param lockCount the number of AUTO-SYN symbols before sending is allowed after lost arbitration. */ - BusHandler(Port* port, MessageMap* messages, unsigned char ownMasterAddress, - unsigned char ownSlaveAddress) - : m_port(port), m_messages(messages), m_ownMasterAddress(ownMasterAddress), - m_ownSlaveAddress(ownSlaveAddress), m_request(NULL), m_nextSendPos(0), + BusHandler(Port* port, MessageMap* messages, + const unsigned char ownMasterAddress, const unsigned char ownSlaveAddress, + const unsigned int busLostRetries, const unsigned int failedSendRetries, + const unsigned int busAcquireTimeout, const unsigned int slaveRecvTimeout, + const unsigned int lockCount) + : m_port(port), m_messages(messages), + m_ownMasterAddress(ownMasterAddress), m_ownSlaveAddress(ownSlaveAddress), + m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries), + m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout), + m_lockCount(lockCount), m_remainLockCount(lockCount), + m_request(NULL), m_nextSendPos(0), m_state(bs_skip), m_repeat(false), m_commandCrcValid(false), m_responseCrcValid(false) {} @@ -189,10 +194,9 @@ private: result_t setState(BusState state, result_t result); /** - * @brief Called when a transfer was successfully completed. - * @param type the @a TransferType. + * @brief Called when a passive reception was successfully completed. */ - void transferCompleted(TransferType type); + void receiveCompleted(); /** the @a Port instance for accessing the bus. */ Port* m_port; @@ -201,10 +205,28 @@ private: MessageMap* m_messages; /** the own master address to react on master-master messages, or @a SYN to ignore. */ - unsigned char m_ownMasterAddress; + const unsigned char m_ownMasterAddress; /** the own slave address to react on master-slave messages, or @a SYN to ignore. */ - unsigned char m_ownSlaveAddress; + const unsigned char m_ownSlaveAddress; + + /** the number of times a send is repeated due to lost arbitration. */ + const unsigned int m_busLostRetries; + + /** the number of times a failed send is repeated (other than lost arbitration). */ + const unsigned int m_failedSendRetries; + + /** the maximum time in microseconds for bus acquisition. */ + const unsigned int m_busAcquireTimeout; + + /** the maximum time in microseconds an addressed slave is expected to acknowledge. */ + const unsigned int m_slaveRecvTimeout; + + /** the number of AUTO-SYN symbols before sending is allowed after lost arbitration. */ + const unsigned int m_lockCount; + + /** the remaining number of AUTO-SYN symbols before sending is allowed again. */ + unsigned int m_remainLockCount; /** the queue of @a BusRequests that shall be handled. */ WQueue m_requests; diff --git a/src/ebusd/ebusd.cpp b/src/ebusd/ebusd.cpp index aad7f47f..61749241 100644 --- a/src/ebusd/ebusd.cpp +++ b/src/ebusd/ebusd.cpp @@ -67,8 +67,8 @@ void define_args() A.addOption("recvtimeout", "", OptVal(15000), dt_long, ot_mandatory, "receive timeout in 'us' (15000)"); - A.addOption("acquiretime", "", OptVal(4200), dt_long, ot_mandatory, - "waiting time for bus acquire in 'us' (4200)\n"); + A.addOption("acquiretimeout", "", OptVal(9400), dt_long, ot_mandatory, + "bus acquisition timeout in 'us' (9400)\n"); A.addOption("pollinterval", "", OptVal(5), dt_int, ot_mandatory, "polling interval in 's' (5)\n");