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