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