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:
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;
190 STM32CANFD(FDCAN_HandleTypeDef* hcan, uint32_t queue_size);
197 ErrorCode
Init(
void);
205 ErrorCode
SetConfig(
const CAN::Configuration& cfg)
override;
213 ErrorCode
SetConfig(
const FDCAN::Configuration& cfg)
override;
220 ErrorCode
AddMessage(
const ClassicPack& pack)
override;
222 ErrorCode
AddMessage(
const FDPack& pack)
override;
227 ErrorCode
GetErrorState(CAN::ErrorState& state)
const override;
250 auto free = HAL_FDCAN_GetTxFifoFreeLevel(hcan_);
254 static inline void BuildTxHeader(
const ClassicPack& p, FDCAN_TxHeaderTypeDef& h);
255 static inline void BuildTxHeader(
const FDPack& p, FDCAN_TxHeaderTypeDef& h);
259 std::atomic<uint32_t> tx_lock_{0};
260 std::atomic<uint32_t> tx_pend_{0};
262 FDCAN_HandleTypeDef* hcan_;
264 stm32_fdcan_id_t id_;
265 LockFreePool<ClassicPack> tx_pool_;
266 LockFreePool<FDPack> tx_pool_fd_;
272 FDCAN_RxHeaderTypeDef header;
279 FDCAN_TxHeaderTypeDef header;