libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_canfd.cpp
1#include "stm32_canfd.hpp"
2
3#ifdef HAL_FDCAN_MODULE_ENABLED
4
5using namespace LibXR;
6
7STM32CANFD* STM32CANFD::map[STM32_FDCAN_NUMBER] = {nullptr};
8
15stm32_fdcan_id_t STM32_FDCAN_GetID(FDCAN_GlobalTypeDef* addr)
16{
17 if (addr == nullptr)
18 { // NOLINT
19 return stm32_fdcan_id_t::STM32_FDCAN_ID_ERROR;
20 }
21#ifdef FDCAN1
22 else if (addr == FDCAN1)
23 { // NOLINT
24 return stm32_fdcan_id_t::STM32_FDCAN1;
25 }
26#endif
27#ifdef FDCAN2
28 else if (addr == FDCAN2)
29 { // NOLINT
30 return stm32_fdcan_id_t::STM32_FDCAN2;
31 }
32#endif
33#ifdef FDCAN3
34 else if (addr == FDCAN3)
35 { // NOLINT
36 return stm32_fdcan_id_t::STM32_FDCAN3;
37 }
38#endif
39 else
40 {
41 return stm32_fdcan_id_t::STM32_FDCAN_ID_ERROR;
42 }
43}
44
45STM32CANFD::STM32CANFD(FDCAN_HandleTypeDef* hcan, uint32_t queue_size)
46 : FDCAN(),
47 hcan_(hcan),
48 id_(STM32_FDCAN_GetID(hcan->Instance)),
49 tx_pool_(queue_size),
50 tx_pool_fd_(queue_size)
51{
52 map[id_] = this;
53 Init();
54}
55
56ErrorCode STM32CANFD::Init(void)
57{
58 FDCAN_FilterTypeDef can_filter = {};
59 can_filter.IdType = FDCAN_STANDARD_ID;
60 can_filter.FilterType = FDCAN_FILTER_MASK;
61 can_filter.FilterID1 = 0x0000;
62 can_filter.FilterID2 = 0x0000;
63 can_filter.FilterIndex = 0;
64
65#ifdef FDCAN3
66 if (id_ == STM32_FDCAN1)
67 {
68 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
69 }
70 else if (id_ == STM32_FDCAN2)
71 {
72 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
73 }
74 else if (id_ == STM32_FDCAN3)
75 {
76 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
77 }
78#else
79#ifdef FDCAN2
80 if (id_ == STM32_FDCAN1)
81 {
82 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
83 }
84 else if (id_ == STM32_FDCAN2)
85 {
86 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
87 }
88#else
89 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
90#endif
91#endif
92
93 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
94 {
95 return ErrorCode::FAILED;
96 }
97
98 can_filter.IdType = FDCAN_EXTENDED_ID;
99
100 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
101 {
102 return ErrorCode::FAILED;
103 }
104
105 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
106 {
107 return ErrorCode::FAILED;
108 }
109
110 if (can_filter.FilterConfig == FDCAN_FILTER_TO_RXFIFO0)
111 {
112 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
113 }
114 else
115 {
116 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
117 }
118
119 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
120
121 return ErrorCode::OK;
122}
123
124ErrorCode STM32CANFD::AddMessage(const ClassicPack& pack)
125{
126 FDCAN_TxHeaderTypeDef header; // NOLINT
127
128 header.Identifier = pack.id;
129
130 switch (pack.type)
131 {
132 case Type::STANDARD:
133 ASSERT(pack.id <= 0x7FF);
134 header.IdType = FDCAN_STANDARD_ID;
135 header.TxFrameType = FDCAN_DATA_FRAME;
136 break;
137
138 case Type::EXTENDED:
139 ASSERT(pack.id <= 0x1FFFFFFF);
140 header.IdType = FDCAN_EXTENDED_ID;
141 header.TxFrameType = FDCAN_DATA_FRAME;
142 break;
143
145 ASSERT(pack.id <= 0x7FF);
146 header.IdType = FDCAN_STANDARD_ID;
147 header.TxFrameType = FDCAN_REMOTE_FRAME;
148 break;
149
151 ASSERT(pack.id <= 0x1FFFFFFF);
152 header.IdType = FDCAN_EXTENDED_ID;
153 header.TxFrameType = FDCAN_REMOTE_FRAME;
154 break;
155 default:
156 ASSERT(false);
157 return ErrorCode::FAILED;
158 }
159
160 header.DataLength = FDCAN_DLC_BYTES_8;
161 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
162 header.BitRateSwitch = FDCAN_BRS_OFF;
163 header.FDFormat = FDCAN_CLASSIC_CAN;
164 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
165 header.MessageMarker = 0x01;
166
167 while (true)
168 {
169 uint32_t slot = 0;
170
171 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
172 {
173 if (tx_pool_.Put(pack, slot) != ErrorCode::OK)
174 {
175 return ErrorCode::FAILED;
176 }
177 }
178 else
179 {
180 return ErrorCode::OK;
181 }
182
183 if (bus_busy_.load(std::memory_order_acquire) == 0 &&
184 tx_pool_.RecycleSlot(slot) == ErrorCode::OK)
185 {
186 continue;
187 }
188 else
189 {
190 return ErrorCode::OK;
191 }
192 }
193}
194
195ErrorCode STM32CANFD::AddMessage(const FDPack& pack)
196{
197 FDCAN_TxHeaderTypeDef header;
198 ASSERT(pack.len <= 64);
199
200 header.Identifier = pack.id;
201
202 switch (pack.type)
203 {
204 case Type::STANDARD:
205 ASSERT(pack.id <= 0x7FF);
206 header.IdType = FDCAN_STANDARD_ID;
207 header.TxFrameType = FDCAN_DATA_FRAME;
208 break;
209
210 case Type::EXTENDED:
211 ASSERT(pack.id <= 0x1FFFFFFF);
212 header.IdType = FDCAN_EXTENDED_ID;
213 header.TxFrameType = FDCAN_DATA_FRAME;
214 break;
215
218 default:
219 ASSERT(false);
220 return ErrorCode::FAILED;
221 }
222
223 if (pack.len <= 8)
224 {
225 header.DataLength = FDCAN_PACK_LEN_MAP[pack.len];
226 }
227 else if (pack.len <= 24)
228 {
229 header.DataLength = FDCAN_PACK_LEN_MAP[(pack.len - 9) / 4 + 1 + 8];
230 }
231 else if (pack.len < 32)
232 {
233 header.DataLength = FDCAN_DLC_BYTES_32;
234 }
235 else if (pack.len < 48)
236 {
237 header.DataLength = FDCAN_DLC_BYTES_48;
238 }
239 else
240 {
241 header.DataLength = FDCAN_DLC_BYTES_64;
242 }
243
244 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
245 header.BitRateSwitch = FDCAN_BRS_ON;
246 header.FDFormat = FDCAN_FD_CAN;
247 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
248 header.MessageMarker = 0x00;
249
250 while (true)
251 {
252 uint32_t slot = 0;
253
254 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
255 {
256 if (tx_pool_fd_.Put(pack, slot) != ErrorCode::OK)
257 {
258 return ErrorCode::FAILED;
259 }
260 }
261 else
262 {
263 return ErrorCode::OK;
264 }
265
266 if (bus_busy_.load(std::memory_order_acquire) == 0 &&
267 tx_pool_fd_.RecycleSlot(slot) == ErrorCode::OK)
268 {
269 continue;
270 }
271 else
272 {
273 return ErrorCode::OK;
274 }
275 }
276}
277
279{
280 if (HAL_FDCAN_GetRxMessage(hcan_, fifo, &rx_buff_.header, rx_buff_.pack_fd.data) ==
281 HAL_OK)
282 {
283 if (rx_buff_.header.FDFormat == FDCAN_FD_CAN)
284 {
285 rx_buff_.pack_fd.id = rx_buff_.header.Identifier;
286 rx_buff_.pack_fd.type =
287 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
288
289 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
290 {
291 if (rx_buff_.pack_fd.type == Type::STANDARD)
292 {
293 rx_buff_.pack_fd.type = Type::REMOTE_STANDARD;
294 }
295 else
296 {
297 rx_buff_.pack_fd.type = Type::REMOTE_EXTENDED;
298 }
299 }
300
301 rx_buff_.pack_fd.len = rx_buff_.header.DataLength;
302
303 for (uint32_t i = 0; i < 16; i++)
304 {
305 if (rx_buff_.pack_fd.len == FDCAN_PACK_LEN_MAP[i])
306 {
307 rx_buff_.pack_fd.len = FDCAN_PACK_LEN_TO_INT_MAP[i];
308 break;
309 }
310 }
311
312 OnMessage(rx_buff_.pack_fd, true);
313 }
314 else
315 {
316 rx_buff_.pack.id = rx_buff_.header.Identifier;
317 rx_buff_.pack.type =
318 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
319
320 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
321 {
322 if (rx_buff_.pack.type == Type::STANDARD)
323 {
324 rx_buff_.pack.type = Type::REMOTE_STANDARD;
325 }
326 else
327 {
328 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
329 }
330 }
331 else
332 {
333 memcpy(rx_buff_.pack.data, rx_buff_.pack_fd.data, 8);
334 }
335
336 OnMessage(rx_buff_.pack, true);
337 }
338 }
339}
340
342{
343 if (tx_pool_fd_.Get(tx_buff_.pack_fd) == ErrorCode::OK)
344 {
345 tx_buff_.header.Identifier = tx_buff_.pack_fd.id;
346 switch (tx_buff_.pack_fd.type)
347 {
348 case Type::STANDARD:
349 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
350 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
351 break;
352
353 case Type::EXTENDED:
354 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
355 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
356 break;
357
359 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
360 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
361 break;
362
364 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
365 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
366 break;
367 default:
368 ASSERT(false);
369 return;
370 }
371 tx_buff_.header.DataLength = tx_buff_.pack_fd.len;
372 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
373 tx_buff_.header.BitRateSwitch = FDCAN_BRS_ON;
374 tx_buff_.header.FDFormat = FDCAN_FD_CAN;
375 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
376 tx_buff_.header.MessageMarker = 0x00;
377
378 HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack_fd.data);
379 bus_busy_.store(UINT32_MAX, std::memory_order_release);
380 }
381 else if (tx_pool_.Get(tx_buff_.pack) == ErrorCode::OK)
382 {
383 tx_buff_.header.Identifier = tx_buff_.pack.id;
384 switch (tx_buff_.pack.type)
385 {
386 case Type::STANDARD:
387 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
388 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
389 break;
390
391 case Type::EXTENDED:
392 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
393 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
394 break;
395
397 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
398 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
399 break;
400
402 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
403 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
404 break;
405 default:
406 ASSERT(false);
407 return;
408 }
409 tx_buff_.header.DataLength = 8;
410 tx_buff_.header.FDFormat = FDCAN_CLASSIC_CAN;
411 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
412 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
413 tx_buff_.header.MessageMarker = 0x00;
414 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
415 tx_buff_.header.BitRateSwitch = FDCAN_BRS_OFF;
416
417 HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack.data);
418 bus_busy_.store(UINT32_MAX, std::memory_order_release);
419 }
420
421 if (hcan_->Init.TxFifoQueueElmtsNbr - HAL_FDCAN_GetTxFifoFreeLevel(hcan_) == 0)
422 {
423 bus_busy_.store(0, std::memory_order_release);
424 }
425}
426
427extern "C" void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef* hcan)
428{
429 hcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
430 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
431 if (can)
432 {
433 can->ProcessTxInterrupt();
434 }
435}
436
437extern "C" void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef* hfdcan,
438 uint32_t ErrorStatusITs)
439{
440 if ((ErrorStatusITs & FDCAN_IT_BUS_OFF) != RESET)
441 {
442 FDCAN_ProtocolStatusTypeDef protocol_status = {};
443 HAL_FDCAN_GetProtocolStatus(hfdcan, &protocol_status);
444 if (protocol_status.BusOff)
445 {
446 CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
447 }
448 }
449
450 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hfdcan->Instance)];
451 if (can)
452 {
453 can->ProcessTxInterrupt();
454 }
455}
456
457extern "C" void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef* hcan,
458 uint32_t BufferIndexes)
459{
460 UNUSED(BufferIndexes);
461 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
462 if (can)
463 {
464 can->ProcessTxInterrupt();
465 }
466}
467
468extern "C" void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef* hcan)
469{
470 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
471 if (can)
472 {
473 can->ProcessTxInterrupt();
474 }
475}
476
477extern "C" void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo0ITs)
478{
479 UNUSED(RxFifo0ITs);
480 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
481 if (can)
482 {
483 can->ProcessRxInterrupt(FDCAN_RX_FIFO0);
484 }
485}
486
487extern "C" void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo1ITs)
488{
489 UNUSED(RxFifo1ITs);
490 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
491 if (can)
492 {
493 can->ProcessRxInterrupt(FDCAN_RX_FIFO1);
494 }
495}
496
497#endif
@ EXTENDED
扩展 CAN 消息 (Extended CAN message).
@ REMOTE_EXTENDED
远程扩展 CAN 消息 (Remote extended CAN message).
@ STANDARD
标准 CAN 消息 (Standard CAN message).
@ REMOTE_STANDARD
远程标准 CAN 消息 (Remote standard CAN message).
FDCAN 通信接口,扩展 CAN 功能,支持灵活数据速率(FD)CAN 消息 (FDCAN communication interface that extends CAN functionality...
Definition can.hpp:95
ErrorCode RecycleSlot(uint32_t index)
回收指定槽位 / Recycle a slot
ErrorCode Put(const Data &data)
向池中放入一个元素 / Put an element into the pool
ErrorCode Get(Data &data)
从池中取出一个元素 / Retrieve an element from the pool
STM32CANFD 类,用于处理 STM32 系统的 CANFD 通道。 Provides handling for STM32 CANFD.
ErrorCode Init(void)
初始化
void ProcessRxInterrupt(uint32_t fifo)
处理接收中断
STM32CANFD(FDCAN_HandleTypeDef *hcan, uint32_t queue_size)
STM32CANFD 类,用于处理 STM32 系统的 CANFD 通道。 Provides handling for STM32 CANFD.
ErrorCode AddMessage(const ClassicPack &pack) override
添加 CAN 消息到系统 (Adds a CAN message to the system).
void ProcessTxInterrupt()
处理发送中断
LibXR 命名空间
Definition ch32_gpio.hpp:9