libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_can.cpp
1#include "ch32_can.hpp"
2
3#include "ch32_usbcan_shared.hpp"
4
5using namespace LibXR;
6
7CH32CAN* CH32CAN::map[CH32_CAN_NUMBER] = {nullptr};
8
9#if defined(CAN1) && !defined(CAN2)
10static void can1_rx0_thunk()
11{
12 if (auto* can = LibXR::CH32CAN::map[CH32_CAN1])
13 {
14 can->ProcessRxInterrupt();
15 }
16}
17
18static void can1_tx_thunk()
19{
20 if (auto* can = LibXR::CH32CAN::map[CH32_CAN1])
21 {
22 can->ProcessTxInterrupt();
23 }
24}
25#endif
26
27static inline uint8_t ch32_can_mode_macro(const CAN::Mode& m)
28{
29 if (m.loopback && m.listen_only)
30 {
31 return CAN_Mode_Silent_LoopBack;
32 }
33 if (m.loopback)
34 {
35 return CAN_Mode_LoopBack;
36 }
37 if (m.listen_only)
38 {
39 return CAN_Mode_Silent;
40 }
41 return CAN_Mode_Normal;
42}
43
44static inline void ch32_can_enable_nvic(ch32_can_id_t id, uint8_t fifo)
45{
46 // TX 中断线。
47 // TX interrupt line.
48 switch (id)
49 {
50#if defined(CAN1)
51 case CH32_CAN1:
52 NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
53 break;
54#endif
55
56#if defined(CAN2)
57 case CH32_CAN2:
58 NVIC_EnableIRQ(CAN2_TX_IRQn);
59 break;
60#endif
61 default:
62 break;
63 }
64
65 // RX 中断线:FIFO0 -> RX0 vector,FIFO1 -> RX1 vector。
66 // RX interrupt line: FIFO0 -> RX0 vector, FIFO1 -> RX1 vector.
67 if (fifo == 0u)
68 {
69 switch (id)
70 {
71#if defined(CAN1)
72 case CH32_CAN1:
73 NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
74 break;
75#endif
76
77#if defined(CAN2)
78 case CH32_CAN2:
79 NVIC_EnableIRQ(CAN2_RX0_IRQn);
80 break;
81#endif
82 default:
83 break;
84 }
85 }
86 else
87 {
88 switch (id)
89 {
90#if defined(CAN1)
91 case CH32_CAN1:
92 NVIC_EnableIRQ(CAN1_RX1_IRQn);
93 break;
94#endif
95
96#if defined(CAN2)
97 case CH32_CAN2:
98 NVIC_EnableIRQ(CAN2_RX1_IRQn);
99 break;
100#endif
101
102 default:
103 break;
104 }
105 }
106
107 // SCE 中断线。
108 // SCE interrupt line.
109 switch (id)
110 {
111#if defined(CAN1)
112 case CH32_CAN1:
113 NVIC_EnableIRQ(CAN1_SCE_IRQn);
114 break;
115#endif
116
117#if defined(CAN2)
118 case CH32_CAN2:
119 NVIC_EnableIRQ(CAN2_SCE_IRQn);
120 break;
121#endif
122
123 default:
124 break;
125 }
126}
127
128CH32CAN::CH32CAN(ch32_can_id_t id, uint32_t queue_size)
129 : CAN(), instance_(CH32_CAN_GetInstanceID(id)), id_(id), tx_queue_(queue_size)
130{
131 if constexpr (LibXR::CH32UsbCanShared::usb_can_share_enabled())
132 {
133#if defined(CAN1) && !defined(CAN2)
134 const bool USB_ALREADY_INITED =
135 LibXR::CH32UsbCanShared::usb_inited.load(std::memory_order_acquire);
136 // 在 USB/CAN 共享中断拓扑下,CAN1 必须先于 USB 初始化。
137 // On shared USB/CAN interrupt configurations, CAN1 must initialize before USB.
138 ASSERT(USB_ALREADY_INITED == false);
139#endif
140 }
141
142#if defined(CAN2)
143 if (id == CH32_CAN1)
144 {
145 filter_bank_ = 0;
146 fifo_ = CAN_FilterFIFO0; // 0
147 }
148 else
149 {
150 filter_bank_ = 14;
151 fifo_ = CAN_FilterFIFO1; // 1
152 }
153#else
154 filter_bank_ = 0;
155 fifo_ = CAN_FilterFIFO0; // 0
156#endif
157
158 ASSERT(id_ < CH32_CAN_NUMBER);
159 ASSERT(instance_ != nullptr);
160
161 map[id_] = this;
162
163 // 打开外设时钟。
164 // Enable the peripheral clock.
165 RCC_APB1PeriphClockCmd(CH32_CAN_RCC_PERIPH_MAP[id_], ENABLE);
166
167 // 在调用 SetConfig() 之前,保持 CAN 处于初始化模式。
168 // Keep CAN in initialization mode until SetConfig() is called.
169 (void)CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Initialization);
170
171#if defined(CAN2)
172 // 在双 CAN 变体上,配置默认的共享过滤器分界点。
173 // On dual-CAN variants, configure the default shared filter split point.
174 CAN_SlaveStartBank(CH32_CAN_DEFAULT_SLAVE_START_BANK);
175#endif
176
177 (void)Init();
178}
179
181{
182 if (instance_ == nullptr)
183 {
184 return ErrorCode::ARG_ERR;
185 }
186
187 // 默认全接收过滤器(ID-mask 模式,全 0)。
188 // Default accept-all filter (ID-mask mode, all zeros).
189 CAN_FilterInitTypeDef f = {};
190 f.CAN_FilterIdHigh = 0u;
191 f.CAN_FilterIdLow = 0u;
192 f.CAN_FilterMaskIdHigh = 0u;
193 f.CAN_FilterMaskIdLow = 0u;
194 f.CAN_FilterFIFOAssignment = fifo_;
195 f.CAN_FilterNumber = filter_bank_;
196 f.CAN_FilterMode = CAN_FilterMode_IdMask;
197 f.CAN_FilterScale = CAN_FilterScale_32bit;
198 f.CAN_FilterActivation = ENABLE;
199
200 CAN_FilterInit(&f);
201
202 EnableIRQs();
203
204 // 为当前 CAN 实例打开 NVIC。
205 // Enable NVIC for this CAN instance.
206 ch32_can_enable_nvic(id_, fifo_);
207
208 if constexpr (LibXR::CH32UsbCanShared::usb_can_share_enabled())
209 {
210#if defined(CAN1) && !defined(CAN2)
211 LibXR::CH32UsbCanShared::register_can1_rx0(&can1_rx0_thunk);
212 LibXR::CH32UsbCanShared::register_can1_tx(&can1_tx_thunk);
213 LibXR::CH32UsbCanShared::can1_inited.store(true, std::memory_order_release);
214#endif
215 }
216
217 return ErrorCode::OK;
218}
219
220void CH32CAN::DisableIRQs()
221{
222 uint32_t it = 0u;
223
224#ifdef CAN_IT_FMP0
225 if (fifo_ == 0u)
226 {
227 it |= CAN_IT_FMP0;
228 }
229#endif
230#ifdef CAN_IT_FMP1
231 if (fifo_ == 1u)
232 {
233 it |= CAN_IT_FMP1;
234 }
235#endif
236
237#ifdef CAN_IT_TME
238 it |= CAN_IT_TME;
239#endif
240
241#ifdef CAN_IT_ERR
242 it |= CAN_IT_ERR;
243#endif
244#ifdef CAN_IT_BOF
245 it |= CAN_IT_BOF;
246#endif
247#ifdef CAN_IT_EPV
248 it |= CAN_IT_EPV;
249#endif
250#ifdef CAN_IT_EWG
251 it |= CAN_IT_EWG;
252#endif
253#ifdef CAN_IT_LEC
254 it |= CAN_IT_LEC;
255#endif
256
257 if (it != 0u)
258 {
259 CAN_ITConfig(instance_, it, DISABLE);
260 }
261}
262
263void CH32CAN::EnableIRQs()
264{
265 uint32_t it = 0u;
266
267#ifdef CAN_IT_FMP0
268 if (fifo_ == 0u)
269 {
270 it |= CAN_IT_FMP0;
271 }
272#endif
273#ifdef CAN_IT_FMP1
274 if (fifo_ == 1u)
275 {
276 it |= CAN_IT_FMP1;
277 }
278#endif
279
280#ifdef CAN_IT_TME
281 it |= CAN_IT_TME;
282#endif
283
284#ifdef CAN_IT_ERR
285 it |= CAN_IT_ERR;
286#endif
287#ifdef CAN_IT_BOF
288 it |= CAN_IT_BOF;
289#endif
290#ifdef CAN_IT_EPV
291 it |= CAN_IT_EPV;
292#endif
293#ifdef CAN_IT_EWG
294 it |= CAN_IT_EWG;
295#endif
296#ifdef CAN_IT_LEC
297 it |= CAN_IT_LEC;
298#endif
299
300 if (it != 0u)
301 {
302 // Clear pending interrupt flags before enabling interrupt sources.
303#ifdef CAN_IT_TME
304 if ((it & CAN_IT_TME) != 0u)
305 {
306 CAN_ClearITPendingBit(instance_, CAN_IT_TME);
307 }
308#endif
309
310#ifdef CAN_IT_FMP0
311 if (fifo_ == 0u && ((it & CAN_IT_FMP0) != 0u))
312 {
313 CAN_ClearITPendingBit(instance_, CAN_IT_FMP0);
314 }
315#endif
316#ifdef CAN_IT_FMP1
317 if (fifo_ == 1u && ((it & CAN_IT_FMP1) != 0u))
318 {
319 CAN_ClearITPendingBit(instance_, CAN_IT_FMP1);
320 }
321#endif
322
323 CAN_ITConfig(instance_, it, ENABLE);
324 }
325}
326
327static inline bool fill_keep_zero_from_cache(CAN::BitTiming& dst,
328 const CAN::BitTiming& cache)
329{
330 auto keep = [&](uint32_t& field, uint32_t cached) -> bool
331 {
332 if (field == 0u)
333 {
334 if (cached == 0u)
335 {
336 return false;
337 }
338 field = cached;
339 }
340 return true;
341 };
342
343 bool ok = true;
344 ok &= keep(dst.brp, cache.brp);
345 ok &= keep(dst.prop_seg, cache.prop_seg);
346 ok &= keep(dst.phase_seg1, cache.phase_seg1);
347 ok &= keep(dst.phase_seg2, cache.phase_seg2);
348 ok &= keep(dst.sjw, cache.sjw);
349 return ok;
350}
351
353{
354 if (instance_ == nullptr)
355 {
356 return ErrorCode::ARG_ERR;
357 }
358
359 // 保证所有返回路径都会恢复 IRQ 状态。
360 // Ensure IRQ state restoration on all return paths.
361 struct IrqGuard
362 {
363 CH32CAN* self;
364 explicit IrqGuard(CH32CAN* s) : self(s) { self->DisableIRQs(); }
365 ~IrqGuard() { self->EnableIRQs(); }
366 } guard(this);
367
369 bool entered_init = false;
370
371 // 构造实际使用的时序参数;为 0 的字段复用缓存配置。
372 // Build effective timing values; zero fields reuse cached configuration.
373 CAN::Configuration cfg = cfg_in;
374
375 if (!fill_keep_zero_from_cache(cfg.bit_timing, cfg_cache_.bit_timing))
376 {
377 return ErrorCode::ARG_ERR;
378 }
379
380 // 校验 bxCAN 时序约束。
381 // Validate bxCAN timing constraints.
382 const CAN::BitTiming& bt = cfg.bit_timing;
383
384 // BRP: 1..1024.
385 if (bt.brp < 1u || bt.brp > 1024u)
386 {
387 ASSERT(false);
388 return ErrorCode::ARG_ERR;
389 }
390
391 // BS1 = PROP_SEG + PHASE_SEG1: 1..16.
392 const uint32_t BS1 = bt.prop_seg + bt.phase_seg1;
393 if (BS1 < 1u || BS1 > 16u)
394 {
395 ASSERT(false);
396 return ErrorCode::ARG_ERR;
397 }
398
399 // BS2: 1..8.
400 if (bt.phase_seg2 < 1u || bt.phase_seg2 > 8u)
401 {
402 ASSERT(false);
403 return ErrorCode::ARG_ERR;
404 }
405
406 // SJW: 1..4 and SJW <= BS2.
407 if (bt.sjw < 1u || bt.sjw > 4u || bt.sjw > bt.phase_seg2)
408 {
409 ASSERT(false);
410 return ErrorCode::ARG_ERR;
411 }
412
413 // 进入初始化模式。
414 // Enter initialization mode.
415 if (CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Initialization) ==
416 CAN_ModeStatus_Failed)
417 {
418 return ErrorCode::FAILED;
419 }
420 entered_init = true;
421
422 // 填充并应用初始化结构体。
423 // Apply the initialization structure.
424 CAN_InitTypeDef init;
425 std::memset(&init, 0, sizeof(init));
426 CAN_StructInit(&init);
427
428 init.CAN_Prescaler = static_cast<uint16_t>(bt.brp);
429 init.CAN_Mode = ch32_can_mode_macro(cfg.mode);
430
431 init.CAN_SJW = static_cast<uint8_t>(bt.sjw - 1u);
432 init.CAN_BS1 = static_cast<uint8_t>(BS1 - 1u);
433 init.CAN_BS2 = static_cast<uint8_t>(bt.phase_seg2 - 1u);
434
435 // 工作模式映射。
436 // Mode mapping.
437 init.CAN_NART = cfg.mode.one_shot ? ENABLE : DISABLE;
438
439 // 控制器默认选项。
440 // Default controller options.
441 init.CAN_TTCM = DISABLE;
442 init.CAN_ABOM = ENABLE; // auto bus-off management
443 init.CAN_AWUM = DISABLE; // auto wake-up
444 init.CAN_RFLM = DISABLE; // FIFO not locked
445 init.CAN_TXFP = ENABLE; // prioritize by TX request order
446
447 if (CAN_Init(instance_, &init) != CAN_InitStatus_Success)
448 {
450 }
451 else
452 {
453 if (CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Normal) ==
454 CAN_ModeStatus_Failed)
455 {
457 }
458 else
459 {
460 // 仅在配置成功后更新缓存。
461 // Update the cache only on successful configuration.
462 cfg_cache_ = cfg;
463 ec = ErrorCode::OK;
464 }
465 }
466
467 // 如果进入 init 模式后配置失败,则请求回到 normal 模式。
468 // If configuration fails after entering init mode, request normal mode.
469 if (ec != ErrorCode::OK && entered_init)
470 {
471 (void)CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Normal);
472 }
473
474 return ec;
475}
476
477uint32_t CH32CAN::GetClockFreq() const
478{
479 RCC_ClocksTypeDef clocks{};
480 RCC_GetClocksFreq(&clocks);
481 return clocks.PCLK1_Frequency;
482}
483
484inline void CH32CAN::BuildTxMsg(const ClassicPack& p, CanTxMsg& m)
485{
486 const bool IS_EXT = (p.type == Type::EXTENDED) || (p.type == Type::REMOTE_EXTENDED);
487 const bool IS_RTR =
488 (p.type == Type::REMOTE_STANDARD) || (p.type == Type::REMOTE_EXTENDED);
489
490 m.DLC = (p.dlc <= 8u) ? static_cast<uint8_t>(p.dlc) : 8u;
491 m.IDE = IS_EXT ? CAN_ID_EXT : CAN_ID_STD;
492 m.RTR = IS_RTR ? CAN_RTR_REMOTE : CAN_RTR_DATA;
493
494 m.StdId = IS_EXT ? 0u : (p.id & 0x7FFu);
495 m.ExtId = IS_EXT ? (p.id & 0x1FFFFFFFu) : 0u;
496
497 std::memcpy(m.Data, p.data, 8);
498}
499
500void CH32CAN::TxService()
501{
502 if (instance_ == nullptr)
503 {
504 return;
505 }
506
507 tx_pend_.store(1u, std::memory_order_release);
508
509 uint32_t expected = 0u;
510 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
511 std::memory_order_relaxed))
512 {
513 return;
514 }
515
516 constexpr uint32_t TME_MASK = (CAN_TSTATR_TME0 | CAN_TSTATR_TME1 | CAN_TSTATR_TME2);
517
518 for (;;)
519 {
520 tx_pend_.store(0u, std::memory_order_release);
521
522 while ((instance_->TSTATR & TME_MASK) != 0u)
523 {
524 ClassicPack p{};
525 if (tx_retry_valid_)
526 {
527 p = tx_retry_pack_;
528 }
529 else if (tx_queue_.Pop(p) != ErrorCode::OK)
530 {
531 break;
532 }
533
534 BuildTxMsg(p, tx_msg_);
535
536 uint8_t mb = CAN_Transmit(instance_, &tx_msg_);
537 if (mb == CAN_TxStatus_NoMailBox)
538 {
539 tx_retry_pack_ = p;
540 tx_retry_valid_ = true;
541 break;
542 }
543
544 tx_retry_valid_ = false;
545 }
546
547 tx_lock_.store(0u, std::memory_order_release);
548
549 if (tx_pend_.load(std::memory_order_acquire) == 0u)
550 {
551 return;
552 }
553
554 expected = 0u;
555 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
556 std::memory_order_relaxed))
557 {
558 return;
559 }
560 }
561}
562
564{
565 if (pack.type == Type::ERROR)
566 {
567 return ErrorCode::ARG_ERR;
568 }
569
570 if (tx_queue_.Push(pack) != ErrorCode::OK)
571 {
572 return ErrorCode::FULL;
573 }
574
575 TxService();
576 return ErrorCode::OK;
577}
578
580{
581#ifdef CAN_IT_TME
582 if (instance_ == nullptr)
583 {
584 return;
585 }
586
587 if (CAN_GetITStatus(instance_, CAN_IT_TME) != RESET)
588 {
589 CAN_ClearITPendingBit(instance_, CAN_IT_TME);
590 TxService();
591 }
592#else
593 TxService();
594#endif
595}
596
598{
599 if (instance_ == nullptr)
600 {
601 return;
602 }
603
604 // 先排空 RX FIFO,再确认 RX 挂起标志。
605 // Drain the RX FIFO first, then acknowledge RX pending flags.
606 while (CAN_MessagePending(instance_, fifo_) != 0u)
607 {
608 CAN_Receive(instance_, fifo_, &rx_msg_);
609
610 ClassicPack p{};
611 if (rx_msg_.IDE == CAN_ID_STD)
612 {
613 p.id = rx_msg_.StdId;
614 p.type = Type::STANDARD;
615 }
616 else
617 {
618 p.id = rx_msg_.ExtId;
619 p.type = Type::EXTENDED;
620 }
621
622 if (rx_msg_.RTR == CAN_RTR_REMOTE)
623 {
625 }
626
627 p.dlc = (rx_msg_.DLC <= 8u) ? rx_msg_.DLC : 8u;
628 std::memcpy(p.data, rx_msg_.Data, 8);
629
630 OnMessage(p, true);
631 }
632
633 // 确认 RX 挂起标志。
634 // Acknowledge RX pending flags.
635#ifdef CAN_IT_FMP0
636 if (fifo_ == 0u)
637 {
638 if (CAN_GetITStatus(instance_, CAN_IT_FMP0) != RESET)
639 {
640 CAN_ClearITPendingBit(instance_, CAN_IT_FMP0);
641 }
642 }
643#endif
644#ifdef CAN_IT_FMP1
645 if (fifo_ == 1u)
646 {
647 if (CAN_GetITStatus(instance_, CAN_IT_FMP1) != RESET)
648 {
649 CAN_ClearITPendingBit(instance_, CAN_IT_FMP1);
650 }
651 }
652#endif
653}
654
656{
657 if (instance_ == nullptr)
658 {
659 return;
660 }
661
662 // 在清 pending 位前先快照错误标志和 LEC。
663 // Snapshot error flags and LEC before clearing pending bits.
664 const bool BOF = (CAN_GetFlagStatus(instance_, CAN_FLAG_BOF) != RESET);
665 const bool EPV = (CAN_GetFlagStatus(instance_, CAN_FLAG_EPV) != RESET);
666 const bool EWG = (CAN_GetFlagStatus(instance_, CAN_FLAG_EWG) != RESET);
667 const uint8_t LEC = CAN_GetLastErrorCode(instance_);
668
669#ifdef CAN_IT_LEC
670 if (CAN_GetITStatus(instance_, CAN_IT_LEC) != RESET)
671 {
672 CAN_ClearITPendingBit(instance_, CAN_IT_LEC);
673 }
674#endif
675#ifdef CAN_IT_ERR
676 if (CAN_GetITStatus(instance_, CAN_IT_ERR) != RESET)
677 {
678 CAN_ClearITPendingBit(instance_, CAN_IT_ERR);
679 }
680#endif
681#ifdef CAN_IT_BOF
682 if (CAN_GetITStatus(instance_, CAN_IT_BOF) != RESET)
683 {
684 CAN_ClearITPendingBit(instance_, CAN_IT_BOF);
685 }
686#endif
687#ifdef CAN_IT_EPV
688 if (CAN_GetITStatus(instance_, CAN_IT_EPV) != RESET)
689 {
690 CAN_ClearITPendingBit(instance_, CAN_IT_EPV);
691 }
692#endif
693#ifdef CAN_IT_EWG
694 if (CAN_GetITStatus(instance_, CAN_IT_EWG) != RESET)
695 {
696 CAN_ClearITPendingBit(instance_, CAN_IT_EWG);
697 }
698#endif
699
700 ClassicPack p{};
701 p.type = Type::ERROR;
702 p.dlc = 0u;
703
704 CAN::ErrorID eid = CAN::ErrorID::CAN_ERROR_ID_GENERIC;
705
706 if (BOF)
707 {
708 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
709 }
710 else if (EPV)
711 {
712 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
713 }
714 else if (EWG)
715 {
716 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
717 }
718 else
719 {
720 switch (LEC)
721 {
722 case CAN_ErrorCode_StuffErr:
723 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
724 break;
725 case CAN_ErrorCode_FormErr:
726 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
727 break;
728 case CAN_ErrorCode_ACKErr:
729 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
730 break;
731 case CAN_ErrorCode_BitRecessiveErr:
732 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
733 break;
734 case CAN_ErrorCode_BitDominantErr:
735 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
736 break;
737 case CAN_ErrorCode_CRCErr:
738 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
739 break;
740 default:
741 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
742 break;
743 }
744 }
745
746 p.id = static_cast<uint32_t>(eid);
747 OnMessage(p, true);
748}
749
751{
752 if (instance_ == nullptr)
753 {
754 return ErrorCode::ARG_ERR;
755 }
756
757 state.rx_error_counter = CAN_GetReceiveErrorCounter(instance_);
758 state.tx_error_counter = CAN_GetLSBTransmitErrorCounter(instance_);
759
760 state.bus_off = (CAN_GetFlagStatus(instance_, CAN_FLAG_BOF) != RESET);
761 state.error_passive = (CAN_GetFlagStatus(instance_, CAN_FLAG_EPV) != RESET);
762 state.error_warning = (CAN_GetFlagStatus(instance_, CAN_FLAG_EWG) != RESET);
763
764 return ErrorCode::OK;
765}
766
767#if defined(CAN1)
768// NOLINTNEXTLINE(readability-identifier-naming)
769extern "C" void CAN1_TX_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
770// NOLINTNEXTLINE(readability-identifier-naming)
771extern "C" void CAN1_TX_IRQHandler(void)
772{
773 if (auto* can = LibXR::CH32CAN::map[CH32_CAN1])
774 {
775 can->ProcessTxInterrupt();
776 }
777}
778
779// NOLINTNEXTLINE(readability-identifier-naming)
780extern "C" void CAN1_RX1_IRQHandler(void)
781 __attribute__((interrupt("WCH-Interrupt-fast")));
782// NOLINTNEXTLINE(readability-identifier-naming)
783extern "C" void CAN1_RX1_IRQHandler(void)
784{
785 if (auto* can = LibXR::CH32CAN::map[CH32_CAN1])
786 {
787 can->ProcessRxInterrupt();
788 }
789}
790
791// NOLINTNEXTLINE(readability-identifier-naming)
792extern "C" void CAN1_SCE_IRQHandler(void)
793 __attribute__((interrupt("WCH-Interrupt-fast")));
794// NOLINTNEXTLINE(readability-identifier-naming)
795extern "C" void CAN1_SCE_IRQHandler(void)
796{
797 if (auto* can = LibXR::CH32CAN::map[CH32_CAN1])
798 {
799 can->ProcessErrorInterrupt();
800 }
801}
802#endif
803
804#if defined(CAN2)
805// NOLINTNEXTLINE(readability-identifier-naming)
806extern "C" void CAN2_TX_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
807// NOLINTNEXTLINE(readability-identifier-naming)
808extern "C" void CAN2_TX_IRQHandler(void)
809{
810 if (auto* can = LibXR::CH32CAN::map[CH32_CAN2])
811 {
812 can->ProcessTxInterrupt();
813 }
814}
815
816// NOLINTNEXTLINE(readability-identifier-naming)
817extern "C" void CAN2_RX0_IRQHandler(void)
818 __attribute__((interrupt("WCH-Interrupt-fast")));
819// NOLINTNEXTLINE(readability-identifier-naming)
820extern "C" void CAN2_RX0_IRQHandler(void)
821{
822 if (auto* can = LibXR::CH32CAN::map[CH32_CAN2])
823 {
824 can->ProcessRxInterrupt();
825 }
826}
827
828// NOLINTNEXTLINE(readability-identifier-naming)
829extern "C" void CAN2_RX1_IRQHandler(void)
830 __attribute__((interrupt("WCH-Interrupt-fast")));
831// NOLINTNEXTLINE(readability-identifier-naming)
832extern "C" void CAN2_RX1_IRQHandler(void)
833{
834 if (auto* can = LibXR::CH32CAN::map[CH32_CAN2])
835 {
836 can->ProcessRxInterrupt();
837 }
838}
839
840// NOLINTNEXTLINE(readability-identifier-naming)
841extern "C" void CAN2_SCE_IRQHandler(void)
842 __attribute__((interrupt("WCH-Interrupt-fast")));
843// NOLINTNEXTLINE(readability-identifier-naming)
844extern "C" void CAN2_SCE_IRQHandler(void)
845{
846 if (auto* can = LibXR::CH32CAN::map[CH32_CAN2])
847 {
848 can->ProcessErrorInterrupt();
849 }
850}
851#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
CH32 CAN 驱动实现 / CH32 CAN driver implementation.
Definition ch32_can.hpp:24
CH32CAN(ch32_can_id_t id, uint32_t queue_size)
构造 CAN 驱动对象 / Construct CAN driver object
Definition ch32_can.cpp:128
ErrorCode SetConfig(const CAN::Configuration &cfg) override
设置 CAN 配置 / Set CAN configuration
Definition ch32_can.cpp:352
void ProcessTxInterrupt()
处理发送中断 / Handle TX interrupt
Definition ch32_can.cpp:579
void ProcessErrorInterrupt()
处理错误中断 / Handle error interrupt
Definition ch32_can.cpp:655
MPMCQueue< ClassicPack > tx_queue_
发送软件队列。 TX software queue.
Definition ch32_can.hpp:95
CAN::Configuration cfg_cache_
缓存配置(用于保留原值语义) / Cached configuration for keep-previous semantics
Definition ch32_can.hpp:105
ErrorCode AddMessage(const ClassicPack &pack) override
发送消息入队 / Enqueue TX message
Definition ch32_can.cpp:563
void ProcessRxInterrupt()
处理接收中断 / Handle RX interrupt
Definition ch32_can.cpp:597
ErrorCode Init()
初始化过滤器和中断路由 / Initialize filters and IRQ routing
Definition ch32_can.cpp:180
ErrorCode GetErrorState(CAN::ErrorState &state) const override
获取总线错误状态 / Get bus error state
Definition ch32_can.cpp:750
uint32_t GetClockFreq() const override
获取 CAN 时钟频率 / Get CAN clock frequency
Definition ch32_can.cpp:477
bool tx_retry_valid_
待重试帧有效标记。 Pending retry frame flag.
Definition ch32_can.hpp:97
static CH32CAN * map[CH32_CAN_NUMBER]
中断分发表 / IRQ dispatch map
Definition ch32_can.hpp:77
ClassicPack tx_retry_pack_
待重试帧。 Pending retry frame.
Definition ch32_can.hpp:99
CanRxMsg rx_msg_
中断上下文收发缓冲 / RX/TX buffers in IRQ context
Definition ch32_can.hpp:108
ErrorCode Push(const Data &item)
推入一个强类型元素。
ErrorCode Pop(Data &item)
弹出一个强类型元素。
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ FAILED
操作失败 | Operation failed
@ FULL
已满 | Full
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
CAN 位时序配置。Bit timing configuration for CAN.
Definition can.hpp:37
uint32_t brp
预分频。Baud rate prescaler.
Definition can.hpp:38
uint32_t sjw
同步跳宽。Synchronization jump width.
Definition can.hpp:42
uint32_t phase_seg2
相位段 2。Phase segment 2.
Definition can.hpp:41
uint32_t prop_seg
传播段。Propagation segment.
Definition can.hpp:39
uint32_t phase_seg1
相位段 1。Phase segment 1.
Definition can.hpp:40
经典 CAN 帧数据结构。Classic CAN frame structure.
Definition can.hpp:129
Type type
帧类型。Frame type.
Definition can.hpp:131
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
CAN 工作模式。CAN operating mode.
Definition can.hpp:50
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