libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_can.cpp
1#include "stm32_can.hpp"
2
3#ifdef HAL_CAN_MODULE_ENABLED
4
5using namespace LibXR;
6
7STM32CAN* STM32CAN::map[STM32_CAN_NUMBER] = {nullptr};
8
15stm32_can_id_t STM32_CAN_GetID(CAN_TypeDef* addr)
16{
17 // NOLINTBEGIN
18 if (addr == nullptr)
19 { // NOLINT
20 return stm32_can_id_t::STM32_CAN_ID_ERROR;
21 }
22#ifdef CAN1
23 else if (addr == CAN1)
24 { // NOLINT
25 return stm32_can_id_t::STM32_CAN1;
26 }
27#endif
28#ifdef CAN2
29 else if (addr == CAN2)
30 { // NOLINT
31 return stm32_can_id_t::STM32_CAN2;
32 }
33#endif
34#ifdef CAN3
35 else if (addr == CAN3)
36 { // NOLINT
37 return stm32_can_id_t::STM32_CAN3;
38 }
39#endif
40 else
41 {
42 return stm32_can_id_t::STM32_CAN_ID_ERROR;
43 }
44 // NOLINTEND
45}
46
47STM32CAN::STM32CAN(CAN_HandleTypeDef* hcan, uint32_t pool_size)
48 : CAN(), hcan_(hcan), id_(STM32_CAN_GetID(hcan->Instance)), tx_pool_(pool_size)
49{
50 map[id_] = this;
51 Init();
52}
53
54ErrorCode STM32CAN::Init(void)
55{
56 CAN_FilterTypeDef can_filter = {};
57
58 can_filter.FilterIdHigh = 0;
59 can_filter.FilterIdLow = 0;
60 can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
61 can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
62 can_filter.FilterMaskIdHigh = 0;
63 can_filter.FilterMaskIdLow = 0;
64 can_filter.FilterFIFOAssignment = fifo_;
65 can_filter.FilterActivation = ENABLE;
66#ifdef CAN3
67 if (id_ == STM32_CAN1)
68 {
69 can_filter.FilterBank = 0;
70 can_filter.SlaveStartFilterBank = 14;
71 fifo_ = CAN_RX_FIFO0;
72 }
73 else if (id_ == STM32_CAN2)
74 {
75 can_filter.FilterBank = 14;
76 can_filter.SlaveStartFilterBank = 14;
77 fifo_ = CAN_RX_FIFO0;
78 }
79 else if (id_ == STM32_CAN3)
80 {
81 can_filter.FilterBank = 3;
82 fifo_ = CAN_RX_FIFO1;
83 }
84#else
85#ifdef CAN2
86 if (id_ == STM32_CAN1)
87 {
88 can_filter.FilterBank = 0;
89 can_filter.SlaveStartFilterBank = 14;
90 fifo_ = CAN_RX_FIFO0;
91 }
92 else if (id_ == STM32_CAN2)
93 {
94 can_filter.FilterBank = 14;
95 can_filter.SlaveStartFilterBank = 14;
96 fifo_ = CAN_RX_FIFO1;
97 }
98#else
99 if (id_ == STM32_CAN1)
100 {
101 can_filter.FilterBank = 0;
102 can_filter.SlaveStartFilterBank = 14;
103 fifo_ = CAN_RX_FIFO0;
104 }
105#endif
106#endif
107 else
108 {
109 ASSERT(false);
110 return ErrorCode::FAILED;
111 }
112 can_filter.FilterFIFOAssignment = fifo_;
113
114 if (HAL_CAN_ConfigFilter(hcan_, &can_filter) != HAL_OK)
115 {
116 return ErrorCode::FAILED;
117 }
118
119 if (HAL_CAN_Start(hcan_) != HAL_OK)
120 {
121 return ErrorCode::FAILED;
122 }
123
124 if (fifo_ == CAN_RX_FIFO0)
125 {
126 HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO0_MSG_PENDING);
127 }
128 else
129 {
130 HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO1_MSG_PENDING);
131 }
132
133 HAL_CAN_ActivateNotification(hcan_, CAN_IT_ERROR);
134 HAL_CAN_ActivateNotification(hcan_, CAN_IT_TX_MAILBOX_EMPTY);
135
136 return ErrorCode::OK;
137}
138
139ErrorCode STM32CAN::AddMessage(const ClassicPack& pack)
140{
141 CAN_TxHeaderTypeDef txHeader; // NOLINT
142
143 txHeader.DLC = sizeof(pack.data);
144
145 switch (pack.type)
146 {
147 case Type::STANDARD:
148 txHeader.IDE = CAN_ID_STD;
149 txHeader.RTR = CAN_RTR_DATA;
150 break;
151 case Type::EXTENDED:
152 txHeader.IDE = CAN_ID_EXT;
153 txHeader.RTR = CAN_RTR_DATA;
154 break;
156 txHeader.IDE = CAN_ID_STD;
157 txHeader.RTR = CAN_RTR_REMOTE;
158 break;
160 txHeader.IDE = CAN_ID_EXT;
161 txHeader.RTR = CAN_RTR_REMOTE;
162 break;
163 default:
164 ASSERT(false);
165 return ErrorCode::FAILED;
166 }
167 txHeader.StdId = (pack.type == Type::EXTENDED) ? 0 : pack.id;
168 txHeader.ExtId = (pack.type == Type::EXTENDED) ? pack.id : 0;
169 txHeader.TransmitGlobalTime = DISABLE;
170
171 while (true)
172 {
173 uint32_t slot = 0;
174
175 if (HAL_CAN_AddTxMessage(hcan_, &txHeader, pack.data, &txMailbox) != HAL_OK)
176 {
177 if (tx_pool_.Put(pack, slot) != ErrorCode::OK)
178 {
179 return ErrorCode::FULL;
180 }
181 }
182 else
183 {
184 return ErrorCode::OK;
185 }
186
187 if (bus_busy_.load(std::memory_order_acquire) == 0 &&
188 tx_pool_.RecycleSlot(slot) == ErrorCode::OK)
189 {
190 continue;
191 }
192 else
193 {
194 return ErrorCode::OK;
195 }
196 }
197}
198
200{
201 while (HAL_CAN_GetRxMessage(hcan_, fifo_, &rx_buff_.header, rx_buff_.pack.data) ==
202 HAL_OK)
203 {
204 if (rx_buff_.header.IDE == CAN_ID_STD)
205 {
206 if (rx_buff_.header.StdId == 2046)
207 {
208 __NOP();
209 }
210 rx_buff_.pack.id = rx_buff_.header.StdId;
211 rx_buff_.pack.type = Type::STANDARD;
212 }
213 else
214 {
215 rx_buff_.pack.id = rx_buff_.header.ExtId;
216 rx_buff_.pack.type = Type::EXTENDED;
217 }
218
219 if (rx_buff_.header.RTR == CAN_RTR_REMOTE)
220 {
221 if (rx_buff_.pack.type == Type::STANDARD)
222 {
223 rx_buff_.pack.type = Type::REMOTE_STANDARD;
224 }
225 else
226 {
227 rx_buff_.pack.type = Type::REMOTE_EXTENDED;
228 }
229 }
230 OnMessage(rx_buff_.pack, true);
231 }
232}
233
235{
236 if (tx_pool_.Get(tx_buff_.pack) == ErrorCode::OK)
237 {
238 tx_buff_.header.DLC = sizeof(tx_buff_.pack.data);
239 switch (tx_buff_.pack.type)
240 {
241 case Type::STANDARD:
242 tx_buff_.header.IDE = CAN_ID_STD;
243 tx_buff_.header.RTR = CAN_RTR_DATA;
244 break;
245 case Type::EXTENDED:
246 tx_buff_.header.IDE = CAN_ID_EXT;
247 tx_buff_.header.RTR = CAN_RTR_DATA;
248 break;
250 tx_buff_.header.IDE = CAN_ID_STD;
251 tx_buff_.header.RTR = CAN_RTR_REMOTE;
252 break;
254 tx_buff_.header.IDE = CAN_ID_EXT;
255 tx_buff_.header.RTR = CAN_RTR_REMOTE;
256 break;
257 default:
258 ASSERT(false);
259 return;
260 }
261 tx_buff_.header.StdId = (tx_buff_.pack.type == Type::EXTENDED) ? 0 : tx_buff_.pack.id;
262 tx_buff_.header.ExtId = (tx_buff_.pack.type == Type::EXTENDED) ? tx_buff_.pack.id : 0;
263 tx_buff_.header.TransmitGlobalTime = DISABLE;
264
265 HAL_CAN_AddTxMessage(hcan_, &tx_buff_.header, tx_buff_.pack.data, &txMailbox);
266
267 bus_busy_.store(UINT32_MAX, std::memory_order_release);
268 }
269 else
270 {
271 uint32_t tsr = READ_REG(hcan_->Instance->TSR);
272
273 if (((tsr & CAN_TSR_TME0) != 0U) && ((tsr & CAN_TSR_TME1) != 0U) &&
274 ((tsr & CAN_TSR_TME2) != 0U))
275 {
276 bus_busy_.store(0, std::memory_order_release);
277 }
278 else
279 {
280 bus_busy_.store(UINT32_MAX, std::memory_order_release);
281 }
282 }
283}
284
285extern "C" void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* hcan)
286{
287 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
288 if (can)
289 {
290 can->ProcessRxInterrupt();
291 }
292}
293
294extern "C" void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef* hcan)
295{
296 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
297 if (can)
298 {
299 can->ProcessRxInterrupt();
300 }
301}
302
303extern "C" void HAL_CAN_ErrorCallback(CAN_HandleTypeDef* hcan)
304{
305 HAL_CAN_ResetError(hcan);
306}
307
308extern "C" void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef* hcan)
309{
310 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
311 if (can)
312 {
313 can->ProcessTxInterrupt();
314 }
315}
316
317extern "C" void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef* hcan)
318{
319 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
320 if (can)
321 {
322 can->ProcessTxInterrupt();
323 }
324}
325
326extern "C" void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef* hcan)
327{
328 STM32CAN* can = STM32CAN::map[STM32_CAN_GetID(hcan->Instance)];
329 if (can)
330 {
331 can->ProcessTxInterrupt();
332 }
333}
334
335#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).
ErrorCode RecycleSlot(uint32_t index)
回收指定槽位 / Recycle a slot
ErrorCode Put(const Data &data)
向池中放入一个元素 / Put an element into the pool
ErrorCode Get(Data &data)
从池中取出一个元素 / Retrieve an element from the pool
STM32CAN 类,用于处理 STM32 系统的 CAN 通道。 Provides handling for STM32 CAN channels.
Definition stm32_can.hpp:39
STM32CAN(CAN_HandleTypeDef *hcan, uint32_t pool_size)
STM32CAN 类,用于处理 STM32 系统的 CAN 通道。 Provides handling for STM32 CAN.
Definition stm32_can.cpp:47
ErrorCode Init(void)
初始化
Definition stm32_can.cpp:54
ErrorCode AddMessage(const ClassicPack &pack) override
添加 CAN 消息到系统 (Adds a CAN message to the system).
void ProcessRxInterrupt()
处理接收中断
void ProcessTxInterrupt()
处理发送中断
LibXR 命名空间
Definition ch32_gpio.hpp:9