libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_canfd.hpp
1#pragma once
2
3#include <cstdint>
4#include <type_traits>
5#include <utility>
6
7#include "libxr_def.hpp"
8#include "main.h"
9
10#ifdef HAL_FDCAN_MODULE_ENABLED
11
12#ifdef FDCAN
13#undef FDCAN
14#endif
15
16#include "can.hpp"
17#include "libxr.hpp"
18
19#ifndef FDCAN_MESSAGE_RAM_WORDS_MAX
20#define FDCAN_MESSAGE_RAM_WORDS_MAX 2560u
21#endif
22
23typedef enum : uint8_t
24{
25#ifdef FDCAN1
26 STM32_FDCAN1,
27#endif
28#ifdef FDCAN2
29 STM32_FDCAN2,
30#endif
31#ifdef FDCAN3
32 STM32_FDCAN3,
33#endif
34 STM32_FDCAN_NUMBER,
35 STM32_FDCAN_ID_ERROR
36} stm32_fdcan_id_t;
37
38stm32_fdcan_id_t STM32_FDCAN_GetID(FDCAN_GlobalTypeDef* addr); // NOLINT
39
40template <typename, typename = void>
41struct HasTxFifoQueueElmtsNbr : std::false_type
42{
43};
44
45template <typename T>
47 T, std::void_t<decltype(std::declval<T>()->Init.TxFifoQueueElmtsNbr)>>
48 : std::true_type
49{
50};
51
52// 当没有TxFifoQueueElmtsNbr成员时的处理函数
53template <typename T>
54typename std::enable_if<!HasTxFifoQueueElmtsNbr<T>::value, uint32_t>::type
55GetTxFifoTotalElements(T& hcan) // NOLINT
56{
57 UNUSED(hcan);
58 return 3;
59}
60
61// 当有TxFifoQueueElmtsNbr成员时的处理函数
62template <typename T>
63typename std::enable_if<HasTxFifoQueueElmtsNbr<T>::value, uint32_t>::type
64GetTxFifoTotalElements(T& hcan) // NOLINT
65{
66 return hcan->Init.TxFifoQueueElmtsNbr;
67}
68
69namespace LibXR
70{
76class STM32CANFD : public FDCAN
77{
78 public:
79 template <typename, typename = void>
80 struct HasMessageRAMOffset : std::false_type
81 {
82 };
83
84 template <typename T>
86 T, std::void_t<decltype(std::declval<T>()->Init.MessageRAMOffset)>> : std::true_type
87 {
88 };
89
90 template <typename T>
91 typename std::enable_if<!HasMessageRAMOffset<T>::value, void>::type
92 CheckMessageRAMOffset(T&, uint32_t = FDCAN_MESSAGE_RAM_WORDS_MAX)
93 {
94 }
95
96 template <typename T>
97 typename std::enable_if<HasMessageRAMOffset<T>::value, void>::type
98 CheckMessageRAMOffset(T& fdcan_handle, uint32_t max_words = FDCAN_MESSAGE_RAM_WORDS_MAX)
99 {
100 using HandleT = std::remove_reference_t<decltype(*fdcan_handle)>;
101 using InitT = decltype(HandleT{}.Init);
102
103 // NOLINTNEXTLINE
104 static const auto FDCAN_ElmtWords = [](uint32_t sz) -> uint32_t
105 {
106#if defined(FDCAN_DATA_BYTES_8)
107 switch (sz)
108 {
109 case FDCAN_DATA_BYTES_8:
110 return 4; // 2 words header + 2 words data(0..8B)
111 case FDCAN_DATA_BYTES_12:
112 return 5;
113 case FDCAN_DATA_BYTES_16:
114 return 6;
115 case FDCAN_DATA_BYTES_20:
116 return 7;
117 case FDCAN_DATA_BYTES_24:
118 return 8;
119 case FDCAN_DATA_BYTES_32:
120 return 10;
121 case FDCAN_DATA_BYTES_48:
122 return 14;
123 case FDCAN_DATA_BYTES_64:
124 return 18;
125 default:
126 return 4;
127 }
128#else
129 ASSERT(false);
130 return 4;
131#endif
132 };
133
134 const uint32_t TX_FIFO_ELEMS =
135 HasTxFifoQueueElmtsNbr<T>::value ? fdcan_handle->Init.TxFifoQueueElmtsNbr : 0u;
136
137 // NOLINTNEXTLINE
138 const auto FDCAN_MessageRAMWords = [&](const InitT& c) -> uint32_t
139 {
140 return c.StdFiltersNbr * 1u + c.ExtFiltersNbr * 2u +
141 c.RxFifo0ElmtsNbr * FDCAN_ElmtWords(c.RxFifo0ElmtSize) +
142 c.RxFifo1ElmtsNbr * FDCAN_ElmtWords(c.RxFifo1ElmtSize) +
143 c.RxBuffersNbr * FDCAN_ElmtWords(c.RxBufferSize) + c.TxEventsNbr * 2u +
144 (c.TxBuffersNbr + TX_FIFO_ELEMS) * FDCAN_ElmtWords(c.TxElmtSize);
145 };
146
147 static struct
148 {
149 bool inited;
150 uint32_t offset;
151 uint32_t size;
152 } offset_map[STM32_FDCAN_NUMBER] = {}; // NOLINT
153
154 auto id = STM32_FDCAN_GetID(fdcan_handle->Instance);
155 ASSERT(id >= 0 && id < STM32_FDCAN_NUMBER);
156
157 offset_map[id].offset = fdcan_handle->Init.MessageRAMOffset;
158 offset_map[id].size = FDCAN_MessageRAMWords(fdcan_handle->Init);
159
160 const uint32_t START = offset_map[id].offset;
161 const uint32_t END = START + offset_map[id].size;
162
163 /* 内存越界 */
164 ASSERT(START <= max_words);
165 ASSERT(END <= max_words);
166
167 for (auto& it : offset_map)
168 {
169 if (!it.inited)
170 {
171 continue;
172 }
173
174 const uint32_t A0 = it.offset, A1 = it.offset + it.size;
175 const uint32_t B0 = START, B1 = END;
176 if (A0 < B1 && B0 < A1)
177 {
178 /* 内存区域重叠 */
179 ASSERT(false);
180 }
181 }
182
183 offset_map[id].inited = true;
184 }
185
193 STM32CANFD(FDCAN_HandleTypeDef* hcan, uint32_t queue_size);
194
200 ErrorCode Init(void);
201
202 ErrorCode AddMessage(const ClassicPack& pack) override;
203
204 ErrorCode AddMessage(const FDPack& pack) override;
205
211 void ProcessRxInterrupt(uint32_t fifo);
212
217 void ProcessTxInterrupt();
218
225 {
226 auto free = HAL_FDCAN_GetTxFifoFreeLevel(hcan_);
227 return free;
228 }
229
230 FDCAN_HandleTypeDef* hcan_;
231
232 stm32_fdcan_id_t id_;
234 LockFreePool<FDPack> tx_pool_fd_;
235
236 static STM32CANFD* map[STM32_FDCAN_NUMBER]; // NOLINT
237
238 struct
239 {
240 FDCAN_RxHeaderTypeDef header;
241 ClassicPack pack;
242 FDPack pack_fd;
243 } rx_buff_;
244
245 struct
246 {
247 FDCAN_TxHeaderTypeDef header;
248 ClassicPack pack;
249 FDPack pack_fd;
250 } tx_buff_;
251
252 uint32_t txMailbox;
253};
254} // namespace LibXR
255
256#endif
FDCAN 通信接口,扩展 CAN 功能,支持灵活数据速率(FD)CAN 消息 (FDCAN communication interface that extends CAN functionality...
Definition can.hpp:95
无锁无序槽池 / Lock-free, unordered slot pool
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).
size_t HardwareTxQueueEmptySize()
获取硬件发送队列空闲大小
void ProcessTxInterrupt()
处理发送中断
LibXR 命名空间
Definition ch32_gpio.hpp:9