1 /*********************************************************************************************************//**
2 * @file ht32f5xxxx_can.c
3 * @version $Rev:: 8284 $
4 * @date $Date:: 2024-11-22 #$
5 * @brief This file provides all the CAN firmware functions.
6 *************************************************************************************************************
7 * @attention
8 *
9 * Firmware Disclaimer Information
10 *
11 * 1. The customer hereby acknowledges and agrees that the program technical documentation, including the
12 * code, which is supplied by Holtek Semiconductor Inc., (hereinafter referred to as "HOLTEK") is the
13 * proprietary and confidential intellectual property of HOLTEK, and is protected by copyright law and
14 * other intellectual property laws.
15 *
16 * 2. The customer hereby acknowledges and agrees that the program technical documentation, including the
17 * code, is confidential information belonging to HOLTEK, and must not be disclosed to any third parties
18 * other than HOLTEK and the customer.
19 *
20 * 3. The program technical documentation, including the code, is provided "as is" and for customer reference
21 * only. After delivery by HOLTEK, the customer shall use the program technical documentation, including
22 * the code, at their own risk. HOLTEK disclaims any expressed, implied or statutory warranties, including
23 * the warranties of merchantability, satisfactory quality and fitness for a particular purpose.
24 *
25 * <h2><center>Copyright (C) Holtek Semiconductor Inc. All rights reserved</center></h2>
26 ************************************************************************************************************/
27
28 /* Includes ------------------------------------------------------------------------------------------------*/
29 #include "ht32f5xxxx_can.h"
30
31 /** @addtogroup HT32F5xxxx_Peripheral_Driver HT32F5xxxx Peripheral Driver
32 * @{
33 */
34
35 /** @defgroup CAN CAN
36 * @brief CAN driver modules
37 * @{
38 */
39
40
41 /* Private types -------------------------------------------------------------------------------------------*/
42 typedef enum
43 {
44 IF0_NUM = 0,
45 IF1_NUM,
46 IF_TOTAL_NUM
47 } CANIF_NUMBER_Enum;
48
49 /* Private function prototypes -----------------------------------------------------------------------------*/
50 static HT_CANIF_TypeDef *_GetFreeIF(HT_CAN_TypeDef *CANx);
51 static void _CAN_EnterInitMode(HT_CAN_TypeDef *CANx);
52 static void _CAN_LeaveInitMode(HT_CAN_TypeDef *CANx);
53 static void _CAN_SetRxMsgObj(HT_CAN_TypeDef *CANx, u32 MsgNum, CAN_MSG_TypeDef* pCanMsg, u32 uSingleOrFifoLast);
54 static s32 _CAN_ReadMsgObj(HT_CAN_TypeDef *CANx, u32 MsgNum, u32 Release, CAN_MSG_TypeDef* pCanMsg, u8* data, u32* len);
55 static ErrStatus _CAN_SetTxMsg(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg, u8* data, u8 len);
56 static int _CAN_GetValidMsg(HT_CAN_TypeDef *CANx);
57 static bool _CAN_GetNewData(HT_CAN_TypeDef *CANx, u32 MsgNum);
58 static bool _CAN_CheckMsgIsValid(HT_CAN_TypeDef *CANx, u32 MsgNum);
59 static void _CAN_ClearMsgPendingFlag(HT_CAN_TypeDef *CANx, u32 MsgNum);
60 static volatile bool gIsBusOff = FALSE;
61
62 /* Global functions ----------------------------------------------------------------------------------------*/
63 /** @defgroup CAN_Exported_Functions CAN exported functions
64 * @{
65 */
66 /*********************************************************************************************************//**
67 * @brief Deinitialize the specified CAN registers to their default values.
68 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
69 * @retval None
70 ************************************************************************************************************/
CAN_DeInit(HT_CAN_TypeDef * CANx)71 void CAN_DeInit(HT_CAN_TypeDef* CANx)
72 {
73 RSTCU_PeripReset_TypeDef RSTCUReset = {{0}};
74 /* Check the parameters */
75 Assert_Param(IS_CAN(CANx));
76
77 if (CANx == HT_CAN0)
78 {
79 RSTCUReset.Bit.CAN0 = 1;
80 }
81
82 RSTCU_PeripReset(RSTCUReset, ENABLE);
83 }
84
85 /*********************************************************************************************************//**
86 * @brief Set CAN operation mode and target baud-rate.
87 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
88 * @param CAN_InitStruct: pointer to a CAN_InitTypeDef structure.
89 * @retval None
90 ***********************************************************************************************************/
CAN_Init(HT_CAN_TypeDef * CANx,CAN_InitTypeDef * CAN_InitStruct)91 void CAN_Init(HT_CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct)
92 {
93 /* Check the parameters */
94 Assert_Param(IS_CAN(CANx));
95
96 _CAN_EnterInitMode(CANx);
97
98 CANx->BTR = (((u32)(CAN_InitStruct->CAN_TSEG1 - 1) << CAN_BTR_TSEG1_Pos) & CAN_BTR_TSEG1_Msk)|
99 (((u32)(CAN_InitStruct->CAN_TSEG0 -1) << CAN_BTR_TSEG0_Pos) & CAN_BTR_TSEG0_Msk)|
100 (((u32)(CAN_InitStruct->CAN_BRPrescaler -1) << CAN_BTR_BRP_Pos) & CAN_BTR_BRP_Msk) |
101 (((u32)(CAN_InitStruct->CAN_SJW -1) << CAN_BTR_SJW_Pos) & CAN_BTR_SJW_Msk);
102
103 CANx->BRPER = (CAN_InitStruct->CAN_BRPrescaler >> 6) & CAN_BRPE_BRPE_Msk;
104 _CAN_LeaveInitMode(CANx);
105
106 if (CAN_InitStruct->CAN_NART)
107 HT_CAN0->CR |= CAN_CR_DAR;
108
109 if (CAN_InitStruct->CAN_Mode)
110 {
111 CAN_EnterTestMode(CANx, CAN_InitStruct->CAN_Mode);
112 }
113 CAN_IntConfig(CANx, CAN_INT_EIE | CAN_INT_IE , ENABLE);
114
115 return;
116 }
117
118 /**********************************************************************************************************//**
119 * @brief Enable or Disable the specified CAN interrupt.
120 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
121 * @param CAN_Int: specify if the CAN interrupt source to be enabled or disabled.
122 * This parameter can be any combination of the following values:
123 * @arg CAN_INT_IE : Module interrupt enable.
124 * @arg CAN_INT_SIE : Status change interrupt enable.
125 * @arg CAN_INT_EIE : Error interrupt enable.
126 * @arg CAN_INT_ALL : All CAN interrupt
127 * @param NewState: this parameter can be ENABLE or DISABLE.
128 * @retval None
129 ***********************************************************************************************************/
CAN_IntConfig(HT_CAN_TypeDef * CANx,u32 CAN_Int,ControlStatus NewState)130 void CAN_IntConfig(HT_CAN_TypeDef *CANx, u32 CAN_Int, ControlStatus NewState)
131 {
132 /* Check the parameters */
133 Assert_Param(IS_CAN(CANx));
134 Assert_Param(IS_CONTROL_STATUS(NewState));
135 CAN_Int = CAN_Int & CAN_INT_ALL;
136
137 _CAN_EnterInitMode(CANx);
138 if (NewState != DISABLE)
139 {
140 CANx->CR |= CAN_Int;
141 }
142 else
143 {
144 CANx->CR = CANx->CR & ~(CAN_Int);
145 }
146 _CAN_LeaveInitMode(CANx);
147 }
148
149 /**********************************************************************************************************//**
150 * @brief Get the specified CAN INT status.
151 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
152 * @param CAN_Int: the CAN interrupt source.
153 * This parameter can be one of the following values:
154 * @arg CAN_INT_IE : Module interrupt enable.
155 * @arg CAN_INT_SIE : Status change interrupt enable.
156 * @arg CAN_INT_EIE : Error interrupt enable.
157 * @retval SET or RESET
158 ***********************************************************************************************************/
CAN_GetIntStatus(HT_CAN_TypeDef * CANx,u32 CAN_Int)159 FlagStatus CAN_GetIntStatus(HT_CAN_TypeDef* CANx, u32 CAN_Int)
160 {
161 FlagStatus Status;
162 /* Check the parameters */
163 Assert_Param(IS_CAN(CANx));
164 if ((CANx->CR & CAN_Int) != RESET)
165 {
166 Status = SET;
167 }
168 else
169 {
170 Status = RESET;
171 }
172 return Status;
173 }
174
175 /*********************************************************************************************************//**
176 * @brief Check whether the specified CAN flag has been set.
177 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
178 * @param CAN_Flag: specify the flag to be check.
179 * This parameter can be one of the following values:
180 * @arg CAN_FLAG_BOFF : Busoff Status
181 * @arg CAN_FLAG_EWARN : Warning Status
182 * @arg CAN_FLAG_EPASS : Error Passive
183 * @arg CAN_FLAG_RXOK : Received a Message Successfully
184 * @arg CAN_FLAG_TXOK : Transmitted a Message Successfully
185 * @retval SET or RESET
186 ************************************************************************************************************/
CAN_GetFlagStatus(HT_CAN_TypeDef * CANx,uint32_t CAN_Flag)187 FlagStatus CAN_GetFlagStatus(HT_CAN_TypeDef* CANx, uint32_t CAN_Flag)
188 {
189 /* Check the parameters */
190 Assert_Param(IS_CAN(CANx));
191
192 if (CANx->SR & CAN_Flag)
193 {
194 return SET;
195 }
196 else
197 {
198 return RESET;
199 }
200 }
201
202 /**********************************************************************************************************//**
203 * @brief Clear the interrupt flag of the specified CAN.
204 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
205 * @param CAN_Flag: specify the flag that is to be cleared.
206 * @arg CAN_FLAG_RXOK : Received a Message Successfully
207 * @arg CAN_FLAG_TXOK : Transmitted a Message Successfully
208 * @retval None
209 ***********************************************************************************************************/
CAN_ClearFlag(HT_CAN_TypeDef * CANx,uint32_t CAN_Flag)210 void CAN_ClearFlag(HT_CAN_TypeDef* CANx, uint32_t CAN_Flag)
211 {
212 /* Check the parameters */
213 Assert_Param(IS_CAN(CANx));
214
215 CANx->SR &= ~CAN_Flag;
216 }
217
218 /**********************************************************************************************************//**
219 * @brief Returns the CANx's last error code (LEC).
220 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
221 * @retval This function will return the CAN_ErrorCode following values:
222 * - NO_ERROR : No Error
223 * - STUFF_ERROR : Stuff Error
224 * - FORM_ERROR : Form Error
225 * - ACK_ERROR : Acknowledgment Error
226 * - BIT1_EROR : Bit Recessive Error
227 * - BIT0_ERROR : Bit Dominant Error
228 * - CRC_ERROR : CRC Error
229 * - NO_CHANGE : Software Set Error
230 ***********************************************************************************************************/
CAN_GetLastErrorCode(HT_CAN_TypeDef * CANx)231 CAN_LastErrorCode_TypeDef CAN_GetLastErrorCode(HT_CAN_TypeDef* CANx)
232 {
233 /* Check the parameters */
234 Assert_Param(IS_CAN(CANx));
235 return (CAN_LastErrorCode_TypeDef)(CANx->SR & CAN_LEC_Msk);
236 }
237
238 /**********************************************************************************************************//**
239 * @brief Returns the CANx Receive Error Counter (REC).
240 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
241 * @retval CAN Receive Error Counter.
242 ***********************************************************************************************************/
CAN_GetReceiveErrorCounter(HT_CAN_TypeDef * CANx)243 u32 CAN_GetReceiveErrorCounter(HT_CAN_TypeDef* CANx)
244 {
245 /* Check the parameters */
246 Assert_Param(IS_CAN(CANx));
247
248 return ((CANx->ECR & CAN_ECR_REC_MsK) >> CAN_ECR_REC_Pos);
249 }
250
251 /*********************************************************************************************************//**
252 * @brief Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC).
253 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
254 * @retval LSB of the 9-bit CAN Transmit Error Counter.
255 ***********************************************************************************************************/
CAN_GetLSBTransmitErrorCounter(HT_CAN_TypeDef * CANx)256 u32 CAN_GetLSBTransmitErrorCounter(HT_CAN_TypeDef* CANx)
257 {
258 /* Check the parameters */
259 Assert_Param(IS_CAN(CANx));
260
261 return (CANx->ECR & CAN_ECR_TEC_MsK);
262 }
263
264 /*********************************************************************************************************//**
265 * @brief Monitor CAN BusOff status.
266 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
267 * @retval None
268 ***********************************************************************************************************/
CAN_BusOffRecovery(HT_CAN_TypeDef * CANx)269 void CAN_BusOffRecovery(HT_CAN_TypeDef *CANx)
270 {
271 /* Check the parameters */
272 Assert_Param(IS_CAN(CANx));
273
274 /* Get BusOff Flag */
275 if (CANx->SR & CAN_FLAG_BOFF)
276 {
277 _CAN_LeaveInitMode(CANx);
278 }
279 return;
280 }
281
282 /**********************************************************************************************************//**
283 * @brief Switch the CAN into test mode.
284 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
285 * @param u8TestMask Specifies the configuration in test modes
286 * @arg CAN_MODE_BASIC : Enable basic mode of test mode
287 * @arg CAN_MODE_SILENT : Enable silent mode of test mode
288 * @arg CAN_MODE_LBACK : Enable Loop Back Mode of test mode
289 * @arg CAN_MODE_MONITORER : Sample Point can be monitored at CAN_TX pin.
290 * @arg CAN_MODE_TX_DOMINANT : CAN_TX pin drives a dominant ('0') value
291 * @arg CAN_MODE_TX_RECESSIVE : CAN_TX pin drives a recessive ('1') value
292 * @retval None
293 ***********************************************************************************************************/
CAN_EnterTestMode(HT_CAN_TypeDef * CANx,u32 u8TestMask)294 void CAN_EnterTestMode(HT_CAN_TypeDef *CANx, u32 u8TestMask)
295 {
296 /* Check the parameters */
297 Assert_Param(IS_CAN(CANx));
298
299 CANx->CR |= CAN_CR_TEST;
300 CANx->TR = u8TestMask;
301 }
302
303 /*********************************************************************************************************//**
304 * @brief Leave the test mode
305 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
306 * @retval None
307 ***********************************************************************************************************/
CAN_LeaveTestMode(HT_CAN_TypeDef * CANx)308 void CAN_LeaveTestMode(HT_CAN_TypeDef *CANx)
309 {
310 /* Check the parameters */
311 Assert_Param(IS_CAN(CANx));
312
313 CANx->CR |= CAN_CR_TEST;
314 CANx->TR &= ~(CAN_MODE_LBACK | CAN_MODE_SILENT | CAN_MODE_BASIC | CAN_MODE_TX_RECESSIVE);
315 CANx->CR &= (~CAN_CR_TEST);
316 }
317
318 /*********************************************************************************************************//**
319 * @brief The function is used to Send CAN message in BASIC mode of test mode. Before call the API,
320 * the user should be call CAN_EnterTestMode(CAN_TEST_BASIC) and let CAN controller enter
321 * basic mode of test mode. Please notice IF0 Registers used as Tx Buffer in basic mode.
322 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
323 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
324 * @param data: Pointer to the data buffer to be transmitted.
325 * @param len: Length of the data to be transmitted.
326 * @retval SUCCESS or ERROR
327 ***********************************************************************************************************/
CAN_BasicSendMsg(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg,u8 * data,u8 len)328 ErrStatus CAN_BasicSendMsg(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg, u8* data, u8 len)
329 {
330 /* Check the parameters */
331 Assert_Param(IS_CAN(CANx));
332 if (CANx->SR & CAN_FLAG_BOFF)
333 {
334 return ERROR;
335 }
336 while (CANx->IF0.CREQ & CAN_FLAG_IF_BUSY)
337 {
338 }
339
340 CANx->SR &= (~CAN_FLAG_TXOK);
341
342 if (pCanMsg->IdType == CAN_STD_ID)
343 {
344 /* standard ID */
345 CANx->IF0.ARB0 = 0;
346 CANx->IF0.ARB1 = (((pCanMsg->Id) & CAN_STD_FRAME_Msk) << 2);
347 }
348 else
349 {
350 /* extended ID */
351 CANx->IF0.ARB0 = (pCanMsg->Id) & CAN_EXT_FRAME_LSB_Msk;
352 CANx->IF0.ARB1 = (((pCanMsg->Id) >> 16) & CAN_EXT_FRAME_MSB_Msk) | CAN_IF_ARB1_XTD;
353 }
354
355 if (pCanMsg->FrameType)
356 CANx->IF0.ARB1 |= CAN_IF_ARB1_DIR;
357 else
358 CANx->IF0.ARB1 &= (~CAN_IF_ARB1_DIR);
359
360 CANx->IF0.MCR = (CANx->IF0.MCR & (~CAN_IF_MCR_DLC_Msk)) | len;
361 CANx->IF0.DA0R = ((u16)data[1] << 8) | data[0];
362 CANx->IF0.DA1R = ((u16)data[3] << 8) | data[2];
363 CANx->IF0.DB0R = ((u16)data[5] << 8) | data[4];
364 CANx->IF0.DB1R = ((u16)data[7] << 8) | data[6];
365
366 /* request transmission */
367 CANx->IF0.CREQ &= (~CAN_FLAG_IF_BUSY);
368 if (CANx->IF0.CREQ & CAN_FLAG_IF_BUSY)
369 {
370 return ERROR;
371 }
372
373 CANx->IF0.CREQ |= CAN_FLAG_IF_BUSY; /* Sending */
374
375 return SUCCESS;
376 }
377
378 /*********************************************************************************************************//**
379 * @brief Get a message information in BASIC mode.
380 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
381 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
382 * @param data: Pointer to the buffer where received data will be stored.
383 * @param len: Pointer to a variable that will store the length of the received data.
384 * @retval SUCCESS or ERROR
385 ***********************************************************************************************************/
CAN_BasicReceiveMsg(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg,u8 * data,u8 * len)386 ErrStatus CAN_BasicReceiveMsg(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg, u8* data, u8* len)
387 {
388 /* Check the parameters */
389 Assert_Param(IS_CAN(CANx));
390
391 if ((CANx->IF1.MCR & CAN_IF_MCR_NEWDAT) == 0) /* In basic mode, receive data always save in IF1 */
392 {
393 return ERROR;
394 }
395
396 CANx->SR &= (~CAN_FLAG_RXOK);
397
398 CANx->IF1.CMASK = CAN_IF_CMASK_ARB
399 | CAN_IF_CMASK_CONTROL
400 | CAN_IF_CMASK_DATAA
401 | CAN_IF_CMASK_DATAB;
402
403 if ((CANx->IF1.MASK1 & CAN_IF_ARB1_XTD) == 0)
404 {
405 /* standard ID */
406 pCanMsg->IdType = CAN_STD_ID;
407 pCanMsg->Id = (CANx->IF1.MASK1 >> 2) & CAN_STD_FRAME_Msk;
408 }
409 else
410 {
411 /* extended ID */
412 pCanMsg->IdType = CAN_EXT_ID;
413 pCanMsg->Id = (CANx->IF1.ARB1 & CAN_EXT_FRAME_MSB_Msk) << 16;
414 pCanMsg->Id |= (u32)CANx->IF1.ARB0;
415 }
416
417 *len = CANx->IF1.MCR & CAN_IF_MCR_DLC_Msk;
418 data[0] = CANx->IF1.DA0R & CAN_IF_DAT_A0_DATA0_Msk;
419 data[1] = (CANx->IF1.DA0R & CAN_IF_DAT_A0_DATA1_Msk) >> CAN_IF_DAT_A0_DATA1_Pos;
420 data[2] = CANx->IF1.DA1R & CAN_IF_DAT_A1_DATA2_Msk;
421 data[3] = (CANx->IF1.DA1R & CAN_IF_DAT_A1_DATA3_Msk) >> CAN_IF_DAT_A1_DATA3_Pos;
422 data[4] = CANx->IF1.DB0R & CAN_IF_DAT_B0_DATA4_Msk;
423 data[5] = (CANx->IF1.DB0R & CAN_IF_DAT_B0_DATA5_Msk) >> CAN_IF_DAT_B0_DATA5_Pos;
424 data[6] = CANx->IF1.DB1R & CAN_IF_DAT_B1_DATA6_Msk;
425 data[7] = (CANx->IF1.DB1R & CAN_IF_DAT_B1_DATA7_Msk) >> CAN_IF_DAT_B1_DATA7_Pos;
426
427 return SUCCESS;
428 }
429
430 /*********************************************************************************************************//**
431 * @brief Send CAN message.
432 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
433 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
434 * @param data: Pointer to the data buffer to be transmitted.
435 * @param len: Length of the data to be transmitted.
436 * @retval SUCCESS or ERROR
437 ***********************************************************************************************************/
CAN_Transmit(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg,u8 * data,u8 len)438 ErrStatus CAN_Transmit(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg, u8* data, u8 len)
439 {
440 /* Check the parameters */
441 Assert_Param(IS_CAN(CANx));
442 if (_CAN_SetTxMsg(CANx, pCanMsg, data, len) == ERROR)
443 {
444 return ERROR;
445 }
446 return (CAN_TriggerTxMsg(CANx, pCanMsg));
447 }
448
449 /*********************************************************************************************************//**
450 * @brief Gets the message, if received.
451 * The Interface Registers avoid conflict between the CPU accesses to the Message RAM and CAN message
452 * reception and transmission by buffering the data to be transferred.
453 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
454 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
455 * @param data: Pointer to the buffer where received data will be stored.
456 * @param len: Pointer to a variable that will store the length of the received data.
457 * @retval RxStatus_TypeDef: Returns the status of the message reception. Possible values are:
458 * - MSG_OBJ_NOT_SET
459 * - MSG_NOT_RECEIVED
460 * - MSG_OVER_RUN
461 ***********************************************************************************************************/
CAN_Receive(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg,u8 * data,u32 * len)462 CAN_RxStatus_TypeDef CAN_Receive(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg, u8* data, u32* len)
463 {
464 u32 _MsgNum = pCanMsg->MsgNum;
465 CAN_RxStatus_TypeDef status = MSG_OBJ_NOT_SET;
466 bool firstMsg = TRUE;
467 *len = 0;
468 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) != FALSE)
469 {
470 while (1)
471 {
472 s32 ReadMsgStatus;
473 if (_CAN_GetNewData(CANx, _MsgNum) == FALSE)
474 {
475 if (firstMsg == TRUE)
476 status = MSG_NOT_RECEIVED;
477 else
478 status = MSG_RX_FINISH;
479 break;
480 }
481 firstMsg = FALSE;
482 ReadMsgStatus = _CAN_ReadMsgObj(CANx, _MsgNum, TRUE, pCanMsg, &data[*len], len);
483 if (ReadMsgStatus != 0)
484 {
485 if (ReadMsgStatus == 2)
486 {
487 status = MSG_OVER_RUN;
488 break;
489 }
490 status = MSG_RX_FINISH;
491 break;
492 }
493 _MsgNum++;
494 }
495 }
496 return status;
497 }
498
499 /*********************************************************************************************************//**
500 * @brief Cancels a transmit request.
501 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
502 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
503 * @retval SUCCESS or ERROR
504 ***********************************************************************************************************/
CAN_CancelTransmit(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg)505 ErrStatus CAN_CancelTransmit(HT_CAN_TypeDef* CANx, CAN_MSG_TypeDef* pCanMsg)
506 {
507 HT_CANIF_TypeDef *IFx = NULL;
508 /* Check the parameters */
509 Assert_Param(IS_CAN(CANx));
510
511 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) == FALSE)
512 {
513 return ERROR;
514 }
515
516 while (IFx == NULL)
517 {
518 IFx = _GetFreeIF(CANx);
519 }
520 if ((IFx->CREQ & CAN_FLAG_IF_BUSY) == 0)
521 {
522 IFx->CMASK = CAN_IF_CMASK_WRRD | CAN_IF_CMASK_CLRINTPND;
523 IFx->MCR = 0;
524 IFx->CREQ = pCanMsg->MsgNum;
525 }
526
527 return SUCCESS;
528 }
529
530 /*********************************************************************************************************//**
531 * @brief Discard the specified FIFO.
532 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
533 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
534 * @retval SUCCESS or ERROR
535 ***********************************************************************************************************/
CAN_DiscardRxMsg(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg)536 ErrStatus CAN_DiscardRxMsg(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg)
537 {
538 /* Check the parameters */
539 Assert_Param(IS_CAN(CANx));
540 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) == FALSE)
541 {
542 return ERROR;
543 }
544 while (1)
545 {
546 HT_CANIF_TypeDef *IFx = NULL;
547 while (IFx == NULL)
548 {
549 IFx = _GetFreeIF(CANx);
550 }
551 IFx->CMASK = CAN_IF_CMASK_TXRQSTNEWDAT | CAN_IF_CMASK_CONTROL;
552 IFx->CREQ = pCanMsg->MsgNum;
553 if (IFx->MCR & CAN_IF_MCR_EOB)
554 {
555 break;
556 }
557 }
558 return SUCCESS;
559 }
560
561 /*********************************************************************************************************//**
562 * @brief The function is used to configure several receive message objects.
563 * The Interface Registers avoid conflict between the CPU accesses to the Message RAM and CAN message
564 * reception and transmission by buffering the data to be transferred.
565 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
566 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
567 * @param FifoDepth: the number of MSG RAM of the FIFO.
568 * @retval SUCCESS or ERROR
569 ***********************************************************************************************************/
CAN_SetRxMsg(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg,u32 FifoDepth)570 ErrStatus CAN_SetRxMsg(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg, u32 FifoDepth)
571 {
572 s32 i = 0;
573 u32 _MsgNum;
574
575 u32 eob;
576 if (pCanMsg->MsgNum == 0)
577 {
578 _MsgNum = _CAN_GetValidMsg(CANx);
579 }
580 else
581 {
582 _MsgNum = pCanMsg->MsgNum;
583 }
584 if ((_MsgNum + FifoDepth) > MSG_OBJ_TOTAL_NUM)
585 {
586 return ERROR;
587 }
588 pCanMsg->MsgNum = _MsgNum;
589 eob = 0;
590 for (i = _MsgNum; i < FifoDepth + _MsgNum + 1; i++)
591 {
592 if (i == FifoDepth + _MsgNum)
593 {
594 eob = 1;
595 }
596 _CAN_SetRxMsgObj(CANx, i, pCanMsg, eob);
597 }
598 return SUCCESS;
599 }
600
601 /*********************************************************************************************************//**
602 * @brief Get the waiting status of a received message.
603 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
604 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
605 * @retval TRUE: The corresponding message object has a new data bit is set, FALSE otherwise.
606 ***********************************************************************************************************/
CAN_NewDataReceived(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg)607 bool CAN_NewDataReceived(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg)
608 {
609
610 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) == FALSE)
611 {
612 return FALSE;
613 }
614 return _CAN_GetNewData(CANx, pCanMsg->MsgNum);
615 }
616
617 /*********************************************************************************************************//**
618 * @brief Get the interrupt pending status of a message object.
619 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
620 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
621 * @retval TRUE: The corresponding message object has a interrupt pending bit is set, FALSE otherwise.
622 ***********************************************************************************************************/
CAN_GetMsgPending(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg)623 bool CAN_GetMsgPending(HT_CAN_TypeDef* CANx, CAN_MSG_TypeDef* pCanMsg)
624 {
625 u32 Pending = CANx->IPR0;
626 Pending |= CANx->IPR1 << 16;
627
628 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) == FALSE)
629 {
630 return FALSE;
631 }
632
633 if ((Pending & 1 << (pCanMsg->MsgNum - 1)) == 0)
634 {
635 return FALSE;
636 }
637 return TRUE;
638 }
639
640 /*********************************************************************************************************//**
641 * @brief Clear interrupt pending bit.
642 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
643 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
644 * @retval SUCCESS or ERROR
645 ***********************************************************************************************************/
CAN_ClearMsgPendingFlag(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg)646 ErrStatus CAN_ClearMsgPendingFlag(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg)
647 {
648 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) == FALSE)
649 {
650 return ERROR;
651 }
652 _CAN_ClearMsgPendingFlag(CANx, pCanMsg->MsgNum);
653
654 return SUCCESS;
655 }
656
657 /*********************************************************************************************************//**
658 * @brief Checks the transmission of a message object.
659 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
660 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
661 * @retval 0: Transmitting, 1: Transmission successful, -1: Transmission failed.
662 ***********************************************************************************************************/
CAN_TransmitStatus(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg)663 s32 CAN_TransmitStatus(HT_CAN_TypeDef* CANx, CAN_MSG_TypeDef* pCanMsg)
664 {
665 s32 TxStatus = 0;
666 u32 u32Reg;
667 s32 MsgNum = pCanMsg->MsgNum -1;
668
669 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) == FALSE)
670 {
671 return -1;
672 }
673
674 /* Check the parameters */
675 Assert_Param(IS_CAN(CANx));
676
677 u32Reg = CANx->TRR0;
678 u32Reg |= (CANx->TRR1 << 16);
679 MsgNum = 1 << (MsgNum);
680 if ((u32Reg & (MsgNum)) == 0)
681 {
682 TxStatus = 1;
683 }
684
685 u32Reg = CANx->NDR0;
686 u32Reg |= (CANx->NDR1 << 16);
687 if ((u32Reg & (MsgNum)) > 0)
688 {
689 TxStatus = -1;
690 }
691 return TxStatus;
692 }
693
694 /*********************************************************************************************************//**
695 * @brief Updates the data of a specified CAN message object.
696 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
697 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
698 * @param data: Pointer to the data array.
699 * @param len: Length of the data to be sent, in bytes (maximum 8 bytes).
700 * @retval SUCCESS or ERROR
701 ***********************************************************************************************************/
CAN_UpdateTxMsgData(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg,u8 * data,u8 len)702 ErrStatus CAN_UpdateTxMsgData(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg, u8* data, u8 len)
703 {
704 HT_CANIF_TypeDef *IFx = NULL;
705
706 len &= CAN_IF_MCR_DLC_Msk;
707 while (IFx == NULL)
708 {
709 IFx = _GetFreeIF(CANx);
710 }
711
712 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) == FALSE)
713 {
714 return ERROR;
715 }
716
717 IFx->CMASK = CAN_IF_CMASK_WRRD | CAN_IF_CMASK_DATAA | CAN_IF_CMASK_DATAB | CAN_IF_CMASK_CONTROL;
718
719 IFx->MCR &= (~CAN_IF_MCR_DLC_Msk);
720 IFx->MCR |= (len & CAN_IF_MCR_DLC_Msk);
721 IFx->DA0R = ((u16)(data[1] << 8) | data[0]);
722 IFx->DA1R = ((u16)(data[3] << 8) | data[2]);
723 IFx->DB0R = ((u16)(data[5] << 8) | data[4]);
724 IFx->DB1R = ((u16)(data[7] << 8) | data[6]);
725
726 IFx->CREQ = pCanMsg->MsgNum;
727
728 return SUCCESS;
729 }
730
731 /*********************************************************************************************************//**
732 * @brief Set transmit request bit.
733 * If a transmission is requested by programming bit TxRqst/NewDat, the TxRqst will be ignored.
734 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
735 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
736 * @retval SUCCESS or ERROR
737 ***********************************************************************************************************/
CAN_TriggerTxMsg(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg)738 ErrStatus CAN_TriggerTxMsg(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg)
739 {
740 HT_CANIF_TypeDef *IFx = NULL;
741 /* Check the parameters */
742 Assert_Param(IS_CAN(CANx));
743
744 if (CANx->SR & CAN_FLAG_BOFF)
745 {
746 return ERROR;
747 }
748
749 if (_CAN_CheckMsgIsValid(CANx, pCanMsg->MsgNum) == FALSE)
750 {
751 return ERROR;
752 }
753
754 while (IFx == NULL)
755 {
756 IFx = _GetFreeIF(CANx);
757 }
758
759 IFx->CMASK = CAN_IF_CMASK_WRRD | CAN_IF_CMASK_CONTROL;
760 IFx->MCR |= CAN_IF_MCR_NEWDAT | CAN_IF_MCR_TXRQST;
761 IFx->CREQ = pCanMsg->MsgNum;
762
763 return SUCCESS;
764 }
765
766 /*********************************************************************************************************//**
767 * @brief Clears all pending message flags.
768 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
769 * @retval None
770 ***********************************************************************************************************/
CAN_ClearAllMsgPendingFlag(HT_CAN_TypeDef * CANx)771 void CAN_ClearAllMsgPendingFlag(HT_CAN_TypeDef *CANx)
772 {
773 int i;
774 u32 Pending = CANx->IPR0;
775 Pending |= CANx->IPR1 << 16;
776 for (i = 0 ; i < MSG_OBJ_TOTAL_NUM ; i++)
777 {
778 if ((Pending & 1) == 1)
779 {
780 _CAN_ClearMsgPendingFlag(CANx, i + 1);
781 }
782
783 Pending = Pending >> 1;
784 if (Pending == 0)
785 {
786 break;
787 }
788 }
789 }
790 /**
791 * @}
792 */
793
794 /* Private functions ---------------------------------------------------------------------------------------*/
795 /** @defgroup CAN_Private_Functions CAN private functions
796 * @{
797 */
798 /*********************************************************************************************************//**
799 * @brief The function is used to configure a transmit object.
800 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
801 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
802 * @param data: Pointer to the data buffer to be transmitted.
803 * @param len: Length of the data to be transmitted.
804 * @retval SUCCESS or ERROR
805 ***********************************************************************************************************/
_CAN_SetTxMsg(HT_CAN_TypeDef * CANx,CAN_MSG_TypeDef * pCanMsg,u8 * data,u8 len)806 ErrStatus _CAN_SetTxMsg(HT_CAN_TypeDef *CANx, CAN_MSG_TypeDef* pCanMsg, u8* data, u8 len)
807 {
808 HT_CANIF_TypeDef *IFx = NULL;
809 if (pCanMsg->MsgNum == 0)
810 {
811 pCanMsg->MsgNum = _CAN_GetValidMsg(CANx);
812 }
813 if (pCanMsg->MsgNum > MSG_OBJ_TOTAL_NUM)
814 {
815 return ERROR;
816 }
817
818 while (IFx == NULL)
819 {
820 IFx = _GetFreeIF(CANx);
821 }
822
823 /* update the contents needed for transmission */
824 IFx->CMASK = CAN_IF_CMASK_WRRD | CAN_IF_CMASK_MASK | CAN_IF_CMASK_ARB
825 | CAN_IF_CMASK_CONTROL | CAN_IF_CMASK_DATAA | CAN_IF_CMASK_DATAB;
826
827 if (pCanMsg->IdType == CAN_STD_ID)
828 {
829 /* standard ID */
830 IFx->ARB0 = 0;
831 IFx->ARB1 = (((pCanMsg->Id) & CAN_STD_FRAME_Msk) << 2) | CAN_IF_ARB1_DIR | CAN_IF_ARB1_MSGVAL;
832 }
833 else
834 {
835 /* extended ID */
836 IFx->ARB0 = (pCanMsg->Id) & CAN_EXT_FRAME_LSB_Msk;
837 IFx->ARB1 = (((pCanMsg->Id) >> 16) & CAN_EXT_FRAME_MSB_Msk)
838 | CAN_IF_ARB1_DIR | CAN_IF_ARB1_XTD | CAN_IF_ARB1_MSGVAL;
839 }
840
841 if (pCanMsg->FrameType)
842 IFx->ARB1 |= CAN_IF_ARB1_DIR;
843 else
844 IFx->ARB1 &= (~CAN_IF_ARB1_DIR);
845
846 IFx->DA0R = ((u16)data[1] << 8) | data[0];
847 IFx->DA1R = ((u16)data[3] << 8) | data[2];
848 IFx->DB0R = ((u16)data[5] << 8) | data[4];
849 IFx->DB1R = ((u16)data[7] << 8) | data[6];
850
851 IFx->MCR = 0;
852
853 IFx->MCR &= (~CAN_IF_MCR_RMTEN);
854
855 IFx->MCR |= CAN_IF_MCR_NEWDAT | len | CAN_IF_MCR_TXIE;
856 IFx->CREQ = pCanMsg->MsgNum;
857 return SUCCESS;
858 }
859
860 /*********************************************************************************************************//**
861 * @brief Get the waiting status of a received message.
862 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
863 * @param MsgNum: Specifies the Message object number, from 1 to 32.
864 * @retval TRUE: The corresponding message object has a new data bit is set, FALSE otherwise.
865 ***********************************************************************************************************/
_CAN_GetNewData(HT_CAN_TypeDef * CANx,u32 MsgNum)866 bool _CAN_GetNewData(HT_CAN_TypeDef *CANx, u32 MsgNum)
867 {
868 u32 NewData = CANx->NDR0;
869 NewData |= CANx->NDR1 << 16;
870
871 if ((NewData & 1 << (MsgNum - 1)) == 0)
872 {
873 return FALSE;
874 }
875 return TRUE;
876 }
877
878 /*********************************************************************************************************//**
879 * @brief Get free interface.
880 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
881 * @retval Free IF pointer. NULL: No IF is free
882 ***********************************************************************************************************/
_GetFreeIF(HT_CAN_TypeDef * CANx)883 static HT_CANIF_TypeDef *_GetFreeIF(HT_CAN_TypeDef *CANx)
884 {
885 /* Check the parameters */
886 Assert_Param(IS_CAN(CANx));
887
888 if ((CANx->IF0.CREQ & CAN_FLAG_IF_BUSY) == 0)
889 {
890 return &CANx->IF0;
891 }
892 else if ((CANx->IF1.CREQ & CAN_FLAG_IF_BUSY) == 0)
893 {
894 return &CANx->IF1;
895 }
896 else
897 {
898 return NULL;
899 }
900 }
901
902 /*********************************************************************************************************//**
903 * @brief This function is used to set CAN to enter initialization mode and enable access bit timing
904 * register.After bit timing configuration ready, user must call CAN_LeaveInitMode() to leave
905 * initialization mode and lock bit timing register to let new configuration take effect.
906 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
907 * @retval None
908 ***********************************************************************************************************/
_CAN_EnterInitMode(HT_CAN_TypeDef * CANx)909 static void _CAN_EnterInitMode(HT_CAN_TypeDef *CANx)
910 {
911 /* Check the parameters */
912 Assert_Param(IS_CAN(CANx));
913
914 CANx->CR |= CAN_CR_INIT;
915 CANx->CR |= CAN_CR_CCE;
916 }
917
918 /*********************************************************************************************************//**
919 * @brief Leave initialization mode
920 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
921 * @retval None
922 ***********************************************************************************************************/
_CAN_LeaveInitMode(HT_CAN_TypeDef * CANx)923 static void _CAN_LeaveInitMode(HT_CAN_TypeDef *CANx)
924 {
925 /* Check the parameters */
926 Assert_Param(IS_CAN(CANx));
927
928 CANx->CR &= (~(CAN_CR_INIT | CAN_CR_CCE));
929
930 while (CANx->CR & CAN_CR_INIT); /* Check INIT bit is released */
931 }
932
933 /*********************************************************************************************************//**
934 * @brief Set Rx message object
935 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
936 * @param MsgNum: Specifies the Message object number, from 1 to 32.
937 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
938 * @param uSingleOrFifoLast: Specifies the end-of-buffer indicator.
939 * @retval None
940 ***********************************************************************************************************/
_CAN_SetRxMsgObj(HT_CAN_TypeDef * CANx,u32 MsgNum,CAN_MSG_TypeDef * pCanMsg,u32 uSingleOrFifoLast)941 static void _CAN_SetRxMsgObj(HT_CAN_TypeDef *CANx, u32 MsgNum, CAN_MSG_TypeDef* pCanMsg, u32 uSingleOrFifoLast)
942 {
943 HT_CANIF_TypeDef *IFx = NULL;
944
945 /* Check the parameters */
946 Assert_Param(IS_CAN(CANx));
947 while (IFx == NULL)
948 {
949 IFx = _GetFreeIF(CANx);
950 }
951 /* Command Setting */
952 IFx->CMASK = CAN_IF_CMASK_WRRD | CAN_IF_CMASK_MASK | CAN_IF_CMASK_ARB |
953 CAN_IF_CMASK_CONTROL | CAN_IF_CMASK_DATAA | CAN_IF_CMASK_DATAB;
954
955 if (pCanMsg->IdType == CAN_STD_ID) /* According STD/EXT ID format, Configure Mask and Arbitration register */
956 {
957 /* Standard Mask.(bit28..bit18). */
958 IFx->ARB0 = 0;
959 IFx->ARB1 = CAN_IF_ARB1_MSGVAL | (pCanMsg->Id & CAN_STD_FRAME_Msk) << 2;
960 IFx->MASK0 = 0;
961 IFx->MASK1 = CAN_IF_MASK1_MDIR | (pCanMsg->IdMask & CAN_STD_FRAME_Msk) << 2;
962 }
963 else
964 {
965 IFx->ARB0 = pCanMsg->Id & CAN_EXT_FRAME_LSB_Msk;
966 IFx->ARB1 = CAN_IF_ARB1_MSGVAL | CAN_IF_ARB1_XTD | ((pCanMsg->Id >> 16) & CAN_EXT_FRAME_MSB_Msk);
967 IFx->MASK0 = pCanMsg->IdMask & CAN_EXT_FRAME_LSB_Msk;
968 IFx->MASK1 = CAN_IF_MASK1_MXTD | CAN_IF_MASK1_MDIR | ((pCanMsg->IdMask>> 16) & CAN_EXT_FRAME_MSB_Msk);
969 }
970
971 IFx->MCR = CAN_IF_MCR_RXIE | CAN_IF_MCR_UMASK;
972
973 if (pCanMsg->FrameType == CAN_REMOTE_FRAME)
974 {
975
976 IFx->ARB1 |= CAN_IF_ARB1_DIR;
977 IFx->MCR |= CAN_IF_MCR_RMTEN;
978 }
979
980 if (uSingleOrFifoLast)
981 IFx->MCR |= CAN_IF_MCR_EOB;
982
983 IFx->MCR &= (~CAN_IF_MCR_INTPND);
984 IFx->MCR &= (~CAN_IF_MCR_NEWDAT);
985 IFx->CREQ = MsgNum;
986 }
987
988 /*********************************************************************************************************//**
989 * @brief Gets the message
990 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
991 * @param MsgNum: Specifies the Message object number, from 1 to 32.
992 * @param Release: Specifies the message release indicator.
993 * @arg TRUE : the message object is released when getting the data.
994 * @arg FALSE: the message object is not released.
995 * @param pCanMsg: Pointer to the message structure for transmitting or receiving data.
996 * @param data: Pointer to the buffer where received data will be stored.
997 * @param len: Pointer to a variable that will store the length of the received data.
998 * @retval 0: Data not empty, 1: Finish, 2: data over run
999 ***********************************************************************************************************/
_CAN_ReadMsgObj(HT_CAN_TypeDef * CANx,u32 MsgNum,u32 Release,CAN_MSG_TypeDef * pCanMsg,u8 * data,u32 * len)1000 static s32 _CAN_ReadMsgObj(HT_CAN_TypeDef *CANx, u32 MsgNum, u32 Release, CAN_MSG_TypeDef* pCanMsg, u8* data, u32* len)
1001 {
1002 HT_CANIF_TypeDef *IFx = NULL;
1003
1004 /* Check the parameters */
1005 Assert_Param(IS_CAN(CANx));
1006
1007 while (IFx == NULL)
1008 {
1009 IFx = _GetFreeIF(CANx);
1010 }
1011
1012 /* read the message contents */
1013 IFx->CMASK = CAN_IF_CMASK_MASK
1014 | CAN_IF_CMASK_ARB
1015 | CAN_IF_CMASK_CONTROL
1016 | CAN_IF_CMASK_CLRINTPND
1017 | (Release ? CAN_IF_CMASK_TXRQSTNEWDAT : 0)
1018 | CAN_IF_CMASK_DATAA
1019 | CAN_IF_CMASK_DATAB;
1020
1021 IFx->CREQ = MsgNum;
1022
1023 while (IFx->CREQ & CAN_FLAG_IF_BUSY)
1024 {
1025 /*Wait */
1026 }
1027
1028 if ((IFx->ARB1 & CAN_IF_ARB1_XTD) == 0)
1029 {
1030 /* standard ID */
1031 pCanMsg->Id = (IFx->ARB1 & CAN_IF_ARB1_ID_Msk) >> 2;
1032 }
1033 else
1034 {
1035 /* extended ID */
1036 pCanMsg->Id = (IFx->ARB1 & CAN_EXT_FRAME_MSB_Msk) << 16;
1037 pCanMsg->Id |= IFx->ARB0;
1038 }
1039 if ((IFx->MCR & CAN_IF_MCR_RMTEN) == 0)
1040 {
1041 pCanMsg->FrameType = CAN_DATA_FRAME;
1042 }
1043 else
1044 {
1045 pCanMsg->FrameType = CAN_REMOTE_FRAME;
1046 }
1047
1048 *len += IFx->MCR & CAN_IF_MCR_DLC_Msk;
1049 data[0] = IFx->DA0R & CAN_IF_DAT_A0_DATA0_Msk;
1050 data[1] = (IFx->DA0R & CAN_IF_DAT_A0_DATA1_Msk) >> CAN_IF_DAT_A0_DATA1_Pos;
1051 data[2] = IFx->DA1R & CAN_IF_DAT_A1_DATA2_Msk;
1052 data[3] = (IFx->DA1R & CAN_IF_DAT_A1_DATA3_Msk) >> CAN_IF_DAT_A1_DATA3_Pos;
1053 data[4] = IFx->DB0R & CAN_IF_DAT_B0_DATA4_Msk;
1054 data[5] = (IFx->DB0R & CAN_IF_DAT_B0_DATA5_Msk) >> CAN_IF_DAT_B0_DATA5_Pos;
1055 data[6] = IFx->DB1R & CAN_IF_DAT_B1_DATA6_Msk;
1056 data[7] = (IFx->DB1R & CAN_IF_DAT_B1_DATA7_Msk) >> CAN_IF_DAT_B1_DATA7_Pos;
1057 if ((IFx->MCR & CAN_IF_MCR_MSGLST) > 0)
1058 {
1059 IFx->CMASK =CAN_IF_CMASK_WRRD | CAN_IF_CMASK_CONTROL;
1060 IFx->MCR &= ~CAN_IF_MCR_MSGLST;
1061 IFx->CREQ = MsgNum;
1062 IFx->CMASK = CAN_IF_CMASK_TXRQSTNEWDAT;
1063 IFx->CREQ = MsgNum;
1064 return 2;
1065 }
1066 if ((IFx->MCR & CAN_IF_MCR_EOB) > 0)
1067 {
1068 return 1;
1069 }
1070 else
1071 {
1072 return 0;
1073 }
1074 }
1075
1076 /*********************************************************************************************************//**
1077 * @brief Gets the first valid message object number from the CAN message valid registers (MVR0 and MVR1).
1078 * This function scans through the message object table to find the first valid message object that is
1079 * not set (i.e., where the corresponding bit in the message valid register is 0).
1080 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
1081 * @retval The index of the first valid message object that is not set.
1082 ***********************************************************************************************************/
_CAN_GetValidMsg(HT_CAN_TypeDef * CANx)1083 static int _CAN_GetValidMsg(HT_CAN_TypeDef *CANx)
1084 {
1085 s32 _MsgNum;
1086 u32 msgNumTable = CANx->MVR0;
1087 msgNumTable |= CANx->MVR1 << 16;
1088 for (_MsgNum = 0 ; _MsgNum < MSG_OBJ_TOTAL_NUM ; _MsgNum++)
1089 {
1090 if ((msgNumTable & 1) == 0)
1091 {
1092 break;
1093 }
1094 msgNumTable = msgNumTable >> 1;
1095 }
1096 return _MsgNum + 1;
1097 }
1098
1099 /*********************************************************************************************************//**
1100 * @brief Checks if the specified message number is valid.
1101 * @param CANx: Pointer to the CAN peripheral.
1102 * @param MsgNum: The message number.
1103 * @retval TRUE if the message number is valid, FALSE otherwise.
1104 ***********************************************************************************************************/
_CAN_CheckMsgIsValid(HT_CAN_TypeDef * CANx,u32 MsgNum)1105 static bool _CAN_CheckMsgIsValid(HT_CAN_TypeDef *CANx, u32 MsgNum)
1106 {
1107 if ((MsgNum == 0) || (MsgNum > MSG_OBJ_TOTAL_NUM))
1108 {
1109 return FALSE;
1110 }
1111 return TRUE;
1112 }
1113
1114 /*********************************************************************************************************//**
1115 * @brief Clears the pending flag for a specific CAN message object.
1116 * @param CANx: where the CANx is the selected CAN from the CAN peripherals.
1117 * @param MsgNum: The message number.
1118 * @retval None.
1119 ***********************************************************************************************************/
_CAN_ClearMsgPendingFlag(HT_CAN_TypeDef * CANx,u32 MsgNum)1120 static void _CAN_ClearMsgPendingFlag(HT_CAN_TypeDef *CANx, u32 MsgNum)
1121 {
1122 HT_CANIF_TypeDef *IFx = NULL;
1123 while (IFx == NULL)
1124 {
1125 IFx = _GetFreeIF(CANx);
1126 }
1127 IFx->CMASK = CAN_IF_CMASK_CLRINTPND;
1128 IFx->CREQ = MsgNum;
1129 }
1130 /**
1131 * @}
1132 */
1133
1134
1135 /**
1136 * @}
1137 */
1138
1139 /**
1140 * @}
1141 */
1142