5CH32CAN* CH32CAN::map[CH32_CAN_NUMBER] = {
nullptr};
7static inline uint8_t ch32_can_mode_macro(
const CAN::Mode& m)
11 return CAN_Mode_Silent_LoopBack;
15 return CAN_Mode_LoopBack;
19 return CAN_Mode_Silent;
21 return CAN_Mode_Normal;
32static inline void CH32_CAN_EnableNVIC(ch32_can_id_t
id, uint8_t fifo)
39 NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
45 NVIC_EnableIRQ(CAN2_TX_IRQn);
59 NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
65 NVIC_EnableIRQ(CAN2_RX0_IRQn);
78 NVIC_EnableIRQ(CAN1_RX1_IRQn);
84 NVIC_EnableIRQ(CAN2_RX1_IRQn);
98 NVIC_EnableIRQ(CAN1_SCE_IRQn);
104 NVIC_EnableIRQ(CAN2_SCE_IRQn);
114 :
CAN(), instance_(CH32_CAN_GetInstanceID(id)), id_(id), tx_pool_(pool_size)
120 fifo_ = CAN_FilterFIFO0;
125 fifo_ = CAN_FilterFIFO1;
129 fifo_ = CAN_FilterFIFO0;
132 ASSERT(id_ < CH32_CAN_NUMBER);
133 ASSERT(instance_ !=
nullptr);
138 RCC_APB1PeriphClockCmd(CH32_CAN_RCC_PERIPH_MAP[id_], ENABLE);
141 (void)CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Initialization);
145 CAN_SlaveStartBank(CH32_CAN_DEFAULT_SLAVE_START_BANK);
153 if (instance_ ==
nullptr)
155 return ErrorCode::ARG_ERR;
159 CAN_FilterInitTypeDef f = {};
160 f.CAN_FilterIdHigh = 0u;
161 f.CAN_FilterIdLow = 0u;
162 f.CAN_FilterMaskIdHigh = 0u;
163 f.CAN_FilterMaskIdLow = 0u;
164 f.CAN_FilterFIFOAssignment = fifo_;
165 f.CAN_FilterNumber = filter_bank_;
166 f.CAN_FilterMode = CAN_FilterMode_IdMask;
167 f.CAN_FilterScale = CAN_FilterScale_32bit;
168 f.CAN_FilterActivation = ENABLE;
175 CH32_CAN_EnableNVIC(id_, fifo_);
177 return ErrorCode::OK;
180void CH32CAN::DisableIRQs()
182 if (instance_ ==
nullptr)
return;
187 if (fifo_ == 0u) it |= CAN_IT_FMP0;
190 if (fifo_ == 1u) it |= CAN_IT_FMP1;
215 CAN_ITConfig(instance_, it, DISABLE);
219void CH32CAN::EnableIRQs()
221 if (instance_ ==
nullptr)
return;
226 if (fifo_ == 0u) it |= CAN_IT_FMP0;
229 if (fifo_ == 1u) it |= CAN_IT_FMP1;
257 if ((it & CAN_IT_TME) != 0u)
259 CAN_ClearITPendingBit(instance_, CAN_IT_TME);
264 if (fifo_ == 0u && ((it & CAN_IT_FMP0) != 0u))
266 CAN_ClearITPendingBit(instance_, CAN_IT_FMP0);
270 if (fifo_ == 1u && ((it & CAN_IT_FMP1) != 0u))
272 CAN_ClearITPendingBit(instance_, CAN_IT_FMP1);
276 CAN_ITConfig(instance_, it, ENABLE);
289 auto keep = [&](uint32_t& field, uint32_t cached) ->
bool
293 if (cached == 0u)
return false;
300 ok &= keep(dst.
brp, cache.
brp);
304 ok &= keep(dst.
sjw, cache.
sjw);
310 if (instance_ ==
nullptr)
312 return ErrorCode::ARG_ERR;
319 explicit IrqGuard(
CH32CAN* s) : self(s) { self->DisableIRQs(); }
320 ~IrqGuard() { self->EnableIRQs(); }
323 ErrorCode ec = ErrorCode::OK;
324 bool entered_init =
false;
334 return ErrorCode::ARG_ERR;
341 return ErrorCode::ARG_ERR;
349 if (bt.
brp < 1u || bt.
brp > 1024u)
352 return ErrorCode::ARG_ERR;
357 if (bs1 < 1u || bs1 > 16u)
360 return ErrorCode::ARG_ERR;
367 return ErrorCode::ARG_ERR;
374 return ErrorCode::ARG_ERR;
378 if (CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Initialization) ==
379 CAN_ModeStatus_Failed)
381 return ErrorCode::FAILED;
386 CAN_InitTypeDef init;
387 std::memset(&init, 0,
sizeof(init));
388 CAN_StructInit(&init);
390 init.CAN_Prescaler =
static_cast<uint16_t
>(bt.
brp);
391 init.CAN_Mode = ch32_can_mode_macro(cfg.
mode);
393 init.CAN_SJW =
static_cast<uint8_t
>(bt.
sjw - 1u);
394 init.CAN_BS1 =
static_cast<uint8_t
>(bs1 - 1u);
395 init.CAN_BS2 =
static_cast<uint8_t
>(bt.
phase_seg2 - 1u);
401 init.CAN_TTCM = DISABLE;
402 init.CAN_ABOM = ENABLE;
403 init.CAN_AWUM = DISABLE;
404 init.CAN_RFLM = DISABLE;
405 init.CAN_TXFP = ENABLE;
407 if (CAN_Init(instance_, &init) != CAN_InitStatus_Success)
409 ec = ErrorCode::FAILED;
413 if (CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Normal) ==
414 CAN_ModeStatus_Failed)
416 ec = ErrorCode::FAILED;
427 if (ec != ErrorCode::OK && entered_init)
429 (void)CAN_OperatingModeRequest(instance_, CAN_OperatingMode_Normal);
437 RCC_ClocksTypeDef clocks{};
438 RCC_GetClocksFreq(&clocks);
439 return clocks.PCLK1_Frequency;
442inline void CH32CAN::BuildTxMsg(
const ClassicPack& p, CanTxMsg& m)
448 m.DLC = (p.dlc <= 8u) ?
static_cast<uint8_t
>(p.dlc) : 8u;
449 m.IDE = is_ext ? CAN_ID_EXT : CAN_ID_STD;
450 m.RTR = is_rtr ? CAN_RTR_REMOTE : CAN_RTR_DATA;
452 m.StdId = is_ext ? 0u : (p.id & 0x7FFu);
453 m.ExtId = is_ext ? (p.id & 0x1FFFFFFFu) : 0u;
455 std::memcpy(m.Data, p.data, 8);
458void CH32CAN::TxService()
460 if (instance_ ==
nullptr)
return;
462 tx_pend_.store(1u, std::memory_order_release);
464 uint32_t expected = 0u;
465 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
466 std::memory_order_relaxed))
473 tx_pend_.store(0u, std::memory_order_release);
478 if (tx_pool_.
Get(p) != ErrorCode::OK)
483 BuildTxMsg(p, tx_msg_);
485 uint8_t mb = CAN_Transmit(instance_, &tx_msg_);
486 if (mb == CAN_TxStatus_NoMailBox)
488 (void)tx_pool_.
Put(p);
493 tx_lock_.store(0u, std::memory_order_release);
495 if (tx_pend_.load(std::memory_order_acquire) == 0u)
501 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
502 std::memory_order_relaxed))
513 return ErrorCode::ARG_ERR;
516 if (tx_pool_.
Put(pack) != ErrorCode::OK)
518 return ErrorCode::FULL;
522 return ErrorCode::OK;
528 if (instance_ ==
nullptr)
return;
530 if (CAN_GetITStatus(instance_, CAN_IT_TME) != RESET)
532 CAN_ClearITPendingBit(instance_, CAN_IT_TME);
542 if (instance_ ==
nullptr)
return;
547 while (CAN_MessagePending(instance_, fifo_) != 0u)
549 CAN_Receive(instance_, fifo_, &rx_msg_);
552 if (rx_msg_.IDE == CAN_ID_STD)
554 p.id = rx_msg_.StdId;
559 p.id = rx_msg_.ExtId;
563 if (rx_msg_.RTR == CAN_RTR_REMOTE)
568 p.
dlc = (rx_msg_.DLC <= 8u) ? rx_msg_.DLC : 8u;
569 std::memcpy(p.data, rx_msg_.Data, 8);
578 if (CAN_GetITStatus(instance_, CAN_IT_FMP0) != RESET)
580 CAN_ClearITPendingBit(instance_, CAN_IT_FMP0);
587 if (CAN_GetITStatus(instance_, CAN_IT_FMP1) != RESET)
589 CAN_ClearITPendingBit(instance_, CAN_IT_FMP1);
597 if (instance_ ==
nullptr)
return;
602 const bool bof = (CAN_GetFlagStatus(instance_, CAN_FLAG_BOF) != RESET);
603 const bool epv = (CAN_GetFlagStatus(instance_, CAN_FLAG_EPV) != RESET);
604 const bool ewg = (CAN_GetFlagStatus(instance_, CAN_FLAG_EWG) != RESET);
605 const uint8_t lec = CAN_GetLastErrorCode(instance_);
608 if (CAN_GetITStatus(instance_, CAN_IT_LEC) != RESET)
610 CAN_ClearITPendingBit(instance_, CAN_IT_LEC);
614 if (CAN_GetITStatus(instance_, CAN_IT_ERR) != RESET)
616 CAN_ClearITPendingBit(instance_, CAN_IT_ERR);
620 if (CAN_GetITStatus(instance_, CAN_IT_BOF) != RESET)
622 CAN_ClearITPendingBit(instance_, CAN_IT_BOF);
626 if (CAN_GetITStatus(instance_, CAN_IT_EPV) != RESET)
628 CAN_ClearITPendingBit(instance_, CAN_IT_EPV);
632 if (CAN_GetITStatus(instance_, CAN_IT_EWG) != RESET)
634 CAN_ClearITPendingBit(instance_, CAN_IT_EWG);
646 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
650 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
654 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
660 case CAN_ErrorCode_StuffErr:
661 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
663 case CAN_ErrorCode_FormErr:
664 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
666 case CAN_ErrorCode_ACKErr:
667 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
669 case CAN_ErrorCode_BitRecessiveErr:
670 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
672 case CAN_ErrorCode_BitDominantErr:
673 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
675 case CAN_ErrorCode_CRCErr:
676 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
679 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
684 p.id =
static_cast<uint32_t
>(eid);
690 if (instance_ ==
nullptr)
692 return ErrorCode::ARG_ERR;
698 state.
bus_off = (CAN_GetFlagStatus(instance_, CAN_FLAG_BOF) != RESET);
699 state.
error_passive = (CAN_GetFlagStatus(instance_, CAN_FLAG_EPV) != RESET);
700 state.
error_warning = (CAN_GetFlagStatus(instance_, CAN_FLAG_EWG) != RESET);
702 return ErrorCode::OK;
706extern "C" void USB_HP_CAN1_TX_IRQHandler(
void) __attribute__((interrupt));
707extern "C" void USB_HP_CAN1_TX_IRQHandler(
void)
709 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN1])
711 can->ProcessTxInterrupt();
715extern "C" void USB_LP_CAN1_RX0_IRQHandler(
void) __attribute__((interrupt));
716extern "C" void USB_LP_CAN1_RX0_IRQHandler(
void)
718 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN1])
720 can->ProcessRxInterrupt();
724extern "C" void CAN1_TX_IRQHandler(
void) __attribute__((interrupt));
725extern "C" void CAN1_TX_IRQHandler(
void)
727 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN1])
729 can->ProcessTxInterrupt();
733extern "C" void CAN1_RX1_IRQHandler(
void) __attribute__((interrupt));
734extern "C" void CAN1_RX1_IRQHandler(
void)
736 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN1])
738 can->ProcessRxInterrupt();
742extern "C" void CAN1_SCE_IRQHandler(
void) __attribute__((interrupt));
743extern "C" void CAN1_SCE_IRQHandler(
void)
745 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN1])
747 can->ProcessErrorInterrupt();
753extern "C" void CAN2_TX_IRQHandler(
void) __attribute__((interrupt));
754extern "C" void CAN2_TX_IRQHandler(
void)
756 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN2])
758 can->ProcessTxInterrupt();
762extern "C" void CAN2_RX0_IRQHandler(
void) __attribute__((interrupt));
763extern "C" void CAN2_RX0_IRQHandler(
void)
765 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN2])
767 can->ProcessRxInterrupt();
771extern "C" void CAN2_RX1_IRQHandler(
void) __attribute__((interrupt));
772extern "C" void CAN2_RX1_IRQHandler(
void)
774 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN2])
776 can->ProcessRxInterrupt();
780extern "C" void CAN2_SCE_IRQHandler(
void) __attribute__((interrupt));
781extern "C" void CAN2_SCE_IRQHandler(
void)
783 if (
auto* can = LibXR::CH32CAN::map[CH32_CAN2])
785 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.
CH32CAN driver (bxCAN-like) for LibXR::CAN.
ErrorCode SetConfig(const CAN::Configuration &cfg) override
Set CAN configuration (bit timing + mode). Also (re-)enables IRQs.
void ProcessTxInterrupt()
Process TX interrupt (call from CANx_TX handler).
void ProcessErrorInterrupt()
Process SCE/error interrupt (call from CANx_SCE handler).
ErrorCode AddMessage(const ClassicPack &pack) override
Enqueue a ClassicPack for transmission.
void ProcessRxInterrupt()
Process RX interrupt (call from CANx_RX0 / CANx_RX1 handlers).
ErrorCode Init()
Initialize filter + IRQ routing. Does NOT force a bitrate; call SetConfig().
ErrorCode GetErrorState(CAN::ErrorState &state) const override
Read bus error state and counters.
uint32_t GetClockFreq() const override
CAN clock frequency (Hz). CH32 CAN is on APB1.
CH32CAN(ch32_can_id_t id, uint32_t pool_size)
Construct CH32CAN.
ErrorCode Put(const Data &data)
向池中放入一个元素 / Put an element into the pool
ErrorCode Get(Data &data)
从池中取出一个元素 / Retrieve an element from the pool
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.
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.