libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_can.cpp
1#include "stm32_can.hpp"
2
3#ifdef HAL_CAN_MODULE_ENABLED
4
5using namespace LibXR;
6
7STM32CAN* STM32CAN::map[STM32_CAN_NUMBER] = {nullptr};
8
15stm32_can_id_t STM32_CAN_GetID(CAN_TypeDef* addr)
16{
17 // NOLINTBEGIN
18 if (addr == nullptr)
19 { // NOLINT
20 return stm32_can_id_t::STM32_CAN_ID_ERROR;
21 }
22#ifdef CAN1
23 else if (addr == CAN1)
24 { // NOLINT
25 return stm32_can_id_t::STM32_CAN1;
26 }
27#endif
28#ifdef CAN2
29 else if (addr == CAN2)
30 { // NOLINT
31 return stm32_can_id_t::STM32_CAN2;
32 }
33#endif
34#ifdef CAN3
35 else if (addr == CAN3)
36 { // NOLINT
37 return stm32_can_id_t::STM32_CAN3;
38 }
39#endif
40 else
41 {
42 return stm32_can_id_t::STM32_CAN_ID_ERROR;
43 }
44 // NOLINTEND
45}
46
47STM32CAN::STM32CAN(CAN_HandleTypeDef* hcan, uint32_t pool_size)
48 : CAN(), hcan_(hcan), id_(STM32_CAN_GetID(hcan->Instance)), tx_pool_(pool_size)
49{
50 map[id_] = this;
51 Init();
52}
53
54ErrorCode STM32CAN::Init(void)
55{
56 CAN_FilterTypeDef can_filter = {};
57
58 can_filter.FilterIdHigh = 0;
59 can_filter.FilterIdLow = 0;
60 can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
61 can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
62 can_filter.FilterMaskIdHigh = 0;
63 can_filter.FilterMaskIdLow = 0;
64 can_filter.FilterFIFOAssignment = fifo_;
65 can_filter.FilterActivation = ENABLE;
66
67#ifdef CAN3
68 if (id_ == STM32_CAN1)
69 {
70 can_filter.FilterBank = 0;
71 can_filter.SlaveStartFilterBank = 14;
72 fifo_ = CAN_RX_FIFO0;
73 }
74 else if (id_ == STM32_CAN2)
75 {
76 can_filter.FilterBank = 14;
77 can_filter.SlaveStartFilterBank = 14;
78 fifo_ = CAN_RX_FIFO0;
79 }
80 else if (id_ == STM32_CAN3)
81 {
82 can_filter.FilterBank = 3;
83 fifo_ = CAN_RX_FIFO1;
84 }
85#else
86#ifdef CAN2
87 if (id_ == STM32_CAN1)
88 {
89 can_filter.FilterBank = 0;
90 can_filter.SlaveStartFilterBank = 14;
91 fifo_ = CAN_RX_FIFO0;
92 }
93 else if (id_ == STM32_CAN2)
94 {
95 can_filter.FilterBank = 14;
96 can_filter.SlaveStartFilterBank = 14;
97 fifo_ = CAN_RX_FIFO1;
98 }
99#else
100 if (id_ == STM32_CAN1)
101 {
102 can_filter.FilterBank = 0;
103 can_filter.SlaveStartFilterBank = 14;
104 fifo_ = CAN_RX_FIFO0;
105 }
106#endif
107#endif
108 else
109 {
110 ASSERT(false);
111 return ErrorCode::FAILED;
112 }
113
114 can_filter.FilterFIFOAssignment = fifo_;
115
116 if (HAL_CAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
117 {
118 return ErrorCode::FAILED;
119 }
120
121 if (HAL_CAN_Start(hcan_) != HAL_OK)
122 {
123 return ErrorCode::FAILED;
124 }
125
126 if (fifo_ == CAN_RX_FIFO0)
127 {
128 HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO0_MSG_PENDING);
129 }
130 else
131 {
132 HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO1_MSG_PENDING);
133 }
134
135 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR);
136 HAL_CAN_ActivateNotification(hcan_, CAN_IT_BUSOFF);
137 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR_PASSIVE);
138 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR_WARNING);
139 HAL_CAN_ActivateNotification(hcan_, CAN_IT_TX_MAILBOX_EMPTY);
140
141 return ErrorCode::OK;
142}
143
145{
146 if (hcan_ == nullptr || hcan_->Instance == nullptr)
147 {
148 ASSERT(false);
149 return ErrorCode::ARG_ERR;
150 }
151
152 CAN_TypeDef* can = hcan_->Instance;
153
154 // 先关掉与 Init 对应的中断
155 uint32_t it_mask = 0u;
156
157#ifdef CAN_IT_RX_FIFO0_MSG_PENDING
158 if (fifo_ == CAN_RX_FIFO0)
159 {
160 it_mask |= CAN_IT_RX_FIFO0_MSG_PENDING;
161 }
162#endif
163
164#ifdef CAN_IT_RX_FIFO1_MSG_PENDING
165 if (fifo_ == CAN_RX_FIFO1)
166 {
167 it_mask |= CAN_IT_RX_FIFO1_MSG_PENDING;
168 }
169#endif
170
171#ifdef CAN_IT_ERROR
172 it_mask |= CAN_IT_ERROR;
173#endif
174
175#ifdef CAN_IT_TX_MAILBOX_EMPTY
176 it_mask |= CAN_IT_TX_MAILBOX_EMPTY;
177#endif
178
179 if (it_mask != 0u)
180 {
181 HAL_CAN_DeactivateNotification(hcan_, it_mask);
182 }
183
184 // 停止 CAN,进入配置状态
185 if (HAL_CAN_Stop(hcan_) != HAL_OK)
186 {
187 return ErrorCode::FAILED;
188 }
189
190 // 一次发送模式(不自动重发)→ NART
191#ifdef CAN_MCR_NART
192 if (cfg.mode.one_shot)
193 {
194 SET_BIT(can->MCR, CAN_MCR_NART);
195 }
196 else
197 {
198 CLEAR_BIT(can->MCR, CAN_MCR_NART);
199 }
200#endif
201
202 const auto& bt = cfg.bit_timing;
203
204 // ====== 范围校验(0 表示“保持原值”,跳过检查) ======
205 // 最大值从掩码推出来,避免硬编码
206 constexpr uint32_t BRP_FIELD_MAX =
207 (CAN_BTR_BRP_Msk >> CAN_BTR_BRP_Pos); // 存的是 brp-1
208 constexpr uint32_t TS1_FIELD_MAX =
209 (CAN_BTR_TS1_Msk >> CAN_BTR_TS1_Pos); // 存的是 ts1-1
210 constexpr uint32_t TS2_FIELD_MAX =
211 (CAN_BTR_TS2_Msk >> CAN_BTR_TS2_Pos); // 存的是 ts2-1
212 constexpr uint32_t SJW_FIELD_MAX =
213 (CAN_BTR_SJW_Msk >> CAN_BTR_SJW_Pos); // 存的是 sjw-1
214
215 // 实际可配置的量(寄存器值 + 1)
216 constexpr uint32_t BRP_MAX = BRP_FIELD_MAX + 1u; // 1..1024
217 constexpr uint32_t TS1_MAX = TS1_FIELD_MAX + 1u; // 1..16
218 constexpr uint32_t TS2_MAX = TS2_FIELD_MAX + 1u; // 1..8
219 constexpr uint32_t SJW_MAX = SJW_FIELD_MAX + 1u; // 1..4
220
221 // brp 范围检查
222 if (bt.brp != 0u)
223 {
224 if (bt.brp < 1u || bt.brp > BRP_MAX)
225 {
226 ASSERT(false);
227 return ErrorCode::ARG_ERR;
228 }
229 }
230
231 // tseg1 = prop_seg + phase_seg1
232 uint32_t tseg1 = bt.prop_seg + bt.phase_seg1;
233 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
234 {
235 if (tseg1 < 1u || tseg1 > TS1_MAX)
236 {
237 ASSERT(false);
238 return ErrorCode::ARG_ERR;
239 }
240 }
241
242 if (bt.phase_seg2 != 0u)
243 {
244 if (bt.phase_seg2 < 1u || bt.phase_seg2 > TS2_MAX)
245 {
246 ASSERT(false);
247 return ErrorCode::ARG_ERR;
248 }
249 }
250
251 if (bt.sjw != 0u)
252 {
253 if (bt.sjw < 1u || bt.sjw > SJW_MAX)
254 {
255 ASSERT(false);
256 return ErrorCode::ARG_ERR;
257 }
258
259 // 规范上 SJW ≤ TSEG2(只在二者都要更新时检查)
260 if (bt.phase_seg2 != 0u && bt.sjw > bt.phase_seg2)
261 {
262 ASSERT(false);
263 return ErrorCode::ARG_ERR;
264 }
265 }
266
267 uint32_t btr_old = can->BTR;
268 uint32_t btr_new = btr_old;
269 uint32_t btr_mask = 0u;
270
271 // BRP:bt.brp == 0 → 保持原值
272 if (bt.brp != 0u)
273 {
274 uint32_t brp = (bt.brp - 1u) & BRP_FIELD_MAX;
275 uint32_t mask = CAN_BTR_BRP_Msk;
276 btr_mask |= mask;
277 btr_new &= ~mask;
278 btr_new |= (brp << CAN_BTR_BRP_Pos);
279 }
280
281 // TSEG1 = PROP_SEG + PHASE_SEG1,两者都为 0 → 保持原值
282 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
283 {
284 uint32_t ts1 = (tseg1 - 1u) & TS1_FIELD_MAX;
285 uint32_t mask = CAN_BTR_TS1_Msk;
286 btr_mask |= mask;
287 btr_new &= ~mask;
288 btr_new |= (ts1 << CAN_BTR_TS1_Pos);
289 }
290
291 // TSEG2 = PHASE_SEG2,phase_seg2 == 0 → 保持原值
292 if (bt.phase_seg2 != 0u)
293 {
294 uint32_t ts2 = (bt.phase_seg2 - 1u) & TS2_FIELD_MAX;
295 uint32_t mask = CAN_BTR_TS2_Msk;
296 btr_mask |= mask;
297 btr_new &= ~mask;
298 btr_new |= (ts2 << CAN_BTR_TS2_Pos);
299 }
300
301 // SJW,sjw == 0 → 保持原值
302 if (bt.sjw != 0u)
303 {
304 uint32_t sjw = (bt.sjw - 1u) & SJW_FIELD_MAX;
305 uint32_t mask = CAN_BTR_SJW_Msk;
306 btr_mask |= mask;
307 btr_new &= ~mask;
308 btr_new |= (sjw << CAN_BTR_SJW_Pos);
309 }
310
311 // 三采样:只有 HAL 定义了 CAN_BTR_SAM 才动;否则忽略 triple_sampling
312#ifdef CAN_BTR_SAM
313 {
314 uint32_t mask = CAN_BTR_SAM;
315 btr_mask |= mask;
316 btr_new &= ~mask;
317 if (cfg.mode.triple_sampling)
318 {
319 btr_new |= mask;
320 }
321 }
322#else
323 (void)cfg.mode.triple_sampling;
324#endif
325
326 // Loopback:bool 两态,强制覆盖
327#ifdef CAN_BTR_LBKM
328 {
329 uint32_t mask = CAN_BTR_LBKM;
330 btr_mask |= mask;
331 btr_new &= ~mask;
332 if (cfg.mode.loopback)
333 {
334 btr_new |= mask;
335 }
336 }
337#endif
338
339 // Listen-only:bool 两态,强制覆盖
340#ifdef CAN_BTR_SILM
341 {
342 uint32_t mask = CAN_BTR_SILM;
343 btr_mask |= mask;
344 btr_new &= ~mask;
345 if (cfg.mode.listen_only)
346 {
347 btr_new |= mask;
348 }
349 }
350#endif
351
352 // 只改被 btr_mask 覆盖到的位,其余保持原值
353 if (btr_mask != 0u)
354 {
355 btr_old &= ~btr_mask;
356 btr_old |= (btr_new & btr_mask);
357 can->BTR = btr_old;
358 }
359
360 // 重新启动 CAN
361 if (HAL_CAN_Start(hcan_) != HAL_OK)
362 {
363 return ErrorCode::FAILED;
364 }
365
366 // 按 Init 的方式恢复中断
367 uint32_t it_rx = 0u;
368
369#ifdef CAN_IT_RX_FIFO0_MSG_PENDING
370 if (fifo_ == CAN_RX_FIFO0)
371 {
372 it_rx = CAN_IT_RX_FIFO0_MSG_PENDING;
373 }
374#endif
375
376#ifdef CAN_IT_RX_FIFO1_MSG_PENDING
377 if (fifo_ == CAN_RX_FIFO1)
378 {
379 it_rx = CAN_IT_RX_FIFO1_MSG_PENDING;
380 }
381#endif
382
383 if (it_rx != 0u)
384 {
385 HAL_CAN_ActivateNotification(hcan_, it_rx);
386 }
387
388 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR);
389 HAL_CAN_ActivateNotification(hcan_, CAN_IT_BUSOFF);
390 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR_PASSIVE);
391 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR_WARNING);
392 HAL_CAN_ActivateNotification(hcan_, CAN_IT_TX_MAILBOX_EMPTY);
393
394 return ErrorCode::OK;
395}
396
398{
399 // 经典 bxCAN 始终挂在 APB1 上
400 return HAL_RCC_GetPCLK1Freq();
401}
402
403inline void STM32CAN::BuildTxHeader(const ClassicPack& p, CAN_TxHeaderTypeDef& h)
404{
405 const bool IS_EXT = (p.type == Type::EXTENDED) || (p.type == Type::REMOTE_EXTENDED);
406 const bool IS_RTR =
407 (p.type == Type::REMOTE_STANDARD) || (p.type == Type::REMOTE_EXTENDED);
408
409 h.DLC = (p.dlc <= 8u) ? p.dlc : 8u;
410 h.IDE = IS_EXT ? CAN_ID_EXT : CAN_ID_STD;
411 h.RTR = IS_RTR ? CAN_RTR_REMOTE : CAN_RTR_DATA;
412
413 h.StdId = IS_EXT ? 0u : (p.id & 0x7FFu);
414 h.ExtId = IS_EXT ? (p.id & 0x1FFFFFFFu) : 0u;
415
416 h.TransmitGlobalTime = DISABLE;
417}
418
419void STM32CAN::TxService()
420{
421 if (hcan_ == nullptr || hcan_->Instance == nullptr)
422 {
423 return;
424 }
425
426 // 标记:需要一次 TX 服务(无论本次是否抢到锁)
427 tx_pend_.store(1u, std::memory_order_release);
428
429 // 尝试抢占服务锁:0 -> 1
430 uint32_t expected = 0u;
431 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
432 std::memory_order_relaxed))
433 {
434 // 有别的上下文在服务;PEND 已置位,它会在结束时看到并再服务
435 return;
436 }
437
438 constexpr uint32_t TME_MASK = (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2);
439
440 for (;;)
441 {
442 // 本轮服务开始:消费掉 pend(期间如有新 kick,会再次置 1)
443 tx_pend_.store(0u, std::memory_order_release);
444
445 // 尽可能把空 mailbox 填满:一直到队列空或者 AddTxMessage 失败(邮箱满/忙)
446 while ((hcan_->Instance->TSR & TME_MASK) != 0u)
447 {
448 ClassicPack p{};
449 if (tx_pool_.Get(p) != ErrorCode::OK)
450 {
451 break; // 队列空
452 }
453
454 CAN_TxHeaderTypeDef hdr{};
455 BuildTxHeader(p, hdr);
456
457 uint32_t mailbox = 0u;
458 if (HAL_CAN_AddTxMessage(hcan_, &hdr, p.data, &mailbox) != HAL_OK)
459 {
460 // 发送失败:回队列,不做任何兜底/处理
461 (void)tx_pool_.Put(p);
462 break;
463 }
464
465 txMailbox = mailbox;
466 }
467
468 // 按你的要求:先解锁
469 tx_lock_.store(0u, std::memory_order_release);
470
471 // 再看是否还有 pend:若没有,直接退出
472 if (tx_pend_.load(std::memory_order_acquire) == 0u)
473 {
474 return;
475 }
476
477 // 允许出现 PEND=1, LOCK=0 的“无人服务”状态:尝试重新加锁再服务
478 expected = 0u;
479 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
480 std::memory_order_relaxed))
481 {
482 return;
483 }
484 }
485}
486
487ErrorCode STM32CAN::AddMessage(const ClassicPack& pack)
488{
489 if (pack.type == Type::ERROR)
490 {
491 return ErrorCode::ARG_ERR;
492 }
493
494 // 池满直接返回 FULL,不做补救
495 if (tx_pool_.Put(pack) != ErrorCode::OK)
496 {
497 return ErrorCode::FULL;
498 }
499
500 // kick
501 TxService();
502 return ErrorCode::OK;
503}
504
506{
507 while (HAL_CAN_GetRxMessage(hcan_, fifo_, &rx_buff_.header, rx_buff_.pack.data) ==
508 HAL_OK)
509 {
510 if (rx_buff_.header.IDE == CAN_ID_STD)
511 {
512 rx_buff_.pack.id = rx_buff_.header.StdId;
513 rx_buff_.pack.type = Type::STANDARD;
514 }
515 else
516 {
517 rx_buff_.pack.id = rx_buff_.header.ExtId;
518 rx_buff_.pack.type = Type::EXTENDED;
519 }
520
521 if (rx_buff_.header.RTR == CAN_RTR_REMOTE)
522 {
523 if (rx_buff_.pack.type == Type::STANDARD)
524 {
525 rx_buff_.pack.type = Type::REMOTE_STANDARD;
526 }
527 else
528 {
529 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
530 }
531 }
532
533 uint8_t dlc = (rx_buff_.header.DLC <= 8u) ? rx_buff_.header.DLC : 8u;
534 rx_buff_.pack.dlc = dlc;
535
536 OnMessage(rx_buff_.pack, true);
537 }
538}
539
541{
542 if (hcan_ == nullptr || hcan_->Instance == nullptr)
543 {
544 return;
545 }
546
547 uint32_t esr = hcan_->Instance->ESR;
548
549 CAN::ClassicPack pack{};
550 pack.type = CAN::Type::ERROR;
551 pack.dlc = 0;
552
553 CAN::ErrorID eid = CAN::ErrorID::CAN_ERROR_ID_GENERIC;
554
555 if (esr & CAN_ESR_BOFF)
556 {
557 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
558 }
559 else if (esr & CAN_ESR_EPVF)
560 {
561 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
562 }
563 else if (esr & CAN_ESR_EWGF)
564 {
565 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
566 }
567 else
568 {
569 uint32_t lec = (esr >> 4) & 0x7u;
570
571 switch (lec)
572 {
573 case 0x01:
574 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
575 break;
576 case 0x02:
577 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
578 break;
579 case 0x03:
580 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
581 break;
582 case 0x04:
583 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
584 break;
585 case 0x05:
586 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
587 break;
588 case 0x06:
589 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
590 break;
591 default:
592 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
593 break;
594 }
595 }
596
597 pack.id = static_cast<uint32_t>(eid);
598
599 // 在中断上下文中分发错误帧
600 OnMessage(pack, true);
601}
602
604{
605 if (hcan_ == nullptr || hcan_->Instance == nullptr)
606 {
607 return ErrorCode::ARG_ERR;
608 }
609
610 // 直接读取 bxCAN 的错误状态寄存器 ESR
611 uint32_t esr = hcan_->Instance->ESR;
612
613 // TEC: bits 23:16, REC: bits 31:24(参考 RM & CAN_ESR 描述)
614 state.tx_error_counter = static_cast<uint8_t>((esr >> 16) & 0xFFu);
615 state.rx_error_counter = static_cast<uint8_t>((esr >> 24) & 0xFFu);
616
617 // 状态位:BOFF / EPVF / EWGF
618 state.bus_off = (esr & CAN_ESR_BOFF) != 0u;
619 state.error_passive = (esr & CAN_ESR_EPVF) != 0u;
620 state.error_warning = (esr & CAN_ESR_EWGF) != 0u;
621
622 return ErrorCode::OK;
623}
624
625extern "C" void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* hcan)
626{
627 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
628 if (can)
629 {
630 can->ProcessRxInterrupt();
631 }
632}
633
634extern "C" void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef* hcan)
635{
636 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
637 if (can)
638 {
639 can->ProcessRxInterrupt();
640 }
641}
642
643extern "C" void HAL_CAN_ErrorCallback(CAN_HandleTypeDef* hcan)
644{
645 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
646 if (can)
647 {
649 }
650
651 HAL_CAN_ResetError(hcan);
652}
653
654extern "C" void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef* hcan)
655{
656 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
657 if (can)
658 {
659 can->TxService();
660 }
661}
662
663extern "C" void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef* hcan)
664{
665 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
666 if (can)
667 {
668 can->TxService();
669 }
670}
671
672extern "C" void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef* hcan)
673{
674 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
675 if (can)
676 {
677 can->TxService();
678 }
679}
680
681#endif
CAN 通信抽象类,定义经典 CAN 帧与订阅接口。 Abstract class for CAN communication with classic CAN frames and subscript...
Definition can.hpp:16
@ 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).
void OnMessage(const ClassicPack &pack, bool in_isr)
分发接收到的经典 CAN 帧。 Dispatch a received classic CAN frame.
Definition can.cpp:18
ErrorID
ClassicPack::type == Type::ERROR 时使用的虚拟 ID。 Virtual IDs used when ClassicPack::type == Type::ERROR.
Definition can.hpp:146
ErrorCode Put(const Data &data)
向池中放入一个元素 / Put an element into the pool
ErrorCode Get(Data &data)
从池中取出一个元素 / Retrieve an element from the pool
STM32CAN 类,用于处理 STM32 系统的 CAN 通道。 Provides handling for STM32 CAN channels.
Definition stm32_can.hpp:44
ErrorCode GetErrorState(CAN::ErrorState &state) const override
查询当前错误状态(快照)。 Query current CAN controller error state (snapshot).
ErrorCode SetConfig(const CAN::Configuration &cfg) override
设置 CAN 配置。Set CAN configuration.
STM32CAN(CAN_HandleTypeDef *hcan, uint32_t pool_size)
STM32CAN 类,用于处理 STM32 系统的 CAN 通道。 Provides handling for STM32 CAN.
Definition stm32_can.cpp:47
uint32_t GetClockFreq() const override
获取 CAN 外设时钟频率(Hz)。 Get CAN peripheral clock frequency in Hz.
ErrorCode Init(void)
初始化
Definition stm32_can.cpp:54
ErrorCode AddMessage(const ClassicPack &pack) override
添加经典 CAN 消息。Add classic CAN message.
void ProcessErrorInterrupt()
处理错误中断
void ProcessRxInterrupt()
处理接收中断
LibXR 命名空间
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
Mode mode
工作模式。Operating mode.
Definition can.hpp:66
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