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)
117 id_(STM32_FDCAN_GetID(hcan->Instance)),
118 tx_pool_(queue_size),
119 tx_pool_fd_(queue_size)
121 CheckMessageRAMOffset(hcan);
128 FDCAN_FilterTypeDef can_filter = {};
129 can_filter.IdType = FDCAN_STANDARD_ID;
130 can_filter.FilterType = FDCAN_FILTER_MASK;
131 can_filter.FilterID1 = 0x0000;
132 can_filter.FilterID2 = 0x0000;
133 can_filter.FilterIndex = 0;
136 if (id_ == STM32_FDCAN1)
138 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
140 else if (id_ == STM32_FDCAN2)
142 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
144 else if (id_ == STM32_FDCAN3)
146 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
150 if (id_ == STM32_FDCAN1)
152 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
154 else if (id_ == STM32_FDCAN2)
156 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
159 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
163 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
165 return ErrorCode::FAILED;
168 can_filter.IdType = FDCAN_EXTENDED_ID;
170 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
172 return ErrorCode::FAILED;
175 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
177 return ErrorCode::FAILED;
180 if (can_filter.FilterConfig == FDCAN_FILTER_TO_RXFIFO0)
182 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
186 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
189 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
191 return ErrorCode::OK;
196 FDCAN_TxHeaderTypeDef header;
198 header.Identifier = pack.id;
203 ASSERT(pack.id <= 0x7FF);
204 header.IdType = FDCAN_STANDARD_ID;
205 header.TxFrameType = FDCAN_DATA_FRAME;
209 ASSERT(pack.id <= 0x1FFFFFFF);
210 header.IdType = FDCAN_EXTENDED_ID;
211 header.TxFrameType = FDCAN_DATA_FRAME;
215 ASSERT(pack.id <= 0x7FF);
216 header.IdType = FDCAN_STANDARD_ID;
217 header.TxFrameType = FDCAN_REMOTE_FRAME;
221 ASSERT(pack.id <= 0x1FFFFFFF);
222 header.IdType = FDCAN_EXTENDED_ID;
223 header.TxFrameType = FDCAN_REMOTE_FRAME;
227 return ErrorCode::FAILED;
230 header.DataLength = FDCAN_DLC_BYTES_8;
231 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
232 header.BitRateSwitch = FDCAN_BRS_OFF;
233 header.FDFormat = FDCAN_CLASSIC_CAN;
234 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
235 header.MessageMarker = 0x01;
241 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
243 if (tx_pool_.
Put(pack, slot) != ErrorCode::OK)
245 return ErrorCode::FAILED;
250 return ErrorCode::OK;
259 return ErrorCode::OK;
266 FDCAN_TxHeaderTypeDef header;
267 ASSERT(pack.len <= 64);
269 header.Identifier = pack.id;
274 ASSERT(pack.id <= 0x7FF);
275 header.IdType = FDCAN_STANDARD_ID;
276 header.TxFrameType = FDCAN_DATA_FRAME;
280 ASSERT(pack.id <= 0x1FFFFFFF);
281 header.IdType = FDCAN_EXTENDED_ID;
282 header.TxFrameType = FDCAN_DATA_FRAME;
289 return ErrorCode::FAILED;
292 header.DataLength = BytesToDlc(pack.len);
294 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
295 header.BitRateSwitch = FDCAN_BRS_ON;
296 header.FDFormat = FDCAN_FD_CAN;
297 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
298 header.MessageMarker = 0x00;
304 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
306 if (tx_pool_fd_.
Put(pack, slot) != ErrorCode::OK)
308 return ErrorCode::FAILED;
313 return ErrorCode::OK;
322 return ErrorCode::OK;
329 if (HAL_FDCAN_GetRxMessage(hcan_, fifo, &rx_buff_.header, rx_buff_.pack_fd.data) ==
332 if (rx_buff_.header.FDFormat == FDCAN_FD_CAN)
334 rx_buff_.pack_fd.id = rx_buff_.header.Identifier;
335 rx_buff_.pack_fd.type =
338 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
350 rx_buff_.pack_fd.len = DlcToBytes(rx_buff_.header.DataLength);
352 OnMessage(rx_buff_.pack_fd,
true);
356 rx_buff_.pack.id = rx_buff_.header.Identifier;
360 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
373 memcpy(rx_buff_.pack.data, rx_buff_.pack_fd.data, 8);
376 OnMessage(rx_buff_.pack,
true);
383 if (tx_pool_fd_.
Get(tx_buff_.pack_fd) == ErrorCode::OK)
385 tx_buff_.header.Identifier = tx_buff_.pack_fd.id;
386 switch (tx_buff_.pack_fd.type)
389 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
390 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
394 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
395 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
399 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
400 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
404 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
405 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
411 tx_buff_.header.DataLength = BytesToDlc(tx_buff_.pack_fd.len);
412 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
413 tx_buff_.header.BitRateSwitch = FDCAN_BRS_ON;
414 tx_buff_.header.FDFormat = FDCAN_FD_CAN;
415 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
416 tx_buff_.header.MessageMarker = 0x00;
418 HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack_fd.data);
420 else if (tx_pool_.
Get(tx_buff_.pack) == ErrorCode::OK)
422 tx_buff_.header.Identifier = tx_buff_.pack.id;
423 switch (tx_buff_.pack.type)
426 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
427 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
431 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
432 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
436 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
437 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
441 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
442 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
448 tx_buff_.header.DataLength = 8;
449 tx_buff_.header.FDFormat = FDCAN_CLASSIC_CAN;
450 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
451 tx_buff_.header.MessageMarker = 0x00;
452 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
453 tx_buff_.header.BitRateSwitch = FDCAN_BRS_OFF;
455 HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack.data);
459extern "C" void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef* hcan)
461 hcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
462 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
465 can->ProcessTxInterrupt();
469extern "C" void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef* hfdcan,
470 uint32_t ErrorStatusITs)
472 if ((ErrorStatusITs & FDCAN_IT_BUS_OFF) != RESET)
474 FDCAN_ProtocolStatusTypeDef protocol_status = {};
475 HAL_FDCAN_GetProtocolStatus(hfdcan, &protocol_status);
476 if (protocol_status.BusOff)
478 CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
482 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hfdcan->Instance)];
485 can->ProcessTxInterrupt();
489extern "C" void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef* hcan,
490 uint32_t BufferIndexes)
492 UNUSED(BufferIndexes);
493 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
496 can->ProcessTxInterrupt();
500extern "C" void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef* hcan)
502 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
505 can->ProcessTxInterrupt();
509extern "C" void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo0ITs)
512 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
515 can->ProcessRxInterrupt(FDCAN_RX_FIFO0);
519extern "C" void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo1ITs)
522 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
525 can->ProcessRxInterrupt(FDCAN_RX_FIFO1);
@ EXTENDED
扩展 CAN 消息 (Extended CAN message).
@ REMOTE_EXTENDED
远程扩展 CAN 消息 (Remote extended CAN message).
@ STANDARD
标准 CAN 消息 (Standard CAN message).
@ REMOTE_STANDARD
远程标准 CAN 消息 (Remote standard CAN message).
FDCAN 通信接口,扩展 CAN 功能,支持灵活数据速率(FD)CAN 消息 (FDCAN communication interface that extends CAN functionality...
ErrorCode RecycleSlot(uint32_t index)
回收指定槽位 / Recycle a slot
ErrorCode Put(const Data &data)
向池中放入一个元素 / Put an element into the pool
ErrorCode Get(Data &data)
从池中取出一个元素 / Retrieve an element from the pool
STM32CANFD 类,用于处理 STM32 系统的 CANFD 通道。 Provides handling for STM32 CANFD.
void ProcessRxInterrupt(uint32_t fifo)
处理接收中断
STM32CANFD(FDCAN_HandleTypeDef *hcan, uint32_t queue_size)
STM32CANFD 类,用于处理 STM32 系统的 CANFD 通道。 Provides handling for STM32 CANFD.
ErrorCode AddMessage(const ClassicPack &pack) override
添加 CAN 消息到系统 (Adds a CAN message to the system).
size_t HardwareTxQueueEmptySize()
获取硬件发送队列空闲大小
void ProcessTxInterrupt()
处理发送中断