Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
can_io.hpp
00001 /* 00002 * CAN bus IO logic. 00003 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00004 */ 00005 00006 #ifndef UAVCAN_TRANSPORT_CAN_IO_HPP_INCLUDED 00007 #define UAVCAN_TRANSPORT_CAN_IO_HPP_INCLUDED 00008 00009 #include <cassert> 00010 #include <uavcan/error.hpp> 00011 #include <uavcan/std.hpp> 00012 #include <uavcan/util/linked_list.hpp> 00013 #include <uavcan/dynamic_memory.hpp> 00014 #include <uavcan/build_config.hpp> 00015 #include <uavcan/util/templates.hpp> 00016 #include <uavcan/util/lazy_constructor.hpp> 00017 #include <uavcan/driver/can.hpp> 00018 #include <uavcan/driver/system_clock.hpp> 00019 #include <uavcan/time.hpp> 00020 00021 namespace uavcan 00022 { 00023 00024 struct UAVCAN_EXPORT CanRxFrame : public CanFrame 00025 { 00026 MonotonicTime ts_mono; 00027 UtcTime ts_utc; 00028 uint8_t iface_index; 00029 00030 CanRxFrame() 00031 : iface_index(0) 00032 { } 00033 00034 #if UAVCAN_TOSTRING 00035 std::string toString(StringRepresentation mode = StrTight) const; 00036 #endif 00037 }; 00038 00039 00040 class UAVCAN_EXPORT CanTxQueue : Noncopyable 00041 { 00042 public: 00043 enum Qos { Volatile, Persistent }; 00044 00045 struct Entry : public LinkedListNode<Entry> // Not required to be packed - fits the block in any case 00046 { 00047 MonotonicTime deadline; 00048 CanFrame frame; 00049 uint8_t qos; 00050 CanIOFlags flags; 00051 00052 Entry(const CanFrame& arg_frame, MonotonicTime arg_deadline, Qos arg_qos, CanIOFlags arg_flags) 00053 : deadline(arg_deadline) 00054 , frame(arg_frame) 00055 , qos(uint8_t(arg_qos)) 00056 , flags(arg_flags) 00057 { 00058 UAVCAN_ASSERT((qos == Volatile) || (qos == Persistent)); 00059 IsDynamicallyAllocatable<Entry>::check(); 00060 } 00061 00062 static void destroy(Entry*& obj, IPoolAllocator& allocator); 00063 00064 bool isExpired(MonotonicTime timestamp) const { return timestamp > deadline; } 00065 00066 bool qosHigherThan(const CanFrame& rhs_frame, Qos rhs_qos) const; 00067 bool qosLowerThan(const CanFrame& rhs_frame, Qos rhs_qos) const; 00068 bool qosHigherThan(const Entry& rhs) const { return qosHigherThan(rhs.frame, Qos(rhs.qos)); } 00069 bool qosLowerThan(const Entry& rhs) const { return qosLowerThan(rhs.frame, Qos(rhs.qos)); } 00070 00071 #if UAVCAN_TOSTRING 00072 std::string toString() const; 00073 #endif 00074 }; 00075 00076 private: 00077 class PriorityInsertionComparator 00078 { 00079 const CanFrame& frm_; 00080 public: 00081 explicit PriorityInsertionComparator(const CanFrame& frm) : frm_(frm) { } 00082 bool operator()(const Entry* entry) 00083 { 00084 UAVCAN_ASSERT(entry); 00085 return frm_.priorityHigherThan(entry->frame); 00086 } 00087 }; 00088 00089 LinkedListRoot<Entry> queue_; 00090 LimitedPoolAllocator allocator_; 00091 ISystemClock& sysclock_; 00092 uint32_t rejected_frames_cnt_; 00093 00094 void registerRejectedFrame(); 00095 00096 public: 00097 CanTxQueue(IPoolAllocator& allocator, ISystemClock& sysclock, std::size_t allocator_quota) 00098 : allocator_(allocator, allocator_quota) 00099 , sysclock_(sysclock) 00100 , rejected_frames_cnt_(0) 00101 { } 00102 00103 ~CanTxQueue(); 00104 00105 void push(const CanFrame& frame, MonotonicTime tx_deadline, Qos qos, CanIOFlags flags); 00106 00107 Entry* peek(); // Modifier 00108 void remove(Entry*& entry); 00109 const CanFrame* getTopPriorityPendingFrame() const; 00110 00111 /// The 'or equal' condition is necessary to avoid frame reordering. 00112 bool topPriorityHigherOrEqual(const CanFrame& rhs_frame) const; 00113 00114 uint32_t getRejectedFrameCount() const { return rejected_frames_cnt_; } 00115 00116 bool isEmpty() const { return queue_.isEmpty(); } 00117 }; 00118 00119 00120 struct UAVCAN_EXPORT CanIfacePerfCounters 00121 { 00122 uint64_t frames_tx; 00123 uint64_t frames_rx; 00124 uint64_t errors; 00125 00126 CanIfacePerfCounters() 00127 : frames_tx(0) 00128 , frames_rx(0) 00129 , errors(0) 00130 { } 00131 }; 00132 00133 00134 class UAVCAN_EXPORT CanIOManager : Noncopyable 00135 { 00136 struct IfaceFrameCounters 00137 { 00138 uint64_t frames_tx; 00139 uint64_t frames_rx; 00140 00141 IfaceFrameCounters() 00142 : frames_tx(0) 00143 , frames_rx(0) 00144 { } 00145 }; 00146 00147 ICanDriver& driver_; 00148 ISystemClock& sysclock_; 00149 00150 LazyConstructor<CanTxQueue> tx_queues_[MaxCanIfaces]; 00151 IfaceFrameCounters counters_[MaxCanIfaces]; 00152 00153 const uint8_t num_ifaces_; 00154 00155 int sendToIface(uint8_t iface_index, const CanFrame& frame, MonotonicTime tx_deadline, CanIOFlags flags); 00156 int sendFromTxQueue(uint8_t iface_index); 00157 int callSelect(CanSelectMasks& inout_masks, const CanFrame* (& pending_tx)[MaxCanIfaces], 00158 MonotonicTime blocking_deadline); 00159 00160 public: 00161 CanIOManager(ICanDriver& driver, IPoolAllocator& allocator, ISystemClock& sysclock, 00162 std::size_t mem_blocks_per_iface = 0); 00163 00164 uint8_t getNumIfaces() const { return num_ifaces_; } 00165 00166 CanIfacePerfCounters getIfacePerfCounters(uint8_t iface_index) const; 00167 00168 const ICanDriver& getCanDriver() const { return driver_; } 00169 ICanDriver& getCanDriver() { return driver_; } 00170 00171 uint8_t makePendingTxMask() const; 00172 00173 /** 00174 * Returns: 00175 * 0 - rejected/timedout/enqueued 00176 * 1+ - sent/received 00177 * negative - failure 00178 */ 00179 int send(const CanFrame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, 00180 uint8_t iface_mask, CanTxQueue::Qos qos, CanIOFlags flags); 00181 int receive(CanRxFrame& out_frame, MonotonicTime blocking_deadline, CanIOFlags& out_flags); 00182 }; 00183 00184 } 00185 00186 #endif // UAVCAN_TRANSPORT_CAN_IO_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:30 by
