LCOV - code coverage report
Current view: top level - AP_HAL - CANIface.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 8 38 21.1 %
Date: 2026-09-09 11:02:08 Functions: 2 17 11.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2020 Siddharth B Purohit
       3             :  *
       4             :  * This file is free software: you can redistribute it and/or modify it
       5             :  * under the terms of the GNU General Public License as published by the
       6             :  * Free Software Foundation, either version 3 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * This file is distributed in the hope that it will be useful, but
      10             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      12             :  * See the GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License along
      15             :  * with this program.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #pragma once
      19             : 
      20             : #include <stdint.h>
      21             : #include "AP_HAL_Namespace.h"
      22             : #include "AP_HAL_Boards.h"
      23             : 
      24             : class ExpandingString;
      25             : 
      26             : /**
      27             :  * Raw CAN frame, as passed to/from the CAN driver.
      28             :  */
      29             : struct AP_HAL::CANFrame {
      30             :     static const uint32_t MaskStdID = 0x000007FFU;
      31             :     static const uint32_t MaskExtID = 0x1FFFFFFFU;
      32             :     static const uint32_t FlagEFF = 1U << 31;                  ///< Extended frame format
      33             :     static const uint32_t FlagRTR = 1U << 30;                  ///< Remote transmission request
      34             :     static const uint32_t FlagERR = 1U << 29;                  ///< Error frame
      35             : 
      36             : #if HAL_CANFD_SUPPORTED
      37             :     static const uint8_t NonFDCANMaxDataLen = 8;
      38             :     static const uint8_t MaxDataLen = 64;
      39             : #else
      40             :     static const uint8_t NonFDCANMaxDataLen = 8;
      41             :     static const uint8_t MaxDataLen = 8;
      42             : #endif
      43             :     uint32_t id;                ///< CAN ID with flags (above)
      44             :     union {
      45             :         uint8_t data[MaxDataLen];
      46             :         uint32_t data_32[MaxDataLen/4];
      47             :     };
      48             :     uint8_t dlc;                ///< Data Length Code
      49             :     bool canfd;
      50             : 
      51      162534 :     CANFrame() :
      52      162534 :         id(0),
      53      162534 :         dlc(0),
      54      162534 :         canfd(false)
      55             :     {
      56      162534 :         memset(data,0, MaxDataLen);
      57      162534 :     }
      58             : 
      59             :     CANFrame(uint32_t can_id, const uint8_t* can_data, uint8_t data_len, bool canfd_frame = false);
      60             : 
      61             :     bool operator!=(const CANFrame& rhs) const
      62             :     {
      63             :         return !operator==(rhs);
      64             :     }
      65             :     bool operator==(const CANFrame& rhs) const
      66             :     {
      67             :         return (id == rhs.id) && (dlc == rhs.dlc) && (memcmp(data, rhs.data, dlc) == 0);
      68             :     }
      69             : 
      70             :     // signed version of id, for use by scriping where uint32_t is expensive
      71           0 :     int32_t id_signed(void) const {
      72           0 :         return isExtended()? int32_t(id & MaskExtID) : int32_t(id & MaskStdID);
      73             :     }
      74             : 
      75         152 :     bool isExtended()                  const
      76             :     {
      77         152 :         return id & FlagEFF;
      78             :     }
      79           0 :     bool isRemoteTransmissionRequest() const
      80             :     {
      81           0 :         return id & FlagRTR;
      82             :     }
      83           0 :     bool isErrorFrame()                const
      84             :     {
      85           0 :         return id & FlagERR;
      86             :     }
      87             :     void setCanFD(bool canfd_frame)
      88             :     {
      89             :         canfd = canfd_frame;
      90             :     }
      91             : 
      92           0 :     bool isCanFDFrame() const
      93             :     {
      94           0 :         return canfd;
      95             :     }
      96             : 
      97             :     static uint8_t dlcToDataLength(uint8_t dlc);
      98             : 
      99             :     static uint8_t dataLengthToDlc(uint8_t data_length);
     100             :     /**
     101             :      * CAN frame arbitration rules, particularly STD vs EXT:
     102             :      *     Marco Di Natale - "Understanding and using the Controller Area Network"
     103             :      *     http://www6.in.tum.de/pub/Main/TeachingWs2013MSE/CANbus.pdf
     104             :      */
     105             :     bool priorityHigherThan(const CANFrame& rhs) const;
     106           0 :     bool priorityLowerThan(const CANFrame& rhs) const
     107             :     {
     108           0 :         return rhs.priorityHigherThan(*this);
     109             :     }
     110             : };
     111             : 
     112             : class AP_HAL::CANIface
     113             : {
     114             : public:
     115             : 
     116             :     typedef uint16_t CanIOFlags;
     117             :     static const CanIOFlags Loopback = 1;
     118             :     static const CanIOFlags AbortOnError = 2;
     119             :     static const CanIOFlags IsForwardedFrame = 4;
     120             : 
     121             :     // Single Rx Frame with related info
     122             :     struct CanRxItem {
     123             :         uint64_t timestamp_us = 0;
     124             :         CanIOFlags flags = 0;
     125             :         CANFrame frame;
     126             :     };
     127             : 
     128             :     // Single Tx Frame with related info
     129             :     struct CanTxItem {
     130             :         uint64_t deadline = 0;
     131             :         CANFrame frame;
     132             :         uint32_t index = 0;
     133             :         bool loopback:1;
     134             :         bool abort_on_error:1;
     135             :         bool aborted:1;
     136             :         bool pushed:1;
     137             :         bool setup:1;
     138             :         bool canfd_frame:1;
     139             : 
     140           0 :         bool operator<(const CanTxItem& rhs) const
     141             :         {
     142           0 :             if (frame.priorityLowerThan(rhs.frame)) {
     143           0 :                 return true;
     144             :             }
     145           0 :             if (frame.priorityHigherThan(rhs.frame)) {
     146           0 :                 return false;
     147             :             }
     148           0 :             return index > rhs.index;
     149             :         }
     150             :     };
     151             : 
     152           0 :     virtual bool init(const uint32_t bitrate, const uint32_t fdbitrate) {
     153           0 :         return init(bitrate);
     154             :     }
     155             : 
     156             :     // Initialise the interface with hardware configuration required to start comms.
     157             :     virtual bool init(const uint32_t bitrate) = 0;
     158             : 
     159             :     // Select method to notify user of Rx and Tx buffer state.
     160             :     // fill read select with true if a frame is available in Rx buffer
     161             :     // fill write select with true if space is available in Tx buffer
     162             :     // Also waits for Rx or Tx event depending on read_select and write_select values
     163             :     // passed to the method until timeout. Returns true if the Rx/Tx even occurred
     164             :     // while waiting, false if timedout
     165           0 :     virtual bool select(bool &read_select, bool &write_select,
     166             :                         const CANFrame* const pending_tx, uint64_t timeout)
     167             :     {
     168           0 :         return false;
     169             :     }
     170             : 
     171           0 :     virtual bool set_event_handle(AP_HAL::BinarySemaphore *sem_handle)
     172             :     {
     173           0 :         return true;
     174             :     }
     175             : 
     176             :     // Put frame in queue to be sent, return negative if error occurred, 0 if no space, and 1 if successful
     177             :     // must be called on child class
     178             :     virtual int16_t send(const CANFrame& frame, uint64_t tx_deadline, CanIOFlags flags);
     179             : 
     180             :     // Non blocking receive frame that pops the frames received inside the buffer, return negative if error occurred, 
     181             :     // 0 if no frame available, 1 if successful
     182             :     // must be called on child class
     183             :     virtual int16_t receive(CANFrame& out_frame, uint64_t& out_ts_monotonic, CanIOFlags& out_flags);
     184             : 
     185             :     //Return Total Error Count generated so far
     186           0 :     virtual uint32_t getErrorCount() const
     187             :     {
     188           0 :         return 0;
     189             :     }
     190             : 
     191             :     typedef struct {
     192             :         uint32_t tx_requests;
     193             :         uint32_t tx_rejected;
     194             :         uint32_t tx_overflow;
     195             :         uint32_t tx_success;
     196             :         uint32_t tx_timedout;
     197             :         uint32_t tx_abort;
     198             :         uint32_t rx_received;
     199             :         uint32_t rx_overflow;
     200             :         uint32_t rx_errors;
     201             :         uint32_t num_busoff_err;
     202             :         uint64_t last_transmit_us;
     203             :     } bus_stats_t;
     204             : 
     205             : #if !defined(HAL_BOOTLOADER_BUILD)
     206             :     //Get status info of the interface
     207           0 :     virtual void get_stats(ExpandingString &str) {}
     208             : 
     209             :     /*
     210             :       return bus statistics for logging
     211             :       return nullptr if no statistics available
     212             :      */
     213           0 :     virtual const bus_stats_t *get_statistics(void) const { return nullptr; };
     214             : #endif
     215             : 
     216             :     // return true if busoff was detected and not cleared
     217           0 :     virtual bool is_busoff() const
     218             :     {
     219           0 :         return false;
     220             :     }
     221             : 
     222             :     // Methods to be used only while testing CANBus
     223             :     // Not for normal operation or use case
     224           0 :     virtual void flush_tx() {}
     225           0 :     virtual void clear_rx() {}
     226             : 
     227             :     // return true if init was called and successful
     228             :     virtual bool is_initialized() const = 0;
     229             : 
     230             :     FUNCTOR_TYPEDEF(FrameCb, void, uint8_t, const AP_HAL::CANFrame &, CanIOFlags);
     231             : 
     232             :     // register a frame callback function
     233             :     virtual bool register_frame_callback(FrameCb cb, uint8_t &cb_id);
     234             :     virtual void unregister_frame_callback(uint8_t cb_id);
     235             : 
     236             : protected:
     237             :     virtual int8_t get_iface_num() const = 0;
     238             :     virtual bool add_to_rx_queue(const CanRxItem &rx_item) = 0;
     239             : 
     240             :     struct {
     241             : #ifndef HAL_BOOTLOADER_BUILD
     242             :         HAL_Semaphore sem;
     243             : #endif
     244             :         // allow up to 3 callbacks per interface
     245             :         FrameCb cb[3];
     246             :     } callbacks;
     247             : 
     248             :     uint32_t bitrate_;
     249             : };

Generated by: LCOV version 1.14