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
45static inline uint32_t BytesToDlc(uint32_t n)
46{
47 if (n <= 8U)
48 {
49 return n;
50 } // FDCAN_DLC_BYTES_0..8 == 0..8
51 if (n <= 12U)
52 {
53 return FDCAN_DLC_BYTES_12;
54 }
55 if (n <= 16U)
56 {
57 return FDCAN_DLC_BYTES_16;
58 }
59 if (n <= 20U)
60 {
61 return FDCAN_DLC_BYTES_20;
62 }
63 if (n <= 24U)
64 {
65 return FDCAN_DLC_BYTES_24;
66 }
67 if (n <= 32U)
68 {
69 return FDCAN_DLC_BYTES_32;
70 }
71 if (n <= 48U)
72 {
73 return FDCAN_DLC_BYTES_48;
74 }
75 return FDCAN_DLC_BYTES_64; // n >= 49 → 64
76}
77
78static inline uint32_t DlcToBytes(uint32_t dlc)
79{
80 if (dlc <= FDCAN_DLC_BYTES_8)
81 { // 0..8 → 0..8
82 return dlc;
83 }
84 else if (dlc == FDCAN_DLC_BYTES_12)
85 {
86 return 12U;
87 }
88 else if (dlc == FDCAN_DLC_BYTES_16)
89 {
90 return 16U;
91 }
92 else if (dlc == FDCAN_DLC_BYTES_20)
93 {
94 return 20U;
95 }
96 else if (dlc == FDCAN_DLC_BYTES_24)
97 {
98 return 24U;
99 }
100 else if (dlc == FDCAN_DLC_BYTES_32)
101 {
102 return 32U;
103 }
104 else if (dlc == FDCAN_DLC_BYTES_48)
105 {
106 return 48U;
107 }
108 else
109 { // FDCAN_DLC_BYTES_64 或其它非法值
110 return 64U;
111 }
112}
113
114STM32CANFD::STM32CANFD(FDCAN_HandleTypeDef* hcan, uint32_t queue_size)
115 : FDCAN(),
116 hcan_(hcan),
117 id_(STM32_FDCAN_GetID(hcan->Instance)),
118 tx_pool_(queue_size),
119 tx_pool_fd_(queue_size)
120{
121 CheckMessageRAMOffset(hcan);
122 map[id_] = this;
123 Init();
124}
125
126ErrorCode STM32CANFD::Init(void)
127{
128 FDCAN_FilterTypeDef can_filter = {};
129 can_filter.IdType = FDCAN_STANDARD_ID;
130 can_filter.FilterType = FDCAN_FILTER_MASK;
131 can_filter.FilterID1 = 0x0000;
132 can_filter.FilterID2 = 0x0000;
133 can_filter.FilterIndex = 0;
134
135#ifdef FDCAN3
136 if (id_ == STM32_FDCAN1)
137 {
138 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
139 }
140 else if (id_ == STM32_FDCAN2)
141 {
142 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
143 }
144 else if (id_ == STM32_FDCAN3)
145 {
146 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
147 }
148#else
149#ifdef FDCAN2
150 if (id_ == STM32_FDCAN1)
151 {
152 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
153 }
154 else if (id_ == STM32_FDCAN2)
155 {
156 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
157 }
158#else
159 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
160#endif
161#endif
162
163 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
164 {
165 return ErrorCode::FAILED;
166 }
167
168 can_filter.IdType = FDCAN_EXTENDED_ID;
169
170 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
171 {
172 return ErrorCode::FAILED;
173 }
174
175 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
176 {
177 return ErrorCode::FAILED;
178 }
179
180 if (can_filter.FilterConfig == FDCAN_FILTER_TO_RXFIFO0)
181 {
182 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
183 }
184 else
185 {
186 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
187 }
188
189 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
190
191 return ErrorCode::OK;
192}
193
194ErrorCode STM32CANFD::AddMessage(const ClassicPack& pack)
195{
196 FDCAN_TxHeaderTypeDef header; // NOLINT
197
198 header.Identifier = pack.id;
199
200 switch (pack.type)
201 {
202 case Type::STANDARD:
203 ASSERT(pack.id <= 0x7FF);
204 header.IdType = FDCAN_STANDARD_ID;
205 header.TxFrameType = FDCAN_DATA_FRAME;
206 break;
207
208 case Type::EXTENDED:
209 ASSERT(pack.id <= 0x1FFFFFFF);
210 header.IdType = FDCAN_EXTENDED_ID;
211 header.TxFrameType = FDCAN_DATA_FRAME;
212 break;
213
215 ASSERT(pack.id <= 0x7FF);
216 header.IdType = FDCAN_STANDARD_ID;
217 header.TxFrameType = FDCAN_REMOTE_FRAME;
218 break;
219
221 ASSERT(pack.id <= 0x1FFFFFFF);
222 header.IdType = FDCAN_EXTENDED_ID;
223 header.TxFrameType = FDCAN_REMOTE_FRAME;
224 break;
225 default:
226 ASSERT(false);
227 return ErrorCode::FAILED;
228 }
229
230 header.DataLength = FDCAN_DLC_BYTES_8;
231 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
232 header.BitRateSwitch = FDCAN_BRS_OFF;
233 header.FDFormat = FDCAN_CLASSIC_CAN;
234 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
235 header.MessageMarker = 0x01;
236
237 while (true)
238 {
239 uint32_t slot = 0;
240
241 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
242 {
243 if (tx_pool_.Put(pack, slot) != ErrorCode::OK)
244 {
245 return ErrorCode::FAILED;
246 }
247 }
248 else
249 {
250 return ErrorCode::OK;
251 }
252
253 if (HardwareTxQueueEmptySize() != 0 && tx_pool_.RecycleSlot(slot) == ErrorCode::OK)
254 {
255 continue;
256 }
257 else
258 {
259 return ErrorCode::OK;
260 }
261 }
262}
263
264ErrorCode STM32CANFD::AddMessage(const FDPack& pack)
265{
266 FDCAN_TxHeaderTypeDef header;
267 ASSERT(pack.len <= 64);
268
269 header.Identifier = pack.id;
270
271 switch (pack.type)
272 {
273 case Type::STANDARD:
274 ASSERT(pack.id <= 0x7FF);
275 header.IdType = FDCAN_STANDARD_ID;
276 header.TxFrameType = FDCAN_DATA_FRAME;
277 break;
278
279 case Type::EXTENDED:
280 ASSERT(pack.id <= 0x1FFFFFFF);
281 header.IdType = FDCAN_EXTENDED_ID;
282 header.TxFrameType = FDCAN_DATA_FRAME;
283 break;
284
287 default:
288 ASSERT(false);
289 return ErrorCode::FAILED;
290 }
291
292 header.DataLength = BytesToDlc(pack.len);
293
294 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
295 header.BitRateSwitch = FDCAN_BRS_ON;
296 header.FDFormat = FDCAN_FD_CAN;
297 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
298 header.MessageMarker = 0x00;
299
300 while (true)
301 {
302 uint32_t slot = 0;
303
304 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
305 {
306 if (tx_pool_fd_.Put(pack, slot) != ErrorCode::OK)
307 {
308 return ErrorCode::FAILED;
309 }
310 }
311 else
312 {
313 return ErrorCode::OK;
314 }
315
316 if (HardwareTxQueueEmptySize() != 0 && tx_pool_fd_.RecycleSlot(slot) == ErrorCode::OK)
317 {
318 continue;
319 }
320 else
321 {
322 return ErrorCode::OK;
323 }
324 }
325}
326
328{
329 if (HAL_FDCAN_GetRxMessage(hcan_, fifo, &rx_buff_.header, rx_buff_.pack_fd.data) ==
330 HAL_OK)
331 {
332 if (rx_buff_.header.FDFormat == FDCAN_FD_CAN)
333 {
334 rx_buff_.pack_fd.id = rx_buff_.header.Identifier;
335 rx_buff_.pack_fd.type =
336 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
337
338 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
339 {
340 if (rx_buff_.pack_fd.type == Type::STANDARD)
341 {
342 rx_buff_.pack_fd.type = Type::REMOTE_STANDARD;
343 }
344 else
345 {
346 rx_buff_.pack_fd.type = Type::REMOTE_EXTENDED;
347 }
348 }
349
350 rx_buff_.pack_fd.len = DlcToBytes(rx_buff_.header.DataLength);
351
352 OnMessage(rx_buff_.pack_fd, true);
353 }
354 else
355 {
356 rx_buff_.pack.id = rx_buff_.header.Identifier;
357 rx_buff_.pack.type =
358 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
359
360 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
361 {
362 if (rx_buff_.pack.type == Type::STANDARD)
363 {
364 rx_buff_.pack.type = Type::REMOTE_STANDARD;
365 }
366 else
367 {
368 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
369 }
370 }
371 else
372 {
373 memcpy(rx_buff_.pack.data, rx_buff_.pack_fd.data, 8);
374 }
375
376 OnMessage(rx_buff_.pack, true);
377 }
378 }
379}
380
382{
383 if (tx_pool_fd_.Get(tx_buff_.pack_fd) == ErrorCode::OK)
384 {
385 tx_buff_.header.Identifier = tx_buff_.pack_fd.id;
386 switch (tx_buff_.pack_fd.type)
387 {
388 case Type::STANDARD:
389 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
390 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
391 break;
392
393 case Type::EXTENDED:
394 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
395 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
396 break;
397
399 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
400 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
401 break;
402
404 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
405 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
406 break;
407 default:
408 ASSERT(false);
409 return;
410 }
411 tx_buff_.header.DataLength = BytesToDlc(tx_buff_.pack_fd.len);
412 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
413 tx_buff_.header.BitRateSwitch = FDCAN_BRS_ON;
414 tx_buff_.header.FDFormat = FDCAN_FD_CAN;
415 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
416 tx_buff_.header.MessageMarker = 0x00;
417
418 HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack_fd.data);
419 }
420 else if (tx_pool_.Get(tx_buff_.pack) == ErrorCode::OK)
421 {
422 tx_buff_.header.Identifier = tx_buff_.pack.id;
423 switch (tx_buff_.pack.type)
424 {
425 case Type::STANDARD:
426 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
427 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
428 break;
429
430 case Type::EXTENDED:
431 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
432 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
433 break;
434
436 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
437 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
438 break;
439
441 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
442 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
443 break;
444 default:
445 ASSERT(false);
446 return;
447 }
448 tx_buff_.header.DataLength = 8;
449 tx_buff_.header.FDFormat = FDCAN_CLASSIC_CAN;
450 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
451 tx_buff_.header.MessageMarker = 0x00;
452 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
453 tx_buff_.header.BitRateSwitch = FDCAN_BRS_OFF;
454
455 HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack.data);
456 }
457}
458
459extern "C" void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef* hcan)
460{
461 hcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
462 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
463 if (can)
464 {
465 can->ProcessTxInterrupt();
466 }
467}
468
469extern "C" void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef* hfdcan,
470 uint32_t ErrorStatusITs)
471{
472 if ((ErrorStatusITs & FDCAN_IT_BUS_OFF) != RESET)
473 {
474 FDCAN_ProtocolStatusTypeDef protocol_status = {};
475 HAL_FDCAN_GetProtocolStatus(hfdcan, &protocol_status);
476 if (protocol_status.BusOff)
477 {
478 CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
479 }
480 }
481
482 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hfdcan->Instance)];
483 if (can)
484 {
485 can->ProcessTxInterrupt();
486 }
487}
488
489extern "C" void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef* hcan,
490 uint32_t BufferIndexes)
491{
492 UNUSED(BufferIndexes);
493 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
494 if (can)
495 {
496 can->ProcessTxInterrupt();
497 }
498}
499
500extern "C" void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef* hcan)
501{
502 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
503 if (can)
504 {
505 can->ProcessTxInterrupt();
506 }
507}
508
509extern "C" void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo0ITs)
510{
511 UNUSED(RxFifo0ITs);
512 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
513 if (can)
514 {
515 can->ProcessRxInterrupt(FDCAN_RX_FIFO0);
516 }
517}
518
519extern "C" void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo1ITs)
520{
521 UNUSED(RxFifo1ITs);
522 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
523 if (can)
524 {
525 can->ProcessRxInterrupt(FDCAN_RX_FIFO1);
526 }
527}
528
529#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).
size_t HardwareTxQueueEmptySize()
获取硬件发送队列空闲大小
void ProcessTxInterrupt()
处理发送中断
LibXR 命名空间
Definition ch32_gpio.hpp:9