3#include "ch32_usbcan_shared.hpp"
9#if defined(CAN1) && defined(RCC_APB1Periph_USB)
10static void can1_rx0_thunk()
14 can->ProcessRxInterrupt();
18static void can1_tx_thunk()
22 can->ProcessTxInterrupt();
27static inline uint8_t ch32_can_mode_macro(
const CAN::Mode& m)
31 return CAN_Mode_Silent_LoopBack;
35 return CAN_Mode_LoopBack;
39 return CAN_Mode_Silent;
41 return CAN_Mode_Normal;
44static inline void ch32_can_enable_nvic(ch32_can_id_t
id, uint8_t fifo)
52 NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
56#if LIBXR_CH32_HAS_CAN2
58 NVIC_EnableIRQ(CAN2_TX_IRQn);
73 NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
77#if LIBXR_CH32_HAS_CAN2
79 NVIC_EnableIRQ(CAN2_RX0_IRQn);
92 NVIC_EnableIRQ(CAN1_RX1_IRQn);
96#if LIBXR_CH32_HAS_CAN2
98 NVIC_EnableIRQ(CAN2_RX1_IRQn);
113 NVIC_EnableIRQ(CAN1_SCE_IRQn);
117#if LIBXR_CH32_HAS_CAN2
119 NVIC_EnableIRQ(CAN2_SCE_IRQn);
129 :
CAN(), instance_(CH32_CAN_GetInstanceID(id)), id_(id), tx_queue_(queue_size)
131 if constexpr (LibXR::CH32UsbCanShared::usb_can_share_enabled())
135 ASSERT(!LibXR::CH32UsbCanShared::usb_pma_configured.load(std::memory_order_acquire));
138#if LIBXR_CH32_HAS_CAN2
142 fifo_ = CAN_FilterFIFO0;
147 fifo_ = CAN_FilterFIFO1;
151 fifo_ = CAN_FilterFIFO0;
154 ASSERT(id_ < CH32_CAN_NUMBER);
155 ASSERT(instance_ !=
nullptr);
161 RCC_APB1PeriphClockCmd(CH32_CAN_RCC_PERIPH_MAP[id_], ENABLE);
162#if LIBXR_CH32_HAS_CAN2
163 if (id_ == CH32_CAN2)
167 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
173 (void)CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Initialization);
175#if LIBXR_CH32_HAS_CAN2
178 CAN_SlaveStartBank(CH32_CAN_DEFAULT_SLAVE_START_BANK);
186 if (instance_ ==
nullptr)
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;
208 if constexpr (LibXR::CH32UsbCanShared::usb_can_irq_share_enabled())
210#if defined(CAN1) && defined(RCC_APB1Periph_USB)
211 if (id_ == CH32_CAN1)
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);
217#if LIBXR_CH32_HAS_CAN2
218 else if (id_ == CH32_CAN2)
220 LibXR::CH32UsbCanShared::can2_inited.store(
true, std::memory_order_release);
227 ch32_can_enable_nvic(id_, fifo_);
232void CH32CAN::DisableIRQs()
271 CAN_ITConfig(instance_, it, DISABLE);
275void CH32CAN::EnableIRQs()
316 if ((it & CAN_IT_TME) != 0u)
318 CAN_ClearITPendingBit(instance_, CAN_IT_TME);
323 if (fifo_ == 0u && ((it & CAN_IT_FMP0) != 0u))
325 CAN_ClearITPendingBit(instance_, CAN_IT_FMP0);
329 if (fifo_ == 1u && ((it & CAN_IT_FMP1) != 0u))
331 CAN_ClearITPendingBit(instance_, CAN_IT_FMP1);
335 CAN_ITConfig(instance_, it, ENABLE);
342 auto keep = [&](uint32_t& field, uint32_t cached) ->
bool
356 ok &= keep(dst.
brp, cache.
brp);
360 ok &= keep(dst.
sjw, cache.
sjw);
366 if (instance_ ==
nullptr)
376 explicit IrqGuard(
CH32CAN* s) : self(s) { self->DisableIRQs(); }
377 ~IrqGuard() { self->EnableIRQs(); }
381 bool entered_init =
false;
397 if (bt.
brp < 1u || bt.
brp > 1024u)
404 if (BS1 < 1u || BS1 > 16u)
423 if (CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Initialization) ==
424 CAN_ModeStatus_Failed)
432 CAN_InitTypeDef init;
433 std::memset(&init, 0,
sizeof(init));
434 CAN_StructInit(&init);
436 init.CAN_Prescaler =
static_cast<uint16_t
>(bt.
brp);
437 init.CAN_Mode = ch32_can_mode_macro(cfg.
mode);
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);
449 init.CAN_TTCM = DISABLE;
450 init.CAN_ABOM = ENABLE;
451 init.CAN_AWUM = DISABLE;
452 init.CAN_RFLM = DISABLE;
453 init.CAN_TXFP = ENABLE;
455 if (CAN_Init(instance_, &init) != CAN_InitStatus_Success)
461 if (CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Normal) ==
462 CAN_ModeStatus_Failed)
479 (void)CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Normal);
487 RCC_ClocksTypeDef clocks{};
488 RCC_GetClocksFreq(&clocks);
489 return clocks.PCLK1_Frequency;
492inline void CH32CAN::BuildTxMsg(
const ClassicPack& p, CanTxMsg& m)
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;
502 m.StdId = IS_EXT ? 0u : (p.id & 0x7FFu);
503 m.ExtId = IS_EXT ? (p.id & 0x1FFFFFFFu) : 0u;
505 std::memcpy(m.Data, p.data, 8);
508void CH32CAN::TxService()
510 if (instance_ ==
nullptr)
515 tx_pend_.store(1u, std::memory_order_release);
517 uint32_t expected = 0u;
518 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
519 std::memory_order_relaxed))
524 constexpr uint32_t TME_MASK = (CAN_TSTATR_TME0 | CAN_TSTATR_TME1 | CAN_TSTATR_TME2);
528 tx_pend_.store(0u, std::memory_order_release);
530 while ((instance_->TSTATR & TME_MASK) != 0u)
542 BuildTxMsg(p, tx_msg_);
544 uint8_t mb = CAN_Transmit(instance_, &tx_msg_);
545 if (mb == CAN_TxStatus_NoMailBox)
548 tx_retry_valid_ =
true;
552 tx_retry_valid_ =
false;
555 tx_lock_.store(0u, std::memory_order_release);
557 if (tx_pend_.load(std::memory_order_acquire) == 0u)
563 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
564 std::memory_order_relaxed))
590 if (instance_ ==
nullptr)
595 if (CAN_GetITStatus(instance_, CAN_IT_TME) != RESET)
597 CAN_ClearITPendingBit(instance_, CAN_IT_TME);
607 if (instance_ ==
nullptr)
614 while (CAN_MessagePending(instance_, fifo_) != 0u)
616 CAN_Receive(instance_, fifo_, &rx_msg_);
619 if (rx_msg_.IDE == CAN_ID_STD)
621 p.id = rx_msg_.StdId;
626 p.id = rx_msg_.ExtId;
630 if (rx_msg_.RTR == CAN_RTR_REMOTE)
635 p.
dlc = (rx_msg_.DLC <= 8u) ? rx_msg_.DLC : 8u;
636 std::memcpy(p.data, rx_msg_.Data, 8);
646 if (CAN_GetITStatus(instance_, CAN_IT_FMP0) != RESET)
648 CAN_ClearITPendingBit(instance_, CAN_IT_FMP0);
655 if (CAN_GetITStatus(instance_, CAN_IT_FMP1) != RESET)
657 CAN_ClearITPendingBit(instance_, CAN_IT_FMP1);
665 if (instance_ ==
nullptr)
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_);
678 if (CAN_GetITStatus(instance_, CAN_IT_LEC) != RESET)
680 CAN_ClearITPendingBit(instance_, CAN_IT_LEC);
684 if (CAN_GetITStatus(instance_, CAN_IT_ERR) != RESET)
686 CAN_ClearITPendingBit(instance_, CAN_IT_ERR);
690 if (CAN_GetITStatus(instance_, CAN_IT_BOF) != RESET)
692 CAN_ClearITPendingBit(instance_, CAN_IT_BOF);
696 if (CAN_GetITStatus(instance_, CAN_IT_EPV) != RESET)
698 CAN_ClearITPendingBit(instance_, CAN_IT_EPV);
702 if (CAN_GetITStatus(instance_, CAN_IT_EWG) != RESET)
704 CAN_ClearITPendingBit(instance_, CAN_IT_EWG);
716 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
720 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
724 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
730 case CAN_ErrorCode_StuffErr:
731 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
733 case CAN_ErrorCode_FormErr:
734 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
736 case CAN_ErrorCode_ACKErr:
737 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
739 case CAN_ErrorCode_BitRecessiveErr:
740 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
742 case CAN_ErrorCode_BitDominantErr:
743 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
745 case CAN_ErrorCode_CRCErr:
746 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
749 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
754 p.id =
static_cast<uint32_t
>(eid);
760 if (instance_ ==
nullptr)
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);
777extern "C" void CAN1_TX_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
779extern "C" void CAN1_TX_IRQHandler(
void)
783 can->ProcessTxInterrupt();
788extern "C" void CAN1_RX1_IRQHandler(
void)
789 __attribute__((interrupt(
"WCH-Interrupt-fast")));
791extern "C" void CAN1_RX1_IRQHandler(
void)
795 can->ProcessRxInterrupt();
800extern "C" void CAN1_SCE_IRQHandler(
void)
801 __attribute__((interrupt(
"WCH-Interrupt-fast")));
803extern "C" void CAN1_SCE_IRQHandler(
void)
807 can->ProcessErrorInterrupt();
812#if LIBXR_CH32_HAS_CAN2
814extern "C" void CAN2_TX_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
816extern "C" void CAN2_TX_IRQHandler(
void)
820 can->ProcessTxInterrupt();
825extern "C" void CAN2_RX0_IRQHandler(
void)
826 __attribute__((interrupt(
"WCH-Interrupt-fast")));
828extern "C" void CAN2_RX0_IRQHandler(
void)
832 can->ProcessRxInterrupt();
837extern "C" void CAN2_RX1_IRQHandler(
void)
838 __attribute__((interrupt(
"WCH-Interrupt-fast")));
840extern "C" void CAN2_RX1_IRQHandler(
void)
844 can->ProcessRxInterrupt();
849extern "C" void CAN2_SCE_IRQHandler(
void)
850 __attribute__((interrupt(
"WCH-Interrupt-fast")));
852extern "C" void CAN2_SCE_IRQHandler(
void)
856 can->ProcessErrorInterrupt();
CAN 通信抽象类,定义经典 CAN 帧与订阅接口。 Abstract class for CAN communication with classic CAN frames and subscript...
@ 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.
ErrorID
ClassicPack::type == Type::ERROR 时使用的虚拟 ID。 Virtual IDs used when ClassicPack::type == Type::ERROR.
CH32 CAN 驱动实现 / CH32 CAN driver implementation.
CH32CAN(ch32_can_id_t id, uint32_t queue_size)
构造 CAN 驱动对象 / Construct CAN driver object
ErrorCode SetConfig(const CAN::Configuration &cfg) override
设置 CAN 配置 / Set CAN configuration
void ProcessTxInterrupt()
处理发送中断 / Handle TX interrupt
void ProcessErrorInterrupt()
处理错误中断 / Handle error interrupt
ErrorCode AddMessage(const ClassicPack &pack) override
发送消息入队 / Enqueue TX message
void ProcessRxInterrupt()
处理接收中断 / Handle RX interrupt
ErrorCode Init()
初始化过滤器和中断路由 / Initialize filters and IRQ routing
ErrorCode GetErrorState(CAN::ErrorState &state) const override
获取总线错误状态 / Get bus error state
uint32_t GetClockFreq() const override
获取 CAN 时钟频率 / Get CAN clock frequency
static CH32CAN * map[CH32_CAN_NUMBER]
中断分发表 / IRQ dispatch map
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.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
CAN 位时序配置 / Bit timing configuration for CAN.
uint32_t brp
预分频 / Baud rate prescaler.
uint32_t sjw
同步跳宽 / Synchronization jump width.
uint32_t phase_seg2
相位段 2 / Phase segment 2.
uint32_t prop_seg
传播段 / Propagation segment.
uint32_t phase_seg1
相位段 1 / Phase segment 1.
经典 CAN 帧数据结构 / Classic CAN frame structure.
Type type
帧类型 / Frame type.
uint8_t dlc
有效数据长度(0~8) / Data length code (0–8).
CAN 配置参数 / CAN configuration parameters.
BitTiming bit_timing
位时序配置 / Bit timing configuration.
Mode mode
工作模式 / Operating mode.
CAN 当前错误状态快照(来自硬件计数器/状态机)。 Snapshot of current CAN controller error state (from HW counters/state).
bool bus_off
是否处于 BUS-OFF / True if controller is bus-off.
bool error_passive
是否处于 Error Passive / True if error-passive.
uint8_t tx_error_counter
发送错误计数 TEC / Transmit error counter (TEC).
bool error_warning
是否处于 Error Warning / True if error-warning.
uint8_t rx_error_counter
接收错误计数 REC / Receive error counter (REC).
CAN 工作模式 / CAN operating mode.
bool loopback
回环模式 / Loopback mode.
bool one_shot
单次发送模式 / One-shot transmission.
bool listen_only
只听(静默)模式 / Listen-only (silent) mode.