7#include "libxr_def.hpp"
10#ifdef HAL_FDCAN_MODULE_ENABLED
19#ifndef FDCAN_MESSAGE_RAM_WORDS_MAX
20#define FDCAN_MESSAGE_RAM_WORDS_MAX 2560u
38stm32_fdcan_id_t STM32_FDCAN_GetID(FDCAN_GlobalTypeDef* addr);
40template <
typename,
typename =
void>
47 T, std::void_t<decltype(std::declval<T>()->Init.TxFifoQueueElmtsNbr)>>
54typename std::enable_if<!HasTxFifoQueueElmtsNbr<T>::value, uint32_t>::type
55GetTxFifoTotalElements(T& hcan)
63typename std::enable_if<HasTxFifoQueueElmtsNbr<T>::value, uint32_t>::type
64GetTxFifoTotalElements(T& hcan)
66 return hcan->Init.TxFifoQueueElmtsNbr;
77 template <
typename,
typename =
void>
84 T, std::void_t<decltype(std::declval<T>()->Init.MessageRAMOffset)>> : std::true_type
89 typename std::enable_if<!HasMessageRAMOffset<T>::value,
void>::type
90 CheckMessageRAMOffset(T&, uint32_t = FDCAN_MESSAGE_RAM_WORDS_MAX)
95 typename std::enable_if<HasMessageRAMOffset<T>::value,
void>::type
96 CheckMessageRAMOffset(T& fdcan_handle, uint32_t max_words = FDCAN_MESSAGE_RAM_WORDS_MAX)
98 using HandleT = std::remove_reference_t<
decltype(*fdcan_handle)>;
99 using InitT =
decltype(HandleT{}.Init);
102 static const auto FDCAN_ElmtWords = [](uint32_t sz) -> uint32_t
104#if defined(FDCAN_DATA_BYTES_8)
107 case FDCAN_DATA_BYTES_8:
109 case FDCAN_DATA_BYTES_12:
111 case FDCAN_DATA_BYTES_16:
113 case FDCAN_DATA_BYTES_20:
115 case FDCAN_DATA_BYTES_24:
117 case FDCAN_DATA_BYTES_32:
119 case FDCAN_DATA_BYTES_48:
121 case FDCAN_DATA_BYTES_64:
127 static_assert(
sizeof(T) == 0,
"FDCAN_DATA_BYTES_8 is not defined by the HAL");
132 const uint32_t TX_FIFO_ELEMS =
136 const auto FDCAN_MessageRAMWords = [&](
const InitT& c) -> uint32_t
138 return c.StdFiltersNbr * 1u + c.ExtFiltersNbr * 2u +
139 c.RxFifo0ElmtsNbr * FDCAN_ElmtWords(c.RxFifo0ElmtSize) +
140 c.RxFifo1ElmtsNbr * FDCAN_ElmtWords(c.RxFifo1ElmtSize) +
141 c.RxBuffersNbr * FDCAN_ElmtWords(c.RxBufferSize) + c.TxEventsNbr * 2u +
142 (c.TxBuffersNbr + TX_FIFO_ELEMS) * FDCAN_ElmtWords(c.TxElmtSize);
150 } offset_map[STM32_FDCAN_NUMBER] = {};
152 auto id = STM32_FDCAN_GetID(fdcan_handle->Instance);
153 ASSERT(
id >= 0 &&
id < STM32_FDCAN_NUMBER);
155 offset_map[id].offset = fdcan_handle->Init.MessageRAMOffset;
156 offset_map[id].size = FDCAN_MessageRAMWords(fdcan_handle->Init);
158 const uint32_t START = offset_map[id].offset;
159 const uint32_t END = START + offset_map[id].size;
162 ASSERT(START <= max_words);
163 ASSERT(END <= max_words);
165 for (
auto& it : offset_map)
172 const uint32_t A0 = it.offset, A1 = it.offset + it.size;
173 const uint32_t B0 = START, B1 = END;
174 if (A0 < B1 && B0 < A1)
181 offset_map[id].inited =
true;
191 STM32CANFD(FDCAN_HandleTypeDef* hcan, uint32_t queue_size);
251 auto free = HAL_FDCAN_GetTxFifoFreeLevel(hcan_);
255 static inline void BuildTxHeader(
const ClassicPack& p, FDCAN_TxHeaderTypeDef& h);
256 static inline void BuildTxHeader(
const FDPack& p, FDCAN_TxHeaderTypeDef& h);
260 std::atomic<uint32_t> tx_lock_{0};
261 std::atomic<uint32_t> tx_pend_{0};
263 FDCAN_HandleTypeDef* hcan_;
265 stm32_fdcan_id_t id_;
283 FDCAN_RxHeaderTypeDef header;
290 FDCAN_TxHeaderTypeDef header;
FDCAN 通信抽象类,扩展支持 CAN FD 帧。 Abstract class for FDCAN communication with CAN FD frame support.
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.
面向任务与中断的小容量消息槽池。 Small message slot pool shared between tasks and interrupts.
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
定长槽池:任务与中断共享的小容量消息槽 / Fixed-size slot pool for small task/interrupt shared message slots.
经典 CAN 帧数据结构 / Classic CAN frame structure.
CAN FD 帧数据结构 / CAN FD frame structure.