1 /**
2 ******************************************************************************
3 * @file tae32f53xx_ll_can.c
4 * @author MCD Application Team
5 * @brief CAN LL Module Driver.
6 *
7 ******************************************************************************
8 * @attention
9 *
10 * <h2><center>© Copyright (c) 2020 Tai-Action.
11 * All rights reserved.</center></h2>
12 *
13 * This software is licensed by Tai-Action under BSD 3-Clause license,
14 * the "License"; You may not use this file except in compliance with the
15 * License. You may obtain a copy of the License at:
16 * opensource.org/licenses/BSD-3-Clause
17 *
18 ******************************************************************************
19 */
20
21 /* Includes ------------------------------------------------------------------*/
22 #include "tae32f53xx_ll.h"
23
24
25 #define DBG_TAG "CAN LL"
26 #define DBG_LVL DBG_ERROR
27 #include "dbg/tae32f53xx_dbg.h"
28
29
30 /** @addtogroup TAE32F53xx_LL_Driver
31 * @{
32 */
33
34 /** @defgroup CAN_LL CAN LL
35 * @brief CAN LL Module Driver
36 * @{
37 */
38
39 #ifdef LL_CAN_MODULE_ENABLED
40
41 /* Private define ------------------------------------------------------------*/
42 /* Private variables ---------------------------------------------------------*/
43 /* Private typedef -----------------------------------------------------------*/
44 /* Private macro -------------------------------------------------------------*/
45 /* Private function prototypes -----------------------------------------------*/
46 /** @addtogroup CAN_LL_Private_Functions
47 * @{
48 */
49 LL_StatusETypeDef LL_CAN_AcceptFilCfg(CAN_TypeDef *Instance, CAN_AcceptFilCfgTypeDef *fil_cfg);
50 /**
51 * @}
52 */
53
54 /* Exported functions --------------------------------------------------------*/
55 /** @defgroup CAN_LL_Exported_Functions CAN LL Exported Functions
56 * @brief CAN LL Exported Functions
57 * @{
58 */
59
60 /** @defgroup CAN_LL_Exported_Functions_Group1 Initialization and de-initialization functions
61 * @brief Initialization and de-initialization functions
62 * @{
63 */
64
65 /**
66 * @brief CAN LL Init
67 * @param Instance Specifies CAN peripheral
68 * @param user_cfg user config pointer
69 * @return Status of the Initialization
70 */
LL_CAN_Init(CAN_TypeDef * Instance,CAN_UserCfgTypeDef * user_cfg)71 LL_StatusETypeDef LL_CAN_Init(CAN_TypeDef *Instance, CAN_UserCfgTypeDef *user_cfg)
72 {
73 assert_param(Instance);
74 assert_param(user_cfg);
75
76 /* Init the low level hardware eg. Clock, NVIC */
77 LL_CAN_MspInit(Instance);
78
79 /* Set reset status to config some register which can config in reset status only */
80 __LL_CAN_Reset_Set(Instance);
81
82 //Baudrate config
83 assert_param(user_cfg->baudrate);
84 __LL_CAN_SS_Prescaler_Set(Instance, (LL_SYSCTRL_AHBClkGet() / 10 / user_cfg->baudrate - 1));
85
86 //Bit timing config
87 __LL_CAN_SS_BitTimingSeg1_Set(Instance, user_cfg->bit_timing_seg1);
88 __LL_CAN_SS_BitTimingSeg2_Set(Instance, user_cfg->bit_timing_seg2);
89 __LL_CAN_SS_SyncJumpWidth_Set(Instance, user_cfg->bit_timing_sjw);
90
91 //Acceptance filter config
92 for (uint8_t i = 0; i < user_cfg->accept_fil_cfg_num; i++) {
93 LL_CAN_AcceptFilCfg(Instance, (CAN_AcceptFilCfgTypeDef *)&user_cfg->accept_fil_cfg_ptr[i]);
94 }
95
96 /*Clear reset status to config other register */
97 __LL_CAN_Reset_Clr(Instance);
98
99 //RX buffer almost full and error warning limit set
100 __LL_CAN_RxBufAlmostFullLimit_Set(Instance, user_cfg->rx_almost_full_limit);
101 __LL_CAN_ErrWarnLimit_Set(Instance, user_cfg->err_limit);
102
103 return LL_OK;
104 }
105
106 /**
107 * @brief CAN LL DeInit
108 * @param Instance Specifies CAN peripheral
109 * @return Status of the DeInitialization
110 */
LL_CAN_DeInit(CAN_TypeDef * Instance)111 LL_StatusETypeDef LL_CAN_DeInit(CAN_TypeDef *Instance)
112 {
113 /* DeInit the low level hardware eg. Clock, NVIC */
114 LL_CAN_MspDeInit(Instance);
115
116 return LL_OK;
117 }
118
119 /**
120 * @brief Initializes the CAN MSP.
121 * @param Instance Specifies CAN peripheral
122 * @return None
123 */
LL_CAN_MspInit(CAN_TypeDef * Instance)124 __WEAK void LL_CAN_MspInit(CAN_TypeDef *Instance)
125 {
126 /* Prevent unused argument(s) compilation warning */
127 LL_UNUSED(Instance);
128 /* NOTE: This function should not be modified, when the callback is needed,
129 the LL_CAN_MspInit could be implemented in the user file
130 */
131 }
132
133 /**
134 * @brief DeInitializes the CAN MSP
135 * @param Instance Specifies CAN peripheral
136 * @return None
137 */
LL_CAN_MspDeInit(CAN_TypeDef * Instance)138 __WEAK void LL_CAN_MspDeInit(CAN_TypeDef *Instance)
139 {
140 /* Prevent unused argument(s) compilation warning */
141 LL_UNUSED(Instance);
142 /* NOTE: This function should not be modified, when the callback is needed,
143 the LL_CAN_MspDeInit could be implemented in the user file
144 */
145 }
146
147 /**
148 * @}
149 */
150
151 /** @defgroup CAN_LL_Exported_Functions_Group2 Send data functions
152 * @brief Send data functions
153 * @{
154 */
155
156 /**
157 * @brief CAN LL send standard primary transmit buffer
158 * @param Instance Specifies CAN peripheral
159 * @param buf_fmt buffer format pointer
160 * @param buf buffer pointer
161 * @return success send length in byte
162 */
LL_CAN_SendStandard_PTB(CAN_TypeDef * Instance,CAN_TxBufFormatTypeDef * buf_fmt,uint32_t * buf)163 uint32_t LL_CAN_SendStandard_PTB(CAN_TypeDef *Instance, CAN_TxBufFormatTypeDef *buf_fmt, uint32_t *buf)
164 {
165 uint32_t i, j;
166
167 assert_param(Instance);
168 assert_param(buf_fmt);
169 assert_param(buf);
170
171 //TX buffer select PTB
172 __LL_CAN_TxBufSel_PTB(Instance);
173
174 //Write buffer format data to TX buffer
175 Instance->TXBUF[0] = *((uint32_t *)buf_fmt);
176 Instance->TXBUF[1] = *(((uint32_t *)buf_fmt) + 1);
177
178 //Write data to TX buffer
179 for (i = 0, j = 0; i < buf_fmt->data_len_code; i += 4, j++) {
180 Instance->TXBUF[2 + j] = *buf++;
181 }
182
183 //TX primary enable
184 __LL_CAN_TxPriEn_Set(Instance);
185
186 //Wait TX complete
187 while (__LL_CAN_TxPriEn_Get(Instance));
188
189 return buf_fmt->data_len_code;
190 }
191
192 /**
193 * @brief CAN LL send standard secondary transmit buffer
194 * @param Instance Specifies CAN peripheral
195 * @param buf_fmt buffer format pointer
196 * @param buf buffer pointer
197 * @return success send length in byte
198 */
LL_CAN_SendStandard_STB(CAN_TypeDef * Instance,CAN_TxBufFormatTypeDef * buf_fmt,uint32_t * buf)199 uint32_t LL_CAN_SendStandard_STB(CAN_TypeDef *Instance, CAN_TxBufFormatTypeDef *buf_fmt, uint32_t *buf)
200 {
201 uint32_t i, j;
202
203 assert_param(Instance);
204 assert_param(buf_fmt);
205 assert_param(buf);
206
207 //TX buffer select STB
208 __LL_CAN_TxBufSel_STB(Instance);
209
210 //Write buffer format data to TX buffer
211 Instance->TXBUF[0] = *((uint32_t *)buf_fmt);
212 Instance->TXBUF[1] = *(((uint32_t *)buf_fmt) + 1);
213
214 //Write data to TX buffer
215 for (i = 0, j = 0; i < buf_fmt->data_len_code; i += 4, j++) {
216 Instance->TXBUF[2 + j] = *buf++;
217 }
218
219 //TX buffer Secondary next
220 __LL_CAN_TxSecNext_Set(Instance);
221
222 //TX secondary send one start
223 __LL_CAN_TxSecOne_Set(Instance);
224
225 //Wait TX complete
226 while (__LL_CAN_TxSecOne_Get(Instance));
227
228 return buf_fmt->data_len_code;
229 }
230
231 /**
232 * @brief CAN LL send a multi-package standard secondary transmit buffer
233 * @param Instance Specifies CAN peripheral
234 * @param buf_fmt buffer format pointer
235 * @param buf buffer pointer
236 * @param send_cnt send packets count
237 * @return success send length in byte
238 */
LL_CAN_SendStandard_STB_Multi(CAN_TypeDef * Instance,CAN_TxBufFormatTypeDef * buf_fmt,uint32_t * buf,uint32_t send_cnt)239 uint32_t LL_CAN_SendStandard_STB_Multi(CAN_TypeDef *Instance, CAN_TxBufFormatTypeDef *buf_fmt,
240 uint32_t *buf, uint32_t send_cnt)
241 {
242 uint32_t i, j, cnt;
243
244 assert_param(Instance);
245 assert_param(buf_fmt);
246 assert_param(buf);
247
248 //TX buffer select STB
249 __LL_CAN_TxBufSel_STB(Instance);
250
251 for (cnt = 0; cnt < send_cnt; cnt++) {
252 //Write buffer format data to TX buffer
253 Instance->TXBUF[0] = *((uint32_t *)buf_fmt);
254 Instance->TXBUF[1] = *(((uint32_t *)buf_fmt) + 1);
255
256 //Write data to TX buffer
257 for (i = 0, j = 0; i < buf_fmt->data_len_code; i += 4, j++) {
258 Instance->TXBUF[2 + j] = *buf++;
259 }
260
261 //TX buffer Secondary next
262 __LL_CAN_TxSecNext_Set(Instance);
263
264 //TX buffer Secondary full and send
265 if (__LL_CAN_IsTxSecBufFull(Instance)) {
266 //TX secondary send all start
267 __LL_CAN_TxSecAll_Set(Instance);
268
269 //Wait TX complete
270 while (__LL_CAN_TxSecAll_Get(Instance));
271 }
272 }
273
274 //TX secondary send all start
275 __LL_CAN_TxSecAll_Set(Instance);
276
277 //Wait TX complete
278 while (__LL_CAN_TxSecAll_Get(Instance));
279
280 return buf_fmt->data_len_code * send_cnt;
281 }
282
283 /**
284 * @}
285 */
286
287 /** @defgroup CAN_LL_Exported_Functions_Interrupt CAN Interrupt handler and call back
288 * @brief CAN Interrupt handler and call back
289 * @{
290 */
291
292 /**
293 * @brief CAN IRQ Handler
294 * @param Instance Specifies CAN peripheral
295 * @note All interrupt pending will be reset immediately after a read access
296 * @return None
297 */
LL_CAN_IRQHandler(CAN_TypeDef * Instance)298 void LL_CAN_IRQHandler(CAN_TypeDef *Instance)
299 {
300 uint8_t txrx_int_sta = __LL_CAN_IntSta_Get(Instance);
301 uint8_t err_int_sta = __LL_CAN_ErrIntSta_Get(Instance);
302
303 if (txrx_int_sta & CAN_RX_INT_STA_Msk) {
304 LL_CAN_RxCallback(Instance);
305 }
306
307 if (txrx_int_sta & CAN_RX_BUF_OVER_INT_STA_Msk) {
308 LL_CAN_RxOverCallback(Instance);
309 }
310
311 if (txrx_int_sta & CAN_RX_BUF_FULL_INT_STA_Msk) {
312 LL_CAN_RxFullCallback(Instance);
313 }
314
315 if (txrx_int_sta & CAN_RX_BUF_ALMOST_FULL_INT_STA_Msk) {
316 LL_CAN_RxAlmostFullCallback(Instance);
317 }
318
319 if (txrx_int_sta & CAN_TX_PRI_INT_STA_Msk) {
320 LL_CAN_TxPriCallback(Instance);
321 }
322
323 if (txrx_int_sta & CAN_TX_SEC_INT_STA_Msk) {
324 LL_CAN_TxSecCallback(Instance);
325 }
326
327 if (txrx_int_sta & CAN_ERR_INT_STA_Msk) {
328 LL_CAN_ErrCallback(Instance);
329 }
330
331 if (txrx_int_sta & CAN_ABORT_INT_STA_Msk) {
332 LL_CAN_AbortCallback(Instance);
333 }
334
335
336 if (err_int_sta & CAN_ERR_PASS_INT_STA_Msk) {
337 LL_CAN_ErrPassiveCallback(Instance);
338 }
339
340 if (err_int_sta & CAN_ARB_LOST_INT_STA_Msk) {
341 LL_CAN_ArbLostCallback(Instance);
342 }
343
344 if (err_int_sta & CAN_BUS_ERR_INT_STA_Msk) {
345 LL_CAN_BusErrCallback(Instance);
346 }
347 }
348
349
350 /**
351 * @brief CAN RX interrupt callback
352 * @param Instance Specifies CAN peripheral
353 * @return None
354 */
LL_CAN_RxCallback(CAN_TypeDef * Instance)355 __WEAK void LL_CAN_RxCallback(CAN_TypeDef *Instance)
356 {
357 /* Prevent unused argument(s) compilation warning */
358 LL_UNUSED(Instance);
359 /* NOTE: This function should not be modified, when the callback is needed,
360 the LL_CAN_RxCallback could be implemented in the user file
361 */
362 }
363
364 /**
365 * @brief CAN RX over interrupt callback
366 * @param Instance Specifies CAN peripheral
367 * @return None
368 */
LL_CAN_RxOverCallback(CAN_TypeDef * Instance)369 __WEAK void LL_CAN_RxOverCallback(CAN_TypeDef *Instance)
370 {
371 /* Prevent unused argument(s) compilation warning */
372 LL_UNUSED(Instance);
373 /* NOTE: This function should not be modified, when the callback is needed,
374 the LL_CAN_RxOverCallback could be implemented in the user file
375 */
376 }
377
378 /**
379 * @brief CAN RX full interrupt callback
380 * @param Instance Specifies CAN peripheral
381 * @return None
382 */
LL_CAN_RxFullCallback(CAN_TypeDef * Instance)383 __WEAK void LL_CAN_RxFullCallback(CAN_TypeDef *Instance)
384 {
385 /* Prevent unused argument(s) compilation warning */
386 LL_UNUSED(Instance);
387 /* NOTE: This function should not be modified, when the callback is needed,
388 the LL_CAN_RxFullCallback could be implemented in the user file
389 */
390 }
391
392 /**
393 * @brief CAN RX almost full interrupt callback
394 * @param Instance Specifies CAN peripheral
395 * @return None
396 */
LL_CAN_RxAlmostFullCallback(CAN_TypeDef * Instance)397 __WEAK void LL_CAN_RxAlmostFullCallback(CAN_TypeDef *Instance)
398 {
399 /* Prevent unused argument(s) compilation warning */
400 LL_UNUSED(Instance);
401 /* NOTE: This function should not be modified, when the callback is needed,
402 the LL_CAN_RxAlmostFullCallback could be implemented in the user file
403 */
404 }
405
406 /**
407 * @brief CAN TX primary interrupt callback
408 * @param Instance Specifies CAN peripheral
409 * @return None
410 */
LL_CAN_TxPriCallback(CAN_TypeDef * Instance)411 __WEAK void LL_CAN_TxPriCallback(CAN_TypeDef *Instance)
412 {
413 /* Prevent unused argument(s) compilation warning */
414 LL_UNUSED(Instance);
415 /* NOTE: This function should not be modified, when the callback is needed,
416 the LL_CAN_TxPriCallback could be implemented in the user file
417 */
418 }
419
420 /**
421 * @brief CAN TX secondary interrupt callback
422 * @param Instance Specifies CAN peripheral
423 * @return None
424 */
LL_CAN_TxSecCallback(CAN_TypeDef * Instance)425 __WEAK void LL_CAN_TxSecCallback(CAN_TypeDef *Instance)
426 {
427 /* Prevent unused argument(s) compilation warning */
428 LL_UNUSED(Instance);
429 /* NOTE: This function should not be modified, when the callback is needed,
430 the LL_CAN_TxSecCallback could be implemented in the user file
431 */
432 }
433
434 /**
435 * @brief CAN error interrupt callback
436 * @param Instance Specifies CAN peripheral
437 * @return None
438 */
LL_CAN_ErrCallback(CAN_TypeDef * Instance)439 __WEAK void LL_CAN_ErrCallback(CAN_TypeDef *Instance)
440 {
441 /* Prevent unused argument(s) compilation warning */
442 LL_UNUSED(Instance);
443 /* NOTE: This function should not be modified, when the callback is needed,
444 the LL_CAN_ErrCallback could be implemented in the user file
445 */
446 }
447
448 /**
449 * @brief CAN abort interrupt callback
450 * @param Instance Specifies CAN peripheral
451 * @return None
452 */
LL_CAN_AbortCallback(CAN_TypeDef * Instance)453 __WEAK void LL_CAN_AbortCallback(CAN_TypeDef *Instance)
454 {
455 /* Prevent unused argument(s) compilation warning */
456 LL_UNUSED(Instance);
457 /* NOTE: This function should not be modified, when the callback is needed,
458 the LL_CAN_AbortCallback could be implemented in the user file
459 */
460 }
461
462 /**
463 * @brief CAN error passive interrupt callback
464 * @param Instance Specifies CAN peripheral
465 * @return None
466 */
LL_CAN_ErrPassiveCallback(CAN_TypeDef * Instance)467 __WEAK void LL_CAN_ErrPassiveCallback(CAN_TypeDef *Instance)
468 {
469 /* Prevent unused argument(s) compilation warning */
470 LL_UNUSED(Instance);
471 /* NOTE: This function should not be modified, when the callback is needed,
472 the LL_CAN_ErrPassiveCallback could be implemented in the user file
473 */
474 }
475
476 /**
477 * @brief CAN arbitration lost interrupt callback
478 * @param Instance Specifies CAN peripheral
479 * @return None
480 */
LL_CAN_ArbLostCallback(CAN_TypeDef * Instance)481 __WEAK void LL_CAN_ArbLostCallback(CAN_TypeDef *Instance)
482 {
483 /* Prevent unused argument(s) compilation warning */
484 LL_UNUSED(Instance);
485 /* NOTE: This function should not be modified, when the callback is needed,
486 the LL_CAN_ArbLostCallback could be implemented in the user file
487 */
488 }
489
490 /**
491 * @brief CAN bus error interrupt callback
492 * @param Instance Specifies CAN peripheral
493 * @return None
494 */
LL_CAN_BusErrCallback(CAN_TypeDef * Instance)495 __WEAK void LL_CAN_BusErrCallback(CAN_TypeDef *Instance)
496 {
497 /* Prevent unused argument(s) compilation warning */
498 LL_UNUSED(Instance);
499 /* NOTE: This function should not be modified, when the callback is needed,
500 the LL_CAN_BusErrCallback could be implemented in the user file
501 */
502 }
503
504
505 /**
506 * @}
507 */
508
509 /**
510 * @}
511 */
512
513 /* Private functions ---------------------------------------------------------*/
514 /** @defgroup CAN_LL_Private_Functions CAN LL Private Functions
515 * @brief CAN LL Private Functions
516 * @{
517 */
518
519 /**
520 * @brief CAN LL acceptance filter config
521 * @param Instance Specifies CAN peripheral
522 * @param fil_cfg filter config pointer
523 * @return Config result
524 */
LL_CAN_AcceptFilCfg(CAN_TypeDef * Instance,CAN_AcceptFilCfgTypeDef * fil_cfg)525 LL_StatusETypeDef LL_CAN_AcceptFilCfg(CAN_TypeDef *Instance, CAN_AcceptFilCfgTypeDef *fil_cfg)
526 {
527 assert_param(Instance);
528 assert_param(fil_cfg);
529
530 //Check in reset status or not
531 if (!__LL_CAN_ResetSta_Get(Instance)) {
532 LOG_E("Acceptance filter register can config in reset status only!\n");
533 return LL_ERROR;
534 }
535
536 //CAN acceptance filter Code and Mask config
537 __LL_CAN_AcceptFilAddr_Set(Instance, fil_cfg->slot);
538 __LL_CAN_AcceptFilContentSel_Code(Instance);
539 __LL_CAN_AcceptFilCodeOrMaskVal_Set(Instance, fil_cfg->code_val);
540 __LL_CAN_AcceptFilContentSel_Mask(Instance);
541 __LL_CAN_AcceptFilCodeOrMaskVal_Set(Instance, fil_cfg->mask_val);
542
543 //CAN acceptance filter enable
544 __LL_CAN_AcceptFil_En(Instance, ((uint8_t)fil_cfg->slot));
545
546 return LL_OK;
547 }
548
549
550 /**
551 * @}
552 */
553
554 #endif /* LL_CAN_MODULE_ENABLED */
555
556 /**
557 * @}
558 */
559
560 /**
561 * @}
562 */
563
564 /************************* (C) COPYRIGHT Tai-Action *****END OF FILE***********/
565
566