20template <>
class Can<FDCAN_HandleTypeDef *> :
public CanBase {
22 Can(FDCAN_HandleTypeDef *hfdcan)
23 : hfdcan_{hfdcan}, std_rx_queues_(hfdcan_->Init.StdFiltersNbr, nullptr),
24 ext_rx_queues_(hfdcan_->Init.ExtFiltersNbr, nullptr) {
25 hal::set_fdcan_context(hfdcan_,
this);
26 HAL_FDCAN_RegisterRxFifo0Callback(
27 hfdcan_, [](FDCAN_HandleTypeDef *hfdcan, uint32_t) {
28 static FDCAN_RxHeaderTypeDef rx_header;
31 auto fdcan =
reinterpret_cast<Can *
>(hal::get_fdcan_context(hfdcan));
33 while (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header,
34 msg.
data.data()) == HAL_OK) {
35 if (rx_header.IsFilterMatchingFrame == 1) {
38 if (rx_header.IdType == FDCAN_STANDARD_ID) {
39 if (rx_header.FilterIndex >= fdcan->std_rx_queues_.size()) {
43 fdcan->std_rx_queues_[rx_header.FilterIndex];
45 update_rx_message(msg, rx_header);
46 rx_queue->
push(msg, 0);
48 }
else if (rx_header.IdType == FDCAN_EXTENDED_ID) {
49 if (rx_header.FilterIndex >= fdcan->ext_rx_queues_.size()) {
53 fdcan->ext_rx_queues_[rx_header.FilterIndex];
55 update_rx_message(msg, rx_header);
56 rx_queue->
push(msg, 0);
64 HAL_FDCAN_UnRegisterRxFifo0Callback(hfdcan_);
65 hal::set_fdcan_context(hfdcan_,
nullptr);
69 if (HAL_FDCAN_ConfigGlobalFilter(hfdcan_, FDCAN_REJECT, FDCAN_REJECT,
71 FDCAN_REJECT_REMOTE) != HAL_OK) {
74 if (HAL_FDCAN_ActivateNotification(hfdcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
78 return HAL_FDCAN_Start(hfdcan_) == HAL_OK;
82 if (HAL_FDCAN_Stop(hfdcan_) != HAL_OK) {
85 return HAL_FDCAN_DeactivateNotification(
86 hfdcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE) == HAL_OK;
90 FDCAN_TxHeaderTypeDef tx_header = create_tx_header(msg);
92 while (HAL_FDCAN_AddMessageToTxFifoQ(hfdcan_, &tx_header,
93 msg.
data.data()) != HAL_OK) {
105 size_t rx_queue_index = find_ext_rx_queue_index(
nullptr);
106 if (rx_queue_index >= ext_rx_queues_.size()) {
109 FDCAN_FilterTypeDef filter_config =
110 create_filter_config(filter, rx_queue_index);
111 if (HAL_FDCAN_ConfigFilter(hfdcan_, &filter_config) != HAL_OK) {
114 ext_rx_queues_[rx_queue_index] = &queue;
116 size_t rx_queue_index = find_std_rx_queue_index(
nullptr);
117 if (rx_queue_index >= std_rx_queues_.size()) {
120 FDCAN_FilterTypeDef filter_config =
121 create_filter_config(filter, rx_queue_index);
122 if (HAL_FDCAN_ConfigFilter(hfdcan_, &filter_config) != HAL_OK) {
125 std_rx_queues_[rx_queue_index] = &queue;
131 size_t rx_queue_index = find_std_rx_queue_index(&queue);
132 if (rx_queue_index < std_rx_queues_.size()) {
133 FDCAN_FilterTypeDef filter_config{};
134 filter_config.FilterIndex = rx_queue_index;
135 filter_config.FilterConfig = FDCAN_FILTER_DISABLE;
136 if (HAL_FDCAN_ConfigFilter(hfdcan_, &filter_config) != HAL_OK) {
139 std_rx_queues_[rx_queue_index] =
nullptr;
141 rx_queue_index = find_ext_rx_queue_index(&queue);
142 if (rx_queue_index >= ext_rx_queues_.size()) {
145 FDCAN_FilterTypeDef filter_config{};
146 filter_config.FilterIndex = rx_queue_index;
147 filter_config.FilterConfig = FDCAN_FILTER_DISABLE;
148 if (HAL_FDCAN_ConfigFilter(hfdcan_, &filter_config) != HAL_OK) {
151 ext_rx_queues_[rx_queue_index] =
nullptr;
157 FDCAN_HandleTypeDef *hfdcan_;
158 std::vector<core::Queue<CanMessage> *> std_rx_queues_{};
159 std::vector<core::Queue<CanMessage> *> ext_rx_queues_{};
161 Can(
const Can &) =
delete;
162 Can &operator=(
const Can &) =
delete;
164 size_t find_std_rx_queue_index(
const core::Queue<CanMessage> *queue) {
165 return std::distance(
166 std_rx_queues_.begin(),
167 std::find(std_rx_queues_.begin(), std_rx_queues_.end(), queue));
170 size_t find_ext_rx_queue_index(
const core::Queue<CanMessage> *queue) {
171 return std::distance(
172 ext_rx_queues_.begin(),
173 std::find(ext_rx_queues_.begin(), ext_rx_queues_.end(), queue));
176 static inline FDCAN_FilterTypeDef
177 create_filter_config(
const CanFilter &filter, uint32_t filter_index) {
178 FDCAN_FilterTypeDef filter_config{};
180 filter_config.IdType = FDCAN_EXTENDED_ID;
182 filter_config.IdType = FDCAN_STANDARD_ID;
184 filter_config.FilterIndex = filter_index;
185 filter_config.FilterType = FDCAN_FILTER_MASK;
186 filter_config.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
187 filter_config.FilterID1 = filter.id;
188 filter_config.FilterID2 = filter.mask;
189 return filter_config;
192 static inline FDCAN_TxHeaderTypeDef create_tx_header(
const CanMessage &msg) {
193 FDCAN_TxHeaderTypeDef tx_header{};
194 tx_header.Identifier = msg.id;
196 tx_header.IdType = FDCAN_EXTENDED_ID;
198 tx_header.IdType = FDCAN_STANDARD_ID;
200 tx_header.TxFrameType = FDCAN_DATA_FRAME;
203 tx_header.DataLength = FDCAN_DLC_BYTES_0;
206 tx_header.DataLength = FDCAN_DLC_BYTES_1;
209 tx_header.DataLength = FDCAN_DLC_BYTES_2;
212 tx_header.DataLength = FDCAN_DLC_BYTES_3;
215 tx_header.DataLength = FDCAN_DLC_BYTES_4;
218 tx_header.DataLength = FDCAN_DLC_BYTES_5;
221 tx_header.DataLength = FDCAN_DLC_BYTES_6;
224 tx_header.DataLength = FDCAN_DLC_BYTES_7;
227 tx_header.DataLength = FDCAN_DLC_BYTES_8;
230 tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
231 tx_header.BitRateSwitch = FDCAN_BRS_OFF;
232 tx_header.FDFormat = FDCAN_CLASSIC_CAN;
233 tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
234 tx_header.MessageMarker = 0;
238 static inline void update_rx_message(
CanMessage &msg,
239 const FDCAN_RxHeaderTypeDef &rx_header) {
240 msg.id = rx_header.Identifier;
241 if (rx_header.IdType == FDCAN_STANDARD_ID) {
243 }
else if (rx_header.IdType == FDCAN_EXTENDED_ID) {
246 switch (rx_header.DataLength) {
247 case FDCAN_DLC_BYTES_0:
250 case FDCAN_DLC_BYTES_1:
253 case FDCAN_DLC_BYTES_2:
256 case FDCAN_DLC_BYTES_3:
259 case FDCAN_DLC_BYTES_4:
262 case FDCAN_DLC_BYTES_5:
265 case FDCAN_DLC_BYTES_6:
268 case FDCAN_DLC_BYTES_7:
271 case FDCAN_DLC_BYTES_8: