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