libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_can.hpp
1#pragma once
2
3#include "main.h"
4
5#ifdef HAL_CAN_MODULE_ENABLED
6
7#ifdef CAN
8#undef CAN
9#endif
10
11#include "can.hpp"
12#include "libxr.hpp"
13
14typedef enum
15{
16#ifdef CAN1
17 STM32_CAN1,
18#endif
19#ifdef CAN2
20 STM32_CAN2,
21#endif
22#ifdef CAN3
23 STM32_CAN3,
24#endif
25 STM32_CAN_NUMBER,
26 STM32_CAN_ID_ERROR
27} stm32_can_id_t;
28
29stm32_can_id_t STM32_CAN_GetID(CAN_TypeDef* addr); // NOLINT
30
31namespace LibXR
32{
38class STM32CAN : public CAN
39{
40 public:
47 STM32CAN(CAN_HandleTypeDef* hcan, uint32_t queue_size)
48 : CAN(), hcan_(hcan), id_(STM32_CAN_GetID(hcan->Instance)), tx_queue_(queue_size)
49 {
50 map[id_] = this;
51 Init();
52 }
53
59 ErrorCode Init(void)
60 {
61 CAN_FilterTypeDef can_filter = {};
62
63 can_filter.FilterIdHigh = 0;
64 can_filter.FilterIdLow = 0;
65 can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
66 can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
67 can_filter.FilterMaskIdHigh = 0;
68 can_filter.FilterMaskIdLow = 0;
69 can_filter.FilterFIFOAssignment = fifo_;
70 can_filter.FilterActivation = ENABLE;
71#ifdef CAN3
72 if (id_ == STM32_CAN1)
73 {
74 can_filter.FilterBank = 0;
75 can_filter.SlaveStartFilterBank = 14;
76 fifo_ = CAN_RX_FIFO0;
77 }
78 else if (id_ == STM32_CAN2)
79 {
80 can_filter.FilterBank = 14;
81 can_filter.SlaveStartFilterBank = 14;
82 fifo_ = CAN_RX_FIFO0;
83 }
84 else if (id_ == STM32_CAN3)
85 {
86 can_filter.FilterBank = 3;
87 fifo_ = CAN_RX_FIFO1;
88 }
89#else
90#ifdef CAN2
91 if (id_ == STM32_CAN1)
92 {
93 can_filter.FilterBank = 0;
94 can_filter.SlaveStartFilterBank = 14;
95 fifo_ = CAN_RX_FIFO0;
96 }
97 else if (id_ == STM32_CAN2)
98 {
99 can_filter.FilterBank = 14;
100 can_filter.SlaveStartFilterBank = 14;
101 fifo_ = CAN_RX_FIFO1;
102 }
103#else
104 if (id_ == STM32_CAN1)
105 {
106 can_filter.FilterBank = 0;
107 can_filter.SlaveStartFilterBank = 14;
108 fifo_ = CAN_RX_FIFO0;
109 }
110#endif
111#endif
112 else
113 {
114 ASSERT(false);
115 return ErrorCode::FAILED;
116 }
117 can_filter.FilterFIFOAssignment = fifo_;
118
119 if (HAL_CAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
120 {
121 return ErrorCode::FAILED;
122 }
123
124 if (HAL_CAN_Start(hcan_) != HAL_OK)
125 {
126 return ErrorCode::FAILED;
127 }
128
129 if (fifo_ == CAN_RX_FIFO0)
130 {
131 HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO0_MSG_PENDING);
132 }
133 else
134 {
135 HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO1_MSG_PENDING);
136 }
137
138 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR);
139 HAL_CAN_ActivateNotification(hcan_, CAN_IT_TX_MAILBOX_EMPTY);
140
141 return ErrorCode::OK;
142 }
143
144 ErrorCode AddMessage(const ClassicPack& pack) override
145 {
146 CAN_TxHeaderTypeDef txHeader; // NOLINT
147
148 txHeader.DLC = sizeof(pack.data);
149
150 switch (pack.type)
151 {
152 case Type::STANDARD:
153 txHeader.IDE = CAN_ID_STD;
154 txHeader.RTR = CAN_RTR_DATA;
155 break;
156 case Type::EXTENDED:
157 txHeader.IDE = CAN_ID_EXT;
158 txHeader.RTR = CAN_RTR_DATA;
159 break;
161 txHeader.IDE = CAN_ID_STD;
162 txHeader.RTR = CAN_RTR_REMOTE;
163 break;
165 txHeader.IDE = CAN_ID_EXT;
166 txHeader.RTR = CAN_RTR_REMOTE;
167 break;
168 default:
169 ASSERT(false);
170 return ErrorCode::FAILED;
171 }
172 txHeader.StdId = (pack.type == Type::EXTENDED) ? 0 : pack.id;
173 txHeader.ExtId = (pack.type == Type::EXTENDED) ? pack.id : 0;
174 txHeader.TransmitGlobalTime = DISABLE;
175
176 if (HAL_CAN_AddTxMessage(hcan_, &txHeader, pack.data, &txMailbox) != HAL_OK)
177 {
178 Mutex::LockGuard lock(write_mutex_);
179 if (tx_queue_.Push(pack) != ErrorCode::OK)
180 {
181 return ErrorCode::FULL;
182 }
183 }
184
185 return ErrorCode::OK;
186 }
187
193 {
194 while (HAL_CAN_GetRxMessage(hcan_, fifo_, &rx_buff_.header, rx_buff_.pack.data) ==
195 HAL_OK)
196 {
197 if (rx_buff_.header.IDE == CAN_ID_STD)
198 {
199 if (rx_buff_.header.StdId == 2046)
200 {
201 __NOP();
202 }
203 rx_buff_.pack.id = rx_buff_.header.StdId;
204 rx_buff_.pack.type = Type::STANDARD;
205 }
206 else
207 {
208 rx_buff_.pack.id = rx_buff_.header.ExtId;
209 rx_buff_.pack.type = Type::EXTENDED;
210 }
211
212 if (rx_buff_.header.RTR == CAN_RTR_REMOTE)
213 {
214 if (rx_buff_.pack.type == Type::STANDARD)
215 {
216 rx_buff_.pack.type = Type::REMOTE_STANDARD;
217 }
218 else
219 {
220 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
221 }
222 }
223 OnMessage(rx_buff_.pack, true);
224 }
225 }
226
232 {
233 if (tx_queue_.Peek(tx_buff_.pack) == ErrorCode::OK)
234 {
235 tx_buff_.header.DLC = sizeof(tx_buff_.pack.data);
236 switch (tx_buff_.pack.type)
237 {
238 case Type::STANDARD:
239 tx_buff_.header.IDE = CAN_ID_STD;
240 tx_buff_.header.RTR = CAN_RTR_DATA;
241 break;
242 case Type::EXTENDED:
243 tx_buff_.header.IDE = CAN_ID_EXT;
244 tx_buff_.header.RTR = CAN_RTR_DATA;
245 break;
247 tx_buff_.header.IDE = CAN_ID_STD;
248 tx_buff_.header.RTR = CAN_RTR_REMOTE;
249 break;
251 tx_buff_.header.IDE = CAN_ID_EXT;
252 tx_buff_.header.RTR = CAN_RTR_REMOTE;
253 break;
254 default:
255 ASSERT(false);
256 return;
257 }
258 tx_buff_.header.StdId =
259 (tx_buff_.pack.type == Type::EXTENDED) ? 0 : tx_buff_.pack.id;
260 tx_buff_.header.ExtId =
261 (tx_buff_.pack.type == Type::EXTENDED) ? tx_buff_.pack.id : 0;
262 tx_buff_.header.TransmitGlobalTime = DISABLE;
263
264 if (HAL_CAN_AddTxMessage(hcan_, &tx_buff_.header, tx_buff_.pack.data, &txMailbox) ==
265 HAL_OK)
266 {
267 tx_queue_.Pop();
268 }
269 }
270 }
271
272 CAN_HandleTypeDef* hcan_;
273
274 stm32_can_id_t id_;
276 uint32_t fifo_;
277 static STM32CAN* map[STM32_CAN_NUMBER]; // NOLINT
278
279 struct
280 {
281 CAN_RxHeaderTypeDef header;
282 ClassicPack pack;
283 } rx_buff_;
284
285 struct
286 {
287 CAN_TxHeaderTypeDef header;
288 ClassicPack pack;
289 } tx_buff_;
290
291 uint32_t txMailbox;
292 Mutex write_mutex_;
293};
294} // namespace LibXR
295
296#endif
CAN通信接口,定义标准CAN通信结构,支持不同类型的消息 (CAN communication interface that defines a standard CAN structure supp...
Definition can.hpp:14
@ EXTENDED
扩展 CAN 消息 (Extended CAN message).
@ REMOTE_EXTENDED
远程扩展 CAN 消息 (Remote extended CAN message).
@ STANDARD
标准 CAN 消息 (Standard CAN message).
@ REMOTE_STANDARD
远程标准 CAN 消息 (Remote standard CAN message).
无锁队列实现 / 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
互斥锁的 RAII 机制封装 (RAII-style mechanism for automatic mutex management).
Definition mutex.hpp:65
STM32CAN 类,用于处理 STM32 系统的 CAN 通道。 Provides handling for STM32 CAN channels.
Definition stm32_can.hpp:39
ErrorCode AddMessage(const ClassicPack &pack) override
添加 CAN 消息到系统 (Adds a CAN message to the system).
ErrorCode Init(void)
初始化
Definition stm32_can.hpp:59
void ProcessRxInterrupt()
处理接收中断
void ProcessTxInterrupt()
处理发送中断
STM32CAN(CAN_HandleTypeDef *hcan, uint32_t queue_size)
STM32CAN 类,用于处理 STM32 系统的 CAN 通道。 Provides handling for STM32 CAN.
Definition stm32_can.hpp:47
LibXR 命名空间
Definition ch32_gpio.hpp:9