libxr
Embedded C++ framework for bare-metal, RTOS and Linux
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 DEV_ASSERT(false);
153 return;
154 }
155
156 DEV_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_.Put(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 ASSERT(hcan_ != nullptr && hcan_->Instance != nullptr);
282
283 FDCAN_GlobalTypeDef* can = hcan_->Instance;
284
285 // 先关通知:只关本驱动用到的这些
286 uint32_t it_mask = 0u;
287
288#ifdef FDCAN_IT_RX_FIFO0_NEW_MESSAGE
289 it_mask |= FDCAN_IT_RX_FIFO0_NEW_MESSAGE;
290#endif
291#ifdef FDCAN_IT_RX_FIFO1_NEW_MESSAGE
292 it_mask |= FDCAN_IT_RX_FIFO1_NEW_MESSAGE;
293#endif
294#ifdef FDCAN_IT_TX_FIFO_EMPTY
295 it_mask |= FDCAN_IT_TX_FIFO_EMPTY;
296#endif
297
298 if (it_mask != 0u)
299 {
300 HAL_FDCAN_DeactivateNotification(hcan_, it_mask);
301 }
302
303 // 停止 FDCAN,进入 INIT / CCE 配置状态
304 if (HAL_FDCAN_Stop(hcan_) != HAL_OK)
305 {
306 return ErrorCode::FAILED;
307 }
308
309#ifdef FDCAN_CCCR_INIT
310 SET_BIT(can->CCCR, FDCAN_CCCR_INIT);
311#endif
312#ifdef FDCAN_CCCR_CCE
313 SET_BIT(can->CCCR, FDCAN_CCCR_CCE);
314#endif
315
316 // 模式配置:one-shot / loopback / listen-only。
317 // Configure mode flags: one-shot / loopback / listen-only.
318#ifdef FDCAN_CCCR_DAR
319 if (cfg.mode.one_shot)
320 {
321 // 禁用自动重发
322 SET_BIT(can->CCCR, FDCAN_CCCR_DAR);
323 }
324 else
325 {
326 CLEAR_BIT(can->CCCR, FDCAN_CCCR_DAR);
327 }
328#endif
329
330 // triple_sampling 对 FDCAN 没意义,这里直接忽略
331 (void)cfg.mode.triple_sampling;
332
333#ifdef FDCAN_CCCR_TEST
334#ifdef FDCAN_TEST_LBCK
335 if (cfg.mode.loopback)
336 {
337 // 内部回环
338 SET_BIT(can->CCCR, FDCAN_CCCR_TEST);
339 SET_BIT(can->TEST, FDCAN_TEST_LBCK);
340 }
341 else
342 {
343 CLEAR_BIT(can->TEST, FDCAN_TEST_LBCK);
344 CLEAR_BIT(can->CCCR, FDCAN_CCCR_TEST);
345 }
346#endif
347#endif
348
349#ifdef FDCAN_CCCR_MON
350 if (cfg.mode.loopback || cfg.mode.listen_only)
351 {
352 // 内部回环和只听模式都需要总线监控。
353 // Internal loopback and listen-only mode both require bus monitoring.
354 SET_BIT(can->CCCR, FDCAN_CCCR_MON);
355 }
356 else
357 {
358 CLEAR_BIT(can->CCCR, FDCAN_CCCR_MON);
359 }
360#endif
361
362 // 仲裁相位时序范围校验并写入 NBTP。
363 // Validate nominal timing range and update NBTP.
364 const auto& bt = cfg.bit_timing;
365
366 // 用掩码算出字段最大值,避免硬编码
367#ifdef FDCAN_NBTP_NBRP_Msk
368 constexpr uint32_t NBRP_FIELD_MAX = (FDCAN_NBTP_NBRP_Msk >> FDCAN_NBTP_NBRP_Pos);
369 constexpr uint32_t NTSEG1_FIELD_MAX = (FDCAN_NBTP_NTSEG1_Msk >> FDCAN_NBTP_NTSEG1_Pos);
370 constexpr uint32_t NTSEG2_FIELD_MAX = (FDCAN_NBTP_NTSEG2_Msk >> FDCAN_NBTP_NTSEG2_Pos);
371 constexpr uint32_t NSJW_FIELD_MAX = (FDCAN_NBTP_NSJW_Msk >> FDCAN_NBTP_NSJW_Pos);
372
373 constexpr uint32_t NBRP_MAX = NBRP_FIELD_MAX + 1u;
374 constexpr uint32_t NTSEG1_MAX = NTSEG1_FIELD_MAX + 1u;
375 constexpr uint32_t NTSEG2_MAX = NTSEG2_FIELD_MAX + 1u;
376 constexpr uint32_t NSJW_MAX = NSJW_FIELD_MAX + 1u;
377
378 // 0 = 保持原值,非 0 做范围检查
379 if (bt.brp != 0u)
380 {
381 if (bt.brp < 1u || bt.brp > NBRP_MAX)
382 {
383 return ErrorCode::ARG_ERR;
384 }
385 }
386
387 uint32_t tseg1 = bt.prop_seg + bt.phase_seg1;
388 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
389 {
390 if (tseg1 < 1u || tseg1 > NTSEG1_MAX)
391 {
392 return ErrorCode::ARG_ERR;
393 }
394 }
395
396 if (bt.phase_seg2 != 0u)
397 {
398 if (bt.phase_seg2 < 1u || bt.phase_seg2 > NTSEG2_MAX)
399 {
400 return ErrorCode::ARG_ERR;
401 }
402 }
403
404 if (bt.sjw != 0u)
405 {
406 if (bt.sjw < 1u || bt.sjw > NSJW_MAX)
407 {
408 return ErrorCode::ARG_ERR;
409 }
410 if (bt.phase_seg2 != 0u && bt.sjw > bt.phase_seg2)
411 {
412 return ErrorCode::ARG_ERR;
413 }
414 }
415
416 uint32_t nbtp_old = can->NBTP;
417 uint32_t nbtp_new = nbtp_old;
418 uint32_t nbtp_mask = 0u;
419
420 // NBRP
421 if (bt.brp != 0u)
422 {
423 uint32_t nbrp = (bt.brp - 1u) & NBRP_FIELD_MAX;
424 uint32_t mask = FDCAN_NBTP_NBRP_Msk;
425 nbtp_mask |= mask;
426 nbtp_new &= ~mask;
427 nbtp_new |= (nbrp << FDCAN_NBTP_NBRP_Pos);
428 }
429
430 // NTSEG1 = PROP_SEG + PHASE_SEG1
431 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
432 {
433 uint32_t ntseg1 = (tseg1 - 1u) & NTSEG1_FIELD_MAX;
434 uint32_t mask = FDCAN_NBTP_NTSEG1_Msk;
435 nbtp_mask |= mask;
436 nbtp_new &= ~mask;
437 nbtp_new |= (ntseg1 << FDCAN_NBTP_NTSEG1_Pos);
438 }
439
440 // NTSEG2 = PHASE_SEG2
441 if (bt.phase_seg2 != 0u)
442 {
443 uint32_t ntseg2 = (bt.phase_seg2 - 1u) & NTSEG2_FIELD_MAX;
444 uint32_t mask = FDCAN_NBTP_NTSEG2_Msk;
445 nbtp_mask |= mask;
446 nbtp_new &= ~mask;
447 nbtp_new |= (ntseg2 << FDCAN_NBTP_NTSEG2_Pos);
448 }
449
450 // NSJW
451 if (bt.sjw != 0u)
452 {
453 uint32_t nsjw = (bt.sjw - 1u) & NSJW_FIELD_MAX;
454 uint32_t mask = FDCAN_NBTP_NSJW_Msk;
455 nbtp_mask |= mask;
456 nbtp_new &= ~mask;
457 nbtp_new |= (nsjw << FDCAN_NBTP_NSJW_Pos);
458 }
459
460 if (nbtp_mask != 0u)
461 {
462 nbtp_old &= ~nbtp_mask;
463 nbtp_old |= (nbtp_new & nbtp_mask);
464 can->NBTP = nbtp_old;
465 }
466#endif // FDCAN_NBTP_NBRP_Msk
467
468 // 数据相位时序范围校验并写入 DBTP(仅 CAN FD)。
469 // Validate data-phase timing and update DBTP (CAN FD only).
470 const auto& dbt = cfg.data_timing;
471
472#ifdef FDCAN_DBTP_DBRP_Msk
473 constexpr uint32_t DBRP_FIELD_MAX = (FDCAN_DBTP_DBRP_Msk >> FDCAN_DBTP_DBRP_Pos);
474 constexpr uint32_t DTSEG1_FIELD_MAX = (FDCAN_DBTP_DTSEG1_Msk >> FDCAN_DBTP_DTSEG1_Pos);
475 constexpr uint32_t DTSEG2_FIELD_MAX = (FDCAN_DBTP_DTSEG2_Msk >> FDCAN_DBTP_DTSEG2_Pos);
476 constexpr uint32_t DSJW_FIELD_MAX = (FDCAN_DBTP_DSJW_Msk >> FDCAN_DBTP_DSJW_Pos);
477
478 constexpr uint32_t DBRP_MAX = DBRP_FIELD_MAX + 1u;
479 constexpr uint32_t DTSEG1_MAX = DTSEG1_FIELD_MAX + 1u;
480 constexpr uint32_t DTSEG2_MAX = DTSEG2_FIELD_MAX + 1u;
481 constexpr uint32_t DSJW_MAX = DSJW_FIELD_MAX + 1u;
482
483 if (dbt.brp != 0u)
484 {
485 if (dbt.brp < 1u || dbt.brp > DBRP_MAX)
486 {
487 return ErrorCode::ARG_ERR;
488 }
489 }
490
491 uint32_t dtseg1 = dbt.prop_seg + dbt.phase_seg1;
492 if (dbt.prop_seg != 0u || dbt.phase_seg1 != 0u)
493 {
494 if (dtseg1 < 1u || dtseg1 > DTSEG1_MAX)
495 {
496 return ErrorCode::ARG_ERR;
497 }
498 }
499
500 if (dbt.phase_seg2 != 0u)
501 {
502 if (dbt.phase_seg2 < 1u || dbt.phase_seg2 > DTSEG2_MAX)
503 {
504 return ErrorCode::ARG_ERR;
505 }
506 }
507
508 if (dbt.sjw != 0u)
509 {
510 if (dbt.sjw < 1u || dbt.sjw > DSJW_MAX)
511 {
512 return ErrorCode::ARG_ERR;
513 }
514 if (dbt.phase_seg2 != 0u && dbt.sjw > dbt.phase_seg2)
515 {
516 return ErrorCode::ARG_ERR;
517 }
518 }
519
520 uint32_t dbtp_old = can->DBTP;
521 uint32_t dbtp_new = dbtp_old;
522 uint32_t dbtp_mask = 0u;
523
524 if (dbt.brp != 0u)
525 {
526 uint32_t dbrp = (dbt.brp - 1u) & DBRP_FIELD_MAX;
527 uint32_t mask = FDCAN_DBTP_DBRP_Msk;
528 dbtp_mask |= mask;
529 dbtp_new &= ~mask;
530 dbtp_new |= (dbrp << FDCAN_DBTP_DBRP_Pos);
531 }
532
533 if (dbt.prop_seg != 0u || dbt.phase_seg1 != 0u)
534 {
535 uint32_t dt1 = (dtseg1 - 1u) & DTSEG1_FIELD_MAX;
536 uint32_t mask = FDCAN_DBTP_DTSEG1_Msk;
537 dbtp_mask |= mask;
538 dbtp_new &= ~mask;
539 dbtp_new |= (dt1 << FDCAN_DBTP_DTSEG1_Pos);
540 }
541
542 if (dbt.phase_seg2 != 0u)
543 {
544 uint32_t dt2 = (dbt.phase_seg2 - 1u) & DTSEG2_FIELD_MAX;
545 uint32_t mask = FDCAN_DBTP_DTSEG2_Msk;
546 dbtp_mask |= mask;
547 dbtp_new &= ~mask;
548 dbtp_new |= (dt2 << FDCAN_DBTP_DTSEG2_Pos);
549 }
550
551 if (dbt.sjw != 0u)
552 {
553 uint32_t dsjw = (dbt.sjw - 1u) & DSJW_FIELD_MAX;
554 uint32_t mask = FDCAN_DBTP_DSJW_Msk;
555 dbtp_mask |= mask;
556 dbtp_new &= ~mask;
557 dbtp_new |= (dsjw << FDCAN_DBTP_DSJW_Pos);
558 }
559
560 if (dbtp_mask != 0u)
561 {
562 dbtp_old &= ~dbtp_mask;
563 dbtp_old |= (dbtp_new & dbtp_mask);
564 can->DBTP = dbtp_old;
565 }
566#else
567 (void)dbt;
568#endif // FDCAN_DBTP_DBRP_Msk
569
570 // 数据相位 FDMode:这里不动寄存器,只保留在上层语义中使用
571 (void)cfg.fd_mode;
572
573 // 重新启动 FDCAN
574 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
575 {
576 return ErrorCode::FAILED;
577 }
578
579 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_PASSIVE, 0);
580 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_WARNING, 0);
581 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_BUS_OFF, 0);
582 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
583 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
584 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
585 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_COMPLETE, 0xFFFFFFFF);
586
587 return ErrorCode::OK;
588}
589
591{
592 // 所有带 FDCAN 的 STM32 都通过 RCCEx 提供核时钟查询
593#if defined(RCC_PERIPHCLK_FDCAN)
594 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN);
595#elif defined(RCC_PERIPHCLK_FDCAN1)
596 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1);
597#else
598 // 理论上不会走到这里,有就说明 HAL/RCC 宏不一致
599 static_assert(false, "RCC_PERIPHCLK_FDCAN is not defined by the HAL");
600 return 0u;
601#endif
602}
603
605{
606 if (pack.type == Type::ERROR)
607 {
608 return ErrorCode::ARG_ERR;
609 }
610
611 ASSERT(pack.len <= 64u);
612 if (pack.type != Type::STANDARD && pack.type != Type::EXTENDED)
613 {
614 return ErrorCode::FAILED;
615 }
616
617 if (tx_fd_queue_.Put(pack) != ErrorCode::OK)
618 {
619 return ErrorCode::FULL;
620 }
621
622 TxService();
623 return ErrorCode::OK;
624}
625
627{
628 if (HAL_FDCAN_GetRxMessage(hcan_, fifo, &rx_buff_.header, rx_buff_.pack_fd.data) ==
629 HAL_OK)
630 {
631 if (rx_buff_.header.FDFormat == FDCAN_FD_CAN)
632 {
633 rx_buff_.pack_fd.id = rx_buff_.header.Identifier;
634 rx_buff_.pack_fd.type =
635 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
636
637 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
638 {
639 if (rx_buff_.pack_fd.type == Type::STANDARD)
640 {
641 rx_buff_.pack_fd.type = Type::REMOTE_STANDARD;
642 }
643 else
644 {
645 rx_buff_.pack_fd.type = Type::REMOTE_EXTENDED;
646 }
647 }
648
649 rx_buff_.pack_fd.len = DlcToBytes(rx_buff_.header.DataLength);
650
651 OnMessage(rx_buff_.pack_fd, true);
652 }
653 else
654 {
655 rx_buff_.pack.id = rx_buff_.header.Identifier;
656 rx_buff_.pack.type =
657 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
658
659 uint32_t bytes = DlcToBytes(rx_buff_.header.DataLength);
660 if (bytes > 8u)
661 {
662 bytes = 8u;
663 }
664
665 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
666 {
667 if (rx_buff_.pack.type == Type::STANDARD)
668 {
669 rx_buff_.pack.type = Type::REMOTE_STANDARD;
670 }
671 else
672 {
673 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
674 }
675 rx_buff_.pack.dlc = static_cast<uint8_t>(bytes);
676 }
677 else
678 {
679 rx_buff_.pack.dlc = static_cast<uint8_t>(bytes);
680 if (bytes > 0u)
681 {
682 Memory::FastCopy(rx_buff_.pack.data, rx_buff_.pack_fd.data, bytes);
683 }
684 }
685
686 OnMessage(rx_buff_.pack, true);
687 }
688 }
689}
690
691void STM32CANFD::TxService()
692{
693 if (hcan_ == nullptr || hcan_->Instance == nullptr)
694 {
695 return;
696 }
697
698 tx_pend_.store(1u, std::memory_order_release);
699
700 uint32_t expected = 0u;
701 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
702 std::memory_order_relaxed))
703 {
704 return;
705 }
706
707 for (;;)
708 {
709 tx_pend_.store(0u, std::memory_order_release);
710
711 while (HardwareTxQueueEmptySize() != 0u)
712 {
713 // 保留原有 FD 优先发送策略。
714 // Preserve the existing FD-priority TX policy.
715 FDPack pfd{};
716 bool has_fd = tx_fd_retry_valid_;
717 if (has_fd)
718 {
719 pfd = tx_fd_retry_pack_;
720 }
721 else
722 {
723 has_fd = (tx_fd_queue_.Get(pfd) == ErrorCode::OK);
724 }
725
726 if (has_fd)
727 {
728 FDCAN_TxHeaderTypeDef hdr{};
729 BuildTxHeader(pfd, hdr);
730
731 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &hdr, pfd.data) != HAL_OK)
732 {
733 tx_fd_retry_pack_ = pfd;
734 tx_fd_retry_valid_ = true;
735 break; // 不做立即 retry
736 }
737 tx_fd_retry_valid_ = false;
738 continue;
739 }
740
741 ClassicPack pc{};
742 bool has_classic = tx_classic_retry_valid_;
743 if (has_classic)
744 {
746 }
747 else
748 {
749 has_classic = (tx_queue_.Get(pc) == ErrorCode::OK);
750 }
751
752 if (has_classic)
753 {
754 FDCAN_TxHeaderTypeDef hdr{};
755 BuildTxHeader(pc, hdr);
756
757 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &hdr, pc.data) != HAL_OK)
758 {
761 break;
762 }
764 continue;
765 }
766
767 break; // 两个软件队列都空
768 }
769
770 tx_lock_.store(0u, std::memory_order_release);
771
772 if (tx_pend_.load(std::memory_order_acquire) == 0u)
773 {
774 return;
775 }
776
777 expected = 0u;
778 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
779 std::memory_order_relaxed))
780 {
781 return;
782 }
783 }
784}
785
786void STM32CANFD::ProcessErrorStatusInterrupt(uint32_t error_status_its)
787{
788 FDCAN_ProtocolStatusTypeDef protocol_status = {};
789 HAL_FDCAN_GetProtocolStatus(hcan_, &protocol_status);
790
791#ifdef FDCAN_IT_BUS_OFF
792#ifdef FDCAN_CCCR_INIT
793 if ((error_status_its & FDCAN_IT_BUS_OFF) != 0u && protocol_status.BusOff != 0u)
794 {
795 CLEAR_BIT(hcan_->Instance->CCCR, FDCAN_CCCR_INIT);
796 }
797#endif
798#endif
799
800 CAN::ClassicPack pack{};
801 pack.type = CAN::Type::ERROR;
802 pack.dlc = 0;
803
804 CAN::ErrorID eid = CAN::ErrorID::CAN_ERROR_ID_GENERIC;
805
806 if (protocol_status.BusOff != 0u)
807 {
808 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
809 }
810 else if (protocol_status.ErrorPassive != 0u)
811 {
812 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
813 }
814 else if (protocol_status.Warning != 0u)
815 {
816 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
817 }
818 else
819 {
820 uint32_t lec = protocol_status.LastErrorCode & 0x7u;
821 if (lec == 0u)
822 {
823 lec = protocol_status.DataLastErrorCode & 0x7u;
824 }
825
826 switch (lec)
827 {
828 case 0x01u:
829 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
830 break;
831 case 0x02u:
832 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
833 break;
834 case 0x03u:
835 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
836 break;
837 case 0x04u:
838 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
839 break;
840 case 0x05u:
841 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
842 break;
843 case 0x06u:
844 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
845 break;
846 default:
847 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
848 break;
849 }
850 }
851
852 pack.id = static_cast<uint32_t>(eid);
853
854 OnMessage(pack, true);
855}
856
858{
859 if (hcan_ == nullptr || hcan_->Instance == nullptr)
860 {
861 return ErrorCode::ARG_ERR;
862 }
863
864 FDCAN_ErrorCountersTypeDef counters{};
865 if (HAL_FDCAN_GetErrorCounters(hcan_, &counters) != HAL_OK)
866 {
867 return ErrorCode::FAILED;
868 }
869
870 FDCAN_ProtocolStatusTypeDef proto{};
871 if (HAL_FDCAN_GetProtocolStatus(hcan_, &proto) != HAL_OK)
872 {
873 return ErrorCode::FAILED;
874 }
875
876 state.tx_error_counter = counters.TxErrorCnt;
877 state.rx_error_counter = counters.RxErrorCnt;
878
879 state.bus_off = (proto.BusOff != 0u);
880 state.error_passive = (proto.ErrorPassive != 0u);
881 state.error_warning = (proto.Warning != 0u);
882
883 return ErrorCode::OK;
884}
885
886extern "C" void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef* hcan)
887{
888 hcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
889 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
890 if (can)
891 {
892 can->TxService();
893 }
894}
895
896extern "C" void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef* hfdcan,
897 uint32_t ErrorStatusITs)
898{
899 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hfdcan->Instance)];
900 if (can)
901 {
902 can->ProcessErrorStatusInterrupt(ErrorStatusITs);
903 can->TxService();
904 }
905}
906
907extern "C" void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef* hcan,
908 uint32_t BufferIndexes)
909{
910 UNUSED(BufferIndexes);
911 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
912 if (can)
913 {
914 can->TxService();
915 }
916}
917
918extern "C" void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef* hcan)
919{
920 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
921 if (can)
922 {
923 can->TxService();
924 }
925}
926
927extern "C" void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo0ITs)
928{
929 UNUSED(RxFifo0ITs);
930 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
931 if (can)
932 {
933 while (HAL_FDCAN_GetRxFifoFillLevel(hcan, FDCAN_RX_FIFO0) > 0U)
934 {
935 can->ProcessRxInterrupt(FDCAN_RX_FIFO0);
936 }
937 }
938}
939
940extern "C" void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo1ITs)
941{
942 UNUSED(RxFifo1ITs);
943 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
944 if (can)
945 {
946 while (HAL_FDCAN_GetRxFifoFillLevel(hcan, FDCAN_RX_FIFO1) > 0U)
947 {
948 can->ProcessRxInterrupt(FDCAN_RX_FIFO1);
949 }
950 }
951}
952
953#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:147
FDCAN 通信抽象类,扩展支持 CAN FD 帧。 Abstract class for FDCAN communication with CAN FD frame support.
Definition can.hpp:248
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
STM32 FDCAN 驱动实现 / STM32 FDCAN driver implementation.
void ProcessErrorStatusInterrupt(uint32_t error_status_its)
处理错误状态中断 / Handle error-status interrupt
SlotPool< FDPack > tx_fd_queue_
FD 发送槽池 / FD TX slot pool.
uint32_t GetClockFreq() const override
获取 FDCAN 外设时钟 / Get FDCAN kernel clock
ErrorCode Init(void)
初始化驱动 / Initialize driver
void ProcessRxInterrupt(uint32_t fifo)
处理接收中断 / Handle RX interrupt
SlotPool< ClassicPack > tx_queue_
Classic 发送槽池 / Classic TX slot pool.
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.
ErrorCode Get(T &value)
便捷出队:Take + 拷贝 + Release / Convenient dequeue: Take + copy + Release.
ErrorCode Put(const T &value)
便捷入队:Acquire + 拷贝 + Publish / Convenient enqueue: Acquire + copy + Publish.
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ 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:132
uint8_t dlc
有效数据长度(0~8) / Data length code (0–8).
Definition can.hpp:133
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:324
FDMode fd_mode
FD 模式配置 / FD mode configuration.
Definition can.hpp:328
DataBitTiming data_timing
数据相位位时序 / Data-phase bit timing.
Definition can.hpp:327
uint32_t prop_seg
传播段 / Propagation segment.
Definition can.hpp:301
CAN FD 帧数据结构 / CAN FD frame structure.
Definition can.hpp:266
Type type
帧类型 / Frame type.
Definition can.hpp:268
uint8_t len
数据长度(0~64) / Data length (0–64 bytes).
Definition can.hpp:269