Superrefactoring - all time values were replaced with new safer classes from uavcan/time.hpp; generated types were moved away from anonymous namespaces because this makes it impossible to use a type from different compilation units. Some less vital fixes are to follow - see the next few commits

This commit is contained in:
Pavel Kirienko
2014-03-11 14:41:48 +04:00
parent 633fa9d8bd
commit 65a4dcc2cf
48 changed files with 654 additions and 565 deletions
+9 -8
View File
@@ -10,6 +10,7 @@
#include <algorithm>
#include <string>
#include <uavcan/internal/impl_constants.hpp>
#include <uavcan/system_clock.hpp>
namespace uavcan
{
@@ -87,10 +88,10 @@ public:
/**
* Non-blocking transmission.
* If the frame wasn't transmitted upon TX timeout expiration, the driver should discard it.
* If the frame wasn't transmitted upon TX deadline, the driver should discard it.
* @return 1 = one frame transmitted, 0 = TX buffer full, negative for error.
*/
virtual int send(const CanFrame& frame, uint64_t tx_timeout_usec) = 0;
virtual int send(const CanFrame& frame, MonotonicTime tx_deadline) = 0;
/**
* Non-blocking reception.
@@ -100,11 +101,11 @@ public:
* UTC timestamp is optional, if available it will be used for precise time synchronization;
* must be set to zero if not available.
* Refer to @ref ISystemClock to learn more about timestamps.
* @param [out] out_ts_monotonic_usec Monotonic timestamp, usec, mandatory.
* @param [out] out_ts_utc_usec UTC timestamp, usec, optional, zero if unknown.
* @param [out] out_ts_monotonic Monotonic timestamp, mandatory.
* @param [out] out_ts_utc UTC timestamp, optional, zero if unknown.
* @return 1 = one frame received, 0 = RX buffer empty, negative for error.
*/
virtual int receive(CanFrame& out_frame, uint64_t& out_ts_monotonic_usec, uint64_t& out_ts_utc_usec) = 0;
virtual int receive(CanFrame& out_frame, MonotonicTime& out_ts_monotonic, UtcTime& out_ts_utc) = 0;
/**
* Configure the hardware CAN filters. @ref CanFilterConfig.
@@ -142,15 +143,15 @@ public:
virtual int getNumIfaces() const = 0;
/**
* Block until the blocking timeout expires, or one of the specified interfaces becomes available for read or write.
* Block until the deadline, or one of the specified interfaces becomes available for read or write.
* Iface masks will be modified by the driver to indicate which exactly interfaces are available for IO.
* Bit position in the masks defines interface index.
* @param [in,out] inout_write_iface_mask Mask indicating which interfaces are needed/available to write.
* @param [in,out] inout_read_iface_mask Same as above for reading.
* @param [in] timeout_usec Zero means non-blocking operation.
* @param [in] blocking_deadline Zero means non-blocking operation.
* @return Positive number of ready interfaces or negative error code.
*/
virtual int select(int& inout_write_iface_mask, int& inout_read_iface_mask, uint64_t timeout_usec) = 0;
virtual int select(int& inout_write_iface_mask, int& inout_read_iface_mask, MonotonicTime blocking_deadline) = 0;
};
}
+2 -1
View File
@@ -8,12 +8,13 @@
#include <cstring>
#include <stdint.h>
#include <algorithm>
#include <uavcan/internal/transport/crc.hpp>
#include <uavcan/internal/transport/transfer.hpp>
namespace uavcan
{
class TransferCRC;
enum DataTypeKind
{
DataTypeKindService,
@@ -25,16 +25,11 @@ namespace uavcan
template <typename DataSpec, typename DataStruct>
class GenericPublisher
{
public:
enum { DefaultTxTimeoutUsec = 2500 }; // 2500 ms --> 400Hz max
enum { MinTxTimeoutUsec = 200 };
private:
enum { Qos = (DataTypeKind(DataSpec::DataTypeKind) == DataTypeKindMessage) ?
CanTxQueue::Volatile : CanTxQueue::Persistent };
const uint64_t max_transfer_interval_; // TODO: memory usage can be reduced
uint64_t tx_timeout_;
const MonotonicDuration max_transfer_interval_; // TODO: memory usage can be reduced
MonotonicDuration tx_timeout_;
Scheduler& scheduler_;
IMarshalBufferProvider& buffer_provider_;
LazyConstructor<TransferSender> sender_;
@@ -54,12 +49,12 @@ private:
UAVCAN_TRACE("GenericPublisher", "Type [%s] is not registered", DataSpec::getDataTypeFullName());
return false;
}
sender_.template construct<Dispatcher&, const DataTypeDescriptor&, CanTxQueue::Qos, uint64_t>
sender_.template construct<Dispatcher&, const DataTypeDescriptor&, CanTxQueue::Qos, MonotonicDuration>
(scheduler_.getDispatcher(), *descr, CanTxQueue::Qos(Qos), max_transfer_interval_);
return true;
}
uint64_t getTxDeadline() const { return scheduler_.getMonotonicTimestamp() + tx_timeout_; }
MonotonicTime getTxDeadline() const { return scheduler_.getMonotonicTimestamp() + tx_timeout_; }
IMarshalBuffer* getBuffer()
{
@@ -67,7 +62,7 @@ private:
}
int genericPublish(const DataStruct& message, TransferType transfer_type, NodeID dst_node_id,
TransferID* tid, uint64_t monotonic_blocking_deadline)
TransferID* tid, MonotonicTime blocking_deadline)
{
if (!checkInit())
return -1;
@@ -89,20 +84,20 @@ private:
if (tid)
{
return sender_->send(buf->getDataPtr(), buf->getDataLength(), getTxDeadline(),
monotonic_blocking_deadline, transfer_type, dst_node_id, *tid);
blocking_deadline, transfer_type, dst_node_id, *tid);
}
else
{
return sender_->send(buf->getDataPtr(), buf->getDataLength(), getTxDeadline(),
monotonic_blocking_deadline, transfer_type, dst_node_id);
blocking_deadline, transfer_type, dst_node_id);
}
}
protected:
GenericPublisher(Scheduler& scheduler, IMarshalBufferProvider& buffer_provider,
uint64_t max_transfer_interval = TransferSender::DefaultMaxTransferInterval)
MonotonicDuration max_transfer_interval = TransferSender::getDefaultMaxTransferInterval())
: max_transfer_interval_(max_transfer_interval)
, tx_timeout_(DefaultTxTimeoutUsec)
, tx_timeout_(getDefaultTxTimeout())
, scheduler_(scheduler)
, buffer_provider_(buffer_provider)
{ }
@@ -110,22 +105,25 @@ protected:
~GenericPublisher() { }
int publish(const DataStruct& message, TransferType transfer_type, NodeID dst_node_id,
uint64_t monotonic_blocking_deadline = 0)
MonotonicTime blocking_deadline = MonotonicTime())
{
return genericPublish(message, transfer_type, dst_node_id, NULL, monotonic_blocking_deadline);
return genericPublish(message, transfer_type, dst_node_id, NULL, blocking_deadline);
}
int publish(const DataStruct& message, TransferType transfer_type, NodeID dst_node_id, TransferID tid,
uint64_t monotonic_blocking_deadline = 0)
MonotonicTime blocking_deadline = MonotonicTime())
{
return genericPublish(message, transfer_type, dst_node_id, &tid, monotonic_blocking_deadline);
return genericPublish(message, transfer_type, dst_node_id, &tid, blocking_deadline);
}
public:
uint64_t getTxTimeout() const { return tx_timeout_; }
void setTxTimeout(uint64_t usec)
static MonotonicDuration getDefaultTxTimeout() { return MonotonicDuration::fromUSec(2500); }// 2500ms --> 400Hz max
static MonotonicDuration getMinTxTimeout() { return MonotonicDuration::fromUSec(200); }
MonotonicDuration getTxTimeout() const { return tx_timeout_; }
void setTxTimeout(MonotonicDuration tx_timeout)
{
tx_timeout_ = std::max(usec, uint64_t(MinTxTimeoutUsec));
tx_timeout_ = std::max(tx_timeout, getMinTxTimeout());
}
Scheduler& getScheduler() const { return scheduler_; }
@@ -45,8 +45,11 @@ protected:
public:
typedef DataType_ DataType;
uint64_t getMonotonicTimestamp() const { return safeget<uint64_t, &IncomingTransfer::getMonotonicTimestamp>(); }
uint64_t getUtcTimestamp() const { return safeget<uint64_t, &IncomingTransfer::getUtcTimestamp>(); }
MonotonicTime getMonotonicTimestamp() const
{
return safeget<MonotonicTime, &IncomingTransfer::getMonotonicTimestamp>();
}
UtcTime getUtcTimestamp() const { return safeget<UtcTime, &IncomingTransfer::getUtcTimestamp>(); }
TransferType getTransferType() const { return safeget<TransferType, &IncomingTransfer::getTransferType>(); }
TransferID getTransferID() const { return safeget<TransferID, &IncomingTransfer::getTransferID>(); }
NodeID getSrcNodeID() const { return safeget<NodeID, &IncomingTransfer::getSrcNodeID>(); }
@@ -14,29 +14,28 @@ class Scheduler;
class MonotonicDeadlineHandler : public LinkedListNode<MonotonicDeadlineHandler>, Noncopyable
{
uint64_t monotonic_deadline_;
MonotonicTime deadline_;
protected:
Scheduler& scheduler_;
explicit MonotonicDeadlineHandler(Scheduler& scheduler)
: monotonic_deadline_(0)
, scheduler_(scheduler)
: scheduler_(scheduler)
{ }
virtual ~MonotonicDeadlineHandler() { stop(); }
public:
virtual void handleMonotonicDeadline(uint64_t monotonic_timestamp) = 0;
virtual void handleDeadline(MonotonicTime current_timestamp) = 0;
void startWithDeadline(uint64_t monotonic_deadline);
void startWithDelay(uint64_t delay_usec);
void startWithDeadline(MonotonicTime deadline);
void startWithDelay(MonotonicDuration delay);
void stop();
bool isRunning() const;
uint64_t getMonotonicDeadline() const { return monotonic_deadline_; }
MonotonicTime getDeadline() const { return deadline_; }
Scheduler& getScheduler() const { return scheduler_; }
};
@@ -51,8 +50,8 @@ public:
bool doesExist(const MonotonicDeadlineHandler* mdh) const;
unsigned int getNumHandlers() const { return handlers_.getLength(); }
uint64_t pollAndGetMonotonicTimestamp(ISystemClock& sysclock);
uint64_t getEarliestDeadline() const;
MonotonicTime pollAndGetMonotonicTimestamp(ISystemClock& sysclock);
MonotonicTime getEarliestDeadline() const;
};
@@ -68,45 +67,45 @@ class Scheduler : Noncopyable
MonotonicDeadlineScheduler deadline_scheduler_;
Dispatcher dispatcher_;
uint64_t prev_cleanup_ts_;
uint64_t monotonic_deadline_resolution_;
uint64_t cleanup_period_;
MonotonicTime prev_cleanup_ts_;
MonotonicDuration deadline_resolution_;
MonotonicDuration cleanup_period_;
uint64_t computeDispatcherSpinDeadline(uint64_t spin_deadline) const;
void pollCleanup(uint64_t mono_ts, uint32_t num_frames_processed_with_last_spin);
MonotonicTime computeDispatcherSpinDeadline(MonotonicTime spin_deadline) const;
void pollCleanup(MonotonicTime mono_ts, uint32_t num_frames_processed_with_last_spin);
public:
Scheduler(ICanDriver& can_driver, IAllocator& allocator, ISystemClock& sysclock, IOutgoingTransferRegistry& otr,
NodeID self_node_id)
: dispatcher_(can_driver, allocator, sysclock, otr, self_node_id)
, prev_cleanup_ts_(sysclock.getMonotonicMicroseconds())
, monotonic_deadline_resolution_(DefaultMonotonicDeadlineResolutionMs * 1000)
, cleanup_period_(DefaultCleanupPeriodMs * 1000)
, prev_cleanup_ts_(sysclock.getMonotonic())
, deadline_resolution_(MonotonicDuration::fromMSec(DefaultMonotonicDeadlineResolutionMs))
, cleanup_period_(MonotonicDuration::fromMSec(DefaultCleanupPeriodMs))
{ }
int spin(uint64_t monotonic_deadline);
int spin(MonotonicTime deadline);
MonotonicDeadlineScheduler& getMonotonicDeadlineScheduler() { return deadline_scheduler_; }
Dispatcher& getDispatcher() { return dispatcher_; }
ISystemClock& getSystemClock() { return dispatcher_.getSystemClock(); }
uint64_t getMonotonicTimestamp() const { return dispatcher_.getSystemClock().getMonotonicMicroseconds(); }
uint64_t getUtcTimestamp() const { return dispatcher_.getSystemClock().getUtcMicroseconds(); }
ISystemClock& getSystemClock() { return dispatcher_.getSystemClock(); }
MonotonicTime getMonotonicTimestamp() const { return dispatcher_.getSystemClock().getMonotonic(); }
UtcTime getUtcTimestamp() const { return dispatcher_.getSystemClock().getUtc(); }
uint64_t getMonotonicDeadlineResolution() const { return monotonic_deadline_resolution_; }
void setMonotonicDeadlineResolution(uint64_t res_usec)
MonotonicDuration getMonotonicDeadlineResolution() const { return deadline_resolution_; }
void setMonotonicDeadlineResolution(MonotonicDuration res)
{
res_usec = std::min(res_usec, MaxMonotonicDeadlineResolutionMs * uint64_t(1000));
res_usec = std::max(res_usec, MinMonotonicDeadlineResolutionMs * uint64_t(1000));
monotonic_deadline_resolution_ = res_usec;
res = std::min(res, MonotonicDuration::fromMSec(MaxMonotonicDeadlineResolutionMs));
res = std::max(res, MonotonicDuration::fromMSec(MinMonotonicDeadlineResolutionMs));
deadline_resolution_ = res;
}
uint64_t getCleanupPeriod() const { return cleanup_period_; }
void setCleanupPeriod(uint64_t period_usec)
MonotonicDuration getCleanupPeriod() const { return cleanup_period_; }
void setCleanupPeriod(MonotonicDuration period)
{
period_usec = std::min(period_usec, MaxCleanupPeriodMs * uint64_t(1000));
period_usec = std::max(period_usec, MinCleanupPeriodMs * uint64_t(1000));
cleanup_period_ = period_usec;
period = std::min(period, MonotonicDuration::fromMSec(MaxCleanupPeriodMs));
period = std::max(period, MonotonicDuration::fromMSec(MinCleanupPeriodMs));
cleanup_period_ = period;
}
};
@@ -13,20 +13,19 @@
#include <uavcan/util/compile_time.hpp>
#include <uavcan/can_driver.hpp>
#include <uavcan/system_clock.hpp>
#include <uavcan/time.hpp>
namespace uavcan
{
struct CanRxFrame : public CanFrame
{
uint64_t ts_monotonic;
uint64_t ts_utc;
MonotonicTime ts_mono;
UtcTime ts_utc;
uint8_t iface_index;
CanRxFrame()
: ts_monotonic(0)
, ts_utc(0)
, iface_index(0)
: iface_index(0)
{ }
std::string toString(StringRepresentation mode = StrTight) const;
@@ -40,12 +39,12 @@ public:
struct Entry : public LinkedListNode<Entry> // Not required to be packed - fits the block in any case
{
uint64_t monotonic_deadline;
MonotonicTime deadline;
CanFrame frame;
uint8_t qos;
Entry(const CanFrame& frame, uint64_t monotonic_deadline, Qos qos)
: monotonic_deadline(monotonic_deadline)
Entry(const CanFrame& frame, MonotonicTime deadline, Qos qos)
: deadline(deadline)
, frame(frame)
, qos(uint8_t(qos))
{
@@ -55,7 +54,7 @@ public:
static void destroy(Entry*& obj, IAllocator& allocator);
bool isExpired(uint64_t monotonic_timestamp) const { return monotonic_timestamp > monotonic_deadline; }
bool isExpired(MonotonicTime timestamp) const { return timestamp > deadline; }
bool qosHigherThan(const CanFrame& rhs_frame, Qos rhs_qos) const;
bool qosLowerThan(const CanFrame& rhs_frame, Qos rhs_qos) const;
@@ -100,7 +99,7 @@ public:
~CanTxQueue();
void push(const CanFrame& frame, uint64_t monotonic_tx_deadline, Qos qos);
void push(const CanFrame& frame, MonotonicTime tx_deadline, Qos qos);
Entry* peek(); // Modifier
void remove(Entry*& entry);
@@ -128,10 +127,9 @@ private:
CanIOManager(CanIOManager&);
CanIOManager& operator=(CanIOManager&);
int sendToIface(int iface_index, const CanFrame& frame, uint64_t monotonic_tx_deadline);
int sendToIface(int iface_index, const CanFrame& frame, MonotonicTime tx_deadline);
int sendFromTxQueue(int iface_index);
int makePendingTxMask() const;
uint64_t getTimeUntilMonotonicDeadline(uint64_t monotonic_deadline) const;
public:
CanIOManager(ICanDriver& driver, IAllocator& allocator, ISystemClock& sysclock)
@@ -157,9 +155,9 @@ public:
* 1+ - sent/received
* negative - failure
*/
int send(const CanFrame& frame, uint64_t monotonic_tx_deadline, uint64_t monotonic_blocking_deadline,
int send(const CanFrame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline,
int iface_mask, CanTxQueue::Qos qos);
int receive(CanRxFrame& frame, uint64_t monotonic_blocking_deadline);
int receive(CanRxFrame& frame, MonotonicTime blocking_deadline);
};
}
@@ -41,7 +41,7 @@ class Dispatcher : Noncopyable
bool add(TransferListenerBase* listener, Mode mode);
void remove(TransferListenerBase* listener);
void cleanup(uint64_t ts_monotonic);
void cleanup(MonotonicTime ts);
void handleFrame(const RxFrame& frame);
int getNumEntries() const { return list_.getLength(); }
@@ -64,15 +64,14 @@ public:
, self_node_id_(self_node_id)
{ }
int spin(uint64_t monotonic_deadline);
int spin(MonotonicTime deadline);
/**
* Refer to CanIOManager::send() for the parameter description
*/
int send(const Frame& frame, uint64_t monotonic_tx_deadline, uint64_t monotonic_blocking_deadline,
CanTxQueue::Qos qos);
int send(const Frame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, CanTxQueue::Qos qos);
void cleanup(uint64_t ts_monotonic);
void cleanup(MonotonicTime ts);
bool registerMessageListener(TransferListenerBase* listener);
bool registerServiceRequestListener(TransferListenerBase* listener);
@@ -54,8 +54,8 @@ class IOutgoingTransferRegistry
{
public:
virtual ~IOutgoingTransferRegistry() { }
virtual TransferID* accessOrCreate(const OutgoingTransferRegistryKey& key, uint64_t new_monotonic_deadline) = 0;
virtual void cleanup(uint64_t monotonic_deadline) = 0;
virtual TransferID* accessOrCreate(const OutgoingTransferRegistryKey& key, MonotonicTime new_deadline) = 0;
virtual void cleanup(MonotonicTime deadline) = 0;
};
@@ -65,26 +65,25 @@ class OutgoingTransferRegistry : public IOutgoingTransferRegistry, Noncopyable
UAVCAN_PACKED_BEGIN
struct Value
{
uint64_t monotonic_deadline;
MonotonicTime deadline;
TransferID tid;
Value() : monotonic_deadline(0) { }
};
UAVCAN_PACKED_END
class DeadlineExpiredPredicate
{
const uint64_t ts_monotonic_;
const MonotonicTime ts_;
public:
DeadlineExpiredPredicate(uint64_t ts_monotonic)
: ts_monotonic_(ts_monotonic)
DeadlineExpiredPredicate(MonotonicTime ts)
: ts_(ts)
{ }
bool operator()(const OutgoingTransferRegistryKey& key, const Value& value) const
{
(void)key;
assert(value.monotonic_deadline > 0);
return value.monotonic_deadline <= ts_monotonic_;
assert(!value.deadline.isZero());
return value.deadline <= ts_;
}
};
@@ -95,21 +94,21 @@ public:
: map_(allocator)
{ }
TransferID* accessOrCreate(const OutgoingTransferRegistryKey& key, uint64_t new_monotonic_deadline)
TransferID* accessOrCreate(const OutgoingTransferRegistryKey& key, MonotonicTime new_deadline)
{
assert(new_monotonic_deadline > 0);
assert(!new_deadline.isZero());
Value* p = map_.access(key);
if (p == NULL)
p = map_.insert(key, Value());
if (p == NULL)
return NULL;
p->monotonic_deadline = new_monotonic_deadline;
p->deadline = new_deadline;
return &p->tid;
}
void cleanup(uint64_t ts_monotonic)
void cleanup(MonotonicTime ts)
{
map_.removeWhere(DeadlineExpiredPredicate(ts_monotonic));
map_.removeWhere(DeadlineExpiredPredicate(ts));
}
};
@@ -7,11 +7,13 @@
#include <cassert>
#include <algorithm>
#include <string>
#include <uavcan/internal/transport/can_io.hpp>
#include <uavcan/can_driver.hpp>
namespace uavcan
{
struct CanRxFrame;
enum { MaxTransferPayloadLen = 439 }; ///< According to the standard
enum { MaxSingleFrameTransferPayloadLen = 7 };
@@ -175,37 +177,27 @@ public:
class RxFrame : public Frame
{
uint64_t ts_monotonic_;
uint64_t ts_utc_;
MonotonicTime ts_mono_;
UtcTime ts_utc_;
uint8_t iface_index_;
public:
RxFrame()
: ts_monotonic_(0)
, ts_utc_(0)
, iface_index_(0)
: iface_index_(0)
{ }
RxFrame(const Frame& frame, uint64_t ts_monotonic, uint64_t ts_utc, uint8_t iface_index)
: ts_monotonic_(ts_monotonic)
RxFrame(const Frame& frame, MonotonicTime ts_mono, UtcTime ts_utc, uint8_t iface_index)
: ts_mono_(ts_mono)
, ts_utc_(ts_utc)
, iface_index_(iface_index)
{
*static_cast<Frame*>(this) = frame;
}
bool parse(const CanRxFrame& can_frame)
{
if (!Frame::parse(can_frame))
return false;
ts_monotonic_ = can_frame.ts_monotonic;
ts_utc_ = can_frame.ts_utc;
iface_index_ = can_frame.iface_index;
return true;
}
bool parse(const CanRxFrame& can_frame);
uint64_t getMonotonicTimestamp() const { return ts_monotonic_; }
uint64_t getUtcTimestamp() const { return ts_utc_; }
MonotonicTime getMonotonicTimestamp() const { return ts_mono_; }
UtcTime getUtcTimestamp() const { return ts_utc_; }
uint8_t getIfaceIndex() const { return iface_index_; }
@@ -9,6 +9,7 @@
#include <limits>
#include <uavcan/internal/transport/transfer.hpp>
#include <uavcan/internal/linked_list.hpp>
#include <uavcan/internal/dynamic_memory.hpp>
#include <uavcan/internal/impl_constants.hpp>
#include <uavcan/internal/debug.hpp>
@@ -21,8 +21,8 @@ namespace uavcan
*/
class IncomingTransfer : public ITransferBuffer
{
uint64_t ts_monotonic_;
uint64_t ts_utc_;
MonotonicTime ts_mono_;
UtcTime ts_utc_;
TransferType transfer_type_;
TransferID transfer_id_;
NodeID src_node_id_;
@@ -31,9 +31,9 @@ class IncomingTransfer : public ITransferBuffer
int write(unsigned int offset, const uint8_t* data, unsigned int len);
protected:
IncomingTransfer(uint64_t ts_monotonic, uint64_t ts_utc, TransferType transfer_type,
IncomingTransfer(MonotonicTime ts_mono, UtcTime ts_utc, TransferType transfer_type,
TransferID transfer_id, NodeID source_node_id)
: ts_monotonic_(ts_monotonic)
: ts_mono_(ts_mono)
, ts_utc_(ts_utc)
, transfer_type_(transfer_type)
, transfer_id_(transfer_id)
@@ -46,11 +46,11 @@ public:
*/
virtual void release() { }
uint64_t getMonotonicTimestamp() const { return ts_monotonic_; }
uint64_t getUtcTimestamp() const { return ts_utc_; }
TransferType getTransferType() const { return transfer_type_; }
TransferID getTransferID() const { return transfer_id_; }
NodeID getSrcNodeID() const { return src_node_id_; }
MonotonicTime getMonotonicTimestamp() const { return ts_mono_; }
UtcTime getUtcTimestamp() const { return ts_utc_; }
TransferType getTransferType() const { return transfer_type_; }
TransferID getTransferID() const { return transfer_id_; }
NodeID getSrcNodeID() const { return src_node_id_; }
};
/**
@@ -72,7 +72,7 @@ class MultiFrameIncomingTransfer : public IncomingTransfer, Noncopyable
{
TransferBufferAccessor& buf_acc_;
public:
MultiFrameIncomingTransfer(uint64_t ts_monotonic, uint64_t ts_utc, const RxFrame& last_frame,
MultiFrameIncomingTransfer(MonotonicTime ts_mono, UtcTime ts_utc, const RxFrame& last_frame,
TransferBufferAccessor& tba);
int read(unsigned int offset, uint8_t* data, unsigned int len) const;
void release() { buf_acc_.remove(); }
@@ -104,7 +104,7 @@ public:
const DataTypeDescriptor& getDataTypeDescriptor() const { return data_type_; }
virtual void handleFrame(const RxFrame& frame) = 0;
virtual void cleanup(uint64_t ts_monotonic) = 0;
virtual void cleanup(MonotonicTime ts) = 0;
};
/**
@@ -141,18 +141,18 @@ class TransferListener : public TransferListenerBase, Noncopyable
class TimedOutReceiverPredicate
{
const uint64_t ts_monotonic_;
const MonotonicTime ts_;
BufferManager& bufmgr_;
public:
TimedOutReceiverPredicate(uint64_t ts_monotonic, BufferManager& bufmgr)
: ts_monotonic_(ts_monotonic)
TimedOutReceiverPredicate(MonotonicTime ts, BufferManager& bufmgr)
: ts_(ts)
, bufmgr_(bufmgr)
{ }
bool operator()(const TransferBufferManagerKey& key, const TransferReceiver& value) const
{
if (value.isTimedOut(ts_monotonic_))
if (value.isTimedOut(ts_))
{
UAVCAN_TRACE("TransferListener", "Timed out receiver: %s", key.toString().c_str());
/*
@@ -168,9 +168,9 @@ class TransferListener : public TransferListenerBase, Noncopyable
}
};
void cleanup(uint64_t ts_monotonic)
void cleanup(MonotonicTime ts)
{
receivers_.removeWhere(TimedOutReceiverPredicate(ts_monotonic, bufmgr_));
receivers_.removeWhere(TimedOutReceiverPredicate(ts, bufmgr_));
assert(receivers_.isEmpty() ? bufmgr_.isEmpty() : 1);
}
@@ -17,18 +17,25 @@ class TransferReceiver
public:
enum ResultCode { ResultNotComplete, ResultComplete, ResultSingleFrame };
static const uint32_t DefaultTransferInterval = 500 * 1000UL;
static const uint32_t MinTransferInterval = 1 * 1000UL;
static const uint32_t MaxTransferInterval = 10 * 1000 * 1000UL;
static const uint32_t DefaultTransferIntervalUSec = 500 * 1000UL;
static const uint32_t MinTransferIntervalUSec = 1 * 1000UL;
static const uint32_t MaxTransferIntervalUSec = 10 * 1000 * 1000UL;
static MonotonicDuration getDefaultTransferInterval()
{
return MonotonicDuration::fromUSec(DefaultTransferIntervalUSec);
}
static MonotonicDuration getMinTransferInterval() { return MonotonicDuration::fromUSec(MinTransferIntervalUSec); }
static MonotonicDuration getMaxTransferInterval() { return MonotonicDuration::fromUSec(MaxTransferIntervalUSec); }
private:
enum TidRelation { TidSame, TidRepeat, TidFuture };
enum { IfaceIndexNotSet = 0xFF };
uint64_t prev_transfer_ts_monotonic_;
uint64_t this_transfer_ts_monotonic_;
uint64_t first_frame_ts_utc_;
uint32_t transfer_interval_;
MonotonicTime prev_transfer_ts_;
MonotonicTime this_transfer_ts_;
UtcTime first_frame_ts_;
uint32_t transfer_interval_usec_;
uint16_t this_transfer_crc_;
uint16_t buffer_write_pos_;
TransferID tid_;
@@ -48,26 +55,23 @@ private:
public:
TransferReceiver()
: prev_transfer_ts_monotonic_(0)
, this_transfer_ts_monotonic_(0)
, first_frame_ts_utc_(0)
, transfer_interval_(DefaultTransferInterval)
: transfer_interval_usec_(DefaultTransferIntervalUSec)
, this_transfer_crc_(0)
, buffer_write_pos_(0)
, iface_index_(IfaceIndexNotSet)
, next_frame_index_(0)
{ }
bool isTimedOut(uint64_t ts_monotonic) const;
bool isTimedOut(MonotonicTime current_ts) const;
ResultCode addFrame(const RxFrame& frame, TransferBufferAccessor& tba);
uint64_t getLastTransferTimestampMonotonic() const { return prev_transfer_ts_monotonic_; }
uint64_t getLastTransferTimestampUtc() const { return first_frame_ts_utc_; }
MonotonicTime getLastTransferTimestampMonotonic() const { return prev_transfer_ts_; }
UtcTime getLastTransferTimestampUtc() const { return first_frame_ts_; }
uint16_t getLastTransferCrc() const { return this_transfer_crc_; }
uint32_t getInterval() const { return transfer_interval_; }
MonotonicDuration getInterval() const { return MonotonicDuration::fromUSec(transfer_interval_usec_); }
};
UAVCAN_PACKED_END
@@ -16,7 +16,7 @@ namespace uavcan
class TransferSender
{
const uint64_t max_transfer_interval_;
const MonotonicDuration max_transfer_interval_;
const DataTypeDescriptor& data_type_;
const CanTxQueue::Qos qos_;
const TransferCRC crc_base_;
@@ -24,10 +24,13 @@ class TransferSender
Dispatcher& dispatcher_;
public:
static const uint64_t DefaultMaxTransferInterval = 60 * 1000 * 1000;
static MonotonicDuration getDefaultMaxTransferInterval()
{
return MonotonicDuration::fromMSec(60 * 1000);
}
TransferSender(Dispatcher& dispatcher, const DataTypeDescriptor& data_type, CanTxQueue::Qos qos,
uint64_t max_transfer_interval = DefaultMaxTransferInterval)
MonotonicDuration max_transfer_interval = getDefaultMaxTransferInterval())
: max_transfer_interval_(max_transfer_interval)
, data_type_(data_type)
, qos_(qos)
@@ -39,16 +42,16 @@ public:
* Send with explicit Transfer ID.
* Should be used only for service responses, where response TID should match request TID.
*/
int send(const uint8_t* payload, int payload_len, uint64_t monotonic_tx_deadline,
uint64_t monotonic_blocking_deadline, TransferType transfer_type, NodeID dst_node_id,
int send(const uint8_t* payload, int payload_len, MonotonicTime tx_deadline,
MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id,
TransferID tid);
/**
* Send with automatic Transfer ID.
* TID is managed by OutgoingTransferRegistry.
*/
int send(const uint8_t* payload, int payload_len, uint64_t monotonic_tx_deadline,
uint64_t monotonic_blocking_deadline, TransferType transfer_type, NodeID dst_node_id);
int send(const uint8_t* payload, int payload_len, MonotonicTime tx_deadline,
MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id);
};
}
+3 -3
View File
@@ -18,11 +18,11 @@ public:
typedef DataType_ DataType;
Publisher(Scheduler& scheduler, IMarshalBufferProvider& buffer_provider,
uint64_t tx_timeout_usec = BaseType::DefaultTxTimeoutUsec,
uint64_t max_transfer_interval = TransferSender::DefaultMaxTransferInterval)
MonotonicDuration tx_timeout = BaseType::getDefaultTxTimeout(),
MonotonicDuration max_transfer_interval = TransferSender::getDefaultMaxTransferInterval())
: BaseType(scheduler, buffer_provider, max_transfer_interval)
{
BaseType::setTxTimeout(tx_timeout_usec);
BaseType::setTxTimeout(tx_timeout);
StaticAssert<DataTypeKind(DataType::DataTypeKind) == DataTypeKindMessage>::check();
}
+8 -5
View File
@@ -6,9 +6,12 @@
#pragma once
#include <stdint.h>
#include <uavcan/internal/impl_constants.hpp>
#include <uavcan/time.hpp>
namespace uavcan
{
/**
* System clock interface - monotonic and UTC.
* Note that this library uses microseconds for all time related values (timestamps, deadlines, delays),
@@ -21,19 +24,19 @@ public:
virtual ~ISystemClock() { }
/**
* Monototic system clock in microseconds.
* Monototic system clock.
* This shall never jump during UTC timestamp adjustments; the base time is irrelevant.
* On POSIX systems use clock_gettime() with CLOCK_MONOTONIC.
*/
virtual uint64_t getMonotonicMicroseconds() const = 0;
virtual MonotonicTime getMonotonic() const = 0;
/**
* UTC clock in microseconds.
* UTC clock.
* This can jump when the UTC timestamp is being adjusted.
* Return 0 if the UTC time is not available yet (e.g. the device just started up with no battery clock).
* On POSIX systems use gettimeofday().
*/
virtual uint64_t getUtcMicroseconds() const = 0;
virtual UtcTime getUtc() const = 0;
/**
* Set the UTC system clock.
@@ -41,7 +44,7 @@ public:
* @param [in] offset Current UTC time error. More precise than just timestamp, use it if possible.
* For POSIX refer to adjtime(), settimeofday().
*/
virtual void adjustUtcMicroseconds(uint64_t new_timestamp_usec, int64_t offset_usec) = 0;
virtual void adjustUtc(UtcTime new_time, UtcDuration offset) = 0;
};
}
+25 -24
View File
@@ -10,7 +10,15 @@
#include <sstream>
#include <cstdio>
#include <uavcan/util/compile_time.hpp>
#include <uavcan/Timestamp.hpp>
// TODO: Fix inclusion loops!
namespace uavcan
{
struct Timestamp_;
typedef Timestamp_ Timestamp;
}
namespace uavcan
{
@@ -27,6 +35,8 @@ public:
StaticAssert<(sizeof(D) == 8)>::check();
}
static D getInfinite() { return fromUSec(std::numeric_limits<int64_t>::max()); }
static D fromUSec(int64_t us)
{
D d;
@@ -95,6 +105,8 @@ public:
StaticAssert<(sizeof(D) == 8)>::check();
}
static T getMax() { return fromUSec(std::numeric_limits<uint64_t>::max()); }
static T fromUSec(uint64_t us)
{
T d;
@@ -120,15 +132,15 @@ public:
{
if (r.isNegative())
{
if (uint64_t(r.getAbs().usec_) > usec_)
if (uint64_t(r.getAbs().toUSec()) > usec_)
return fromUSec(0);
}
else
{
if (uint64_t(usec_ + r.usec_) < usec_)
if (uint64_t(usec_ + r.toUSec()) < usec_)
return fromUSec(std::numeric_limits<uint64_t>::max());
}
return fromUSec(usec_ + r.usec_);
return fromUSec(usec_ + r.toUSec());
}
T operator-(const D& r) const
@@ -154,36 +166,25 @@ public:
std::string toString() const;
};
/*
* Monotonic
*/
class MonotonicDuration : public DurationBase<MonotonicDuration> { };
class MonotonicTime : public TimeBase<MonotonicTime, MonotonicDuration> { };
/*
* UTC
*/
class UtcDuration : public DurationBase<UtcDuration> { };
class UtcTime : public TimeBase<UtcTime, UtcDuration>
{
public:
UtcTime() { }
UtcTime(const Timestamp& ts) // Implicit
{
operator=(ts);
}
UtcTime& operator=(const Timestamp& ts)
{
*this = fromUSec(ts.husec * Timestamp::USEC_PER_LSB);
return *this;
}
operator Timestamp() const
{
Timestamp ts;
ts.husec = toUSec() / Timestamp::USEC_PER_LSB;
return ts;
}
UtcTime(const Timestamp& ts); // Implicit
UtcTime& operator=(const Timestamp& ts);
operator Timestamp() const;
};
+13 -15
View File
@@ -17,13 +17,13 @@ class Timer;
struct TimerEvent
{
uint64_t scheduled_monotonic_deadline;
uint64_t monotonic_timestamp;
MonotonicTime scheduled_deadline;
MonotonicTime current_timestamp;
Timer* timer;
TimerEvent(Timer* timer, uint64_t scheduled_monotonic_deadline, uint64_t monotonic_timestamp)
: scheduled_monotonic_deadline(scheduled_monotonic_deadline)
, monotonic_timestamp(monotonic_timestamp)
TimerEvent(Timer* timer, MonotonicTime scheduled_deadline, MonotonicTime current_timestamp)
: scheduled_deadline(scheduled_deadline)
, current_timestamp(current_timestamp)
, timer(timer)
{ }
};
@@ -31,28 +31,26 @@ struct TimerEvent
class Timer : private MonotonicDeadlineHandler
{
uint64_t period_;
MonotonicDuration period_;
void handleMonotonicDeadline(uint64_t monotonic_timestamp);
void handleDeadline(MonotonicTime current_timestamp);
public:
static const uint64_t InfinitePeriod = 0xFFFFFFFFFFFFFFFFUL;
using MonotonicDeadlineHandler::stop;
using MonotonicDeadlineHandler::isRunning;
using MonotonicDeadlineHandler::getMonotonicDeadline;
using MonotonicDeadlineHandler::getDeadline;
using MonotonicDeadlineHandler::getScheduler;
explicit Timer(Scheduler& scheduler)
: MonotonicDeadlineHandler(scheduler)
, period_(InfinitePeriod)
, period_(MonotonicDuration::getInfinite())
{ }
void startOneShotWithDeadline(uint64_t monotonic_deadline);
void startOneShotWithDelay(uint64_t delay_usec);
void startPeriodic(uint64_t period_usec);
void startOneShotWithDeadline(MonotonicTime deadline);
void startOneShotWithDelay(MonotonicDuration delay);
void startPeriodic(MonotonicDuration period);
uint64_t getPeriod() const { return period_; }
MonotonicDuration getPeriod() const { return period_; }
virtual void handleTimerEvent(const TimerEvent& event) = 0;
};