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