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