1 /**************************************************************************//**
2 * @file can.c
3 * @version V2.00
4 * @brief M480 series CAN driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10
11 /** @addtogroup Standard_Driver Standard Driver
12 @{
13 */
14
15 /** @addtogroup CAN_Driver CAN Driver
16 @{
17 */
18
19 /** @addtogroup CAN_EXPORTED_FUNCTIONS CAN Exported Functions
20 @{
21 */
22
23 /** @cond HIDDEN_SYMBOLS */
24
25 #if defined(CAN2)
26 static uint8_t gu8LockCanIf[3ul][2ul] = {0ul}; /* The chip has three CANs. */
27 #elif defined(CAN1)
28 static uint8_t gu8LockCanIf[2ul][2ul] = {0ul}; /* The chip has two CANs. */
29 #elif defined(CAN0) || defined(CAN)
30 static uint8_t gu8LockCanIf[1ul][2ul] = {0ul}; /* The chip only has one CAN. */
31 #endif
32
33 #define RETRY_COUNTS (0x10000000ul)
34
35 #define TSEG1_MIN 2ul
36 #define TSEG1_MAX 16ul
37 #define TSEG2_MIN 1ul
38 #define TSEG2_MAX 8ul
39 #define BRP_MIN 1ul
40 #define BRP_MAX 1024ul /* 6-bit BRP field + 4-bit BRPE field*/
41 #define SJW_MAX 4ul
42 #define BRP_INC 1ul
43
44 /* #define DEBUG_PRINTF printf */
45 #define DEBUG_PRINTF(...)
46
47 static uint32_t LockIF(CAN_T *tCAN);
48 static uint32_t LockIF_TL(CAN_T *tCAN);
49 static void ReleaseIF(CAN_T *tCAN, uint32_t u32IfNo);
50 static int can_update_spt(int sampl_pt, int tseg, int *tseg1, int *tseg2);
51
52 /**
53 * @brief Check if any interface is available then lock it for usage.
54 * @param[in] tCAN The pointer to CAN module base address.
55 * @retval 0 IF0 is free
56 * @retval 1 IF1 is free
57 * @retval 2 No IF is free
58 * @details Search the first free message interface, starting from 0. If a interface is
59 * available, set a flag to lock the interface.
60 */
LockIF(CAN_T * tCAN)61 static uint32_t LockIF(CAN_T *tCAN)
62 {
63 uint32_t u32CanNo;
64 uint32_t u32FreeIfNo;
65 uint32_t u32IntMask;
66
67 #if defined(CAN1)
68 if(tCAN == CAN0)
69 u32CanNo = 0ul;
70 else if(tCAN == CAN1)
71 u32CanNo = 1ul;
72 #if defined(CAN2)
73 else if(tCAN == CAN2)
74 u32CanNo = 2ul;
75 #endif
76 #else /* defined(CAN0) || defined(CAN) */
77 u32CanNo = 0ul;
78 #endif
79
80 u32FreeIfNo = 2ul;
81
82 /* Disable CAN interrupt */
83 u32IntMask = tCAN->CON & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
84 tCAN->CON = tCAN->CON & ~(CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
85
86 /* Check interface 1 is available or not */
87 if((tCAN->IF[0ul].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0ul)
88 {
89 if(gu8LockCanIf[u32CanNo][0ul] == 0ul)
90 {
91 gu8LockCanIf[u32CanNo][0ul] = 1u;
92 u32FreeIfNo = 0ul;
93 }
94 else
95 {
96 }
97 }
98 else
99 {
100 }
101
102 /* Or check interface 2 is available or not */
103 if(u32FreeIfNo == 2ul)
104 {
105 if((tCAN->IF[1ul].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0ul)
106 {
107 if(gu8LockCanIf[u32CanNo][1ul] == 0ul)
108 {
109 gu8LockCanIf[u32CanNo][1ul] = 1u;
110 u32FreeIfNo = 1ul;
111 }
112 else
113 {
114 }
115 }
116 else
117 {
118 }
119 }
120 else
121 {
122 }
123
124 /* Enable CAN interrupt */
125 tCAN->CON |= u32IntMask;
126
127 return u32FreeIfNo;
128 }
129
130 /**
131 * @brief Check if any interface is available in a time limitation then lock it for usage.
132 * @param[in] tCAN The pointer to CAN module base address.
133 * @retval 0 IF0 is free
134 * @retval 1 IF1 is free
135 * @retval 2 No IF is free
136 * @details Search the first free message interface, starting from 0. If no interface is
137 * it will try again until time out. If a interface is available, set a flag to
138 * lock the interface.
139 */
LockIF_TL(CAN_T * tCAN)140 static uint32_t LockIF_TL(CAN_T *tCAN)
141 {
142 uint32_t u32Count;
143 uint32_t u32FreeIfNo;
144
145 for(u32Count = 0ul; u32Count < RETRY_COUNTS; u32Count++)
146 {
147 if((u32FreeIfNo = LockIF(tCAN)) != 2ul)
148 {
149 break;
150 }
151 else
152 {
153 }
154 }
155
156 return u32FreeIfNo;
157 }
158
159 /**
160 * @brief Release locked interface.
161 * @param[in] tCAN The pointer to CAN module base address.
162 * @param[in] u32Info The interface number, 0 or 1.
163 * @return none
164 * @details Release the locked interface.
165 */
ReleaseIF(CAN_T * tCAN,uint32_t u32IfNo)166 static void ReleaseIF(CAN_T *tCAN, uint32_t u32IfNo)
167 {
168 uint32_t u32IntMask;
169 uint32_t u32CanNo;
170
171 if(u32IfNo >= 2ul)
172 {
173 }
174 else
175 {
176 #if defined(CAN1)
177 if(tCAN == CAN0)
178 u32CanNo = 0ul;
179 else if(tCAN == CAN1)
180 u32CanNo = 1ul;
181 #if defined(CAN2)
182 else if(tCAN == CAN2)
183 u32CanNo = 2ul;
184 #endif
185 #else /* defined(CAN0) || defined(CAN) */
186 u32CanNo = 0ul;
187 #endif
188
189 /* Disable CAN interrupt */
190 u32IntMask = tCAN->CON & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
191 tCAN->CON = tCAN->CON & ~(CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
192
193 gu8LockCanIf[u32CanNo][u32IfNo] = 0u;
194
195 /* Enable CAN interrupt */
196 tCAN->CON |= u32IntMask;
197 }
198 }
199
can_update_spt(int sampl_pt,int tseg,int * tseg1,int * tseg2)200 static int can_update_spt(int sampl_pt, int tseg, int *tseg1, int *tseg2)
201 {
202 *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
203 if (*tseg2 < TSEG2_MIN)
204 {
205 *tseg2 = TSEG2_MIN;
206 }
207 else
208 {
209 }
210
211 if (*tseg2 > TSEG2_MAX)
212 {
213 *tseg2 = TSEG2_MAX;
214 }
215 else
216 {
217 }
218
219 *tseg1 = tseg - *tseg2;
220 if (*tseg1 > TSEG1_MAX)
221 {
222 *tseg1 = TSEG1_MAX;
223 *tseg2 = tseg - *tseg1;
224 }
225 else
226 {
227 }
228
229 return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
230 }
231
232 /** @endcond HIDDEN_SYMBOLS */
233
234 /**
235 * @brief Enter initialization mode
236 * @param[in] tCAN The pointer to CAN module base address.
237 * @param[in] u8Mask Following values can be used.
238 * \ref CAN_CON_DAR_Msk Disable automatic retransmission.
239 * \ref CAN_CON_EIE_Msk Enable error interrupt.
240 * \ref CAN_CON_SIE_Msk Enable status interrupt.
241 * \ref CAN_CON_IE_Msk CAN interrupt.
242 * @return None
243 * @details This function is used to set CAN to enter initialization mode and enable access bit timing
244 * register. After bit timing configuration ready, user must call CAN_LeaveInitMode()
245 * to leave initialization mode and lock bit timing register to let new configuration
246 * take effect.
247 */
CAN_EnterInitMode(CAN_T * tCAN,uint8_t u8Mask)248 void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask)
249 {
250 tCAN->CON = u8Mask | (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk);
251 }
252
253
254 /**
255 * @brief Leave initialization mode
256 * @param[in] tCAN The pointer to CAN module base address.
257 * @return None
258 * @details This function is used to set CAN to leave initialization mode to let
259 * bit timing configuration take effect after configuration ready.
260 */
CAN_LeaveInitMode(CAN_T * tCAN)261 void CAN_LeaveInitMode(CAN_T *tCAN)
262 {
263 tCAN->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk));
264 while(tCAN->CON & CAN_CON_INIT_Msk)
265 {
266 /* Check INIT bit is released */
267 }
268 }
269
270 /**
271 * @brief Wait message into message buffer in basic mode.
272 * @param[in] tCAN The pointer to CAN module base address.
273 * @return None
274 * @details This function is used to wait message into message buffer in basic mode. Please notice the
275 * function is polling NEWDAT bit of MCON register by while loop and it is used in basic mode.
276 */
CAN_WaitMsg(CAN_T * tCAN)277 void CAN_WaitMsg(CAN_T *tCAN)
278 {
279 tCAN->STATUS = 0x0ul; /* clr status */
280
281 while(1)
282 {
283 if(tCAN->IF[1].MCON & CAN_IF_MCON_NEWDAT_Msk) /* check new data */
284 {
285 /* New Data IN */
286 break;
287 }
288 else
289 {
290 }
291
292 if(tCAN->STATUS & CAN_STATUS_RXOK_Msk)
293 {
294 /* Rx OK */
295 }
296 else
297 {
298 }
299
300 if(tCAN->STATUS & CAN_STATUS_LEC_Msk)
301 {
302 /* Error */
303 }
304 else
305 {
306 }
307 }
308 }
309
310 /**
311 * @brief Get current bit rate
312 * @param[in] tCAN The pointer to CAN module base address.
313 * @return Current Bit-Rate (kilo bit per second)
314 * @details Return current CAN bit rate according to the user bit-timing parameter settings
315 */
CAN_GetCANBitRate(CAN_T * tCAN)316 uint32_t CAN_GetCANBitRate(CAN_T *tCAN)
317 {
318 uint32_t u32Tseg1, u32Tseg2;
319 uint32_t u32Bpr;
320
321 u32Tseg1 = (tCAN->BTIME & CAN_BTIME_TSEG1_Msk) >> CAN_BTIME_TSEG1_Pos;
322 u32Tseg2 = (tCAN->BTIME & CAN_BTIME_TSEG2_Msk) >> CAN_BTIME_TSEG2_Pos;
323 u32Bpr = (tCAN->BTIME & CAN_BTIME_BRP_Msk) | (tCAN->BRPE << 6ul);
324
325 return (SystemCoreClock / (u32Bpr + 1ul) / (u32Tseg1 + u32Tseg2 + 3ul));
326 }
327
328 /**
329 * @brief Switch the CAN into test mode.
330 * @param[in] tCAN The pointer to CAN module base address.
331 * @param[in] u8TestMask Specifies the configuration in test modes
332 * \ref CAN_TEST_BASIC_Msk Enable basic mode of test mode
333 * \ref CAN_TEST_SILENT_Msk Enable silent mode of test mode
334 * \ref CAN_TEST_LBACK_Msk Enable Loop Back Mode of test mode
335 * \ref CAN_TEST_Tx_Msk Control CAN_TX pin bit field
336 * @return None
337 * @details Switch the CAN into test mode. There are four test mode (BASIC/SILENT/LOOPBACK/
338 * LOOPBACK combined SILENT/CONTROL_TX_PIN)could be selected. After setting test mode,user
339 * must call CAN_LeaveInitMode() to let the setting take effect.
340 */
CAN_EnterTestMode(CAN_T * tCAN,uint8_t u8TestMask)341 void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask)
342 {
343 tCAN->CON |= CAN_CON_TEST_Msk;
344 tCAN->TEST = u8TestMask;
345 }
346
347
348 /**
349 * @brief Leave the test mode
350 * @param[in] tCAN The pointer to CAN module base address.
351 * @return None
352 * @details This function is used to Leave the test mode (switch into normal mode).
353 */
CAN_LeaveTestMode(CAN_T * tCAN)354 void CAN_LeaveTestMode(CAN_T *tCAN)
355 {
356 tCAN->CON |= CAN_CON_TEST_Msk;
357 tCAN->TEST &= ~(CAN_TEST_LBACK_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_BASIC_Msk);
358 tCAN->CON &= (~CAN_CON_TEST_Msk);
359 }
360
361 /**
362 * @brief Get the waiting status of a received message.
363 * @param[in] tCAN The pointer to CAN module base address.
364 * @param[in] u8MsgObj Specifies the Message object number, from 0 to 31.
365 * @retval non-zero The corresponding message object has a new data bit is set.
366 * @retval 0 No message object has new data.
367 * @details This function is used to get the waiting status of a received message.
368 */
CAN_IsNewDataReceived(CAN_T * tCAN,uint8_t u8MsgObj)369 uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj)
370 {
371 return (u8MsgObj < 16ul ? tCAN->NDAT1 & (1ul << u8MsgObj) : tCAN->NDAT2 & (1ul << (u8MsgObj - 16ul)));
372 }
373
374
375 /**
376 * @brief Send CAN message in BASIC mode of test mode
377 * @param[in] tCAN The pointer to CAN module base address.
378 * @param[in] pCanMsg Pointer to the message structure containing data to transmit.
379 * @return TRUE: Transmission OK
380 * FALSE: Check busy flag of interface 0 is timeout
381 * @details The function is used to send CAN message in BASIC mode of test mode. Before call the API,
382 * the user should be call CAN_EnterTestMode(CAN_TEST_BASIC) and let CAN controller enter
383 * basic mode of test mode. Please notice IF1 Registers used as Tx Buffer in basic mode.
384 */
CAN_BasicSendMsg(CAN_T * tCAN,STR_CANMSG_T * pCanMsg)385 int32_t CAN_BasicSendMsg(CAN_T *tCAN, STR_CANMSG_T* pCanMsg)
386 {
387 uint32_t i = 0ul;
388 int32_t rev = 1l;
389
390 while(tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk)
391 {
392 }
393
394 tCAN->STATUS &= (~CAN_STATUS_TXOK_Msk);
395
396 if(pCanMsg->IdType == CAN_STD_ID)
397 {
398 /* standard ID*/
399 tCAN->IF[0].ARB1 = 0ul;
400 tCAN->IF[0].ARB2 = (((pCanMsg->Id) & 0x7FFul) << 2ul) ;
401 }
402 else
403 {
404 /* extended ID*/
405 tCAN->IF[0].ARB1 = (pCanMsg->Id) & 0xFFFFul;
406 tCAN->IF[0].ARB2 = ((pCanMsg->Id) & 0x1FFF0000ul) >> 16ul | CAN_IF_ARB2_XTD_Msk;
407
408 }
409
410 if(pCanMsg->FrameType)
411 {
412 tCAN->IF[0].ARB2 |= CAN_IF_ARB2_DIR_Msk;
413 }
414 else
415 {
416 tCAN->IF[0].ARB2 &= (~CAN_IF_ARB2_DIR_Msk);
417 }
418
419 tCAN->IF[0].MCON = (tCAN->IF[0].MCON & (~CAN_IF_MCON_DLC_Msk)) | pCanMsg->DLC;
420 tCAN->IF[0].DAT_A1 = (uint16_t)((uint16_t)((uint16_t)pCanMsg->Data[1] << 8) | pCanMsg->Data[0]);
421 tCAN->IF[0].DAT_A2 = (uint16_t)((uint16_t)((uint16_t)pCanMsg->Data[3] << 8) | pCanMsg->Data[2]);
422 tCAN->IF[0].DAT_B1 = (uint16_t)((uint16_t)((uint16_t)pCanMsg->Data[5] << 8) | pCanMsg->Data[4]);
423 tCAN->IF[0].DAT_B2 = (uint16_t)((uint16_t)((uint16_t)pCanMsg->Data[7] << 8) | pCanMsg->Data[6]);
424
425 /* request transmission*/
426 tCAN->IF[0].CREQ &= (~CAN_IF_CREQ_BUSY_Msk);
427 if(tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk)
428 {
429 /* Cannot clear busy for sending ...*/
430 rev = 0l; /* return FALSE */
431 }
432 else
433 {
434 tCAN->IF[0].CREQ |= CAN_IF_CREQ_BUSY_Msk; /* sending */
435
436 for(i = 0ul; i < 0xFFFFFul; i++)
437 {
438 if((tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0ul)
439 {
440 break;
441 }
442 else
443 {
444 }
445 }
446
447 if(i >= 0xFFFFFul)
448 {
449 /* Cannot send out... */
450 rev = 0l; /* return FALSE */
451 }
452 else
453 {
454 }
455 }
456
457 return rev;
458 }
459
460 /**
461 * @brief Get a message information in BASIC mode.
462 *
463 * @param[in] tCAN The pointer to CAN module base address.
464 * @param[in] pCanMsg Pointer to the message structure where received data is copied.
465 *
466 * @return FALSE No any message received.
467 * TRUE Receive a message success.
468 *
469 */
CAN_BasicReceiveMsg(CAN_T * tCAN,STR_CANMSG_T * pCanMsg)470 int32_t CAN_BasicReceiveMsg(CAN_T *tCAN, STR_CANMSG_T* pCanMsg)
471 {
472 int32_t rev = 1l;
473
474 if((tCAN->IF[1].MCON & CAN_IF_MCON_NEWDAT_Msk) == 0ul)
475 {
476 /* In basic mode, receive data always save in IF2 */
477 rev = 0; /* return FALSE */
478 }
479 else
480 {
481
482 tCAN->STATUS &= (~CAN_STATUS_RXOK_Msk);
483
484 tCAN->IF[1].CMASK = CAN_IF_CMASK_ARB_Msk
485 | CAN_IF_CMASK_CONTROL_Msk
486 | CAN_IF_CMASK_DATAA_Msk
487 | CAN_IF_CMASK_DATAB_Msk;
488
489 if((tCAN->IF[1].ARB2 & CAN_IF_ARB2_XTD_Msk) == 0ul)
490 {
491 /* standard ID*/
492 pCanMsg->IdType = CAN_STD_ID;
493 pCanMsg->Id = (tCAN->IF[1].ARB2 >> 2) & 0x07FFul;
494
495 }
496 else
497 {
498 /* extended ID*/
499 pCanMsg->IdType = CAN_EXT_ID;
500 pCanMsg->Id = (tCAN->IF[1].ARB2 & 0x1FFFul) << 16;
501 pCanMsg->Id |= (uint32_t)tCAN->IF[1].ARB1;
502 }
503
504 pCanMsg->FrameType = (((tCAN->IF[1].ARB2 & CAN_IF_ARB2_DIR_Msk) >> CAN_IF_ARB2_DIR_Pos)) ? 0ul : 1ul;
505
506 pCanMsg->DLC = (uint8_t)(tCAN->IF[1].MCON & CAN_IF_MCON_DLC_Msk);
507 pCanMsg->Data[0] = (uint8_t)(tCAN->IF[1].DAT_A1 & CAN_IF_DAT_A1_DATA0_Msk);
508 pCanMsg->Data[1] = (uint8_t)((tCAN->IF[1].DAT_A1 & CAN_IF_DAT_A1_DATA1_Msk) >> CAN_IF_DAT_A1_DATA1_Pos);
509 pCanMsg->Data[2] = (uint8_t)(tCAN->IF[1].DAT_A2 & CAN_IF_DAT_A2_DATA2_Msk);
510 pCanMsg->Data[3] = (uint8_t)((tCAN->IF[1].DAT_A2 & CAN_IF_DAT_A2_DATA3_Msk) >> CAN_IF_DAT_A2_DATA3_Pos);
511 pCanMsg->Data[4] = (uint8_t)(tCAN->IF[1].DAT_B1 & CAN_IF_DAT_B1_DATA4_Msk);
512 pCanMsg->Data[5] = (uint8_t)((tCAN->IF[1].DAT_B1 & CAN_IF_DAT_B1_DATA5_Msk) >> CAN_IF_DAT_B1_DATA5_Pos);
513 pCanMsg->Data[6] = (uint8_t)(tCAN->IF[1].DAT_B2 & CAN_IF_DAT_B2_DATA6_Msk);
514 pCanMsg->Data[7] = (uint8_t)((tCAN->IF[1].DAT_B2 & CAN_IF_DAT_B2_DATA7_Msk) >> CAN_IF_DAT_B2_DATA7_Pos);
515 }
516
517 return rev;
518 }
519
520 /**
521 * @brief Set Rx message object, include ID mask.
522 * @param[in] tCAN The pointer to CAN module base address.
523 * @param[in] u8MsgObj Specifies the Message object number, from 0 to 31.
524 * @param[in] u8idType Specifies the identifier type of the frames that will be transmitted
525 * This parameter can be one of the following values:
526 * \ref CAN_STD_ID (standard ID, 11-bit)
527 * \ref CAN_EXT_ID (extended ID, 29-bit)
528 * @param[in] u32id Specifies the identifier used for acceptance filtering.
529 * @param[in] u32idmask Specifies the identifier mask used for acceptance filtering.
530 * @param[in] u8singleOrFifoLast Specifies the end-of-buffer indicator.
531 * This parameter can be one of the following values:
532 * TRUE: for a single receive object or a FIFO receive object that is the last one of the FIFO.
533 * FALSE: for a FIFO receive object that is not the last one.
534 * @retval TRUE SUCCESS
535 * @retval FALSE No useful interface
536 * @details The function is used to configure a receive message object.
537 */
CAN_SetRxMsgObjAndMsk(CAN_T * tCAN,uint8_t u8MsgObj,uint8_t u8idType,uint32_t u32id,uint32_t u32idmask,uint8_t u8singleOrFifoLast)538 int32_t CAN_SetRxMsgObjAndMsk(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8idType, uint32_t u32id, uint32_t u32idmask, uint8_t u8singleOrFifoLast)
539 {
540 int32_t rev = 1l;
541 uint32_t u32MsgIfNum;
542
543 /* Get and lock a free interface */
544 if((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul)
545 {
546 rev = 0; /* return FALSE */
547 }
548 else
549 {
550 /* Command Setting */
551 tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_WRRD_Msk | CAN_IF_CMASK_MASK_Msk | CAN_IF_CMASK_ARB_Msk |
552 CAN_IF_CMASK_CONTROL_Msk | CAN_IF_CMASK_DATAA_Msk | CAN_IF_CMASK_DATAB_Msk;
553
554 if(u8idType == CAN_STD_ID) /* According STD/EXT ID format,Configure Mask and Arbitration register */
555 {
556 tCAN->IF[u32MsgIfNum].ARB1 = 0ul;
557 tCAN->IF[u32MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | (u32id & 0x7FFul) << 2;
558 }
559 else
560 {
561 tCAN->IF[u32MsgIfNum].ARB1 = u32id & 0xFFFFul;
562 tCAN->IF[u32MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | CAN_IF_ARB2_XTD_Msk | (u32id & 0x1FFF0000ul) >> 16;
563 }
564
565 tCAN->IF[u32MsgIfNum].MASK1 = (u32idmask & 0xFFFFul);
566 tCAN->IF[u32MsgIfNum].MASK2 = (u32idmask >> 16) & 0xFFFFul;
567
568 /* tCAN->IF[u32MsgIfNum].MCON |= CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk; */
569 tCAN->IF[u32MsgIfNum].MCON = CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk;
570 if(u8singleOrFifoLast)
571 {
572 tCAN->IF[u32MsgIfNum].MCON |= CAN_IF_MCON_EOB_Msk;
573 }
574 else
575 {
576 tCAN->IF[u32MsgIfNum].MCON &= (~CAN_IF_MCON_EOB_Msk);
577 }
578
579 tCAN->IF[u32MsgIfNum].DAT_A1 = 0ul;
580 tCAN->IF[u32MsgIfNum].DAT_A2 = 0ul;
581 tCAN->IF[u32MsgIfNum].DAT_B1 = 0ul;
582 tCAN->IF[u32MsgIfNum].DAT_B2 = 0ul;
583
584 tCAN->IF[u32MsgIfNum].CREQ = 1ul + u8MsgObj;
585 ReleaseIF(tCAN, u32MsgIfNum);
586 }
587
588 return rev;
589 }
590
591 /**
592 * @brief Set Rx message object
593 * @param[in] tCAN The pointer to CAN module base address.
594 * @param[in] u8MsgObj Specifies the Message object number, from 0 to 31.
595 * @param[in] u8idType Specifies the identifier type of the frames that will be transmitted
596 * This parameter can be one of the following values:
597 * \ref CAN_STD_ID (standard ID, 11-bit)
598 * \ref CAN_EXT_ID (extended ID, 29-bit)
599 * @param[in] u32id Specifies the identifier used for acceptance filtering.
600 * @param[in] u8singleOrFifoLast Specifies the end-of-buffer indicator.
601 * This parameter can be one of the following values:
602 * TRUE: for a single receive object or a FIFO receive object that is the last one of the FIFO.
603 * FALSE: for a FIFO receive object that is not the last one.
604 * @retval TRUE SUCCESS
605 * @retval FALSE No useful interface
606 * @details The function is used to configure a receive message object.
607 */
CAN_SetRxMsgObj(CAN_T * tCAN,uint8_t u8MsgObj,uint8_t u8idType,uint32_t u32id,uint8_t u8singleOrFifoLast)608 int32_t CAN_SetRxMsgObj(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8idType, uint32_t u32id, uint8_t u8singleOrFifoLast)
609 {
610 int32_t rev = 1l;
611 uint32_t u32MsgIfNum;
612
613 /* Get and lock a free interface */
614 if((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul)
615 {
616 rev = 0; /* return FALSE */
617 }
618 else
619 {
620 /* Command Setting */
621 tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_WRRD_Msk | CAN_IF_CMASK_MASK_Msk | CAN_IF_CMASK_ARB_Msk |
622 CAN_IF_CMASK_CONTROL_Msk | CAN_IF_CMASK_DATAA_Msk | CAN_IF_CMASK_DATAB_Msk;
623
624 if(u8idType == CAN_STD_ID) /* According STD/EXT ID format,Configure Mask and Arbitration register */
625 {
626 tCAN->IF[u32MsgIfNum].ARB1 = 0ul;
627 tCAN->IF[u32MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | (u32id & 0x7FFul) << 2;
628 }
629 else
630 {
631 tCAN->IF[u32MsgIfNum].ARB1 = u32id & 0xFFFFul;
632 tCAN->IF[u32MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | CAN_IF_ARB2_XTD_Msk | (u32id & 0x1FFF0000ul) >> 16;
633 }
634
635 /* tCAN->IF[u8MsgIfNum].MCON |= CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk; */
636 tCAN->IF[u32MsgIfNum].MCON = CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk;
637 if(u8singleOrFifoLast)
638 {
639 tCAN->IF[u32MsgIfNum].MCON |= CAN_IF_MCON_EOB_Msk;
640 }
641 else
642 {
643 tCAN->IF[u32MsgIfNum].MCON &= (~CAN_IF_MCON_EOB_Msk);
644 }
645
646 tCAN->IF[u32MsgIfNum].DAT_A1 = 0ul;
647 tCAN->IF[u32MsgIfNum].DAT_A2 = 0ul;
648 tCAN->IF[u32MsgIfNum].DAT_B1 = 0ul;
649 tCAN->IF[u32MsgIfNum].DAT_B2 = 0ul;
650
651 tCAN->IF[u32MsgIfNum].CREQ = 1ul + u8MsgObj;
652 ReleaseIF(tCAN, u32MsgIfNum);
653 }
654
655 return rev;
656 }
657
658 /**
659 * @brief Gets the message
660 * @param[in] tCAN The pointer to CAN module base address.
661 * @param[in] u8MsgObj Specifies the Message object number, from 0 to 31.
662 * @param[in] u8Release Specifies the message release indicator.
663 * This parameter can be one of the following values:
664 * TRUE: the message object is released when getting the data.
665 * FALSE:the message object is not released.
666 * @param[in] pCanMsg Pointer to the message structure where received data is copied.
667 * @retval TRUE Success
668 * @retval FALSE No any message received
669 * @details Gets the message, if received.
670 */
CAN_ReadMsgObj(CAN_T * tCAN,uint8_t u8MsgObj,uint8_t u8Release,STR_CANMSG_T * pCanMsg)671 int32_t CAN_ReadMsgObj(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8Release, STR_CANMSG_T* pCanMsg)
672 {
673 int32_t rev = 1l;
674 uint32_t u32MsgIfNum;
675
676 if(!CAN_IsNewDataReceived(tCAN, u8MsgObj))
677 {
678 rev = 0; /* return FALSE */
679 }
680 else
681 {
682 /* Get and lock a free interface */
683 if((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul)
684 {
685 rev = 0; /* return FALSE */
686 }
687 else
688 {
689 tCAN->STATUS &= (~CAN_STATUS_RXOK_Msk);
690
691 /* read the message contents*/
692 tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_MASK_Msk
693 | CAN_IF_CMASK_ARB_Msk
694 | CAN_IF_CMASK_CONTROL_Msk
695 | CAN_IF_CMASK_CLRINTPND_Msk
696 | (u8Release ? CAN_IF_CMASK_TXRQSTNEWDAT_Msk : 0ul)
697 | CAN_IF_CMASK_DATAA_Msk
698 | CAN_IF_CMASK_DATAB_Msk;
699
700 tCAN->IF[u32MsgIfNum].CREQ = 1ul + u8MsgObj;
701
702 while(tCAN->IF[u32MsgIfNum].CREQ & CAN_IF_CREQ_BUSY_Msk)
703 {
704 /*Wait*/
705 }
706
707 if((tCAN->IF[u32MsgIfNum].ARB2 & CAN_IF_ARB2_XTD_Msk) == 0ul)
708 {
709 /* standard ID*/
710 pCanMsg->IdType = CAN_STD_ID;
711 pCanMsg->Id = (tCAN->IF[u32MsgIfNum].ARB2 & CAN_IF_ARB2_ID_Msk) >> 2ul;
712 }
713 else
714 {
715 /* extended ID*/
716 pCanMsg->IdType = CAN_EXT_ID;
717 pCanMsg->Id = (((tCAN->IF[u32MsgIfNum].ARB2) & 0x1FFFul) << 16) | tCAN->IF[u32MsgIfNum].ARB1;
718 }
719
720 pCanMsg->DLC = (uint8_t)(tCAN->IF[u32MsgIfNum].MCON & CAN_IF_MCON_DLC_Msk);
721 pCanMsg->Data[0] = (uint8_t)(tCAN->IF[u32MsgIfNum].DAT_A1 & CAN_IF_DAT_A1_DATA0_Msk);
722 pCanMsg->Data[1] = (uint8_t)((tCAN->IF[u32MsgIfNum].DAT_A1 & CAN_IF_DAT_A1_DATA1_Msk) >> CAN_IF_DAT_A1_DATA1_Pos);
723 pCanMsg->Data[2] = (uint8_t)(tCAN->IF[u32MsgIfNum].DAT_A2 & CAN_IF_DAT_A2_DATA2_Msk);
724 pCanMsg->Data[3] = (uint8_t)((tCAN->IF[u32MsgIfNum].DAT_A2 & CAN_IF_DAT_A2_DATA3_Msk) >> CAN_IF_DAT_A2_DATA3_Pos);
725 pCanMsg->Data[4] = (uint8_t)(tCAN->IF[u32MsgIfNum].DAT_B1 & CAN_IF_DAT_B1_DATA4_Msk);
726 pCanMsg->Data[5] = (uint8_t)((tCAN->IF[u32MsgIfNum].DAT_B1 & CAN_IF_DAT_B1_DATA5_Msk) >> CAN_IF_DAT_B1_DATA5_Pos);
727 pCanMsg->Data[6] = (uint8_t)(tCAN->IF[u32MsgIfNum].DAT_B2 & CAN_IF_DAT_B2_DATA6_Msk);
728 pCanMsg->Data[7] = (uint8_t)((tCAN->IF[u32MsgIfNum].DAT_B2 & CAN_IF_DAT_B2_DATA7_Msk) >> CAN_IF_DAT_B2_DATA7_Pos);
729
730 ReleaseIF(tCAN, u32MsgIfNum);
731 }
732 }
733
734 return rev;
735 }
736
737
738 /**
739 * @brief Set bus baud-rate.
740 *
741 * @param[in] tCAN The pointer to CAN module base address.
742 * @param[in] u32BaudRate The target CAN baud-rate. The range of u32BaudRate is 1~1000KHz.
743 *
744 * @return u32CurrentBitRate Real baud-rate value.
745 *
746 * @details The function is used to set bus timing parameter according current clock and target baud-rate.
747 */
CAN_SetBaudRate(CAN_T * tCAN,uint32_t u32BaudRate)748 uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate)
749 {
750 long rate;
751 long best_error = 1000000000, error = 0;
752 int best_tseg = 0, best_brp = 0, brp = 0;
753 int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
754 int spt_error = 1000, spt = 0, sampl_pt;
755 uint64_t clock_freq = (uint64_t)0, u64PCLK_DIV = (uint64_t)1;
756 uint32_t sjw = (uint32_t)1;
757
758 CAN_EnterInitMode(tCAN, (uint8_t)0);
759
760 SystemCoreClockUpdate();
761 if((tCAN == CAN0) || (tCAN == CAN2))
762 {
763 u64PCLK_DIV = (uint64_t)(CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk);
764 u64PCLK_DIV = (uint64_t)(1 << u64PCLK_DIV);
765 }
766 else if(tCAN == CAN1)
767 {
768 u64PCLK_DIV = (uint64_t)((CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) >> CLK_PCLKDIV_APB1DIV_Pos);
769 u64PCLK_DIV = (uint64_t)(1 << u64PCLK_DIV);
770 }
771
772 clock_freq = SystemCoreClock / u64PCLK_DIV;
773
774 if(u32BaudRate >= (uint32_t)1000000)
775 {
776 u32BaudRate = (uint32_t)1000000;
777 }
778
779 /* Use CIA recommended sample points */
780 if (u32BaudRate > (uint32_t)800000)
781 {
782 sampl_pt = (int)750;
783 }
784 else if (u32BaudRate > (uint32_t)500000)
785 {
786 sampl_pt = (int)800;
787 }
788 else
789 {
790 sampl_pt = (int)875;
791 }
792
793 /* tseg even = round down, odd = round up */
794 for (tseg = (TSEG1_MAX + TSEG2_MAX) * 2ul + 1ul; tseg >= (TSEG1_MIN + TSEG2_MIN) * 2ul; tseg--)
795 {
796 tsegall = 1ul + tseg / 2ul;
797 /* Compute all possible tseg choices (tseg=tseg1+tseg2) */
798 brp = clock_freq / (tsegall * u32BaudRate) + tseg % 2;
799 /* chose brp step which is possible in system */
800 brp = (brp / BRP_INC) * BRP_INC;
801
802 if ((brp < BRP_MIN) || (brp > BRP_MAX))
803 {
804 continue;
805 }
806 rate = clock_freq / (brp * tsegall);
807
808 error = u32BaudRate - rate;
809
810 /* tseg brp biterror */
811 if (error < 0)
812 {
813 error = -error;
814 }
815 if (error > best_error)
816 {
817 continue;
818 }
819 best_error = error;
820 if (error == 0)
821 {
822 spt = can_update_spt(sampl_pt, tseg / 2, &tseg1, &tseg2);
823 error = sampl_pt - spt;
824 if (error < 0)
825 {
826 error = -error;
827 }
828 if (error > spt_error)
829 {
830 continue;
831 }
832 spt_error = error;
833 }
834 best_tseg = tseg / 2;
835 best_brp = brp;
836
837 if (error == 0)
838 {
839 break;
840 }
841 }
842
843 spt = can_update_spt(sampl_pt, best_tseg, &tseg1, &tseg2);
844
845 /* check for sjw user settings */
846 /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
847 if (sjw > SJW_MAX)
848 {
849 sjw = SJW_MAX;
850 }
851 /* bt->sjw must not be higher than tseg2 */
852 if (tseg2 < sjw)
853 {
854 sjw = tseg2;
855 }
856
857 /* real bit-rate */
858 u32BaudRate = clock_freq / (best_brp * (tseg1 + tseg2 + 1));
859
860 tCAN->BTIME = ((uint32_t)(tseg2 - 1ul) << CAN_BTIME_TSEG2_Pos) | ((uint32_t)(tseg1 - 1ul) << CAN_BTIME_TSEG1_Pos) |
861 ((uint32_t)(best_brp - 1ul) & CAN_BTIME_BRP_Msk) | (sjw << CAN_BTIME_SJW_Pos);
862 tCAN->BRPE = ((uint32_t)(best_brp - 1ul) >> 6) & 0x0Ful;
863
864 /* printf("\n bitrate = %d \n", CAN_GetCANBitRate(tCAN)); */
865
866 CAN_LeaveInitMode(tCAN);
867
868 return u32BaudRate;
869 }
870
871 /**
872 * @brief The function is used to disable all CAN interrupt.
873 *
874 * @param[in] tCAN The pointer to CAN module base address.
875 *
876 * @return None
877 *
878 * @details No Status Change Interrupt and Error Status Interrupt will be generated.
879 */
CAN_Close(CAN_T * tCAN)880 void CAN_Close(CAN_T *tCAN)
881 {
882 CAN_DisableInt(tCAN, (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk));
883 }
884
885 /**
886 * @brief Set CAN operation mode and target baud-rate.
887 *
888 * @param[in] tCAN The pointer to CAN module base address.
889 * @param[in] u32BaudRate The target CAN baud-rate. The range of u32BaudRate is 1~1000KHz.
890 * @param[in] u32Mode The CAN operation mode. Valid values are:
891 * - \ref CAN_NORMAL_MODE Normal operation.
892 * - \ref CAN_BASIC_MODE Basic mode.
893 * @return u32CurrentBitRate Real baud-rate value.
894 *
895 * @details Set bus timing parameter according current clock and target baud-rate.
896 * In Basic mode, IF1 Registers used as Tx Buffer, IF2 Registers used as Rx Buffer.
897 */
CAN_Open(CAN_T * tCAN,uint32_t u32BaudRate,uint32_t u32Mode)898 uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode)
899 {
900 uint32_t u32CurrentBitRate;
901
902 u32CurrentBitRate = CAN_SetBaudRate(tCAN, u32BaudRate);
903
904 if(u32Mode == CAN_BASIC_MODE)
905 {
906 CAN_EnterTestMode(tCAN, (uint8_t)CAN_TEST_BASIC_Msk);
907 }
908 else
909 {
910 }
911
912 return u32CurrentBitRate;
913 }
914
915 /**
916 * @brief The function is used to configure a transmit object.
917 *
918 * @param[in] tCAN The pointer to CAN module base address.
919 * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31.
920 * @param[in] pCanMsg Pointer to the message structure where received data is copied.
921 *
922 * @retval FALSE No useful interface.
923 * @retval TRUE Config message object success.
924 *
925 * @details The two sets of interface registers (IF1 and IF2) control the software access to the Message RAM.
926 * They buffer the data to be transferred to and from the RAM, avoiding conflicts between software accesses and message reception/transmission.
927 */
CAN_SetTxMsg(CAN_T * tCAN,uint32_t u32MsgNum,STR_CANMSG_T * pCanMsg)928 int32_t CAN_SetTxMsg(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg)
929 {
930 int32_t rev = 1l;
931 uint32_t u32MsgIfNum;
932
933 if((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul)
934 {
935 rev = 0; /* return FALSE */
936 }
937 else
938 {
939 /* update the contents needed for transmission*/
940 tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_WRRD_Msk | CAN_IF_CMASK_MASK_Msk | CAN_IF_CMASK_ARB_Msk |
941 CAN_IF_CMASK_CONTROL_Msk | CAN_IF_CMASK_DATAA_Msk | CAN_IF_CMASK_DATAB_Msk;
942
943 if(pCanMsg->IdType == CAN_STD_ID)
944 {
945 /* standard ID*/
946 tCAN->IF[u32MsgIfNum].ARB1 = 0ul;
947 tCAN->IF[u32MsgIfNum].ARB2 = (((pCanMsg->Id) & 0x7FFul) << 2) | CAN_IF_ARB2_DIR_Msk | CAN_IF_ARB2_MSGVAL_Msk;
948 }
949 else
950 {
951 /* extended ID*/
952 tCAN->IF[u32MsgIfNum].ARB1 = (pCanMsg->Id) & 0xFFFFul;
953 tCAN->IF[u32MsgIfNum].ARB2 = ((pCanMsg->Id) & 0x1FFF0000ul) >> 16 |
954 CAN_IF_ARB2_DIR_Msk | CAN_IF_ARB2_XTD_Msk | CAN_IF_ARB2_MSGVAL_Msk;
955 }
956
957 if(pCanMsg->FrameType)
958 {
959 tCAN->IF[u32MsgIfNum].ARB2 |= CAN_IF_ARB2_DIR_Msk;
960 }
961 else
962 {
963 tCAN->IF[u32MsgIfNum].ARB2 &= (~CAN_IF_ARB2_DIR_Msk);
964 }
965
966 tCAN->IF[u32MsgIfNum].DAT_A1 = (uint16_t)((uint16_t)(((uint16_t)pCanMsg->Data[1] << 8)) | pCanMsg->Data[0]);
967 tCAN->IF[u32MsgIfNum].DAT_A2 = (uint16_t)((uint16_t)(((uint16_t)pCanMsg->Data[3] << 8)) | pCanMsg->Data[2]);
968 tCAN->IF[u32MsgIfNum].DAT_B1 = (uint16_t)((uint16_t)(((uint16_t)pCanMsg->Data[5] << 8)) | pCanMsg->Data[4]);
969 tCAN->IF[u32MsgIfNum].DAT_B2 = (uint16_t)((uint16_t)(((uint16_t)pCanMsg->Data[7] << 8)) | pCanMsg->Data[6]);
970
971 tCAN->IF[u32MsgIfNum].MCON = CAN_IF_MCON_NEWDAT_Msk | pCanMsg->DLC | CAN_IF_MCON_TXIE_Msk | CAN_IF_MCON_EOB_Msk;
972 tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum;
973
974 ReleaseIF(tCAN, u32MsgIfNum);
975 }
976
977 return rev;
978 }
979
980 /**
981 * @brief Set transmit request bit.
982 *
983 * @param[in] tCAN The pointer to CAN module base address.
984 * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31.
985 *
986 * @return TRUE: Start transmit message.
987 *
988 * @details If a transmission is requested by programming bit TxRqst/NewDat (IFn_CMASK[2]), the TxRqst (IFn_MCON[8]) will be ignored.
989 */
CAN_TriggerTxMsg(CAN_T * tCAN,uint32_t u32MsgNum)990 int32_t CAN_TriggerTxMsg(CAN_T *tCAN, uint32_t u32MsgNum)
991 {
992 int32_t rev = 1l;
993 uint32_t u32MsgIfNum;
994
995 if((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul)
996 {
997 rev = 0; /* return FALSE */
998 }
999 else
1000 {
1001 tCAN->STATUS &= (~CAN_STATUS_TXOK_Msk);
1002
1003 /* read the message contents*/
1004 tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk
1005 | CAN_IF_CMASK_TXRQSTNEWDAT_Msk;
1006
1007 tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum;
1008
1009 while(tCAN->IF[u32MsgIfNum].CREQ & CAN_IF_CREQ_BUSY_Msk)
1010 {
1011 /*Wait*/
1012 }
1013 tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_WRRD_Msk | CAN_IF_CMASK_TXRQSTNEWDAT_Msk;
1014 tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum;
1015
1016 ReleaseIF(tCAN, u32MsgIfNum);
1017 }
1018
1019 return rev;
1020 }
1021
1022 /**
1023 * @brief Enable CAN interrupt.
1024 *
1025 * @param[in] tCAN The pointer to CAN module base address.
1026 * @param[in] u32Mask Interrupt Mask. Valid values are:
1027 * - \ref CAN_CON_IE_Msk Module interrupt enable.
1028 * - \ref CAN_CON_SIE_Msk Status change interrupt enable.
1029 * - \ref CAN_CON_EIE_Msk Error interrupt enable.
1030 *
1031 * @return None
1032 *
1033 * @details The application software has two possibilities to follow the source of a message interrupt.
1034 * First, it can follow the IntId in the Interrupt Register and second it can poll the Interrupt Pending Register.
1035 */
CAN_EnableInt(CAN_T * tCAN,uint32_t u32Mask)1036 void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask)
1037 {
1038 tCAN->CON = (tCAN->CON & ~(CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) |
1039 (u32Mask & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk));
1040 }
1041
1042 /**
1043 * @brief Disable CAN interrupt.
1044 *
1045 * @param[in] tCAN The pointer to CAN module base address.
1046 * @param[in] u32Mask Interrupt Mask. (CAN_CON_IE_Msk / CAN_CON_SIE_Msk / CAN_CON_EIE_Msk).
1047 *
1048 * @return None
1049 *
1050 * @details The interrupt remains active until the Interrupt Register is back to value zero (the cause of the interrupt is reset) or until IE is reset.
1051 */
CAN_DisableInt(CAN_T * tCAN,uint32_t u32Mask)1052 void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask)
1053 {
1054 tCAN->CON = tCAN->CON & ~((u32Mask & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)));
1055 }
1056
1057
1058 /**
1059 * @brief The function is used to configure a receive message object.
1060 *
1061 * @param[in] tCAN The pointer to CAN module base address.
1062 * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31.
1063 * @param[in] u32IDType Specifies the identifier type of the frames that will be transmitted. Valid values are:
1064 * - \ref CAN_STD_ID The 11-bit identifier.
1065 * - \ref CAN_EXT_ID The 29-bit identifier.
1066 * @param[in] u32ID Specifies the identifier used for acceptance filtering.
1067 *
1068 * @retval FALSE No useful interface.
1069 * @retval TRUE Configure a receive message object success.
1070 *
1071 * @details If the RxIE bit (CAN_IFn_MCON[10]) is set, the IntPnd bit (CAN_IFn_MCON[13])
1072 * will be set when a received Data Frame is accepted and stored in the Message Object.
1073 */
CAN_SetRxMsg(CAN_T * tCAN,uint32_t u32MsgNum,uint32_t u32IDType,uint32_t u32ID)1074 int32_t CAN_SetRxMsg(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, uint32_t u32ID)
1075 {
1076 int32_t rev = (int32_t)TRUE;
1077 uint32_t u32TimeOutCount = 0ul;
1078
1079 while(CAN_SetRxMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, (uint8_t)TRUE) == (int32_t)FALSE)
1080 {
1081 if(++u32TimeOutCount >= RETRY_COUNTS)
1082 {
1083 rev = (int32_t)(FALSE); /* return FALSE */
1084 break;
1085 }
1086 else
1087 {
1088 }
1089 }
1090
1091 return rev;
1092 }
1093
1094 /**
1095 * @brief The function is used to configure a receive message object.
1096 *
1097 * @param[in] tCAN The pointer to CAN module base address.
1098 * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31.
1099 * @param[in] u32IDType Specifies the identifier type of the frames that will be transmitted. Valid values are:
1100 * - \ref CAN_STD_ID The 11-bit identifier.
1101 * - \ref CAN_EXT_ID The 29-bit identifier.
1102 * @param[in] u32ID Specifies the identifier used for acceptance filtering.
1103 * @param[in] u32IDMask Specifies the identifier mask used for acceptance filtering.
1104 *
1105 * @retval FALSE No useful interface.
1106 * @retval TRUE Configure a receive message object success.
1107 *
1108 * @details If the RxIE bit (CAN_IFn_MCON[10]) is set, the IntPnd bit (CAN_IFn_MCON[13])
1109 * will be set when a received Data Frame is accepted and stored in the Message Object.
1110 */
CAN_SetRxMsgAndMsk(CAN_T * tCAN,uint32_t u32MsgNum,uint32_t u32IDType,uint32_t u32ID,uint32_t u32IDMask)1111 int32_t CAN_SetRxMsgAndMsk(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, uint32_t u32ID, uint32_t u32IDMask)
1112 {
1113 int32_t rev = (int32_t)TRUE;
1114 uint32_t u32TimeOutCount = 0ul;
1115
1116 while(CAN_SetRxMsgObjAndMsk(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, u32IDMask, (uint8_t)TRUE) == (int32_t)FALSE)
1117 {
1118 if(++u32TimeOutCount >= RETRY_COUNTS)
1119 {
1120 rev = (int32_t)FALSE;
1121 break;
1122 }
1123 else
1124 {
1125 }
1126 }
1127
1128 return rev;
1129 }
1130
1131 /**
1132 * @brief The function is used to configure several receive message objects.
1133 *
1134 * @param[in] tCAN The pointer to CAN module base address.
1135 * @param[in] u32MsgNum The starting MSG RAM number(0 ~ 31).
1136 * @param[in] u32MsgCount the number of MSG RAM of the FIFO.
1137 * @param[in] u32IDType Specifies the identifier type of the frames that will be transmitted. Valid values are:
1138 * - \ref CAN_STD_ID The 11-bit identifier.
1139 * - \ref CAN_EXT_ID The 29-bit identifier.
1140 * @param[in] u32ID Specifies the identifier used for acceptance filtering.
1141 *
1142 * @retval FALSE No useful interface.
1143 * @retval TRUE Configure receive message objects success.
1144 *
1145 * @details The Interface Registers avoid conflict between the CPU accesses to the Message RAM and CAN message reception
1146 * and transmission by buffering the data to be transferred.
1147 */
CAN_SetMultiRxMsg(CAN_T * tCAN,uint32_t u32MsgNum,uint32_t u32MsgCount,uint32_t u32IDType,uint32_t u32ID)1148 int32_t CAN_SetMultiRxMsg(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32MsgCount, uint32_t u32IDType, uint32_t u32ID)
1149 {
1150 int32_t rev = (int32_t)TRUE;
1151 uint32_t i = 0ul;
1152 uint32_t u32TimeOutCount;
1153 uint32_t u32EOB_Flag = 0ul;
1154
1155 for(i = 1ul; i < u32MsgCount; i++)
1156 {
1157 u32TimeOutCount = 0ul;
1158
1159 u32MsgNum += (i - 1ul);
1160
1161 if(i == u32MsgCount)
1162 {
1163 u32EOB_Flag = 1ul;
1164 }
1165 else
1166 {
1167 }
1168
1169 while(CAN_SetRxMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, (uint8_t)u32EOB_Flag) == (int32_t)FALSE)
1170 {
1171 if(++u32TimeOutCount >= RETRY_COUNTS)
1172 {
1173 rev = (int32_t)FALSE;
1174 break;
1175 }
1176 else
1177 {
1178 }
1179 }
1180 }
1181
1182 return rev;
1183 }
1184
1185
1186 /**
1187 * @brief Send CAN message.
1188 * @param[in] tCAN The pointer to CAN module base address.
1189 * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31.
1190 * @param[in] pCanMsg Pointer to the message structure where received data is copied.
1191 *
1192 * @retval FALSE 1. When operation in basic mode: Transmit message time out. \n
1193 * 2. When operation in normal mode: No useful interface. \n
1194 * @retval TRUE Transmit Message success.
1195 *
1196 * @details The receive/transmit priority for the Message Objects is attached to the message number.
1197 * Message Object 1 has the highest priority, while Message Object 32 has the lowest priority.
1198 */
CAN_Transmit(CAN_T * tCAN,uint32_t u32MsgNum,STR_CANMSG_T * pCanMsg)1199 int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg)
1200 {
1201 int32_t rev = (int32_t)TRUE;
1202 uint32_t u32Tmp;
1203
1204 u32Tmp = (tCAN->TEST & CAN_TEST_BASIC_Msk);
1205
1206 if((tCAN->CON & CAN_CON_TEST_Msk) && u32Tmp)
1207 {
1208 rev = CAN_BasicSendMsg(tCAN, pCanMsg);
1209 }
1210 else
1211 {
1212 if(CAN_SetTxMsg(tCAN, u32MsgNum, pCanMsg) == FALSE)
1213 {
1214 rev = (int32_t)FALSE;
1215 }
1216 else
1217 {
1218 CAN_TriggerTxMsg(tCAN, u32MsgNum);
1219 }
1220 }
1221
1222 return rev;
1223 }
1224
1225
1226 /**
1227 * @brief Gets the message, if received.
1228 * @param[in] tCAN The pointer to CAN module base address.
1229 * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31.
1230 * @param[in] pCanMsg Pointer to the message structure where received data is copied.
1231 *
1232 * @retval FALSE No any message received.
1233 * @retval TRUE Receive Message success.
1234 *
1235 * @details The Interface Registers avoid conflict between the CPU accesses to the Message RAM and CAN message reception
1236 * and transmission by buffering the data to be transferred.
1237 */
CAN_Receive(CAN_T * tCAN,uint32_t u32MsgNum,STR_CANMSG_T * pCanMsg)1238 int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg)
1239 {
1240 int32_t rev = (int32_t)TRUE;
1241 uint32_t u32Tmp;
1242
1243 u32Tmp = (tCAN->TEST & CAN_TEST_BASIC_Msk);
1244
1245 if((tCAN->CON & CAN_CON_TEST_Msk) && u32Tmp)
1246 {
1247 rev = CAN_BasicReceiveMsg(tCAN, pCanMsg);
1248 }
1249 else
1250 {
1251 rev = CAN_ReadMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)TRUE, pCanMsg);
1252 }
1253
1254 return rev;
1255 }
1256
1257 /**
1258 * @brief Clear interrupt pending bit.
1259 * @param[in] tCAN The pointer to CAN module base address.
1260 * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31.
1261 *
1262 * @return None
1263 *
1264 * @details An interrupt remains pending until the application software has cleared it.
1265 */
CAN_CLR_INT_PENDING_BIT(CAN_T * tCAN,uint8_t u32MsgNum)1266 void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum)
1267 {
1268 uint32_t u32MsgIfNum;
1269
1270 if((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul)
1271 {
1272 u32MsgIfNum = 0ul;
1273 }
1274 else
1275 {
1276 }
1277
1278 tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk | CAN_IF_CMASK_TXRQSTNEWDAT_Msk;
1279 tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum;
1280
1281 ReleaseIF(tCAN, u32MsgIfNum);
1282 }
1283
1284
1285 /*@}*/ /* end of group CAN_EXPORTED_FUNCTIONS */
1286
1287 /*@}*/ /* end of group CAN_Driver */
1288
1289 /*@}*/ /* end of group Standard_Driver */
1290
1291 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
1292
1293