1 /**************************************************************************//**
\r
4 * @brief CAN driver source file
\r
6 * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
\r
7 *****************************************************************************/
\r
10 #if defined(__ICCARM__)
\r
11 # pragma diag_suppress=Pm073, Pm143 /* Misra C rule 14.7 */
\r
15 /** @addtogroup Standard_Driver Standard Driver
\r
19 /** @addtogroup CAN_Driver CAN Driver
\r
23 /** @addtogroup CAN_EXPORTED_FUNCTIONS CAN Exported Functions
\r
27 /** @cond HIDDEN_SYMBOLS */
\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
35 #define RETRY_COUNTS (0x10000000UL)
\r
38 #define TSEG1_MAX 16
\r
42 #define BRP_MAX 1024 /* 6-bit BRP field + 4-bit BRPE field*/
\r
46 /* #define DEBUG_PRINTF printf */
\r
47 #define DEBUG_PRINTF(...)
\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
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
64 static uint32_t LockIF(CAN_T *tCAN)
\r
67 uint32_t u32FreeIfNo;
\r
68 uint32_t u32IntMask;
\r
71 u32CanNo = (tCAN == CAN1) ? 1 : 0;
\r
72 #else // defined(CAN0) || defined(CAN)
\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
82 /* Check interface 1 is available or not */
\r
83 if((tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0U)
\r
85 if(gu8LockCanIf[u32CanNo][0] == (uint8_t)FALSE)
\r
87 gu8LockCanIf[u32CanNo][0] = (uint8_t)TRUE;
\r
92 /* Or check interface 2 is available or not */
\r
93 if(u32FreeIfNo == 2U)
\r
95 if((tCAN->IF[1].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0U)
\r
97 if(gu8LockCanIf[u32CanNo][1] == (uint8_t)FALSE)
\r
99 gu8LockCanIf[u32CanNo][1] = (uint8_t)TRUE;
\r
105 /* Enable CAN interrupt */
\r
106 tCAN->CON |= u32IntMask;
\r
108 return u32FreeIfNo;
\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
121 static uint32_t LockIF_TL(CAN_T *tCAN)
\r
124 uint32_t u32FreeIfNo;
\r
126 for(u32Count = 0U; u32Count < (uint32_t)RETRY_COUNTS; u32Count++)
\r
128 if((u32FreeIfNo = LockIF(tCAN)) != 2U)
\r
134 return u32FreeIfNo;
\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
142 * @details Release the locked interface.
\r
144 static void ReleaseIF(CAN_T *tCAN, uint32_t u32IfNo)
\r
146 uint32_t u32IntMask;
\r
153 u32CanNo = (tCAN == CAN1) ? 1U : 0U;
\r
154 #else // defined(CAN0) || defined(CAN)
\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
162 gu8LockCanIf[u32CanNo][u32IfNo] = (uint8_t)FALSE;
\r
164 /* Enable CAN interrupt */
\r
165 tCAN->CON |= u32IntMask;
\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
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
183 void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask)
\r
185 tCAN->CON = u8Mask | (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk);
\r
190 * @brief Leave initialization mode
\r
191 * @param[in] tCAN The pointer to CAN module base address.
\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
196 void CAN_LeaveInitMode(CAN_T *tCAN)
\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
203 * @brief Wait message into message buffer in basic mode.
\r
204 * @param[in] tCAN The pointer to CAN module base address.
\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
209 void CAN_WaitMsg(CAN_T *tCAN)
\r
211 tCAN->STATUS = 0x0U; /* clr status */
\r
215 if(tCAN->IF[1].MCON & CAN_IF_MCON_NEWDAT_Msk) /* check new data */
\r
217 /* DEBUG_PRINTF("New Data IN\n"); */
\r
221 if(tCAN->STATUS & CAN_STATUS_RXOK_Msk)
\r
223 /* DEBUG_PRINTF("Rx OK\n"); */
\r
226 if(tCAN->STATUS & CAN_STATUS_LEC_Msk)
\r
228 /* DEBUG_PRINTF("Error\n"); */
\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
239 uint32_t CAN_GetCANBitRate(CAN_T *tCAN)
\r
241 uint8_t u8Tseg1, u8Tseg2;
\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
250 return (SystemCoreClock / (u32Bpr + 1U) / ((uint32_t)u8Tseg1 + (uint32_t)u8Tseg2 + 3U));
\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
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
266 void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask)
\r
268 tCAN->CON |= CAN_CON_TEST_Msk;
\r
269 tCAN->TEST = u8TestMask;
\r
274 * @brief Leave the test mode
\r
275 * @param[in] tCAN The pointer to CAN module base address.
\r
277 * @details This function is used to Leave the test mode (switch into normal mode).
\r
279 void CAN_LeaveTestMode(CAN_T *tCAN)
\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
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
294 uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj)
\r
298 if((uint32_t)u8MsgObj < 16U)
\r
300 ret = tCAN->NDAT1 & (1UL << u8MsgObj);
\r
304 ret = tCAN->NDAT2 & (1UL << (u8MsgObj - 16U));
\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
321 int32_t CAN_BasicSendMsg(CAN_T *tCAN, STR_CANMSG_T* pCanMsg)
\r
324 while(tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) {}
\r
327 tCAN->STATUS &= (~CAN_STATUS_TXOK_Msk);
\r
329 if(pCanMsg->IdType == CAN_STD_ID)
\r
332 tCAN->IF[0].ARB1 = 0UL;
\r
333 tCAN->IF[0].ARB2 = (((pCanMsg->Id) & 0x7FFUL) << 2) ;
\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
343 if(pCanMsg->FrameType)
\r
345 tCAN->IF[0].ARB2 |= CAN_IF_ARB2_DIR_Msk;
\r
349 tCAN->IF[0].ARB2 &= (~CAN_IF_ARB2_DIR_Msk);
\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
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
362 /* DEBUG_PRINTF("Cannot clear busy for sending ...\n"); */
\r
363 return (int32_t)FALSE;
\r
366 tCAN->IF[0].CREQ |= CAN_IF_CREQ_BUSY_Msk; /* sending */
\r
368 for(i = 0UL; i < 0xFFFFFUL; i++)
\r
370 if((tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0UL)
\r
378 /* DEBUG_PRINTF("Cannot send out...\n"); */
\r
379 return (int32_t)FALSE;
\r
383 return (int32_t)TRUE;
\r
387 * @brief Get a message information in BASIC mode.
\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
392 * @return FALSE No any message received.
\r
393 * TRUE Receive a message success.
\r
396 int32_t CAN_BasicReceiveMsg(CAN_T *tCAN, STR_CANMSG_T* pCanMsg)
\r
399 if((tCAN->IF[1].MCON & CAN_IF_MCON_NEWDAT_Msk) == 0UL) /* In basic mode, receive data always save in IF2 */
\r
401 return (int32_t)FALSE;
\r
404 tCAN->STATUS &= (~CAN_STATUS_RXOK_Msk);
\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
411 if((tCAN->IF[1].ARB2 & CAN_IF_ARB2_XTD_Msk) == 0UL)
\r
414 pCanMsg->IdType = CAN_STD_ID;
\r
415 pCanMsg->Id = (tCAN->IF[1].ARB2 >> 2) & 0x07FFUL;
\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
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
430 pCanMsg->FrameType = (tCAN->IF[1].ARB2 & CAN_IF_ARB2_DIR_Msk) ? 0UL : 1UL;
\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
442 return (int32_t)TRUE;
\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
461 int32_t CAN_SetRxMsgObjAndMsk(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8idType, uint32_t u32id, uint32_t u32idmask, uint8_t u8singleOrFifoLast)
\r
463 uint8_t u8MsgIfNum;
\r
465 /* Get and lock a free interface */
\r
466 if((u8MsgIfNum = (uint8_t)LockIF_TL(tCAN)) == 2U)
\r
468 return (int32_t)FALSE;
\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
475 if(u8idType == CAN_STD_ID) /* According STD/EXT ID format,Configure Mask and Arbitration register */
\r
477 tCAN->IF[u8MsgIfNum].ARB1 = 0U;
\r
478 tCAN->IF[u8MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | (u32id & 0x7FFUL) << 2;
\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
486 tCAN->IF[u8MsgIfNum].MASK1 = (u32idmask & 0xFFFFUL);
\r
487 tCAN->IF[u8MsgIfNum].MASK2 = (u32idmask >> 16) & 0xFFFFUL;
\r
490 tCAN->IF[u8MsgIfNum].MCON = CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk;
\r
491 if(u8singleOrFifoLast)
\r
493 tCAN->IF[u8MsgIfNum].MCON |= CAN_IF_MCON_EOB_Msk;
\r
497 tCAN->IF[u8MsgIfNum].MCON &= (~CAN_IF_MCON_EOB_Msk);
\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
505 tCAN->IF[u8MsgIfNum].CREQ = 1UL + u8MsgObj;
\r
506 ReleaseIF(tCAN, (uint32_t)u8MsgIfNum);
\r
508 return (int32_t)TRUE;
\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
527 int32_t CAN_SetRxMsgObj(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8idType, uint32_t u32id, uint8_t u8singleOrFifoLast)
\r
529 uint8_t u8MsgIfNum;
\r
531 /* Get and lock a free interface */
\r
532 if((u8MsgIfNum = (uint8_t)LockIF_TL(tCAN)) == 2U)
\r
534 return (int32_t)FALSE;
\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
541 if(u8idType == CAN_STD_ID) /* According STD/EXT ID format,Configure Mask and Arbitration register */
\r
543 tCAN->IF[u8MsgIfNum].ARB1 = 0U;
\r
544 tCAN->IF[u8MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | (u32id & 0x7FFUL) << 2;
\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
553 tCAN->IF[u8MsgIfNum].MCON = CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk;
\r
554 if(u8singleOrFifoLast)
\r
556 tCAN->IF[u8MsgIfNum].MCON |= CAN_IF_MCON_EOB_Msk;
\r
560 tCAN->IF[u8MsgIfNum].MCON &= (~CAN_IF_MCON_EOB_Msk);
\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
568 tCAN->IF[u8MsgIfNum].CREQ = 1UL + u8MsgObj;
\r
569 ReleaseIF(tCAN, (uint32_t)u8MsgIfNum);
\r
571 return (int32_t)TRUE;
\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
586 int32_t CAN_ReadMsgObj(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8Release, STR_CANMSG_T* pCanMsg)
\r
588 uint8_t u8MsgIfNum;
\r
591 if(!CAN_IsNewDataReceived(tCAN, u8MsgObj))
\r
593 return (int32_t)FALSE;
\r
596 /* Get and lock a free interface */
\r
597 if((u8MsgIfNum = (uint8_t)LockIF_TL(tCAN)) == 2U)
\r
599 return (int32_t)FALSE;
\r
602 tCAN->STATUS &= (~CAN_STATUS_RXOK_Msk);
\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
613 tCAN->IF[u8MsgIfNum].CREQ = 1UL + u8MsgObj;
\r
615 while(tCAN->IF[u8MsgIfNum].CREQ & CAN_IF_CREQ_BUSY_Msk)
\r
620 if((tCAN->IF[u8MsgIfNum].ARB2 & CAN_IF_ARB2_XTD_Msk) == 0U)
\r
623 pCanMsg->IdType = CAN_STD_ID;
\r
624 pCanMsg->Id = (tCAN->IF[u8MsgIfNum].ARB2 & CAN_IF_ARB2_ID_Msk) >> 2;
\r
629 pCanMsg->IdType = CAN_EXT_ID;
\r
631 u32Tmp = (((tCAN->IF[u8MsgIfNum].ARB2) & 0x1FFFUL) << 16);
\r
632 u32Tmp |= tCAN->IF[u8MsgIfNum].ARB1;
\r
634 pCanMsg->Id = u32Tmp;
\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
647 ReleaseIF(tCAN, (uint32_t)u8MsgIfNum);
\r
648 return (int32_t)TRUE;
\r
651 static int can_update_spt(int sampl_pt, int tseg, int *tseg1, int *tseg2)
\r
653 *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
\r
654 if(*tseg2 < TSEG2_MIN)
\r
656 *tseg2 = TSEG2_MIN;
\r
658 if(*tseg2 > TSEG2_MAX)
\r
660 *tseg2 = TSEG2_MAX;
\r
663 *tseg1 = tseg - *tseg2;
\r
665 if(*tseg1 > TSEG1_MAX)
\r
667 *tseg1 = TSEG1_MAX;
\r
668 *tseg2 = tseg - *tseg1;
\r
670 return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
\r
673 /** @endcond HIDDEN_SYMBOLS */
\r
676 * @brief Set bus baud-rate.
\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
681 * @return u32CurrentBitRate Real baud-rate value.
\r
683 * @details The function is used to set bus timing parameter according current clock and target baud-rate.
\r
685 uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate)
\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
695 CAN_EnterInitMode(tCAN, 0U);
\r
697 clock_freq = (int64_t)CLK_GetPCLK0Freq();
\r
699 if(u32BaudRate >= 1000000UL)
\r
701 u32BaudRate = 1000000UL;
\r
704 /* Use CIA recommended sample points */
\r
705 if(u32BaudRate > 800000UL)
\r
709 else if(u32BaudRate > 500000UL)
\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
721 tsegall = 1 + tseg / 2;
\r
722 /* Compute all possible tseg choices (tseg=tseg1+tseg2) */
\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
728 /* chose brp step which is possible in system */
\r
729 brp = (brp / BRP_INC) * BRP_INC;
\r
731 if((brp >= BRP_MIN) && (brp <= BRP_MAX))
\r
733 rate = (int32_t)(clock_freq / ((int64_t)brp * tsegall));
\r
735 error = (int32_t)u32BaudRate - rate;
\r
737 /* tseg brp biterror */
\r
743 if(error <= best_error)
\r
745 best_error = error;
\r
748 spt = can_update_spt(sampl_pt, tseg / 2, &tseg1, &tseg2);
\r
749 error = sampl_pt - spt;
\r
754 if(error <= spt_error)
\r
757 best_tseg = tseg / 2;
\r
767 best_tseg = tseg / 2;
\r
774 spt = can_update_spt(sampl_pt, best_tseg, &tseg1, &tseg2);
\r
776 /* check for sjw user settings */
\r
777 /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
\r
782 /* bt->sjw must not be higher than tseg2 */
\r
783 if(tseg2 < (int32_t)sjw)
\r
785 sjw = (uint32_t)tseg2;
\r
788 /* real bit-rate */
\r
789 u32BaudRate = (uint32_t)(int32_t)(clock_freq / (int32_t)(best_brp * (tseg1 + tseg2 + 1)));
\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
795 tCAN->BRPE = (((uint32_t)best_brp - 1UL) >> 6) & 0x0FUL;
\r
797 /* DEBUG_PRINTF("\n bitrate = %d \n", CAN_GetCANBitRate(tCAN)); */
\r
799 CAN_LeaveInitMode(tCAN);
\r
801 return u32BaudRate;
\r
805 * @brief The function is used to disable all CAN interrupt.
\r
807 * @param[in] tCAN The pointer to CAN module base address.
\r
811 * @details No Status Change Interrupt and Error Status Interrupt will be generated.
\r
815 void CAN_Close(CAN_T *tCAN)
\r
817 CAN_DisableInt(tCAN, (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk));
\r
823 * @brief Set CAN operation mode and target baud-rate.
\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
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
835 uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode)
\r
837 uint32_t u32CurrentBitRate;
\r
839 u32CurrentBitRate = CAN_SetBaudRate(tCAN, u32BaudRate);
\r
841 if(u32Mode == CAN_BASIC_MODE)
\r
843 CAN_EnterTestMode(tCAN, (uint8_t)CAN_TEST_BASIC_Msk);
\r
846 return u32CurrentBitRate;
\r
850 * @brief The function is used to configure a transmit object.
\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
856 * @retval FALSE No useful interface.
\r
857 * @retval TRUE Config message object success.
\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
862 int32_t CAN_SetTxMsg(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg)
\r
864 uint8_t u8MsgIfNum;
\r
866 if((u8MsgIfNum = (uint8_t)LockIF_TL(tCAN)) == 2U)
\r
868 return (int32_t)FALSE;
\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
875 if(pCanMsg->IdType == CAN_STD_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
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
888 if(pCanMsg->FrameType)
\r
890 tCAN->IF[u8MsgIfNum].ARB2 |= CAN_IF_ARB2_DIR_Msk;
\r
894 tCAN->IF[u8MsgIfNum].ARB2 &= (~CAN_IF_ARB2_DIR_Msk);
\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
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
906 ReleaseIF(tCAN, (uint32_t)u8MsgIfNum);
\r
908 return (int32_t)TRUE;
\r
912 * @brief Set transmit request bit.
\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
917 * @return TRUE: Start transmit message.
\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
921 int32_t CAN_TriggerTxMsg(CAN_T *tCAN, uint32_t u32MsgNum)
\r
923 uint8_t u8MsgIfNum;
\r
925 if((u8MsgIfNum = (uint8_t)LockIF_TL(tCAN)) == 2U)
\r
927 return (int32_t)FALSE;
\r
930 tCAN->STATUS &= (~CAN_STATUS_TXOK_Msk);
\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
936 tCAN->IF[u8MsgIfNum].CREQ = 1UL + u32MsgNum;
\r
938 while(tCAN->IF[u8MsgIfNum].CREQ & CAN_IF_CREQ_BUSY_Msk)
\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
945 ReleaseIF(tCAN, (uint32_t)u8MsgIfNum);
\r
947 return (int32_t)TRUE;
\r
951 * @brief Enable CAN interrupt.
\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
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
964 void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask)
\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
971 * @brief Disable CAN interrupt.
\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
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
980 void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask)
\r
982 tCAN->CON = tCAN->CON & ~((u32Mask & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)));
\r
987 * @brief The function is used to configure a receive message object.
\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
996 * @retval FALSE No useful interface.
\r
997 * @retval TRUE Configure a receive message object success.
\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
1002 int32_t CAN_SetRxMsg(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, uint32_t u32ID)
\r
1004 uint32_t u32TimeOutCount = 0UL;
\r
1006 while(CAN_SetRxMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, (uint8_t)TRUE) == (int32_t)FALSE)
\r
1008 if(++u32TimeOutCount >= RETRY_COUNTS)
\r
1010 return (int32_t)FALSE;
\r
1014 return (int32_t)TRUE;
\r
1018 * @brief The function is used to configure a receive message object.
\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
1028 * @retval FALSE No useful interface.
\r
1029 * @retval TRUE Configure a receive message object success.
\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
1034 int32_t CAN_SetRxMsgAndMsk(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, uint32_t u32ID, uint32_t u32IDMask)
\r
1036 uint32_t u32TimeOutCount = 0UL;
\r
1038 while(CAN_SetRxMsgObjAndMsk(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, u32IDMask, (uint8_t)TRUE) == (int32_t)FALSE)
\r
1040 if(++u32TimeOutCount >= RETRY_COUNTS)
\r
1042 return (int32_t)FALSE;
\r
1046 return (int32_t)TRUE;
\r
1050 * @brief The function is used to configure several receive message objects.
\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
1060 * @retval FALSE No useful interface.
\r
1061 * @retval TRUE Configure receive message objects success.
\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
1066 int32_t CAN_SetMultiRxMsg(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32MsgCount, uint32_t u32IDType, uint32_t u32ID)
\r
1069 uint32_t u32TimeOutCount;
\r
1070 uint32_t u32EOB_Flag = 0UL;
\r
1072 for(i = 1UL; i < u32MsgCount; i++)
\r
1074 u32TimeOutCount = 0UL;
\r
1076 u32MsgNum += (i - 1UL);
\r
1078 if(i == u32MsgCount)
\r
1080 u32EOB_Flag = 1UL;
\r
1083 while(CAN_SetRxMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, (uint8_t)u32EOB_Flag) == (int32_t)FALSE)
\r
1085 if(++u32TimeOutCount >= RETRY_COUNTS)
\r
1087 return (int32_t)FALSE;
\r
1092 return (int32_t)TRUE;
\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
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
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
1109 int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg)
\r
1111 uint32_t cond0, cond1;
\r
1113 cond0 = tCAN->CON & CAN_CON_TEST_Msk;
\r
1114 cond1 = tCAN->TEST & CAN_TEST_BASIC_Msk;
\r
1115 if(cond0 && cond1)
\r
1117 return (CAN_BasicSendMsg(tCAN, pCanMsg));
\r
1121 if(CAN_SetTxMsg(tCAN, u32MsgNum, pCanMsg) == (int32_t)FALSE)
\r
1123 return (int32_t)FALSE;
\r
1125 CAN_TriggerTxMsg(tCAN, u32MsgNum);
\r
1128 return (int32_t)TRUE;
\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
1138 * @retval FALSE No any message received.
\r
1139 * @retval TRUE Receive Message success.
\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
1144 int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg)
\r
1146 uint32_t cond0, cond1;
\r
1148 cond0 = tCAN->CON & CAN_CON_TEST_Msk;
\r
1149 cond1 = tCAN->TEST & CAN_TEST_BASIC_Msk;
\r
1151 if(cond0 && cond1)
\r
1153 return (CAN_BasicReceiveMsg(tCAN, pCanMsg));
\r
1157 return CAN_ReadMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)TRUE, pCanMsg);
\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
1168 * @details An interrupt remains pending until the application software has cleared it.
\r
1170 void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum)
\r
1172 uint32_t u32MsgIfNum;
\r
1174 if((u32MsgIfNum = LockIF_TL(tCAN)) == 2UL)
\r
1176 u32MsgIfNum = 0UL;
\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
1182 ReleaseIF(tCAN, u32MsgIfNum);
\r
1185 /*@}*/ /* end of group CAN_EXPORTED_FUNCTIONS */
\r
1187 /*@}*/ /* end of group CAN_Driver */
\r
1189 /*@}*/ /* end of group Standard_Driver */
\r
1191 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
\r