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