-
Notifications
You must be signed in to change notification settings - Fork 502
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #198 from Zarkopafilis/txq
- Loading branch information
Showing
17 changed files
with
1,449 additions
and
499 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
/* | ||
* CAN bus IO logic. | ||
* Copyright (C) 2014 Pavel Kirienko <[email protected]> | ||
* Copyright (C) 2019 Theodoros Ntakouris <[email protected]> | ||
*/ | ||
|
||
#ifndef UAVCAN_TRANSPORT_CAN_IO_HPP_INCLUDED | ||
|
@@ -10,6 +11,7 @@ | |
#include <uavcan/error.hpp> | ||
#include <uavcan/std.hpp> | ||
#include <uavcan/util/linked_list.hpp> | ||
#include <uavcan/util/avl_tree.hpp> | ||
#include <uavcan/dynamic_memory.hpp> | ||
#include <uavcan/build_config.hpp> | ||
#include <uavcan/util/templates.hpp> | ||
|
@@ -20,7 +22,6 @@ | |
|
||
namespace uavcan | ||
{ | ||
|
||
struct UAVCAN_EXPORT CanRxFrame : public CanFrame | ||
{ | ||
MonotonicTime ts_mono; | ||
|
@@ -36,87 +37,81 @@ struct UAVCAN_EXPORT CanRxFrame : public CanFrame | |
#endif | ||
}; | ||
|
||
|
||
class UAVCAN_EXPORT CanTxQueue : Noncopyable | ||
struct UAVCAN_EXPORT CanTxQueueEntry // Not required to be packed - fits the block in any case | ||
{ | ||
public: | ||
enum Qos { Volatile, Persistent }; | ||
MonotonicTime deadline; | ||
const CanFrame frame; | ||
CanIOFlags flags; | ||
|
||
CanTxQueueEntry(const CanFrame& arg_frame, const MonotonicTime arg_deadline, CanIOFlags arg_flags) | ||
: deadline(arg_deadline) | ||
, frame(arg_frame) | ||
, flags(arg_flags) | ||
{ | ||
IsDynamicallyAllocatable<CanTxQueueEntry>::check(); | ||
} | ||
|
||
static void destroy(CanTxQueueEntry*& obj, IPoolAllocator& allocator); | ||
|
||
bool isExpired(const MonotonicTime timestamp) const { return timestamp > deadline; } | ||
|
||
bool operator<(const CanTxQueueEntry& other) const | ||
{ | ||
return this->frame.priorityLowerThan(other.frame); | ||
} | ||
|
||
bool operator>(const CanTxQueueEntry& other) const | ||
{ | ||
return this->frame.priorityHigherThan(other.frame); | ||
} | ||
|
||
struct Entry : public LinkedListNode<Entry> // Not required to be packed - fits the block in any case | ||
bool operator==(const CanTxQueueEntry& other) const | ||
{ | ||
MonotonicTime deadline; | ||
CanFrame frame; | ||
uint8_t qos; | ||
CanIOFlags flags; | ||
|
||
Entry(const CanFrame& arg_frame, MonotonicTime arg_deadline, Qos arg_qos, CanIOFlags arg_flags) | ||
: deadline(arg_deadline) | ||
, frame(arg_frame) | ||
, qos(uint8_t(arg_qos)) | ||
, flags(arg_flags) | ||
{ | ||
UAVCAN_ASSERT((qos == Volatile) || (qos == Persistent)); | ||
IsDynamicallyAllocatable<Entry>::check(); | ||
} | ||
|
||
static void destroy(Entry*& obj, IPoolAllocator& allocator); | ||
|
||
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; | ||
bool qosHigherThan(const Entry& rhs) const { return qosHigherThan(rhs.frame, Qos(rhs.qos)); } | ||
bool qosLowerThan(const Entry& rhs) const { return qosLowerThan(rhs.frame, Qos(rhs.qos)); } | ||
return this->frame == other.frame; | ||
} | ||
|
||
#if UAVCAN_TOSTRING | ||
std::string toString() const; | ||
#endif | ||
}; | ||
}; | ||
|
||
class UAVCAN_EXPORT CanTxQueue : public AvlTree<CanTxQueueEntry> | ||
{ | ||
private: | ||
class PriorityInsertionComparator | ||
{ | ||
const CanFrame& frm_; | ||
public: | ||
explicit PriorityInsertionComparator(const CanFrame& frm) : frm_(frm) { } | ||
bool operator()(const Entry* entry) | ||
{ | ||
UAVCAN_ASSERT(entry); | ||
return frm_.priorityHigherThan(entry->frame); | ||
} | ||
}; | ||
void postOrderTraverseEntryCleanup(Node* n); | ||
|
||
LinkedListRoot<Entry> queue_; | ||
LimitedPoolAllocator allocator_; | ||
protected: | ||
ISystemClock& sysclock_; | ||
uint32_t rejected_frames_cnt_; | ||
|
||
void registerRejectedFrame(); | ||
bool linkedListContains(Node* head, const CanFrame& frame) const; | ||
void safeIncrementRejectedFrames(); | ||
AvlTree::Node* searchForNonExpiredMax(Node* n); | ||
|
||
public: | ||
CanTxQueue(IPoolAllocator& allocator, ISystemClock& sysclock, std::size_t allocator_quota) | ||
: allocator_(allocator, allocator_quota) | ||
, sysclock_(sysclock) | ||
, rejected_frames_cnt_(0) | ||
{ } | ||
CanTxQueue(IPoolAllocator& allocator, ISystemClock& sysclock, std::size_t allocator_quota) : | ||
AvlTree(allocator, allocator_quota), | ||
sysclock_(sysclock), | ||
rejected_frames_cnt_(0) | ||
{} | ||
|
||
~CanTxQueue(); | ||
~CanTxQueue() override; | ||
|
||
void push(const CanFrame& frame, MonotonicTime tx_deadline, Qos qos, CanIOFlags flags); | ||
/* Avl Tree allocates the AvlTree::Node, while this(CanTxQueue) allocates the CanTxQueueEntry | ||
* Same logic for removal. */ | ||
void push(const CanFrame& frame, MonotonicTime tx_deadline, CanIOFlags flags); | ||
void remove(CanTxQueueEntry* entry); | ||
|
||
Entry* peek(); // Modifier | ||
void remove(Entry*& entry); | ||
const CanFrame* getTopPriorityPendingFrame() const; | ||
uint32_t getRejectedFrameCount() const { return rejected_frames_cnt_; } | ||
|
||
/// The 'or equal' condition is necessary to avoid frame reordering. | ||
bool topPriorityHigherOrEqual(const CanFrame& rhs_frame) const; | ||
bool contains(const CanFrame& frame) const; | ||
|
||
uint32_t getRejectedFrameCount() const { return rejected_frames_cnt_; } | ||
/* Tries to look up rightmost Node. If the frame is expired, removes it and continues traversing */ | ||
CanTxQueueEntry* peek(); | ||
|
||
bool isEmpty() const { return queue_.isEmpty(); } | ||
bool topPriorityHigherOrEqual(const CanFrame& rhs_frame); | ||
}; | ||
|
||
|
||
struct UAVCAN_EXPORT CanIfacePerfCounters | ||
{ | ||
uint64_t frames_tx; | ||
|
@@ -130,7 +125,6 @@ struct UAVCAN_EXPORT CanIfacePerfCounters | |
{ } | ||
}; | ||
|
||
|
||
class UAVCAN_EXPORT CanIOManager : Noncopyable | ||
{ | ||
struct IfaceFrameCounters | ||
|
@@ -177,7 +171,7 @@ class UAVCAN_EXPORT CanIOManager : Noncopyable | |
* negative - failure | ||
*/ | ||
int send(const CanFrame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, | ||
uint8_t iface_mask, CanTxQueue::Qos qos, CanIOFlags flags); | ||
uint8_t iface_mask, CanIOFlags flags); | ||
int receive(CanRxFrame& out_frame, MonotonicTime blocking_deadline, CanIOFlags& out_flags); | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.