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
114inline void STM32CANFD::BuildTxHeader(const ClassicPack& p, FDCAN_TxHeaderTypeDef& h)
115{
116 const bool is_ext = (p.type == Type::EXTENDED) || (p.type == Type::REMOTE_EXTENDED);
117 const bool is_rtr =
118 (p.type == Type::REMOTE_STANDARD) || (p.type == Type::REMOTE_EXTENDED);
119
120 h.Identifier = p.id;
121 h.IdType = is_ext ? FDCAN_EXTENDED_ID : FDCAN_STANDARD_ID;
122 h.TxFrameType = is_rtr ? FDCAN_REMOTE_FRAME : FDCAN_DATA_FRAME;
123
124 uint32_t bytes = (p.dlc <= 8u) ? p.dlc : 8u;
125 h.DataLength = BytesToDlc(bytes);
126
127 h.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
128 h.BitRateSwitch = FDCAN_BRS_OFF;
129 h.FDFormat = FDCAN_CLASSIC_CAN;
130
131 h.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
132 h.MessageMarker = 0x01;
133}
134
135inline void STM32CANFD::BuildTxHeader(const FDPack& p, FDCAN_TxHeaderTypeDef& h)
136{
137 h.Identifier = p.id;
138
139 switch (p.type)
140 {
141 case Type::STANDARD:
142 h.IdType = FDCAN_STANDARD_ID;
143 h.TxFrameType = FDCAN_DATA_FRAME;
144 break;
145
146 case Type::EXTENDED:
147 h.IdType = FDCAN_EXTENDED_ID;
148 h.TxFrameType = FDCAN_DATA_FRAME;
149 break;
150
151 default:
152 ASSERT(false);
153 return;
154 }
155
156 ASSERT(p.len <= 64u);
157 h.DataLength = BytesToDlc(p.len);
158
159 h.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
160 h.BitRateSwitch = FDCAN_BRS_ON;
161 h.FDFormat = FDCAN_FD_CAN;
162
163 h.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
164 h.MessageMarker = 0x00;
165}
166
167STM32CANFD::STM32CANFD(FDCAN_HandleTypeDef* hcan, uint32_t queue_size)
168 : FDCAN(),
169 hcan_(hcan),
170 id_(STM32_FDCAN_GetID(hcan->Instance)),
171 tx_queue_(queue_size),
172 tx_fd_queue_(queue_size)
173{
174 CheckMessageRAMOffset(hcan);
175 map[id_] = this;
176 Init();
177}
178
180{
181 FDCAN_FilterTypeDef can_filter = {};
182 can_filter.IdType = FDCAN_STANDARD_ID;
183 can_filter.FilterType = FDCAN_FILTER_MASK;
184 can_filter.FilterID1 = 0x0000;
185 can_filter.FilterID2 = 0x0000;
186 can_filter.FilterIndex = 0;
187
188#ifdef FDCAN3
189 if (id_ == STM32_FDCAN1)
190 {
191 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
192 }
193 else if (id_ == STM32_FDCAN2)
194 {
195 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
196 }
197 else if (id_ == STM32_FDCAN3)
198 {
199 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
200 }
201#else
202#ifdef FDCAN2
203 if (id_ == STM32_FDCAN1)
204 {
205 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
206 }
207 else if (id_ == STM32_FDCAN2)
208 {
209 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
210 }
211#else
212 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
213#endif
214#endif
215
216 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
217 {
218 return ErrorCode::FAILED;
219 }
220
221 can_filter.IdType = FDCAN_EXTENDED_ID;
222
223 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
224 {
225 return ErrorCode::FAILED;
226 }
227
228 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
229 {
230 return ErrorCode::FAILED;
231 }
232
233 if (can_filter.FilterConfig == FDCAN_FILTER_TO_RXFIFO0)
234 {
235 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
236 }
237 else
238 {
239 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
240 }
241
242 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_PASSIVE, 0);
243 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_WARNING, 0);
244 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_BUS_OFF, 0);
245 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
246 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_COMPLETE, 0xFFFFFFFF);
247
248 return ErrorCode::OK;
249}
250
252{
253 if (pack.type == Type::ERROR)
254 {
255 return ErrorCode::ARG_ERR;
256 }
257
258 if (tx_queue_.Push(pack) != ErrorCode::OK)
259 {
260 return ErrorCode::FULL;
261 }
262
263 TxService();
264 return ErrorCode::OK;
265}
266
268{
269 // 兼容接口:只用仲裁相位参数,FD 数据相位保持不动
270 FDCAN::Configuration fd_cfg{};
271 fd_cfg.bitrate = cfg.bitrate;
272 fd_cfg.sample_point = cfg.sample_point;
273 fd_cfg.bit_timing = cfg.bit_timing;
274 fd_cfg.mode = cfg.mode;
275 // data_timing / fd_mode 全部置 0 → “保持原值”
276 return SetConfig(fd_cfg);
277}
278
280{
281 if (hcan_ == nullptr || hcan_->Instance == nullptr)
282 {
283 ASSERT(false);
284 return ErrorCode::ARG_ERR;
285 }
286
287 FDCAN_GlobalTypeDef* can = hcan_->Instance;
288
289 // 先关通知:只关本驱动用到的这些
290 uint32_t it_mask = 0u;
291
292#ifdef FDCAN_IT_RX_FIFO0_NEW_MESSAGE
293 it_mask |= FDCAN_IT_RX_FIFO0_NEW_MESSAGE;
294#endif
295#ifdef FDCAN_IT_RX_FIFO1_NEW_MESSAGE
296 it_mask |= FDCAN_IT_RX_FIFO1_NEW_MESSAGE;
297#endif
298#ifdef FDCAN_IT_TX_FIFO_EMPTY
299 it_mask |= FDCAN_IT_TX_FIFO_EMPTY;
300#endif
301
302 if (it_mask != 0u)
303 {
304 HAL_FDCAN_DeactivateNotification(hcan_, it_mask);
305 }
306
307 // 停止 FDCAN,进入 INIT / CCE 配置状态
308 if (HAL_FDCAN_Stop(hcan_) != HAL_OK)
309 {
310 return ErrorCode::FAILED;
311 }
312
313#ifdef FDCAN_CCCR_INIT
314 SET_BIT(can->CCCR, FDCAN_CCCR_INIT);
315#endif
316#ifdef FDCAN_CCCR_CCE
317 SET_BIT(can->CCCR, FDCAN_CCCR_CCE);
318#endif
319
320 // 模式配置:one-shot / loopback / listen-only。
321 // Configure mode flags: one-shot / loopback / listen-only.
322#ifdef FDCAN_CCCR_DAR
323 if (cfg.mode.one_shot)
324 {
325 // 禁用自动重发
326 SET_BIT(can->CCCR, FDCAN_CCCR_DAR);
327 }
328 else
329 {
330 CLEAR_BIT(can->CCCR, FDCAN_CCCR_DAR);
331 }
332#endif
333
334 // triple_sampling 对 FDCAN 没意义,这里直接忽略
335 (void)cfg.mode.triple_sampling;
336
337#ifdef FDCAN_CCCR_TEST
338#ifdef FDCAN_TEST_LBCK
339 if (cfg.mode.loopback)
340 {
341 // 内部回环
342 SET_BIT(can->CCCR, FDCAN_CCCR_TEST);
343 SET_BIT(can->TEST, FDCAN_TEST_LBCK);
344 }
345 else
346 {
347 CLEAR_BIT(can->TEST, FDCAN_TEST_LBCK);
348 CLEAR_BIT(can->CCCR, FDCAN_CCCR_TEST);
349 }
350#endif
351#endif
352
353#ifdef FDCAN_CCCR_MON
354 if (cfg.mode.listen_only)
355 {
356 // 总线监控(只听)
357 SET_BIT(can->CCCR, FDCAN_CCCR_MON);
358 }
359 else
360 {
361 CLEAR_BIT(can->CCCR, FDCAN_CCCR_MON);
362 }
363#endif
364
365 // 仲裁相位时序范围校验并写入 NBTP。
366 // Validate nominal timing range and update NBTP.
367 const auto& bt = cfg.bit_timing;
368
369 // 用掩码算出字段最大值,避免硬编码
370#ifdef FDCAN_NBTP_NBRP_Msk
371 constexpr uint32_t NBRP_FIELD_MAX = (FDCAN_NBTP_NBRP_Msk >> FDCAN_NBTP_NBRP_Pos);
372 constexpr uint32_t NTSEG1_FIELD_MAX = (FDCAN_NBTP_NTSEG1_Msk >> FDCAN_NBTP_NTSEG1_Pos);
373 constexpr uint32_t NTSEG2_FIELD_MAX = (FDCAN_NBTP_NTSEG2_Msk >> FDCAN_NBTP_NTSEG2_Pos);
374 constexpr uint32_t NSJW_FIELD_MAX = (FDCAN_NBTP_NSJW_Msk >> FDCAN_NBTP_NSJW_Pos);
375
376 constexpr uint32_t NBRP_MAX = NBRP_FIELD_MAX + 1u;
377 constexpr uint32_t NTSEG1_MAX = NTSEG1_FIELD_MAX + 1u;
378 constexpr uint32_t NTSEG2_MAX = NTSEG2_FIELD_MAX + 1u;
379 constexpr uint32_t NSJW_MAX = NSJW_FIELD_MAX + 1u;
380
381 // 0 = 保持原值,非 0 做范围检查
382 if (bt.brp != 0u)
383 {
384 if (bt.brp < 1u || bt.brp > NBRP_MAX)
385 {
386 ASSERT(false);
387 return ErrorCode::ARG_ERR;
388 }
389 }
390
391 uint32_t tseg1 = bt.prop_seg + bt.phase_seg1;
392 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
393 {
394 if (tseg1 < 1u || tseg1 > NTSEG1_MAX)
395 {
396 ASSERT(false);
397 return ErrorCode::ARG_ERR;
398 }
399 }
400
401 if (bt.phase_seg2 != 0u)
402 {
403 if (bt.phase_seg2 < 1u || bt.phase_seg2 > NTSEG2_MAX)
404 {
405 ASSERT(false);
406 return ErrorCode::ARG_ERR;
407 }
408 }
409
410 if (bt.sjw != 0u)
411 {
412 if (bt.sjw < 1u || bt.sjw > NSJW_MAX)
413 {
414 ASSERT(false);
415 return ErrorCode::ARG_ERR;
416 }
417 if (bt.phase_seg2 != 0u && bt.sjw > bt.phase_seg2)
418 {
419 ASSERT(false);
420 return ErrorCode::ARG_ERR;
421 }
422 }
423
424 uint32_t nbtp_old = can->NBTP;
425 uint32_t nbtp_new = nbtp_old;
426 uint32_t nbtp_mask = 0u;
427
428 // NBRP
429 if (bt.brp != 0u)
430 {
431 uint32_t nbrp = (bt.brp - 1u) & NBRP_FIELD_MAX;
432 uint32_t mask = FDCAN_NBTP_NBRP_Msk;
433 nbtp_mask |= mask;
434 nbtp_new &= ~mask;
435 nbtp_new |= (nbrp << FDCAN_NBTP_NBRP_Pos);
436 }
437
438 // NTSEG1 = PROP_SEG + PHASE_SEG1
439 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
440 {
441 uint32_t ntseg1 = (tseg1 - 1u) & NTSEG1_FIELD_MAX;
442 uint32_t mask = FDCAN_NBTP_NTSEG1_Msk;
443 nbtp_mask |= mask;
444 nbtp_new &= ~mask;
445 nbtp_new |= (ntseg1 << FDCAN_NBTP_NTSEG1_Pos);
446 }
447
448 // NTSEG2 = PHASE_SEG2
449 if (bt.phase_seg2 != 0u)
450 {
451 uint32_t ntseg2 = (bt.phase_seg2 - 1u) & NTSEG2_FIELD_MAX;
452 uint32_t mask = FDCAN_NBTP_NTSEG2_Msk;
453 nbtp_mask |= mask;
454 nbtp_new &= ~mask;
455 nbtp_new |= (ntseg2 << FDCAN_NBTP_NTSEG2_Pos);
456 }
457
458 // NSJW
459 if (bt.sjw != 0u)
460 {
461 uint32_t nsjw = (bt.sjw - 1u) & NSJW_FIELD_MAX;
462 uint32_t mask = FDCAN_NBTP_NSJW_Msk;
463 nbtp_mask |= mask;
464 nbtp_new &= ~mask;
465 nbtp_new |= (nsjw << FDCAN_NBTP_NSJW_Pos);
466 }
467
468 if (nbtp_mask != 0u)
469 {
470 nbtp_old &= ~nbtp_mask;
471 nbtp_old |= (nbtp_new & nbtp_mask);
472 can->NBTP = nbtp_old;
473 }
474#endif // FDCAN_NBTP_NBRP_Msk
475
476 // 数据相位时序范围校验并写入 DBTP(仅 CAN FD)。
477 // Validate data-phase timing and update DBTP (CAN FD only).
478 const auto& dbt = cfg.data_timing;
479
480#ifdef FDCAN_DBTP_DBRP_Msk
481 constexpr uint32_t DBRP_FIELD_MAX = (FDCAN_DBTP_DBRP_Msk >> FDCAN_DBTP_DBRP_Pos);
482 constexpr uint32_t DTSEG1_FIELD_MAX = (FDCAN_DBTP_DTSEG1_Msk >> FDCAN_DBTP_DTSEG1_Pos);
483 constexpr uint32_t DTSEG2_FIELD_MAX = (FDCAN_DBTP_DTSEG2_Msk >> FDCAN_DBTP_DTSEG2_Pos);
484 constexpr uint32_t DSJW_FIELD_MAX = (FDCAN_DBTP_DSJW_Msk >> FDCAN_DBTP_DSJW_Pos);
485
486 constexpr uint32_t DBRP_MAX = DBRP_FIELD_MAX + 1u;
487 constexpr uint32_t DTSEG1_MAX = DTSEG1_FIELD_MAX + 1u;
488 constexpr uint32_t DTSEG2_MAX = DTSEG2_FIELD_MAX + 1u;
489 constexpr uint32_t DSJW_MAX = DSJW_FIELD_MAX + 1u;
490
491 if (dbt.brp != 0u)
492 {
493 if (dbt.brp < 1u || dbt.brp > DBRP_MAX)
494 {
495 ASSERT(false);
496 return ErrorCode::ARG_ERR;
497 }
498 }
499
500 uint32_t dtseg1 = dbt.prop_seg + dbt.phase_seg1;
501 if (dbt.prop_seg != 0u || dbt.phase_seg1 != 0u)
502 {
503 if (dtseg1 < 1u || dtseg1 > DTSEG1_MAX)
504 {
505 ASSERT(false);
506 return ErrorCode::ARG_ERR;
507 }
508 }
509
510 if (dbt.phase_seg2 != 0u)
511 {
512 if (dbt.phase_seg2 < 1u || dbt.phase_seg2 > DTSEG2_MAX)
513 {
514 ASSERT(false);
515 return ErrorCode::ARG_ERR;
516 }
517 }
518
519 if (dbt.sjw != 0u)
520 {
521 if (dbt.sjw < 1u || dbt.sjw > DSJW_MAX)
522 {
523 ASSERT(false);
524 return ErrorCode::ARG_ERR;
525 }
526 if (dbt.phase_seg2 != 0u && dbt.sjw > dbt.phase_seg2)
527 {
528 ASSERT(false);
529 return ErrorCode::ARG_ERR;
530 }
531 }
532
533 uint32_t dbtp_old = can->DBTP;
534 uint32_t dbtp_new = dbtp_old;
535 uint32_t dbtp_mask = 0u;
536
537 if (dbt.brp != 0u)
538 {
539 uint32_t dbrp = (dbt.brp - 1u) & DBRP_FIELD_MAX;
540 uint32_t mask = FDCAN_DBTP_DBRP_Msk;
541 dbtp_mask |= mask;
542 dbtp_new &= ~mask;
543 dbtp_new |= (dbrp << FDCAN_DBTP_DBRP_Pos);
544 }
545
546 if (dbt.prop_seg != 0u || dbt.phase_seg1 != 0u)
547 {
548 uint32_t dt1 = (dtseg1 - 1u) & DTSEG1_FIELD_MAX;
549 uint32_t mask = FDCAN_DBTP_DTSEG1_Msk;
550 dbtp_mask |= mask;
551 dbtp_new &= ~mask;
552 dbtp_new |= (dt1 << FDCAN_DBTP_DTSEG1_Pos);
553 }
554
555 if (dbt.phase_seg2 != 0u)
556 {
557 uint32_t dt2 = (dbt.phase_seg2 - 1u) & DTSEG2_FIELD_MAX;
558 uint32_t mask = FDCAN_DBTP_DTSEG2_Msk;
559 dbtp_mask |= mask;
560 dbtp_new &= ~mask;
561 dbtp_new |= (dt2 << FDCAN_DBTP_DTSEG2_Pos);
562 }
563
564 if (dbt.sjw != 0u)
565 {
566 uint32_t dsjw = (dbt.sjw - 1u) & DSJW_FIELD_MAX;
567 uint32_t mask = FDCAN_DBTP_DSJW_Msk;
568 dbtp_mask |= mask;
569 dbtp_new &= ~mask;
570 dbtp_new |= (dsjw << FDCAN_DBTP_DSJW_Pos);
571 }
572
573 if (dbtp_mask != 0u)
574 {
575 dbtp_old &= ~dbtp_mask;
576 dbtp_old |= (dbtp_new & dbtp_mask);
577 can->DBTP = dbtp_old;
578 }
579#else
580 (void)dbt;
581#endif // FDCAN_DBTP_DBRP_Msk
582
583 // 数据相位 FDMode:这里不动寄存器,只保留在上层语义中使用
584 (void)cfg.fd_mode;
585
586 // 重新启动 FDCAN
587 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
588 {
589 return ErrorCode::FAILED;
590 }
591
592 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_PASSIVE, 0);
593 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_WARNING, 0);
594 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_BUS_OFF, 0);
595 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
596 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
597 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
598 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_COMPLETE, 0xFFFFFFFF);
599
600 return ErrorCode::OK;
601}
602
604{
605 // 所有带 FDCAN 的 STM32 都通过 RCCEx 提供核时钟查询
606#if defined(RCC_PERIPHCLK_FDCAN)
607 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN);
608#elif defined(RCC_PERIPHCLK_FDCAN1)
609 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1);
610#else
611 // 理论上不会走到这里,有就说明 HAL/RCC 宏不一致
612 ASSERT(false);
613 return 0u;
614#endif
615}
616
618{
619 if (pack.type == Type::ERROR)
620 {
621 return ErrorCode::ARG_ERR;
622 }
623
624 ASSERT(pack.len <= 64u);
625 if (pack.type != Type::STANDARD && pack.type != Type::EXTENDED)
626 {
627 ASSERT(false);
628 return ErrorCode::FAILED;
629 }
630
631 if (tx_fd_queue_.Push(pack) != ErrorCode::OK)
632 {
633 return ErrorCode::FULL;
634 }
635
636 TxService();
637 return ErrorCode::OK;
638}
639
641{
642 if (HAL_FDCAN_GetRxMessage(hcan_, fifo, &rx_buff_.header, rx_buff_.pack_fd.data) ==
643 HAL_OK)
644 {
645 if (rx_buff_.header.FDFormat == FDCAN_FD_CAN)
646 {
647 rx_buff_.pack_fd.id = rx_buff_.header.Identifier;
648 rx_buff_.pack_fd.type =
649 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
650
651 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
652 {
653 if (rx_buff_.pack_fd.type == Type::STANDARD)
654 {
655 rx_buff_.pack_fd.type = Type::REMOTE_STANDARD;
656 }
657 else
658 {
659 rx_buff_.pack_fd.type = Type::REMOTE_EXTENDED;
660 }
661 }
662
663 rx_buff_.pack_fd.len = DlcToBytes(rx_buff_.header.DataLength);
664
665 OnMessage(rx_buff_.pack_fd, true);
666 }
667 else
668 {
669 rx_buff_.pack.id = rx_buff_.header.Identifier;
670 rx_buff_.pack.type =
671 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
672
673 uint32_t bytes = DlcToBytes(rx_buff_.header.DataLength);
674 if (bytes > 8u)
675 {
676 bytes = 8u;
677 }
678
679 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
680 {
681 if (rx_buff_.pack.type == Type::STANDARD)
682 {
683 rx_buff_.pack.type = Type::REMOTE_STANDARD;
684 }
685 else
686 {
687 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
688 }
689 rx_buff_.pack.dlc = static_cast<uint8_t>(bytes);
690 }
691 else
692 {
693 rx_buff_.pack.dlc = static_cast<uint8_t>(bytes);
694 if (bytes > 0u)
695 {
696 Memory::FastCopy(rx_buff_.pack.data, rx_buff_.pack_fd.data, bytes);
697 }
698 }
699
700 OnMessage(rx_buff_.pack, true);
701 }
702 }
703}
704
705void STM32CANFD::TxService()
706{
707 if (hcan_ == nullptr || hcan_->Instance == nullptr)
708 {
709 return;
710 }
711
712 tx_pend_.store(1u, std::memory_order_release);
713
714 uint32_t expected = 0u;
715 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
716 std::memory_order_relaxed))
717 {
718 return;
719 }
720
721 for (;;)
722 {
723 tx_pend_.store(0u, std::memory_order_release);
724
725 while (HardwareTxQueueEmptySize() != 0u)
726 {
727 // 保留原有 FD 优先发送策略。
728 // Preserve the existing FD-priority TX policy.
729 FDPack pfd{};
730 bool has_fd = tx_fd_retry_valid_;
731 if (has_fd)
732 {
733 pfd = tx_fd_retry_pack_;
734 }
735 else
736 {
737 has_fd = (tx_fd_queue_.Pop(pfd) == ErrorCode::OK);
738 }
739
740 if (has_fd)
741 {
742 FDCAN_TxHeaderTypeDef hdr{};
743 BuildTxHeader(pfd, hdr);
744
745 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &hdr, pfd.data) != HAL_OK)
746 {
747 tx_fd_retry_pack_ = pfd;
748 tx_fd_retry_valid_ = true;
749 break; // 不做立即 retry
750 }
751 tx_fd_retry_valid_ = false;
752 continue;
753 }
754
755 ClassicPack pc{};
756 bool has_classic = tx_classic_retry_valid_;
757 if (has_classic)
758 {
760 }
761 else
762 {
763 has_classic = (tx_queue_.Pop(pc) == ErrorCode::OK);
764 }
765
766 if (has_classic)
767 {
768 FDCAN_TxHeaderTypeDef hdr{};
769 BuildTxHeader(pc, hdr);
770
771 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &hdr, pc.data) != HAL_OK)
772 {
775 break;
776 }
778 continue;
779 }
780
781 break; // 两个软件队列都空
782 }
783
784 tx_lock_.store(0u, std::memory_order_release);
785
786 if (tx_pend_.load(std::memory_order_acquire) == 0u)
787 {
788 return;
789 }
790
791 expected = 0u;
792 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
793 std::memory_order_relaxed))
794 {
795 return;
796 }
797 }
798}
799
800void STM32CANFD::ProcessErrorStatusInterrupt(uint32_t error_status_its)
801{
802 FDCAN_ProtocolStatusTypeDef protocol_status = {};
803 HAL_FDCAN_GetProtocolStatus(hcan_, &protocol_status);
804
805#ifdef FDCAN_IT_BUS_OFF
806#ifdef FDCAN_CCCR_INIT
807 if ((error_status_its & FDCAN_IT_BUS_OFF) != 0u && protocol_status.BusOff != 0u)
808 {
809 CLEAR_BIT(hcan_->Instance->CCCR, FDCAN_CCCR_INIT);
810 }
811#endif
812#endif
813
814 CAN::ClassicPack pack{};
815 pack.type = CAN::Type::ERROR;
816 pack.dlc = 0;
817
818 CAN::ErrorID eid = CAN::ErrorID::CAN_ERROR_ID_GENERIC;
819
820 if (protocol_status.BusOff != 0u)
821 {
822 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
823 }
824 else if (protocol_status.ErrorPassive != 0u)
825 {
826 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
827 }
828 else if (protocol_status.Warning != 0u)
829 {
830 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
831 }
832 else
833 {
834 uint32_t lec = protocol_status.LastErrorCode & 0x7u;
835 if (lec == 0u)
836 {
837 lec = protocol_status.DataLastErrorCode & 0x7u;
838 }
839
840 switch (lec)
841 {
842 case 0x01u:
843 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
844 break;
845 case 0x02u:
846 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
847 break;
848 case 0x03u:
849 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
850 break;
851 case 0x04u:
852 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
853 break;
854 case 0x05u:
855 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
856 break;
857 case 0x06u:
858 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
859 break;
860 default:
861 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
862 break;
863 }
864 }
865
866 pack.id = static_cast<uint32_t>(eid);
867
868 OnMessage(pack, true);
869}
870
872{
873 if (hcan_ == nullptr || hcan_->Instance == nullptr)
874 {
875 return ErrorCode::ARG_ERR;
876 }
877
878 FDCAN_ErrorCountersTypeDef counters{};
879 if (HAL_FDCAN_GetErrorCounters(hcan_, &counters) != HAL_OK)
880 {
881 return ErrorCode::FAILED;
882 }
883
884 FDCAN_ProtocolStatusTypeDef proto{};
885 if (HAL_FDCAN_GetProtocolStatus(hcan_, &proto) != HAL_OK)
886 {
887 return ErrorCode::FAILED;
888 }
889
890 state.tx_error_counter = counters.TxErrorCnt;
891 state.rx_error_counter = counters.RxErrorCnt;
892
893 state.bus_off = (proto.BusOff != 0u);
894 state.error_passive = (proto.ErrorPassive != 0u);
895 state.error_warning = (proto.Warning != 0u);
896
897 return ErrorCode::OK;
898}
899
900extern "C" void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef* hcan)
901{
902 hcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
903 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
904 if (can)
905 {
906 can->TxService();
907 }
908}
909
910extern "C" void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef* hfdcan,
911 uint32_t ErrorStatusITs)
912{
913 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hfdcan->Instance)];
914 if (can)
915 {
916 can->ProcessErrorStatusInterrupt(ErrorStatusITs);
917 can->TxService();
918 }
919}
920
921extern "C" void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef* hcan,
922 uint32_t BufferIndexes)
923{
924 UNUSED(BufferIndexes);
925 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
926 if (can)
927 {
928 can->TxService();
929 }
930}
931
932extern "C" void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef* hcan)
933{
934 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
935 if (can)
936 {
937 can->TxService();
938 }
939}
940
941extern "C" void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo0ITs)
942{
943 UNUSED(RxFifo0ITs);
944 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
945 if (can)
946 {
947 can->ProcessRxInterrupt(FDCAN_RX_FIFO0);
948 }
949}
950
951extern "C" void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo1ITs)
952{
953 UNUSED(RxFifo1ITs);
954 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
955 if (can)
956 {
957 can->ProcessRxInterrupt(FDCAN_RX_FIFO1);
958 }
959}
960
961#endif
@ EXTENDED
扩展数据帧(29-bit ID)。Extended data frame (29-bit ID).
@ REMOTE_EXTENDED
扩展远程帧。Extended remote frame.
@ STANDARD
标准数据帧(11-bit ID)。Standard data frame (11-bit ID).
@ REMOTE_STANDARD
标准远程帧。Standard remote frame.
@ ERROR
错误帧(虚拟事件)。Error frame (virtual event).
ErrorID
ClassicPack::type == Type::ERROR 时使用的虚拟 ID。 Virtual IDs used when ClassicPack::type == Type::ERROR.
Definition can.hpp:146
FDCAN 通信抽象类,扩展支持 CAN FD 帧。 Abstract class for FDCAN communication with CAN FD frame support.
Definition can.hpp:247
void OnMessage(const FDPack &pack, bool in_isr)
分发接收到的 FD CAN 帧。 Dispatch a received FD CAN frame.
Definition can.cpp:54
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
ErrorCode Push(const Data &item)
推入一个强类型元素。
ErrorCode Pop(Data &item)
弹出一个强类型元素。
STM32 FDCAN 驱动实现 / STM32 FDCAN driver implementation.
void ProcessErrorStatusInterrupt(uint32_t error_status_its)
处理错误状态中断 / Handle error-status interrupt
MPMCQueue< FDPack > tx_fd_queue_
FD 发送软件队列。 FD TX software queue.
MPMCQueue< ClassicPack > tx_queue_
Classic 发送软件队列。 Classic TX software queue.
uint32_t GetClockFreq() const override
获取 FDCAN 外设时钟 / Get FDCAN kernel clock
ErrorCode Init(void)
初始化驱动 / Initialize driver
void ProcessRxInterrupt(uint32_t fifo)
处理接收中断 / Handle RX interrupt
STM32CANFD(FDCAN_HandleTypeDef *hcan, uint32_t queue_size)
构造 FDCAN 驱动对象 / Construct FDCAN driver object
ErrorCode GetErrorState(CAN::ErrorState &state) const override
查询当前错误状态 / Query current FDCAN error state
ErrorCode AddMessage(const ClassicPack &pack) override
添加经典 CAN 消息。Add classic CAN message.
size_t HardwareTxQueueEmptySize()
获取硬件发送队列空闲数 / Get free level of hardware TX queue
bool tx_classic_retry_valid_
待重试 Classic 帧有效标记。 Pending Classic retry frame flag.
ErrorCode SetConfig(const CAN::Configuration &cfg) override
设置 CAN/FDCAN 配置 / Set CAN/FDCAN configuration
FDPack tx_fd_retry_pack_
待重试 FD 帧。 Pending FD retry frame.
bool tx_fd_retry_valid_
待重试 FD 帧有效标记。 Pending FD retry frame flag.
ClassicPack tx_classic_retry_pack_
待重试 Classic 帧。 Pending Classic retry frame.
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ FAILED
操作失败 | Operation failed
@ FULL
已满 | Full
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
uint32_t prop_seg
传播段。Propagation segment.
Definition can.hpp:39
经典 CAN 帧数据结构。Classic CAN frame structure.
Definition can.hpp:129
Type type
帧类型。Frame type.
Definition can.hpp:131
uint32_t id
CAN ID(11/29 bit 或 ErrorID)。CAN ID (11/29 bits or ErrorID).
Definition can.hpp:130
uint8_t dlc
有效数据长度(0~8)。Data length code (0–8).
Definition can.hpp:132
CAN 配置参数。CAN configuration parameters.
Definition can.hpp:62
BitTiming bit_timing
位时序配置。Bit timing configuration.
Definition can.hpp:65
float sample_point
仲裁相位采样点(0~1)。Nominal sample point (0–1).
Definition can.hpp:64
Mode mode
工作模式。Operating mode.
Definition can.hpp:66
uint32_t bitrate
仲裁相位目标波特率。Target nominal bitrate.
Definition can.hpp:63
CAN 当前错误状态快照(来自硬件计数器/状态机)。 Snapshot of current CAN controller error state (from HW counters/state).
Definition can.hpp:88
bool bus_off
是否处于 BUS-OFF。True if controller is bus-off.
Definition can.hpp:92
bool error_passive
是否处于 Error Passive。True if error-passive.
Definition can.hpp:93
uint8_t tx_error_counter
发送错误计数 TEC。Transmit error counter (TEC).
Definition can.hpp:89
bool error_warning
是否处于 Error Warning。True if error-warning.
Definition can.hpp:94
uint8_t rx_error_counter
接收错误计数 REC。Receive error counter (REC).
Definition can.hpp:90
bool triple_sampling
三采样。Triple sampling.
Definition can.hpp:53
bool loopback
回环模式。Loopback mode.
Definition can.hpp:51
bool one_shot
单次发送模式。One-shot transmission.
Definition can.hpp:54
bool listen_only
只听(静默)模式。Listen-only (silent) mode.
Definition can.hpp:52
FDCAN 配置参数,扩展 CAN::Configuration。 FDCAN configuration, extending CAN::Configuration.
Definition can.hpp:323
FDMode fd_mode
FD 模式配置。FD mode configuration.
Definition can.hpp:327
DataBitTiming data_timing
数据相位位时序。Data-phase bit timing.
Definition can.hpp:326
uint32_t prop_seg
传播段。Propagation segment.
Definition can.hpp:300
CAN FD 帧数据结构。CAN FD frame structure.
Definition can.hpp:265
Type type
帧类型。Frame type.
Definition can.hpp:267
uint8_t len
数据长度(0~64)。Data length (0–64 bytes).
Definition can.hpp:268