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
|