1 /****************************************************************************
2 * @file canfd.c
3 * @version V1.00
4 * @brief CAN FD driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2023 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9
10 #include "NuMicro.h"
11 #include "string.h"
12
13 /*******************************************************************************
14 * Definitions
15 ******************************************************************************/
16
17 /* Minimum number of time quanta in a bit. */
18 #define MIN_TIME_QUANTA 9ul
19 /* Maximum number of time quanta in a bit. */
20 #define MAX_TIME_QUANTA 20ul
21 /* Number of receive FIFOs (1 - 2) */
22 #define CANFD_NUM_RX_FIFOS 2ul
23
24 /*CANFD max nominal bit rate*/
25 #define MAX_NOMINAL_BAUDRATE (1000000UL)
26
27 /* Tx Event FIFO Element ESI(Error State Indicator) */
28 #define TX_FIFO_E0_EVENT_ESI_Pos (31)
29 #define TX_FIFO_E0_EVENT_ESI_Msk (0x1ul << TX_FIFO_E0_EVENT_ESI_Pos)
30
31 /* Tx Event FIFO Element XTD(Extended Identifier) */
32 #define TX_FIFO_E0_EVENT_XTD_Pos (30)
33 #define TX_FIFO_E0_EVENT_XTD_Msk (0x1ul << TX_FIFO_E0_EVENT_XTD_Pos)
34
35 /* Tx Event FIFO Element RTR(Remote Transmission Request) */
36 #define TX_FIFO_E0_EVENT_RTR_Pos (29)
37 #define TX_FIFO_E0_EVENT_RTR_Msk (0x1ul << TX_FIFO_E0_EVENT_RTR_Pos)
38
39 /* Tx Event FIFO Element ID(Identifier) */
40 #define TX_FIFO_E0_EVENT_ID_Pos (0)
41 #define TX_FIFO_E0_EVENT_ID_Msk (0x1FFFFFFFul << TX_FIFO_E0_EVENT_ID_Pos)
42
43 /* Tx Event FIFO Element MM(Message Marker) */
44 #define TX_FIFO_E1_EVENT_MM_Pos (24)
45 #define TX_FIFO_E1_EVENT_MM_Msk (0xFFul << TX_FIFO_E1_EVENT_MM_Pos)
46
47 /* Tx Event FIFO Element ET(Event Type) */
48 #define TX_FIFO_E1_EVENT_ET_Pos (22)
49 #define TX_FIFO_E1_EVENT_ET_Msk (0x3ul << TX_FIFO_E1_EVENT_ET_Pos)
50
51 /* Tx Event FIFO Element FDF(FD Format) */
52 #define TX_FIFO_E1_EVENT_FDF_Pos (21)
53 #define TX_FIFO_E1_EVENT_FDF_Msk (0x1ul << TX_FIFO_E1_EVENT_FDF_Pos)
54
55 /* Tx Event FIFO Element BRS(Bit Rate Switch) */
56 #define TX_FIFO_E1_EVENT_BRS_Pos (20)
57 #define TX_FIFO_E1_EVENT_BRS_Msk (0x1ul << TX_FIFO_E1_EVENT_BRS_Pos)
58
59 /* Tx Event FIFO Element DLC(Data Length Code) */
60 #define TX_FIFO_E1_EVENT_DLC_Pos (16)
61 #define TX_FIFO_E1_EVENT_DLC_Msk (0xFul << TX_FIFO_E1_EVENT_DLC_Pos)
62
63 /* Tx Event FIFO Element TXTS(Tx Timestamp) */
64 #define TX_FIFO_E1A_EVENT_TXTS_Pos (0)
65 #define TX_FIFO_E1A_EVENT_TXTS_Msk (0xFFFFul << TX_FIFO_E1A_EVENT_TXTS_Pos)
66
67 /* Tx Event FIFO Element MM(Message Marker) */
68 #define TX_FIFO_E1B_EVENT_MM_Pos (8)
69 #define TX_FIFO_E1B_EVENT_MM_Msk (0xFFul << TX_FIFO_E1B_EVENT_MM_Pos)
70
71 /* Tx Event FIFO Element TSC(Timestamp Captured) */
72 #define TX_FIFO_E1B_EVENT_TSC_Pos (4)
73 #define TX_FIFO_E1B_EVENT_TSC_Msk (0x1ul << TX_FIFO_E1B_EVENT_TSC_Pos)
74
75 /* Tx Event FIFO Element TSC(Timestamp Captured) */
76 #define TX_FIFO_E1B_EVENT_TXTS_Pos (0)
77 #define TX_FIFO_E1B_EVENT_TXTS_Msk (0xFul << TX_FIFO_E1B_EVENT_TSC_Pos)
78
79 /* Rx Buffer and FIFO Element ESI2(Error State Indicator) */
80 #define RX_BUFFER_AND_FIFO_R0_ELEM_ESI_Pos (31)
81 #define RX_BUFFER_AND_FIFO_R0_ELEM_ESI_Msk (0x1ul << RX_BUFFER_AND_FIFO_R0_ELEM_ESI_Pos)
82
83 /* Rx Buffer and FIFO Element XTD(Extended Identifier) */
84 #define RX_BUFFER_AND_FIFO_R0_ELEM_XTD_Pos (30)
85 #define RX_BUFFER_AND_FIFO_R0_ELEM_XTD_Msk (0x1ul << RX_BUFFER_AND_FIFO_R0_ELEM_XTD_Pos)
86
87 /* Rx Buffer and FIFO Element RTR(Remote Transmission Request) */
88 #define RX_BUFFER_AND_FIFO_R0_ELEM_RTR_Pos (29)
89 #define RX_BUFFER_AND_FIFO_R0_ELEM_RTR_Msk (0x1ul << RX_BUFFER_AND_FIFO_R0_ELEM_RTR_Pos)
90
91 /* Rx Buffer and FIFO Element ID(Identifier) */
92 #define RX_BUFFER_AND_FIFO_R0_ELEM_ID_Pos (0)
93 #define RX_BUFFER_AND_FIFO_R0_ELEM_ID_Msk (0x1FFFFFFFul << RX_BUFFER_AND_FIFO_R0_ELEM_ID_Pos)
94
95 /* Rx Buffer and FIFO Element ANMF(Accepted Non-matching Frame) */
96 #define RX_BUFFER_AND_FIFO_R1_ELEM_ANMF_Pos (31)
97 #define RX_BUFFER_AND_FIFO_R1_ELEM_ANMF_Msk (0x1ul << RX_BUFFER_AND_FIFO_R1_ELEM_ANMF_Pos)
98
99 /* Rx Buffer and FIFO Element FIDX(Filter Index) */
100 #define RX_BUFFER_AND_FIFO_R1_ELEM_FIDX_Pos (24)
101 #define RX_BUFFER_AND_FIFO_R1_ELEM_FIDX_Msk (0x7Ful << RX_BUFFER_AND_FIFO_R1_ELEM_FIDX_Pos)
102
103 /* Rx Buffer and FIFO Element FDF(FD Format) */
104 #define RX_BUFFER_AND_FIFO_R1_ELEM_FDF_Pos (21)
105 #define RX_BUFFER_AND_FIFO_R1_ELEM_FDF_Msk (0x1ul << RX_BUFFER_AND_FIFO_R1_ELEM_FDF_Pos)
106
107 /* Rx Buffer and FIFO Element BRS(Bit Rate Swit) */
108 #define RX_BUFFER_AND_FIFO_R1_ELEM_BSR_Pos (20)
109 #define RX_BUFFER_AND_FIFO_R1_ELEM_BSR_Msk (0x1ul << RX_BUFFER_AND_FIFO_R1_ELEM_BSR_Pos)
110
111 /* Rx Buffer and FIFO Element DLC(Bit Rate Swit) */
112 #define RX_BUFFER_AND_FIFO_R1_ELEM_DLC_Pos (16)
113 #define RX_BUFFER_AND_FIFO_R1_ELEM_DLC_Msk (0xFul << RX_BUFFER_AND_FIFO_R1_ELEM_DLC_Pos)
114
115 /* Rx Buffer and FIFO Element RXTS(Rx Timestamp) */
116 #define RX_BUFFER_AND_FIFO_R1_ELEM_RXTS_Pos (0)
117 #define RX_BUFFER_AND_FIFO_R1_ELEM_RXTS_Msk (0xFFFFul << RX_BUFFER_AND_FIFO_R1_ELEM_RXTS_Pos)
118
119 /* Tx Buffer Element ESI(Error State Indicator) */
120 #define TX_BUFFER_T0_ELEM_ESI_Pos (31)
121 #define TX_BUFFER_T0_ELEM_ESI_Msk (0x1ul << TX_BUFFER_T0_ELEM_ESI_Pos)
122
123 /* Tx Buffer Element XTD(Extended Identifier) */
124 #define TX_BUFFER_T0_ELEM_XTD_Pos (30)
125 #define TX_BUFFER_T0_ELEM_XTD_Msk (0x1ul << TX_BUFFER_T0_ELEM_XTD_Pos)
126
127 /* Tx Buffer RTR(Remote Transmission Request) */
128 #define TX_BUFFER_T0_ELEM_RTR_Pos (29)
129 #define TX_BUFFER_T0_ELEM_RTR_Msk (0x1ul << TX_BUFFER_T0_ELEM_RTR_Pos)
130
131 /* Tx Buffer Element ID(Identifier) */
132 #define TX_BUFFER_T0_ELEM_ID_Pos (0)
133 #define TX_BUFFER_T0_ELEM_ID_Msk (0x1FFFFFFFul << TX_BUFFER_T0_ELEM_ID_Pos)
134
135 /* Tx Buffer Element MM(Message Marker) */
136 #define TX_BUFFER_T1_ELEM_MM1_Pos (24)
137 #define TX_BUFFER_T1_ELEM_MM1_Msk (0xFFul << TX_BUFFER_T1_ELEM_MM1_Pos)
138
139 /* Tx Buffer Element EFC(Event FIFO Control) */
140 #define TX_BUFFER_T1_ELEM_EFC_Pos (23)
141 #define TX_BUFFER_T1_ELEM_EFC_Msk (0xFFul << TX_BUFFER_T1_ELEM_EFC_Pos)
142
143 /* Tx Buffer Element TSCE(Time Stamp Capture Enable for TSU) */
144 #define TX_BUFFER_T1_ELEM_TSCE_Pos (22)
145 #define TX_BUFFER_T1_ELEM_TSCE_Msk (0x1ul << TX_BUFFER_T1_ELEM_TSCE_Pos)
146
147 /* Tx Buffer Element FDF(FD Format) */
148 #define TX_BUFFER_T1_ELEM_FDF_Pos (21)
149 #define TX_BUFFER_T1_ELEM_FDF_Msk (0x1ul << TX_BUFFER_T1_ELEM_FDF_Pos)
150
151 /* Tx Buffer Element BRS(Bit Rate Swit) */
152 #define TX_BUFFER_T1_ELEM_BSR_Pos (20)
153 #define TX_BUFFER_T1_ELEM_BSR_Msk (0x1ul << TX_BUFFER_T1_ELEM_BSR_Pos)
154
155 /* Tx Buffer Element DLC(Bit Rate Swit) */
156 #define TX_BUFFER_T1_ELEM_DLC_Pos (16)
157 #define TX_BUFFER_T1_ELEM_DLC_Msk (0xFul << TX_BUFFER_T1_ELEM_DLC_Pos)
158
159 /* Tx Buffer Element MM(Message Marker) */
160 #define TX_BUFFER_T1_ELEM_MM0_Pos (8)
161 #define TX_BUFFER_T1_ELEM_MM0_Msk (0xFFul << TX_BUFFER_T1_ELEM_MM0_Pos)
162
163 #define CANFD_RXFS_RFL CANFD_RXF0S_RF0L_Msk
164
165 /** @addtogroup Standard_Driver Standard Driver
166 @{
167 */
168
169 /** @addtogroup CANFD_Driver CAN_FD Driver
170 @{
171 */
172
173 /** @addtogroup CANFD_EXPORTED_FUNCTIONS CAN_FD Exported Functions
174 @{
175 */
176
177 static void CANFD_InitRxFifo(CANFD_T *canfd, uint32_t u32RxFifoNum, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize, uint32_t u32FifoWM, E_CANFD_DATA_FIELD_SIZE eFifoSize);
178 static void CANFD_InitRxDBuf(CANFD_T *canfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize, E_CANFD_DATA_FIELD_SIZE eRxBufSize);
179 static void CANFD_InitTxDBuf(CANFD_T *canfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize, E_CANFD_DATA_FIELD_SIZE eTxBufSize);
180 static void CANFD_InitTxEvntFifo(CANFD_T *canfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize, uint32_t u32FifoWaterLvl);
181 static void CANFD_ConfigSIDFC(CANFD_T *canfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize);
182 static void CANFD_ConfigXIDFC(CANFD_T *canfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize);
183
184 /**
185 * @brief Calculates the CAN FD RAM buffer address.
186 *
187 * @param[in] psConfigAddr CAN FD element star address structure.
188 * @param[in] psConfigSize CAN FD element size structure.
189 *
190 * @return None.
191 *
192 * @details Calculates the CAN FD RAM buffer address.
193 */
CANFD_CalculateRamAddress(CANFD_RAM_PART_T * psConfigAddr,CANFD_ELEM_SIZE_T * psConfigSize)194 static void CANFD_CalculateRamAddress(CANFD_RAM_PART_T *psConfigAddr, CANFD_ELEM_SIZE_T *psConfigSize)
195 {
196 uint32_t u32RamAddrOffset = 0;
197
198 /* Get the Standard Message ID Filter element address */
199 if (psConfigSize->u32SIDFC > 0)
200 {
201 psConfigAddr->u32SIDFC_FLSSA = 0;
202 u32RamAddrOffset += psConfigSize->u32SIDFC * sizeof(CANFD_STD_FILTER_T);
203 }
204
205 /* Get the Extended Message ID Filter element address */
206 if (psConfigSize->u32XIDFC > 0)
207 {
208 psConfigAddr->u32XIDFC_FLESA = u32RamAddrOffset;
209 u32RamAddrOffset += psConfigSize->u32XIDFC * sizeof(CANFD_EXT_FILTER_T);
210 }
211
212 /* Get the Rx FIFO0 element address */
213 if (psConfigSize->u32RxFifo0 > 0)
214 {
215 psConfigAddr->u32RXF0C_F0SA = u32RamAddrOffset;
216 u32RamAddrOffset += psConfigSize->u32RxFifo0 * sizeof(CANFD_BUF_T);
217 }
218
219 /* Get the Rx FIFO1 element address */
220 if (psConfigSize->u32RxFifo1 > 0)
221 {
222 psConfigAddr->u32RXF1C_F1SA = u32RamAddrOffset;
223 u32RamAddrOffset += psConfigSize->u32RxFifo1 * sizeof(CANFD_BUF_T);
224 }
225
226 /* Get the Rx Buffer element address */
227 if (psConfigSize->u32RxBuf > 0)
228 {
229 psConfigAddr->u32RXBC_RBSA = u32RamAddrOffset;
230 u32RamAddrOffset += psConfigSize->u32RxBuf * sizeof(CANFD_BUF_T);
231 }
232
233 /* Get the TX Event FIFO element address */
234 if (psConfigSize->u32TxEventFifo > 0)
235 {
236 psConfigAddr->u32TXEFC_EFSA = u32RamAddrOffset;
237 u32RamAddrOffset += psConfigSize->u32TxEventFifo * sizeof(CANFD_EXT_FILTER_T);
238 }
239
240 /* Get the Tx Buffer element address */
241 if (psConfigSize->u32TxBuf > 0)
242 {
243 psConfigAddr->u32TXBC_TBSA = u32RamAddrOffset;
244 u32RamAddrOffset += psConfigSize->u32TxBuf * sizeof(CANFD_BUF_T);
245 }
246 }
247
248 /**
249 * @brief Get the default configuration structure.
250 *
251 * @param[in] psConfig Pointer to CAN FD configuration structure.
252 * @param[in] u8OpMode Setting the CAN FD Operating mode.
253 *
254 * @return None.
255 *
256 * @details This function initializes the CAN FD configure structure to default value.
257 * The default value are:
258 * sNormBitRate.u32BitRate = 500000bps;
259 * u32DataBaudRate = 0(CAN mode) or 1000000(CAN FD mode) ;
260 * u32MRamSize = 6144 bytes (1536 words);
261 * bEnableLoopBack = FALSE;
262 * bBitRateSwitch = FALSE(CAN Mode) or TRUE(CAN FD Mode);
263 * bFDEn = FALSE(CAN Mode) or TRUE(CAN FD Mode);
264 */
CANFD_GetDefaultConfig(CANFD_FD_T * psConfig,uint8_t u8OpMode)265 void CANFD_GetDefaultConfig(CANFD_FD_T *psConfig, uint8_t u8OpMode)
266 {
267 memset(psConfig, 0, sizeof(CANFD_FD_T));
268
269 psConfig->sBtConfig.sNormBitRate.u32BitRate = 500000;
270
271 if (u8OpMode == CANFD_OP_CAN_MODE)
272 {
273 psConfig->sBtConfig.sDataBitRate.u32BitRate = 0;
274 psConfig->sBtConfig.bFDEn = FALSE;
275 psConfig->sBtConfig.bBitRateSwitch = FALSE;
276 }
277 else
278 {
279 psConfig->sBtConfig.sDataBitRate.u32BitRate = 1000000;
280 psConfig->sBtConfig.bFDEn = TRUE;
281 psConfig->sBtConfig.bBitRateSwitch = TRUE;
282 }
283
284 /*Disable the Internal Loopback mode */
285 psConfig->sBtConfig.bEnableLoopBack = FALSE;
286 /*Get the CAN FD memory size(number of byte) */
287 psConfig->u32MRamSize = CANFD_SRAM_SIZE;
288
289 /* CAN FD Standard message ID elements as 64 elements */
290 psConfig->sElemSize.u32SIDFC = 64;
291 /* CAN FD Extended message ID elements as 64 elements */
292 psConfig->sElemSize.u32XIDFC = 64;
293 /* CAN FD TX Buffer elements as 8 elements */
294 psConfig->sElemSize.u32TxBuf = 8;
295 /* CAN FD RX Buffer elements as 8 elements */
296 psConfig->sElemSize.u32RxBuf = 8;
297 /* CAN FD RX FIFO0 elements as 48 elements */
298 psConfig->sElemSize.u32RxFifo0 = 48;
299 /* CAN FD RX FIFO1 elements as 8 elements */
300 psConfig->sElemSize.u32RxFifo1 = 8;
301 /* CAN FD TX Event FOFI elements as 8 elements */
302 psConfig->sElemSize.u32TxEventFifo = 8;
303 /*Calculates the CAN FD RAM buffer address*/
304 CANFD_CalculateRamAddress(&psConfig->sMRamStartAddr, &psConfig->sElemSize);
305 }
306
307
308 /**
309 * @brief Encode the Data Length Code.
310 *
311 * @param[in] u8NumberOfBytes Number of bytes in a message.
312 *
313 * @return Data Length Code.
314 *
315 * @details Converts number of bytes in a message into a Data Length Code.
316 */
CANFD_EncodeDLC(uint8_t u8NumberOfBytes)317 static uint8_t CANFD_EncodeDLC(uint8_t u8NumberOfBytes)
318 {
319 if (u8NumberOfBytes <= 8) return u8NumberOfBytes;
320 else if (u8NumberOfBytes <= 12) return 9;
321 else if (u8NumberOfBytes <= 16) return 10;
322 else if (u8NumberOfBytes <= 20) return 11;
323 else if (u8NumberOfBytes <= 24) return 12;
324 else if (u8NumberOfBytes <= 32) return 13;
325 else if (u8NumberOfBytes <= 48) return 14;
326 else return 15;
327 }
328
329
330 /**
331 * @brief Decode the Data Length Code.
332 *
333 * @param[in] u8Dlc Data Length Code.
334 *
335 * @return Number of bytes in a message.
336 *
337 * @details Converts a Data Length Code into a number of message bytes.
338 */
CANFD_DecodeDLC(uint8_t u8Dlc)339 static uint8_t CANFD_DecodeDLC(uint8_t u8Dlc)
340 {
341 if (u8Dlc <= 8) return u8Dlc;
342 else if (u8Dlc == 9) return 12;
343 else if (u8Dlc == 10) return 16;
344 else if (u8Dlc == 11) return 20;
345 else if (u8Dlc == 12) return 24;
346 else if (u8Dlc == 13) return 32;
347 else if (u8Dlc == 14) return 48;
348 else return 64;
349 }
350
351
352 /**
353 * @brief Sets the CAN FD protocol timing characteristic.
354 *
355 * @param[in] psCanfd The pointer of the specified CANFD module.
356 * @param[in] psConfig Pointer to the timing configuration structure.
357 *
358 * @return None.
359 *
360 * @details This function gives user settings to CAN bus timing characteristic.
361 * The function is for an experienced user. For less experienced users, call
362 * the CANFD_Open() and fill the baud rate field with a desired value.
363 * This provides the default timing characteristics to the module.
364 */
CANFD_SetTimingConfig(CANFD_T * psCanfd,const CANFD_TIMEING_CONFIG_T * psConfig)365 static void CANFD_SetTimingConfig(CANFD_T *psCanfd, const CANFD_TIMEING_CONFIG_T *psConfig)
366 {
367 if (psCanfd == (CANFD_T *)CANFD0)
368 {
369 /* Set CANFD0 clock divider number */
370 CLK->CLKDIV5 = (CLK->CLKDIV5 & ~CLK_CLKDIV5_CANFD0DIV_Msk) | CLK_CLKDIV5_CANFD0(psConfig->u8PreDivider) ;
371 }
372 else if (psCanfd == (CANFD_T *)CANFD1)
373 {
374 /* Set CANFD1 clock divider number */
375 CLK->CLKDIV5 = (CLK->CLKDIV5 & ~CLK_CLKDIV5_CANFD1DIV_Msk) | CLK_CLKDIV5_CANFD1(psConfig->u8PreDivider) ;
376 }
377 else
378 {
379 return;
380 }
381
382 /* configuration change enable */
383 psCanfd->CCCR |= CANFD_CCCR_CCE_Msk;
384
385 /* nominal bit rate */
386 psCanfd->NBTP = (((psConfig->u8NominalRJumpwidth & 0x7F) - 1) << 25) +
387 (((psConfig->u16NominalPrescaler & 0x1FF) - 1) << 16) +
388 ((((psConfig->u8NominalPhaseSeg1 + psConfig->u8NominalPropSeg) & 0xFF) - 1) << 8) +
389 (((psConfig->u8NominalPhaseSeg2 & 0x7F) - 1) << 0);
390
391
392 /* canfd->DBTP */
393 if (psCanfd->CCCR & CANFD_CCCR_FDOE_Msk)
394 {
395 psCanfd->DBTP = (((psConfig->u8DataPrescaler & 0x1F) - 1) << 16) +
396 ((((psConfig->u8DataPhaseSeg1 + psConfig->u8DataPropSeg) & 0x1F) - 1) << 8) +
397 (((psConfig->u8DataPhaseSeg2 & 0xF) - 1) << 4) +
398 (((psConfig->u8DataRJumpwidth & 0xF) - 1) << 0);
399 }
400 }
401
402
403 /**
404 * @brief Get the segment values.
405 *
406 * @param[in] u32NominalBaudRate The nominal speed in bps.
407 * @param[in] u32DataBaudRate The data speed in bps.
408 * @param[in] u32Ntq Number of nominal time quanta per bit.
409 * @param[in] u32Dtq Number of data time quanta per bit.
410 * @param[in] psConfig Passed is a configuration structure, on return the configuration is stored in the structure
411 *
412 * @return None.
413 *
414 * @details Calculates the segment values for a single bit time for nominal and data baudrates.
415 */
CANFD_GetSegments(uint32_t u32NominalBaudRate,uint32_t u32DataBaudRate,uint32_t u32Ntq,uint32_t u32Dtq,CANFD_TIMEING_CONFIG_T * psConfig)416 static void CANFD_GetSegments(uint32_t u32NominalBaudRate, uint32_t u32DataBaudRate, uint32_t u32Ntq, uint32_t u32Dtq, CANFD_TIMEING_CONFIG_T *psConfig)
417 {
418 float ideal_sp;
419 int int32P1;
420
421 /* get ideal sample point */
422 if (u32NominalBaudRate >= 1000000) ideal_sp = 0.750;
423 else if (u32NominalBaudRate >= 800000) ideal_sp = 0.800;
424 else ideal_sp = 0.875;
425
426 /* distribute time quanta */
427 int32P1 = (int)(u32Ntq * ideal_sp);
428 /* can controller doesn't separate prop seg and phase seg 1 */
429 psConfig->u8NominalPropSeg = 0;
430 /* subtract one TQ for sync seg */
431 psConfig->u8NominalPhaseSeg1 = int32P1 - 1;
432 psConfig->u8NominalPhaseSeg2 = u32Ntq - int32P1;
433 /* sjw is 20% of total TQ, rounded to nearest int */
434 psConfig->u8NominalRJumpwidth = (u32Ntq + (5 - 1)) / 5;
435
436
437 /* if using baud rate switching then distribute time quanta for data rate */
438 if (u32Dtq > 0)
439 {
440 /* get ideal sample point */
441 if (u32DataBaudRate >= 1000000) ideal_sp = 0.750;
442 else if (u32DataBaudRate >= 800000) ideal_sp = 0.800;
443 else ideal_sp = 0.875;
444
445 /* distribute time quanta */
446 int32P1 = (int)(u32Dtq * ideal_sp);
447 /* can controller doesn't separate prop seg and phase seg 1 */
448 psConfig->u8DataPropSeg = 0;
449 /* subtract one TQ for sync seg */
450 psConfig->u8DataPhaseSeg1 = int32P1 - 1;
451 psConfig->u8DataPhaseSeg2 = u32Dtq - int32P1;
452 /* sjw is 20% of total TQ, rounded to nearest int */
453 psConfig->u8DataRJumpwidth = (u32Dtq + (5 - 1)) / 5;
454 }
455 else
456 {
457 psConfig->u8DataPropSeg = 0;
458 psConfig->u8DataPhaseSeg1 = 0;
459 psConfig->u8DataPhaseSeg2 = 0;
460 psConfig->u8DataRJumpwidth = 0;
461 }
462 }
463
464
465 /**
466 * @brief Calculates the CAN controller timing values for specific baudrates.
467 *
468 * @param[in] psCanfd Pointer to CAN FD configuration structure.
469 * @param[in] u32NominalBaudRate The nominal speed in bps.
470 * @param[in] u32DataBaudRate The data speed in bps. Zero to disable baudrate switching.
471 * @param[in] u32SourceClock_Hz CAN FD Protocol Engine clock source frequency in Hz.
472 * @param[in] psConfig Passed is a configuration structure, on return the configuration is stored in the structure
473 *
474 * @return true if timing configuration found, false if failed to find configuration.
475 *
476 * @details Calculates the CAN controller timing values for specific baudrates.
477 */
CANFD_CalculateTimingValues(CANFD_T * psCanfd,uint32_t u32NominalBaudRate,uint32_t u32DataBaudRate,uint32_t u32SourceClock_Hz,CANFD_TIMEING_CONFIG_T * psConfig)478 static uint32_t CANFD_CalculateTimingValues(CANFD_T *psCanfd, uint32_t u32NominalBaudRate, uint32_t u32DataBaudRate, uint32_t u32SourceClock_Hz, CANFD_TIMEING_CONFIG_T *psConfig)
479 {
480 int i32Nclk;
481 int i32Nclk2;
482 int i32Ntq;
483 int i32Dclk;
484 int i32Dclk2;
485 int i32Dtq;
486
487 /* observe baud rate maximums */
488 if (u32NominalBaudRate > MAX_NOMINAL_BAUDRATE) u32NominalBaudRate = MAX_NOMINAL_BAUDRATE;
489
490 for (i32Ntq = MAX_TIME_QUANTA; i32Ntq >= MIN_TIME_QUANTA; i32Ntq--)
491 {
492 i32Nclk = u32NominalBaudRate * i32Ntq;
493
494 for (psConfig->u16NominalPrescaler = 0x001; psConfig->u16NominalPrescaler <= 0x400; (psConfig->u16NominalPrescaler)++)
495 {
496 i32Nclk2 = i32Nclk * psConfig->u16NominalPrescaler;
497
498 if (((u32SourceClock_Hz / i32Nclk2) <= 5) && ((u32SourceClock_Hz % i32Nclk2) == 0))
499 {
500 psConfig->u8PreDivider = u32SourceClock_Hz / i32Nclk2;
501
502 /* FD Operation? */
503 if ( psCanfd->CCCR & CANFD_CCCR_FDOE_Msk )
504 {
505 /* Exception case: Let u32DataBaudRate is same with u32NominalBaudRate. */
506 if (u32DataBaudRate == 0)
507 u32DataBaudRate = u32NominalBaudRate;
508
509 /* if baudrates are the same and the solution for nominal will work for
510 data, then use the nominal settings for both */
511 if ((u32DataBaudRate == u32NominalBaudRate) && (psConfig->u16NominalPrescaler <= 0x20))
512 {
513 i32Dtq = i32Ntq;
514 psConfig->u8DataPrescaler = (uint8_t)psConfig->u16NominalPrescaler;
515 CANFD_GetSegments(u32NominalBaudRate, u32DataBaudRate, i32Ntq, i32Dtq, psConfig);
516 return TRUE;
517 }
518
519 /* calculate data settings */
520 for (i32Dtq = MAX_TIME_QUANTA; i32Dtq >= MIN_TIME_QUANTA; i32Dtq--)
521 {
522 i32Dclk = u32DataBaudRate * i32Dtq;
523
524 for (psConfig->u8DataPrescaler = 0x01; psConfig->u8DataPrescaler <= 0x20; (psConfig->u8DataPrescaler)++)
525 {
526 i32Dclk2 = i32Dclk * psConfig->u8DataPrescaler;
527 if (u32SourceClock_Hz == ((uint32_t)i32Dclk2 * psConfig->u8PreDivider))
528 {
529 CANFD_GetSegments(u32NominalBaudRate, u32DataBaudRate, i32Ntq, i32Dtq, psConfig);
530 return TRUE;
531 }
532 }
533 }
534 }
535 else
536 {
537 psConfig->u8DataPrescaler = 0;
538 CANFD_GetSegments(u32NominalBaudRate, 0, i32Ntq, 0, psConfig);
539 return TRUE;
540 }
541 }
542 }
543 }
544
545 /* failed to find solution */
546 return FALSE;
547 }
548
549
550 /**
551 * @brief Config message ram and Set bit-time.
552 *
553 * @param[in] psCanfd The pointer to CAN FD module base address.
554 * @param[in] psCanfdStr message ram setting and bit-time setting
555 *
556 * @return None.
557 *
558 * @details Converts a Data Length Code into a number of message bytes.
559 */
CANFD_Open(CANFD_T * psCanfd,CANFD_FD_T * psCanfdStr)560 void CANFD_Open(CANFD_T *psCanfd, CANFD_FD_T *psCanfdStr)
561 {
562 uint32_t u32RegLockLevel = SYS_IsRegLocked();
563
564 if (u32RegLockLevel)
565 SYS_UnlockReg();
566
567 if (psCanfd == (CANFD_T *)CANFD0)
568 {
569 CLK_EnableModuleClock(CANFD0_MODULE);
570 SYS_ResetModule(CANFD0_RST);
571 }
572 else if (psCanfd == (CANFD_T *)CANFD1)
573 {
574 CLK_EnableModuleClock(CANFD1_MODULE);
575 SYS_ResetModule(CANFD1_RST);
576 }
577 else
578 {
579 if (u32RegLockLevel)
580 SYS_LockReg();
581
582 return;
583 }
584
585 /* configuration change enable */
586 psCanfd->CCCR |= CANFD_CCCR_CCE_Msk;
587
588 if (psCanfdStr->sBtConfig.bBitRateSwitch)
589 {
590 /* enable FD and baud-rate switching */
591 psCanfd->CCCR |= CANFD_CCCR_BRSE_Msk;
592 }
593
594 if (psCanfdStr->sBtConfig.bFDEn)
595 {
596 /*FD Operation enabled*/
597 psCanfd->CCCR |= CANFD_CCCR_FDOE_Msk;
598 }
599
600 /*Clear the Rx Fifo0 element setting */
601 psCanfd->RXF0C = 0;
602 /*Clear the Rx Fifo1 element setting */
603 psCanfd->RXF1C = 0;
604
605 /* calculate and apply timing */
606 if (CANFD_CalculateTimingValues(psCanfd, psCanfdStr->sBtConfig.sNormBitRate.u32BitRate, psCanfdStr->sBtConfig.sDataBitRate.u32BitRate,
607 SystemCoreClock, &psCanfdStr->sBtConfig.sConfigBitTing))
608 {
609 CANFD_SetTimingConfig(psCanfd, &psCanfdStr->sBtConfig.sConfigBitTing);
610 }
611
612 if (u32RegLockLevel)
613 SYS_LockReg();
614
615 /* Configures the Standard ID Filter element */
616 if (psCanfdStr->sElemSize.u32SIDFC != 0)
617 CANFD_ConfigSIDFC(psCanfd, &psCanfdStr->sMRamStartAddr, &psCanfdStr->sElemSize);
618
619 /*Configures the Extended ID Filter element */
620 if (psCanfdStr->sElemSize.u32XIDFC != 0)
621 CANFD_ConfigXIDFC(psCanfd, &psCanfdStr->sMRamStartAddr, &psCanfdStr->sElemSize);
622
623 /*Configures the Tx Buffer element */
624 if (psCanfdStr->sElemSize.u32TxBuf != 0)
625 CANFD_InitTxDBuf(psCanfd, &psCanfdStr->sMRamStartAddr, &psCanfdStr->sElemSize, eCANFD_BYTE64);
626
627 /*Configures the Rx Buffer element */
628 if (psCanfdStr->sElemSize.u32RxBuf != 0)
629 CANFD_InitRxDBuf(psCanfd, &psCanfdStr->sMRamStartAddr, &psCanfdStr->sElemSize, eCANFD_BYTE64);
630
631 /*Configures the Rx Fifo0 element */
632 if (psCanfdStr->sElemSize.u32RxFifo0 != 0)
633 CANFD_InitRxFifo(psCanfd, 0, &psCanfdStr->sMRamStartAddr, &psCanfdStr->sElemSize, 0, eCANFD_BYTE64);
634
635 /*Configures the Rx Fifo1 element */
636 if (psCanfdStr->sElemSize.u32RxFifo1 != 0)
637 CANFD_InitRxFifo(psCanfd, 1, &psCanfdStr->sMRamStartAddr, &psCanfdStr->sElemSize, 0, eCANFD_BYTE64);
638
639 /*Configures the Tx Event FIFO element */
640 if (psCanfdStr->sElemSize.u32TxEventFifo != 0)
641 CANFD_InitTxEvntFifo(psCanfd, &psCanfdStr->sMRamStartAddr, &psCanfdStr->sElemSize, 0);
642
643 /*Reject all Non-matching Frames Extended ID and Frames Standard ID,Reject all remote frames with 11-bit standard IDs and 29-bit extended IDs */
644 CANFD_SetGFC(psCanfd, eCANFD_REJ_NON_MATCH_FRM, eCANFD_REJ_NON_MATCH_FRM, 1, 1);
645
646 if (psCanfdStr->sBtConfig.bEnableLoopBack)
647 {
648 psCanfd->CCCR |= CANFD_CCCR_TEST_Msk;
649 psCanfd->TEST |= CANFD_TEST_LBCK_Msk;
650 }
651 }
652
653
654 /**
655 * @brief Close the CAN FD Bus.
656 *
657 * @param[in] psCanfd The pointer to CANFD module base address.
658 *
659 * @return None.
660 *
661 * @details Disable the CAN FD clock and Interrupt.
662 */
CANFD_Close(CANFD_T * psCanfd)663 void CANFD_Close(CANFD_T *psCanfd)
664 {
665 if (psCanfd == (CANFD_T *)CANFD0)
666 {
667 CLK_DisableModuleClock(CANFD0_MODULE);
668 }
669 else if (psCanfd == (CANFD_T *)CANFD1)
670 {
671 CLK_DisableModuleClock(CANFD1_MODULE);
672 }
673 }
674
675
676 /**
677 * @brief Get the element's address when read transmit buffer.
678 *
679 * @param[in] psCanfd The pointer of the specified CAN FD module.
680 * @param[in] u32Idx The number of the transmit buffer element
681 *
682 * @return Address of the element in transmit buffer.
683 *
684 * @details The function is used to get the element's address when read transmit buffer.
685 */
CANFD_GetTxBufferElementAddress(CANFD_T * psCanfd,uint32_t u32Idx)686 static uint32_t CANFD_GetTxBufferElementAddress(CANFD_T *psCanfd, uint32_t u32Idx)
687 {
688 uint32_t u32Size = 0;
689 u32Size = (psCanfd->TXESC & CANFD_TXESC_TBDS_Msk) >> CANFD_TXESC_TBDS_Pos;
690
691 if (u32Size < 5U)
692 {
693 u32Size += 4U;
694 }
695 else
696 {
697 u32Size = u32Size * 4U - 10U;
698 }
699
700 return (psCanfd->TXBC & CANFD_TXBC_TBSA_Msk) + u32Idx * u32Size * 4U;
701 }
702
703
704 /**
705 * @brief Enables CAN FD interrupts according to provided mask .
706 *
707 * @param[in] psCanfd The pointer of the specified CAN FD module.
708 * @param[in] u32IntLine0 The Interrupt Line 0 type select.
709 * @param[in] u32IntLine1 The Interrupt Line 1 type select.
710 * - \ref CANFD_IE_ARAE_Msk : Access to Reserved Address Interrupt
711 * - \ref CANFD_IE_PEDE_Msk : Protocol Error in Data Phase Interrupt
712 * - \ref CANFD_IE_PEAE_Msk : Protocol Error in Arbitration Phase Interrupt
713 * - \ref CANFD_IE_WDIE_Msk : Watchdog Interrupt
714 * - \ref CANFD_IE_BOE_Msk : Bus_Off Status Interrupt
715 * - \ref CANFD_IE_EWE_Msk : Warning Status Interrupt
716 * - \ref CANFD_IE_EPE_Msk : Error Passive Interrupt
717 * - \ref CANFD_IE_ELOE_Msk : Error Logging Overflow Interrupt
718 * - \ref CANFD_IE_BEUE_Msk : Bit Error Uncorrected Interrupt
719 * - \ref CANFD_IE_BECE_Msk : Bit Error Corrected Interrupt
720 * - \ref CANFD_IE_DRXE_Msk : Message stored to Dedicated Rx Buffer Interrupt
721 * - \ref CANFD_IE_TOOE_Msk : Timeout Occurred Interrupt
722 * - \ref CANFD_IE_MRAFE_Msk : Message RAM Access Failure Interrupt
723 * - \ref CANFD_IE_TSWE_Msk : Timestamp Wraparound Interrupt
724 * - \ref CANFD_IE_TEFLE_Msk : Tx Event FIFO Event Lost Interrupt
725 * - \ref CANFD_IE_TEFFE_Msk : Tx Event FIFO Full Interrupt
726 * - \ref CANFD_IE_TEFWE_Msk : Tx Event FIFO Watermark Reached Interrupt
727 * - \ref CANFD_IE_TEFNE_Msk : Tx Event FIFO New Entry Interrupt
728 * - \ref CANFD_IE_TFEE_Msk : Tx FIFO Empty Interrupt
729 * - \ref CANFD_IE_TCFE_Msk : Transmission Cancellation Finished Interrupt
730 * - \ref CANFD_IE_TCE_Msk : Transmission Completed Interrupt
731 * - \ref CANFD_IE_HPME_Msk : High Priority Message Interrupt
732 * - \ref CANFD_IE_RF1LE_Msk : Rx FIFO 1 Message Lost Interrupt
733 * - \ref CANFD_IE_RF1FE_Msk : Rx FIFO 1 Full Interrupt
734 * - \ref CANFD_IE_RF1WE_Msk : Rx FIFO 1 Watermark Reached Interrupt
735 * - \ref CANFD_IE_RF1NE_Msk : Rx FIFO 1 New Message Interrupt
736 * - \ref CANFD_IE_RF0LE_Msk : Rx FIFO 0 Message Lost Interrupt
737 * - \ref CANFD_IE_RF0FE_Msk : Rx FIFO 0 Full Interrupt
738 * - \ref CANFD_IE_RF0WE_Msk : Rx FIFO 0 Watermark Reached Interrupt
739 * - \ref CANFD_IE_RF0NE_Msk : Rx FIFO 0 New Message Interrupt
740 *
741 * @param[in] u32TXBTIE Enable Tx Buffer Transmission 0-31 Interrupt.
742 * @param[in] u32TXBCIE Enable Tx Buffer Cancellation Finished 0-31 Interrupt.
743 * @return None.
744 *
745 * @details This macro enable specified CAN FD interrupt.
746 */
CANFD_EnableInt(CANFD_T * psCanfd,uint32_t u32IntLine0,uint32_t u32IntLine1,uint32_t u32TXBTIE,uint32_t u32TXBCIE)747 void CANFD_EnableInt(CANFD_T *psCanfd, uint32_t u32IntLine0, uint32_t u32IntLine1, uint32_t u32TXBTIE, uint32_t u32TXBCIE)
748 {
749
750 if (u32IntLine0 != 0)
751 {
752 /*Setting the CANFD0_IRQ0 Interrupt*/
753 psCanfd->IE |= u32IntLine0;
754 /* Enable CAN FD specified interrupt */
755 psCanfd->ILE |= CANFD_ILE_EINT0_Msk;
756 }
757
758 if (u32IntLine1 != 0)
759 {
760 /*Setting the CANFD0_IRQ1 Interrupt*/
761 psCanfd->ILS |= u32IntLine1;
762 /* Enable CAN FD specified interrupt */
763 psCanfd->ILE |= CANFD_ILE_EINT1_Msk;
764 }
765
766 /*Setting the Tx Buffer Transmission Interrupt Enable*/
767 psCanfd->TXBTIE |= u32TXBTIE;
768
769 /*Tx Buffer Cancellation Finished Interrupt Enable*/
770 psCanfd->TXBCIE |= u32TXBCIE;
771 }
772
773
774 /**
775 * @brief Disables CAN FD interrupts according to provided mask .
776 *
777 * @param[in] psCanfd The pointer of the specified CAN FD module.
778 * @param[in] u32IntLine0 The Interrupt Line 0 type select.
779 * @param[in] u32IntLine1 The Interrupt Line 1 type select.
780 * - \ref CANFD_IE_ARAE_Msk : Access to Reserved Address Interrupt
781 * - \ref CANFD_IE_PEDE_Msk : Protocol Error in Data Phase Interrupt
782 * - \ref CANFD_IE_PEAE_Msk : Protocol Error in Arbitration Phase Interrupt
783 * - \ref CANFD_IE_WDIE_Msk : Watchdog Interrupt
784 * - \ref CANFD_IE_BOE_Msk : Bus_Off Status Interrupt
785 * - \ref CANFD_IE_EWE_Msk : Warning Status Interrupt
786 * - \ref CANFD_IE_EPE_Msk : Error Passive Interrupt
787 * - \ref CANFD_IE_ELOE_Msk : Error Logging Overflow Interrupt
788 * - \ref CANFD_IE_BEUE_Msk : Bit Error Uncorrected Interrupt
789 * - \ref CANFD_IE_BECE_Msk : Bit Error Corrected Interrupt
790 * - \ref CANFD_IE_DRXE_Msk : Message stored to Dedicated Rx Buffer Interrupt
791 * - \ref CANFD_IE_TOOE_Msk : Timeout Occurred Interrupt
792 * - \ref CANFD_IE_MRAFE_Msk : Message RAM Access Failure Interrupt
793 * - \ref CANFD_IE_TSWE_Msk : Timestamp Wraparound Interrupt
794 * - \ref CANFD_IE_TEFLE_Msk : Tx Event FIFO Event Lost Interrupt
795 * - \ref CANFD_IE_TEFFE_Msk : Tx Event FIFO Full Interrupt
796 * - \ref CANFD_IE_TEFWE_Msk : Tx Event FIFO Watermark Reached Interrupt
797 * - \ref CANFD_IE_TEFNE_Msk : Tx Event FIFO New Entry Interrupt
798 * - \ref CANFD_IE_TFEE_Msk : Tx FIFO Empty Interrupt
799 * - \ref CANFD_IE_TCFE_Msk : Transmission Cancellation Finished Interrupt
800 * - \ref CANFD_IE_TCE_Msk : Transmission Completed Interrupt
801 * - \ref CANFD_IE_HPME_Msk : High Priority Message Interrupt
802 * - \ref CANFD_IE_RF1LE_Msk : Rx FIFO 1 Message Lost Interrupt
803 * - \ref CANFD_IE_RF1FE_Msk : Rx FIFO 1 Full Interrupt
804 * - \ref CANFD_IE_RF1WE_Msk : Rx FIFO 1 Watermark Reached Interrupt
805 * - \ref CANFD_IE_RF1NE_Msk : Rx FIFO 1 New Message Interrupt
806 * - \ref CANFD_IE_RF0LE_Msk : Rx FIFO 0 Message Lost Interrupt
807 * - \ref CANFD_IE_RF0FE_Msk : Rx FIFO 0 Full Interrupt
808 * - \ref CANFD_IE_RF0WE_Msk : Rx FIFO 0 Watermark Reached Interrupt
809 * - \ref CANFD_IE_RF0NE_Msk : Rx FIFO 0 New Message Interrupt
810 *
811 * @param[in] u32TXBTIE Disable Tx Buffer Transmission 0-31 Interrupt.
812 * @param[in] u32TXBCIE Disable Tx Buffer Cancellation Finished 0-31 Interrupt.
813 * @return None.
814 *
815 * @details This macro disable specified CAN FD interrupt.
816 */
CANFD_DisableInt(CANFD_T * psCanfd,uint32_t u32IntLine0,uint32_t u32IntLine1,uint32_t u32TXBTIE,uint32_t u32TXBCIE)817 void CANFD_DisableInt(CANFD_T *psCanfd, uint32_t u32IntLine0, uint32_t u32IntLine1, uint32_t u32TXBTIE, uint32_t u32TXBCIE)
818 {
819 if (u32IntLine0 != 0)
820 {
821 /*Clear the CANFD0_IRQ0 Interrupt*/
822 psCanfd->IE &= ~u32IntLine0;
823 /* Disable CAN FD specified interrupt */
824 psCanfd->ILE &= ~CANFD_ILE_EINT0_Msk;
825 }
826
827 if (u32IntLine1 != 0)
828 {
829 /*Clear the CANFD0_IRQ1 Interrupt*/
830 psCanfd->ILS &= ~u32IntLine1;
831 /* Disable CAN FD specified interrupt */
832 psCanfd->ILE &= ~CANFD_ILE_EINT1_Msk;
833 }
834
835 /*Setting the Tx Buffer Transmission Interrupt Disable*/
836 psCanfd->TXBTIE &= ~u32TXBTIE;
837
838 /*Tx Buffer Cancellation Finished Interrupt Disable*/
839 psCanfd->TXBCIE &= ~u32TXBCIE;
840 }
841
842
843 /**
844 * @brief Copy Tx Message to TX buffer and Request transmission.
845 *
846 * @param[in] psCanfd The pointer to CAN FD module base address.
847 * @param[in] u32TxBufIdx The Message Buffer index.
848 * @param[in] psTxMsg Message to be copied.
849 *
850 * @return number of tx requests set: 0= Tx Message Buffer is currently in use.
851 * 1= Write Tx Message Buffer Successfully.
852 *
853 * @details Copy Tx Message to FIFO/Queue TX buffer and Request transmission.
854 */
CANFD_TransmitTxMsg(CANFD_T * psCanfd,uint32_t u32TxBufIdx,CANFD_FD_MSG_T * psTxMsg)855 uint32_t CANFD_TransmitTxMsg(CANFD_T *psCanfd, uint32_t u32TxBufIdx, CANFD_FD_MSG_T *psTxMsg)
856 {
857 uint32_t u32Success = 0;
858 uint32_t u32TimeOutCnt = CANFD_TIMEOUT;
859
860 /* write the message to the message buffer */
861 u32Success = CANFD_TransmitDMsg(psCanfd, u32TxBufIdx, psTxMsg);
862
863 if (u32Success == 1)
864 {
865 /* wait for completion */
866 while (!(psCanfd->TXBRP & (1UL << u32TxBufIdx)))
867 {
868 if (--u32TimeOutCnt == 0)
869 {
870 u32Success = 0;
871 break;
872 }
873
874 }
875 }
876
877 return u32Success;
878 }
879
880
881 /**
882 * @brief Writes a Tx Message to Transmit Message Buffer.
883 *
884 * @param[in] psCanfd The pointer of the specified CAN FD module.
885 * @param[in] u32TxBufIdx The Message Buffer index.
886 * @param[in] psTxMsg Pointer to CAN FD message frame to be sent.
887 *
888 * @return 1 Write Tx Message Buffer Successfully.
889 * 0 Tx Message Buffer is currently in use.
890 *
891 * @details This function writes a CANFD Message to the specified Transmit Message Buffer
892 * and changes the Message Buffer state to start CANFD Message transmit. After
893 * that the function returns immediately.
894 */
CANFD_TransmitDMsg(CANFD_T * psCanfd,uint32_t u32TxBufIdx,CANFD_FD_MSG_T * psTxMsg)895 uint32_t CANFD_TransmitDMsg(CANFD_T *psCanfd, uint32_t u32TxBufIdx, CANFD_FD_MSG_T *psTxMsg)
896 {
897 CANFD_BUF_T *psTxBuffer;
898 uint32_t u32Idx = 0, u32Success = 1;
899 uint32_t u32TimeOutCnt = CANFD_TIMEOUT;
900
901 if (u32TxBufIdx >= CANFD_MAX_TX_BUF_ELEMS) return 0;
902
903 /* transmission is pending in this message buffer */
904 if (psCanfd->TXBRP & (1UL << u32TxBufIdx)) return 0;
905
906 /*Get the TX Buffer Start Address in the RAM*/
907 psTxBuffer = (CANFD_BUF_T *)(CANFD_SRAM_BASE_ADDR(psCanfd) + (psCanfd->TXBC & 0xFFFF) + (u32TxBufIdx * sizeof(CANFD_BUF_T)));
908
909 if (psTxMsg->eIdType == eCANFD_XID)
910 {
911 psTxBuffer->u32Id = TX_BUFFER_T0_ELEM_XTD_Msk | (psTxMsg->u32Id & 0x1FFFFFFF);
912 }
913 else
914 {
915 psTxBuffer->u32Id = (psTxMsg->u32Id & 0x7FF) << 18;
916 }
917
918 if (psTxMsg->eFrmType == eCANFD_REMOTE_FRM) psTxBuffer->u32Id |= TX_BUFFER_T0_ELEM_RTR_Msk;
919
920 psTxBuffer->u32Config = (CANFD_EncodeDLC(psTxMsg->u32DLC) << 16);
921
922 if (psTxMsg->bFDFormat) psTxBuffer->u32Config |= TX_BUFFER_T1_ELEM_FDF_Msk;
923
924 if (psTxMsg->bBitRateSwitch) psTxBuffer->u32Config |= TX_BUFFER_T1_ELEM_BSR_Msk;
925
926
927 for (u32Idx = 0; u32Idx < (psTxMsg->u32DLC + (4 - 1)) / 4; u32Idx++)
928 {
929 psTxBuffer->au32Data[u32Idx] = psTxMsg->au32Data[u32Idx];
930 }
931
932 while (CANFD_GET_COMMUNICATION_STATE(psCanfd) != eCANFD_IDLE)
933 {
934 if (--u32TimeOutCnt == 0) return 0;
935 }
936
937 psCanfd->TXBAR = (1 << u32TxBufIdx);
938
939 return u32Success;
940 }
941
942
943 /**
944 * @brief Global Filter Configuration (GFC).
945 *
946 * @param[in] psCanfd The pointer to CAN FD module base address.
947 * @param[in] eNMStdFrm Accept/Reject Non-Matching Standard(11-bits) Frames.
948 * @param[in] eEMExtFrm Accept/Reject Non-Matching Extended(29-bits) Frames.
949 * @param[in] u32RejRmtStdFrm Reject/Filter Remote Standard Frames.
950 * @param[in] u32RejRmtExtFrm Reject/Filter Remote Extended Frames.
951 *
952 * @return None.
953 *
954 * @details Global Filter Configuration.
955 */
CANFD_SetGFC(CANFD_T * psCanfd,E_CANFD_ACC_NON_MATCH_FRM eNMStdFrm,E_CANFD_ACC_NON_MATCH_FRM eEMExtFrm,uint32_t u32RejRmtStdFrm,uint32_t u32RejRmtExtFrm)956 void CANFD_SetGFC(CANFD_T *psCanfd, E_CANFD_ACC_NON_MATCH_FRM eNMStdFrm, E_CANFD_ACC_NON_MATCH_FRM eEMExtFrm, uint32_t u32RejRmtStdFrm, uint32_t u32RejRmtExtFrm)
957 {
958 psCanfd->GFC &= (CANFD_GFC_RRFS_Msk | CANFD_GFC_RRFE_Msk);
959 psCanfd->GFC = (eNMStdFrm << CANFD_GFC_ANFS_Pos) | (eEMExtFrm << CANFD_GFC_ANFE_Pos)
960 | (u32RejRmtStdFrm << CANFD_GFC_RRFS_Pos) | (u32RejRmtExtFrm << CANFD_GFC_RRFE_Pos);
961 }
962
963
964 /**
965 * @brief Rx FIFO Configuration for RX_FIFO_0 and RX_FIFO_1.
966 *
967 * @param[in] psCanfd The pointer to CAN FD module base address.
968 * @param[in] u32RxFifoNum 0: RX FIFO_0, 1: RX_FIFO_1.
969 * @param[in] psRamConfig Rx FIFO Size in number of configuration ram address.
970 * @param[in] psElemSize Rx FIFO Size in number of Rx FIFO elements (element number (max. = 64)).
971 * @param[in] u32FifoWM Watermark in number of Rx FIFO elements
972 * @param[in] eFifoSize Maximum data field size that should be stored in this Rx FIFO
973 * (configure BYTE64 if you are unsure, as this is the largest data field allowed in CAN FD)
974 *
975 * @return None.
976 *
977 * @details Rx FIFO Configuration for RX_FIFO_0 and RX_FIFO_1.
978 */
CANFD_InitRxFifo(CANFD_T * psCanfd,uint32_t u32RxFifoNum,CANFD_RAM_PART_T * psRamConfig,CANFD_ELEM_SIZE_T * psElemSize,uint32_t u32FifoWM,E_CANFD_DATA_FIELD_SIZE eFifoSize)979 static void CANFD_InitRxFifo(CANFD_T *psCanfd, uint32_t u32RxFifoNum, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize, uint32_t u32FifoWM, E_CANFD_DATA_FIELD_SIZE eFifoSize)
980 {
981 uint32_t u32Address;
982 uint32_t u32Size;
983
984 /* ignore if index is too high */
985 if (u32RxFifoNum > CANFD_NUM_RX_FIFOS)return;
986
987 /* ignore if index is too high */
988 if (psElemSize->u32RxFifo0 > CANFD_MAX_RX_FIFO0_ELEMS) return;
989
990 /* ignore if index is too high */
991 if (psElemSize->u32RxFifo1 > CANFD_MAX_RX_FIFO1_ELEMS) return;
992
993 switch (u32RxFifoNum)
994 {
995 case 0:
996 if (psElemSize->u32RxFifo0)
997 {
998 /* set size of Rx FIFO 0, set offset, blocking mode */
999 psCanfd->RXF0C = (psRamConfig->u32RXF0C_F0SA) | (psElemSize->u32RxFifo0 << CANFD_RXF0C_F0S_Pos)
1000 | (u32FifoWM << CANFD_RXF0C_F0WM_Pos);
1001 psCanfd->RXESC = (psCanfd->RXESC & (~CANFD_RXESC_F0DS_Msk)) | (eFifoSize << CANFD_RXESC_F0DS_Pos);
1002
1003 /*Get the RX FIFO 0 Start Address in the RAM*/
1004 u32Address = CANFD_SRAM_BASE_ADDR(psCanfd) + (psRamConfig->u32RXF0C_F0SA & CANFD_RXF0C_F0SA_Msk);
1005 u32Size = eFifoSize;
1006
1007 if (u32Size < 5U)
1008 {
1009 u32Size += 4U;
1010 }
1011 else
1012 {
1013 u32Size = u32Size * 4U - 10U;
1014 }
1015
1016 /*Clear the RX FIFO 0 Memory*/
1017 memset((uint32_t *)(u32Address), 0x00, (u32Size * 4 * psElemSize->u32RxFifo0));
1018 }
1019 else
1020 {
1021 psCanfd->RXF0C = 0;
1022 }
1023
1024 break;
1025
1026 case 1:
1027 if (psElemSize->u32RxFifo1)
1028 {
1029 /* set size of Rx FIFO 1, set offset, blocking mode */
1030 psCanfd->RXF1C = (psRamConfig->u32RXF1C_F1SA) | (psElemSize->u32RxFifo1 << CANFD_RXF1C_F1S_Pos)
1031 | (u32FifoWM << CANFD_RXF1C_F1WM_Pos);
1032 psCanfd->RXESC = (psCanfd->RXESC & (~CANFD_RXESC_F1DS_Msk)) | (eFifoSize << CANFD_RXESC_F1DS_Pos);
1033
1034 /*Get the RX FIFO 1 Start Address in the RAM*/
1035 u32Address = CANFD_SRAM_BASE_ADDR(psCanfd) + (psRamConfig->u32RXF1C_F1SA & CANFD_RXF1C_F1SA_Msk);
1036
1037 u32Size = eFifoSize;
1038
1039 if (u32Size < 5U)
1040 {
1041 u32Size += 4U;
1042 }
1043 else
1044 {
1045 u32Size = u32Size * 4U - 10U;
1046 }
1047
1048 /*Clear the RX FIFO 0 Memory*/
1049 memset((uint32_t *)(u32Address), 0x00, (u32Size * 4 * psElemSize->u32RxFifo1));
1050 }
1051 else
1052 {
1053 psCanfd->RXF1C = 0;
1054 }
1055
1056 break;
1057 }
1058 }
1059
1060
1061 /**
1062 * @brief Function configures the data structures used by a dedicated Rx Buffer.
1063 *
1064 * @param[in] psCanfd The pointer to CAN FD module base address.
1065 * @param[in] psRamConfig Tx buffer configuration ram address.
1066 * @param[in] psElemSize Tx buffer configuration element size.
1067 * @param[in] eTxBufSize Maximum data field size that should be stored in a dedicated Tx Buffer
1068 * (configure BYTE64 if you are unsure, as this is the largest data field allowed in CAN FD)largest data field allowed in CAN FD)
1069 *
1070 * @return None.
1071 *
1072 * @details Function configures the data structures used by a dedicated Rx Buffer.
1073 */
CANFD_InitTxDBuf(CANFD_T * psCanfd,CANFD_RAM_PART_T * psRamConfig,CANFD_ELEM_SIZE_T * psElemSize,E_CANFD_DATA_FIELD_SIZE eTxBufSize)1074 static void CANFD_InitTxDBuf(CANFD_T *psCanfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize, E_CANFD_DATA_FIELD_SIZE eTxBufSize)
1075 {
1076 uint32_t u32Address;
1077 uint32_t u32Size;
1078
1079 /*Setting the Tx Buffer Start Address*/
1080 psCanfd->TXBC = ((psElemSize->u32TxBuf & 0x3F) << CANFD_TXBC_NDTB_Pos) | (psRamConfig->u32TXBC_TBSA & CANFD_TXBC_TBSA_Msk);
1081
1082 /*Get the TX Buffer Start Address in the RAM*/
1083 u32Address = CANFD_SRAM_BASE_ADDR(psCanfd) + (psRamConfig->u32TXBC_TBSA & CANFD_TXBC_TBSA_Msk);
1084
1085 /*Setting the Tx Buffer Data Field Size*/
1086 psCanfd->TXESC = (psCanfd->TXESC & (~CANFD_TXESC_TBDS_Msk)) | (eTxBufSize << CANFD_TXESC_TBDS_Pos);
1087
1088 /*Get the Buffer Data Field Size*/
1089 u32Size = eTxBufSize;
1090
1091 if (u32Size < 5U)
1092 {
1093 u32Size += 4U;
1094 }
1095 else
1096 {
1097 u32Size = u32Size * 4U - 10U;
1098 }
1099
1100 /*Clear the TX Buffer Memory*/
1101 memset((uint32_t *)(u32Address), 0x00, (u32Size * 4 * psElemSize->u32TxBuf));
1102 }
1103
1104
1105 /**
1106 * @brief Function configures the data structures used by a dedicated Rx Buffer.
1107 *
1108 * @param[in] psCanfd The pointer to CAN FD module base address.
1109 * @param[in] psRamConfig Rx buffer configuration ram address.
1110 * @param[in] psElemSize Rx buffer configuration element size.
1111 * @param[in] eRxBufSize Maximum data field size that should be stored in a dedicated Rx Buffer
1112 * (configure BYTE64 if you are unsure, as this is the largest data field allowed in CAN FD)largest data field allowed in CAN FD)
1113 *
1114 * @return None.
1115 *
1116 * @details Function configures the data structures used by a dedicated Rx Buffer.
1117 */
CANFD_InitRxDBuf(CANFD_T * psCanfd,CANFD_RAM_PART_T * psRamConfig,CANFD_ELEM_SIZE_T * psElemSize,E_CANFD_DATA_FIELD_SIZE eRxBufSize)1118 static void CANFD_InitRxDBuf(CANFD_T *psCanfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize, E_CANFD_DATA_FIELD_SIZE eRxBufSize)
1119 {
1120 uint32_t u32Address;
1121 uint32_t u32Size;
1122
1123 /*Setting the Rx Buffer Start Address*/
1124 psCanfd->RXBC = (psRamConfig->u32RXBC_RBSA & CANFD_RXBC_RBSA_Msk);
1125
1126 /*Get the RX Buffer Start Address in the RAM*/
1127 u32Address = CANFD_SRAM_BASE_ADDR(psCanfd) + (psRamConfig->u32RXBC_RBSA & CANFD_RXBC_RBSA_Msk);
1128
1129 /*Setting the Rx Buffer Data Field Size*/
1130 psCanfd->RXESC = (psCanfd->RXESC & (~CANFD_RXESC_RBDS_Msk)) | (eRxBufSize << CANFD_RXESC_RBDS_Pos);
1131 /*Get the Buffer Data Field Size*/
1132 u32Size = eRxBufSize;
1133
1134 if (u32Size < 5U)
1135 {
1136 u32Size += 4U;
1137 }
1138 else
1139 {
1140 u32Size = u32Size * 4U - 10U;
1141 }
1142
1143 /*Clear the RX Buffer Memory*/
1144 memset((uint32_t *)(u32Address), 0x00, (u32Size * 4 * psElemSize->u32RxBuf));
1145 }
1146
1147
1148 /**
1149 * @brief Configures the register SIDFC for the 11-bit Standard Message ID Filter elements.
1150 *
1151 * @param[in] psCanfd The pointer to CAN FD module base address.
1152 * @param[in] psRamConfig Standard ID filter configuration ram address
1153 * @param[in] psElemSize Standard ID filter configuration element size
1154 *
1155 * @return None.
1156 *
1157 * @details Function configures the data structures used by a dedicated Rx Buffer.
1158 */
CANFD_ConfigSIDFC(CANFD_T * psCanfd,CANFD_RAM_PART_T * psRamConfig,CANFD_ELEM_SIZE_T * psElemSize)1159 static void CANFD_ConfigSIDFC(CANFD_T *psCanfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize)
1160 {
1161 uint32_t u32Address;
1162
1163 /*Setting the Filter List Standard Start Address and List Size */
1164 psCanfd->SIDFC = ((psElemSize->u32SIDFC & 0xFF) << CANFD_SIDFC_LSS_Pos) | (psRamConfig->u32SIDFC_FLSSA & CANFD_SIDFC_FLSSA_Msk);
1165
1166 /*Get the Filter List Standard Start Address in the RAM*/
1167 u32Address = CANFD_SRAM_BASE_ADDR(psCanfd) + (psRamConfig->u32SIDFC_FLSSA & CANFD_SIDFC_FLSSA_Msk);
1168
1169 /*Clear the Filter List Memory*/
1170 memset((uint32_t *)(u32Address), 0x00, (psElemSize->u32SIDFC * sizeof(CANFD_STD_FILTER_T)));
1171 }
1172
1173
1174 /**
1175 * @brief Configures the register XIDFC for the 29-bit Extended Message ID Filter elements.
1176 *
1177 * @param[in] psCanfd The pointer to CAN FD module base address.
1178 * @param[in] psRamConfig Extended ID filter configuration ram address
1179 * @param[in] psElemSize Extended ID filter configuration element size
1180 *
1181 * @return None.
1182 *
1183 * @details Configures the register XIDFC for the 29-bit Extended Message ID Filter elements.
1184 */
CANFD_ConfigXIDFC(CANFD_T * psCanfd,CANFD_RAM_PART_T * psRamConfig,CANFD_ELEM_SIZE_T * psElemSize)1185 static void CANFD_ConfigXIDFC(CANFD_T *psCanfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize)
1186 {
1187 uint32_t u32Address;
1188
1189 /*Setting the Filter List Extended Start Address and List Size */
1190 psCanfd->XIDFC = ((psElemSize->u32XIDFC & 0xFF) << CANFD_XIDFC_LSE_Pos) | (psRamConfig->u32XIDFC_FLESA & CANFD_XIDFC_FLESA_Msk);
1191
1192 /*Get the Filter List Standard Start Address in the RAM*/
1193 u32Address = CANFD_SRAM_BASE_ADDR(psCanfd) + (psRamConfig->u32XIDFC_FLESA & CANFD_XIDFC_FLESA_Msk);
1194
1195 /*Clear the Filter List Memory*/
1196 memset((uint32_t *)(u32Address), 0x00, (psElemSize->u32XIDFC * sizeof(CANFD_EXT_FILTER_T)));
1197 }
1198
1199
1200 /**
1201 * @brief Writes a 11-bit Standard ID filter element in the Message RAM.
1202 *
1203 * @param[in] psCanfd The pointer to CAN FD module base address.
1204 * @param[in] u32FltrIdx Index at which the filter element should be written in the '11-bit Filter' section of Message RAM
1205 * @param[in] u32Filter Rx Individual filter value.
1206 *
1207 * @return None.
1208 *
1209 * @details Writes a 11-bit Standard ID filter element in the Message RAM.
1210 */
CANFD_SetSIDFltr(CANFD_T * psCanfd,uint32_t u32FltrIdx,uint32_t u32Filter)1211 void CANFD_SetSIDFltr(CANFD_T *psCanfd, uint32_t u32FltrIdx, uint32_t u32Filter)
1212 {
1213 CANFD_STD_FILTER_T *psFilter;
1214
1215 /* ignore if index is too high */
1216 if (u32FltrIdx >= CANFD_MAX_11_BIT_FTR_ELEMS) return;
1217
1218 /*Get the Filter List Configuration Address in the RAM*/
1219 psFilter = (CANFD_STD_FILTER_T *)(CANFD_SRAM_BASE_ADDR(psCanfd) + (psCanfd->SIDFC & CANFD_SIDFC_FLSSA_Msk) + (u32FltrIdx * sizeof(CANFD_STD_FILTER_T)));
1220
1221 /*Wirted the Standard ID filter element to RAM */
1222 psFilter->VALUE = u32Filter;
1223 }
1224
1225
1226 /**
1227 * @brief Writes a 29-bit extended id filter element in the Message RAM.
1228 * Size of an Extended Id filter element is 2 words. So 2 words are written into the Message RAM for each filter element
1229 *
1230 * @param[in] psCanfd The pointer to CAN FD module base address.
1231 * @param[in] u32FltrIdx Index at which the filter element should be written in the '29-bit Filter' section of Message RAM.
1232 * @param[in] u32FilterLow Rx Individual filter low value.
1233 * @param[in] u32FilterHigh Rx Individual filter high value.
1234 *
1235 * @return None.
1236 *
1237 * @details Writes a 29-bit extended id filter element in the Message RAM.
1238 */
CANFD_SetXIDFltr(CANFD_T * psCanfd,uint32_t u32FltrIdx,uint32_t u32FilterLow,uint32_t u32FilterHigh)1239 void CANFD_SetXIDFltr(CANFD_T *psCanfd, uint32_t u32FltrIdx, uint32_t u32FilterLow, uint32_t u32FilterHigh)
1240 {
1241 CANFD_EXT_FILTER_T *psFilter;
1242
1243 /* ignore if index is too high */
1244 if (u32FltrIdx >= CANFD_MAX_29_BIT_FTR_ELEMS) return;
1245
1246 /*Get the Filter List Configuration Address on RAM*/
1247 psFilter = (CANFD_EXT_FILTER_T *)(CANFD_SRAM_BASE_ADDR(psCanfd) + (psCanfd->XIDFC & CANFD_XIDFC_FLESA_Msk) + (u32FltrIdx * sizeof(CANFD_EXT_FILTER_T)));
1248
1249 /*Wirted the Extended ID filter element to RAM */
1250 psFilter->LOWVALUE = u32FilterLow;
1251 psFilter->HIGHVALUE = u32FilterHigh;
1252 }
1253
1254
1255 /**
1256 * @brief Reads a CAN FD Message from Receive Message Buffer.
1257 *
1258 * @param[in] psCanfd The pointer of the specified CAN FD module.
1259 * @param[in] u8MbIdx The CANFD Message Buffer index.
1260 * @param[in] psMsgBuf Pointer to CAN FD message frame structure for reception.
1261 *
1262 * @return 1:Rx Message Buffer is full and has been read successfully.
1263 * 0:Rx Message Buffer is empty.
1264 *
1265 * @details This function reads a CAN message from a specified Receive Message Buffer.
1266 * The function fills a receive CAN message frame structure with just received data
1267 * and activates the Message Buffer again.The function returns immediately.
1268 */
CANFD_ReadRxBufMsg(CANFD_T * psCanfd,uint8_t u8MbIdx,CANFD_FD_MSG_T * psMsgBuf)1269 uint32_t CANFD_ReadRxBufMsg(CANFD_T *psCanfd, uint8_t u8MbIdx, CANFD_FD_MSG_T *psMsgBuf)
1270 {
1271 CANFD_BUF_T *psRxBuffer;
1272 uint32_t u32Success = 0;
1273 uint32_t newData = 0;
1274
1275 if (u8MbIdx < CANFD_MAX_RX_BUF_ELEMS)
1276 {
1277 if (u8MbIdx < 32)
1278 newData = (psCanfd->NDAT1 >> u8MbIdx) & 1;
1279 else
1280 newData = (psCanfd->NDAT2 >> (u8MbIdx - 32)) & 1;
1281
1282 /* new message is waiting to be read */
1283 if (newData)
1284 {
1285 /* get memory location of rx buffer */
1286 psRxBuffer = (CANFD_BUF_T *)(CANFD_SRAM_BASE_ADDR(psCanfd) + (psCanfd->RXBC & 0xFFFF) + (u8MbIdx * sizeof(CANFD_BUF_T)));
1287
1288 /* read the message */
1289 CANFD_CopyDBufToMsgBuf(psRxBuffer, psMsgBuf);
1290
1291 /* clear 'new data' flag */
1292 if (u8MbIdx < 32)
1293 psCanfd->NDAT1 |= (1UL << u8MbIdx);
1294 else
1295 psCanfd->NDAT2 |= (1UL << (u8MbIdx - 32));
1296
1297 u32Success = 1;
1298 }
1299 }
1300
1301 return u32Success;
1302 }
1303
1304
1305 /**
1306 * @brief Reads a CAN FD Message from Rx FIFO.
1307 *
1308 * @param[in] psCanfd The pointer of the specified CANFD module.
1309 * @param[in] u8FifoIdx Number of the FIFO, 0 or 1.
1310 * @param[in] psMsgBuf Pointer to CANFD message frame structure for reception.
1311 *
1312 * @return 1 Read Message from Rx FIFO successfully.
1313 * 2 Rx FIFO is already overflowed and has been read successfully
1314 * 0 Rx FIFO is not enabled.
1315 *
1316 * @details This function reads a CAN message from the CANFD build-in Rx FIFO.
1317 */
CANFD_ReadRxFifoMsg(CANFD_T * psCanfd,uint8_t u8FifoIdx,CANFD_FD_MSG_T * psMsgBuf)1318 uint32_t CANFD_ReadRxFifoMsg(CANFD_T *psCanfd, uint8_t u8FifoIdx, CANFD_FD_MSG_T *psMsgBuf)
1319 {
1320 CANFD_BUF_T *pRxBuffer;
1321 uint8_t GetIndex;
1322 uint32_t u32Success = 0;
1323 __I uint32_t *pRXFS;
1324 __IO uint32_t *pRXFC, *pRXFA;
1325 uint8_t msgLostBit;
1326
1327 /* check for valid FIFO number */
1328 if (u8FifoIdx < CANFD_NUM_RX_FIFOS)
1329 {
1330 if (u8FifoIdx == 0)
1331 {
1332 pRXFS = &(psCanfd->RXF0S);
1333 pRXFC = &(psCanfd->RXF0C);
1334 pRXFA = &(psCanfd->RXF0A);
1335 msgLostBit = 3;
1336 }
1337 else
1338 {
1339 pRXFS = &(psCanfd->RXF1S);
1340 pRXFC = &(psCanfd->RXF1C);
1341 pRXFA = &(psCanfd->RXF1A);
1342 msgLostBit = 7;
1343 }
1344
1345 /* if FIFO is not empty */
1346 if ((*pRXFS & 0x7F) > 0)
1347 {
1348 GetIndex = (uint8_t)((*pRXFS >> 8) & 0x3F);
1349 pRxBuffer = (CANFD_BUF_T *)(CANFD_SRAM_BASE_ADDR(psCanfd) + (*pRXFC & 0xFFFF) + (GetIndex * sizeof(CANFD_BUF_T)));
1350
1351 CANFD_CopyRxFifoToMsgBuf(pRxBuffer, psMsgBuf);
1352
1353 /* we got the message */
1354 *pRXFA = GetIndex;
1355
1356 /* check for overflow */
1357 if (*pRXFS & CANFD_RXFS_RFL)
1358 {
1359 /* clear overflow flag */
1360 psCanfd->IR = (1UL << msgLostBit);
1361 u32Success = 2;
1362 }
1363 else
1364 {
1365 u32Success = 1;
1366 }
1367 }
1368 }
1369
1370 return u32Success;
1371 }
1372
1373
1374 /**
1375 * @brief Copies a message from a dedicated Rx buffer into a message buffer.
1376 *
1377 * @param[in] psRxBuf Buffer to read from.
1378 * @param[in] psMsgBuf Location to store read message.
1379 *
1380 * @return None.
1381 *
1382 * @details Copies a message from a dedicated Rx buffer into a message buffer.
1383 */
CANFD_CopyDBufToMsgBuf(CANFD_BUF_T * psRxBuf,CANFD_FD_MSG_T * psMsgBuf)1384 void CANFD_CopyDBufToMsgBuf(CANFD_BUF_T *psRxBuf, CANFD_FD_MSG_T *psMsgBuf)
1385 {
1386 uint32_t u32Idx;
1387
1388 if (psRxBuf->u32Id & RX_BUFFER_AND_FIFO_R0_ELEM_ESI_Msk)
1389 psMsgBuf->bErrStaInd = TRUE;
1390 else
1391 psMsgBuf->bErrStaInd = FALSE;
1392
1393 /* if 29-bit ID */
1394 if (psRxBuf->u32Id & RX_BUFFER_AND_FIFO_R0_ELEM_XTD_Msk)
1395 {
1396 psMsgBuf->u32Id = (psRxBuf->u32Id & RX_BUFFER_AND_FIFO_R0_ELEM_ID_Msk);
1397 psMsgBuf->eIdType = eCANFD_XID;
1398 }
1399 /* if 11-bit ID */
1400 else
1401 {
1402 psMsgBuf->u32Id = (psRxBuf->u32Id >> 18) & 0x7FF;
1403 psMsgBuf->eIdType = eCANFD_SID;
1404 }
1405
1406 if (psRxBuf->u32Id & RX_BUFFER_AND_FIFO_R0_ELEM_RTR_Msk)
1407 psMsgBuf->eFrmType = eCANFD_REMOTE_FRM;
1408 else
1409 psMsgBuf->eFrmType = eCANFD_DATA_FRM;
1410
1411
1412 if (psRxBuf->u32Config & RX_BUFFER_AND_FIFO_R1_ELEM_FDF_Msk)
1413 psMsgBuf->bFDFormat = TRUE;
1414 else
1415 psMsgBuf->bFDFormat = FALSE;
1416
1417 if (psRxBuf->u32Config & RX_BUFFER_AND_FIFO_R1_ELEM_BSR_Msk)
1418 psMsgBuf->bBitRateSwitch = TRUE;
1419 else
1420 psMsgBuf->bBitRateSwitch = FALSE;
1421
1422 psMsgBuf->u32DLC = CANFD_DecodeDLC((psRxBuf->u32Config & RX_BUFFER_AND_FIFO_R1_ELEM_DLC_Msk) >> RX_BUFFER_AND_FIFO_R1_ELEM_DLC_Pos);
1423
1424 for (u32Idx = 0 ; u32Idx < psMsgBuf->u32DLC ; u32Idx++)
1425 {
1426 psMsgBuf->au8Data[u32Idx] = psRxBuf->au8Data[u32Idx];
1427 }
1428 }
1429
1430
1431 /**
1432 * @brief Get Rx FIFO water level.
1433 *
1434 * @param[in] psCanfd The pointer to CANFD module base address.
1435 * @param[in] u32RxFifoNum 0: RX FIFO_0, 1: RX_FIFO_1
1436 *
1437 * @return Rx FIFO water level.
1438 *
1439 * @details Get Rx FIFO water level.
1440 */
CANFD_GetRxFifoWaterLvl(CANFD_T * psCanfd,uint32_t u32RxFifoNum)1441 uint32_t CANFD_GetRxFifoWaterLvl(CANFD_T *psCanfd, uint32_t u32RxFifoNum)
1442 {
1443 uint32_t u32WaterLevel = 0;
1444
1445 if (u32RxFifoNum == 0)
1446 u32WaterLevel = ((psCanfd->RXF0C & CANFD_RXF0C_F0WM_Msk) >> CANFD_RXF0C_F0WM_Pos);
1447 else
1448 u32WaterLevel = ((psCanfd->RXF1C & CANFD_RXF1C_F1WM_Msk) >> CANFD_RXF1C_F1WM_Pos);
1449
1450 return u32WaterLevel;
1451 }
1452
1453
1454 /**
1455 * @brief Copies messages from FIFO into a message buffert.
1456 *
1457 * @param[in] psRxBuf Buffer to read from.
1458 * @param[in] psMsgBuf Location to store read message.
1459 *
1460 * @return None.
1461 *
1462 * @details Copies messages from FIFO into a message buffert.
1463 */
CANFD_CopyRxFifoToMsgBuf(CANFD_BUF_T * psRxBuf,CANFD_FD_MSG_T * psMsgBuf)1464 void CANFD_CopyRxFifoToMsgBuf(CANFD_BUF_T *psRxBuf, CANFD_FD_MSG_T *psMsgBuf)
1465 {
1466 /*Copies a message from a dedicated Rx FIFO into a message buffer*/
1467 CANFD_CopyDBufToMsgBuf(psRxBuf, psMsgBuf);
1468 }
1469
1470
1471 /**
1472 * @brief Cancel a Tx buffer transmission request.
1473 *
1474 * @param[in] psCanfd The pointer to CANFD module base address.
1475 * @param[in] u32TxBufIdx Tx buffer index number
1476 *
1477 * @return None.
1478 *
1479 * @details Cancel a Tx buffer transmission request.
1480 */
CANFD_TxBufCancelReq(CANFD_T * psCanfd,uint32_t u32TxBufIdx)1481 void CANFD_TxBufCancelReq(CANFD_T *psCanfd, uint32_t u32TxBufIdx)
1482 {
1483 psCanfd->TXBCR |= (0x1ul << u32TxBufIdx);
1484 }
1485
1486
1487 /**
1488 * @brief Checks if a Tx buffer cancellation request has been finished or not.
1489 *
1490 * @param[in] psCanfd The pointer to CAN FD module base address.
1491 * @param[in] u32TxBufIdx Tx buffer index number
1492 *
1493 * @return 0: cancellation finished.
1494 * 1: cancellation fail
1495 *
1496 * @details Checks if a Tx buffer cancellation request has been finished or not.
1497 */
CANFD_IsTxBufCancelFin(CANFD_T * psCanfd,uint32_t u32TxBufIdx)1498 uint32_t CANFD_IsTxBufCancelFin(CANFD_T *psCanfd, uint32_t u32TxBufIdx)
1499 {
1500 /* wait for completion */
1501 return ((psCanfd->TXBCR & (0x1ul << u32TxBufIdx)) >> u32TxBufIdx);
1502 }
1503
1504
1505 /**
1506 * @brief Checks if a Tx buffer transmission has occurred or not.
1507 *
1508 * @param[in] psCanfd The pointer to CAN FD module base address.
1509 * @param[in] u32TxBufIdx Tx buffer index number
1510 *
1511 * @return 0: No transmission occurred.
1512 * 1: Transmission occurred
1513 *
1514 * @details Checks if a Tx buffer transmission has occurred or not.
1515 */
CANFD_IsTxBufTransmitOccur(CANFD_T * psCanfd,uint32_t u32TxBufIdx)1516 uint32_t CANFD_IsTxBufTransmitOccur(CANFD_T *psCanfd, uint32_t u32TxBufIdx)
1517 {
1518 return ((psCanfd->TXBTO & (0x1ul << u32TxBufIdx)) >> u32TxBufIdx);
1519 }
1520
1521
1522 /**
1523 * @brief Init Tx event fifo
1524 *
1525 * @param[in] psCanfd The pointer to CAN FD module base address.
1526 * @param[in] psRamConfig Tx Event Fifo configuration ram address.
1527 * @param[in] psElemSize Tx Event Fifo configuration element size
1528 * @param[in] u32FifoWaterLvl FIFO water level
1529 *
1530 * @return None.
1531 *
1532 * @details Init Tx event fifo.
1533 */
CANFD_InitTxEvntFifo(CANFD_T * psCanfd,CANFD_RAM_PART_T * psRamConfig,CANFD_ELEM_SIZE_T * psElemSize,uint32_t u32FifoWaterLvl)1534 static void CANFD_InitTxEvntFifo(CANFD_T *psCanfd, CANFD_RAM_PART_T *psRamConfig, CANFD_ELEM_SIZE_T *psElemSize, uint32_t u32FifoWaterLvl)
1535 {
1536 /* Set TX Event FIFO element size,watermark,start address. */
1537 psCanfd->TXEFC = (u32FifoWaterLvl << CANFD_TXEFC_EFWM_Pos) | (psElemSize->u32TxEventFifo << CANFD_TXEFC_EFS_Pos)
1538 | (psRamConfig->u32TXEFC_EFSA & CANFD_TXEFC_EFSA_Msk);
1539 }
1540
1541
1542 /**
1543 * @brief Get Tx event fifo water level
1544 *
1545 * @param[in] psCanfd The pointer to CANFD module base address.
1546 *
1547 * @return Tx event fifo water level.
1548 *
1549 * @details Get Tx event fifo water level.
1550 */
CANFD_GetTxEvntFifoWaterLvl(CANFD_T * psCanfd)1551 uint32_t CANFD_GetTxEvntFifoWaterLvl(CANFD_T *psCanfd)
1552 {
1553 return ((psCanfd->TXEFC & CANFD_TXEFC_EFWM_Msk) >> CANFD_TXEFC_EFWM_Pos);
1554 }
1555
1556
1557 /**
1558 * @brief Copy Event Elements from TX Event FIFO to user buffer
1559 *
1560 * @param[in] psCanfd The pointer to CAN FD module base address.
1561 * @param[in] u32TxEvntNum Tx Event FIFO number
1562 * @param[in] psTxEvntElem Tx Event Message struct
1563 *
1564 * @return None.
1565 *
1566 * @details Copy all Event Elements from TX Event FIFO to the Software Event List .
1567 */
CANFD_CopyTxEvntFifoToUsrBuf(CANFD_T * psCanfd,uint32_t u32TxEvntNum,CANFD_TX_EVNT_ELEM_T * psTxEvntElem)1568 void CANFD_CopyTxEvntFifoToUsrBuf(CANFD_T *psCanfd, uint32_t u32TxEvntNum, CANFD_TX_EVNT_ELEM_T *psTxEvntElem)
1569 {
1570 uint32_t *pu32TxEvnt;
1571 /*Get the Tx Event FIFO Address*/
1572 pu32TxEvnt = (uint32_t *)CANFD_GetTxBufferElementAddress(psCanfd, u32TxEvntNum);
1573
1574 /*Get the Error State Indicator*/
1575 if ((pu32TxEvnt[0] & TX_FIFO_E0_EVENT_ESI_Msk) > 0)
1576 psTxEvntElem->bErrStaInd = TRUE; //Transmitting node is error passive
1577 else
1578 psTxEvntElem->bErrStaInd = FALSE;//Transmitting node is error active
1579
1580 /*Get the Tx FIFO Identifier type and Identifier*/
1581
1582 if ((pu32TxEvnt[0] & TX_FIFO_E0_EVENT_XTD_Msk) > 0)
1583 {
1584 psTxEvntElem->eIdType = eCANFD_XID;
1585 psTxEvntElem->u32Id = (pu32TxEvnt[0] & TX_FIFO_E0_EVENT_ID_Msk);// Extended ID
1586 }
1587 else
1588 {
1589 psTxEvntElem->eIdType = eCANFD_SID;
1590 psTxEvntElem->u32Id = (pu32TxEvnt[0] & TX_FIFO_E0_EVENT_ID_Msk) >> 18;// Standard ID
1591 }
1592
1593 /*Get the Frame type*/
1594 if ((pu32TxEvnt[0] & TX_FIFO_E0_EVENT_RTR_Msk) > 0)
1595 psTxEvntElem->bRemote = TRUE; //Remote frame
1596 else
1597 psTxEvntElem->bRemote = FALSE; //Data frame
1598
1599 /*Get the FD Format type*/
1600 if ((pu32TxEvnt[0] & TX_FIFO_E1_EVENT_FDF_Msk) > 0)
1601 psTxEvntElem->bFDFormat = TRUE; //CAN FD frame format
1602 else
1603 psTxEvntElem->bFDFormat = FALSE; //Classical CAN frame format
1604
1605 /*Get the Bit Rate Switch type*/
1606 if ((pu32TxEvnt[0] & TX_FIFO_E1_EVENT_BRS_Msk) > 0)
1607 psTxEvntElem->bBitRateSwitch = TRUE; //Frame transmitted with bit rate switching
1608 else
1609 psTxEvntElem->bBitRateSwitch = FALSE; //Frame transmitted without bit rate switching
1610
1611 /*Get the Tx FIFO Data Length */
1612 psTxEvntElem->u32DLC = CANFD_DecodeDLC((uint8_t)((pu32TxEvnt[1] & TX_FIFO_E1_EVENT_DLC_Msk) >> TX_FIFO_E1_EVENT_DLC_Pos));
1613
1614 /*Get the Tx FIFO Timestamp */
1615 psTxEvntElem->u32TxTs = (((pu32TxEvnt[1] & TX_FIFO_E1A_EVENT_TXTS_Msk) >> TX_FIFO_E1A_EVENT_TXTS_Pos));
1616 /*Get the Tx FIFO Message marker */
1617 psTxEvntElem->u32MsgMarker = (((pu32TxEvnt[1] & TX_FIFO_E1_EVENT_MM_Msk) >> TX_FIFO_E1_EVENT_MM_Pos));
1618 }
1619
1620
1621 /**
1622 * @brief Get CAN FD interrupts status.
1623 *
1624 * @param[in] psCanfd The pointer of the specified CAN FD module.
1625 * @param[in] u32IntTypeFlag Interrupt Type Flag, should be
1626 * - \ref CANFD_IR_ARA_Msk : Access to Reserved Address interrupt Indicator
1627 * - \ref CANFD_IR_PED_Msk : Protocol Error in Data Phase interrupt Indicator
1628 * - \ref CANFD_IR_PEA_Msk : Protocol Error in Arbitration Phase interrupt Indicator
1629 * - \ref CANFD_IR_WDI_Msk : Watchdog interrupt Indicator
1630 * - \ref CANFD_IR_BO_Msk : Bus_Off Status interrupt Indicator
1631 * - \ref CANFD_IR_EW_Msk : Warning Status interrupt Indicator
1632 * - \ref CANFD_IR_EP_Msk : Error Passive interrupt Indicator
1633 * - \ref CANFD_IR_ELO_Msk : Error Logging Overflow interrupt Indicator
1634 * - \ref CANFD_IR_DRX_Msk : Message stored to Dedicated Rx Buffer interrupt Indicator
1635 * - \ref CANFD_IR_TOO_Msk : Timeout Occurred interrupt Indicator
1636 * - \ref CANFD_IR_MRAF_Msk : Message RAM Access Failure interrupt Indicator
1637 * - \ref CANFD_IR_TSW_Msk : Timestamp Wraparound interrupt Indicator
1638 * - \ref CANFD_IR_TEFL_Msk : Tx Event FIFO Event Lost interrupt Indicator
1639 * - \ref CANFD_IR_TEFF_Msk : Tx Event FIFO Full Indicator
1640 * - \ref CANFD_IR_TEFW_Msk : Tx Event FIFO Watermark Reached Interrupt Indicator
1641 * - \ref CANFD_IR_TEFN_Msk : Tx Event FIFO New Entry Interrupt Indicator
1642 * - \ref CANFD_IR_TFE_Msk : Tx FIFO Empty Interrupt Indicator
1643 * - \ref CANFD_IR_TCF_Msk : Transmission Cancellation Finished Interrupt Indicator
1644 * - \ref CANFD_IR_TC_Msk : Transmission Completed interrupt Indicator
1645 * - \ref CANFD_IR_HPM_Msk : High Priority Message Interrupt Indicator
1646 * - \ref CANFD_IR_RF1L_Msk : Rx FIFO 1 Message Lost Interrupt Indicator
1647 * - \ref CANFD_IR_RF1F_Msk : Rx FIFO 1 Full Interrupt Indicator
1648 * - \ref CANFD_IR_RF1W_Msk : Rx FIFO 1 Watermark Reached Interrupt Indicator
1649 * - \ref CANFD_IR_RF1N_Msk : Rx FIFO 1 New Message Interrupt Indicator
1650 * - \ref CANFD_IR_RF0L_Msk : Rx FIFO 0 Message Lost Interrupt Indicator
1651 * - \ref CANFD_IR_RF0F_Msk : Rx FIFO 0 Full Interrupt Indicator
1652 * - \ref CANFD_IR_RF0W_Msk : Rx FIFO 0 Watermark Reached Interrupt Indicator
1653 * - \ref CANFD_IR_RF0N_Msk : Rx FIFO 0 New Message Interrupt Indicator
1654 *
1655 * @return None.
1656 *
1657 * @details This function gets all CAN FD interrupt status flags.
1658 */
CANFD_GetStatusFlag(CANFD_T * psCanfd,uint32_t u32IntTypeFlag)1659 uint32_t CANFD_GetStatusFlag(CANFD_T *psCanfd, uint32_t u32IntTypeFlag)
1660 {
1661 return (psCanfd->IR & u32IntTypeFlag);
1662 }
1663
1664
1665 /**
1666 * @brief Clears the CAN FD module interrupt flags
1667 *
1668 * @param[in] psCanfd The pointer of the specified CANFD module.
1669 * @param[in] u32InterruptFlag The specified interrupt of CAN FD module
1670 * - \ref CANFD_IR_ARA_Msk : Access to Reserved Address interrupt Indicator
1671 * - \ref CANFD_IR_PED_Msk : Protocol Error in Data Phase interrupt Indicator
1672 * - \ref CANFD_IR_PEA_Msk : Protocol Error in Arbitration Phase interrupt Indicator
1673 * - \ref CANFD_IR_WDI_Msk : Watchdog interrupt Indicator
1674 * - \ref CANFD_IR_BO_Msk : Bus_Off Status interrupt Indicator
1675 * - \ref CANFD_IR_EW_Msk : Warning Status interrupt Indicator
1676 * - \ref CANFD_IR_EP_Msk : Error Passive interrupt Indicator
1677 * - \ref CANFD_IR_ELO_Msk : Error Logging Overflow interrupt Indicator
1678 * - \ref CANFD_IR_DRX_Msk : Message stored to Dedicated Rx Buffer interrupt Indicator
1679 * - \ref CANFD_IR_TOO_Msk : Timeout Occurred interrupt Indicator
1680 * - \ref CANFD_IR_MRAF_Msk : Message RAM Access Failure interrupt Indicator
1681 * - \ref CANFD_IR_TSW_Msk : Timestamp Wraparound interrupt Indicator
1682 * - \ref CANFD_IR_TEFL_Msk : Tx Event FIFO Event Lost interrupt Indicator
1683 * - \ref CANFD_IR_TEFF_Msk : Tx Event FIFO Full Indicator
1684 * - \ref CANFD_IR_TEFW_Msk : Tx Event FIFO Watermark Reached Interrupt Indicator
1685 * - \ref CANFD_IR_TEFN_Msk : Tx Event FIFO New Entry Interrupt Indicator
1686 * - \ref CANFD_IR_TFE_Msk : Tx FIFO Empty Interrupt Indicator
1687 * - \ref CANFD_IR_TCF_Msk : Transmission Cancellation Finished Interrupt Indicator
1688 * - \ref CANFD_IR_TC_Msk : Transmission Completed interrupt Indicator
1689 * - \ref CANFD_IR_HPM_Msk : High Priority Message Interrupt Indicator
1690 * - \ref CANFD_IR_RF1L_Msk : Rx FIFO 1 Message Lost Interrupt Indicator
1691 * - \ref CANFD_IR_RF1F_Msk : Rx FIFO 1 Full Interrupt Indicator
1692 * - \ref CANFD_IR_RF1W_Msk : Rx FIFO 1 Watermark Reached Interrupt Indicator
1693 * - \ref CANFD_IR_RF1N_Msk : Rx FIFO 1 New Message Interrupt Indicator
1694 * - \ref CANFD_IR_RF0L_Msk : Rx FIFO 0 Message Lost Interrupt Indicator
1695 * - \ref CANFD_IR_RF0F_Msk : Rx FIFO 0 Full Interrupt Indicator
1696 * - \ref CANFD_IR_RF0W_Msk : Rx FIFO 0 Watermark Reached Interrupt Indicator
1697 * - \ref CANFD_IR_RF0N_Msk : Rx FIFO 0 New Message Interrupt Indicator
1698 *
1699 * @return None.
1700 *
1701 * @details This function clears CAN FD interrupt status flags.
1702 */
CANFD_ClearStatusFlag(CANFD_T * psCanfd,uint32_t u32InterruptFlag)1703 void CANFD_ClearStatusFlag(CANFD_T *psCanfd, uint32_t u32InterruptFlag)
1704 {
1705 /* Write 1 to clear status flag. */
1706 psCanfd->IR |= u32InterruptFlag;
1707 }
1708
1709
1710 /**
1711 * @brief Gets the CAN FD Bus Error Counter value.
1712 *
1713 * @param[in] psCanfd The pointer of the specified CAN FD module.
1714 * @param[in] pu8TxErrBuf TxErrBuf Buffer to store Tx Error Counter value.
1715 * @param[in] pu8RxErrBuf RxErrBuf Buffer to store Rx Error Counter value.
1716 *
1717 * @return None.
1718 *
1719 * @details This function gets the CAN FD Bus Error Counter value for both Tx and Rx direction.
1720 * These values may be needed in the upper layer error handling.
1721 */
CANFD_GetBusErrCount(CANFD_T * psCanfd,uint8_t * pu8TxErrBuf,uint8_t * pu8RxErrBuf)1722 void CANFD_GetBusErrCount(CANFD_T *psCanfd, uint8_t *pu8TxErrBuf, uint8_t *pu8RxErrBuf)
1723 {
1724 if (pu8TxErrBuf)
1725 {
1726 *pu8TxErrBuf = (uint8_t)((psCanfd->ECR >> CANFD_ECR_TEC_Pos) & CANFD_ECR_TEC_Msk);
1727 }
1728
1729 if (pu8RxErrBuf)
1730 {
1731 *pu8RxErrBuf = (uint8_t)((psCanfd->ECR >> CANFD_ECR_REC_Pos) & CANFD_ECR_REC_Msk);
1732 }
1733 }
1734
1735
1736 /**
1737 * @brief CAN FD Run to the Normal Operation.
1738 *
1739 * @param[in] psCanfd The pointer of the specified CAN FD module.
1740 * @param[in] u8Enable TxErrBuf Buffer to store Tx Error Counter value.
1741 *
1742 * @retval CANFD_OK CANFD operation OK.
1743 * @retval CANFD_ERR_TIMEOUT CANFD operation abort due to timeout error.
1744 *
1745 * @details This function gets the CAN FD Bus Error Counter value for both Tx and Rx direction.
1746 * These values may be needed in the upper layer error handling.
1747 */
CANFD_RunToNormal(CANFD_T * psCanfd,uint8_t u8Enable)1748 int32_t CANFD_RunToNormal(CANFD_T *psCanfd, uint8_t u8Enable)
1749 {
1750 uint32_t u32TimeOutCnt = CANFD_TIMEOUT;
1751
1752 if (u8Enable)
1753 {
1754 /* start operation */
1755 psCanfd->CCCR &= ~(CANFD_CCCR_CCE_Msk | CANFD_CCCR_INIT_Msk);
1756
1757 while (psCanfd->CCCR & CANFD_CCCR_INIT_Msk)
1758 {
1759 if (--u32TimeOutCnt == 0) return CANFD_ERR_TIMEOUT;
1760 }
1761 }
1762 else
1763 {
1764 /* init mode */
1765 psCanfd->CCCR |= CANFD_CCCR_INIT_Msk;
1766
1767 while (!(psCanfd->CCCR & CANFD_CCCR_INIT_Msk))
1768 {
1769 if (--u32TimeOutCnt == 0) return CANFD_ERR_TIMEOUT;
1770 }
1771 }
1772
1773 return CANFD_OK;
1774 }
1775
1776
1777
1778 /*@}*/ /* end of group CANFD_EXPORTED_FUNCTIONS */
1779
1780 /*@}*/ /* end of group CANFD_Driver */
1781
1782 /*@}*/ /* end of group Standard_Driver */
1783