libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_canfd.cpp
1#include "stm32_canfd.hpp"
2
3#ifdef HAL_FDCAN_MODULE_ENABLED
4
5using namespace LibXR;
6
7STM32CANFD* STM32CANFD::map[STM32_FDCAN_NUMBER] = {nullptr};
8
15stm32_fdcan_id_t STM32_FDCAN_GetID(FDCAN_GlobalTypeDef* addr)
16{
17 if (addr == nullptr)
18 { // NOLINT
19 return stm32_fdcan_id_t::STM32_FDCAN_ID_ERROR;
20 }
21#ifdef FDCAN1
22 else if (addr == FDCAN1)
23 { // NOLINT
24 return stm32_fdcan_id_t::STM32_FDCAN1;
25 }
26#endif
27#ifdef FDCAN2
28 else if (addr == FDCAN2)
29 { // NOLINT
30 return stm32_fdcan_id_t::STM32_FDCAN2;
31 }
32#endif
33#ifdef FDCAN3
34 else if (addr == FDCAN3)
35 { // NOLINT
36 return stm32_fdcan_id_t::STM32_FDCAN3;
37 }
38#endif
39 else
40 {
41 return stm32_fdcan_id_t::STM32_FDCAN_ID_ERROR;
42 }
43}
44
45STM32CANFD::STM32CANFD(FDCAN_HandleTypeDef* hcan, uint32_t queue_size)
46 : FDCAN(),
47 hcan_(hcan),
48 id_(STM32_FDCAN_GetID(hcan->Instance)),
49 tx_queue_(queue_size),
50 tx_queue_fd_(queue_size)
51{
52 map[id_] = this;
53 Init();
54}
55
56ErrorCode STM32CANFD::Init(void)
57{
58 FDCAN_FilterTypeDef can_filter = {};
59 can_filter.IdType = FDCAN_STANDARD_ID;
60 can_filter.FilterType = FDCAN_FILTER_MASK;
61 can_filter.FilterID1 = 0x0000;
62 can_filter.FilterID2 = 0x0000;
63 can_filter.FilterIndex = 0;
64
65#ifdef FDCAN3
66 if (id_ == STM32_FDCAN1)
67 {
68 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
69 }
70 else if (id_ == STM32_FDCAN2)
71 {
72 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
73 }
74 else if (id_ == STM32_FDCAN3)
75 {
76 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
77 }
78#else
79#ifdef FDCAN2
80 if (id_ == STM32_FDCAN1)
81 {
82 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
83 }
84 else if (id_ == STM32_FDCAN2)
85 {
86 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
87 }
88#else
89 can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
90#endif
91#endif
92
93 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
94 {
95 return ErrorCode::FAILED;
96 }
97
98 can_filter.IdType = FDCAN_EXTENDED_ID;
99
100 if (HAL_FDCAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
101 {
102 return ErrorCode::FAILED;
103 }
104
105 if (HAL_FDCAN_Start(hcan_) != HAL_OK)
106 {
107 return ErrorCode::FAILED;
108 }
109
110 if (can_filter.FilterConfig == FDCAN_FILTER_TO_RXFIFO0)
111 {
112 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
113 }
114 else
115 {
116 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
117 }
118
119 HAL_FDCAN_ActivateNotification(hcan_, FDCAN_IT_TX_FIFO_EMPTY, 0);
120
121 return ErrorCode::OK;
122}
123
124ErrorCode STM32CANFD::AddMessage(const ClassicPack& pack)
125{
126 FDCAN_TxHeaderTypeDef header; // NOLINT
127
128 header.Identifier = pack.id;
129
130 switch (pack.type)
131 {
132 case Type::STANDARD:
133 ASSERT(pack.id <= 0x7FF);
134 header.IdType = FDCAN_STANDARD_ID;
135 header.TxFrameType = FDCAN_DATA_FRAME;
136 break;
137
138 case Type::EXTENDED:
139 ASSERT(pack.id <= 0x1FFFFFFF);
140 header.IdType = FDCAN_EXTENDED_ID;
141 header.TxFrameType = FDCAN_DATA_FRAME;
142 break;
143
145 ASSERT(pack.id <= 0x7FF);
146 header.IdType = FDCAN_STANDARD_ID;
147 header.TxFrameType = FDCAN_REMOTE_FRAME;
148 break;
149
151 ASSERT(pack.id <= 0x1FFFFFFF);
152 header.IdType = FDCAN_EXTENDED_ID;
153 header.TxFrameType = FDCAN_REMOTE_FRAME;
154 break;
155 default:
156 ASSERT(false);
157 return ErrorCode::FAILED;
158 }
159
160 header.DataLength = FDCAN_DLC_BYTES_8;
161 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
162 header.BitRateSwitch = FDCAN_BRS_OFF;
163 header.FDFormat = FDCAN_CLASSIC_CAN;
164 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
165 header.MessageMarker = 0x01;
166
167 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
168 {
169 Mutex::LockGuard guard(write_mutex_);
170 if (tx_queue_.Push(pack) != ErrorCode::OK)
171 {
172 return ErrorCode::FAILED;
173 }
174 }
175
176 return ErrorCode::OK;
177}
178
179ErrorCode STM32CANFD::AddMessage(const FDPack& pack)
180{
181 FDCAN_TxHeaderTypeDef header;
182 ASSERT(pack.len <= 64);
183
184 header.Identifier = pack.id;
185
186 switch (pack.type)
187 {
188 case Type::STANDARD:
189 ASSERT(pack.id <= 0x7FF);
190 header.IdType = FDCAN_STANDARD_ID;
191 header.TxFrameType = FDCAN_DATA_FRAME;
192 break;
193
194 case Type::EXTENDED:
195 ASSERT(pack.id <= 0x1FFFFFFF);
196 header.IdType = FDCAN_EXTENDED_ID;
197 header.TxFrameType = FDCAN_DATA_FRAME;
198 break;
199
202 default:
203 ASSERT(false);
204 return ErrorCode::FAILED;
205 }
206
207 if (pack.len <= 8)
208 {
209 header.DataLength = FDCAN_PACK_LEN_MAP[pack.len];
210 }
211 else if (pack.len <= 24)
212 {
213 header.DataLength = FDCAN_PACK_LEN_MAP[(pack.len - 9) / 4 + 1 + 8];
214 }
215 else if (pack.len < 32)
216 {
217 header.DataLength = FDCAN_DLC_BYTES_32;
218 }
219 else if (pack.len < 48)
220 {
221 header.DataLength = FDCAN_DLC_BYTES_48;
222 }
223 else
224 {
225 header.DataLength = FDCAN_DLC_BYTES_64;
226 }
227
228 header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
229 header.BitRateSwitch = FDCAN_BRS_ON;
230 header.FDFormat = FDCAN_FD_CAN;
231 header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
232 header.MessageMarker = 0x00;
233
234 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &header, pack.data) != HAL_OK)
235 {
236 Mutex::LockGuard guard(write_mutex_fd_);
237 if (tx_queue_fd_.Push(pack) != ErrorCode::OK)
238 {
239 return ErrorCode::FAILED;
240 }
241 }
242
243 return ErrorCode::OK;
244}
245
247{
248 if (HAL_FDCAN_GetRxMessage(hcan_, fifo, &rx_buff_.header, rx_buff_.pack_fd.data) ==
249 HAL_OK)
250 {
251 if (rx_buff_.header.FDFormat == FDCAN_FD_CAN)
252 {
253 rx_buff_.pack_fd.id = rx_buff_.header.Identifier;
254 rx_buff_.pack_fd.type =
255 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
256
257 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
258 {
259 if (rx_buff_.pack_fd.type == Type::STANDARD)
260 {
261 rx_buff_.pack_fd.type = Type::REMOTE_STANDARD;
262 }
263 else
264 {
265 rx_buff_.pack_fd.type = Type::REMOTE_EXTENDED;
266 }
267 }
268
269 rx_buff_.pack_fd.len = rx_buff_.header.DataLength;
270
271 for (uint32_t i = 0; i < 16; i++)
272 {
273 if (rx_buff_.pack_fd.len == FDCAN_PACK_LEN_MAP[i])
274 {
275 rx_buff_.pack_fd.len = FDCAN_PACK_LEN_TO_INT_MAP[i];
276 break;
277 }
278 }
279
280 OnMessage(rx_buff_.pack_fd, true);
281 }
282 else
283 {
284 rx_buff_.pack.id = rx_buff_.header.Identifier;
285 rx_buff_.pack.type =
286 (rx_buff_.header.IdType == FDCAN_EXTENDED_ID) ? Type::EXTENDED : Type::STANDARD;
287
288 if (rx_buff_.header.RxFrameType != FDCAN_DATA_FRAME)
289 {
290 if (rx_buff_.pack.type == Type::STANDARD)
291 {
292 rx_buff_.pack.type = Type::REMOTE_STANDARD;
293 }
294 else
295 {
296 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
297 }
298 }
299 else
300 {
301 memcpy(rx_buff_.pack.data, rx_buff_.pack_fd.data, 8);
302 }
303
304 OnMessage(rx_buff_.pack, true);
305 }
306 }
307}
308
310{
311 if (tx_queue_fd_.Peek(tx_buff_.pack_fd) == ErrorCode::OK)
312 {
313 tx_buff_.header.Identifier = tx_buff_.pack_fd.id;
314 switch (tx_buff_.pack_fd.type)
315 {
316 case Type::STANDARD:
317 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
318 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
319 break;
320
321 case Type::EXTENDED:
322 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
323 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
324 break;
325
327 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
328 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
329 break;
330
332 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
333 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
334 break;
335 default:
336 ASSERT(false);
337 return;
338 }
339 tx_buff_.header.DataLength = tx_buff_.pack_fd.len;
340 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
341 tx_buff_.header.BitRateSwitch = FDCAN_BRS_ON;
342 tx_buff_.header.FDFormat = FDCAN_FD_CAN;
343 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
344 tx_buff_.header.MessageMarker = 0x00;
345
346 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack_fd.data) ==
347 HAL_OK)
348 {
349 tx_queue_fd_.Pop();
350 }
351 }
352 else if (tx_queue_.Peek(tx_buff_.pack) == ErrorCode::OK)
353 {
354 tx_buff_.header.Identifier = tx_buff_.pack.id;
355 switch (tx_buff_.pack.type)
356 {
357 case Type::STANDARD:
358 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
359 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
360 break;
361
362 case Type::EXTENDED:
363 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
364 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
365 break;
366
368 tx_buff_.header.IdType = FDCAN_STANDARD_ID;
369 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
370 break;
371
373 tx_buff_.header.IdType = FDCAN_EXTENDED_ID;
374 tx_buff_.header.TxFrameType = FDCAN_REMOTE_FRAME;
375 break;
376 default:
377 ASSERT(false);
378 return;
379 }
380 tx_buff_.header.DataLength = 8;
381 tx_buff_.header.FDFormat = FDCAN_CLASSIC_CAN;
382 tx_buff_.header.TxFrameType = FDCAN_DATA_FRAME;
383 tx_buff_.header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
384 tx_buff_.header.MessageMarker = 0x00;
385 tx_buff_.header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
386 tx_buff_.header.BitRateSwitch = FDCAN_BRS_OFF;
387
388 if (HAL_FDCAN_AddMessageToTxFifoQ(hcan_, &tx_buff_.header, tx_buff_.pack.data) ==
389 HAL_OK)
390 {
391 tx_queue_.Pop();
392 }
393 }
394}
395
396extern "C" void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef* hcan)
397{
398 hcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
399 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
400 if (can)
401 {
402 can->ProcessTxInterrupt();
403 }
404}
405
406extern "C" void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef* hfdcan,
407 uint32_t ErrorStatusITs)
408{
409 if ((ErrorStatusITs & FDCAN_IT_BUS_OFF) != RESET)
410 {
411 FDCAN_ProtocolStatusTypeDef protocol_status = {};
412 HAL_FDCAN_GetProtocolStatus(hfdcan, &protocol_status);
413 if (protocol_status.BusOff)
414 {
415 CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
416 }
417 }
418
419 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hfdcan->Instance)];
420 if (can)
421 {
422 can->ProcessTxInterrupt();
423 }
424}
425
426extern "C" void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef* hcan,
427 uint32_t BufferIndexes)
428{
429 UNUSED(BufferIndexes);
430 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
431 if (can)
432 {
433 can->ProcessTxInterrupt();
434 }
435}
436
437extern "C" void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef* hcan)
438{
439 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
440 if (can)
441 {
442 can->ProcessTxInterrupt();
443 }
444}
445
446extern "C" void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo0ITs)
447{
448 UNUSED(RxFifo0ITs);
449 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
450 if (can)
451 {
452 can->ProcessRxInterrupt(FDCAN_RX_FIFO0);
453 }
454}
455
456extern "C" void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo1ITs)
457{
458 UNUSED(RxFifo1ITs);
459 auto can = STM32CANFD::map[STM32_FDCAN_GetID(hcan->Instance)];
460 if (can)
461 {
462 can->ProcessRxInterrupt(FDCAN_RX_FIFO1);
463 }
464}
465
466#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).
FDCAN 通信接口,扩展 CAN 功能,支持灵活数据速率(FD)CAN 消息 (FDCAN communication interface that extends CAN functionality...
Definition can.hpp:95
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
互斥锁的 RAII 机制封装 (RAII-style mechanism for automatic mutex management).
Definition mutex.hpp:65
STM32CANFD 类,用于处理 STM32 系统的 CANFD 通道。 Provides handling for STM32 CANFD.
ErrorCode Init(void)
初始化
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).
void ProcessTxInterrupt()
处理发送中断
LibXR 命名空间
Definition ch32_gpio.hpp:9