Руслан Урядинский / libuavcan

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers can.hpp Source File

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