LCOV - code coverage report
Current view: top level - AP_HAL - CANIface.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 30 115 26.1 %
Date: 2026-09-09 11:02:08 Functions: 5 8 62.5 %

          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             : #include "CANIface.h"
      19             : #include "system.h"
      20             : 
      21           0 : bool AP_HAL::CANFrame::priorityHigherThan(const CANFrame& rhs) const
      22             : {
      23           0 :     const uint32_t clean_id     = id     & MaskExtID;
      24           0 :     const uint32_t rhs_clean_id = rhs.id & MaskExtID;
      25             : 
      26             :     /*
      27             :      * STD vs EXT - if 11 most significant bits are the same, EXT loses.
      28             :      */
      29           0 :     const bool ext     = id     & FlagEFF;
      30           0 :     const bool rhs_ext = rhs.id & FlagEFF;
      31           0 :     if (ext != rhs_ext) {
      32           0 :         const uint32_t arb11     = ext     ? (clean_id >> 18)     : clean_id;
      33           0 :         const uint32_t rhs_arb11 = rhs_ext ? (rhs_clean_id >> 18) : rhs_clean_id;
      34           0 :         if (arb11 != rhs_arb11) {
      35           0 :             return arb11 < rhs_arb11;
      36             :         } else {
      37           0 :             return rhs_ext;
      38             :         }
      39             :     }
      40             : 
      41             :     /*
      42             :      * RTR vs Data frame - if frame identifiers and frame types are the same, RTR loses.
      43             :      */
      44           0 :     const bool rtr     = id     & FlagRTR;
      45           0 :     const bool rhs_rtr = rhs.id & FlagRTR;
      46           0 :     if (clean_id == rhs_clean_id && rtr != rhs_rtr) {
      47           0 :         return rhs_rtr;
      48             :     }
      49             : 
      50             :     /*
      51             :      * Plain ID arbitration - greater value loses.
      52             :      */
      53           0 :     return clean_id < rhs_clean_id;
      54             : }
      55             : 
      56             : /*
      57             :   parent class receive handling for forwarding received frames to registered callbacks
      58             :  */
      59         152 : int16_t AP_HAL::CANIface::receive(CANFrame& out_frame, uint64_t& out_ts_monotonic, CanIOFlags& out_flags)
      60             : {
      61         152 :     if ((out_flags & IsForwardedFrame) != 0) {
      62             :         // this frame was forwarded from another interface to this one, so we should not forward it back
      63           0 :         return 1;
      64             :     }
      65             : #ifndef HAL_BOOTLOADER_BUILD
      66         152 :     WITH_SEMAPHORE(callbacks.sem);
      67             : #endif
      68         608 :     for (auto &cb : callbacks.cb) {
      69         456 :         if (cb != nullptr) {
      70             :             // forward the frame to the registered callbacks and mark it as forwarded
      71           0 :             cb(get_iface_num(), out_frame, out_flags | IsForwardedFrame);
      72             :         }
      73             :     }
      74         152 :     return 1;
      75         152 : }
      76             : 
      77             : /*
      78             :   parent class send handling for Forwarded frames
      79             :  */
      80       18063 : int16_t AP_HAL::CANIface::send(const CANFrame& frame, uint64_t tx_deadline, CanIOFlags flags)
      81             : {
      82             : #ifndef HAL_BOOTLOADER_BUILD
      83       18063 :     WITH_SEMAPHORE(callbacks.sem);
      84             : #endif
      85       18063 :     bool added_to_rx_queue = false;
      86       72252 :     for (auto &cb : callbacks.cb) {
      87       54189 :         if (cb == nullptr) {
      88       54189 :             continue;
      89             :         }
      90           0 :         if ((flags & IsForwardedFrame) == 0) {
      91             :             // call the frame callback from send only if the frame originated from this node
      92           0 :             cb(get_iface_num(), frame, flags);
      93           0 :         } else if (!added_to_rx_queue) {
      94             :             // the frame was forwarded from another interface, so add it to the receive queue
      95           0 :             CanRxItem rx_item;
      96           0 :             rx_item.frame = frame;
      97           0 :             rx_item.timestamp_us = AP_HAL::micros64();
      98           0 :             rx_item.flags = AP_HAL::CANIface::IsForwardedFrame;
      99           0 :             add_to_rx_queue(rx_item);
     100           0 :             added_to_rx_queue = true;
     101             :         }
     102             :     }
     103       36126 :     return 1;
     104       18063 : }
     105             : 
     106             : /*
     107             :   register a callback for for sending CAN_FRAME messages.
     108             :   On success the returned callback_id can be used to unregister the callback
     109             :  */
     110           0 : bool AP_HAL::CANIface::register_frame_callback(FrameCb cb, uint8_t &callback_id)
     111             : {
     112             : #ifndef HAL_BOOTLOADER_BUILD
     113           0 :     WITH_SEMAPHORE(callbacks.sem);
     114             : #endif
     115           0 :     for (uint8_t i=0; i<ARRAY_SIZE(callbacks.cb); i++) {
     116           0 :         if (callbacks.cb[i] == nullptr) {
     117           0 :             callbacks.cb[i] = cb;
     118           0 :             callback_id = i+1;
     119           0 :             return true;
     120             :         }
     121             :     }
     122           0 :     return false;
     123           0 : }
     124             : 
     125             : /*
     126             :   unregister a callback for for sending CAN_FRAME messages
     127             :  */
     128           0 : void AP_HAL::CANIface::unregister_frame_callback(uint8_t callback_id)
     129             : {
     130             : #ifndef HAL_BOOTLOADER_BUILD
     131           0 :     WITH_SEMAPHORE(callbacks.sem);
     132             : #endif
     133           0 :     const uint8_t idx = callback_id - 1;
     134           0 :     if (idx < ARRAY_SIZE(callbacks.cb)) {
     135           0 :         callbacks.cb[idx] = nullptr;
     136             :     }
     137           0 : }
     138             : 
     139         152 : AP_HAL::CANFrame::CANFrame(uint32_t can_id, const uint8_t* can_data, uint8_t data_len, bool canfd_frame) :
     140         152 :         id(can_id),
     141         152 :         canfd(canfd_frame)
     142             : {
     143         152 :     const uint8_t data_len_max = canfd_frame ? MaxDataLen : NonFDCANMaxDataLen;
     144         152 :     if ((can_data == nullptr) || (data_len == 0) || (data_len > data_len_max)) {
     145           0 :         dlc = 0;
     146           0 :         memset(data, 0, MaxDataLen);
     147           0 :         return;
     148             :     }
     149         152 :     memcpy(this->data, can_data, data_len);
     150         152 :     memset(&this->data[data_len], 0, MaxDataLen-data_len);
     151         152 :     if (data_len <= NonFDCANMaxDataLen) {
     152         152 :         dlc = data_len;
     153             :     } else {
     154             :         /*
     155             :         Data Length Code      9  10  11  12  13  14  15
     156             :         Number of data bytes 12  16  20  24  32  48  64
     157             :         */
     158           0 :         if (data_len <= 12) {
     159           0 :             dlc = 9;
     160           0 :         } else if (data_len <= 16) {
     161           0 :             dlc = 10;
     162           0 :         } else if (data_len <= 20) {
     163           0 :             dlc = 11;
     164           0 :         } else if  (data_len <= 24) {
     165           0 :             dlc = 12;
     166           0 :         } else if (data_len <= 32) {
     167           0 :             dlc = 13;
     168           0 :         } else if (data_len <= 48) {
     169           0 :             dlc = 14;
     170           0 :         } else if (data_len <= 64) {
     171           0 :             dlc = 15;
     172             :         }
     173             :     }
     174             : }
     175             : 
     176       18064 : uint8_t AP_HAL::CANFrame::dataLengthToDlc(uint8_t data_length)
     177             : {
     178       18064 :     if (data_length <= 8) {
     179       18064 :         return data_length;
     180           0 :     } else if (data_length <= 12) {
     181           0 :         return 9;
     182           0 :     } else if (data_length <= 16) {
     183           0 :         return 10;
     184           0 :     } else if (data_length <= 20) {
     185           0 :         return 11;
     186           0 :     } else if (data_length <= 24) {
     187           0 :         return 12;
     188           0 :     } else if (data_length <= 32) {
     189           0 :         return 13;
     190           0 :     } else if (data_length <= 48) {
     191           0 :         return 14;
     192             :     }
     193           0 :     return 15;
     194             : }
     195             : 
     196             : 
     197       18215 : uint8_t AP_HAL::CANFrame::dlcToDataLength(uint8_t dlc)
     198             : {
     199             :     /*
     200             :     Data Length Code      9  10  11  12  13  14  15
     201             :     Number of data bytes 12  16  20  24  32  48  64
     202             :     */
     203       18215 :     if (dlc <= 8) {
     204       18215 :         return dlc;
     205           0 :     } else if (dlc == 9) {
     206           0 :         return 12;
     207           0 :     } else if (dlc == 10) {
     208           0 :         return 16;
     209           0 :     } else if (dlc == 11) {
     210           0 :         return 20;
     211           0 :     } else if (dlc == 12) {
     212           0 :         return 24;
     213           0 :     } else if (dlc == 13) {
     214           0 :         return 32;
     215           0 :     } else if (dlc == 14) {
     216           0 :         return 48;
     217             :     }
     218           0 :     return 64;
     219             : }

Generated by: LCOV version 1.14