libxr 1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_canfd.hpp
1#pragma once
2
3#include "main.h"
4
5#ifdef HAL_FDCAN_MODULE_ENABLED
6
7#ifdef FDCAN
8#undef FDCAN
9#endif
10
11#include "can.hpp"
12#include "libxr.hpp"
13
14typedef enum
15{
16#ifdef FDCAN1
17 STM32_FDCAN1,
18#endif
19#ifdef FDCAN2
20 STM32_FDCAN2,
21#endif
22#ifdef FDCAN3
23 STM32_FDCAN3,
24#endif
25 STM32_FDCAN_NUMBER,
26 STM32_FDCAN_ID_ERROR
27} stm32_fdcan_id_t;
28
29stm32_fdcan_id_t STM32_FDCAN_GetID(FDCAN_GlobalTypeDef* addr); // NOLINT
30
31namespace LibXR
32{
38class STM32CANFD : public FDCAN
39{
40 public:
49 STM32CANFD(FDCAN_HandleTypeDef* hcan, const char* tp_name, uint32_t queue_size)
50 : FDCAN(tp_name),
51 hcan_(hcan),
52 id_(STM32_FDCAN_GetID(hcan->Instance)),
53 tx_queue_(queue_size),
54 tx_queue_fd_(queue_size)
55 {
56 map[id_] = this;
57 Init();
58 }
59
65 ErrorCode Init(void)
66 {
67 FDCAN_FilterTypeDef can_filter = {};
68 can_filter.IdType = FDCAN_STANDARD_ID;
69 can_filter.FilterType = FDCAN_FILTER_MASK;
70 can_filter.FilterID1 = 0x0000;
71 can_filter.FilterID2 = 0x0000;
72
73#ifdef FDCAN3
74 if (id_ == STM32_FDCAN1)
75 {
76 can_filter.FilterConfig = FDCAN_RX_FIFO0;
77 can_filter.FilterIndex = 0;
78 }
79 else if (id_ == STM32_FDCAN2)
80 {
81 can_filter.FilterConfig = FDCAN_RX_FIFO0;
82 can_filter.FilterIndex = 1;
83 }
84 else if (id_ == STM32_FDCAN3)
85 {
86 can_filter.FilterConfig = FDCAN_RX_FIFO1;
87 can_filter.FilterIndex = 2;
88 }
89#else
90#ifdef FDCAN2
91 if (id_ == STM32_FDCAN1)
92 {
93 can_filter.FilterConfig = FDCAN_RX_FIFO0;
94 can_filter.FilterIndex = 0;
95 }
96 else if (id_ == STM32_FDCAN2)
97 {
98 can_filter.FilterConfig = FDCAN_RX_FIFO1;
99 can_filter.FilterIndex = 1;
100 }
101#else
102 can_filter.FilterConfig = FDCAN_RX_FIFO0;
103 can_filter.FilterIndex = 0;
104#endif
105#endif
106
107 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
108 {
109 return ErrorCode::FAILED;
110 }
111
112 can_filter.IdType = FDCAN_EXTENDED_ID;
113
114 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
115 {
116 return ErrorCode::FAILED;
117 }
118
119 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
120 {
121 return ErrorCode::FAILED;
122 }
123
124 if (can_filter.FilterConfig == FDCAN_RX_FIFO0)
125 {
126 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
127 }
128 else
129 {
130 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
131 }
132
133 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
134
135 return ErrorCode::OK;
136 }
137
138 ErrorCode AddMessage(const ClassicPack& pack) override
139 {
140 FDCAN_TxHeaderTypeDef header; // NOLINT
141
142 header.Identifier = pack.id;
143
144 switch (pack.type)
145 {
146 case Type::STANDARD:
147 header.IdType = FDCAN_STANDARD_ID;
148 header.TxFrameType = FDCAN_DATA_FRAME;
149 break;
150
151 case Type::EXTENDED:
152 header.IdType = FDCAN_EXTENDED_ID;
153 header.TxFrameType = FDCAN_DATA_FRAME;
154 break;
155
157 header.IdType = FDCAN_STANDARD_ID;
158 header.TxFrameType = FDCAN_REMOTE_FRAME;
159 break;
160
162 header.IdType = FDCAN_EXTENDED_ID;
163 header.TxFrameType = FDCAN_REMOTE_FRAME;
164 break;
165 }
166
167 header.DataLength = FDCAN_DLC_BYTES_8;
168 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
169 header.BitRateSwitch = FDCAN_BRS_OFF;
170 header.FDFormat = FDCAN_CLASSIC_CAN;
171 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
172 header.MessageMarker = 0x01;
173
174 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
175 {
176 if (tx_queue_.Push(pack) != ErrorCode::OK)
177 {
178 return ErrorCode::FAILED;
179 }
180 }
181
182 return ErrorCode::OK;
183 }
184
185 static constexpr uint32_t FDCAN_PACK_LEN_MAP[16] = {
186 FDCAN_DLC_BYTES_0, FDCAN_DLC_BYTES_1, FDCAN_DLC_BYTES_2, FDCAN_DLC_BYTES_3,
187 FDCAN_DLC_BYTES_4, FDCAN_DLC_BYTES_5, FDCAN_DLC_BYTES_6, FDCAN_DLC_BYTES_7,
188 FDCAN_DLC_BYTES_8, FDCAN_DLC_BYTES_12, FDCAN_DLC_BYTES_16, FDCAN_DLC_BYTES_20,
189 FDCAN_DLC_BYTES_24, FDCAN_DLC_BYTES_32, FDCAN_DLC_BYTES_48, FDCAN_DLC_BYTES_64,
190 };
191
192 static constexpr uint32_t FDCAN_PACK_LEN_TO_INT_MAP[16] = {
193 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64,
194 };
195
196 ErrorCode AddMessage(const FDPack& pack) override
197 {
198 FDCAN_TxHeaderTypeDef header;
199 ASSERT(pack.len <= 64);
200
201 header.Identifier = pack.id;
202
203 switch (pack.type)
204 {
205 case Type::STANDARD:
206 header.IdType = FDCAN_STANDARD_ID;
207 header.TxFrameType = FDCAN_DATA_FRAME;
208 break;
209
210 case Type::EXTENDED:
211 header.IdType = FDCAN_EXTENDED_ID;
212 header.TxFrameType = FDCAN_DATA_FRAME;
213 break;
214
216 header.IdType = FDCAN_STANDARD_ID;
217 header.TxFrameType = FDCAN_REMOTE_FRAME;
218 break;
219
221 header.IdType = FDCAN_EXTENDED_ID;
222 header.TxFrameType = FDCAN_REMOTE_FRAME;
223 break;
224 }
225
226 if (pack.len <= 8)
227 {
228 header.DataLength = FDCAN_PACK_LEN_MAP[pack.len];
229 }
230 else if (pack.len <= 24)
231 {
232 header.DataLength = FDCAN_PACK_LEN_MAP[(pack.len - 9) / 4 + 1 + 8];
233 }
234 else if (pack.len < 32)
235 {
236 header.DataLength = FDCAN_DLC_BYTES_32;
237 }
238 else if (pack.len < 48)
239 {
240 header.DataLength = FDCAN_DLC_BYTES_48;
241 }
242 else
243 {
244 header.DataLength = FDCAN_DLC_BYTES_64;
245 }
246
247 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
248 header.BitRateSwitch = FDCAN_BRS_ON;
249 header.FDFormat = FDCAN_FD_CAN;
250 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
251 header.MessageMarker = 0x00;
252
253 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
254 {
255 if (tx_queue_fd_.Push(pack) != ErrorCode::OK)
256 {
257 return ErrorCode::FAILED;
258 }
259 }
260
261 return ErrorCode::OK;
262 }
263
269 void ProcessRxInterrupt(uint32_t fifo)
270 {
271 if (HAL_FDCAN_GetRxMessage(hcan_, fifo, &rx_buff_.header, rx_buff_.pack_fd.data) ==
272 HAL_OK)
273 {
274 if (rx_buff_.header.FDFormat == FDCAN_FD_CAN)
275 {
276 rx_buff_.pack_fd.id = rx_buff_.header.Identifier;
277 rx_buff_.pack_fd.type = (rx_buff_.header.IdType == FDCAN_EXTENDED_ID)
280
281 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
282 {
283 if (rx_buff_.pack_fd.type == Type::STANDARD)
284 {
285 rx_buff_.pack_fd.type = Type::REMOTE_STANDARD;
286 }
287 else
288 {
289 rx_buff_.pack_fd.type = Type::REMOTE_EXTENDED;
290 }
291 }
292
293 rx_buff_.pack_fd.len = rx_buff_.header.DataLength;
294
295 for (uint32_t i = 0; i < 16; i++)
296 {
297 if (rx_buff_.pack_fd.len == FDCAN_PACK_LEN_MAP[i])
298 {
299 rx_buff_.pack_fd.len = FDCAN_PACK_LEN_TO_INT_MAP[i];
300 break;
301 }
302 }
303
304 fd_tp_.PublishFromCallback(rx_buff_.pack_fd, true);
305 }
306 else
307 {
308 rx_buff_.pack.id = rx_buff_.header.Identifier;
309 rx_buff_.pack.type = (rx_buff_.header.IdType == FDCAN_EXTENDED_ID)
312
313 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
314 {
315 if (rx_buff_.pack.type == Type::STANDARD)
316 {
317 rx_buff_.pack.type = Type::REMOTE_STANDARD;
318 }
319 else
320 {
321 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
322 }
323 }
324
325 memcpy(rx_buff_.pack.data, rx_buff_.pack_fd.data, 8);
326
327 classic_tp_.PublishFromCallback(rx_buff_.pack, true);
328 }
329 }
330 }
331
337 {
338 if (tx_queue_fd_.Peek(tx_buff_.pack_fd) == ErrorCode::OK)
339 {
340 tx_buff_.header.Identifier = tx_buff_.pack_fd.id;
341 switch (tx_buff_.pack_fd.type)
342 {
343 case Type::STANDARD:
344 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
345 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
346 break;
347
348 case Type::EXTENDED:
349 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
350 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
351 break;
352
354 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
355 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
356 break;
357
359 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
360 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
361 break;
362 }
363 tx_buff_.header.DataLength = tx_buff_.pack_fd.len;
364 tx_buff_.header.FDFormat = FDCAN_FD_CAN;
365 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
366 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
367 tx_buff_.header.MessageMarker = 0x00;
368 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
369 tx_buff_.header.BitRateSwitch = FDCAN_BRS_ON;
370
371 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack_fd.data) ==
372 HAL_OK)
373 {
374 tx_queue_fd_.Pop();
375 }
376 }
377 else if (tx_queue_.Peek(tx_buff_.pack) == ErrorCode::OK)
378 {
379 tx_buff_.header.Identifier = tx_buff_.pack.id;
380 switch (tx_buff_.pack.type)
381 {
382 case Type::STANDARD:
383 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
384 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
385 break;
386
387 case Type::EXTENDED:
388 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
389 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
390 break;
391
393 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
394 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
395 break;
396
398 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
399 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
400 break;
401 }
402 tx_buff_.header.DataLength = 8;
403 tx_buff_.header.FDFormat = FDCAN_CLASSIC_CAN;
404 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
405 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
406 tx_buff_.header.MessageMarker = 0x00;
407 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
408 tx_buff_.header.BitRateSwitch = FDCAN_BRS_OFF;
409
410 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack.data) ==
411 HAL_OK)
412 {
413 tx_queue_.Pop();
414 }
415 }
416 }
417
418 FDCAN_HandleTypeDef* hcan_;
419
420 stm32_fdcan_id_t id_;
422 LockFreeQueue<FDPack> tx_queue_fd_;
423 static STM32CANFD* map[STM32_FDCAN_NUMBER]; // NOLINT
424
425 struct
426 {
427 FDCAN_RxHeaderTypeDef header;
428 ClassicPack pack;
429 FDPack pack_fd;
430 } rx_buff_;
431
432 struct
433 {
434 FDCAN_TxHeaderTypeDef header;
435 ClassicPack pack;
436 FDPack pack_fd;
437 } tx_buff_;
438
439 uint32_t txMailbox;
440};
441} // namespace LibXR
442
443#endif
@ EXTENDED
扩展 CAN 消息 (Extended CAN message).
@ REMOTE_EXTENDED
远程扩展 CAN 消息 (Remote extended CAN message).
@ STANDARD
标准 CAN 消息 (Standard CAN message).
@ REMOTE_STANDARD
远程标准 CAN 消息 (Remote standard CAN message).
Topic classic_tp_
经典 CAN 消息的主题 (Topic for classic CAN messages).
Definition can.hpp:48
FDCAN 通信接口,扩展 CAN 功能,支持灵活数据速率(FD)CAN 消息 (FDCAN communication interface that extends CAN functionality...
Definition can.hpp:64
Topic fd_tp_
FD CAN 消息的主题 (Topic for FD CAN messages).
Definition can.hpp:99
无锁队列实现 / Lock-free queue implementation
ErrorCode Pop(ElementData &item)
从队列中弹出数据 / Pops data from the queue
ErrorCode Push(ElementData &&item)
向队列中推入数据 / Pushes data into the queue
ErrorCode Peek(Data &item)
获取队列头部数据但不弹出 / Retrieves the front data of the queue without popping
STM32CANFD 类,用于处理 STM32 系统的 CANFD 通道。 Provides handling for STM32 CANFD.
void ProcessRxInterrupt(uint32_t fifo)
处理接收中断
void ProcessTxInterrupt()
处理发送中断
ErrorCode Init(void)
初始化
ErrorCode AddMessage(const FDPack &pack) override
添加 FD CAN 消息到系统 (Adds an FD CAN message to the system).
ErrorCode AddMessage(const ClassicPack &pack) override
添加 CAN 消息到系统 (Adds a CAN message to the system).
STM32CANFD(FDCAN_HandleTypeDef *hcan, const char *tp_name, uint32_t queue_size)
STM32CANFD 类,用于处理 STM32 系统的 CANFD 通道。 Provides handling for STM32 CANFD.
void PublishFromCallback(Data &data, bool in_isr)
从回调函数发布数据 Publishes data from a callback function
Definition message.hpp:663
LibXR Color Control Library / LibXR终端颜色控制库
Definition esp_gpio.hpp:8