move transfer latency to device

This commit is contained in:
John-Michael Baier
2020-11-01 10:25:57 +01:00
parent e519193797
commit d02b2bd331
6 changed files with 47 additions and 48 deletions
+7 -7
View File
@@ -433,7 +433,7 @@ result_t BusHandler::handleSymbol() {
// check if another symbol has to be sent and determine timeout for receive // check if another symbol has to be sent and determine timeout for receive
switch (m_state) { switch (m_state) {
case bs_noSignal: case bs_noSignal:
timeout = m_generateSynInterval > 0 ? m_generateSynInterval+m_transferLatency : SIGNAL_TIMEOUT; timeout = m_generateSynInterval > 0 ? m_generateSynInterval : SIGNAL_TIMEOUT;
break; break;
case bs_skip: case bs_skip:
@@ -485,7 +485,7 @@ result_t BusHandler::handleSymbol() {
break; break;
case bs_recvCmdAck: case bs_recvCmdAck:
timeout = m_slaveRecvTimeout+(m_currentRequest ? m_transferLatency : 0); timeout = m_slaveRecvTimeout;
break; break;
case bs_recvRes: case bs_recvRes:
@@ -498,7 +498,7 @@ result_t BusHandler::handleSymbol() {
break; break;
case bs_recvResAck: case bs_recvResAck:
timeout = m_slaveRecvTimeout+m_transferLatency; timeout = m_slaveRecvTimeout;
break; break;
case bs_sendCmd: case bs_sendCmd:
@@ -565,9 +565,9 @@ result_t BusHandler::handleSymbol() {
clockGettime(&sentTime); clockGettime(&sentTime);
if (result == RESULT_OK) { if (result == RESULT_OK) {
if (m_state == bs_ready) { if (m_state == bs_ready) {
timeout = m_transferLatency+m_busAcquireTimeout; timeout = m_busAcquireTimeout;
} else { } else {
timeout = m_transferLatency+SEND_TIMEOUT; timeout = SEND_TIMEOUT;
} }
} else { } else {
sending = false; sending = false;
@@ -579,7 +579,7 @@ result_t BusHandler::handleSymbol() {
// receive next symbol (optionally check reception of sent symbol) // receive next symbol (optionally check reception of sent symbol)
symbol_t recvSymbol; symbol_t recvSymbol;
ArbitrationState arbitrationState = as_none; ArbitrationState arbitrationState = as_none;
result = m_device->recv(timeout+m_transferLatency, &recvSymbol, &arbitrationState); result = m_device->recv(timeout, &recvSymbol, &arbitrationState);
if (sending) { if (sending) {
clockGettime(&recvTime); clockGettime(&recvTime);
} }
@@ -593,7 +593,7 @@ result_t BusHandler::handleSymbol() {
} }
clockGettime(&sentTime); clockGettime(&sentTime);
recvSymbol = ESC; recvSymbol = ESC;
result = m_device->recv(SEND_TIMEOUT+m_transferLatency, &recvSymbol, &arbitrationState); result = m_device->recv(SEND_TIMEOUT, &recvSymbol, &arbitrationState);
clockGettime(&recvTime); clockGettime(&recvTime);
if (result != RESULT_OK) { if (result != RESULT_OK) {
logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result)); logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result));
+2 -5
View File
@@ -378,14 +378,14 @@ class BusHandler : public WaitThread {
BusHandler(Device* device, MessageMap* messages, BusHandler(Device* device, MessageMap* messages,
symbol_t ownAddress, bool answer, symbol_t ownAddress, bool answer,
unsigned int busLostRetries, unsigned int failedSendRetries, unsigned int busLostRetries, unsigned int failedSendRetries,
unsigned int transferLatency, unsigned int busAcquireTimeout, unsigned int slaveRecvTimeout, unsigned int busAcquireTimeout, unsigned int slaveRecvTimeout,
unsigned int lockCount, bool generateSyn, unsigned int lockCount, bool generateSyn,
unsigned int pollInterval) unsigned int pollInterval)
: WaitThread(), m_device(device), m_reconnect(false), m_messages(messages), : WaitThread(), m_device(device), m_reconnect(false), m_messages(messages),
m_ownMasterAddress(ownAddress), m_ownSlaveAddress(getSlaveAddress(ownAddress)), m_ownMasterAddress(ownAddress), m_ownSlaveAddress(getSlaveAddress(ownAddress)),
m_answer(answer), m_addressConflict(false), m_answer(answer), m_addressConflict(false),
m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries), m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries),
m_transferLatency(transferLatency), m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout), m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout),
m_masterCount(device->isReadOnly()?0:1), m_autoLockCount(lockCount == 0), m_masterCount(device->isReadOnly()?0:1), m_autoLockCount(lockCount == 0),
m_lockCount(lockCount <= 3 ? 3 : lockCount), m_remainLockCount(m_autoLockCount ? 1 : 0), m_lockCount(lockCount <= 3 ? 3 : lockCount), m_remainLockCount(m_autoLockCount ? 1 : 0),
m_generateSynInterval(generateSyn ? SYN_TIMEOUT*getMasterNumber(ownAddress)+SYMBOL_DURATION : 0), m_generateSynInterval(generateSyn ? SYN_TIMEOUT*getMasterNumber(ownAddress)+SYMBOL_DURATION : 0),
@@ -686,9 +686,6 @@ class BusHandler : public WaitThread {
/** the number of times a failed send is repeated (other than lost arbitration). */ /** the number of times a failed send is repeated (other than lost arbitration). */
const unsigned int m_failedSendRetries; const unsigned int m_failedSendRetries;
/** the bus transfer latency in microseconds. */
const unsigned int m_transferLatency;
/** the maximum time in microseconds for bus acquisition. */ /** the maximum time in microseconds for bus acquisition. */
const unsigned int m_busAcquireTimeout; const unsigned int m_busAcquireTimeout;
+5 -1
View File
@@ -1306,7 +1306,11 @@ int main(int argc, char* argv[]) {
} }
// open the device // open the device
Device *device = Device::create(opt.device, !opt.noDeviceCheck, opt.readOnly, opt.initialSend); unsigned int latency = 0;
if (opt.latency >= 0) {
latency = (unsigned int)opt.latency;
}
Device *device = Device::create(opt.device, latency, !opt.noDeviceCheck, opt.readOnly, opt.initialSend);
if (device == nullptr) { if (device == nullptr) {
logError(lf_main, "unable to create device %s", opt.device); logError(lf_main, "unable to create device %s", opt.device);
return EINVAL; return EINVAL;
+1 -7
View File
@@ -141,16 +141,10 @@ MainLoop::MainLoop(const struct options& opt, Device *device, MessageMap* messag
} }
} }
// create BusHandler // create BusHandler
unsigned int latency;
if (opt.latency < 0) {
latency = device->getLatency();
} else {
latency = (unsigned int)opt.latency;
}
m_busHandler = new BusHandler(m_device, m_messages, m_busHandler = new BusHandler(m_device, m_messages,
m_address, opt.answer, m_address, opt.answer,
opt.acquireRetries, opt.sendRetries, opt.acquireRetries, opt.sendRetries,
latency, opt.acquireTimeout, opt.receiveTimeout, opt.acquireTimeout, opt.receiveTimeout,
opt.masterCount, opt.generateSyn, opt.masterCount, opt.generateSyn,
opt.pollInterval); opt.pollInterval);
m_busHandler->start("bushandler"); m_busHandler->start("bushandler");
+8 -15
View File
@@ -73,17 +73,9 @@ namespace ebusd {
#define ENH_BYTE2 ((uint8_t)0x80) #define ENH_BYTE2 ((uint8_t)0x80)
#define makeEnhancedSequence(cmd, data) {(uint8_t)(ENH_BYTE1 | ((cmd)<<2) | (((data)&0xc0)>>6)), (uint8_t)(ENH_BYTE2 | ((data)&0x3f))} #define makeEnhancedSequence(cmd, data) {(uint8_t)(ENH_BYTE1 | ((cmd)<<2) | (((data)&0xc0)>>6)), (uint8_t)(ENH_BYTE2 | ((data)&0x3f))}
/** Device::Device(const char* name, bool checkDevice, unsigned int latency, bool readOnly, bool initialSend,
* Construct a new instance. bool enhancedProto)
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network). : m_name(name), m_checkDevice(checkDevice), m_latency(latency), m_readOnly(readOnly), m_initialSend(initialSend),
* @param address the socket address of the device.
* @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open().
* @param udp true for UDP, false to TCP.
* @param enhancedProto whether to use the ebusd enhanced protocol.
*/
Device::Device(const char* name, bool checkDevice, bool readOnly, bool initialSend, bool enhancedProto)
: m_name(name), m_checkDevice(checkDevice), m_readOnly(readOnly), m_initialSend(initialSend),
m_enhancedProto(enhancedProto), m_fd(-1), m_listener(nullptr), m_arbitrationMaster(SYN), m_enhancedProto(enhancedProto), m_fd(-1), m_listener(nullptr), m_arbitrationMaster(SYN),
m_arbitrationCheck(false), m_bufSize(((MAX_LEN+1+3)/4)*4), m_bufLen(0), m_bufPos(0) { m_arbitrationCheck(false), m_bufSize(((MAX_LEN+1+3)/4)*4), m_bufLen(0), m_bufPos(0) {
m_buffer = reinterpret_cast<symbol_t*>(malloc(m_bufSize)); m_buffer = reinterpret_cast<symbol_t*>(malloc(m_bufSize));
@@ -99,7 +91,7 @@ Device::~Device() {
} }
} }
Device* Device::create(const char* name, bool checkDevice, bool readOnly, bool initialSend) { Device* Device::create(const char* name, unsigned int extraLatency, bool checkDevice, bool readOnly, bool initialSend) {
bool enhanced = strncmp(name, "enh:", 4) == 0; bool enhanced = strncmp(name, "enh:", 4) == 0;
if (enhanced) { if (enhanced) {
name += 4; name += 4;
@@ -134,10 +126,10 @@ Device* Device::create(const char* name, bool checkDevice, bool readOnly, bool i
*portpos = 0; *portpos = 0;
char* hostOrIp = strdup(addrpos); char* hostOrIp = strdup(addrpos);
free(in); free(in);
return new NetworkDevice(name, hostOrIp, port, readOnly, initialSend, udp, enhanced); return new NetworkDevice(name, hostOrIp, port, extraLatency, readOnly, initialSend, udp, enhanced);
} }
// support enh:/dev/<device> // support enh:/dev/<device>
return new SerialDevice(name, checkDevice, readOnly, initialSend, enhanced); return new SerialDevice(name, checkDevice, extraLatency, readOnly, initialSend, enhanced);
} }
result_t Device::open() { result_t Device::open() {
@@ -205,6 +197,7 @@ result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* a
} }
bool repeat = false; bool repeat = false;
bool repeated = false; bool repeated = false;
timeout += m_latency;
do { do {
repeat = false; repeat = false;
bool isAvailable = available(); bool isAvailable = available();
@@ -263,7 +256,7 @@ result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* a
// for a two-byte transfer another poll is needed // for a two-byte transfer another poll is needed
repeat = true; repeat = true;
repeated = true; repeated = true;
timeout = ENHANCED_COMPLETE_WAIT_DURATION; timeout = m_latency+ENHANCED_COMPLETE_WAIT_DURATION;
continue; continue;
} }
return RESULT_ERR_TIMEOUT; return RESULT_ERR_TIMEOUT;
+24 -13
View File
@@ -40,6 +40,9 @@ namespace ebusd {
* to a file and/or forwarding it to a logging function. * to a file and/or forwarding it to a logging function.
*/ */
/** the transfer latency of the network device [ms]. */
#define NETWORK_LATENCY_MS 10
/** the arbitration state handled by @a Device. */ /** the arbitration state handled by @a Device. */
enum ArbitrationState { enum ArbitrationState {
as_none, //!< no arbitration in process as_none, //!< no arbitration in process
@@ -80,17 +83,20 @@ class DeviceListener {
* The base class for accessing an eBUS. * The base class for accessing an eBUS.
*/ */
class Device { class Device {
public: protected:
/** /**
* Construct a new instance. * Construct a new instance.
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network). * @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
* @param checkDevice whether to regularly check the device availability. * @param checkDevice whether to regularly check the device availability.
* @param latency the bus transfer latency in milliseconds.
* @param readOnly whether to allow read access to the device only. * @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open(). * @param initialSend whether to send an initial @a ESC symbol in @a open().
* @param enhancedProto whether to use the ebusd enhanced protocol. * @param enhancedProto whether to use the ebusd enhanced protocol.
*/ */
Device(const char* name, bool checkDevice, bool readOnly, bool initialSend, bool enhancedProto=false); Device(const char* name, bool checkDevice, unsigned int latency, bool readOnly, bool initialSend,
bool enhancedProto=false);
public:
/** /**
* Destructor. * Destructor.
*/ */
@@ -99,20 +105,21 @@ class Device {
/** /**
* Factory method for creating a new instance. * Factory method for creating a new instance.
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network). * @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
* @param extraLatency the extra bus transfer latency in milliseconds.
* @param checkDevice whether to regularly check the device availability (only for serial devices). * @param checkDevice whether to regularly check the device availability (only for serial devices).
* @param readOnly whether to allow read access to the device only. * @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open(). * @param initialSend whether to send an initial @a ESC symbol in @a open().
* @return the new @a Device, or nullptr on error. * @return the new @a Device, or nullptr on error.
* Note: the caller needs to free the created instance. * Note: the caller needs to free the created instance.
*/ */
static Device* create(const char* name, bool checkDevice = true, bool readOnly = false, static Device* create(const char* name, unsigned int extraLatency = 0, bool checkDevice = true,
bool initialSend = false); bool readOnly = false, bool initialSend = false);
/** /**
* Get the transfer latency of this device. * Get the transfer latency of this device.
* @return the transfer latency in microseconds. * @return the transfer latency in microseconds.
*/ */
virtual unsigned int getLatency() const { return 0; } virtual unsigned int getLatency() const { return m_latency; }
/** /**
* Open the file descriptor. * Open the file descriptor.
@@ -223,6 +230,9 @@ class Device {
/** whether to regularly check the device availability. */ /** whether to regularly check the device availability. */
const bool m_checkDevice; const bool m_checkDevice;
/** the bus transfer latency in milliseconds. */
const unsigned int m_latency;
/** whether to allow read access to the device only. */ /** whether to allow read access to the device only. */
const bool m_readOnly; const bool m_readOnly;
@@ -269,12 +279,14 @@ class SerialDevice : public Device {
* Construct a new instance. * Construct a new instance.
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network). * @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
* @param checkDevice whether to regularly check the device availability. * @param checkDevice whether to regularly check the device availability.
* @param extraLatency the extra bus transfer latency in milliseconds.
* @param readOnly whether to allow read access to the device only. * @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open(). * @param initialSend whether to send an initial @a ESC symbol in @a open().
* @param enhancedProto whether to use the ebusd enhanced protocol. * @param enhancedProto whether to use the ebusd enhanced protocol.
*/ */
SerialDevice(const char* name, bool checkDevice, bool readOnly, bool initialSend, bool enhancedProto=false) SerialDevice(const char* name, bool checkDevice, unsigned int extraLatency, bool readOnly, bool initialSend,
: Device(name, checkDevice, readOnly, initialSend, enhancedProto) {} bool enhancedProto=false)
: Device(name, checkDevice, extraLatency, readOnly, initialSend, enhancedProto) {}
// @copydoc // @copydoc
result_t open() override; result_t open() override;
@@ -304,14 +316,16 @@ class NetworkDevice : public Device {
* @param address the socket address of the device. * @param address the socket address of the device.
* @param hostOrIp the host name or IP address of the device. * @param hostOrIp the host name or IP address of the device.
* @param port the TCP or UDP port of the device. * @param port the TCP or UDP port of the device.
* @param extraLatency the extra bus transfer latency in milliseconds.
* @param readOnly whether to allow read access to the device only. * @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open(). * @param initialSend whether to send an initial @a ESC symbol in @a open().
* @param udp true for UDP, false to TCP. * @param udp true for UDP, false to TCP.
* @param enhancedProto whether to use the ebusd enhanced protocol. * @param enhancedProto whether to use the ebusd enhanced protocol.
*/ */
NetworkDevice(const char* name, const char* hostOrIp, uint16_t port, bool readOnly, bool initialSend, NetworkDevice(const char* name, const char* hostOrIp, uint16_t port, unsigned int extraLatency, bool readOnly,
bool udp, bool enhancedProto=false) bool initialSend, bool udp, bool enhancedProto=false)
: Device(name, true, readOnly, initialSend, enhancedProto), m_hostOrIp(hostOrIp), m_port(port), m_udp(udp) {} : Device(name, true, NETWORK_LATENCY_MS+extraLatency, readOnly, initialSend, enhancedProto),
m_hostOrIp(hostOrIp), m_port(port), m_udp(udp) {}
/** /**
* Destructor. * Destructor.
@@ -322,9 +336,6 @@ class NetworkDevice : public Device {
} }
} }
// @copydoc
unsigned int getLatency() const override { return 10000; }
// @copydoc // @copydoc
result_t open() override; result_t open() override;