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