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.hpp
00001 /* 00002 * CAN bus driver interface. 00003 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00004 */ 00005 00006 #ifndef UAVCAN_DRIVER_CAN_HPP_INCLUDED 00007 #define UAVCAN_DRIVER_CAN_HPP_INCLUDED 00008 00009 #include <cassert> 00010 #include <uavcan/std.hpp> 00011 #include <uavcan/build_config.hpp> 00012 #include <uavcan/driver/system_clock.hpp> 00013 00014 namespace uavcan 00015 { 00016 /** 00017 * This limit is defined by the specification. 00018 */ 00019 enum { MaxCanIfaces = 3 }; 00020 00021 /** 00022 * Raw CAN frame, as passed to/from the CAN driver. 00023 */ 00024 struct UAVCAN_EXPORT CanFrame 00025 { 00026 static const uint32_t MaskStdID = 0x000007FFU; 00027 static const uint32_t MaskExtID = 0x1FFFFFFFU; 00028 static const uint32_t FlagEFF = 1U << 31; ///< Extended frame format 00029 static const uint32_t FlagRTR = 1U << 30; ///< Remote transmission request 00030 static const uint32_t FlagERR = 1U << 29; ///< Error frame 00031 00032 static const uint8_t MaxDataLen = 8; 00033 00034 uint32_t id; ///< CAN ID with flags (above) 00035 uint8_t data[MaxDataLen]; 00036 uint8_t dlc; ///< Data Length Code 00037 00038 CanFrame() : 00039 id(0), 00040 dlc(0) 00041 { 00042 fill(data, data + MaxDataLen, uint8_t(0)); 00043 } 00044 00045 CanFrame(uint32_t can_id, const uint8_t* can_data, uint8_t data_len) : 00046 id(can_id), 00047 dlc((data_len > MaxDataLen) ? MaxDataLen : data_len) 00048 { 00049 UAVCAN_ASSERT(can_data != UAVCAN_NULLPTR); 00050 UAVCAN_ASSERT(data_len == dlc); 00051 (void)copy(can_data, can_data + dlc, this->data); 00052 } 00053 00054 bool operator!=(const CanFrame& rhs) const { return !operator==(rhs); } 00055 bool operator==(const CanFrame& rhs) const 00056 { 00057 return (id == rhs.id) && (dlc == rhs.dlc) && equal(data, data + dlc, rhs.data); 00058 } 00059 00060 bool isExtended() const { return id & FlagEFF; } 00061 bool isRemoteTransmissionRequest() const { return id & FlagRTR; } 00062 bool isErrorFrame() const { return id & FlagERR; } 00063 00064 #if UAVCAN_TOSTRING 00065 enum StringRepresentation 00066 { 00067 StrTight, ///< Minimum string length (default) 00068 StrAligned ///< Fixed formatting for any frame 00069 }; 00070 00071 std::string toString(StringRepresentation mode = StrTight) const; 00072 00073 #endif 00074 00075 /** 00076 * CAN frame arbitration rules, particularly STD vs EXT: 00077 * Marco Di Natale - "Understanding and using the Controller Area Network" 00078 * http://www6.in.tum.de/pub/Main/TeachingWs2013MSE/CANbus.pdf 00079 */ 00080 bool priorityHigherThan(const CanFrame& rhs) const; 00081 bool priorityLowerThan(const CanFrame& rhs) const { return rhs.priorityHigherThan(*this); } 00082 }; 00083 00084 /** 00085 * CAN hardware filter config struct. 00086 * Flags from @ref CanFrame can be applied to define frame type (EFF, EXT, etc.). 00087 * @ref ICanIface::configureFilters(). 00088 */ 00089 struct UAVCAN_EXPORT CanFilterConfig 00090 { 00091 uint32_t id; 00092 uint32_t mask; 00093 00094 bool operator==(const CanFilterConfig& rhs) const 00095 { 00096 return rhs.id == id && rhs.mask == mask; 00097 } 00098 00099 CanFilterConfig() : 00100 id(0), 00101 mask(0) 00102 { } 00103 }; 00104 00105 /** 00106 * Events to look for during @ref ICanDriver::select() call. 00107 * Bit position defines iface index, e.g. read = 1 << 2 to read from the third iface. 00108 */ 00109 struct UAVCAN_EXPORT CanSelectMasks 00110 { 00111 uint8_t read; 00112 uint8_t write; 00113 00114 CanSelectMasks() : 00115 read(0), 00116 write(0) 00117 { } 00118 }; 00119 00120 /** 00121 * Special IO flags. 00122 * 00123 * @ref CanIOFlagLoopback - Send the frame back to RX with true TX timestamps. 00124 * 00125 * @ref CanIOFlagAbortOnError - Abort transmission on first bus error instead of retransmitting. This does not 00126 * affect the case of arbitration loss, in which case the retransmission will work 00127 * as usual. This flag is used together with anonymous messages which allows to 00128 * implement CSMA bus access. Read the spec for details. 00129 */ 00130 typedef uint16_t CanIOFlags; 00131 static const CanIOFlags CanIOFlagLoopback = 1; 00132 static const CanIOFlags CanIOFlagAbortOnError = 2; 00133 00134 /** 00135 * Single non-blocking CAN interface. 00136 */ 00137 class UAVCAN_EXPORT ICanIface 00138 { 00139 public: 00140 virtual ~ICanIface() { } 00141 00142 /** 00143 * Non-blocking transmission. 00144 * 00145 * If the frame wasn't transmitted upon TX deadline, the driver should discard it. 00146 * 00147 * Note that it is LIKELY that the library will want to send the frames that were passed into the select() 00148 * method as the next ones to transmit, but it is NOT guaranteed. The library can replace those with new 00149 * frames between the calls. 00150 * 00151 * @return 1 = one frame transmitted, 0 = TX buffer full, negative for error. 00152 */ 00153 virtual int16_t send(const CanFrame& frame, MonotonicTime tx_deadline, CanIOFlags flags) = 0; 00154 00155 /** 00156 * Non-blocking reception. 00157 * 00158 * Timestamps should be provided by the CAN driver, ideally by the hardware CAN controller. 00159 * 00160 * Monotonic timestamp is required and can be not precise since it is needed only for 00161 * protocol timing validation (transfer timeouts and inter-transfer intervals). 00162 * 00163 * UTC timestamp is optional, if available it will be used for precise time synchronization; 00164 * must be set to zero if not available. 00165 * 00166 * Refer to @ref ISystemClock to learn more about timestamps. 00167 * 00168 * @param [out] out_ts_monotonic Monotonic timestamp, mandatory. 00169 * @param [out] out_ts_utc UTC timestamp, optional, zero if unknown. 00170 * @return 1 = one frame received, 0 = RX buffer empty, negative for error. 00171 */ 00172 virtual int16_t receive(CanFrame& out_frame, MonotonicTime& out_ts_monotonic, UtcTime& out_ts_utc, 00173 CanIOFlags& out_flags) = 0; 00174 00175 /** 00176 * Configure the hardware CAN filters. @ref CanFilterConfig. 00177 * 00178 * @return 0 = success, negative for error. 00179 */ 00180 virtual int16_t configureFilters(const CanFilterConfig* filter_configs, uint16_t num_configs) = 0; 00181 00182 /** 00183 * Number of available hardware filters. 00184 */ 00185 virtual uint16_t getNumFilters() const = 0; 00186 00187 /** 00188 * Continuously incrementing counter of hardware errors. 00189 * Arbitration lost should not be treated as a hardware error. 00190 */ 00191 virtual uint64_t getErrorCount() const = 0; 00192 }; 00193 00194 /** 00195 * Generic CAN driver. 00196 */ 00197 class UAVCAN_EXPORT ICanDriver 00198 { 00199 public: 00200 virtual ~ICanDriver() { } 00201 00202 /** 00203 * Returns an interface by index, or null pointer if the index is out of range. 00204 */ 00205 virtual ICanIface* getIface(uint8_t iface_index) = 0; 00206 00207 /** 00208 * Default implementation of this method calls the non-const overload of getIface(). 00209 * Can be overriden by the application if necessary. 00210 */ 00211 virtual const ICanIface* getIface(uint8_t iface_index) const 00212 { 00213 return const_cast<ICanDriver*>(this)->getIface(iface_index); 00214 } 00215 00216 /** 00217 * Total number of available CAN interfaces. 00218 * This value shall not change after initialization. 00219 */ 00220 virtual uint8_t getNumIfaces() const = 0; 00221 00222 /** 00223 * Block until the deadline, or one of the specified interfaces becomes available for read or write. 00224 * 00225 * Iface masks will be modified by the driver to indicate which exactly interfaces are available for IO. 00226 * 00227 * Bit position in the masks defines interface index. 00228 * 00229 * Note that it is allowed to return from this method even if no requested events actually happened, or if 00230 * there are events that were not requested by the library. 00231 * 00232 * The pending TX argument contains an array of pointers to CAN frames that the library wants to transmit 00233 * next, per interface. This is intended to allow the driver to properly prioritize transmissions; many 00234 * drivers will not need to use it. If a write flag for the given interface is set to one in the select mask 00235 * structure, then the corresponding pointer is guaranteed to be valid (not UAVCAN_NULLPTR). 00236 * 00237 * @param [in,out] inout_masks Masks indicating which interfaces are needed/available for IO. 00238 * @param [in] pending_tx Array of frames, per interface, that are likely to be transmitted next. 00239 * @param [in] blocking_deadline Zero means non-blocking operation. 00240 * @return Positive number of ready interfaces or negative error code. 00241 */ 00242 virtual int16_t select(CanSelectMasks& inout_masks, 00243 const CanFrame* (& pending_tx)[MaxCanIfaces], 00244 MonotonicTime blocking_deadline) = 0; 00245 }; 00246 00247 } 00248 00249 #endif // UAVCAN_DRIVER_CAN_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:30 by
