LCOV - code coverage report
Current view: top level - home/jenkins/platforms/s32k1xx/bsp/canflex2Transceiver/src/can/transceiver/canflex2 - CanFlex2Transceiver.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 177 188 94.1 %
Date: 2025-10-07 10:52:16 Functions: 15 18 83.3 %

          Line data    Source code
       1             : // Copyright 2024 Accenture.
       2             : 
       3             : #include "can/transceiver/canflex2/CanFlex2Transceiver.h"
       4             : 
       5             : #include <async/Types.h>
       6             : #include <can/CanLogger.h>
       7             : #include <can/framemgmt/IFilteredCANFrameSentListener.h>
       8             : #include <common/busid/BusId.h>
       9             : #include <etl/delegate.h>
      10             : #include <util/estd/assert.h>
      11             : 
      12             : #include <platform/config.h>
      13             : #include <platform/estdint.h>
      14             : 
      15             : namespace logger = ::util::logger;
      16             : 
      17             : namespace bios
      18             : {
      19             : CanFlex2Transceiver* CanFlex2Transceiver::fpCanTransceivers[8] = {0};
      20             : 
      21          36 : CanFlex2Transceiver::CanFlex2Transceiver(
      22             :     ::async::ContextType context,
      23             :     uint8_t const busId,
      24             :     FlexCANDevice::Config const& devConfig,
      25             :     CanPhy& Phy,
      26          36 :     IEcuPowerStateController& powerStateController)
      27             : : AbstractCANTransceiver(busId)
      28          36 : , fdevConfig(devConfig)
      29          36 : , fFlexCANDevice(
      30             :       devConfig,
      31             :       Phy,
      32             :       ::etl::delegate<
      33             :           void()>::create<CanFlex2Transceiver, &CanFlex2Transceiver::canFrameSentCallback>(*this),
      34             :       powerStateController)
      35          36 : , fIsPhyErrorPresent(false)
      36          36 : , fTxOfflineErrors(0)
      37          36 : , fOverrunCount(0)
      38          36 : , fFramesSentCount(0)
      39          36 : , fTxQueue()
      40          36 : , fFirstFrameNotified(false)
      41          36 : , fRxAlive(false)
      42          36 : , _context(context)
      43          36 : , _cyclicTask(
      44          36 :       ::async::Function::CallType::create<CanFlex2Transceiver, &CanFlex2Transceiver::cyclicTask>(
      45             :           *this))
      46             : , _cyclicTaskTimeout()
      47          36 : , _canFrameSent(
      48             :       ::async::Function::CallType::
      49          72 :           create<CanFlex2Transceiver, &CanFlex2Transceiver::canFrameSentAsyncCallback>(*this))
      50             : {
      51          36 :     fpCanTransceivers[fFlexCANDevice.getIndex()] = this;
      52          36 : }
      53             : 
      54          37 : ::can::ICanTransceiver::ErrorCode CanFlex2Transceiver::init()
      55             : {
      56          37 :     if (State::CLOSED == _state)
      57             :     {
      58             :         {
      59          36 :             ::async::LockType const lock;
      60          36 :             if (ErrorCode::CAN_ERR_INIT_FAILED == fFlexCANDevice.init())
      61             :             {
      62           1 :                 return ErrorCode::CAN_ERR_INIT_FAILED;
      63             :             }
      64          36 :         }
      65          35 :         (void)fFlexCANDevice.getPhy().setMode(CanPhy::CAN_PHY_MODE_ACTIVE, fdevConfig.BusId);
      66          35 :         _state = State::INITIALIZED;
      67          35 :         return ErrorCode::CAN_ERR_OK;
      68             :     }
      69           1 :     return ErrorCode::CAN_ERR_ILLEGAL_STATE;
      70             : }
      71             : 
      72           8 : ::can::ICanTransceiver::ErrorCode CanFlex2Transceiver::write(::can::CANFrame const& frame)
      73             : {
      74           8 :     return write(frame, nullptr);
      75             : }
      76             : 
      77             : ::can::ICanTransceiver::ErrorCode
      78          19 : CanFlex2Transceiver::write(::can::CANFrame const& frame, ::can::ICANFrameSentListener& listener)
      79             : {
      80          19 :     return write(frame, &listener);
      81             : }
      82             : 
      83          27 : ::can::ICanTransceiver::ErrorCode CanFlex2Transceiver::write(
      84             :     ::can::CANFrame const& frame, ::can::ICANFrameSentListener* const pListener)
      85             : {
      86          27 :     if (State::MUTED == _state)
      87             :     {
      88           1 :         logger::Logger::warn(
      89             :             logger::CAN,
      90             :             "Write Id 0x%x to muted %s",
      91             :             frame.getId(),
      92           1 :             ::common::busid::BusIdTraits::getName(_busId));
      93           1 :         return ErrorCode::CAN_ERR_ILLEGAL_STATE;
      94             :     }
      95          26 :     if (State::CLOSED == _state)
      96             :     {
      97           1 :         fTxOfflineErrors++;
      98           1 :         return ErrorCode::CAN_ERR_TX_OFFLINE;
      99             :     }
     100             : 
     101          25 :     ::async::ModifiableLockType mlock;
     102          25 :     if (pListener == nullptr)
     103             :     {
     104           6 :         uint8_t const messageBuffer = fFlexCANDevice.getTransmitBuffer(frame, false);
     105           6 :         if (FlexCANDevice::TRANSMIT_BUFFER_UNAVAILABLE == messageBuffer)
     106             :         {
     107           1 :             fOverrunCount++;
     108           1 :             mlock.unlock();
     109           1 :             notifyRegisteredSentListener(frame);
     110           1 :             return ErrorCode::CAN_ERR_TX_HW_QUEUE_FULL;
     111             :         }
     112             : 
     113           5 :         ErrorCode const status = fFlexCANDevice.transmit(frame, messageBuffer, false);
     114           5 :         if (ErrorCode::CAN_ERR_OK == status)
     115             :         {
     116           4 :             fFramesSentCount++;
     117           4 :             mlock.unlock();
     118           4 :             notifyRegisteredSentListener(frame);
     119           4 :             return ErrorCode::CAN_ERR_OK;
     120             :         }
     121           1 :         mlock.unlock();
     122           1 :         notifyRegisteredSentListener(frame);
     123           1 :         return ErrorCode::CAN_ERR_TX_FAIL;
     124             :     }
     125             : 
     126          19 :     if (fTxQueue.full())
     127             :     {
     128             :         // no more room for a sender with callback
     129           1 :         fOverrunCount++;
     130           1 :         mlock.unlock();
     131           1 :         notifyRegisteredSentListener(frame);
     132           1 :         return ErrorCode::CAN_ERR_TX_HW_QUEUE_FULL;
     133             :     }
     134          18 :     bool const wasEmpty = fTxQueue.empty();
     135          18 :     fTxQueue.emplace_back(*pListener, frame);
     136          18 :     if (!wasEmpty)
     137             :     {
     138             :         // nothing to do next frame will be sent from tx isr
     139           7 :         return ErrorCode::CAN_ERR_OK;
     140             :     }
     141             :     ErrorCode status;
     142             :     // we are the first sender --> transmit
     143          11 :     uint8_t const messageBuffer = fFlexCANDevice.getTransmitBuffer(frame, true);
     144          11 :     if (messageBuffer != FlexCANDevice::TRANSMIT_BUFFER_UNAVAILABLE)
     145             :     {
     146          10 :         status = fFlexCANDevice.transmit(frame, messageBuffer, true);
     147          10 :         if (ErrorCode::CAN_ERR_OK == status)
     148             :         {
     149             :             // wait until tx interrupt ...
     150             :             // ... then canFrameSentCallback() is called
     151           8 :             return ErrorCode::CAN_ERR_OK;
     152             :         }
     153           2 :         status = ErrorCode::CAN_ERR_TX_FAIL;
     154             :     }
     155             :     else
     156             :     {
     157           1 :         status = ErrorCode::CAN_ERR_TX_HW_QUEUE_FULL;
     158             :     }
     159           3 :     fTxQueue.pop_front();
     160           3 :     mlock.unlock();
     161           3 :     notifyRegisteredSentListener(frame);
     162           3 :     return status;
     163          25 : }
     164             : 
     165           7 : void CanFlex2Transceiver::canFrameSentCallback() { ::async::execute(_context, _canFrameSent); }
     166             : 
     167           7 : void CanFlex2Transceiver::canFrameSentAsyncCallback()
     168             : {
     169           7 :     ::async::ModifiableLockType mlock;
     170           7 :     fFramesSentCount++;
     171           7 :     if (!fTxQueue.empty())
     172             :     {
     173           5 :         bool sendAgain = false;
     174             :         {
     175           5 :             TxJobWithCallback& job                 = fTxQueue.front();
     176           5 :             ::can::CANFrame const& frame           = job._frame;
     177           5 :             ::can::ICANFrameSentListener& listener = job._listener;
     178           5 :             fTxQueue.pop_front();
     179           5 :             if (!fTxQueue.empty())
     180             :             {
     181             :                 // send again only if same precondition as for write() is satisfied!
     182           4 :                 if ((State::OPEN == _state) || (State::INITIALIZED == _state))
     183             :                 {
     184           4 :                     sendAgain = true;
     185             :                 }
     186             :                 else
     187             :                 {
     188           0 :                     fTxQueue.clear();
     189             :                 }
     190             :             }
     191           5 :             mlock.unlock();
     192           5 :             listener.canFrameSent(frame);
     193           5 :             notifyRegisteredSentListener(frame);
     194             :         }
     195           5 :         if (sendAgain)
     196             :         {
     197           4 :             mlock.lock();
     198           4 :             ::can::CANFrame const& frame = fTxQueue.front()._frame;
     199           4 :             uint8_t const messageBuffer  = fFlexCANDevice.getTransmitBuffer(frame, true);
     200           4 :             if (FlexCANDevice::TRANSMIT_BUFFER_UNAVAILABLE != messageBuffer)
     201             :             {
     202           3 :                 ErrorCode const status = fFlexCANDevice.transmit(frame, messageBuffer, true);
     203           3 :                 if (ErrorCode::CAN_ERR_OK == status)
     204             :                 {
     205             :                     // wait until tx interrupt ...
     206             :                     // ... then canFrameSentCallback() is called
     207           2 :                     return;
     208             :                 }
     209             :             }
     210             :             // no interrupt will ever retrigger this call => remove all queued frames
     211           2 :             fTxQueue.clear();
     212           2 :             mlock.unlock();
     213           2 :             notifyRegisteredSentListener(frame);
     214             :         }
     215             :     }
     216           7 : }
     217             : 
     218           0 : uint16_t CanFlex2Transceiver::getHwQueueTimeout() const
     219             : {
     220             :     // 64 = 8 byte payload
     221             :     // 53 = CAN overhead
     222           0 :     auto const timeout = ((53U + 64U) * 1000U / (fFlexCANDevice.getBaudrate()));
     223           0 :     return static_cast<uint16_t>(timeout);
     224             : }
     225             : 
     226           1 : uint16_t CanFlex2Transceiver::getFirstFrameId() const
     227             : {
     228           1 :     return static_cast<uint16_t>(fFlexCANDevice.getFirstCanId());
     229             : }
     230             : 
     231           1 : void CanFlex2Transceiver::resetFirstFrame()
     232             : {
     233           1 :     fFlexCANDevice.resetFirstFrame();
     234           1 :     fFirstFrameNotified = false;
     235           1 : }
     236             : 
     237           0 : ::can::ICanTransceiver::ErrorCode CanFlex2Transceiver::open(::can::CANFrame const& /* frame */)
     238             : {
     239             :     // not implemented
     240           0 :     estd_assert(false);
     241             :     return ::can::ICanTransceiver::ErrorCode::CAN_ERR_ILLEGAL_STATE;
     242             : }
     243             : 
     244          15 : ::can::ICanTransceiver::ErrorCode CanFlex2Transceiver::open()
     245             : {
     246          15 :     if ((State::INITIALIZED == _state) || (State::CLOSED == _state))
     247             :     {
     248          14 :         if (ErrorCode::CAN_ERR_OK == fFlexCANDevice.start())
     249             :         {
     250          14 :             (void)fFlexCANDevice.getPhy().setMode(CanPhy::CAN_PHY_MODE_ACTIVE, fdevConfig.BusId);
     251          14 :             _state = State::OPEN;
     252             : 
     253          14 :             ::async::scheduleAtFixedRate(
     254          14 :                 _context,
     255             :                 _cyclicTask,
     256          14 :                 _cyclicTaskTimeout,
     257             :                 ERROR_POLLING_TIMEOUT,
     258             :                 ::async::TimeUnitType::MILLISECONDS);
     259             : 
     260          14 :             return ErrorCode::CAN_ERR_OK;
     261             :         }
     262             :         else
     263             :         {
     264           0 :             return ErrorCode::CAN_ERR_ILLEGAL_STATE;
     265             :         }
     266             :     }
     267             :     else
     268             :     {
     269           1 :         return ErrorCode::CAN_ERR_ILLEGAL_STATE;
     270             :     }
     271             : }
     272             : 
     273           4 : ::can::ICanTransceiver::ErrorCode CanFlex2Transceiver::close()
     274             : {
     275           4 :     if ((State::OPEN == _state) || (State::MUTED == _state))
     276             :     {
     277           3 :         fFlexCANDevice.stop();
     278           3 :         (void)fFlexCANDevice.getPhy().setMode(CanPhy::CAN_PHY_MODE_STANDBY, fdevConfig.BusId);
     279             : 
     280           3 :         _cyclicTaskTimeout.cancel();
     281             : 
     282           3 :         _state = State::CLOSED;
     283             :         {
     284           3 :             ::async::LockType const lock;
     285           3 :             fTxQueue.clear();
     286           3 :         }
     287           3 :         return ErrorCode::CAN_ERR_OK;
     288             :     }
     289             :     else
     290             :     {
     291           1 :         return ErrorCode::CAN_ERR_ILLEGAL_STATE;
     292             :     }
     293             : }
     294             : 
     295           0 : void CanFlex2Transceiver::shutdown()
     296             : {
     297           0 :     (void)close();
     298           0 :     _cyclicTaskTimeout.cancel();
     299           0 : }
     300             : 
     301           8 : ::can::ICanTransceiver::ErrorCode CanFlex2Transceiver::mute()
     302             : {
     303           8 :     if (State::OPEN == _state)
     304             :     {
     305           6 :         fFlexCANDevice.mute();
     306             :         {
     307           6 :             async::LockType const lock;
     308           6 :             fTxQueue.clear();
     309           6 :         }
     310           6 :         _state = State::MUTED;
     311           6 :         return ErrorCode::CAN_ERR_OK;
     312             :     }
     313             :     else
     314             :     {
     315           2 :         return ErrorCode::CAN_ERR_ILLEGAL_STATE;
     316             :     }
     317             : }
     318             : 
     319           2 : ::can::ICanTransceiver::ErrorCode CanFlex2Transceiver::unmute()
     320             : {
     321           2 :     if (State::MUTED == _state)
     322             :     {
     323           1 :         fFlexCANDevice.unmute();
     324           1 :         _state = State::OPEN;
     325           1 :         return ErrorCode::CAN_ERR_OK;
     326             :     }
     327             :     else
     328             :     {
     329           1 :         return ErrorCode::CAN_ERR_ILLEGAL_STATE;
     330             :     }
     331             : }
     332             : 
     333           2 : void CanFlex2Transceiver::receiveTask()
     334             : {
     335           2 :     ::async::ModifiableLockType mlock;
     336           3 :     while (!fFlexCANDevice.isRxQueueEmpty())
     337             :     {
     338           1 :         ::can::CANFrame& frame = fFlexCANDevice.getRxFrameQueueFront();
     339           1 :         mlock.unlock();
     340           1 :         notifyListeners(frame);
     341           1 :         mlock.lock();
     342           1 :         fFlexCANDevice.dequeueRxFrame();
     343             :     }
     344           2 : }
     345             : 
     346          10 : void CanFlex2Transceiver::cyclicTask()
     347             : {
     348          10 :     if (fFlexCANDevice.getBusOffState() == FlexCANDevice::BUS_OFF)
     349             :     {
     350           2 :         if (_transceiverState != ::can::ICANTransceiverStateListener::CANTransceiverState::BUS_OFF)
     351             :         {
     352           2 :             _transceiverState = ::can::ICANTransceiverStateListener::CANTransceiverState::BUS_OFF;
     353           2 :             notifyStateListenerWithState(_transceiverState);
     354             :         }
     355             :     }
     356             :     else
     357             :     {
     358           8 :         if (_transceiverState != ::can::ICANTransceiverStateListener::CANTransceiverState::ACTIVE)
     359             :         {
     360           2 :             _transceiverState = ::can::ICANTransceiverStateListener::CANTransceiverState::ACTIVE;
     361           2 :             notifyStateListenerWithState(_transceiverState);
     362             :         }
     363             :     }
     364             : 
     365          10 :     CanPhy::ErrorCode const phyState = fFlexCANDevice.getPhy().getPhyErrorStatus(fdevConfig.BusId);
     366             : 
     367          10 :     if (phyState != CanPhy::CAN_PHY_ERROR_UNSUPPORTED)
     368             :     {
     369           9 :         if (phyState == CanPhy::CAN_PHY_ERROR)
     370             :         {
     371           2 :             if (!fIsPhyErrorPresent)
     372             :             {
     373           1 :                 fIsPhyErrorPresent = true;
     374           1 :                 notifyStateListenerWithPhyError();
     375             :             }
     376             :         }
     377             :         else
     378             :         {
     379           7 :             fIsPhyErrorPresent = false;
     380             :         }
     381             :     }
     382             :     // Check whether CAN was active since last poll
     383          10 :     if (fFlexCANDevice.getRxAlive() != 0)
     384             :     {
     385           6 :         fRxAlive = true;
     386             :     }
     387             :     else
     388             :     {
     389           4 :         fRxAlive = false;
     390             :     }
     391          10 :     fFlexCANDevice.clearRxAlive();
     392          10 : }
     393             : 
     394             : } // namespace bios

Generated by: LCOV version 1.14