Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2024 Accenture
3 : *
4 : * This program and the accompanying materials are made available under the
5 : * terms of the Apache License Version 2.0 which is available at
6 : * https://www.apache.org/licenses/LICENSE-2.0
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : ********************************************************************************/
10 :
11 : /**
12 : * Contains Cpp2CAN CanFlex2Transceiver
13 : * \file CanFlex2Transceiver.h
14 : * \ingroup transceiver
15 : */
16 : #pragma once
17 :
18 : #include <async/Async.h>
19 : #include <async/util/Call.h>
20 : #include <bsp/can/canTransceiver/CanPhy.h>
21 : #include <bsp/power/IEcuPowerStateController.h>
22 : #include <bsp/timer/SystemTimer.h>
23 : #include <can/FlexCANDevice.h>
24 : #include <can/canframes/CANFrame.h>
25 : #include <can/canframes/ICANFrameSentListener.h>
26 : #include <can/framemgmt/IFilteredCANFrameSentListener.h>
27 : #include <can/transceiver/AbstractCANTransceiver.h>
28 : #include <etl/deque.h>
29 : #include <etl/uncopyable.h>
30 : #include <io/Io.h>
31 : #include <lifecycle/AsyncLifecycleComponent.h>
32 :
33 : #include <platform/estdint.h>
34 :
35 : namespace bios
36 : {
37 : /**
38 : * CAN transceiver.
39 : * \see AbstractCANTransceiver
40 : * \see FlexCANDevice
41 : * \see common::AbstractTimeout
42 : */
43 : class CanFlex2Transceiver
44 : : public ::can::AbstractCANTransceiver
45 : , public ::etl::uncopyable
46 : {
47 : public:
48 : CanFlex2Transceiver(
49 : ::async::ContextType context,
50 : uint8_t busId,
51 : FlexCANDevice::Config const& devConfig,
52 : CanPhy& Phy,
53 : IEcuPowerStateController& powerStateController);
54 :
55 : ::can::ICanTransceiver::ErrorCode init() override;
56 : ::can::ICanTransceiver::ErrorCode open(::can::CANFrame const& frame) override;
57 : ::can::ICanTransceiver::ErrorCode open() override;
58 :
59 : ::can::ICanTransceiver::ErrorCode close() override;
60 :
61 : void shutdown() override;
62 :
63 : ::can::ICanTransceiver::ErrorCode write(can::CANFrame const& frame) override;
64 :
65 : ::can::ICanTransceiver::ErrorCode
66 : write(can::CANFrame const& frame, can::ICANFrameSentListener& listener) override;
67 :
68 : ErrorCode mute() override;
69 :
70 : ErrorCode unmute() override;
71 :
72 : /**
73 : * Checks if the CAN device associated with the transceiver has woken up.
74 : */
75 2 : bool wokenUp() { return fFlexCANDevice.wokenUp(); }
76 :
77 1 : uint32_t getBaudrate() const override { return fFlexCANDevice.getBaudrate(); }
78 :
79 : /**
80 : * \return the Hardware Queue Timeout.
81 : */
82 : uint16_t getHwQueueTimeout() const override;
83 :
84 : /**
85 : * \return ID of first frame seen after open() or resetFirstFrame() or INVALID_FRAME_ID.
86 : */
87 : virtual uint16_t getFirstFrameId() const;
88 :
89 : /**
90 : * Resets information about the first frame, the next frame received will be the first frame
91 : */
92 : virtual void resetFirstFrame();
93 :
94 : /**
95 : * Checks if the CAN transceiver is receiving data.
96 : */
97 6 : virtual bool getRxAlive() const
98 : {
99 6 : if (_state == State::MUTED)
100 : {
101 3 : return ((fRxAlive) || (fFlexCANDevice.getFirstCanId() != 0));
102 : }
103 : else
104 : {
105 3 : return fRxAlive;
106 : }
107 : }
108 :
109 : /**
110 : * \return the count of overrun events that have occurred in the CAN transceiver.
111 : */
112 : uint32_t getOverrunCount() const { return fOverrunCount; }
113 :
114 : /**
115 : * cyclicTask()
116 : *
117 : * Called periodically.
118 : * Checks transceiver error pins and bus state.
119 : * Notifies state change and phy error listeners.
120 : */
121 : void cyclicTask();
122 :
123 : /**
124 : * Processes the receive queue of the CAN device.
125 : */
126 : void receiveTask();
127 :
128 : /**
129 : * Handles sending of further frames if the transmit queue is not yet empty.
130 : */
131 : void canFrameSentCallback();
132 : void canFrameSentAsyncCallback();
133 :
134 : /**
135 : * Calls the Receive ISR
136 : * \return the number of frames received
137 : */
138 1 : static uint8_t receiveInterrupt(uint8_t const transceiverIndex)
139 : {
140 1 : return fpCanTransceivers[transceiverIndex]->fFlexCANDevice.receiveISR(
141 2 : fpCanTransceivers[transceiverIndex]->_filter.getRawBitField());
142 : }
143 :
144 : /**
145 : * Calls the Transmit ISR
146 : */
147 1 : static void transmitInterrupt(uint8_t const transceiverIndex)
148 : {
149 1 : fpCanTransceivers[transceiverIndex]->fFlexCANDevice.transmitISR();
150 1 : }
151 :
152 : /**
153 : * \return a list of all CanFlex2Transceiver
154 : */
155 1 : static CanFlex2Transceiver** getAllCanFlex2Transceivers() { return fpCanTransceivers; }
156 :
157 : private:
158 : /** polling time */
159 : static uint32_t const ERROR_POLLING_TIMEOUT = 10;
160 :
161 : struct TxJobWithCallback
162 : {
163 18 : TxJobWithCallback(::can::ICANFrameSentListener& listener, ::can::CANFrame const& frame)
164 18 : : _listener(listener), _frame(frame)
165 18 : {}
166 :
167 : ::can::ICANFrameSentListener& _listener;
168 : ::can::CANFrame const& _frame;
169 : };
170 :
171 : using TxQueue = ::etl::deque<TxJobWithCallback, 3>;
172 :
173 : static CanFlex2Transceiver* fpCanTransceivers[8];
174 : FlexCANDevice::Config const& fdevConfig;
175 : FlexCANDevice fFlexCANDevice;
176 : bool fIsPhyErrorPresent;
177 :
178 : uint16_t fTxOfflineErrors;
179 : uint32_t fOverrunCount;
180 : uint32_t fFramesSentCount;
181 :
182 : TxQueue fTxQueue;
183 :
184 : bool fFirstFrameNotified;
185 : bool fRxAlive;
186 :
187 : ::async::ContextType const _context;
188 : ::async::Function _cyclicTask;
189 : ::async::TimeoutType _cyclicTaskTimeout;
190 : ::async::Function _canFrameSent;
191 :
192 : ::can::ICanTransceiver::ErrorCode
193 : write(::can::CANFrame const& frame, ::can::ICANFrameSentListener* pListener);
194 :
195 17 : void notifyRegisteredSentListener(::can::CANFrame const& frame) { notifySentListeners(frame); }
196 : };
197 :
198 : } // namespace bios
|