mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-21 10:53:34 +08:00
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:
@@ -7,6 +7,7 @@
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
#include <uavcan/data_type.hpp>
|
||||
#include <uavcan/internal/transport/crc.hpp>
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <uavcan/internal/node/scheduler.hpp>
|
||||
#include <uavcan/internal/debug.hpp>
|
||||
|
||||
@@ -12,17 +11,17 @@ namespace uavcan
|
||||
/*
|
||||
* MonotonicDeadlineHandler
|
||||
*/
|
||||
void MonotonicDeadlineHandler::startWithDeadline(uint64_t monotonic_deadline)
|
||||
void MonotonicDeadlineHandler::startWithDeadline(MonotonicTime deadline)
|
||||
{
|
||||
assert(monotonic_deadline > 0);
|
||||
assert(!deadline.isZero());
|
||||
stop();
|
||||
monotonic_deadline_ = monotonic_deadline;
|
||||
deadline_ = deadline;
|
||||
scheduler_.getMonotonicDeadlineScheduler().add(this);
|
||||
}
|
||||
|
||||
void MonotonicDeadlineHandler::startWithDelay(uint64_t delay_usec)
|
||||
void MonotonicDeadlineHandler::startWithDelay(MonotonicDuration delay)
|
||||
{
|
||||
startWithDeadline(scheduler_.getMonotonicTimestamp() + delay_usec);
|
||||
startWithDeadline(scheduler_.getMonotonicTimestamp() + delay);
|
||||
}
|
||||
|
||||
void MonotonicDeadlineHandler::stop()
|
||||
@@ -40,18 +39,18 @@ bool MonotonicDeadlineHandler::isRunning() const
|
||||
*/
|
||||
struct MonotonicDeadlineHandlerInsertionComparator
|
||||
{
|
||||
const uint64_t ts;
|
||||
MonotonicDeadlineHandlerInsertionComparator(uint64_t ts) : ts(ts) { }
|
||||
const MonotonicTime ts;
|
||||
MonotonicDeadlineHandlerInsertionComparator(MonotonicTime ts) : ts(ts) { }
|
||||
bool operator()(const MonotonicDeadlineHandler* t) const
|
||||
{
|
||||
return t->getMonotonicDeadline() > ts;
|
||||
return t->getDeadline() > ts;
|
||||
}
|
||||
};
|
||||
|
||||
void MonotonicDeadlineScheduler::add(MonotonicDeadlineHandler* mdh)
|
||||
{
|
||||
assert(mdh);
|
||||
handlers_.insertBefore(mdh, MonotonicDeadlineHandlerInsertionComparator(mdh->getMonotonicDeadline()));
|
||||
handlers_.insertBefore(mdh, MonotonicDeadlineHandlerInsertionComparator(mdh->getDeadline()));
|
||||
}
|
||||
|
||||
void MonotonicDeadlineScheduler::remove(MonotonicDeadlineHandler* mdh)
|
||||
@@ -65,14 +64,14 @@ bool MonotonicDeadlineScheduler::doesExist(const MonotonicDeadlineHandler* mdh)
|
||||
assert(mdh);
|
||||
const MonotonicDeadlineHandler* p = handlers_.get();
|
||||
#if UAVCAN_DEBUG
|
||||
uint64_t prev_deadline = 0;
|
||||
MonotonicTime prev_deadline;
|
||||
#endif
|
||||
while (p)
|
||||
{
|
||||
#if UAVCAN_DEBUG
|
||||
if (prev_deadline > p->getMonotonicDeadline()) // Self check
|
||||
if (prev_deadline > p->getDeadline()) // Self check
|
||||
std::abort();
|
||||
prev_deadline = p->getMonotonicDeadline();
|
||||
prev_deadline = p->getDeadline();
|
||||
#endif
|
||||
if (p == mdh)
|
||||
return true;
|
||||
@@ -81,56 +80,56 @@ bool MonotonicDeadlineScheduler::doesExist(const MonotonicDeadlineHandler* mdh)
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t MonotonicDeadlineScheduler::pollAndGetMonotonicTimestamp(ISystemClock& sysclock)
|
||||
MonotonicTime MonotonicDeadlineScheduler::pollAndGetMonotonicTimestamp(ISystemClock& sysclock)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
MonotonicDeadlineHandler* const mdh = handlers_.get();
|
||||
if (!mdh)
|
||||
return sysclock.getMonotonicMicroseconds();
|
||||
return sysclock.getMonotonic();
|
||||
#if UAVCAN_DEBUG
|
||||
if (mdh->getNextListNode()) // Order check
|
||||
assert(mdh->getMonotonicDeadline() <= mdh->getNextListNode()->getMonotonicDeadline());
|
||||
assert(mdh->getDeadline() <= mdh->getNextListNode()->getDeadline());
|
||||
#endif
|
||||
|
||||
const uint64_t ts = sysclock.getMonotonicMicroseconds();
|
||||
if (ts < mdh->getMonotonicDeadline())
|
||||
const MonotonicTime ts = sysclock.getMonotonic();
|
||||
if (ts < mdh->getDeadline())
|
||||
return ts;
|
||||
|
||||
handlers_.remove(mdh);
|
||||
mdh->handleMonotonicDeadline(ts); // This handler can be re-registered immediately
|
||||
mdh->handleDeadline(ts); // This handler can be re-registered immediately
|
||||
}
|
||||
assert(0);
|
||||
return 0;
|
||||
return MonotonicTime();
|
||||
}
|
||||
|
||||
uint64_t MonotonicDeadlineScheduler::getEarliestDeadline() const
|
||||
MonotonicTime MonotonicDeadlineScheduler::getEarliestDeadline() const
|
||||
{
|
||||
const MonotonicDeadlineHandler* const mdh = handlers_.get();
|
||||
if (mdh)
|
||||
return mdh->getMonotonicDeadline();
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
return mdh->getDeadline();
|
||||
return MonotonicTime::getMax();
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler
|
||||
*/
|
||||
uint64_t Scheduler::computeDispatcherSpinDeadline(uint64_t spin_deadline) const
|
||||
MonotonicTime Scheduler::computeDispatcherSpinDeadline(MonotonicTime spin_deadline) const
|
||||
{
|
||||
const uint64_t earliest = std::min(deadline_scheduler_.getEarliestDeadline(), spin_deadline);
|
||||
const uint64_t ts = getMonotonicTimestamp();
|
||||
const MonotonicTime earliest = std::min(deadline_scheduler_.getEarliestDeadline(), spin_deadline);
|
||||
const MonotonicTime ts = getMonotonicTimestamp();
|
||||
if (earliest > ts)
|
||||
{
|
||||
if (ts - earliest > monotonic_deadline_resolution_)
|
||||
return ts + monotonic_deadline_resolution_;
|
||||
if (ts - earliest > deadline_resolution_)
|
||||
return ts + deadline_resolution_;
|
||||
}
|
||||
return earliest;
|
||||
}
|
||||
|
||||
void Scheduler::pollCleanup(uint64_t mono_ts, uint32_t num_frames_processed_with_last_spin)
|
||||
void Scheduler::pollCleanup(MonotonicTime mono_ts, uint32_t num_frames_processed_with_last_spin)
|
||||
{
|
||||
// cleanup will be performed less frequently if the stack handles more frames per second
|
||||
const uint64_t deadline = prev_cleanup_ts_ + cleanup_period_ * (num_frames_processed_with_last_spin + 1);
|
||||
const MonotonicTime deadline = prev_cleanup_ts_ + cleanup_period_ * (num_frames_processed_with_last_spin + 1);
|
||||
if (mono_ts > deadline)
|
||||
{
|
||||
UAVCAN_TRACE("Scheduler", "Cleanup with %u processed frames", num_frames_processed_with_last_spin);
|
||||
@@ -139,19 +138,19 @@ void Scheduler::pollCleanup(uint64_t mono_ts, uint32_t num_frames_processed_with
|
||||
}
|
||||
}
|
||||
|
||||
int Scheduler::spin(uint64_t monotonic_deadline)
|
||||
int Scheduler::spin(MonotonicTime deadline)
|
||||
{
|
||||
int retval = 0;
|
||||
while (true)
|
||||
{
|
||||
const uint64_t dl = computeDispatcherSpinDeadline(monotonic_deadline);
|
||||
const MonotonicTime dl = computeDispatcherSpinDeadline(deadline);
|
||||
retval = dispatcher_.spin(dl);
|
||||
if (retval < 0)
|
||||
break;
|
||||
|
||||
const uint64_t ts = deadline_scheduler_.pollAndGetMonotonicTimestamp(getSystemClock());
|
||||
const MonotonicTime ts = deadline_scheduler_.pollAndGetMonotonicTimestamp(getSystemClock());
|
||||
pollCleanup(ts, retval);
|
||||
if (ts >= monotonic_deadline)
|
||||
if (ts >= deadline)
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
|
||||
@@ -19,7 +19,7 @@ std::string CanRxFrame::toString(StringRepresentation mode) const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << CanFrame::toString(mode)
|
||||
<< " ts_m=" << ts_monotonic << " ts_utc=" << ts_utc << " iface=" << int(iface_index);
|
||||
<< " ts_m=" << ts_mono << " ts_utc=" << ts_utc << " iface=" << int(iface_index);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@@ -88,11 +88,11 @@ void CanTxQueue::registerRejectedFrame()
|
||||
rejected_frames_cnt_++;
|
||||
}
|
||||
|
||||
void CanTxQueue::push(const CanFrame& frame, uint64_t monotonic_tx_deadline, Qos qos)
|
||||
void CanTxQueue::push(const CanFrame& frame, MonotonicTime tx_deadline, Qos qos)
|
||||
{
|
||||
const uint64_t timestamp = sysclock_->getMonotonicMicroseconds();
|
||||
const MonotonicTime timestamp = sysclock_->getMonotonic();
|
||||
|
||||
if (timestamp >= monotonic_tx_deadline)
|
||||
if (timestamp >= tx_deadline)
|
||||
{
|
||||
UAVCAN_TRACE("CanTxQueue", "Push rejected: already expired");
|
||||
registerRejectedFrame();
|
||||
@@ -147,14 +147,14 @@ void CanTxQueue::push(const CanFrame& frame, uint64_t monotonic_tx_deadline, Qos
|
||||
if (praw == NULL)
|
||||
return; // Seems that there is no memory at all.
|
||||
|
||||
Entry* entry = new (praw) Entry(frame, monotonic_tx_deadline, qos);
|
||||
Entry* entry = new (praw) Entry(frame, tx_deadline, qos);
|
||||
assert(entry);
|
||||
queue_.insertBefore(entry, PriorityInsertionComparator(frame));
|
||||
}
|
||||
|
||||
CanTxQueue::Entry* CanTxQueue::peek()
|
||||
{
|
||||
const uint64_t timestamp = sysclock_->getMonotonicMicroseconds();
|
||||
const MonotonicTime timestamp = sysclock_->getMonotonic();
|
||||
Entry* p = queue_.get();
|
||||
while (p)
|
||||
{
|
||||
@@ -194,7 +194,7 @@ bool CanTxQueue::topPriorityHigherOrEqual(const CanFrame& rhs_frame) const
|
||||
/*
|
||||
* CanIOManager
|
||||
*/
|
||||
int CanIOManager::sendToIface(int iface_index, const CanFrame& frame, uint64_t monotonic_tx_deadline)
|
||||
int CanIOManager::sendToIface(int iface_index, const CanFrame& frame, MonotonicTime tx_deadline)
|
||||
{
|
||||
assert(iface_index >= 0 && iface_index < MaxIfaces);
|
||||
ICanIface* const iface = driver_.getIface(iface_index);
|
||||
@@ -203,9 +203,7 @@ int CanIOManager::sendToIface(int iface_index, const CanFrame& frame, uint64_t m
|
||||
assert(0); // Nonexistent interface
|
||||
return -1;
|
||||
}
|
||||
const uint64_t timestamp = sysclock_.getMonotonicMicroseconds();
|
||||
const uint64_t timeout = (timestamp >= monotonic_tx_deadline) ? 0 : (monotonic_tx_deadline - timestamp);
|
||||
const int res = iface->send(frame, timeout);
|
||||
const int res = iface->send(frame, tx_deadline);
|
||||
if (res != 1)
|
||||
{
|
||||
UAVCAN_TRACE("CanIOManager", "Send failed: code %i, iface %i, frame %s",
|
||||
@@ -220,7 +218,7 @@ int CanIOManager::sendFromTxQueue(int iface_index)
|
||||
CanTxQueue::Entry* entry = tx_queues_[iface_index].peek();
|
||||
if (entry == NULL)
|
||||
return 0;
|
||||
const int res = sendToIface(iface_index, entry->frame, entry->monotonic_deadline);
|
||||
const int res = sendToIface(iface_index, entry->frame, entry->deadline);
|
||||
if (res > 0)
|
||||
tx_queues_[iface_index].remove(entry);
|
||||
return res;
|
||||
@@ -237,12 +235,6 @@ int CanIOManager::makePendingTxMask() const
|
||||
return write_mask;
|
||||
}
|
||||
|
||||
uint64_t CanIOManager::getTimeUntilMonotonicDeadline(uint64_t monotonic_deadline) const
|
||||
{
|
||||
const uint64_t timestamp = sysclock_.getMonotonicMicroseconds();
|
||||
return (timestamp >= monotonic_deadline) ? 0 : (monotonic_deadline - timestamp);
|
||||
}
|
||||
|
||||
int CanIOManager::getNumIfaces() const
|
||||
{
|
||||
const int num = driver_.getNumIfaces();
|
||||
@@ -261,7 +253,7 @@ uint64_t CanIOManager::getNumErrors(int iface_index) const
|
||||
return iface->getNumErrors() + tx_queues_[iface_index].getNumRejectedFrames();
|
||||
}
|
||||
|
||||
int CanIOManager::send(const CanFrame& frame, uint64_t monotonic_tx_deadline, uint64_t monotonic_blocking_deadline,
|
||||
int CanIOManager::send(const CanFrame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline,
|
||||
int iface_mask, CanTxQueue::Qos qos)
|
||||
{
|
||||
const int num_ifaces = getNumIfaces();
|
||||
@@ -270,8 +262,8 @@ int CanIOManager::send(const CanFrame& frame, uint64_t monotonic_tx_deadline, ui
|
||||
assert((iface_mask & ~all_ifaces_mask) == 0);
|
||||
iface_mask &= all_ifaces_mask;
|
||||
|
||||
if (monotonic_blocking_deadline > monotonic_tx_deadline)
|
||||
monotonic_blocking_deadline = monotonic_tx_deadline;
|
||||
if (blocking_deadline > tx_deadline)
|
||||
blocking_deadline = tx_deadline;
|
||||
|
||||
int retval = 0;
|
||||
|
||||
@@ -280,11 +272,9 @@ int CanIOManager::send(const CanFrame& frame, uint64_t monotonic_tx_deadline, ui
|
||||
if (iface_mask == 0)
|
||||
break;
|
||||
int write_mask = iface_mask | makePendingTxMask();
|
||||
|
||||
const uint64_t timeout = getTimeUntilMonotonicDeadline(monotonic_blocking_deadline);
|
||||
{
|
||||
int read_mask = 0;
|
||||
const int select_res = driver_.select(write_mask, read_mask, timeout);
|
||||
const int select_res = driver_.select(write_mask, read_mask, blocking_deadline);
|
||||
if (select_res < 0)
|
||||
return select_res;
|
||||
}
|
||||
@@ -303,7 +293,7 @@ int CanIOManager::send(const CanFrame& frame, uint64_t monotonic_tx_deadline, ui
|
||||
}
|
||||
if (res <= 0)
|
||||
{
|
||||
res = sendToIface(i, frame, monotonic_tx_deadline);
|
||||
res = sendToIface(i, frame, tx_deadline);
|
||||
if (res > 0)
|
||||
iface_mask &= ~(1 << i); // Mark transmitted
|
||||
}
|
||||
@@ -318,9 +308,10 @@ int CanIOManager::send(const CanFrame& frame, uint64_t monotonic_tx_deadline, ui
|
||||
}
|
||||
|
||||
// Timeout. Enqueue the frame if wasn't transmitted and leave.
|
||||
if (write_mask == 0 || timeout == 0)
|
||||
const bool timed_out = sysclock_.getMonotonic() >= blocking_deadline;
|
||||
if (write_mask == 0 || timed_out)
|
||||
{
|
||||
if ((timeout > 0) && (sysclock_.getMonotonicMicroseconds() < monotonic_blocking_deadline))
|
||||
if (!timed_out)
|
||||
{
|
||||
UAVCAN_TRACE("CanIOManager", "Send: Premature timeout in select(), will try again");
|
||||
continue;
|
||||
@@ -328,7 +319,7 @@ int CanIOManager::send(const CanFrame& frame, uint64_t monotonic_tx_deadline, ui
|
||||
for (int i = 0; i < num_ifaces; i++)
|
||||
{
|
||||
if (iface_mask & (1 << i))
|
||||
tx_queues_[i].push(frame, monotonic_tx_deadline, qos);
|
||||
tx_queues_[i].push(frame, tx_deadline, qos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -336,7 +327,7 @@ int CanIOManager::send(const CanFrame& frame, uint64_t monotonic_tx_deadline, ui
|
||||
return retval;
|
||||
}
|
||||
|
||||
int CanIOManager::receive(CanRxFrame& frame, uint64_t monotonic_deadline)
|
||||
int CanIOManager::receive(CanRxFrame& frame, MonotonicTime blocking_deadline)
|
||||
{
|
||||
const int num_ifaces = getNumIfaces();
|
||||
|
||||
@@ -344,9 +335,8 @@ int CanIOManager::receive(CanRxFrame& frame, uint64_t monotonic_deadline)
|
||||
{
|
||||
int write_mask = makePendingTxMask();
|
||||
int read_mask = (1 << num_ifaces) - 1;
|
||||
const uint64_t timeout = getTimeUntilMonotonicDeadline(monotonic_deadline);
|
||||
{
|
||||
const int select_res = driver_.select(write_mask, read_mask, timeout);
|
||||
const int select_res = driver_.select(write_mask, read_mask, blocking_deadline);
|
||||
if (select_res < 0)
|
||||
return select_res;
|
||||
}
|
||||
@@ -369,7 +359,7 @@ int CanIOManager::receive(CanRxFrame& frame, uint64_t monotonic_deadline)
|
||||
assert(0); // Nonexistent interface
|
||||
continue;
|
||||
}
|
||||
const int res = iface->receive(frame, frame.ts_monotonic, frame.ts_utc);
|
||||
const int res = iface->receive(frame, frame.ts_mono, frame.ts_utc);
|
||||
if (res == 0)
|
||||
{
|
||||
assert(0); // select() reported that iface has pending RX frames, but receive() returned none
|
||||
@@ -380,7 +370,8 @@ int CanIOManager::receive(CanRxFrame& frame, uint64_t monotonic_deadline)
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout == 0) // Timeout checked in the last order - this way we can operate with expired deadline
|
||||
// Timeout checked in the last order - this way we can operate with expired deadline:
|
||||
if (sysclock_.getMonotonic() >= blocking_deadline)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -33,12 +33,12 @@ void Dispatcher::ListenerRegister::remove(TransferListenerBase* listener)
|
||||
list_.remove(listener);
|
||||
}
|
||||
|
||||
void Dispatcher::ListenerRegister::cleanup(uint64_t ts_monotonic)
|
||||
void Dispatcher::ListenerRegister::cleanup(MonotonicTime ts)
|
||||
{
|
||||
TransferListenerBase* p = list_.get();
|
||||
while (p)
|
||||
{
|
||||
p->cleanup(ts_monotonic);
|
||||
p->cleanup(ts);
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
}
|
||||
@@ -94,13 +94,13 @@ void Dispatcher::handleFrame(const CanRxFrame& can_frame)
|
||||
}
|
||||
}
|
||||
|
||||
int Dispatcher::spin(uint64_t monotonic_deadline)
|
||||
int Dispatcher::spin(MonotonicTime deadline)
|
||||
{
|
||||
int num_frames_processed = 0;
|
||||
do
|
||||
{
|
||||
CanRxFrame frame;
|
||||
const int res = canio_.receive(frame, monotonic_deadline);
|
||||
const int res = canio_.receive(frame, deadline);
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (res > 0)
|
||||
@@ -109,12 +109,12 @@ int Dispatcher::spin(uint64_t monotonic_deadline)
|
||||
handleFrame(frame);
|
||||
}
|
||||
}
|
||||
while (sysclock_.getMonotonicMicroseconds() < monotonic_deadline);
|
||||
while (sysclock_.getMonotonic() < deadline);
|
||||
|
||||
return num_frames_processed;
|
||||
}
|
||||
|
||||
int Dispatcher::send(const Frame& frame, uint64_t monotonic_tx_deadline, uint64_t monotonic_blocking_deadline,
|
||||
int Dispatcher::send(const Frame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline,
|
||||
CanTxQueue::Qos qos)
|
||||
{
|
||||
if (frame.getSrcNodeID() != getSelfNodeID())
|
||||
@@ -132,15 +132,15 @@ int Dispatcher::send(const Frame& frame, uint64_t monotonic_tx_deadline, uint64_
|
||||
}
|
||||
const int iface_mask = (1 << canio_.getNumIfaces()) - 1;
|
||||
|
||||
return canio_.send(can_frame, monotonic_tx_deadline, monotonic_blocking_deadline, iface_mask, qos);
|
||||
return canio_.send(can_frame, tx_deadline, blocking_deadline, iface_mask, qos);
|
||||
}
|
||||
|
||||
void Dispatcher::cleanup(uint64_t ts_monotonic)
|
||||
void Dispatcher::cleanup(MonotonicTime ts)
|
||||
{
|
||||
outgoing_transfer_reg_.cleanup(ts_monotonic);
|
||||
lmsg_.cleanup(ts_monotonic);
|
||||
lsrv_req_.cleanup(ts_monotonic);
|
||||
lsrv_resp_.cleanup(ts_monotonic);
|
||||
outgoing_transfer_reg_.cleanup(ts);
|
||||
lmsg_.cleanup(ts);
|
||||
lsrv_req_.cleanup(ts);
|
||||
lsrv_resp_.cleanup(ts);
|
||||
}
|
||||
|
||||
bool Dispatcher::registerMessageListener(TransferListenerBase* listener)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <uavcan/internal/transport/transfer.hpp>
|
||||
#include <uavcan/internal/transport/can_io.hpp>
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
@@ -225,10 +226,20 @@ std::string Frame::toString() const
|
||||
/**
|
||||
* RxFrame
|
||||
*/
|
||||
bool RxFrame::parse(const CanRxFrame& can_frame)
|
||||
{
|
||||
if (!Frame::parse(can_frame))
|
||||
return false;
|
||||
ts_mono_ = can_frame.ts_mono;
|
||||
ts_utc_ = can_frame.ts_utc;
|
||||
iface_index_ = can_frame.iface_index;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string RxFrame::toString() const
|
||||
{
|
||||
std::ostringstream os; // C++03 doesn't support long long, so we need ostream to print the timestamp
|
||||
os << Frame::toString() << " ts_m=" << ts_monotonic_ << " ts_utc=" << ts_utc_ << " iface=" << int(iface_index_);
|
||||
os << Frame::toString() << " ts_m=" << ts_mono_ << " ts_utc=" << ts_utc_ << " iface=" << int(iface_index_);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ int SingleFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsign
|
||||
/*
|
||||
* MultiFrameIncomingTransfer
|
||||
*/
|
||||
MultiFrameIncomingTransfer::MultiFrameIncomingTransfer(uint64_t ts_monotonic, uint64_t ts_utc,
|
||||
MultiFrameIncomingTransfer::MultiFrameIncomingTransfer(MonotonicTime ts_mono, UtcTime ts_utc,
|
||||
const RxFrame& last_frame, TransferBufferAccessor& tba)
|
||||
: IncomingTransfer(ts_monotonic, ts_utc, last_frame.getTransferType(), last_frame.getTransferID(),
|
||||
: IncomingTransfer(ts_mono, ts_utc, last_frame.getTransferType(), last_frame.getTransferID(),
|
||||
last_frame.getSrcNodeID())
|
||||
, buf_acc_(tba)
|
||||
{
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
const uint32_t TransferReceiver::DefaultTransferInterval;
|
||||
const uint32_t TransferReceiver::MinTransferInterval;
|
||||
const uint32_t TransferReceiver::MaxTransferInterval;
|
||||
const uint32_t TransferReceiver::DefaultTransferIntervalUSec;
|
||||
const uint32_t TransferReceiver::MinTransferIntervalUSec;
|
||||
const uint32_t TransferReceiver::MaxTransferIntervalUSec;
|
||||
|
||||
TransferReceiver::TidRelation TransferReceiver::getTidRelation(const RxFrame& frame) const
|
||||
{
|
||||
@@ -29,18 +29,17 @@ TransferReceiver::TidRelation TransferReceiver::getTidRelation(const RxFrame& fr
|
||||
|
||||
void TransferReceiver::updateTransferTimings()
|
||||
{
|
||||
assert(this_transfer_ts_monotonic_ > 0);
|
||||
assert(!this_transfer_ts_.isZero());
|
||||
|
||||
const uint64_t prev_prev_ts = prev_transfer_ts_monotonic_;
|
||||
prev_transfer_ts_monotonic_ = this_transfer_ts_monotonic_;
|
||||
const MonotonicTime prev_prev_ts = prev_transfer_ts_;
|
||||
prev_transfer_ts_ = this_transfer_ts_;
|
||||
|
||||
if ((prev_prev_ts != 0) &&
|
||||
(prev_transfer_ts_monotonic_ != 0) &&
|
||||
(prev_transfer_ts_monotonic_ >= prev_prev_ts))
|
||||
if ((!prev_prev_ts.isZero()) && (!prev_transfer_ts_.isZero()) && (prev_transfer_ts_ >= prev_prev_ts))
|
||||
{
|
||||
uint64_t interval = prev_transfer_ts_monotonic_ - prev_prev_ts;
|
||||
interval = std::max(std::min(interval, uint64_t(MaxTransferInterval)), uint64_t(MinTransferInterval));
|
||||
transfer_interval_ = static_cast<uint32_t>((uint64_t(transfer_interval_) * 7 + interval) / 8);
|
||||
uint64_t interval_usec = (prev_transfer_ts_ - prev_prev_ts).toUSec();
|
||||
interval_usec = std::min(interval_usec, uint64_t(MaxTransferIntervalUSec));
|
||||
interval_usec = std::max(interval_usec, uint64_t(MinTransferIntervalUSec));
|
||||
transfer_interval_usec_ = static_cast<uint32_t>((uint64_t(transfer_interval_usec_) * 7 + interval_usec) / 8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,8 +116,8 @@ TransferReceiver::ResultCode TransferReceiver::receive(const RxFrame& frame, Tra
|
||||
// Transfer timestamps are derived from the first frame
|
||||
if (frame.isFirst())
|
||||
{
|
||||
this_transfer_ts_monotonic_ = frame.getMonotonicTimestamp();
|
||||
first_frame_ts_utc_ = frame.getUtcTimestamp();
|
||||
this_transfer_ts_ = frame.getMonotonicTimestamp();
|
||||
first_frame_ts_ = frame.getUtcTimestamp();
|
||||
}
|
||||
|
||||
if (frame.isFirst() && frame.isLast())
|
||||
@@ -158,20 +157,19 @@ TransferReceiver::ResultCode TransferReceiver::receive(const RxFrame& frame, Tra
|
||||
return ResultNotComplete;
|
||||
}
|
||||
|
||||
bool TransferReceiver::isTimedOut(uint64_t ts_monotonic) const
|
||||
bool TransferReceiver::isTimedOut(MonotonicTime current_ts) const
|
||||
{
|
||||
static const uint64_t INTERVAL_MULT = (1 << TransferID::BitLen) / 2 + 1;
|
||||
const uint64_t ts = this_transfer_ts_monotonic_;
|
||||
if (ts_monotonic <= ts)
|
||||
if (current_ts <= this_transfer_ts_)
|
||||
return false;
|
||||
return (ts_monotonic - ts) > (uint64_t(transfer_interval_) * INTERVAL_MULT);
|
||||
return (current_ts - this_transfer_ts_).toUSec() > (uint64_t(transfer_interval_usec_) * INTERVAL_MULT);
|
||||
}
|
||||
|
||||
TransferReceiver::ResultCode TransferReceiver::addFrame(const RxFrame& frame, TransferBufferAccessor& tba)
|
||||
{
|
||||
if ((frame.getMonotonicTimestamp() == 0) ||
|
||||
(frame.getMonotonicTimestamp() < prev_transfer_ts_monotonic_) ||
|
||||
(frame.getMonotonicTimestamp() < this_transfer_ts_monotonic_))
|
||||
if ((frame.getMonotonicTimestamp().isZero()) ||
|
||||
(frame.getMonotonicTimestamp() < prev_transfer_ts_) ||
|
||||
(frame.getMonotonicTimestamp() < this_transfer_ts_))
|
||||
{
|
||||
return ResultNotComplete;
|
||||
}
|
||||
@@ -182,7 +180,7 @@ TransferReceiver::ResultCode TransferReceiver::addFrame(const RxFrame& frame, Tr
|
||||
const bool first_fame = frame.isFirst();
|
||||
const TidRelation tid_rel = getTidRelation(frame);
|
||||
const bool iface_timed_out =
|
||||
(frame.getMonotonicTimestamp() - this_transfer_ts_monotonic_) > (uint64_t(transfer_interval_) * 2);
|
||||
(frame.getMonotonicTimestamp() - this_transfer_ts_).toUSec() > (uint64_t(transfer_interval_usec_) * 2);
|
||||
|
||||
const bool need_restart = // FSM, the hard way
|
||||
(not_initialized) ||
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
int TransferSender::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 TransferSender::send(const uint8_t* payload, int payload_len, MonotonicTime tx_deadline,
|
||||
MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id,
|
||||
TransferID tid)
|
||||
{
|
||||
Frame frame(data_type_.getID(), transfer_type, dispatcher_.getSelfNodeID(), dst_node_id, 0, tid);
|
||||
@@ -27,7 +27,7 @@ int TransferSender::send(const uint8_t* payload, int payload_len, uint64_t monot
|
||||
}
|
||||
frame.makeLast();
|
||||
assert(frame.isLast() && frame.isFirst());
|
||||
return dispatcher_.send(frame, monotonic_tx_deadline, monotonic_blocking_deadline, qos_);
|
||||
return dispatcher_.send(frame, tx_deadline, blocking_deadline, qos_);
|
||||
}
|
||||
else // Multi Frame Transfer
|
||||
{
|
||||
@@ -57,7 +57,7 @@ int TransferSender::send(const uint8_t* payload, int payload_len, uint64_t monot
|
||||
|
||||
while (true)
|
||||
{
|
||||
const int send_res = dispatcher_.send(frame, monotonic_tx_deadline, monotonic_blocking_deadline, qos_);
|
||||
const int send_res = dispatcher_.send(frame, tx_deadline, blocking_deadline, qos_);
|
||||
if (send_res < 0)
|
||||
return send_res;
|
||||
|
||||
@@ -84,13 +84,13 @@ int TransferSender::send(const uint8_t* payload, int payload_len, uint64_t monot
|
||||
return -1; // Return path analysis is apparently broken. There should be no warning, this 'return' is unreachable.
|
||||
}
|
||||
|
||||
int TransferSender::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 TransferSender::send(const uint8_t* payload, int payload_len, MonotonicTime tx_deadline,
|
||||
MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id)
|
||||
{
|
||||
const OutgoingTransferRegistryKey otr_key(data_type_.getID(), transfer_type, dst_node_id);
|
||||
|
||||
assert(monotonic_tx_deadline > 0);
|
||||
const uint64_t otr_deadline = monotonic_tx_deadline + max_transfer_interval_;
|
||||
assert(!tx_deadline.isZero());
|
||||
const MonotonicTime otr_deadline = tx_deadline + max_transfer_interval_;
|
||||
|
||||
TransferID* const tid = dispatcher_.getOutgoingTransferRegistry().accessOrCreate(otr_key, otr_deadline);
|
||||
if (tid == NULL)
|
||||
@@ -103,7 +103,7 @@ int TransferSender::send(const uint8_t* payload, int payload_len, uint64_t monot
|
||||
const TransferID this_tid = tid->get();
|
||||
tid->increment();
|
||||
|
||||
return send(payload, payload_len, monotonic_tx_deadline, monotonic_blocking_deadline, transfer_type,
|
||||
return send(payload, payload_len, tx_deadline, blocking_deadline, transfer_type,
|
||||
dst_node_id, this_tid);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||
*/
|
||||
|
||||
#include <uavcan/time.hpp>
|
||||
#include <uavcan/Timestamp.hpp>
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
/*
|
||||
* UtcTime
|
||||
*/
|
||||
UtcTime::UtcTime(const Timestamp& ts) // Implicit
|
||||
{
|
||||
operator=(ts);
|
||||
}
|
||||
|
||||
UtcTime& UtcTime::operator=(const Timestamp& ts)
|
||||
{
|
||||
*this = fromUSec(ts.husec * Timestamp::USEC_PER_LSB);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UtcTime::operator Timestamp() const
|
||||
{
|
||||
Timestamp ts;
|
||||
ts.husec = toUSec() / Timestamp::USEC_PER_LSB;
|
||||
return ts;
|
||||
}
|
||||
|
||||
}
|
||||
+24
-22
@@ -8,37 +8,39 @@
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
const uint64_t Timer::InfinitePeriod;
|
||||
|
||||
void Timer::handleMonotonicDeadline(uint64_t monotonic_timestamp)
|
||||
void Timer::handleDeadline(MonotonicTime current_timestamp)
|
||||
{
|
||||
assert(!isRunning());
|
||||
|
||||
if (period_ != InfinitePeriod)
|
||||
startWithDeadline(getMonotonicDeadline() + period_);
|
||||
const MonotonicTime scheduled_deadline = getDeadline();
|
||||
|
||||
if (period_ < MonotonicDuration::getInfinite())
|
||||
startWithDeadline(scheduled_deadline + period_);
|
||||
|
||||
// Application can re-register the timer with different params, it's OK
|
||||
handleTimerEvent(TimerEvent(this, getMonotonicDeadline(), monotonic_timestamp));
|
||||
handleTimerEvent(TimerEvent(this, scheduled_deadline, current_timestamp));
|
||||
}
|
||||
|
||||
void Timer::startOneShotWithDeadline(uint64_t monotonic_deadline_usec)
|
||||
void Timer::startOneShotWithDeadline(MonotonicTime deadline)
|
||||
{
|
||||
period_ = InfinitePeriod;
|
||||
MonotonicDeadlineHandler::startWithDeadline(monotonic_deadline_usec);
|
||||
}
|
||||
|
||||
void Timer::startOneShotWithDelay(uint64_t delay_usec)
|
||||
{
|
||||
period_ = InfinitePeriod;
|
||||
MonotonicDeadlineHandler::startWithDelay(delay_usec);
|
||||
}
|
||||
|
||||
void Timer::startPeriodic(uint64_t period_usec)
|
||||
{
|
||||
assert(period_usec != InfinitePeriod);
|
||||
stop();
|
||||
period_ = period_usec;
|
||||
MonotonicDeadlineHandler::startWithDelay(period_usec);
|
||||
period_ = MonotonicDuration::getInfinite();
|
||||
MonotonicDeadlineHandler::startWithDeadline(deadline);
|
||||
}
|
||||
|
||||
void Timer::startOneShotWithDelay(MonotonicDuration delay)
|
||||
{
|
||||
stop();
|
||||
period_ = MonotonicDuration::getInfinite();
|
||||
MonotonicDeadlineHandler::startWithDelay(delay);
|
||||
}
|
||||
|
||||
void Timer::startPeriodic(MonotonicDuration period)
|
||||
{
|
||||
assert(period < MonotonicDuration::getInfinite());
|
||||
stop();
|
||||
period_ = period;
|
||||
MonotonicDeadlineHandler::startWithDelay(period);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user