1#include "stm32_canfd.hpp"
3#ifdef HAL_FDCAN_MODULE_ENABLED
7STM32CANFD* STM32CANFD::map[STM32_FDCAN_NUMBER] = {
nullptr};
15stm32_fdcan_id_t STM32_FDCAN_GetID(FDCAN_GlobalTypeDef* addr)
19 return stm32_fdcan_id_t::STM32_FDCAN_ID_ERROR;
22 else if (addr == FDCAN1)
24 return stm32_fdcan_id_t::STM32_FDCAN1;
28 else if (addr == FDCAN2)
30 return stm32_fdcan_id_t::STM32_FDCAN2;
34 else if (addr == FDCAN3)
36 return stm32_fdcan_id_t::STM32_FDCAN3;
41 return stm32_fdcan_id_t::STM32_FDCAN_ID_ERROR;
45static inline uint32_t BytesToDlc(uint32_t n)
53 return FDCAN_DLC_BYTES_12;
57 return FDCAN_DLC_BYTES_16;
61 return FDCAN_DLC_BYTES_20;
65 return FDCAN_DLC_BYTES_24;
69 return FDCAN_DLC_BYTES_32;
73 return FDCAN_DLC_BYTES_48;
75 return FDCAN_DLC_BYTES_64;
78static inline uint32_t DlcToBytes(uint32_t dlc)
80 if (dlc <= FDCAN_DLC_BYTES_8)
84 else if (dlc == FDCAN_DLC_BYTES_12)
88 else if (dlc == FDCAN_DLC_BYTES_16)
92 else if (dlc == FDCAN_DLC_BYTES_20)
96 else if (dlc == FDCAN_DLC_BYTES_24)
100 else if (dlc == FDCAN_DLC_BYTES_32)
104 else if (dlc == FDCAN_DLC_BYTES_48)
114inline void STM32CANFD::BuildTxHeader(
const ClassicPack& p, FDCAN_TxHeaderTypeDef& h)
121 h.IdType = is_ext ? FDCAN_EXTENDED_ID : FDCAN_STANDARD_ID;
122 h.TxFrameType = is_rtr ? FDCAN_REMOTE_FRAME : FDCAN_DATA_FRAME;
124 uint32_t bytes = (p.dlc <= 8u) ? p.dlc : 8u;
125 h.DataLength = BytesToDlc(bytes);
127 h.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
128 h.BitRateSwitch = FDCAN_BRS_OFF;
129 h.FDFormat = FDCAN_CLASSIC_CAN;
131 h.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
132 h.MessageMarker = 0x01;
135inline void STM32CANFD::BuildTxHeader(
const FDPack& p, FDCAN_TxHeaderTypeDef& h)
142 h.IdType = FDCAN_STANDARD_ID;
143 h.TxFrameType = FDCAN_DATA_FRAME;
147 h.IdType = FDCAN_EXTENDED_ID;
148 h.TxFrameType = FDCAN_DATA_FRAME;
156 DEV_ASSERT(p.len <= 64u);
157 h.DataLength = BytesToDlc(p.len);
159 h.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
160 h.BitRateSwitch = FDCAN_BRS_ON;
161 h.FDFormat = FDCAN_FD_CAN;
163 h.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
164 h.MessageMarker = 0x00;
170 id_(STM32_FDCAN_GetID(hcan->Instance)),
171 tx_queue_(queue_size),
172 tx_fd_queue_(queue_size)
174 CheckMessageRAMOffset(hcan);
181 FDCAN_FilterTypeDef can_filter = {};
182 can_filter.IdType = FDCAN_STANDARD_ID;
183 can_filter.FilterType = FDCAN_FILTER_MASK;
184 can_filter.FilterID1 = 0x0000;
185 can_filter.FilterID2 = 0x0000;
186 can_filter.FilterIndex = 0;
189 if (id_ == STM32_FDCAN1)
191 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
193 else if (id_ == STM32_FDCAN2)
195 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
197 else if (id_ == STM32_FDCAN3)
199 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
203 if (id_ == STM32_FDCAN1)
205 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
207 else if (id_ == STM32_FDCAN2)
209 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
212 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
216 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
221 can_filter.IdType = FDCAN_EXTENDED_ID;
223 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
228 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
233 if (can_filter.FilterConfig == FDCAN_FILTER_TO_RXFIFO0)
235 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
239 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
242 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_PASSIVE, 0);
243 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_WARNING, 0);
244 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_BUS_OFF, 0);
245 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
246 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_COMPLETE, 0xFFFFFFFF);
274 fd_cfg.mode = cfg.
mode;
281 ASSERT(hcan_ !=
nullptr && hcan_->Instance !=
nullptr);
283 FDCAN_GlobalTypeDef* can = hcan_->Instance;
286 uint32_t it_mask = 0u;
288#ifdef FDCAN_IT_RX_FIFO0_NEW_MESSAGE
289 it_mask |= FDCAN_IT_RX_FIFO0_NEW_MESSAGE;
291#ifdef FDCAN_IT_RX_FIFO1_NEW_MESSAGE
292 it_mask |= FDCAN_IT_RX_FIFO1_NEW_MESSAGE;
294#ifdef FDCAN_IT_TX_FIFO_EMPTY
295 it_mask |= FDCAN_IT_TX_FIFO_EMPTY;
300 HAL_FDCAN_DeactivateNotification(hcan_, it_mask);
304 if (HAL_FDCAN_Stop(hcan_) != HAL_OK)
309#ifdef FDCAN_CCCR_INIT
310 SET_BIT(can->CCCR, FDCAN_CCCR_INIT);
313 SET_BIT(can->CCCR, FDCAN_CCCR_CCE);
322 SET_BIT(can->CCCR, FDCAN_CCCR_DAR);
326 CLEAR_BIT(can->CCCR, FDCAN_CCCR_DAR);
333#ifdef FDCAN_CCCR_TEST
334#ifdef FDCAN_TEST_LBCK
338 SET_BIT(can->CCCR, FDCAN_CCCR_TEST);
339 SET_BIT(can->TEST, FDCAN_TEST_LBCK);
343 CLEAR_BIT(can->TEST, FDCAN_TEST_LBCK);
344 CLEAR_BIT(can->CCCR, FDCAN_CCCR_TEST);
354 SET_BIT(can->CCCR, FDCAN_CCCR_MON);
358 CLEAR_BIT(can->CCCR, FDCAN_CCCR_MON);
367#ifdef FDCAN_NBTP_NBRP_Msk
368 constexpr uint32_t NBRP_FIELD_MAX = (FDCAN_NBTP_NBRP_Msk >> FDCAN_NBTP_NBRP_Pos);
369 constexpr uint32_t NTSEG1_FIELD_MAX = (FDCAN_NBTP_NTSEG1_Msk >> FDCAN_NBTP_NTSEG1_Pos);
370 constexpr uint32_t NTSEG2_FIELD_MAX = (FDCAN_NBTP_NTSEG2_Msk >> FDCAN_NBTP_NTSEG2_Pos);
371 constexpr uint32_t NSJW_FIELD_MAX = (FDCAN_NBTP_NSJW_Msk >> FDCAN_NBTP_NSJW_Pos);
373 constexpr uint32_t NBRP_MAX = NBRP_FIELD_MAX + 1u;
374 constexpr uint32_t NTSEG1_MAX = NTSEG1_FIELD_MAX + 1u;
375 constexpr uint32_t NTSEG2_MAX = NTSEG2_FIELD_MAX + 1u;
376 constexpr uint32_t NSJW_MAX = NSJW_FIELD_MAX + 1u;
381 if (bt.brp < 1u || bt.brp > NBRP_MAX)
387 uint32_t tseg1 = bt.
prop_seg + bt.phase_seg1;
388 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
390 if (tseg1 < 1u || tseg1 > NTSEG1_MAX)
396 if (bt.phase_seg2 != 0u)
398 if (bt.phase_seg2 < 1u || bt.phase_seg2 > NTSEG2_MAX)
406 if (bt.sjw < 1u || bt.sjw > NSJW_MAX)
410 if (bt.phase_seg2 != 0u && bt.sjw > bt.phase_seg2)
416 uint32_t nbtp_old = can->NBTP;
417 uint32_t nbtp_new = nbtp_old;
418 uint32_t nbtp_mask = 0u;
423 uint32_t nbrp = (bt.brp - 1u) & NBRP_FIELD_MAX;
424 uint32_t mask = FDCAN_NBTP_NBRP_Msk;
427 nbtp_new |= (nbrp << FDCAN_NBTP_NBRP_Pos);
431 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
433 uint32_t ntseg1 = (tseg1 - 1u) & NTSEG1_FIELD_MAX;
434 uint32_t mask = FDCAN_NBTP_NTSEG1_Msk;
437 nbtp_new |= (ntseg1 << FDCAN_NBTP_NTSEG1_Pos);
441 if (bt.phase_seg2 != 0u)
443 uint32_t ntseg2 = (bt.phase_seg2 - 1u) & NTSEG2_FIELD_MAX;
444 uint32_t mask = FDCAN_NBTP_NTSEG2_Msk;
447 nbtp_new |= (ntseg2 << FDCAN_NBTP_NTSEG2_Pos);
453 uint32_t nsjw = (bt.sjw - 1u) & NSJW_FIELD_MAX;
454 uint32_t mask = FDCAN_NBTP_NSJW_Msk;
457 nbtp_new |= (nsjw << FDCAN_NBTP_NSJW_Pos);
462 nbtp_old &= ~nbtp_mask;
463 nbtp_old |= (nbtp_new & nbtp_mask);
464 can->NBTP = nbtp_old;
472#ifdef FDCAN_DBTP_DBRP_Msk
473 constexpr uint32_t DBRP_FIELD_MAX = (FDCAN_DBTP_DBRP_Msk >> FDCAN_DBTP_DBRP_Pos);
474 constexpr uint32_t DTSEG1_FIELD_MAX = (FDCAN_DBTP_DTSEG1_Msk >> FDCAN_DBTP_DTSEG1_Pos);
475 constexpr uint32_t DTSEG2_FIELD_MAX = (FDCAN_DBTP_DTSEG2_Msk >> FDCAN_DBTP_DTSEG2_Pos);
476 constexpr uint32_t DSJW_FIELD_MAX = (FDCAN_DBTP_DSJW_Msk >> FDCAN_DBTP_DSJW_Pos);
478 constexpr uint32_t DBRP_MAX = DBRP_FIELD_MAX + 1u;
479 constexpr uint32_t DTSEG1_MAX = DTSEG1_FIELD_MAX + 1u;
480 constexpr uint32_t DTSEG2_MAX = DTSEG2_FIELD_MAX + 1u;
481 constexpr uint32_t DSJW_MAX = DSJW_FIELD_MAX + 1u;
485 if (dbt.brp < 1u || dbt.brp > DBRP_MAX)
491 uint32_t dtseg1 = dbt.
prop_seg + dbt.phase_seg1;
492 if (dbt.prop_seg != 0u || dbt.phase_seg1 != 0u)
494 if (dtseg1 < 1u || dtseg1 > DTSEG1_MAX)
500 if (dbt.phase_seg2 != 0u)
502 if (dbt.phase_seg2 < 1u || dbt.phase_seg2 > DTSEG2_MAX)
510 if (dbt.sjw < 1u || dbt.sjw > DSJW_MAX)
514 if (dbt.phase_seg2 != 0u && dbt.sjw > dbt.phase_seg2)
520 uint32_t dbtp_old = can->DBTP;
521 uint32_t dbtp_new = dbtp_old;
522 uint32_t dbtp_mask = 0u;
526 uint32_t dbrp = (dbt.brp - 1u) & DBRP_FIELD_MAX;
527 uint32_t mask = FDCAN_DBTP_DBRP_Msk;
530 dbtp_new |= (dbrp << FDCAN_DBTP_DBRP_Pos);
533 if (dbt.prop_seg != 0u || dbt.phase_seg1 != 0u)
535 uint32_t dt1 = (dtseg1 - 1u) & DTSEG1_FIELD_MAX;
536 uint32_t mask = FDCAN_DBTP_DTSEG1_Msk;
539 dbtp_new |= (dt1 << FDCAN_DBTP_DTSEG1_Pos);
542 if (dbt.phase_seg2 != 0u)
544 uint32_t dt2 = (dbt.phase_seg2 - 1u) & DTSEG2_FIELD_MAX;
545 uint32_t mask = FDCAN_DBTP_DTSEG2_Msk;
548 dbtp_new |= (dt2 << FDCAN_DBTP_DTSEG2_Pos);
553 uint32_t dsjw = (dbt.sjw - 1u) & DSJW_FIELD_MAX;
554 uint32_t mask = FDCAN_DBTP_DSJW_Msk;
557 dbtp_new |= (dsjw << FDCAN_DBTP_DSJW_Pos);
562 dbtp_old &= ~dbtp_mask;
563 dbtp_old |= (dbtp_new & dbtp_mask);
564 can->DBTP = dbtp_old;
574 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
579 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_PASSIVE, 0);
580 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_ERROR_WARNING, 0);
581 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_BUS_OFF, 0);
582 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
583 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
584 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
585 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_COMPLETE, 0xFFFFFFFF);
593#if defined(RCC_PERIPHCLK_FDCAN)
594 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN);
595#elif defined(RCC_PERIPHCLK_FDCAN1)
596 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1);
599 static_assert(
false,
"RCC_PERIPHCLK_FDCAN is not defined by the HAL");
611 ASSERT(pack.
len <= 64u);
628 if (HAL_FDCAN_GetRxMessage(hcan_, fifo, &rx_buff_.header, rx_buff_.pack_fd.data) ==
631 if (rx_buff_.header.FDFormat == FDCAN_FD_CAN)
633 rx_buff_.pack_fd.id = rx_buff_.header.Identifier;
634 rx_buff_.pack_fd.type =
637 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
649 rx_buff_.pack_fd.len = DlcToBytes(rx_buff_.header.DataLength);
655 rx_buff_.pack.id = rx_buff_.header.Identifier;
659 uint32_t bytes = DlcToBytes(rx_buff_.header.DataLength);
665 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
675 rx_buff_.pack.dlc =
static_cast<uint8_t
>(bytes);
679 rx_buff_.pack.dlc =
static_cast<uint8_t
>(bytes);
691void STM32CANFD::TxService()
693 if (hcan_ ==
nullptr || hcan_->Instance ==
nullptr)
698 tx_pend_.store(1u, std::memory_order_release);
700 uint32_t expected = 0u;
701 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
702 std::memory_order_relaxed))
709 tx_pend_.store(0u, std::memory_order_release);
728 FDCAN_TxHeaderTypeDef hdr{};
729 BuildTxHeader(pfd, hdr);
731 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &hdr, pfd.data) != HAL_OK)
754 FDCAN_TxHeaderTypeDef hdr{};
755 BuildTxHeader(pc, hdr);
757 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &hdr, pc.data) != HAL_OK)
770 tx_lock_.store(0u, std::memory_order_release);
772 if (tx_pend_.load(std::memory_order_acquire) == 0u)
778 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
779 std::memory_order_relaxed))
788 FDCAN_ProtocolStatusTypeDef protocol_status = {};
789 HAL_FDCAN_GetProtocolStatus(hcan_, &protocol_status);
791#ifdef FDCAN_IT_BUS_OFF
792#ifdef FDCAN_CCCR_INIT
793 if ((error_status_its & FDCAN_IT_BUS_OFF) != 0u && protocol_status.BusOff != 0u)
795 CLEAR_BIT(hcan_->Instance->CCCR, FDCAN_CCCR_INIT);
806 if (protocol_status.BusOff != 0u)
808 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
810 else if (protocol_status.ErrorPassive != 0u)
812 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
814 else if (protocol_status.Warning != 0u)
816 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
820 uint32_t lec = protocol_status.LastErrorCode & 0x7u;
823 lec = protocol_status.DataLastErrorCode & 0x7u;
829 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
832 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
835 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
838 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
841 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
844 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
847 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
852 pack.
id =
static_cast<uint32_t
>(eid);
859 if (hcan_ ==
nullptr || hcan_->Instance ==
nullptr)
864 FDCAN_ErrorCountersTypeDef counters{};
865 if (HAL_FDCAN_GetErrorCounters(hcan_, &counters) != HAL_OK)
870 FDCAN_ProtocolStatusTypeDef proto{};
871 if (HAL_FDCAN_GetProtocolStatus(hcan_, &proto) != HAL_OK)
879 state.
bus_off = (proto.BusOff != 0u);
886extern "C" void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef* hcan)
888 hcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
889 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
896extern "C" void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef* hfdcan,
897 uint32_t ErrorStatusITs)
899 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hfdcan->Instance)];
902 can->ProcessErrorStatusInterrupt(ErrorStatusITs);
907extern "C" void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef* hcan,
908 uint32_t BufferIndexes)
910 UNUSED(BufferIndexes);
911 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
918extern "C" void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef* hcan)
920 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
927extern "C" void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo0ITs)
930 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
933 while (HAL_FDCAN_GetRxFifoFillLevel(hcan, FDCAN_RX_FIFO0) > 0U)
935 can->ProcessRxInterrupt(FDCAN_RX_FIFO0);
940extern "C" void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo1ITs)
943 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
946 while (HAL_FDCAN_GetRxFifoFillLevel(hcan, FDCAN_RX_FIFO1) > 0U)
948 can->ProcessRxInterrupt(FDCAN_RX_FIFO1);
@ 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).
ErrorID
ClassicPack::type == Type::ERROR 时使用的虚拟 ID。 Virtual IDs used when ClassicPack::type == Type::ERROR.
FDCAN 通信抽象类,扩展支持 CAN FD 帧。 Abstract class for FDCAN communication with CAN FD frame support.
void OnMessage(const FDPack &pack, bool in_isr)
分发接收到的 FD CAN 帧。 Dispatch a received FD CAN frame.
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
STM32 FDCAN 驱动实现 / STM32 FDCAN driver implementation.
void ProcessErrorStatusInterrupt(uint32_t error_status_its)
处理错误状态中断 / Handle error-status interrupt
SlotPool< FDPack > tx_fd_queue_
FD 发送槽池 / FD TX slot pool.
uint32_t GetClockFreq() const override
获取 FDCAN 外设时钟 / Get FDCAN kernel clock
ErrorCode Init(void)
初始化驱动 / Initialize driver
void ProcessRxInterrupt(uint32_t fifo)
处理接收中断 / Handle RX interrupt
SlotPool< ClassicPack > tx_queue_
Classic 发送槽池 / Classic TX slot pool.
STM32CANFD(FDCAN_HandleTypeDef *hcan, uint32_t queue_size)
构造 FDCAN 驱动对象 / Construct FDCAN driver object
ErrorCode GetErrorState(CAN::ErrorState &state) const override
查询当前错误状态 / Query current FDCAN error state
ErrorCode AddMessage(const ClassicPack &pack) override
添加经典 CAN 消息 / Add classic CAN message.
size_t HardwareTxQueueEmptySize()
获取硬件发送队列空闲数 / Get free level of hardware TX queue
bool tx_classic_retry_valid_
待重试 Classic 帧有效标记 / Pending Classic retry frame flag.
ErrorCode SetConfig(const CAN::Configuration &cfg) override
设置 CAN/FDCAN 配置 / Set CAN/FDCAN configuration
FDPack tx_fd_retry_pack_
待重试 FD 帧 / Pending FD retry frame.
bool tx_fd_retry_valid_
待重试 FD 帧有效标记 / Pending FD retry frame flag.
ClassicPack tx_classic_retry_pack_
待重试 Classic 帧 / Pending Classic retry frame.
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
uint32_t prop_seg
传播段 / Propagation segment.
经典 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.
float sample_point
仲裁相位采样点(0~1) / Nominal sample point (0–1).
Mode mode
工作模式 / Operating mode.
uint32_t bitrate
仲裁相位目标波特率 / Target nominal bitrate.
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).
bool triple_sampling
三采样 / Triple sampling.
bool loopback
回环模式 / Loopback mode.
bool one_shot
单次发送模式 / One-shot transmission.
bool listen_only
只听(静默)模式 / Listen-only (silent) mode.
FDCAN 配置参数,扩展 CAN::Configuration。 FDCAN configuration, extending CAN::Configuration.
FDMode fd_mode
FD 模式配置 / FD mode configuration.
DataBitTiming data_timing
数据相位位时序 / Data-phase bit timing.
uint32_t prop_seg
传播段 / Propagation segment.
CAN FD 帧数据结构 / CAN FD frame structure.
Type type
帧类型 / Frame type.
uint8_t len
数据长度(0~64) / Data length (0–64 bytes).