libxr
Embedded C++ framework for bare-metal, RTOS and Linux
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(RCC_APB1Periph_USB)
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 LIBXR_CH32_HAS_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 LIBXR_CH32_HAS_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 LIBXR_CH32_HAS_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 LIBXR_CH32_HAS_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 // 端点地址在 Stop 后仍有效,不能在分配 PMA 后扩大 CAN 过滤器占用。
134 // Endpoint addresses survive Stop; reserve CAN filters before allocating PMA.
135 ASSERT(!LibXR::CH32UsbCanShared::usb_pma_configured.load(std::memory_order_acquire));
136 }
137
138#if LIBXR_CH32_HAS_CAN2
139 if (id == CH32_CAN1)
140 {
141 filter_bank_ = 0;
142 fifo_ = CAN_FilterFIFO0; // 0
143 }
144 else
145 {
146 filter_bank_ = 14;
147 fifo_ = CAN_FilterFIFO1; // 1
148 }
149#else
150 filter_bank_ = 0;
151 fifo_ = CAN_FilterFIFO0; // 0
152#endif
153
154 ASSERT(id_ < CH32_CAN_NUMBER);
155 ASSERT(instance_ != nullptr);
156
157 map[id_] = this;
158
159 // 打开外设时钟。
160 // Enable the peripheral clock.
161 RCC_APB1PeriphClockCmd(CH32_CAN_RCC_PERIPH_MAP[id_], ENABLE);
162#if LIBXR_CH32_HAS_CAN2
163 if (id_ == CH32_CAN2)
164 {
165 // CAN2 的共享过滤器寄存器位于 CAN1,不能依赖应用先创建 CAN1 对象。
166 // CAN2 filter registers belong to CAN1, even in a CAN2-only application.
167 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
168 }
169#endif
170
171 // 在调用 SetConfig() 之前,保持 CAN 处于初始化模式。
172 // Keep CAN in initialization mode until SetConfig() is called.
173 (void)CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Initialization);
174
175#if LIBXR_CH32_HAS_CAN2
176 // 在双 CAN 变体上,配置默认的共享过滤器分界点。
177 // On dual-CAN variants, configure the default shared filter split point.
178 CAN_SlaveStartBank(CH32_CAN_DEFAULT_SLAVE_START_BANK);
179#endif
180
181 (void)Init();
182}
183
185{
186 if (instance_ == nullptr)
187 {
188 return ErrorCode::ARG_ERR;
189 }
190
191 // 默认全接收过滤器(ID-mask 模式,全 0)。
192 // Default accept-all filter (ID-mask mode, all zeros).
193 CAN_FilterInitTypeDef f = {};
194 f.CAN_FilterIdHigh = 0u;
195 f.CAN_FilterIdLow = 0u;
196 f.CAN_FilterMaskIdHigh = 0u;
197 f.CAN_FilterMaskIdLow = 0u;
198 f.CAN_FilterFIFOAssignment = fifo_;
199 f.CAN_FilterNumber = filter_bank_;
200 f.CAN_FilterMode = CAN_FilterMode_IdMask;
201 f.CAN_FilterScale = CAN_FilterScale_32bit;
202 f.CAN_FilterActivation = ENABLE;
203
204 CAN_FilterInit(&f);
205
206 // 在放行中断源之前发布回调,防止已有 pending 中断进入空分发器。
207 // Publish callbacks before enabling an interrupt source with pending events.
208 if constexpr (LibXR::CH32UsbCanShared::usb_can_irq_share_enabled())
209 {
210#if defined(CAN1) && defined(RCC_APB1Periph_USB)
211 if (id_ == CH32_CAN1)
212 {
213 LibXR::CH32UsbCanShared::register_can1_rx0(&can1_rx0_thunk);
214 LibXR::CH32UsbCanShared::register_can1_tx(&can1_tx_thunk);
215 LibXR::CH32UsbCanShared::can1_inited.store(true, std::memory_order_release);
216 }
217#if LIBXR_CH32_HAS_CAN2
218 else if (id_ == CH32_CAN2)
219 {
220 LibXR::CH32UsbCanShared::can2_inited.store(true, std::memory_order_release);
221 }
222#endif
223#endif
224 }
225
226 EnableIRQs();
227 ch32_can_enable_nvic(id_, fifo_);
228
229 return ErrorCode::OK;
230}
231
232void CH32CAN::DisableIRQs()
233{
234 uint32_t it = 0u;
235
236#ifdef CAN_IT_FMP0
237 if (fifo_ == 0u)
238 {
239 it |= CAN_IT_FMP0;
240 }
241#endif
242#ifdef CAN_IT_FMP1
243 if (fifo_ == 1u)
244 {
245 it |= CAN_IT_FMP1;
246 }
247#endif
248
249#ifdef CAN_IT_TME
250 it |= CAN_IT_TME;
251#endif
252
253#ifdef CAN_IT_ERR
254 it |= CAN_IT_ERR;
255#endif
256#ifdef CAN_IT_BOF
257 it |= CAN_IT_BOF;
258#endif
259#ifdef CAN_IT_EPV
260 it |= CAN_IT_EPV;
261#endif
262#ifdef CAN_IT_EWG
263 it |= CAN_IT_EWG;
264#endif
265#ifdef CAN_IT_LEC
266 it |= CAN_IT_LEC;
267#endif
268
269 if (it != 0u)
270 {
271 CAN_ITConfig(instance_, it, DISABLE);
272 }
273}
274
275void CH32CAN::EnableIRQs()
276{
277 uint32_t it = 0u;
278
279#ifdef CAN_IT_FMP0
280 if (fifo_ == 0u)
281 {
282 it |= CAN_IT_FMP0;
283 }
284#endif
285#ifdef CAN_IT_FMP1
286 if (fifo_ == 1u)
287 {
288 it |= CAN_IT_FMP1;
289 }
290#endif
291
292#ifdef CAN_IT_TME
293 it |= CAN_IT_TME;
294#endif
295
296#ifdef CAN_IT_ERR
297 it |= CAN_IT_ERR;
298#endif
299#ifdef CAN_IT_BOF
300 it |= CAN_IT_BOF;
301#endif
302#ifdef CAN_IT_EPV
303 it |= CAN_IT_EPV;
304#endif
305#ifdef CAN_IT_EWG
306 it |= CAN_IT_EWG;
307#endif
308#ifdef CAN_IT_LEC
309 it |= CAN_IT_LEC;
310#endif
311
312 if (it != 0u)
313 {
314 // Clear pending interrupt flags before enabling interrupt sources.
315#ifdef CAN_IT_TME
316 if ((it & CAN_IT_TME) != 0u)
317 {
318 CAN_ClearITPendingBit(instance_, CAN_IT_TME);
319 }
320#endif
321
322#ifdef CAN_IT_FMP0
323 if (fifo_ == 0u && ((it & CAN_IT_FMP0) != 0u))
324 {
325 CAN_ClearITPendingBit(instance_, CAN_IT_FMP0);
326 }
327#endif
328#ifdef CAN_IT_FMP1
329 if (fifo_ == 1u && ((it & CAN_IT_FMP1) != 0u))
330 {
331 CAN_ClearITPendingBit(instance_, CAN_IT_FMP1);
332 }
333#endif
334
335 CAN_ITConfig(instance_, it, ENABLE);
336 }
337}
338
339static inline bool fill_keep_zero_from_cache(CAN::BitTiming& dst,
340 const CAN::BitTiming& cache)
341{
342 auto keep = [&](uint32_t& field, uint32_t cached) -> bool
343 {
344 if (field == 0u)
345 {
346 if (cached == 0u)
347 {
348 return false;
349 }
350 field = cached;
351 }
352 return true;
353 };
354
355 bool ok = true;
356 ok &= keep(dst.brp, cache.brp);
357 ok &= keep(dst.prop_seg, cache.prop_seg);
358 ok &= keep(dst.phase_seg1, cache.phase_seg1);
359 ok &= keep(dst.phase_seg2, cache.phase_seg2);
360 ok &= keep(dst.sjw, cache.sjw);
361 return ok;
362}
363
365{
366 if (instance_ == nullptr)
367 {
368 return ErrorCode::ARG_ERR;
369 }
370
371 // 保证所有返回路径都会恢复 IRQ 状态。
372 // Ensure IRQ state restoration on all return paths.
373 struct IrqGuard
374 {
375 CH32CAN* self;
376 explicit IrqGuard(CH32CAN* s) : self(s) { self->DisableIRQs(); }
377 ~IrqGuard() { self->EnableIRQs(); }
378 } guard(this);
379
381 bool entered_init = false;
382
383 // 构造实际使用的时序参数;为 0 的字段复用缓存配置。
384 // Build effective timing values; zero fields reuse cached configuration.
385 CAN::Configuration cfg = cfg_in;
386
387 if (!fill_keep_zero_from_cache(cfg.bit_timing, cfg_cache_.bit_timing))
388 {
389 return ErrorCode::ARG_ERR;
390 }
391
392 // 校验 bxCAN 时序约束。
393 // Validate bxCAN timing constraints.
394 const CAN::BitTiming& bt = cfg.bit_timing;
395
396 // BRP: 1..1024.
397 if (bt.brp < 1u || bt.brp > 1024u)
398 {
399 return ErrorCode::ARG_ERR;
400 }
401
402 // BS1 = PROP_SEG + PHASE_SEG1: 1..16.
403 const uint32_t BS1 = bt.prop_seg + bt.phase_seg1;
404 if (BS1 < 1u || BS1 > 16u)
405 {
406 return ErrorCode::ARG_ERR;
407 }
408
409 // BS2: 1..8.
410 if (bt.phase_seg2 < 1u || bt.phase_seg2 > 8u)
411 {
412 return ErrorCode::ARG_ERR;
413 }
414
415 // SJW: 1..4 and SJW <= BS2.
416 if (bt.sjw < 1u || bt.sjw > 4u || bt.sjw > bt.phase_seg2)
417 {
418 return ErrorCode::ARG_ERR;
419 }
420
421 // 进入初始化模式。
422 // Enter initialization mode.
423 if (CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Initialization) ==
424 CAN_ModeStatus_Failed)
425 {
426 return ErrorCode::FAILED;
427 }
428 entered_init = true;
429
430 // 填充并应用初始化结构体。
431 // Apply the initialization structure.
432 CAN_InitTypeDef init;
433 std::memset(&init, 0, sizeof(init));
434 CAN_StructInit(&init);
435
436 init.CAN_Prescaler = static_cast<uint16_t>(bt.brp);
437 init.CAN_Mode = ch32_can_mode_macro(cfg.mode);
438
439 init.CAN_SJW = static_cast<uint8_t>(bt.sjw - 1u);
440 init.CAN_BS1 = static_cast<uint8_t>(BS1 - 1u);
441 init.CAN_BS2 = static_cast<uint8_t>(bt.phase_seg2 - 1u);
442
443 // 工作模式映射。
444 // Mode mapping.
445 init.CAN_NART = cfg.mode.one_shot ? ENABLE : DISABLE;
446
447 // 控制器默认选项。
448 // Default controller options.
449 init.CAN_TTCM = DISABLE;
450 init.CAN_ABOM = ENABLE; // auto bus-off management
451 init.CAN_AWUM = DISABLE; // auto wake-up
452 init.CAN_RFLM = DISABLE; // FIFO not locked
453 init.CAN_TXFP = ENABLE; // prioritize by TX request order
454
455 if (CAN_Init(instance_, &init) != CAN_InitStatus_Success)
456 {
458 }
459 else
460 {
461 if (CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Normal) ==
462 CAN_ModeStatus_Failed)
463 {
465 }
466 else
467 {
468 // 仅在配置成功后更新缓存。
469 // Update the cache only on successful configuration.
470 cfg_cache_ = cfg;
471 ec = ErrorCode::OK;
472 }
473 }
474
475 // 如果进入 init 模式后配置失败,则请求回到 normal 模式。
476 // If configuration fails after entering init mode, request normal mode.
477 if (ec != ErrorCode::OK && entered_init)
478 {
479 (void)CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Normal);
480 }
481
482 return ec;
483}
484
485uint32_t CH32CAN::GetClockFreq() const
486{
487 RCC_ClocksTypeDef clocks{};
488 RCC_GetClocksFreq(&clocks);
489 return clocks.PCLK1_Frequency;
490}
491
492inline void CH32CAN::BuildTxMsg(const ClassicPack& p, CanTxMsg& m)
493{
494 const bool IS_EXT = (p.type == Type::EXTENDED) || (p.type == Type::REMOTE_EXTENDED);
495 const bool IS_RTR =
496 (p.type == Type::REMOTE_STANDARD) || (p.type == Type::REMOTE_EXTENDED);
497
498 m.DLC = (p.dlc <= 8u) ? static_cast<uint8_t>(p.dlc) : 8u;
499 m.IDE = IS_EXT ? CAN_ID_EXT : CAN_ID_STD;
500 m.RTR = IS_RTR ? CAN_RTR_REMOTE : CAN_RTR_DATA;
501
502 m.StdId = IS_EXT ? 0u : (p.id & 0x7FFu);
503 m.ExtId = IS_EXT ? (p.id & 0x1FFFFFFFu) : 0u;
504
505 std::memcpy(m.Data, p.data, 8);
506}
507
508void CH32CAN::TxService()
509{
510 if (instance_ == nullptr)
511 {
512 return;
513 }
514
515 tx_pend_.store(1u, std::memory_order_release);
516
517 uint32_t expected = 0u;
518 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
519 std::memory_order_relaxed))
520 {
521 return;
522 }
523
524 constexpr uint32_t TME_MASK = (CAN_TSTATR_TME0 | CAN_TSTATR_TME1 | CAN_TSTATR_TME2);
525
526 for (;;)
527 {
528 tx_pend_.store(0u, std::memory_order_release);
529
530 while ((instance_->TSTATR & TME_MASK) != 0u)
531 {
532 ClassicPack p{};
533 if (tx_retry_valid_)
534 {
535 p = tx_retry_pack_;
536 }
537 else if (tx_queue_.Get(p) != ErrorCode::OK)
538 {
539 break;
540 }
541
542 BuildTxMsg(p, tx_msg_);
543
544 uint8_t mb = CAN_Transmit(instance_, &tx_msg_);
545 if (mb == CAN_TxStatus_NoMailBox)
546 {
547 tx_retry_pack_ = p;
548 tx_retry_valid_ = true;
549 break;
550 }
551
552 tx_retry_valid_ = false;
553 }
554
555 tx_lock_.store(0u, std::memory_order_release);
556
557 if (tx_pend_.load(std::memory_order_acquire) == 0u)
558 {
559 return;
560 }
561
562 expected = 0u;
563 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
564 std::memory_order_relaxed))
565 {
566 return;
567 }
568 }
569}
570
572{
573 if (pack.type == Type::ERROR)
574 {
575 return ErrorCode::ARG_ERR;
576 }
577
578 if (tx_queue_.Put(pack) != ErrorCode::OK)
579 {
580 return ErrorCode::FULL;
581 }
582
583 TxService();
584 return ErrorCode::OK;
585}
586
588{
589#ifdef CAN_IT_TME
590 if (instance_ == nullptr)
591 {
592 return;
593 }
594
595 if (CAN_GetITStatus(instance_, CAN_IT_TME) != RESET)
596 {
597 CAN_ClearITPendingBit(instance_, CAN_IT_TME);
598 TxService();
599 }
600#else
601 TxService();
602#endif
603}
604
606{
607 if (instance_ == nullptr)
608 {
609 return;
610 }
611
612 // 先排空 RX FIFO,再确认 RX 挂起标志。
613 // Drain the RX FIFO first, then acknowledge RX pending flags.
614 while (CAN_MessagePending(instance_, fifo_) != 0u)
615 {
616 CAN_Receive(instance_, fifo_, &rx_msg_);
617
618 ClassicPack p{};
619 if (rx_msg_.IDE == CAN_ID_STD)
620 {
621 p.id = rx_msg_.StdId;
622 p.type = Type::STANDARD;
623 }
624 else
625 {
626 p.id = rx_msg_.ExtId;
627 p.type = Type::EXTENDED;
628 }
629
630 if (rx_msg_.RTR == CAN_RTR_REMOTE)
631 {
633 }
634
635 p.dlc = (rx_msg_.DLC <= 8u) ? rx_msg_.DLC : 8u;
636 std::memcpy(p.data, rx_msg_.Data, 8);
637
638 OnMessage(p, true);
639 }
640
641 // 确认 RX 挂起标志。
642 // Acknowledge RX pending flags.
643#ifdef CAN_IT_FMP0
644 if (fifo_ == 0u)
645 {
646 if (CAN_GetITStatus(instance_, CAN_IT_FMP0) != RESET)
647 {
648 CAN_ClearITPendingBit(instance_, CAN_IT_FMP0);
649 }
650 }
651#endif
652#ifdef CAN_IT_FMP1
653 if (fifo_ == 1u)
654 {
655 if (CAN_GetITStatus(instance_, CAN_IT_FMP1) != RESET)
656 {
657 CAN_ClearITPendingBit(instance_, CAN_IT_FMP1);
658 }
659 }
660#endif
661}
662
664{
665 if (instance_ == nullptr)
666 {
667 return;
668 }
669
670 // 在清 pending 位前先快照错误标志和 LEC。
671 // Snapshot error flags and LEC before clearing pending bits.
672 const bool BOF = (CAN_GetFlagStatus(instance_, CAN_FLAG_BOF) != RESET);
673 const bool EPV = (CAN_GetFlagStatus(instance_, CAN_FLAG_EPV) != RESET);
674 const bool EWG = (CAN_GetFlagStatus(instance_, CAN_FLAG_EWG) != RESET);
675 const uint8_t LEC = CAN_GetLastErrorCode(instance_);
676
677#ifdef CAN_IT_LEC
678 if (CAN_GetITStatus(instance_, CAN_IT_LEC) != RESET)
679 {
680 CAN_ClearITPendingBit(instance_, CAN_IT_LEC);
681 }
682#endif
683#ifdef CAN_IT_ERR
684 if (CAN_GetITStatus(instance_, CAN_IT_ERR) != RESET)
685 {
686 CAN_ClearITPendingBit(instance_, CAN_IT_ERR);
687 }
688#endif
689#ifdef CAN_IT_BOF
690 if (CAN_GetITStatus(instance_, CAN_IT_BOF) != RESET)
691 {
692 CAN_ClearITPendingBit(instance_, CAN_IT_BOF);
693 }
694#endif
695#ifdef CAN_IT_EPV
696 if (CAN_GetITStatus(instance_, CAN_IT_EPV) != RESET)
697 {
698 CAN_ClearITPendingBit(instance_, CAN_IT_EPV);
699 }
700#endif
701#ifdef CAN_IT_EWG
702 if (CAN_GetITStatus(instance_, CAN_IT_EWG) != RESET)
703 {
704 CAN_ClearITPendingBit(instance_, CAN_IT_EWG);
705 }
706#endif
707
708 ClassicPack p{};
709 p.type = Type::ERROR;
710 p.dlc = 0u;
711
712 CAN::ErrorID eid = CAN::ErrorID::CAN_ERROR_ID_GENERIC;
713
714 if (BOF)
715 {
716 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
717 }
718 else if (EPV)
719 {
720 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
721 }
722 else if (EWG)
723 {
724 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
725 }
726 else
727 {
728 switch (LEC)
729 {
730 case CAN_ErrorCode_StuffErr:
731 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
732 break;
733 case CAN_ErrorCode_FormErr:
734 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
735 break;
736 case CAN_ErrorCode_ACKErr:
737 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
738 break;
739 case CAN_ErrorCode_BitRecessiveErr:
740 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
741 break;
742 case CAN_ErrorCode_BitDominantErr:
743 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
744 break;
745 case CAN_ErrorCode_CRCErr:
746 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
747 break;
748 default:
749 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
750 break;
751 }
752 }
753
754 p.id = static_cast<uint32_t>(eid);
755 OnMessage(p, true);
756}
757
759{
760 if (instance_ == nullptr)
761 {
762 return ErrorCode::ARG_ERR;
763 }
764
765 state.rx_error_counter = CAN_GetReceiveErrorCounter(instance_);
766 state.tx_error_counter = CAN_GetLSBTransmitErrorCounter(instance_);
767
768 state.bus_off = (CAN_GetFlagStatus(instance_, CAN_FLAG_BOF) != RESET);
769 state.error_passive = (CAN_GetFlagStatus(instance_, CAN_FLAG_EPV) != RESET);
770 state.error_warning = (CAN_GetFlagStatus(instance_, CAN_FLAG_EWG) != RESET);
771
772 return ErrorCode::OK;
773}
774
775#if defined(CAN1)
776// NOLINTNEXTLINE(readability-identifier-naming)
777extern "C" void CAN1_TX_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
778// NOLINTNEXTLINE(readability-identifier-naming)
779extern "C" void CAN1_TX_IRQHandler(void)
780{
781 if (auto* can = LibXR::CH32CAN::map[CH32_CAN1])
782 {
783 can->ProcessTxInterrupt();
784 }
785}
786
787// NOLINTNEXTLINE(readability-identifier-naming)
788extern "C" void CAN1_RX1_IRQHandler(void)
789 __attribute__((interrupt("WCH-Interrupt-fast")));
790// NOLINTNEXTLINE(readability-identifier-naming)
791extern "C" void CAN1_RX1_IRQHandler(void)
792{
793 if (auto* can = LibXR::CH32CAN::map[CH32_CAN1])
794 {
795 can->ProcessRxInterrupt();
796 }
797}
798
799// NOLINTNEXTLINE(readability-identifier-naming)
800extern "C" void CAN1_SCE_IRQHandler(void)
801 __attribute__((interrupt("WCH-Interrupt-fast")));
802// NOLINTNEXTLINE(readability-identifier-naming)
803extern "C" void CAN1_SCE_IRQHandler(void)
804{
805 if (auto* can = LibXR::CH32CAN::map[CH32_CAN1])
806 {
807 can->ProcessErrorInterrupt();
808 }
809}
810#endif
811
812#if LIBXR_CH32_HAS_CAN2
813// NOLINTNEXTLINE(readability-identifier-naming)
814extern "C" void CAN2_TX_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
815// NOLINTNEXTLINE(readability-identifier-naming)
816extern "C" void CAN2_TX_IRQHandler(void)
817{
818 if (auto* can = LibXR::CH32CAN::map[CH32_CAN2])
819 {
820 can->ProcessTxInterrupt();
821 }
822}
823
824// NOLINTNEXTLINE(readability-identifier-naming)
825extern "C" void CAN2_RX0_IRQHandler(void)
826 __attribute__((interrupt("WCH-Interrupt-fast")));
827// NOLINTNEXTLINE(readability-identifier-naming)
828extern "C" void CAN2_RX0_IRQHandler(void)
829{
830 if (auto* can = LibXR::CH32CAN::map[CH32_CAN2])
831 {
832 can->ProcessRxInterrupt();
833 }
834}
835
836// NOLINTNEXTLINE(readability-identifier-naming)
837extern "C" void CAN2_RX1_IRQHandler(void)
838 __attribute__((interrupt("WCH-Interrupt-fast")));
839// NOLINTNEXTLINE(readability-identifier-naming)
840extern "C" void CAN2_RX1_IRQHandler(void)
841{
842 if (auto* can = LibXR::CH32CAN::map[CH32_CAN2])
843 {
844 can->ProcessRxInterrupt();
845 }
846}
847
848// NOLINTNEXTLINE(readability-identifier-naming)
849extern "C" void CAN2_SCE_IRQHandler(void)
850 __attribute__((interrupt("WCH-Interrupt-fast")));
851// NOLINTNEXTLINE(readability-identifier-naming)
852extern "C" void CAN2_SCE_IRQHandler(void)
853{
854 if (auto* can = LibXR::CH32CAN::map[CH32_CAN2])
855 {
856 can->ProcessErrorInterrupt();
857 }
858}
859#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:147
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:364
void ProcessTxInterrupt()
处理发送中断 / Handle TX interrupt
Definition ch32_can.cpp:587
void ProcessErrorInterrupt()
处理错误中断 / Handle error interrupt
Definition ch32_can.cpp:663
ErrorCode AddMessage(const ClassicPack &pack) override
发送消息入队 / Enqueue TX message
Definition ch32_can.cpp:571
void ProcessRxInterrupt()
处理接收中断 / Handle RX interrupt
Definition ch32_can.cpp:605
ErrorCode Init()
初始化过滤器和中断路由 / Initialize filters and IRQ routing
Definition ch32_can.cpp:184
ErrorCode GetErrorState(CAN::ErrorState &state) const override
获取总线错误状态 / Get bus error state
Definition ch32_can.cpp:758
uint32_t GetClockFreq() const override
获取 CAN 时钟频率 / Get CAN clock frequency
Definition ch32_can.cpp:485
static CH32CAN * map[CH32_CAN_NUMBER]
中断分发表 / IRQ dispatch map
Definition ch32_can.hpp:77
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
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: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
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