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