1#include "stm32_can.hpp"
3#ifdef HAL_CAN_MODULE_ENABLED
7STM32CAN* STM32CAN::map[STM32_CAN_NUMBER] = {
nullptr};
15stm32_can_id_t STM32_CAN_GetID(CAN_TypeDef* addr)
20 return stm32_can_id_t::STM32_CAN_ID_ERROR;
23 else if (addr == CAN1)
25 return stm32_can_id_t::STM32_CAN1;
29 else if (addr == CAN2)
31 return stm32_can_id_t::STM32_CAN2;
35 else if (addr == CAN3)
37 return stm32_can_id_t::STM32_CAN3;
42 return stm32_can_id_t::STM32_CAN_ID_ERROR;
48 :
CAN(), hcan_(hcan), id_(STM32_CAN_GetID(hcan->Instance)), tx_pool_(pool_size)
56 CAN_FilterTypeDef can_filter = {};
58 can_filter.FilterIdHigh = 0;
59 can_filter.FilterIdLow = 0;
60 can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
61 can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
62 can_filter.FilterMaskIdHigh = 0;
63 can_filter.FilterMaskIdLow = 0;
64 can_filter.FilterFIFOAssignment = fifo_;
65 can_filter.FilterActivation = ENABLE;
68 if (id_ == STM32_CAN1)
70 can_filter.FilterBank = 0;
71 can_filter.SlaveStartFilterBank = 14;
74 else if (id_ == STM32_CAN2)
76 can_filter.FilterBank = 14;
77 can_filter.SlaveStartFilterBank = 14;
80 else if (id_ == STM32_CAN3)
82 can_filter.FilterBank = 3;
87 if (id_ == STM32_CAN1)
89 can_filter.FilterBank = 0;
90 can_filter.SlaveStartFilterBank = 14;
93 else if (id_ == STM32_CAN2)
95 can_filter.FilterBank = 14;
96 can_filter.SlaveStartFilterBank = 14;
100 if (id_ == STM32_CAN1)
102 can_filter.FilterBank = 0;
103 can_filter.SlaveStartFilterBank = 14;
104 fifo_ = CAN_RX_FIFO0;
111 return ErrorCode::FAILED;
114 can_filter.FilterFIFOAssignment = fifo_;
116 if (HAL_CAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
118 return ErrorCode::FAILED;
121 if (HAL_CAN_Start(hcan_) != HAL_OK)
123 return ErrorCode::FAILED;
126 if (fifo_ == CAN_RX_FIFO0)
128 HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO0_MSG_PENDING);
132 HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO1_MSG_PENDING);
135 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR);
136 HAL_CAN_ActivateNotification(hcan_, CAN_IT_BUSOFF);
137 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR_PASSIVE);
138 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR_WARNING);
139 HAL_CAN_ActivateNotification(hcan_, CAN_IT_TX_MAILBOX_EMPTY);
141 return ErrorCode::OK;
146 if (hcan_ ==
nullptr || hcan_->Instance ==
nullptr)
149 return ErrorCode::ARG_ERR;
152 CAN_TypeDef* can = hcan_->Instance;
155 uint32_t it_mask = 0u;
157#ifdef CAN_IT_RX_FIFO0_MSG_PENDING
158 if (fifo_ == CAN_RX_FIFO0)
160 it_mask |= CAN_IT_RX_FIFO0_MSG_PENDING;
164#ifdef CAN_IT_RX_FIFO1_MSG_PENDING
165 if (fifo_ == CAN_RX_FIFO1)
167 it_mask |= CAN_IT_RX_FIFO1_MSG_PENDING;
172 it_mask |= CAN_IT_ERROR;
175#ifdef CAN_IT_TX_MAILBOX_EMPTY
176 it_mask |= CAN_IT_TX_MAILBOX_EMPTY;
181 HAL_CAN_DeactivateNotification(hcan_, it_mask);
185 if (HAL_CAN_Stop(hcan_) != HAL_OK)
187 return ErrorCode::FAILED;
194 SET_BIT(can->MCR, CAN_MCR_NART);
198 CLEAR_BIT(can->MCR, CAN_MCR_NART);
206 constexpr uint32_t BRP_FIELD_MAX =
207 (CAN_BTR_BRP_Msk >> CAN_BTR_BRP_Pos);
208 constexpr uint32_t TS1_FIELD_MAX =
209 (CAN_BTR_TS1_Msk >> CAN_BTR_TS1_Pos);
210 constexpr uint32_t TS2_FIELD_MAX =
211 (CAN_BTR_TS2_Msk >> CAN_BTR_TS2_Pos);
212 constexpr uint32_t SJW_FIELD_MAX =
213 (CAN_BTR_SJW_Msk >> CAN_BTR_SJW_Pos);
216 constexpr uint32_t BRP_MAX = BRP_FIELD_MAX + 1u;
217 constexpr uint32_t TS1_MAX = TS1_FIELD_MAX + 1u;
218 constexpr uint32_t TS2_MAX = TS2_FIELD_MAX + 1u;
219 constexpr uint32_t SJW_MAX = SJW_FIELD_MAX + 1u;
224 if (bt.brp < 1u || bt.brp > BRP_MAX)
227 return ErrorCode::ARG_ERR;
232 uint32_t tseg1 = bt.
prop_seg + bt.phase_seg1;
233 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
235 if (tseg1 < 1u || tseg1 > TS1_MAX)
238 return ErrorCode::ARG_ERR;
242 if (bt.phase_seg2 != 0u)
244 if (bt.phase_seg2 < 1u || bt.phase_seg2 > TS2_MAX)
247 return ErrorCode::ARG_ERR;
253 if (bt.sjw < 1u || bt.sjw > SJW_MAX)
256 return ErrorCode::ARG_ERR;
260 if (bt.phase_seg2 != 0u && bt.sjw > bt.phase_seg2)
263 return ErrorCode::ARG_ERR;
267 uint32_t btr_old = can->BTR;
268 uint32_t btr_new = btr_old;
269 uint32_t btr_mask = 0u;
274 uint32_t brp = (bt.brp - 1u) & BRP_FIELD_MAX;
275 uint32_t mask = CAN_BTR_BRP_Msk;
278 btr_new |= (brp << CAN_BTR_BRP_Pos);
282 if (bt.prop_seg != 0u || bt.phase_seg1 != 0u)
284 uint32_t ts1 = (tseg1 - 1u) & TS1_FIELD_MAX;
285 uint32_t mask = CAN_BTR_TS1_Msk;
288 btr_new |= (ts1 << CAN_BTR_TS1_Pos);
292 if (bt.phase_seg2 != 0u)
294 uint32_t ts2 = (bt.phase_seg2 - 1u) & TS2_FIELD_MAX;
295 uint32_t mask = CAN_BTR_TS2_Msk;
298 btr_new |= (ts2 << CAN_BTR_TS2_Pos);
304 uint32_t sjw = (bt.sjw - 1u) & SJW_FIELD_MAX;
305 uint32_t mask = CAN_BTR_SJW_Msk;
308 btr_new |= (sjw << CAN_BTR_SJW_Pos);
314 uint32_t mask = CAN_BTR_SAM;
329 uint32_t mask = CAN_BTR_LBKM;
342 uint32_t mask = CAN_BTR_SILM;
355 btr_old &= ~btr_mask;
356 btr_old |= (btr_new & btr_mask);
361 if (HAL_CAN_Start(hcan_) != HAL_OK)
363 return ErrorCode::FAILED;
369#ifdef CAN_IT_RX_FIFO0_MSG_PENDING
370 if (fifo_ == CAN_RX_FIFO0)
372 it_rx = CAN_IT_RX_FIFO0_MSG_PENDING;
376#ifdef CAN_IT_RX_FIFO1_MSG_PENDING
377 if (fifo_ == CAN_RX_FIFO1)
379 it_rx = CAN_IT_RX_FIFO1_MSG_PENDING;
385 HAL_CAN_ActivateNotification(hcan_, it_rx);
388 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR);
389 HAL_CAN_ActivateNotification(hcan_, CAN_IT_BUSOFF);
390 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR_PASSIVE);
391 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR_WARNING);
392 HAL_CAN_ActivateNotification(hcan_, CAN_IT_TX_MAILBOX_EMPTY);
394 return ErrorCode::OK;
400 return HAL_RCC_GetPCLK1Freq();
403inline void STM32CAN::BuildTxHeader(
const ClassicPack& p, CAN_TxHeaderTypeDef& h)
409 h.DLC = (p.dlc <= 8u) ? p.dlc : 8u;
410 h.IDE = IS_EXT ? CAN_ID_EXT : CAN_ID_STD;
411 h.RTR = IS_RTR ? CAN_RTR_REMOTE : CAN_RTR_DATA;
413 h.StdId = IS_EXT ? 0u : (p.id & 0x7FFu);
414 h.ExtId = IS_EXT ? (p.id & 0x1FFFFFFFu) : 0u;
416 h.TransmitGlobalTime = DISABLE;
419void STM32CAN::TxService()
421 if (hcan_ ==
nullptr || hcan_->Instance ==
nullptr)
427 tx_pend_.store(1u, std::memory_order_release);
430 uint32_t expected = 0u;
431 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
432 std::memory_order_relaxed))
438 constexpr uint32_t TME_MASK = (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2);
443 tx_pend_.store(0u, std::memory_order_release);
446 while ((hcan_->Instance->TSR & TME_MASK) != 0u)
449 if (tx_pool_.
Get(p) != ErrorCode::OK)
454 CAN_TxHeaderTypeDef hdr{};
455 BuildTxHeader(p, hdr);
457 uint32_t mailbox = 0u;
458 if (HAL_CAN_AddTxMessage(hcan_, &hdr, p.data, &mailbox) != HAL_OK)
461 (void)tx_pool_.
Put(p);
469 tx_lock_.store(0u, std::memory_order_release);
472 if (tx_pend_.load(std::memory_order_acquire) == 0u)
479 if (!tx_lock_.compare_exchange_strong(expected, 1u, std::memory_order_acquire,
480 std::memory_order_relaxed))
491 return ErrorCode::ARG_ERR;
495 if (tx_pool_.
Put(pack) != ErrorCode::OK)
497 return ErrorCode::FULL;
502 return ErrorCode::OK;
507 while (HAL_CAN_GetRxMessage(hcan_, fifo_, &rx_buff_.header, rx_buff_.pack.data) ==
510 if (rx_buff_.header.IDE == CAN_ID_STD)
512 rx_buff_.pack.id = rx_buff_.header.StdId;
517 rx_buff_.pack.id = rx_buff_.header.ExtId;
521 if (rx_buff_.header.RTR == CAN_RTR_REMOTE)
533 uint8_t dlc = (rx_buff_.header.DLC <= 8u) ? rx_buff_.header.DLC : 8u;
534 rx_buff_.pack.dlc = dlc;
542 if (hcan_ ==
nullptr || hcan_->Instance ==
nullptr)
547 uint32_t esr = hcan_->Instance->ESR;
555 if (esr & CAN_ESR_BOFF)
557 eid = CAN::ErrorID::CAN_ERROR_ID_BUS_OFF;
559 else if (esr & CAN_ESR_EPVF)
561 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE;
563 else if (esr & CAN_ESR_EWGF)
565 eid = CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING;
569 uint32_t lec = (esr >> 4) & 0x7u;
574 eid = CAN::ErrorID::CAN_ERROR_ID_STUFF;
577 eid = CAN::ErrorID::CAN_ERROR_ID_FORM;
580 eid = CAN::ErrorID::CAN_ERROR_ID_ACK;
583 eid = CAN::ErrorID::CAN_ERROR_ID_BIT1;
586 eid = CAN::ErrorID::CAN_ERROR_ID_BIT0;
589 eid = CAN::ErrorID::CAN_ERROR_ID_CRC;
592 eid = CAN::ErrorID::CAN_ERROR_ID_OTHER;
597 pack.
id =
static_cast<uint32_t
>(eid);
605 if (hcan_ ==
nullptr || hcan_->Instance ==
nullptr)
607 return ErrorCode::ARG_ERR;
611 uint32_t esr = hcan_->Instance->ESR;
618 state.
bus_off = (esr & CAN_ESR_BOFF) != 0u;
622 return ErrorCode::OK;
625extern "C" void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* hcan)
627 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
634extern "C" void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef* hcan)
636 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
643extern "C" void HAL_CAN_ErrorCallback(CAN_HandleTypeDef* hcan)
645 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
651 HAL_CAN_ResetError(hcan);
654extern "C" void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef* hcan)
656 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
663extern "C" void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef* hcan)
665 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
672extern "C" void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef* hcan)
674 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
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.
ErrorCode Put(const Data &data)
向池中放入一个元素 / Put an element into the pool
ErrorCode Get(Data &data)
从池中取出一个元素 / Retrieve an element from the pool
STM32CAN 类,用于处理 STM32 系统的 CAN 通道。 Provides handling for STM32 CAN channels.
ErrorCode GetErrorState(CAN::ErrorState &state) const override
查询当前错误状态(快照)。 Query current CAN controller error state (snapshot).
ErrorCode SetConfig(const CAN::Configuration &cfg) override
设置 CAN 配置。Set CAN configuration.
STM32CAN(CAN_HandleTypeDef *hcan, uint32_t pool_size)
STM32CAN 类,用于处理 STM32 系统的 CAN 通道。 Provides handling for STM32 CAN.
uint32_t GetClockFreq() const override
获取 CAN 外设时钟频率(Hz)。 Get CAN peripheral clock frequency in Hz.
ErrorCode AddMessage(const ClassicPack &pack) override
添加经典 CAN 消息。Add classic CAN message.
void ProcessErrorInterrupt()
处理错误中断
void ProcessRxInterrupt()
处理接收中断
uint32_t prop_seg
传播段。Propagation segment.
经典 CAN 帧数据结构。Classic CAN frame structure.
uint32_t id
CAN ID(11/29 bit 或 ErrorID)。CAN ID (11/29 bits or ErrorID).
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).
bool triple_sampling
三采样。Triple sampling.
bool loopback
回环模式。Loopback mode.
bool one_shot
单次发送模式。One-shot transmission.
bool listen_only
只听(静默)模式。Listen-only (silent) mode.