1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_flexcan.h"
10 
11 /*
12  * $Coverage Justification Reference$
13  *
14  * $Justification flexcan_c_ref_1$
15  * The FLEXCAN_ReadRxFifo() return fail only when Rx FIFO is diabled. But in IRQ handler, will first check whether the
16  * FIFO is enabled, and only call FLEXCAN_ReadRxFifo if the FIFO is enabled. So to cover this line/branch, need to
17  * interrupt the current execution by a high priority IRQ after confirming that the FIFO is enabled, and disabled the
18  * FIFO in the high priority interrupt. It is difficult to simulate this situation in unit test, so add Justification.
19  *
20  */
21 
22 /*******************************************************************************
23  * Definitions
24  ******************************************************************************/
25 
26 /* Component ID definition, used by tools. */
27 #ifndef FSL_COMPONENT_ID
28 #define FSL_COMPONENT_ID "platform.drivers.flexcan"
29 #endif
30 
31 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032)
32 #define RXINTERMISSION (CAN_DBG1_CFSM(0x2f))
33 #define TXINTERMISSION (CAN_DBG1_CFSM(0x14))
34 #define BUSIDLE        (CAN_DBG1_CFSM(0x02))
35 #define CBN_VALUE3     (CAN_DBG1_CBN(0x03))
36 #define DELAY_BUSIDLE  (200)
37 #endif
38 
39 /* According to CiA doc 1301 v1.0.0, specified data/nominal phase sample point postion for CAN FD at 80 MHz. */
40 #define IDEAL_DATA_SP_1  (800U)
41 #define IDEAL_DATA_SP_2  (750U)
42 #define IDEAL_DATA_SP_3  (700U)
43 #define IDEAL_DATA_SP_4  (625U)
44 #define IDEAL_NOMINAL_SP (800U)
45 
46 /* According to CiA doc 301 v4.2.0 and previous version. */
47 #define IDEAL_SP_LOW  (750U)
48 #define IDEAL_SP_MID  (800U)
49 #define IDEAL_SP_HIGH (875U)
50 
51 #define IDEAL_SP_FACTOR (1000U)
52 
53 /* Define the max value of bit timing segments when use different timing register. */
54 #define MAX_PROPSEG           (CAN_CTRL1_PROPSEG_MASK >> CAN_CTRL1_PROPSEG_SHIFT)
55 #define MAX_PSEG1             (CAN_CTRL1_PSEG1_MASK >> CAN_CTRL1_PSEG1_SHIFT)
56 #define MAX_PSEG2             (CAN_CTRL1_PSEG2_MASK >> CAN_CTRL1_PSEG2_SHIFT)
57 #define MAX_RJW               (CAN_CTRL1_RJW_MASK >> CAN_CTRL1_RJW_SHIFT)
58 #define MAX_PRESDIV           (CAN_CTRL1_PRESDIV_MASK >> CAN_CTRL1_PRESDIV_SHIFT)
59 #define CTRL1_MAX_TIME_QUANTA (1U + MAX_PROPSEG + 1U + MAX_PSEG1 + 1U + MAX_PSEG2 + 1U)
60 #define CTRL1_MIN_TIME_QUANTA (8U)
61 
62 #define MAX_EPROPSEG        (CAN_CBT_EPROPSEG_MASK >> CAN_CBT_EPROPSEG_SHIFT)
63 #define MAX_EPSEG1          (CAN_CBT_EPSEG1_MASK >> CAN_CBT_EPSEG1_SHIFT)
64 #define MAX_EPSEG2          (CAN_CBT_EPSEG2_MASK >> CAN_CBT_EPSEG2_SHIFT)
65 #define MAX_ERJW            (CAN_CBT_ERJW_MASK >> CAN_CBT_ERJW_SHIFT)
66 #define MAX_EPRESDIV        (CAN_CBT_EPRESDIV_MASK >> CAN_CBT_EPRESDIV_SHIFT)
67 #define CBT_MAX_TIME_QUANTA (1U + MAX_EPROPSEG + 1U + MAX_EPSEG1 + 1U + MAX_EPSEG2 + 1U)
68 #define CBT_MIN_TIME_QUANTA (8U)
69 
70 #define MAX_FPROPSEG          (CAN_FDCBT_FPROPSEG_MASK >> CAN_FDCBT_FPROPSEG_SHIFT)
71 #define MAX_FPSEG1            (CAN_FDCBT_FPSEG1_MASK >> CAN_FDCBT_FPSEG1_SHIFT)
72 #define MAX_FPSEG2            (CAN_FDCBT_FPSEG2_MASK >> CAN_FDCBT_FPSEG2_SHIFT)
73 #define MAX_FRJW              (CAN_FDCBT_FRJW_MASK >> CAN_FDCBT_FRJW_SHIFT)
74 #define MAX_FPRESDIV          (CAN_FDCBT_FPRESDIV_MASK >> CAN_FDCBT_FPRESDIV_SHIFT)
75 #define FDCBT_MAX_TIME_QUANTA (1U + MAX_FPROPSEG + 0U + MAX_FPSEG1 + 1U + MAX_FPSEG2 + 1U)
76 #define FDCBT_MIN_TIME_QUANTA (5U)
77 
78 #define MAX_TDCOFF ((uint32_t)CAN_FDCTRL_TDCOFF_MASK >> CAN_FDCTRL_TDCOFF_SHIFT)
79 
80 #define MAX_NTSEG1            (CAN_ENCBT_NTSEG1_MASK >> CAN_ENCBT_NTSEG1_SHIFT)
81 #define MAX_NTSEG2            (CAN_ENCBT_NTSEG2_MASK >> CAN_ENCBT_NTSEG2_SHIFT)
82 #define MAX_NRJW              (CAN_ENCBT_NRJW_MASK >> CAN_ENCBT_NRJW_SHIFT)
83 #define MAX_ENPRESDIV         (CAN_EPRS_ENPRESDIV_MASK >> CAN_EPRS_ENPRESDIV_SHIFT)
84 #define ENCBT_MAX_TIME_QUANTA (1U + MAX_NTSEG1 + 1U + MAX_NTSEG2 + 1U)
85 #define ENCBT_MIN_TIME_QUANTA (8U)
86 
87 #define MAX_DTSEG1            (CAN_EDCBT_DTSEG1_MASK >> CAN_EDCBT_DTSEG1_SHIFT)
88 #define MAX_DTSEG2            (CAN_EDCBT_DTSEG2_MASK >> CAN_EDCBT_DTSEG2_SHIFT)
89 #define MAX_DRJW              (CAN_EDCBT_DRJW_MASK >> CAN_EDCBT_DRJW_SHIFT)
90 #define MAX_EDPRESDIV         (CAN_EPRS_EDPRESDIV_MASK >> CAN_EPRS_EDPRESDIV_SHIFT)
91 #define EDCBT_MAX_TIME_QUANTA (1U + MAX_DTSEG1 + 1U + MAX_DTSEG2 + 1U)
92 #define EDCBT_MIN_TIME_QUANTA (5U)
93 
94 #define MAX_ETDCOFF ((uint32_t)CAN_ETDC_ETDCOFF_MASK >> CAN_ETDC_ETDCOFF_SHIFT)
95 
96 /* TSEG1 corresponds to the sum of xPROPSEG and xPSEG1, TSEG2 corresponds to the xPSEG2 value. */
97 #define MIN_TIME_SEGMENT1 (2U)
98 #define MIN_TIME_SEGMENT2 (2U)
99 
100 /* Define maximum CAN and CAN FD bit rate supported by FLEXCAN. */
101 #if (defined(FSL_FEATURE_FLEXCAN_MAX_CANFD_BITRATE))
102 #define MAX_CANFD_BITRATE ((uint32_t)(FSL_FEATURE_FLEXCAN_MAX_CANFD_BITRATE))
103 #else
104 #define MAX_CANFD_BITRATE (8000000U)
105 #endif
106 #define MAX_CAN_BITRATE   (1000000U)
107 
108 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595)
109 #define CAN_ESR1_FLTCONF_BUSOFF CAN_ESR1_FLTCONF(2U)
110 #endif
111 
112 /* Define the range of memory that needs to be initialized when the device has memory error detection feature. */
113 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
114 #define CAN_INIT_RXFIR         ((uintptr_t)base + 0x4Cu)
115 #define CAN_INIT_MEMORY_BASE_1 (uint32_t *)((uintptr_t)base + (uintptr_t)FSL_FEATURE_FLEXCAN_INIT_MEMORY_BASE_1)
116 #define CAN_INIT_MEMORY_SIZE_1 FSL_FEATURE_FLEXCAN_INIT_MEMORY_SIZE_1
117 #define CAN_INIT_MEMORY_BASE_2 (uint32_t *)((uintptr_t)base + (uintptr_t)FSL_FEATURE_FLEXCAN_INIT_MEMORY_BASE_2)
118 #define CAN_INIT_MEMORY_SIZE_2 FSL_FEATURE_FLEXCAN_INIT_MEMORY_SIZE_2
119 #endif
120 
121 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
122 #ifndef CAN_CLOCK_CHECK_NO_AFFECTS
123 /* If no define such MACRO, it mean that the CAN in current device have no clock affect issue. */
124 #define CAN_CLOCK_CHECK_NO_AFFECTS (true)
125 #endif /* CAN_CLOCK_CHECK_NO_AFFECTS */
126 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
127 
128 #if defined(FLEXCAN_RSTS)
129 #define FLEXCAN_RESETS_ARRAY FLEXCAN_RSTS
130 #elif defined(FLEXCAN_RSTS_N)
131 #define FLEXCAN_RESETS_ARRAY FLEXCAN_RSTS_N
132 #endif
133 
134 /*! @brief FlexCAN Internal State. */
135 enum _flexcan_state
136 {
137     kFLEXCAN_StateIdle     = 0x0, /*!< MB/RxFIFO idle.*/
138     kFLEXCAN_StateRxData   = 0x1, /*!< MB receiving.*/
139     kFLEXCAN_StateRxRemote = 0x2, /*!< MB receiving remote reply.*/
140     kFLEXCAN_StateTxData   = 0x3, /*!< MB transmitting.*/
141     kFLEXCAN_StateTxRemote = 0x4, /*!< MB transmitting remote request.*/
142     kFLEXCAN_StateRxFifo   = 0x5, /*!< RxFIFO receiving.*/
143 };
144 
145 /*! @brief FlexCAN message buffer CODE for Rx buffers. */
146 enum _flexcan_mb_code_rx
147 {
148     kFLEXCAN_RxMbInactive = 0x0, /*!< MB is not active.*/
149     kFLEXCAN_RxMbFull     = 0x2, /*!< MB is full.*/
150     kFLEXCAN_RxMbEmpty    = 0x4, /*!< MB is active and empty.*/
151     kFLEXCAN_RxMbOverrun  = 0x6, /*!< MB is overwritten into a full buffer.*/
152     kFLEXCAN_RxMbBusy     = 0x8, /*!< FlexCAN is updating the contents of the MB, The CPU must not access the MB.*/
153     kFLEXCAN_RxMbRanswer  = 0xA, /*!< A frame was configured to recognize a Remote Request Frame and transmit a
154                                       Response Frame in return.*/
155     kFLEXCAN_RxMbNotUsed = 0xF,  /*!< Not used.*/
156 };
157 
158 /*! @brief FlexCAN message buffer CODE FOR Tx buffers. */
159 enum _flexcan_mb_code_tx
160 {
161     kFLEXCAN_TxMbInactive     = 0x8, /*!< MB is not active.*/
162     kFLEXCAN_TxMbAbort        = 0x9, /*!< MB is aborted.*/
163     kFLEXCAN_TxMbDataOrRemote = 0xC, /*!< MB is a TX Data Frame(when MB RTR = 0) or MB is a TX Remote Request
164                                           Frame (when MB RTR = 1).*/
165     kFLEXCAN_TxMbTanswer = 0xE,      /*!< MB is a TX Response Request Frame from an incoming Remote Request Frame.*/
166     kFLEXCAN_TxMbNotUsed = 0xF,      /*!< Not used.*/
167 };
168 
169 /* Typedef for interrupt handler. */
170 typedef void (*flexcan_isr_t)(CAN_Type *base, flexcan_handle_t *handle);
171 
172 /*******************************************************************************
173  * Prototypes
174  ******************************************************************************/
175 
176 #if !defined(NDEBUG)
177 /*!
178  * @brief Check if Message Buffer is occupied by Rx FIFO.
179  *
180  * This function check if Message Buffer is occupied by Rx FIFO.
181  *
182  * @param base FlexCAN peripheral base address.
183  * @param mbIdx The FlexCAN Message Buffer index.
184  * @return TRUE if the index MB is occupied by Rx FIFO, FALSE if the index MB not occupied by Rx FIFO.
185  */
186 static bool FLEXCAN_IsMbOccupied(CAN_Type *base, uint8_t mbIdx);
187 #endif
188 
189 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
190      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
191 /*!
192  * @brief Get the first valid Message buffer ID of give FlexCAN instance.
193  *
194  * This function is a helper function for Errata 5641 workaround.
195  *
196  * @param base FlexCAN peripheral base address.
197  * @return The first valid Message Buffer Number.
198  */
199 static uint8_t FLEXCAN_GetFirstValidMb(CAN_Type *base);
200 #endif
201 
202 /*!
203  * @brief Reset the FlexCAN Instance.
204  *
205  * Restores the FlexCAN module to reset state, notice that this function
206  * will set all the registers to reset state so the FlexCAN module can not work
207  * after calling this API.
208  *
209  * @param base FlexCAN peripheral base address.
210  */
211 static void FLEXCAN_Reset(CAN_Type *base);
212 
213 /*!
214  * @brief Calculates the segment values for a single bit time for classical CAN.
215  *
216  * This function use to calculates the Classical CAN segment values which will be set in CTRL1/CBT/ENCBT register.
217  *
218  * @param base FlexCAN peripheral base address.
219  * @param tqNum Number of time quantas per bit, range in 8 ~ 25 when use CTRL1, range in 8 ~ 129 when use CBT, range in
220  *             8 ~ 385 when use ENCBT. param pTimingConfig Pointer to the FlexCAN timing configuration structure.
221  */
222 static void FLEXCAN_GetSegments(CAN_Type *base,
223                                 uint32_t bitRate,
224                                 uint32_t tqNum,
225                                 flexcan_timing_config_t *pTimingConfig);
226 
227 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
228 /*!
229  * @brief Get Mailbox offset number by dword.
230  *
231  * This function gets the offset number of the specified mailbox.
232  * Mailbox is not consecutive between memory regions when payload is not 8 bytes
233  * so need to calculate the specified mailbox address.
234  * For example, in the first memory region, MB[0].CS address is 0x4002_4080. For 32 bytes
235  * payload frame, the second mailbox is ((1/12)*512 + 1%12*40)/4 = 10, meaning 10 dword
236  * after the 0x4002_4080, which is actually the address of mailbox MB[1].CS.
237  *
238  * @param base FlexCAN peripheral base address.
239  * @param mbIdx Mailbox index.
240  */
241 static uint32_t FLEXCAN_GetFDMailboxOffset(CAN_Type *base, uint8_t mbIdx);
242 
243 /*!
244  * @brief Calculates the segment values for a single bit time for CAN FD data phase.
245  *
246  * This function use to calculates the CAN FD data phase segment values which will be set in CFDCBT/EDCBT
247  * register.
248  *
249  * @param bitRateFD Data phase bit rate
250  * @param tqNum Number of time quanta per bit
251  * @param pTimingConfig Pointer to the FlexCAN timing configuration structure.
252  */
253 static void FLEXCAN_FDGetSegments(uint32_t bitRateFD, uint32_t tqNum, flexcan_timing_config_t *pTimingConfig);
254 
255 /*!
256  * @brief Calculates the improved timing values by specific bit rate for CAN FD nominal phase.
257  *
258  * This function use to calculates the CAN FD nominal phase timing values according to the given nominal phase bit rate.
259  * The Calculated timing values will be set in CBT/ENCBT registers. The calculation is based on the recommendation of
260  * the CiA 1301 v1.0.0 document.
261  *
262  * @param bitRate  The CAN FD nominal phase speed in bps defined by user, should be less than or equal to 1Mbps.
263  * @param sourceClock_Hz The Source clock frequency in Hz.
264  * @param pTimingConfig Pointer to the FlexCAN timing configuration structure.
265  *
266  * @return TRUE if timing configuration found, FALSE if failed to find configuration.
267  */
268 static bool FLEXCAN_CalculateImprovedNominalTimingValues(uint32_t bitRate,
269                                                          uint32_t sourceClock_Hz,
270                                                          flexcan_timing_config_t *pTimingConfig);
271 
272 #endif
273 
274 /*!
275  * @brief Check unhandle interrupt events
276  *
277  * @param base FlexCAN peripheral base address.
278  * @return TRUE if unhandled interrupt action exist, FALSE if no unhandlered interrupt action exist.
279  */
280 static bool FLEXCAN_CheckUnhandleInterruptEvents(CAN_Type *base);
281 
282 /*!
283  * @brief Sub Handler Data Trasfered Events
284  *
285  * @param base FlexCAN peripheral base address.
286  * @param handle FlexCAN handle pointer.
287  * @param pResult Pointer to the Handle result.
288  *
289  * @return the status after handle each data transfered event.
290  */
291 static status_t FLEXCAN_SubHandlerForDataTransfered(CAN_Type *base, flexcan_handle_t *handle, uint32_t *pResult);
292 
293 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
294 /*!
295  * @brief Sub Handler Ehanced Rx FIFO event
296  *
297  * @param base FlexCAN peripheral base address.
298  * @param handle FlexCAN handle pointer.
299  * @param flags FlexCAN interrupt flags.
300  *
301  * @return the status after handle Ehanced Rx FIFO event.
302  */
303 static status_t FLEXCAN_SubHandlerForEhancedRxFifo(CAN_Type *base, flexcan_handle_t *handle, uint64_t flags);
304 #endif
305 
306 /*******************************************************************************
307  * Variables
308  ******************************************************************************/
309 
310 /* Array of FlexCAN peripheral base address. */
311 static CAN_Type *const s_flexcanBases[] = CAN_BASE_PTRS;
312 
313 /* Array of FlexCAN IRQ number. */
314 static const IRQn_Type s_flexcanRxWarningIRQ[] = CAN_Rx_Warning_IRQS;
315 static const IRQn_Type s_flexcanTxWarningIRQ[] = CAN_Tx_Warning_IRQS;
316 static const IRQn_Type s_flexcanWakeUpIRQ[]    = CAN_Wake_Up_IRQS;
317 static const IRQn_Type s_flexcanErrorIRQ[]     = CAN_Error_IRQS;
318 static const IRQn_Type s_flexcanBusOffIRQ[]    = CAN_Bus_Off_IRQS;
319 static const IRQn_Type s_flexcanMbIRQ[]        = CAN_ORed_Message_buffer_IRQS;
320 
321 /* Array of FlexCAN handle. */
322 static flexcan_handle_t *s_flexcanHandle[ARRAY_SIZE(s_flexcanBases)];
323 
324 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
325 /* Array of FlexCAN clock name. */
326 static const clock_ip_name_t s_flexcanClock[] = FLEXCAN_CLOCKS;
327 #if defined(FLEXCAN_PERIPH_CLOCKS)
328 /* Array of FlexCAN serial clock name. */
329 static const clock_ip_name_t s_flexcanPeriphClock[] = FLEXCAN_PERIPH_CLOCKS;
330 #endif /* FLEXCAN_PERIPH_CLOCKS */
331 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
332 
333 #if defined(FLEXCAN_RESETS_ARRAY)
334 /* Reset array */
335 static const reset_ip_name_t s_flexcanResets[] = FLEXCAN_RESETS_ARRAY;
336 #endif
337 
338 /* FlexCAN ISR for transactional APIs. */
339 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
340 static flexcan_isr_t s_flexcanIsr = (flexcan_isr_t)DefaultISR;
341 #else
342 static flexcan_isr_t s_flexcanIsr;
343 #endif
344 
345 /*******************************************************************************
346  * Implementation of 32-bit memset
347  ******************************************************************************/
348 
flexcan_memset(void * s,uint32_t c,size_t n)349 static void flexcan_memset(void *s, uint32_t c, size_t n)
350 {
351     size_t m;
352     volatile uint32_t *ptr = s;
353 
354     m = n / sizeof(*ptr);
355 
356     while ((m--) != (size_t)0)
357     {
358         *ptr++ = c;
359     }
360 }
361 
362 /*******************************************************************************
363  * Code
364  ******************************************************************************/
365 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
366 /*!
367  * brief Determine whether the FlexCAN instance support CAN FD mode at run time.
368  *
369  * note Use this API only if different soc parts share the SOC part name macro define. Otherwise, a different SOC part
370  *      name can be used to determine at compile time whether the FlexCAN instance supports CAN FD mode or not.
371  *      If need use this API to determine if CAN FD mode is supported, the FLEXCAN_Init function needs to be
372  *      executed first, and then call this API and use the return to value determines whether to supports CAN FD mode,
373  *      if return true, continue calling FLEXCAN_FDInit to enable CAN FD mode.
374  *
375  * param base FlexCAN peripheral base address.
376  * return return TRUE if instance support CAN FD mode, FALSE if instance only support classic CAN (2.0) mode.
377  */
FLEXCAN_IsInstanceHasFDMode(CAN_Type * base)378 bool FLEXCAN_IsInstanceHasFDMode(CAN_Type *base)
379 {
380     /* Enter Freeze Mode. */
381     FLEXCAN_EnterFreezeMode(base);
382     /* Enable CAN FD operation. */
383     base->MCR |= CAN_MCR_FDEN_MASK;
384 
385     /* There are some SoC parts that don't support CAN FD.
386      * Checking if FDEN bit is really set to 1 is a way to ensure that CAN FD is supported.
387      * When SoC parts don't support CAN FD, FDEN bit stuck at 0 and can't be set to 1. */
388     if (0U == (base->MCR & CAN_MCR_FDEN_MASK))
389     {
390         /* Exit Freeze Mode. */
391         FLEXCAN_ExitFreezeMode(base);
392         return false;
393     }
394     else
395     {
396         /* Clear CAN FD operation. */
397         base->MCR &= ~CAN_MCR_FDEN_MASK;
398         /* Exit Freeze Mode. */
399         FLEXCAN_ExitFreezeMode(base);
400         return true;
401     }
402 }
403 #endif
404 
405 /*!
406  * brief Get the FlexCAN instance from peripheral base address.
407  *
408  * param base FlexCAN peripheral base address.
409  * return FlexCAN instance.
410  */
FLEXCAN_GetInstance(CAN_Type * base)411 uint32_t FLEXCAN_GetInstance(CAN_Type *base)
412 {
413     uint32_t instance;
414 
415     /* Find the instance index from base address mappings. */
416     for (instance = 0; instance < ARRAY_SIZE(s_flexcanBases); instance++)
417     {
418         if (s_flexcanBases[instance] == base)
419         {
420             break;
421         }
422     }
423 
424     assert(instance < ARRAY_SIZE(s_flexcanBases));
425 
426     return instance;
427 }
428 
429 /*!
430  * brief Enter FlexCAN Freeze Mode.
431  *
432  * This function makes the FlexCAN work under Freeze Mode.
433  *
434  * param base FlexCAN peripheral base address.
435  */
436 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595)
FLEXCAN_EnterFreezeMode(CAN_Type * base)437 void FLEXCAN_EnterFreezeMode(CAN_Type *base)
438 {
439     uint32_t u32TimeoutCount = 0U;
440     uint32_t u32TempMCR      = 0U;
441     uint32_t u32TempIMASK1   = 0U;
442 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
443     uint32_t u32TempIMASK2 = 0U;
444 #endif
445 
446     /* Step1: set FRZ enable in MCR. */
447     base->MCR |= CAN_MCR_FRZ_MASK;
448 
449     /* Step2: to check if MDIS bit set in MCR. if yes, clear it. */
450     if (0U != (base->MCR & CAN_MCR_MDIS_MASK))
451     {
452         base->MCR &= ~CAN_MCR_MDIS_MASK;
453     }
454 
455     /* Step3: polling LPMACK. */
456     u32TimeoutCount = (uint32_t)FLEXCAN_WAIT_TIMEOUT;
457     while ((0U == (base->MCR & CAN_MCR_LPMACK_MASK)) && (u32TimeoutCount > 0U))
458     {
459         u32TimeoutCount--;
460     }
461 
462     /* Step4: to check FLTCONF in ESR1 register */
463     if (0U == (base->ESR1 & CAN_ESR1_FLTCONF_BUSOFF))
464     {
465         /* Error Active and Error Passive state */
466         /* Step5B: Set Halt bits. */
467         base->MCR |= CAN_MCR_HALT_MASK;
468 
469         /* Step6B: Poll the MCR register until the Freeze Acknowledge (FRZACK) bit is set, timeout need more than 178
470          * CAN bit length, so 20 multiply timeout is enough. */
471         u32TimeoutCount = (uint32_t)FLEXCAN_WAIT_TIMEOUT * 20U;
472         while ((0U == (base->MCR & CAN_MCR_FRZACK_MASK)) && (u32TimeoutCount > 0U))
473         {
474             u32TimeoutCount--;
475         }
476 
477         /* Merge ERRATA_9595 and ERRATA_8341 because both errata exist on some platform. */
478         if (0U == u32TimeoutCount)
479         {
480             /* backup MCR and IMASK register. */
481             u32TempMCR    = base->MCR;
482             u32TempIMASK1 = base->IMASK1;
483 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
484             u32TempIMASK2 = base->IMASK2;
485 #endif
486             /* Set the Soft Reset bit ((SOFTRST) in the MCR.*/
487             base->MCR |= CAN_MCR_SOFTRST_MASK;
488 
489             /* Poll the MCR register until the Soft Reset (SOFTRST) bit is cleared, timeout need more than 178
490              * CAN bit length, so 20 multiply timeout is enough. */
491             u32TimeoutCount = (uint32_t)FLEXCAN_WAIT_TIMEOUT * 20U;
492             while ((CAN_MCR_SOFTRST_MASK == (base->MCR & CAN_MCR_SOFTRST_MASK)) && (u32TimeoutCount > 0U))
493             {
494                 u32TimeoutCount--;
495             }
496 
497             /* Reconfig MCR. */
498             base->MCR = u32TempMCR;
499 
500             /* Reconfig IMASK. */
501             base->IMASK1 = u32TempIMASK1;
502 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
503             base->IMASK2 = u32TempIMASK2;
504 #endif
505         }
506     }
507     else
508     {
509         /* Bus Off state */
510         /* backup MCR and IMASK register. Errata document not descript it, but we need backup for step 8A and 9A. */
511         u32TempMCR    = base->MCR;
512         u32TempIMASK1 = base->IMASK1;
513 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
514         u32TempIMASK2 = base->IMASK2;
515 #endif
516 
517         /* Step5A: Set the Soft Reset bit ((SOFTRST) in the MCR.*/
518         base->MCR |= CAN_MCR_SOFTRST_MASK;
519 
520         /* Step6A: Poll the MCR register until the Soft Reset (SOFTRST) bit is cleared. */
521         u32TimeoutCount = (uint32_t)FLEXCAN_WAIT_TIMEOUT;
522         while ((CAN_MCR_SOFTRST_MASK == (base->MCR & CAN_MCR_SOFTRST_MASK)) && (u32TimeoutCount > 0U))
523         {
524             u32TimeoutCount--;
525         }
526 
527         /* Step7A: Poll the MCR register until the Freeze Acknowledge (FRZACK) bit is set. */
528         u32TimeoutCount = (uint32_t)FLEXCAN_WAIT_TIMEOUT;
529         while ((0U == (base->MCR & CAN_MCR_FRZACK_MASK)) && (u32TimeoutCount > 0U))
530         {
531             u32TimeoutCount--;
532         }
533 
534         /* Step8A: reconfig MCR. */
535         base->MCR = u32TempMCR;
536 
537         /* Step9A: reconfig IMASK. */
538         base->IMASK1 = u32TempIMASK1;
539 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
540         base->IMASK2 = u32TempIMASK2;
541 #endif
542     }
543 }
544 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_8341) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_8341)
FLEXCAN_EnterFreezeMode(CAN_Type * base)545 void FLEXCAN_EnterFreezeMode(CAN_Type *base)
546 {
547     uint32_t u32TimeoutCount = 0U;
548     uint32_t u32TempMCR      = 0U;
549     uint32_t u32TempIMASK1   = 0U;
550 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
551     uint32_t u32TempIMASK2   = 0U;
552 #endif
553 
554     /* Step1: set FRZ and HALT bit enable in MCR. */
555     base->MCR |= CAN_MCR_FRZ_MASK;
556     base->MCR |= CAN_MCR_HALT_MASK;
557 
558     /* Step2: to check if MDIS bit set in MCR. if yes, clear it. */
559     if (0U != (base->MCR & CAN_MCR_MDIS_MASK))
560     {
561         base->MCR &= ~CAN_MCR_MDIS_MASK;
562     }
563 
564     /* Step3: Poll the MCR register until the Freeze Acknowledge (FRZACK) bit is set. */
565     u32TimeoutCount = (uint32_t)FLEXCAN_WAIT_TIMEOUT * 100U;
566     while ((0U == (base->MCR & CAN_MCR_FRZACK_MASK)) && (u32TimeoutCount > 0U))
567     {
568         u32TimeoutCount--;
569     }
570 
571     /* Step4: check whether the timeout reached. if no skip step5 to step8. */
572     if (0U == u32TimeoutCount)
573     {
574         /* backup MCR and IMASK register. Errata document not descript it, but we need backup for step 8A and 9A. */
575         u32TempMCR    = base->MCR;
576         u32TempIMASK1 = base->IMASK1;
577 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
578         u32TempIMASK2 = base->IMASK2;
579 #endif
580         /* Step5: Set the Soft Reset bit ((SOFTRST) in the MCR.*/
581         base->MCR |= CAN_MCR_SOFTRST_MASK;
582 
583         /* Step6: Poll the MCR register until the Soft Reset (SOFTRST) bit is cleared. */
584         while (CAN_MCR_SOFTRST_MASK == (base->MCR & CAN_MCR_SOFTRST_MASK))
585         {
586         }
587 
588         /* Step7: reconfig MCR. */
589         base->MCR = u32TempMCR;
590 
591         /* Step8: reconfig IMASK. */
592         base->IMASK1 = u32TempIMASK1;
593 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
594         base->IMASK2 = u32TempIMASK2;
595 #endif
596     }
597 }
598 #else
FLEXCAN_EnterFreezeMode(CAN_Type * base)599 void FLEXCAN_EnterFreezeMode(CAN_Type *base)
600 {
601     /* Set Freeze, Halt bits. */
602     base->MCR |= CAN_MCR_FRZ_MASK;
603     base->MCR |= CAN_MCR_HALT_MASK;
604     while (0U == (base->MCR & CAN_MCR_FRZACK_MASK))
605     {
606     }
607 }
608 #endif
609 
610 /*!
611  * brief Exit FlexCAN Freeze Mode.
612  *
613  * This function makes the FlexCAN leave Freeze Mode.
614  *
615  * param base FlexCAN peripheral base address.
616  */
FLEXCAN_ExitFreezeMode(CAN_Type * base)617 void FLEXCAN_ExitFreezeMode(CAN_Type *base)
618 {
619 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
620     /* Clean FlexCAN Access With Non-Correctable Error Interrupt Flag to avoid be put in freeze mode. */
621     FLEXCAN_ClearStatusFlags(base, (uint64_t)kFLEXCAN_FlexCanAccessNonCorrectableErrorIntFlag |
622                                        (uint64_t)kFLEXCAN_FlexCanAccessNonCorrectableErrorOverrunFlag);
623 #endif
624 
625     /* Clear Freeze, Halt bits. */
626     base->MCR &= ~CAN_MCR_HALT_MASK;
627     base->MCR &= ~CAN_MCR_FRZ_MASK;
628 
629     /* Wait until the FlexCAN Module exit freeze mode. */
630     while (0U != (base->MCR & CAN_MCR_FRZACK_MASK))
631     {
632     }
633 }
634 
635 #if !defined(NDEBUG)
636 /*!
637  * brief Check if Message Buffer is occupied by Rx FIFO.
638  *
639  * This function check if Message Buffer is occupied by Rx FIFO.
640  *
641  * param base FlexCAN peripheral base address.
642  * param mbIdx The FlexCAN Message Buffer index.
643  * return TRUE if the index MB is occupied by Rx FIFO, FALSE if the index MB not occupied by Rx FIFO.
644  */
FLEXCAN_IsMbOccupied(CAN_Type * base,uint8_t mbIdx)645 static bool FLEXCAN_IsMbOccupied(CAN_Type *base, uint8_t mbIdx)
646 {
647     uint8_t lastOccupiedMb;
648     bool fgRet;
649 
650     /* Is Rx FIFO enabled? */
651     if (0U != (base->MCR & CAN_MCR_RFEN_MASK))
652     {
653         /* Get RFFN value. */
654         lastOccupiedMb = (uint8_t)((base->CTRL2 & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT);
655         /* Calculate the number of last Message Buffer occupied by Rx FIFO. */
656         lastOccupiedMb = ((lastOccupiedMb + 1U) * 2U) + 5U;
657 
658 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
659      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
660         /* the first valid MB should be occupied by ERRATA 5461 or 5829. */
661         lastOccupiedMb += 1U;
662 #endif
663         fgRet = (mbIdx <= lastOccupiedMb);
664     }
665     else
666     {
667 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
668      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
669         if (0U == mbIdx)
670         {
671             fgRet = true;
672         }
673         else
674 #endif
675         {
676             fgRet = false;
677         }
678     }
679 
680     return fgRet;
681 }
682 #endif
683 
684 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
685      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
686 /*!
687  * brief Get the first valid Message buffer ID of give FlexCAN instance.
688  *
689  * This function is a helper function for Errata 5641 workaround.
690  *
691  * param base FlexCAN peripheral base address.
692  * return The first valid Message Buffer Number.
693  */
FLEXCAN_GetFirstValidMb(CAN_Type * base)694 static uint8_t FLEXCAN_GetFirstValidMb(CAN_Type *base)
695 {
696     uint8_t firstValidMbNum;
697 
698     if (0U != (base->MCR & CAN_MCR_RFEN_MASK))
699     {
700         firstValidMbNum = (uint8_t)((base->CTRL2 & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT);
701         firstValidMbNum = ((firstValidMbNum + 1U) * 2U) + 6U;
702     }
703     else
704     {
705         firstValidMbNum = 0U;
706     }
707 
708     return firstValidMbNum;
709 }
710 #endif
711 
712 /*!
713  * brief Reset the FlexCAN Instance.
714  *
715  * Restores the FlexCAN module to reset state, notice that this function
716  * will set all the registers to reset state so the FlexCAN module can not work
717  * after calling this API.
718  *
719  * param base FlexCAN peripheral base address.
720  */
FLEXCAN_Reset(CAN_Type * base)721 static void FLEXCAN_Reset(CAN_Type *base)
722 {
723     /* The module must should be first exit from low power
724      * mode, and then soft reset can be applied.
725      */
726     assert(0U == (base->MCR & CAN_MCR_MDIS_MASK));
727 
728     uint8_t i;
729 
730 #if (defined(FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT)
731     if (0 != (FSL_FEATURE_FLEXCAN_INSTANCE_HAS_DOZE_MODE_SUPPORTn(base)))
732     {
733         /* De-assert DOZE Enable Bit. */
734         base->MCR &= ~CAN_MCR_DOZE_MASK;
735     }
736 #endif
737 
738     /* Wait until FlexCAN exit from any Low Power Mode. */
739     while (0U != (base->MCR & CAN_MCR_LPMACK_MASK))
740     {
741     }
742 
743     /* Assert Soft Reset Signal. */
744     base->MCR |= CAN_MCR_SOFTRST_MASK;
745     /* Wait until FlexCAN reset completes. */
746     while (0U != (base->MCR & CAN_MCR_SOFTRST_MASK))
747     {
748     }
749 
750 /* Reset MCR register. */
751 #if (defined(FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER) && FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER)
752     base->MCR |= CAN_MCR_WRNEN_MASK | CAN_MCR_WAKSRC_MASK |
753                  CAN_MCR_MAXMB((uint32_t)FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1U);
754 #else
755     base->MCR |=
756         CAN_MCR_WRNEN_MASK | CAN_MCR_MAXMB((uint32_t)FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1U);
757 #endif
758 
759     /* Reset CTRL1 and CTRL2 register, default to eanble SMP feature which enable three sample point to determine the
760      * received bit's value of the. */
761     base->CTRL1 = CAN_CTRL1_SMP_MASK;
762     base->CTRL2 = CAN_CTRL2_TASD(0x16) | CAN_CTRL2_RRS_MASK | CAN_CTRL2_EACEN_MASK;
763 
764 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
765     /* Enable unrestricted write access to FlexCAN memory. */
766     base->CTRL2 |= CAN_CTRL2_WRMFRZ_MASK;
767     /* Do memory initialization for all FlexCAN RAM in order to have the parity bits in memory properly
768        updated. */
769     *(volatile uint32_t *)CAN_INIT_RXFIR = 0x0U;
770     flexcan_memset(CAN_INIT_MEMORY_BASE_1, 0, CAN_INIT_MEMORY_SIZE_1);
771     flexcan_memset(CAN_INIT_MEMORY_BASE_2, 0, CAN_INIT_MEMORY_SIZE_2);
772     /* Disable unrestricted write access to FlexCAN memory. */
773     base->CTRL2 &= ~CAN_CTRL2_WRMFRZ_MASK;
774 
775     /* Clean all memory error flags. */
776     FLEXCAN_ClearStatusFlags(base, (uint64_t)kFLEXCAN_AllMemoryErrorFlag);
777 #else
778     /* Only need clean all Message Buffer memory. */
779     flexcan_memset((void *)&base->MB[0], 0, sizeof(base->MB));
780 #endif
781 
782     /* Clean all individual Rx Mask of Message Buffers. */
783     for (i = 0; i < (uint32_t)FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); i++)
784     {
785         base->RXIMR[i] = 0x3FFFFFFF;
786     }
787 
788     /* Clean Global Mask of Message Buffers. */
789     base->RXMGMASK = 0x3FFFFFFF;
790     /* Clean Global Mask of Message Buffer 14. */
791     base->RX14MASK = 0x3FFFFFFF;
792     /* Clean Global Mask of Message Buffer 15. */
793     base->RX15MASK = 0x3FFFFFFF;
794     /* Clean Global Mask of Rx FIFO. */
795     base->RXFGMASK = 0x3FFFFFFF;
796 }
797 
798 /*!
799  * brief Set bit rate of FlexCAN classical CAN frame or CAN FD frame nominal phase.
800  *
801  * This function set the bit rate of classical CAN frame or CAN FD frame nominal phase base on
802  * FLEXCAN_CalculateImprovedTimingValues() API calculated timing values.
803  *
804  * note Calling FLEXCAN_SetBitRate() overrides the bit rate set in FLEXCAN_Init().
805  *
806  * param base FlexCAN peripheral base address.
807  * param sourceClock_Hz Source Clock in Hz.
808  * param bitRate_Bps Bit rate in Bps.
809  * return kStatus_Success - Set CAN baud rate (only Nominal phase) successfully.
810  */
FLEXCAN_SetBitRate(CAN_Type * base,uint32_t sourceClock_Hz,uint32_t bitRate_Bps)811 status_t FLEXCAN_SetBitRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_t bitRate_Bps)
812 {
813     flexcan_timing_config_t timingCfg;
814     status_t result = kStatus_Fail;
815 
816     if (FLEXCAN_CalculateImprovedTimingValues(base, bitRate_Bps, sourceClock_Hz, &timingCfg))
817     {
818         FLEXCAN_SetTimingConfig(base, &timingCfg);
819         result = kStatus_Success;
820     }
821 
822     return result;
823 }
824 
825 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
826 /*!
827  * @brief Set bit rate of FlexCAN FD frame.
828  *
829  * This function set the baud rate of FLEXCAN FD base on FLEXCAN_FDCalculateImprovedTimingValues() API calculated timing
830  * values.
831  *
832  * @param base FlexCAN peripheral base address.
833  * @param sourceClock_Hz Source Clock in Hz.
834  * @param bitRateN_Bps Nominal bit Rate in Bps.
835  * @param bitRateD_Bps Data bit Rate in Bps.
836  * @return kStatus_Success - Set CAN FD bit rate (include Nominal and Data phase) successfully.
837  */
FLEXCAN_SetFDBitRate(CAN_Type * base,uint32_t sourceClock_Hz,uint32_t bitRateN_Bps,uint32_t bitRateD_Bps)838 status_t FLEXCAN_SetFDBitRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_t bitRateN_Bps, uint32_t bitRateD_Bps)
839 {
840     flexcan_timing_config_t timingCfg;
841     status_t result = kStatus_Fail;
842 
843     if (FLEXCAN_FDCalculateImprovedTimingValues(base, bitRateN_Bps, bitRateD_Bps, sourceClock_Hz, &timingCfg))
844     {
845         FLEXCAN_SetFDTimingConfig(base, &timingCfg);
846         result = kStatus_Success;
847     }
848 
849     return result;
850 }
851 #endif
852 
853 /*!
854  * brief Initializes a FlexCAN instance.
855  *
856  * This function initializes the FlexCAN module with user-defined settings.
857  * This example shows how to set up the flexcan_config_t parameters and how
858  * to call the FLEXCAN_Init function by passing in these parameters.
859  *  code
860  *   flexcan_config_t flexcanConfig;
861  *   flexcanConfig.clkSrc               = kFLEXCAN_ClkSrc0;
862  *   flexcanConfig.bitRate              = 1000000U;
863  *   flexcanConfig.maxMbNum             = 16;
864  *   flexcanConfig.enableLoopBack       = false;
865  *   flexcanConfig.enableSelfWakeup     = false;
866  *   flexcanConfig.enableIndividMask    = false;
867  *   flexcanConfig.disableSelfReception = false;
868  *   flexcanConfig.enableListenOnlyMode = false;
869  *   flexcanConfig.enableDoze           = false;
870  *   flexcanConfig.timingConfig         = timingConfig;
871  *   FLEXCAN_Init(CAN0, &flexcanConfig, 40000000UL);
872  *   endcode
873  *
874  * param base FlexCAN peripheral base address.
875  * param pConfig Pointer to the user-defined configuration structure.
876  * param sourceClock_Hz FlexCAN Protocol Engine clock source frequency in Hz.
877  */
FLEXCAN_Init(CAN_Type * base,const flexcan_config_t * pConfig,uint32_t sourceClock_Hz)878 void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *pConfig, uint32_t sourceClock_Hz)
879 {
880     /* Assertion. */
881     assert(NULL != pConfig);
882     assert((pConfig->maxMbNum > 0U) &&
883            (pConfig->maxMbNum <= (uint8_t)FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base)));
884 
885     uint32_t mcrTemp;
886     uint32_t ctrl1Temp;
887 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
888     uint32_t instance;
889 #endif
890     flexcan_timing_config_t timingCfg = pConfig->timingConfig;
891     /* FlexCAN classical CAN frame or CAN FD frame nominal phase timing setting formula:
892      * quantum = 1 + (phaseSeg1 + 1) + (phaseSeg2 + 1) + (propSeg + 1);
893      */
894     uint32_t quantum = (1U + ((uint32_t)timingCfg.phaseSeg1 + 1U) + ((uint32_t)timingCfg.phaseSeg2 + 1U) +
895                         ((uint32_t)timingCfg.propSeg + 1U));
896     uint32_t tqFre   = pConfig->bitRate * quantum;
897     uint16_t maxDivider;
898 
899     /* Assertion: Check bit rate value. */
900     assert((pConfig->bitRate != 0U) && (pConfig->bitRate <= 1000000U) && (tqFre <= sourceClock_Hz));
901 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
902     if (0 != FSL_FEATURE_FLEXCAN_INSTANCE_HAS_FLEXIBLE_DATA_RATEn(base))
903     {
904 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
905         assert((tqFre * MAX_ENPRESDIV) >= sourceClock_Hz);
906         maxDivider = MAX_ENPRESDIV;
907 #else
908         assert((tqFre * MAX_EPRESDIV) >= sourceClock_Hz);
909         maxDivider = MAX_EPRESDIV;
910 #endif
911     }
912     else
913     {
914         assert((tqFre * MAX_PRESDIV) >= sourceClock_Hz);
915         maxDivider = MAX_PRESDIV;
916     }
917 #else
918     assert((tqFre * MAX_PRESDIV) >= sourceClock_Hz);
919     maxDivider                       = MAX_PRESDIV;
920 #endif
921 
922 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
923     instance = FLEXCAN_GetInstance(base);
924     /* Enable FlexCAN clock. */
925     (void)CLOCK_EnableClock(s_flexcanClock[instance]);
926     /*
927      * Check the CAN clock in this device whether affected by Other clock gate
928      * If it affected, we'd better to change other clock source,
929      * If user insist on using that clock source, user need open these gate at same time,
930      * In this scene, User need to care the power consumption.
931      */
932     assert(CAN_CLOCK_CHECK_NO_AFFECTS);
933 #if defined(FLEXCAN_PERIPH_CLOCKS)
934     /* Enable FlexCAN serial clock. */
935     (void)CLOCK_EnableClock(s_flexcanPeriphClock[instance]);
936 #endif /* FLEXCAN_PERIPH_CLOCKS */
937 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
938 
939 #if defined(FLEXCAN_RESETS_ARRAY)
940     RESET_ReleasePeripheralReset(s_flexcanResets[FLEXCAN_GetInstance(base)]);
941 #endif
942 
943 #if defined(CAN_CTRL1_CLKSRC_MASK)
944 #if (defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE) && FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)
945     if (0 == FSL_FEATURE_FLEXCAN_INSTANCE_SUPPORT_ENGINE_CLK_SEL_REMOVEn(base))
946 #endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */
947     {
948         /* Disable FlexCAN Module. */
949         FLEXCAN_Enable(base, false);
950 
951         /* Protocol-Engine clock source selection, This bit must be set
952          * when FlexCAN Module in Disable Mode.
953          */
954         base->CTRL1 = (kFLEXCAN_ClkSrc0 == pConfig->clkSrc) ? (base->CTRL1 & ~CAN_CTRL1_CLKSRC_MASK) :
955                                                               (base->CTRL1 | CAN_CTRL1_CLKSRC_MASK);
956     }
957 #endif /* CAN_CTRL1_CLKSRC_MASK */
958 
959     /* Enable FlexCAN Module for configuration. */
960     FLEXCAN_Enable(base, true);
961 
962     /* Reset to known status. */
963     FLEXCAN_Reset(base);
964 
965 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
966     /* Enable to update in MCER. */
967     base->CTRL2 |= CAN_CTRL2_ECRWRE_MASK;
968     base->MECR &= ~CAN_MECR_ECRWRDIS_MASK;
969 
970     /* Enable/Disable Memory Error Detection and Correction.*/
971     base->MECR = (pConfig->enableMemoryErrorControl) ? (base->MECR & ~CAN_MECR_ECCDIS_MASK) :
972                                                        (base->MECR | CAN_MECR_ECCDIS_MASK);
973 
974     /* Enable/Disable Non-Correctable Errors In FlexCAN Access Put Device In Freeze Mode. */
975     base->MECR = (pConfig->enableNonCorrectableErrorEnterFreeze) ? (base->MECR | CAN_MECR_NCEFAFRZ_MASK) :
976                                                                    (base->MECR & ~CAN_MECR_NCEFAFRZ_MASK);
977     /* Lock MCER register. */
978     base->CTRL2 &= ~CAN_CTRL2_ECRWRE_MASK;
979 #endif
980 
981     /* Save current CTRL1 value and enable to enter Freeze mode(enabled by default). */
982     ctrl1Temp = base->CTRL1;
983 
984     /* Save current MCR value and enable to enter Freeze mode(enabled by default). */
985     mcrTemp = base->MCR;
986 
987     /* Enable Loop Back Mode? */
988     ctrl1Temp = (pConfig->enableLoopBack) ? (ctrl1Temp | CAN_CTRL1_LPB_MASK) : (ctrl1Temp & ~CAN_CTRL1_LPB_MASK);
989 
990     /* Enable Timer Sync? */
991     ctrl1Temp = (pConfig->enableTimerSync) ? (ctrl1Temp | CAN_CTRL1_TSYN_MASK) : (ctrl1Temp & ~CAN_CTRL1_TSYN_MASK);
992 
993     /* Enable Listen Only Mode? */
994     ctrl1Temp = (pConfig->enableListenOnlyMode) ? ctrl1Temp | CAN_CTRL1_LOM_MASK : ctrl1Temp & ~CAN_CTRL1_LOM_MASK;
995 
996 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_SUPV_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_SUPV_SUPPORT)
997     /* Enable Supervisor Mode? */
998     mcrTemp = (pConfig->enableSupervisorMode) ? mcrTemp | CAN_MCR_SUPV_MASK : mcrTemp & ~CAN_MCR_SUPV_MASK;
999 #endif
1000 
1001     /* Set the maximum number of Message Buffers */
1002     mcrTemp = (mcrTemp & ~CAN_MCR_MAXMB_MASK) | CAN_MCR_MAXMB((uint32_t)pConfig->maxMbNum - 1U);
1003 
1004     /* Enable Self Wake Up Mode and configure the wake up source. */
1005 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_SLFWAK_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_SLFWAK_SUPPORT)
1006     mcrTemp = (pConfig->enableSelfWakeup) ? (mcrTemp | CAN_MCR_SLFWAK_MASK) : (mcrTemp & ~CAN_MCR_SLFWAK_MASK);
1007 #endif
1008 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_WAKSRC_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_WAKSRC_SUPPORT)
1009     mcrTemp = (kFLEXCAN_WakeupSrcFiltered == pConfig->wakeupSrc) ? (mcrTemp | CAN_MCR_WAKSRC_MASK) :
1010                                                                    (mcrTemp & ~CAN_MCR_WAKSRC_MASK);
1011 #endif
1012 #if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE)
1013     /* Enable Pretended Networking Mode? When Pretended Networking mode is set, Self Wake Up feature must be disabled.*/
1014     mcrTemp = (pConfig->enablePretendedeNetworking) ? ((mcrTemp & ~CAN_MCR_SLFWAK_MASK) | CAN_MCR_PNET_EN_MASK) :
1015                                                       (mcrTemp & ~CAN_MCR_PNET_EN_MASK);
1016 #endif
1017 
1018     /* Enable Individual Rx Masking and Queue feature? */
1019     mcrTemp = (pConfig->enableIndividMask) ? (mcrTemp | CAN_MCR_IRMQ_MASK) : (mcrTemp & ~CAN_MCR_IRMQ_MASK);
1020 
1021     /* Disable Self Reception? */
1022     mcrTemp = (pConfig->disableSelfReception) ? mcrTemp | CAN_MCR_SRXDIS_MASK : mcrTemp & ~CAN_MCR_SRXDIS_MASK;
1023 
1024 #if (defined(FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT)
1025     if (0 != FSL_FEATURE_FLEXCAN_INSTANCE_HAS_DOZE_MODE_SUPPORTn(base))
1026     {
1027         /* Enable Doze Mode? */
1028         mcrTemp = (pConfig->enableDoze) ? (mcrTemp | CAN_MCR_DOZE_MASK) : (mcrTemp & ~CAN_MCR_DOZE_MASK);
1029     }
1030 #endif
1031 
1032     /* Write back CTRL1 Configuration to register. */
1033     base->CTRL1 = ctrl1Temp;
1034 
1035     /* Write back MCR Configuration to register. */
1036     base->MCR = mcrTemp;
1037 
1038     /* Check whether Nominal Bit Rate Prescaler is overflow. */
1039     if ((sourceClock_Hz / tqFre - 1U) > maxDivider)
1040     {
1041         timingCfg.preDivider = maxDivider;
1042     }
1043     else
1044     {
1045         timingCfg.preDivider = (uint16_t)(sourceClock_Hz / tqFre) - 1U;
1046     }
1047 
1048     /* Update actual timing characteristic. */
1049     FLEXCAN_SetTimingConfig(base, &timingCfg);
1050 }
1051 
1052 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1053 /*!
1054  * brief Initializes a FlexCAN instance.
1055  *
1056  * This function initializes the FlexCAN module with user-defined settings.
1057  * This example shows how to set up the flexcan_config_t parameters and how
1058  * to call the FLEXCAN_FDInit function by passing in these parameters.
1059  *  code
1060  *   flexcan_config_t flexcanConfig;
1061  *   flexcanConfig.clkSrc               = kFLEXCAN_ClkSrc0;
1062  *   flexcanConfig.bitRate              = 1000000U;
1063  *   flexcanConfig.bitRateFD            = 2000000U;
1064  *   flexcanConfig.maxMbNum             = 16;
1065  *   flexcanConfig.enableLoopBack       = false;
1066  *   flexcanConfig.enableSelfWakeup     = false;
1067  *   flexcanConfig.enableIndividMask    = false;
1068  *   flexcanConfig.disableSelfReception = false;
1069  *   flexcanConfig.enableListenOnlyMode = false;
1070  *   flexcanConfig.enableDoze           = false;
1071  *   flexcanConfig.timingConfig         = timingConfig;
1072  *   FLEXCAN_FDInit(CAN0, &flexcanConfig, 80000000UL, kFLEXCAN_16BperMB, true);
1073  *   endcode
1074  *
1075  * param base FlexCAN peripheral base address.
1076  * param pConfig Pointer to the user-defined configuration structure.
1077  * param sourceClock_Hz FlexCAN Protocol Engine clock source frequency in Hz.
1078  * param dataSize FlexCAN Message Buffer payload size. The actual transmitted or received CAN FD frame data size needs
1079  *                to be less than or equal to this value.
1080  * param brs True if bit rate switch is enabled in FD mode.
1081  */
FLEXCAN_FDInit(CAN_Type * base,const flexcan_config_t * pConfig,uint32_t sourceClock_Hz,flexcan_mb_size_t dataSize,bool brs)1082 void FLEXCAN_FDInit(
1083     CAN_Type *base, const flexcan_config_t *pConfig, uint32_t sourceClock_Hz, flexcan_mb_size_t dataSize, bool brs)
1084 {
1085     assert((uint32_t)dataSize <= 3U);
1086     assert(((pConfig->bitRate < pConfig->bitRateFD) && brs) || ((pConfig->bitRate == pConfig->bitRateFD) && (!brs)));
1087 
1088     uint32_t fdctrl                   = 0U;
1089     flexcan_timing_config_t timingCfg = pConfig->timingConfig;
1090     /* FlexCAN FD frame data phase timing setting formula:
1091      * quantum = 1 + (fphaseSeg1 + 1) + (fphaseSeg2 + 1) + fpropSeg;
1092      */
1093     uint32_t quantum = (1U + ((uint32_t)timingCfg.fphaseSeg1 + 1U) + ((uint32_t)timingCfg.fphaseSeg2 + 1U) +
1094                         (uint32_t)timingCfg.fpropSeg);
1095     uint32_t tqFre   = pConfig->bitRateFD * quantum;
1096     uint16_t maxDivider;
1097 
1098     /* Check bit rate value. */
1099     assert((pConfig->bitRateFD <= MAX_CANFD_BITRATE) && (tqFre <= sourceClock_Hz));
1100 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1101     assert((tqFre * MAX_EDPRESDIV) >= sourceClock_Hz);
1102     maxDivider = MAX_EDPRESDIV;
1103 #else
1104     assert((tqFre * MAX_FPRESDIV) >= sourceClock_Hz);
1105     maxDivider = MAX_FPRESDIV;
1106 #endif
1107 
1108     /* Initialization of classical CAN. */
1109     FLEXCAN_Init(base, pConfig, sourceClock_Hz);
1110 
1111     /* Check whether Data Bit Rate Prescaler is overflow. */
1112     if ((sourceClock_Hz / tqFre - 1U) > maxDivider)
1113     {
1114         timingCfg.fpreDivider = maxDivider;
1115     }
1116     else
1117     {
1118         timingCfg.fpreDivider = (uint16_t)(sourceClock_Hz / tqFre) - 1U;
1119     }
1120 
1121     /* Update actual timing characteristic. */
1122     FLEXCAN_SetFDTimingConfig(base, &timingCfg);
1123 
1124     /* read FDCTRL register. */
1125     fdctrl = base->FDCTRL;
1126 
1127     /* Enable FD operation and set bit rate switch. */
1128     if (brs)
1129     {
1130         fdctrl |= CAN_FDCTRL_FDRATE_MASK;
1131     }
1132     else
1133     {
1134         fdctrl &= ~CAN_FDCTRL_FDRATE_MASK;
1135     }
1136 
1137     /* Before use "|=" operation for multi-bits field, CPU should clean previous Setting. */
1138     fdctrl = (fdctrl & ~CAN_FDCTRL_MBDSR0_MASK) | CAN_FDCTRL_MBDSR0(dataSize);
1139 #if defined(CAN_FDCTRL_MBDSR1_MASK)
1140     fdctrl = (fdctrl & ~CAN_FDCTRL_MBDSR1_MASK) | CAN_FDCTRL_MBDSR1(dataSize);
1141 #endif
1142 #if defined(CAN_FDCTRL_MBDSR2_MASK)
1143     fdctrl = (fdctrl & ~CAN_FDCTRL_MBDSR2_MASK) | CAN_FDCTRL_MBDSR2(dataSize);
1144 #endif
1145 #if defined(CAN_FDCTRL_MBDSR3_MASK)
1146     fdctrl = (fdctrl & ~CAN_FDCTRL_MBDSR3_MASK) | CAN_FDCTRL_MBDSR3(dataSize);
1147 #endif
1148 
1149     /* Enter Freeze Mode. */
1150     FLEXCAN_EnterFreezeMode(base);
1151     /* Enable CAN FD operation. */
1152     base->MCR |= CAN_MCR_FDEN_MASK;
1153     /* Clear SMP bit when CAN FD is enabled (CAN FD only can use one regular sample point plus one optional secondary
1154      * sampling point). */
1155     base->CTRL1 &= ~CAN_CTRL1_SMP_MASK;
1156 
1157     if (brs && !(pConfig->enableLoopBack))
1158     {
1159 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1160         /* The TDC offset should be configured as shown in this equation : offset = DTSEG1 + 2 */
1161         if (((uint32_t)pConfig->timingConfig.fphaseSeg1 + pConfig->timingConfig.fpropSeg + 2U) *
1162                 (pConfig->timingConfig.fpreDivider + 1U) <
1163             MAX_ETDCOFF)
1164         {
1165             base->ETDC =
1166                 CAN_ETDC_ETDCEN_MASK | CAN_ETDC_TDMDIS(!pConfig->enableTransceiverDelayMeasure) |
1167                 CAN_ETDC_ETDCOFF(((uint32_t)pConfig->timingConfig.fphaseSeg1 + pConfig->timingConfig.fpropSeg + 2U) *
1168                                  (pConfig->timingConfig.fpreDivider + 1U));
1169         }
1170         else
1171         {
1172             /* Enable the Transceiver Delay Compensation */
1173             base->ETDC = CAN_ETDC_ETDCEN_MASK | CAN_ETDC_TDMDIS(!pConfig->enableTransceiverDelayMeasure) |
1174                          CAN_ETDC_ETDCOFF(MAX_ETDCOFF);
1175         }
1176 #else
1177         /* The TDC offset should be configured as shown in this equation : offset = PSEG1 + PROPSEG + 2 */
1178         if (((uint32_t)pConfig->timingConfig.fphaseSeg1 + pConfig->timingConfig.fpropSeg + 2U) *
1179                 (pConfig->timingConfig.fpreDivider + 1U) <
1180             MAX_TDCOFF)
1181         {
1182             fdctrl =
1183                 (fdctrl & ~CAN_FDCTRL_TDCOFF_MASK) |
1184                 CAN_FDCTRL_TDCOFF(((uint32_t)pConfig->timingConfig.fphaseSeg1 + pConfig->timingConfig.fpropSeg + 2U) *
1185                                   (pConfig->timingConfig.fpreDivider + 1U));
1186         }
1187         else
1188         {
1189             fdctrl = (fdctrl & ~CAN_FDCTRL_TDCOFF_MASK) | CAN_FDCTRL_TDCOFF(MAX_TDCOFF);
1190         }
1191         /* Enable the Transceiver Delay Compensation */
1192         fdctrl = (fdctrl & ~CAN_FDCTRL_TDCEN_MASK) | CAN_FDCTRL_TDCEN_MASK;
1193 #endif
1194     }
1195 
1196     /* update the FDCTL register. */
1197     base->FDCTRL = fdctrl;
1198 
1199     /* Enable CAN FD ISO mode by default. */
1200     base->CTRL2 |= CAN_CTRL2_ISOCANFDEN_MASK;
1201 
1202     /* Exit Freeze Mode. */
1203     FLEXCAN_ExitFreezeMode(base);
1204 }
1205 #endif
1206 
1207 /*!
1208  * brief De-initializes a FlexCAN instance.
1209  *
1210  * This function disables the FlexCAN module clock and sets all register values
1211  * to the reset value.
1212  *
1213  * param base FlexCAN peripheral base address.
1214  */
FLEXCAN_Deinit(CAN_Type * base)1215 void FLEXCAN_Deinit(CAN_Type *base)
1216 {
1217 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1218     uint32_t instance;
1219 #endif
1220     /* Reset all Register Contents. */
1221     FLEXCAN_Reset(base);
1222 
1223     /* Disable FlexCAN module. */
1224     FLEXCAN_Enable(base, false);
1225 
1226 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1227     instance = FLEXCAN_GetInstance(base);
1228 #if defined(FLEXCAN_PERIPH_CLOCKS)
1229     /* Disable FlexCAN serial clock. */
1230     (void)CLOCK_DisableClock(s_flexcanPeriphClock[instance]);
1231 #endif /* FLEXCAN_PERIPH_CLOCKS */
1232     /* Disable FlexCAN clock. */
1233     (void)CLOCK_DisableClock(s_flexcanClock[instance]);
1234 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1235 }
1236 
1237 /*!
1238  * brief Gets the default configuration structure.
1239  *
1240  * This function initializes the FlexCAN configuration structure to default values. The default
1241  * values are as follows.
1242  *   flexcanConfig->clkSrc                               = kFLEXCAN_ClkSrc0;
1243  *   flexcanConfig->bitRate                              = 1000000U;
1244  *   flexcanConfig->bitRateFD                            = 2000000U;
1245  *   flexcanConfig->maxMbNum                             = 16;
1246  *   flexcanConfig->enableLoopBack                       = false;
1247  *   flexcanConfig->enableSelfWakeup                     = false;
1248  *   flexcanConfig->enableIndividMask                    = false;
1249  *   flexcanConfig->disableSelfReception                 = false;
1250  *   flexcanConfig->enableListenOnlyMode                 = false;
1251  *   flexcanConfig->enableDoze                           = false;
1252  *   flexcanConfig->enablePretendedeNetworking           = false;
1253  *   flexcanConfig->enableMemoryErrorControl             = true;
1254  *   flexcanConfig->enableNonCorrectableErrorEnterFreeze = true;
1255  *   flexcanConfig->enableTransceiverDelayMeasure        = true;
1256  *   flexcanConfig.timingConfig                          = timingConfig;
1257  *
1258  * param pConfig Pointer to the FlexCAN configuration structure.
1259  */
FLEXCAN_GetDefaultConfig(flexcan_config_t * pConfig)1260 void FLEXCAN_GetDefaultConfig(flexcan_config_t *pConfig)
1261 {
1262     /* Assertion. */
1263     assert(NULL != pConfig);
1264 
1265     /* Initializes the configure structure to zero. */
1266     (void)memset(pConfig, 0, sizeof(*pConfig));
1267 
1268     /* Initialize FlexCAN Module config struct with default value. */
1269     pConfig->clkSrc  = kFLEXCAN_ClkSrc0;
1270     pConfig->bitRate = 1000000U;
1271 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1272     pConfig->bitRateFD = 2000000U;
1273 #endif
1274     pConfig->maxMbNum             = 16;
1275     pConfig->enableLoopBack       = false;
1276     pConfig->enableTimerSync      = true;
1277 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_SLFWAK_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_SLFWAK_SUPPORT)
1278     pConfig->enableSelfWakeup     = false;
1279 #endif
1280 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_WAKSRC_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_WAKSRC_SUPPORT)
1281     pConfig->wakeupSrc            = kFLEXCAN_WakeupSrcUnfiltered;
1282 #endif
1283     pConfig->enableIndividMask    = false;
1284     pConfig->disableSelfReception = false;
1285     pConfig->enableListenOnlyMode = false;
1286 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_SUPV_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_SUPV_SUPPORT)
1287     pConfig->enableSupervisorMode = true;
1288 #endif
1289 #if (defined(FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT)
1290     pConfig->enableDoze = false;
1291 #endif
1292 #if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE)
1293     pConfig->enablePretendedeNetworking = false;
1294 #endif
1295 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
1296     pConfig->enableMemoryErrorControl             = true;
1297     pConfig->enableNonCorrectableErrorEnterFreeze = true;
1298 #endif
1299 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1300     pConfig->enableTransceiverDelayMeasure = true;
1301 #endif
1302 
1303     /* Default protocol timing configuration, nominal bit time quantum is 10 (80% SP), data bit time quantum is 5
1304      * (60%). Suggest use FLEXCAN_CalculateImprovedTimingValues/FLEXCAN_FDCalculateImprovedTimingValues to get the
1305      * improved timing configuration.*/
1306 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1307     pConfig->timingConfig.phaseSeg1   = 1;
1308     pConfig->timingConfig.phaseSeg2   = 1;
1309     pConfig->timingConfig.propSeg     = 4;
1310     pConfig->timingConfig.rJumpwidth  = 1;
1311     pConfig->timingConfig.fphaseSeg1  = 1;
1312     pConfig->timingConfig.fphaseSeg2  = 1;
1313     pConfig->timingConfig.fpropSeg    = 0;
1314     pConfig->timingConfig.frJumpwidth = 1;
1315 #else
1316     pConfig->timingConfig.phaseSeg1  = 1;
1317     pConfig->timingConfig.phaseSeg2  = 1;
1318     pConfig->timingConfig.propSeg    = 4;
1319     pConfig->timingConfig.rJumpwidth = 1;
1320 #endif
1321 }
1322 
1323 #if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE)
1324 /*!
1325  * brief Configures the FlexCAN Pretended Networking mode.
1326  *
1327  * This function configures the FlexCAN Pretended Networking mode with given configuration.
1328  *
1329  * param base FlexCAN peripheral base address.
1330  * param pConfig Pointer to the FlexCAN Rx FIFO configuration structure.
1331  */
FLEXCAN_SetPNConfig(CAN_Type * base,const flexcan_pn_config_t * pConfig)1332 void FLEXCAN_SetPNConfig(CAN_Type *base, const flexcan_pn_config_t *pConfig)
1333 {
1334     /* Assertion. */
1335     assert(NULL != pConfig);
1336     assert(0U != pConfig->matchNum);
1337     uint32_t pnctrl;
1338     /* Enter Freeze Mode. */
1339     FLEXCAN_EnterFreezeMode(base);
1340     pnctrl = (pConfig->matchNum > 1U) ? CAN_CTRL1_PN_FCS(0x2U | (uint32_t)pConfig->matchSrc) :
1341                                         CAN_CTRL1_PN_FCS(pConfig->matchSrc);
1342     pnctrl |= (pConfig->enableMatch) ? (CAN_CTRL1_PN_WUMF_MSK_MASK) : 0U;
1343     pnctrl |= (pConfig->enableTimeout) ? (CAN_CTRL1_PN_WTOF_MSK_MASK) : 0U;
1344     pnctrl |= CAN_CTRL1_PN_NMATCH(pConfig->matchNum) | CAN_CTRL1_PN_IDFS(pConfig->idMatchMode) |
1345               CAN_CTRL1_PN_PLFS(pConfig->dataMatchMode);
1346     base->CTRL1_PN       = pnctrl;
1347     base->CTRL2_PN       = CAN_CTRL2_PN_MATCHTO(pConfig->timeoutValue);
1348     base->FLT_ID1        = pConfig->idLower;
1349     base->FLT_ID2_IDMASK = pConfig->idUpper;
1350     base->FLT_DLC        = CAN_FLT_DLC_FLT_DLC_LO(pConfig->lengthLower) | CAN_FLT_DLC_FLT_DLC_HI(pConfig->lengthUpper);
1351     base->PL1_LO         = pConfig->lowerWord0;
1352     base->PL1_HI         = pConfig->lowerWord1;
1353     base->PL2_PLMASK_LO  = pConfig->upperWord0;
1354     base->PL2_PLMASK_HI  = pConfig->upperWord1;
1355 
1356     FLEXCAN_ClearStatusFlags(base, (uint64_t)kFLEXCAN_PNMatchIntFlag | (uint64_t)kFLEXCAN_PNTimeoutIntFlag);
1357 
1358     /* Exit Freeze Mode. */
1359     FLEXCAN_ExitFreezeMode(base);
1360 }
1361 
1362 /*!
1363  * brief Reads a FlexCAN Message from Wake Up MB.
1364  *
1365  * This function reads a CAN message from the FlexCAN Wake up Message Buffers. There are four Wake up Message Buffers
1366  * (WMBs) used to store incoming messages in Pretended Networking mode. The WMB index indicates the arrival order. The
1367  * last message is stored in WMB3.
1368  *
1369  * param base FlexCAN peripheral base address.
1370  * param pRxFrame Pointer to CAN message frame structure for reception.
1371  * param mbIdx The FlexCAN Wake up Message Buffer index. Range in 0x0 ~ 0x3.
1372  * retval kStatus_Success - Read Message from Wake up Message Buffer successfully.
1373  * retval kStatus_Fail    - Wake up Message Buffer has no valid content.
1374  */
FLEXCAN_ReadPNWakeUpMB(CAN_Type * base,uint8_t mbIdx,flexcan_frame_t * pRxFrame)1375 status_t FLEXCAN_ReadPNWakeUpMB(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *pRxFrame)
1376 {
1377     /* Assertion. */
1378     assert(NULL != pRxFrame);
1379     assert(mbIdx <= 0x3U);
1380 
1381     uint32_t cs_temp;
1382     status_t status;
1383 
1384     /* Check if Wake Up MB has valid content. */
1385     if (CAN_WU_MTC_MCOUNTER(mbIdx) < (base->WU_MTC & CAN_WU_MTC_MCOUNTER_MASK))
1386     {
1387         /* Read CS field of wake up Message Buffer. */
1388         cs_temp = base->WMB[mbIdx].CS;
1389 
1390         /* Store Message ID. */
1391         pRxFrame->id = base->WMB[mbIdx].ID & (CAN_ID_EXT_MASK | CAN_ID_STD_MASK);
1392 
1393         /* Get the message ID and format. */
1394         pRxFrame->format = (cs_temp & CAN_CS_IDE_MASK) != 0U ? (uint8_t)kFLEXCAN_FrameFormatExtend :
1395                                                                (uint8_t)kFLEXCAN_FrameFormatStandard;
1396 
1397         /* Get the message type. */
1398         pRxFrame->type =
1399             (cs_temp & CAN_CS_RTR_MASK) != 0U ? (uint8_t)kFLEXCAN_FrameTypeRemote : (uint8_t)kFLEXCAN_FrameTypeData;
1400 
1401         /* Get the message length. */
1402         pRxFrame->length = (uint8_t)((cs_temp & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
1403 
1404         /* Messages received during Pretended Networking mode don't have time stamps, and the respective field in the
1405            WMB structure must be ignored. */
1406         pRxFrame->timestamp = 0x0;
1407 
1408         /* Store Message Payload. */
1409         pRxFrame->dataWord0 = base->WMB[mbIdx].D03;
1410         pRxFrame->dataWord1 = base->WMB[mbIdx].D47;
1411 
1412         status = kStatus_Success;
1413     }
1414     else
1415     {
1416         status = kStatus_Fail;
1417     }
1418 
1419     return status;
1420 }
1421 #endif
1422 
1423 /*!
1424  * brief Sets the FlexCAN classical protocol timing characteristic.
1425  *
1426  * This function gives user settings to classical CAN or CAN FD nominal phase timing characteristic.
1427  * The function is for an experienced user. For less experienced users, call the FLEXCAN_GetDefaultConfig()
1428  * and get the default timing characteristicsthe, then call FLEXCAN_Init() and fill the
1429  * bit rate field.
1430  *
1431  * note Calling FLEXCAN_SetTimingConfig() overrides the bit rate set
1432  * in FLEXCAN_Init().
1433  *
1434  * param base FlexCAN peripheral base address.
1435  * param pConfig Pointer to the timing configuration structure.
1436  */
FLEXCAN_SetTimingConfig(CAN_Type * base,const flexcan_timing_config_t * pConfig)1437 void FLEXCAN_SetTimingConfig(CAN_Type *base, const flexcan_timing_config_t *pConfig)
1438 {
1439     /* Assertion. */
1440     assert(NULL != pConfig);
1441 
1442     /* Enter Freeze Mode. */
1443     FLEXCAN_EnterFreezeMode(base);
1444 
1445 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1446     if (0 != FSL_FEATURE_FLEXCAN_INSTANCE_HAS_FLEXIBLE_DATA_RATEn(base))
1447     {
1448 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1449         /* Enable extended Bit Timing register ENCBT. */
1450         base->CTRL2 |= CAN_CTRL2_BTE_MASK;
1451 
1452         /* Updating Timing Setting according to configuration structure. */
1453         base->EPRS  = (base->EPRS & (~CAN_EPRS_ENPRESDIV_MASK)) | CAN_EPRS_ENPRESDIV(pConfig->preDivider);
1454         base->ENCBT = CAN_ENCBT_NRJW(pConfig->rJumpwidth) |
1455                       CAN_ENCBT_NTSEG1((uint32_t)pConfig->phaseSeg1 + pConfig->propSeg + 1U) |
1456                       CAN_ENCBT_NTSEG2(pConfig->phaseSeg2);
1457 #else
1458         /* On RT106x devices, a single write may be ignored, so it is necessary to read back the register value to
1459          * determine whether the value is written successfully. */
1460 
1461         do
1462         {
1463             /* Enable Bit Timing register CBT, updating Timing Setting according to configuration structure. */
1464             base->CBT = CAN_CBT_BTF_MASK | CAN_CBT_EPRESDIV(pConfig->preDivider) | CAN_CBT_ERJW(pConfig->rJumpwidth) |
1465                         CAN_CBT_EPSEG1(pConfig->phaseSeg1) | CAN_CBT_EPSEG2(pConfig->phaseSeg2) |
1466                         CAN_CBT_EPROPSEG(pConfig->propSeg);
1467 
1468         } while ((CAN_CBT_EPRESDIV(pConfig->preDivider) | CAN_CBT_ERJW(pConfig->rJumpwidth) |
1469                   CAN_CBT_EPSEG1(pConfig->phaseSeg1) | CAN_CBT_EPSEG2(pConfig->phaseSeg2) |
1470                   CAN_CBT_EPROPSEG(pConfig->propSeg)) !=
1471                  (base->CBT & (CAN_CBT_EPRESDIV_MASK | CAN_CBT_ERJW_MASK | CAN_CBT_EPSEG1_MASK | CAN_CBT_EPSEG2_MASK |
1472                                CAN_CBT_EPROPSEG_MASK)));
1473 #endif
1474     }
1475     else
1476     {
1477         /* Cleaning previous Timing Setting. */
1478         base->CTRL1 &= ~(CAN_CTRL1_PRESDIV_MASK | CAN_CTRL1_RJW_MASK | CAN_CTRL1_PSEG1_MASK | CAN_CTRL1_PSEG2_MASK |
1479                          CAN_CTRL1_PROPSEG_MASK);
1480 
1481         /* Updating Timing Setting according to configuration structure. */
1482         base->CTRL1 |= (CAN_CTRL1_PRESDIV(pConfig->preDivider) | CAN_CTRL1_RJW(pConfig->rJumpwidth) |
1483                         CAN_CTRL1_PSEG1(pConfig->phaseSeg1) | CAN_CTRL1_PSEG2(pConfig->phaseSeg2) |
1484                         CAN_CTRL1_PROPSEG(pConfig->propSeg));
1485     }
1486 #else
1487     /* Cleaning previous Timing Setting. */
1488     base->CTRL1 &= ~(CAN_CTRL1_PRESDIV_MASK | CAN_CTRL1_RJW_MASK | CAN_CTRL1_PSEG1_MASK | CAN_CTRL1_PSEG2_MASK |
1489                      CAN_CTRL1_PROPSEG_MASK);
1490 
1491     /* Updating Timing Setting according to configuration structure. */
1492     base->CTRL1 |= (CAN_CTRL1_PRESDIV(pConfig->preDivider) | CAN_CTRL1_RJW(pConfig->rJumpwidth) |
1493                     CAN_CTRL1_PSEG1(pConfig->phaseSeg1) | CAN_CTRL1_PSEG2(pConfig->phaseSeg2) |
1494                     CAN_CTRL1_PROPSEG(pConfig->propSeg));
1495 #endif
1496 
1497     /* Exit Freeze Mode. */
1498     FLEXCAN_ExitFreezeMode(base);
1499 }
1500 
1501 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1502 /*!
1503  * brief Sets the FlexCAN FD data phase timing characteristic.
1504  *
1505  * This function gives user settings to CAN FD data phase timing characteristic.
1506  * The function is for an experienced user. For less experienced users, call the FLEXCAN_GetDefaultConfig()
1507  * and get the default timing characteristicsthe, then call FLEXCAN_FDInit() and fill the
1508  * data phase bit rate field.
1509  *
1510  * note Calling FLEXCAN_SetFDTimingConfig() overrides the bit rate set
1511  * in FLEXCAN_FDInit().
1512  *
1513  * param base FlexCAN peripheral base address.
1514  * param pConfig Pointer to the timing configuration structure.
1515  */
FLEXCAN_SetFDTimingConfig(CAN_Type * base,const flexcan_timing_config_t * pConfig)1516 void FLEXCAN_SetFDTimingConfig(CAN_Type *base, const flexcan_timing_config_t *pConfig)
1517 {
1518     /* Assertion. */
1519     assert(NULL != pConfig);
1520 
1521     /* Enter Freeze Mode. */
1522     FLEXCAN_EnterFreezeMode(base);
1523 
1524 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1525     /* Enable extended Bit Timing register EDCBT. */
1526     base->CTRL2 |= CAN_CTRL2_BTE_MASK;
1527 
1528     base->EPRS  = (base->EPRS & (~CAN_EPRS_EDPRESDIV_MASK)) | CAN_EPRS_EDPRESDIV(pConfig->fpreDivider);
1529     base->EDCBT = CAN_EDCBT_DRJW(pConfig->frJumpwidth) | CAN_EDCBT_DTSEG2(pConfig->fphaseSeg2) |
1530                   CAN_EDCBT_DTSEG1((uint32_t)pConfig->fphaseSeg1 + pConfig->fpropSeg);
1531 #else
1532     /* Enable Bit Timing register FDCBT,*/
1533     base->CBT |= CAN_CBT_BTF_MASK;
1534 
1535     /* On RT106x devices, a single write may be ignored, so it is necessary to read back the register value to determine
1536      * whether the value is written successfully. */
1537     do
1538     {
1539         /* Updating Timing Setting according to configuration structure. */
1540         base->FDCBT = (CAN_FDCBT_FPRESDIV(pConfig->fpreDivider) | CAN_FDCBT_FRJW(pConfig->frJumpwidth) |
1541                        CAN_FDCBT_FPSEG1(pConfig->fphaseSeg1) | CAN_FDCBT_FPSEG2(pConfig->fphaseSeg2) |
1542                        CAN_FDCBT_FPROPSEG(pConfig->fpropSeg));
1543     } while ((CAN_FDCBT_FPRESDIV(pConfig->fpreDivider) | CAN_FDCBT_FRJW(pConfig->frJumpwidth) |
1544               CAN_FDCBT_FPSEG1(pConfig->fphaseSeg1) | CAN_FDCBT_FPSEG2(pConfig->fphaseSeg2) |
1545               CAN_FDCBT_FPROPSEG(pConfig->fpropSeg)) !=
1546              (base->FDCBT & (CAN_FDCBT_FPRESDIV_MASK | CAN_FDCBT_FRJW_MASK | CAN_FDCBT_FPSEG1_MASK |
1547                              CAN_FDCBT_FPSEG2_MASK | CAN_FDCBT_FPROPSEG_MASK)));
1548 #endif
1549     /* Exit Freeze Mode. */
1550     FLEXCAN_ExitFreezeMode(base);
1551 }
1552 #endif
1553 
1554 /*!
1555  * brief Sets the FlexCAN receive message buffer global mask.
1556  *
1557  * This function sets the global mask for the FlexCAN message buffer in a matching process.
1558  * The configuration is only effective when the Rx individual mask is disabled in the FLEXCAN_Init().
1559  *
1560  * param base FlexCAN peripheral base address.
1561  * param mask Rx Message Buffer Global Mask value.
1562  */
FLEXCAN_SetRxMbGlobalMask(CAN_Type * base,uint32_t mask)1563 void FLEXCAN_SetRxMbGlobalMask(CAN_Type *base, uint32_t mask)
1564 {
1565     /* Enter Freeze Mode. */
1566     FLEXCAN_EnterFreezeMode(base);
1567 
1568     /* Setting Rx Message Buffer Global Mask value. */
1569     base->RXMGMASK = mask;
1570     base->RX14MASK = mask;
1571     base->RX15MASK = mask;
1572 
1573     /* Exit Freeze Mode. */
1574     FLEXCAN_ExitFreezeMode(base);
1575 }
1576 
1577 /*!
1578  * brief Sets the FlexCAN receive FIFO global mask.
1579  *
1580  * This function sets the global mask for FlexCAN FIFO in a matching process.
1581  *
1582  * param base FlexCAN peripheral base address.
1583  * param mask Rx Fifo Global Mask value.
1584  */
FLEXCAN_SetRxFifoGlobalMask(CAN_Type * base,uint32_t mask)1585 void FLEXCAN_SetRxFifoGlobalMask(CAN_Type *base, uint32_t mask)
1586 {
1587     /* Enter Freeze Mode. */
1588     FLEXCAN_EnterFreezeMode(base);
1589 
1590     /* Setting Rx FIFO Global Mask value. */
1591     base->RXFGMASK = mask;
1592 
1593     /* Exit Freeze Mode. */
1594     FLEXCAN_ExitFreezeMode(base);
1595 }
1596 
1597 /*!
1598  * brief Sets the FlexCAN receive individual mask.
1599  *
1600  * This function sets the individual mask for the FlexCAN matching process.
1601  * The configuration is only effective when the Rx individual mask is enabled in the FLEXCAN_Init().
1602  * If the Rx FIFO is disabled, the individual mask is applied to the corresponding Message Buffer.
1603  * If the Rx FIFO is enabled, the individual mask for Rx FIFO occupied Message Buffer is applied to
1604  * the Rx Filter with the same index. Note that only the first 32
1605  * individual masks can be used as the Rx FIFO filter mask.
1606  *
1607  * param base FlexCAN peripheral base address.
1608  * param maskIdx The Index of individual Mask.
1609  * param mask Rx Individual Mask value.
1610  */
FLEXCAN_SetRxIndividualMask(CAN_Type * base,uint8_t maskIdx,uint32_t mask)1611 void FLEXCAN_SetRxIndividualMask(CAN_Type *base, uint8_t maskIdx, uint32_t mask)
1612 {
1613     assert(maskIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
1614 
1615     /* Enter Freeze Mode. */
1616     FLEXCAN_EnterFreezeMode(base);
1617 
1618     /* Setting Rx Individual Mask value. */
1619     base->RXIMR[maskIdx] = mask;
1620 
1621     /* Exit Freeze Mode. */
1622     FLEXCAN_ExitFreezeMode(base);
1623 }
1624 
1625 /*!
1626  * brief Configures a FlexCAN transmit message buffer.
1627  *
1628  * This function aborts the previous transmission, cleans the Message Buffer, and
1629  * configures it as a Transmit Message Buffer.
1630  *
1631  * param base FlexCAN peripheral base address.
1632  * param mbIdx The Message Buffer index.
1633  * param enable Enable/disable Tx Message Buffer.
1634  *               - true: Enable Tx Message Buffer.
1635  *               - false: Disable Tx Message Buffer.
1636  */
FLEXCAN_SetTxMbConfig(CAN_Type * base,uint8_t mbIdx,bool enable)1637 void FLEXCAN_SetTxMbConfig(CAN_Type *base, uint8_t mbIdx, bool enable)
1638 {
1639     /* Assertion. */
1640     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
1641 #if !defined(NDEBUG)
1642     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
1643 #endif
1644 
1645     /* Inactivate Message Buffer. */
1646     if (enable)
1647     {
1648         base->MB[mbIdx].CS = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
1649     }
1650     else
1651     {
1652         base->MB[mbIdx].CS = 0;
1653     }
1654 
1655     /* Clean Message Buffer content. */
1656     base->MB[mbIdx].ID    = 0x0;
1657     base->MB[mbIdx].WORD0 = 0x0;
1658     base->MB[mbIdx].WORD1 = 0x0;
1659 }
1660 
1661 /*!
1662  * brief Calculates the segment values for a single bit time for classical CAN.
1663  *
1664  * This function use to calculates the Classical CAN segment values which will be set in CTRL1/CBT/ENCBT register.
1665  *
1666  * param bitRate The classical CAN bit rate in bps.
1667  * param base FlexCAN peripheral base address.
1668  * param tqNum Number of time quantas per bit, range in 8 ~ 25 when use CTRL1, range in 8 ~ 129 when use CBT, range in
1669  *             8 ~ 385 when use ENCBT. param pTimingConfig Pointer to the FlexCAN timing configuration structure.
1670  */
FLEXCAN_GetSegments(CAN_Type * base,uint32_t bitRate,uint32_t tqNum,flexcan_timing_config_t * pTimingConfig)1671 static void FLEXCAN_GetSegments(CAN_Type *base,
1672                                 uint32_t bitRate,
1673                                 uint32_t tqNum,
1674                                 flexcan_timing_config_t *pTimingConfig)
1675 {
1676     uint32_t ideal_sp;
1677     uint32_t seg1Max, proSegMax;
1678     uint32_t seg1Temp;
1679 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1680     if (0 != FSL_FEATURE_FLEXCAN_INSTANCE_HAS_FLEXIBLE_DATA_RATEn(base))
1681     {
1682 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1683         /* Maximum value allowed in ENCBT register. */
1684         seg1Max   = MAX_NTSEG2 + 1U;
1685         proSegMax = MAX_NTSEG1 - MAX_NTSEG2;
1686 #else
1687         /* Maximum value allowed in CBT register. */
1688         seg1Max = MAX_EPSEG1 + 1U;
1689         proSegMax = MAX_EPROPSEG + 1U;
1690 #endif
1691     }
1692     else
1693     {
1694         /* Maximum value allowed in CTRL1 register. */
1695         seg1Max   = MAX_PSEG1 + 1U;
1696         proSegMax = MAX_PROPSEG + 1U;
1697     }
1698 #else
1699     /* Maximum value allowed in CTRL1 register. */
1700     seg1Max   = MAX_PSEG1 + 1U;
1701     proSegMax = MAX_PROPSEG + 1U;
1702 #endif
1703 
1704     /* Try to find the ideal sample point, according to CiA 301 doc.*/
1705     if (bitRate == 1000000U)
1706     {
1707         ideal_sp = IDEAL_SP_LOW;
1708     }
1709     else if (bitRate >= 800000U)
1710     {
1711         ideal_sp = IDEAL_SP_MID;
1712     }
1713     else
1714     {
1715         ideal_sp = IDEAL_SP_HIGH;
1716     }
1717     /* Calculates phaseSeg2. */
1718     pTimingConfig->phaseSeg2 = (uint8_t)(tqNum - (tqNum * ideal_sp) / (uint32_t)IDEAL_SP_FACTOR);
1719     if (pTimingConfig->phaseSeg2 < MIN_TIME_SEGMENT2)
1720     {
1721         pTimingConfig->phaseSeg2 = MIN_TIME_SEGMENT2;
1722     }
1723 
1724 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1725     if (0 != FSL_FEATURE_FLEXCAN_INSTANCE_HAS_FLEXIBLE_DATA_RATEn(base))
1726     {
1727 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1728         if (pTimingConfig->phaseSeg2 > (uint8_t)(MAX_EPSEG2 + 1U))
1729         {
1730             pTimingConfig->phaseSeg2 = (uint8_t)(MAX_EPSEG2 + 1U);
1731         }
1732 #endif
1733     }
1734 #endif
1735 
1736     /* Calculates phaseSeg1 and propSeg and try to make phaseSeg1 equal to phaseSeg2. */
1737     if ((tqNum - pTimingConfig->phaseSeg2 - 1U) > (seg1Max + proSegMax))
1738     {
1739         seg1Temp                 = seg1Max + proSegMax;
1740         pTimingConfig->phaseSeg2 = (uint8_t)(tqNum - 1U - seg1Temp);
1741     }
1742     else
1743     {
1744         seg1Temp = tqNum - pTimingConfig->phaseSeg2 - 1U;
1745     }
1746     if (seg1Temp > (pTimingConfig->phaseSeg2 + proSegMax))
1747     {
1748         pTimingConfig->propSeg   = (uint8_t)proSegMax;
1749         pTimingConfig->phaseSeg1 = (uint8_t)(seg1Temp - proSegMax);
1750     }
1751     else
1752     {
1753         pTimingConfig->propSeg   = (uint8_t)(seg1Temp - pTimingConfig->phaseSeg2);
1754         pTimingConfig->phaseSeg1 = pTimingConfig->phaseSeg2;
1755     }
1756 
1757     /* rJumpwidth (sjw) is the minimum value of phaseSeg1 and phaseSeg2. */
1758     pTimingConfig->rJumpwidth =
1759         (pTimingConfig->phaseSeg1 > pTimingConfig->phaseSeg2) ? pTimingConfig->phaseSeg2 : pTimingConfig->phaseSeg1;
1760 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1761     if (pTimingConfig->rJumpwidth > (MAX_RJW + 1U))
1762     {
1763         pTimingConfig->rJumpwidth = (uint8_t)(MAX_RJW + 1U);
1764     }
1765 #else
1766     if (0 == FSL_FEATURE_FLEXCAN_INSTANCE_HAS_FLEXIBLE_DATA_RATEn(base))
1767     {
1768         if (pTimingConfig->rJumpwidth > (MAX_RJW + 1U))
1769         {
1770             pTimingConfig->rJumpwidth = (uint8_t)(MAX_RJW + 1U);
1771         }
1772     }
1773 #endif
1774 
1775     pTimingConfig->phaseSeg1 -= 1U;
1776     pTimingConfig->phaseSeg2 -= 1U;
1777     pTimingConfig->propSeg -= 1U;
1778     pTimingConfig->rJumpwidth -= 1U;
1779 }
1780 
1781 /*!
1782  * brief Calculates the improved timing values by specific bit Rates for classical CAN.
1783  *
1784  * This function use to calculates the Classical CAN timing values according to the given bit rate. The Calculated
1785  * timing values will be set in CTRL1/CBT/ENCBT register. The calculation is based on the recommendation of the CiA 301
1786  * v4.2.0 and previous version document.
1787  *
1788  * param base FlexCAN peripheral base address.
1789  * param bitRate  The classical CAN speed in bps defined by user, should be less than or equal to 1Mbps.
1790  * param sourceClock_Hz The Source clock frequency in Hz.
1791  * param pTimingConfig Pointer to the FlexCAN timing configuration structure.
1792  *
1793  * return TRUE if timing configuration found, FALSE if failed to find configuration.
1794  */
FLEXCAN_CalculateImprovedTimingValues(CAN_Type * base,uint32_t bitRate,uint32_t sourceClock_Hz,flexcan_timing_config_t * pTimingConfig)1795 bool FLEXCAN_CalculateImprovedTimingValues(CAN_Type *base,
1796                                            uint32_t bitRate,
1797                                            uint32_t sourceClock_Hz,
1798                                            flexcan_timing_config_t *pTimingConfig)
1799 {
1800     /* Observe bit rate maximums. */
1801     assert(bitRate <= MAX_CAN_BITRATE);
1802 
1803     uint32_t clk;
1804     uint32_t tqNum, tqMin, pdivMAX;
1805     uint32_t spTemp                    = 1000U;
1806     flexcan_timing_config_t configTemp = {0};
1807     bool fgRet                         = false;
1808 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1809     if (0 != FSL_FEATURE_FLEXCAN_INSTANCE_HAS_FLEXIBLE_DATA_RATEn(base))
1810     {
1811 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1812         /*  Auto Improved Protocal timing for ENCBT. */
1813         tqNum   = ENCBT_MAX_TIME_QUANTA;
1814         tqMin   = ENCBT_MIN_TIME_QUANTA;
1815         pdivMAX = MAX_ENPRESDIV;
1816 #else
1817         /*  Auto Improved Protocal timing for CBT. */
1818         tqNum = CBT_MAX_TIME_QUANTA;
1819         tqMin = CBT_MIN_TIME_QUANTA;
1820         pdivMAX = MAX_PRESDIV;
1821 #endif
1822     }
1823     else
1824     {
1825         /*  Auto Improved Protocal timing for CTRL1. */
1826         tqNum   = CTRL1_MAX_TIME_QUANTA;
1827         tqMin   = CTRL1_MIN_TIME_QUANTA;
1828         pdivMAX = MAX_PRESDIV;
1829     }
1830 #else
1831     /*  Auto Improved Protocal timing for CTRL1. */
1832     tqNum   = CTRL1_MAX_TIME_QUANTA;
1833     tqMin   = CTRL1_MIN_TIME_QUANTA;
1834     pdivMAX = MAX_PRESDIV;
1835 #endif
1836     do
1837     {
1838         clk = bitRate * tqNum;
1839         if (clk > sourceClock_Hz)
1840         {
1841             continue; /* tqNum too large, clk has been exceed sourceClock_Hz. */
1842         }
1843 
1844         if ((sourceClock_Hz / clk * clk) != sourceClock_Hz)
1845         {
1846             continue; /* Non-supporting: the frequency of clock source is not divisible by target bit rate, the user
1847                       should change a divisible bit rate. */
1848         }
1849 
1850         configTemp.preDivider = (uint16_t)(sourceClock_Hz / clk) - 1U;
1851         if (configTemp.preDivider > pdivMAX)
1852         {
1853             break; /* The frequency of source clock is too large or the bit rate is too small, the pre-divider could
1854                       not handle it. */
1855         }
1856 
1857         /* Calculates the best timing configuration under current tqNum. */
1858         FLEXCAN_GetSegments(base, bitRate, tqNum, &configTemp);
1859         /* Determine whether the calculated timing configuration can get the optimal sampling point. */
1860         if (((((uint32_t)configTemp.phaseSeg2 + 1U) * 1000U) / tqNum) < spTemp)
1861         {
1862             spTemp                    = (((uint32_t)configTemp.phaseSeg2 + 1U) * 1000U) / tqNum;
1863             pTimingConfig->preDivider = configTemp.preDivider;
1864             pTimingConfig->rJumpwidth = configTemp.rJumpwidth;
1865             pTimingConfig->phaseSeg1  = configTemp.phaseSeg1;
1866             pTimingConfig->phaseSeg2  = configTemp.phaseSeg2;
1867             pTimingConfig->propSeg    = configTemp.propSeg;
1868         }
1869         fgRet = true;
1870     } while (--tqNum >= tqMin);
1871 
1872     return fgRet;
1873 }
1874 
1875 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
1876 /*!
1877  * brief Get Mailbox offset number by dword.
1878  *
1879  * This function gets the offset number of the specified mailbox.
1880  * Mailbox is not consecutive between memory regions when payload is not 8 bytes
1881  * so need to calculate the specified mailbox address.
1882  * For example, in the first memory region, MB[0].CS address is 0x4002_4080. For 32 bytes
1883  * payload frame, the second mailbox is ((1/12)*512 + 1%12*40)/4 = 10, meaning 10 dword
1884  * after the 0x4002_4080, which is actually the address of mailbox MB[1].CS.
1885  *
1886  * param base FlexCAN peripheral base address.
1887  * param mbIdx Mailbox index.
1888  */
FLEXCAN_GetFDMailboxOffset(CAN_Type * base,uint8_t mbIdx)1889 static uint32_t FLEXCAN_GetFDMailboxOffset(CAN_Type *base, uint8_t mbIdx)
1890 {
1891     uint32_t offset   = 0;
1892     uint32_t dataSize = (base->FDCTRL & CAN_FDCTRL_MBDSR0_MASK) >> CAN_FDCTRL_MBDSR0_SHIFT;
1893     if (dataSize == (uint32_t)kFLEXCAN_8BperMB)
1894     {
1895         offset = (((uint32_t)mbIdx / 32U) * 512U + ((uint32_t)mbIdx % 32U) * 16U);
1896     }
1897     else if (dataSize == (uint32_t)kFLEXCAN_16BperMB)
1898     {
1899         offset = (((uint32_t)mbIdx / 21U) * 512U + ((uint32_t)mbIdx % 21U) * 24U);
1900     }
1901     else if (dataSize == (uint32_t)kFLEXCAN_32BperMB)
1902     {
1903         offset = (((uint32_t)mbIdx / 12U) * 512U + ((uint32_t)mbIdx % 12U) * 40U);
1904     }
1905     else
1906     {
1907         offset = (((uint32_t)mbIdx / 7U) * 512U + ((uint32_t)mbIdx % 7U) * 72U);
1908     }
1909 
1910     /* To get the dword aligned offset, need to divide by 4. */
1911     offset = offset / 4U;
1912     return offset;
1913 }
1914 
1915 /*!
1916  * brief Calculates the segment values for a single bit time for CAN FD data phase.
1917  *
1918  * This function use to calculates the CAN FD data phase segment values which will be set in CFDCBT/EDCBT
1919  * register.
1920  *
1921  * param bitRateFD CAN FD data phase bit rate.
1922  * param tqNum Number of time quanta per bit
1923  * param pTimingConfig Pointer to the FlexCAN timing configuration structure.
1924  */
FLEXCAN_FDGetSegments(uint32_t bitRateFD,uint32_t tqNum,flexcan_timing_config_t * pTimingConfig)1925 static void FLEXCAN_FDGetSegments(uint32_t bitRateFD, uint32_t tqNum, flexcan_timing_config_t *pTimingConfig)
1926 {
1927     uint32_t ideal_sp;
1928     uint32_t seg1Max, proSegMax, seg2Max;
1929     uint32_t seg1Temp;
1930 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
1931     /* Maximum value allowed in EDCBT register. */
1932     seg1Max   = MAX_DTSEG2 + 1U;
1933     proSegMax = MAX_DTSEG1 - MAX_DTSEG2;
1934     seg2Max   = MAX_DTSEG2 + 1U;
1935 #else
1936     /* Maximum value allowed in FDCBT register. */
1937     seg1Max = MAX_FPSEG1 + 1U;
1938     proSegMax = MAX_FPROPSEG;
1939     seg2Max = MAX_FPSEG2 + 1U;
1940 #endif
1941 
1942     /* According to CiA doc 1301 v1.0.0, which specified data phase sample point postion for CAN FD at 80 MHz. */
1943     if (bitRateFD <= 1000000U)
1944     {
1945         ideal_sp = IDEAL_DATA_SP_1;
1946     }
1947     else if (bitRateFD <= 2000000U)
1948     {
1949         ideal_sp = IDEAL_DATA_SP_2;
1950     }
1951     else if (bitRateFD <= 4000000U)
1952     {
1953         ideal_sp = IDEAL_DATA_SP_3;
1954     }
1955     else
1956     {
1957         ideal_sp = IDEAL_DATA_SP_4;
1958     }
1959 
1960     /* Calculates fphaseSeg2. */
1961     pTimingConfig->fphaseSeg2 = (uint8_t)(tqNum - (tqNum * ideal_sp) / (uint32_t)IDEAL_SP_FACTOR);
1962     if (pTimingConfig->fphaseSeg2 < MIN_TIME_SEGMENT2)
1963     {
1964         pTimingConfig->fphaseSeg2 = MIN_TIME_SEGMENT2;
1965     }
1966     else if (pTimingConfig->fphaseSeg2 > seg2Max)
1967     {
1968         pTimingConfig->fphaseSeg2 = (uint8_t)seg2Max;
1969     }
1970     else
1971     {
1972         ; /* Intentional empty */
1973     }
1974 
1975     /* Calculates fphaseSeg1 and fpropSeg and try to make phaseSeg1 equal to phaseSeg2 */
1976     if ((tqNum - pTimingConfig->fphaseSeg2 - 1U) > (seg1Max + proSegMax))
1977     {
1978         seg1Temp                  = seg1Max + proSegMax;
1979         pTimingConfig->fphaseSeg2 = (uint8_t)(tqNum - 1U - seg1Temp);
1980     }
1981     else
1982     {
1983         seg1Temp = tqNum - pTimingConfig->fphaseSeg2 - 1U;
1984     }
1985     if (seg1Temp > (pTimingConfig->fphaseSeg2 + proSegMax))
1986     {
1987         pTimingConfig->fpropSeg   = (uint8_t)proSegMax;
1988         pTimingConfig->fphaseSeg1 = (uint8_t)(seg1Temp - proSegMax);
1989     }
1990     else if (seg1Temp > pTimingConfig->fphaseSeg2)
1991     {
1992         pTimingConfig->fpropSeg   = (uint8_t)(seg1Temp - pTimingConfig->fphaseSeg2);
1993         pTimingConfig->fphaseSeg1 = pTimingConfig->fphaseSeg2;
1994     }
1995     else
1996     {
1997         pTimingConfig->fpropSeg   = 0U;
1998         pTimingConfig->fphaseSeg1 = (uint8_t)seg1Temp;
1999     }
2000 
2001     /* rJumpwidth (sjw) is the minimum value of phaseSeg1 and phaseSeg2. */
2002     pTimingConfig->frJumpwidth =
2003         (pTimingConfig->fphaseSeg1 > pTimingConfig->fphaseSeg2) ? pTimingConfig->fphaseSeg2 : pTimingConfig->fphaseSeg1;
2004 
2005     pTimingConfig->fphaseSeg1 -= 1U;
2006     pTimingConfig->fphaseSeg2 -= 1U;
2007     pTimingConfig->frJumpwidth -= 1U;
2008 }
2009 
2010 /*!
2011  * brief Calculates the improved timing values by specific bit rate for CAN FD nominal phase.
2012  *
2013  * This function use to calculates the CAN FD nominal phase timing values according to the given nominal phase bit rate.
2014  * The Calculated timing values will be set in CBT/ENCBT registers. The calculation is based on the recommendation of
2015  * the CiA 1301 v1.0.0 document.
2016  *
2017  * param bitRate  The CAN FD nominal phase speed in bps defined by user, should be less than or equal to 1Mbps.
2018  * param sourceClock_Hz The Source clock frequency in Hz.
2019  * param pTimingConfig Pointer to the FlexCAN timing configuration structure.
2020  *
2021  * return TRUE if timing configuration found, FALSE if failed to find configuration.
2022  */
FLEXCAN_CalculateImprovedNominalTimingValues(uint32_t bitRate,uint32_t sourceClock_Hz,flexcan_timing_config_t * pTimingConfig)2023 static bool FLEXCAN_CalculateImprovedNominalTimingValues(uint32_t bitRate,
2024                                                          uint32_t sourceClock_Hz,
2025                                                          flexcan_timing_config_t *pTimingConfig)
2026 {
2027     /* Observe bit rate maximums. */
2028     assert(bitRate <= MAX_CAN_BITRATE);
2029 
2030     uint32_t clk;
2031     uint32_t tqNum, tqMin, pdivMAX, seg1Max, proSegMax, seg1Temp;
2032     uint32_t spTemp                    = 1000U;
2033     flexcan_timing_config_t configTemp = {0};
2034     bool fgRet                         = false;
2035 
2036 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
2037     /*  Auto Improved Protocal timing for ENCBT. */
2038     tqNum     = ENCBT_MAX_TIME_QUANTA;
2039     tqMin     = ENCBT_MIN_TIME_QUANTA;
2040     pdivMAX   = MAX_ENPRESDIV;
2041     seg1Max   = MAX_NTSEG2 + 1U;
2042     proSegMax = MAX_NTSEG1 - MAX_NTSEG2;
2043 #else
2044     /*  Auto Improved Protocal timing for CBT. */
2045     tqNum = CBT_MAX_TIME_QUANTA;
2046     tqMin = CBT_MIN_TIME_QUANTA;
2047     pdivMAX = MAX_PRESDIV;
2048     seg1Max = MAX_EPSEG1 + 1U;
2049     proSegMax = MAX_EPROPSEG + 1U;
2050 #endif
2051 
2052     do
2053     {
2054         clk = bitRate * tqNum;
2055         if (clk > sourceClock_Hz)
2056         {
2057             continue; /* tqNum too large, clk has been exceed sourceClock_Hz. */
2058         }
2059 
2060         if ((sourceClock_Hz / clk * clk) != sourceClock_Hz)
2061         {
2062             continue; /* Non-supporting: the frequency of clock source is not divisible by target bit rate, the user
2063                       should change a divisible bit rate. */
2064         }
2065 
2066         configTemp.preDivider = (uint16_t)(sourceClock_Hz / clk) - 1U;
2067         if (configTemp.preDivider > pdivMAX)
2068         {
2069             break; /* The frequency of source clock is too large or the bit rate is too small, the pre-divider could
2070                       not handle it. */
2071         }
2072 
2073         /* Calculates the best timing configuration under current tqNum. */
2074         configTemp.phaseSeg2 = (uint8_t)(tqNum - (tqNum * IDEAL_NOMINAL_SP) / (uint32_t)IDEAL_SP_FACTOR);
2075 
2076         /* Calculates phaseSeg1 and propSeg and try to make phaseSeg1 equal to phaseSeg2. */
2077         if ((tqNum - configTemp.phaseSeg2 - 1U) > (seg1Max + proSegMax))
2078         {
2079             seg1Temp             = seg1Max + proSegMax;
2080             configTemp.phaseSeg2 = (uint8_t)(tqNum - 1U - seg1Temp);
2081         }
2082         else
2083         {
2084             seg1Temp = tqNum - configTemp.phaseSeg2 - 1U;
2085         }
2086         if (seg1Temp > (configTemp.phaseSeg2 + proSegMax))
2087         {
2088             configTemp.propSeg   = (uint8_t)proSegMax;
2089             configTemp.phaseSeg1 = (uint8_t)(seg1Temp - proSegMax);
2090         }
2091         else
2092         {
2093             configTemp.propSeg   = (uint8_t)(seg1Temp - configTemp.phaseSeg2);
2094             configTemp.phaseSeg1 = configTemp.phaseSeg2;
2095         }
2096 
2097         /* rJumpwidth (sjw) is the minimum value of phaseSeg1 and phaseSeg2. */
2098         configTemp.rJumpwidth =
2099             (configTemp.phaseSeg1 > configTemp.phaseSeg2) ? configTemp.phaseSeg2 : configTemp.phaseSeg1;
2100         configTemp.phaseSeg1 -= 1U;
2101         configTemp.phaseSeg2 -= 1U;
2102         configTemp.propSeg -= 1U;
2103         configTemp.rJumpwidth -= 1U;
2104 
2105         if (((((uint32_t)configTemp.phaseSeg2 + 1U) * 1000U) / tqNum) < spTemp)
2106         {
2107             spTemp                    = (((uint32_t)configTemp.phaseSeg2 + 1U) * 1000U) / tqNum;
2108             pTimingConfig->preDivider = configTemp.preDivider;
2109             pTimingConfig->rJumpwidth = configTemp.rJumpwidth;
2110             pTimingConfig->phaseSeg1  = configTemp.phaseSeg1;
2111             pTimingConfig->phaseSeg2  = configTemp.phaseSeg2;
2112             pTimingConfig->propSeg    = configTemp.propSeg;
2113         }
2114         fgRet = true;
2115     } while (--tqNum >= tqMin);
2116 
2117     return fgRet;
2118 }
2119 
2120 /*!
2121  * brief Calculates the improved timing values by specific bit rates for CAN FD.
2122  *
2123  * This function use to calculates the CAN FD timing values according to the given nominal phase bit rate and data phase
2124  * bit rate. The Calculated timing values will be set in CBT/ENCBT and FDCBT/EDCBT registers. The calculation is based
2125  * on the recommendation of the CiA 1301 v1.0.0 document.
2126  *
2127  * param bitRate  The CAN FD nominal phase speed in bps defined by user.
2128  * param bitRateFD  The CAN FD data phase speed in bps defined by user. Equal to bitRate means disable bit rate
2129  * switching. param sourceClock_Hz The Source clock frequency in Hz. param pTimingConfig Pointer to the FlexCAN timing
2130  * configuration structure.
2131  *
2132  * return TRUE if timing configuration found, FALSE if failed to find configuration
2133  */
FLEXCAN_FDCalculateImprovedTimingValues(CAN_Type * base,uint32_t bitRate,uint32_t bitRateFD,uint32_t sourceClock_Hz,flexcan_timing_config_t * pTimingConfig)2134 bool FLEXCAN_FDCalculateImprovedTimingValues(CAN_Type *base,
2135                                              uint32_t bitRate,
2136                                              uint32_t bitRateFD,
2137                                              uint32_t sourceClock_Hz,
2138                                              flexcan_timing_config_t *pTimingConfig)
2139 {
2140     /* Observe bit rate maximums */
2141     assert(bitRate <= MAX_CANFD_BITRATE);
2142     assert(bitRateFD <= MAX_CANFD_BITRATE);
2143     /* Data phase bit rate need greater or equal to nominal phase bit rate. */
2144     assert(bitRate <= bitRateFD);
2145 
2146     uint32_t clk;
2147     uint32_t tqMin, pdivMAX, tqTemp;
2148     bool fgRet = false;
2149 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG)
2150     /*  Auto Improved Protocal timing for EDCBT. */
2151     tqTemp  = EDCBT_MAX_TIME_QUANTA;
2152     tqMin   = EDCBT_MIN_TIME_QUANTA;
2153     pdivMAX = MAX_EDPRESDIV;
2154 #else
2155     /*  Auto Improved Protocal timing for FDCBT. */
2156     tqTemp = FDCBT_MAX_TIME_QUANTA;
2157     tqMin = FDCBT_MIN_TIME_QUANTA;
2158     pdivMAX = MAX_FPRESDIV;
2159 #endif
2160 
2161     if (bitRate != bitRateFD)
2162     {
2163         /* To minimize errors when processing FD frames, try to get the same bit rate prescaler value for nominal phase
2164            and data phase. */
2165         do
2166         {
2167             clk = bitRateFD * tqTemp;
2168             if (clk > sourceClock_Hz)
2169             {
2170                 continue; /* tqTemp too large, clk x tqTemp has been exceed sourceClock_Hz. */
2171             }
2172 
2173             if ((sourceClock_Hz / clk * clk) != sourceClock_Hz)
2174             {
2175                 continue; /*  the frequency of clock source is not divisible by target bit rate. */
2176             }
2177 
2178             pTimingConfig->fpreDivider = (uint16_t)(sourceClock_Hz / clk) - 1U;
2179 
2180             if (pTimingConfig->fpreDivider > pdivMAX)
2181             {
2182                 break; /* The frequency of source clock is too large or the bit rate is too small, the pre-divider
2183                           could not handle it. */
2184             }
2185 
2186             /* Calculates the best data phase timing configuration. */
2187             FLEXCAN_FDGetSegments(bitRateFD, tqTemp, pTimingConfig);
2188 
2189             if (FLEXCAN_CalculateImprovedNominalTimingValues(
2190                     bitRate, sourceClock_Hz / ((uint32_t)pTimingConfig->fpreDivider + 1U), pTimingConfig))
2191             {
2192                 fgRet = true;
2193                 if (pTimingConfig->preDivider == 0U)
2194                 {
2195                     pTimingConfig->preDivider = pTimingConfig->fpreDivider;
2196                     break;
2197                 }
2198                 else
2199                 {
2200                     pTimingConfig->preDivider =
2201                         (pTimingConfig->preDivider + 1U) * (pTimingConfig->fpreDivider + 1U) - 1U;
2202                     continue;
2203                 }
2204             }
2205         } while (--tqTemp >= tqMin);
2206     }
2207     else
2208     {
2209         if (FLEXCAN_CalculateImprovedNominalTimingValues(bitRate, sourceClock_Hz, pTimingConfig))
2210         {
2211             /* No need data phase timing configuration, data phase rate equal to nominal phase rate, user don't use Brs
2212                feature. */
2213             pTimingConfig->fpreDivider = 0U;
2214             pTimingConfig->frJumpwidth = 0U;
2215             pTimingConfig->fphaseSeg1  = 0U;
2216             pTimingConfig->fphaseSeg2  = 0U;
2217             pTimingConfig->fpropSeg    = 0U;
2218             fgRet                      = true;
2219         }
2220     }
2221     return fgRet;
2222 }
2223 
2224 /*!
2225  * brief Configures a FlexCAN transmit message buffer.
2226  *
2227  * This function aborts the previous transmission, cleans the Message Buffer, and
2228  * configures it as a Transmit Message Buffer.
2229  *
2230  * param base FlexCAN peripheral base address.
2231  * param mbIdx The Message Buffer index.
2232  * param enable Enable/disable Tx Message Buffer.
2233  *               - true: Enable Tx Message Buffer.
2234  *               - false: Disable Tx Message Buffer.
2235  */
FLEXCAN_SetFDTxMbConfig(CAN_Type * base,uint8_t mbIdx,bool enable)2236 void FLEXCAN_SetFDTxMbConfig(CAN_Type *base, uint8_t mbIdx, bool enable)
2237 {
2238     /* Assertion. */
2239     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
2240 #if !defined(NDEBUG)
2241     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
2242 #endif
2243 
2244     uint8_t cnt           = 0;
2245     uint8_t payload_dword = 1;
2246     uint32_t dataSize;
2247     dataSize                  = (base->FDCTRL & CAN_FDCTRL_MBDSR0_MASK) >> CAN_FDCTRL_MBDSR0_SHIFT;
2248     volatile uint32_t *mbAddr = &(base->MB[0].CS);
2249     uint32_t offset           = FLEXCAN_GetFDMailboxOffset(base, mbIdx);
2250 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
2251      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
2252     uint32_t availoffset = FLEXCAN_GetFDMailboxOffset(base, FLEXCAN_GetFirstValidMb(base));
2253 #endif
2254 
2255     /* Inactivate Message Buffer. */
2256     if (enable)
2257     {
2258         /* Inactivate by writing CS. */
2259         mbAddr[offset] = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
2260     }
2261     else
2262     {
2263         mbAddr[offset] = 0x0;
2264     }
2265 
2266     /* Calculate the DWORD number, dataSize 0/1/2/3 corresponds to 8/16/32/64
2267        Bytes payload. */
2268     for (cnt = 0; cnt < (dataSize + 1U); cnt++)
2269     {
2270         payload_dword *= 2U;
2271     }
2272 
2273     /* Clean ID. */
2274     mbAddr[offset + 1U] = 0x0U;
2275     /* Clean Message Buffer content, DWORD by DWORD. */
2276     for (cnt = 0; cnt < payload_dword; cnt++)
2277     {
2278         mbAddr[offset + 2U + cnt] = 0x0U;
2279     }
2280 
2281 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
2282      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
2283     mbAddr[availoffset] = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
2284 #endif
2285 }
2286 #endif /* FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE */
2287 
2288 /*!
2289  * brief Configures a FlexCAN Receive Message Buffer.
2290  *
2291  * This function cleans a FlexCAN build-in Message Buffer and configures it
2292  * as a Receive Message Buffer.
2293  *
2294  * param base FlexCAN peripheral base address.
2295  * param mbIdx The Message Buffer index.
2296  * param pRxMbConfig Pointer to the FlexCAN Message Buffer configuration structure.
2297  * param enable Enable/disable Rx Message Buffer.
2298  *               - true: Enable Rx Message Buffer.
2299  *               - false: Disable Rx Message Buffer.
2300  */
FLEXCAN_SetRxMbConfig(CAN_Type * base,uint8_t mbIdx,const flexcan_rx_mb_config_t * pRxMbConfig,bool enable)2301 void FLEXCAN_SetRxMbConfig(CAN_Type *base, uint8_t mbIdx, const flexcan_rx_mb_config_t *pRxMbConfig, bool enable)
2302 {
2303     /* Assertion. */
2304     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
2305     assert(((NULL != pRxMbConfig) || (false == enable)));
2306 #if !defined(NDEBUG)
2307     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
2308 #endif
2309 
2310     uint32_t cs_temp = 0;
2311 
2312     /* Inactivate Message Buffer. */
2313     base->MB[mbIdx].CS = 0;
2314 
2315     /* Clean Message Buffer content. */
2316     base->MB[mbIdx].ID    = 0x0;
2317     base->MB[mbIdx].WORD0 = 0x0;
2318     base->MB[mbIdx].WORD1 = 0x0;
2319 
2320     if (enable)
2321     {
2322         /* Setup Message Buffer ID. */
2323         base->MB[mbIdx].ID = pRxMbConfig->id;
2324 
2325         /* Setup Message Buffer format. */
2326         if (kFLEXCAN_FrameFormatExtend == pRxMbConfig->format)
2327         {
2328             cs_temp |= CAN_CS_IDE_MASK;
2329         }
2330 
2331         /* Setup Message Buffer type. */
2332         if (kFLEXCAN_FrameTypeRemote == pRxMbConfig->type)
2333         {
2334             cs_temp |= CAN_CS_RTR_MASK;
2335         }
2336 
2337         /* Activate Rx Message Buffer. */
2338         cs_temp |= CAN_CS_CODE(kFLEXCAN_RxMbEmpty);
2339         base->MB[mbIdx].CS = cs_temp;
2340     }
2341 }
2342 
2343 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
2344 /*!
2345  * brief Configures a FlexCAN Receive Message Buffer.
2346  *
2347  * This function cleans a FlexCAN build-in Message Buffer and configures it
2348  * as a Receive Message Buffer.
2349  *
2350  * param base FlexCAN peripheral base address.
2351  * param mbIdx The Message Buffer index.
2352  * param pRxMbConfig Pointer to the FlexCAN Message Buffer configuration structure.
2353  * param enable Enable/disable Rx Message Buffer.
2354  *               - true: Enable Rx Message Buffer.
2355  *               - false: Disable Rx Message Buffer.
2356  */
FLEXCAN_SetFDRxMbConfig(CAN_Type * base,uint8_t mbIdx,const flexcan_rx_mb_config_t * pRxMbConfig,bool enable)2357 void FLEXCAN_SetFDRxMbConfig(CAN_Type *base, uint8_t mbIdx, const flexcan_rx_mb_config_t *pRxMbConfig, bool enable)
2358 {
2359     /* Assertion. */
2360     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
2361     assert(((NULL != pRxMbConfig) || (false == enable)));
2362 #if !defined(NDEBUG)
2363     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
2364 #endif
2365 
2366     uint32_t cs_temp          = 0;
2367     uint8_t cnt               = 0;
2368     volatile uint32_t *mbAddr = &(base->MB[0].CS);
2369     uint32_t offset           = FLEXCAN_GetFDMailboxOffset(base, mbIdx);
2370     uint8_t payload_dword;
2371     uint32_t dataSize = (base->FDCTRL & CAN_FDCTRL_MBDSR0_MASK) >> CAN_FDCTRL_MBDSR0_SHIFT;
2372 
2373     /* Inactivate Message Buffer. */
2374     mbAddr[offset] = 0U;
2375 
2376     /* Clean Message Buffer content. */
2377     mbAddr[offset + 1U] = 0U;
2378     /* Calculate the DWORD number, dataSize 0/1/2/3 corresponds to 8/16/32/64
2379        Bytes payload. */
2380     payload_dword = (2U << dataSize);
2381     for (cnt = 0; cnt < payload_dword; cnt++)
2382     {
2383         mbAddr[offset + 2U + cnt] = 0x0;
2384     }
2385 
2386     if (enable)
2387     {
2388         /* Setup Message Buffer ID. */
2389         mbAddr[offset + 1U] = pRxMbConfig->id;
2390 
2391         /* Setup Message Buffer format. */
2392         if (kFLEXCAN_FrameFormatExtend == pRxMbConfig->format)
2393         {
2394             cs_temp |= CAN_CS_IDE_MASK;
2395         }
2396 
2397         /* Setup Message Buffer type. */
2398         if (kFLEXCAN_FrameTypeRemote == pRxMbConfig->type)
2399         {
2400             cs_temp |= CAN_CS_RTR_MASK;
2401         }
2402 
2403         /* Activate Rx Message Buffer. */
2404         cs_temp |= CAN_CS_CODE(kFLEXCAN_RxMbEmpty);
2405         mbAddr[offset] = cs_temp;
2406     }
2407 }
2408 #endif
2409 
2410 /*!
2411  * brief Configures the FlexCAN Legacy Rx FIFO.
2412  *
2413  * This function configures the FlexCAN Rx FIFO with given configuration.
2414  * note Legacy Rx FIFO only can receive classic CAN message.
2415  *
2416  * param base FlexCAN peripheral base address.
2417  * param pRxFifoConfig Pointer to the FlexCAN Legacy Rx FIFO configuration structure. Can be NULL when enable parameter
2418  *                      is false.
2419  * param enable Enable/disable Legacy Rx FIFO.
2420  *              - true: Enable Legacy Rx FIFO.
2421  *              - false: Disable Legacy Rx FIFO.
2422  */
FLEXCAN_SetRxFifoConfig(CAN_Type * base,const flexcan_rx_fifo_config_t * pRxFifoConfig,bool enable)2423 void FLEXCAN_SetRxFifoConfig(CAN_Type *base, const flexcan_rx_fifo_config_t *pRxFifoConfig, bool enable)
2424 {
2425     /* Assertion. */
2426     assert((NULL != pRxFifoConfig) || (false == enable));
2427 
2428     volatile uint32_t *mbAddr;
2429     uint8_t i, j, k, rffn = 0, numMbOccupy;
2430     uint32_t setup_mb = 0;
2431 
2432     /* Enter Freeze Mode. */
2433     FLEXCAN_EnterFreezeMode(base);
2434 
2435     if (enable)
2436     {
2437         assert(pRxFifoConfig->idFilterNum <= 128U);
2438 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
2439         /* Legacy Rx FIFO and Enhanced Rx FIFO cannot be enabled at the same time. */
2440         assert((base->ERFCR & CAN_ERFCR_ERFEN_MASK) == 0U);
2441 #endif
2442 
2443         /* Get the setup_mb value. */
2444         setup_mb = (uint8_t)((base->MCR & CAN_MCR_MAXMB_MASK) >> CAN_MCR_MAXMB_SHIFT);
2445         setup_mb = (setup_mb < (uint32_t)FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base)) ?
2446                        setup_mb :
2447                        (uint32_t)FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base);
2448 
2449         /* Determine RFFN value. */
2450         for (i = 0; i <= 0xFU; i++)
2451         {
2452             if ((8U * (i + 1U)) >= pRxFifoConfig->idFilterNum)
2453             {
2454                 rffn = i;
2455                 assert(((setup_mb - 8U) - (2U * rffn)) > 0U);
2456 
2457                 base->CTRL2 = (base->CTRL2 & ~CAN_CTRL2_RFFN_MASK) | CAN_CTRL2_RFFN(rffn);
2458                 break;
2459             }
2460         }
2461 
2462         /* caculate the Number of Mailboxes occupied by RX Legacy FIFO and the filter. */
2463         numMbOccupy = 6U + (rffn + 1U) * 2U;
2464 
2465         /* Copy ID filter table to Message Buffer Region (Fix MISRA_C-2012 Rule 18.1). */
2466         j = 0U;
2467         for (i = 6U; i < numMbOccupy; i++)
2468         {
2469             /* Get address for current mail box.  */
2470             mbAddr = &(base->MB[i].CS);
2471 
2472             /* One Mail box contain 4U DWORD registers. */
2473             for (k = 0; k < 4U; k++)
2474             {
2475                 /* Fill all valid filter in the mail box occupied by filter.
2476                  * Disable unused Rx FIFO Filter, the other rest of register in the last Mail box occupied by fiter set
2477                  * as 0xffffffff.
2478                  */
2479                 mbAddr[k] = (j < pRxFifoConfig->idFilterNum) ? (pRxFifoConfig->idFilterTable[j]) : 0xFFFFFFFFU;
2480 
2481                 /* Try to fill next filter in current Mail Box.  */
2482                 j++;
2483             }
2484         }
2485 
2486         /* Setup ID Fitlter Type. */
2487         switch (pRxFifoConfig->idFilterType)
2488         {
2489             case kFLEXCAN_RxFifoFilterTypeA:
2490                 base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x0);
2491                 break;
2492             case kFLEXCAN_RxFifoFilterTypeB:
2493                 base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x1);
2494                 break;
2495             case kFLEXCAN_RxFifoFilterTypeC:
2496                 base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x2);
2497                 break;
2498             case kFLEXCAN_RxFifoFilterTypeD:
2499                 /* All frames rejected. */
2500                 base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x3);
2501                 break;
2502             default:
2503                 /* All the cases have been listed above, the default clause should not be reached. */
2504                 assert(false);
2505                 break;
2506         }
2507 
2508         /* Setting Message Reception Priority. */
2509         base->CTRL2 = (pRxFifoConfig->priority == kFLEXCAN_RxFifoPrioHigh) ? (base->CTRL2 & ~CAN_CTRL2_MRP_MASK) :
2510                                                                              (base->CTRL2 | CAN_CTRL2_MRP_MASK);
2511 
2512         /* Enable Rx Message FIFO. */
2513         base->MCR |= CAN_MCR_RFEN_MASK;
2514     }
2515     else
2516     {
2517         rffn = (uint8_t)((base->CTRL2 & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT);
2518         /* caculate the Number of Mailboxes occupied by RX Legacy FIFO and the filter. */
2519         numMbOccupy = 6U + (rffn + 1U) * 2U;
2520 
2521         /* Disable Rx Message FIFO. */
2522         base->MCR &= ~CAN_MCR_RFEN_MASK;
2523 
2524         /* Clean MB0 ~ MB5 and all MB occupied by ID filters (Fix MISRA_C-2012 Rule 18.1). */
2525 
2526         for (i = 0; i < numMbOccupy; i++)
2527         {
2528             FLEXCAN_SetRxMbConfig(base, i, NULL, false);
2529         }
2530     }
2531 
2532     /* Exit Freeze Mode. */
2533     FLEXCAN_ExitFreezeMode(base);
2534 }
2535 
2536 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
2537 /*!
2538  * brief Configures the FlexCAN Enhanced Rx FIFO.
2539  *
2540  * This function configures the Enhanced Rx FIFO with given configuration.
2541  * note  Enhanced Rx FIFO support receive classic CAN or CAN FD messages, Legacy Rx FIFO and Enhanced Rx FIFO
2542  *       cannot be enabled at the same time.
2543  *
2544  * param base    FlexCAN peripheral base address.
2545  * param pConfig Pointer to the FlexCAN Enhanced Rx FIFO configuration structure. Can be NULL when enable parameter
2546  *               is false.
2547  * param enable  Enable/disable Enhanced Rx FIFO.
2548  *               - true: Enable Enhanced Rx FIFO.
2549  *               - false: Disable Enhanced Rx FIFO.
2550  */
FLEXCAN_SetEnhancedRxFifoConfig(CAN_Type * base,const flexcan_enhanced_rx_fifo_config_t * pConfig,bool enable)2551 void FLEXCAN_SetEnhancedRxFifoConfig(CAN_Type *base, const flexcan_enhanced_rx_fifo_config_t *pConfig, bool enable)
2552 {
2553     /* Assertion. */
2554     assert((NULL != pConfig) || (false == enable));
2555     uint32_t i;
2556     /* Enter Freeze Mode. */
2557     FLEXCAN_EnterFreezeMode(base);
2558 
2559     if (enable)
2560     {
2561         /* Each pair of filter elements occupies 2 words and can consist of one extended ID filter element or two
2562          * standard ID filter elements. */
2563         assert((((uint32_t)pConfig->idFilterPairNum * 2UL) <
2564                 (uint32_t)FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO_FILTER_MAX_NUMBER) &&
2565                (pConfig->extendIdFilterNum <= pConfig->idFilterPairNum) && (0UL != pConfig->idFilterPairNum));
2566 
2567         /* The Enhanced Rx FIFO Watermark cannot be greater than the enhanced Rx FIFO size. */
2568         assert(pConfig->fifoWatermark < (uint32_t)FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO_SIZE);
2569 
2570         /* Legacy Rx FIFO and Enhanced Rx FIFO cannot be enabled at the same time. */
2571         assert((base->MCR & CAN_MCR_RFEN_MASK) == 0U);
2572 
2573         /* Reset Enhanced Rx FIFO engine and clear flags. */
2574         base->ERFSR |= CAN_ERFSR_ERFCLR_MASK | CAN_ERFSR_ERFUFW_MASK | CAN_ERFSR_ERFOVF_MASK | CAN_ERFSR_ERFWMI_MASK |
2575                        CAN_ERFSR_ERFDA_MASK;
2576         /* Setting Enhanced Rx FIFO. */
2577         base->ERFCR = CAN_ERFCR_DMALW(pConfig->dmaPerReadLength) | CAN_ERFCR_NEXIF(pConfig->extendIdFilterNum) |
2578                       CAN_ERFCR_NFE((uint32_t)pConfig->idFilterPairNum - 1UL) | CAN_ERFCR_ERFWM(pConfig->fifoWatermark);
2579         /* Copy ID filter table to Enhanced Rx FIFO Filter Element registers. */
2580         for (i = 0; i < (uint32_t)FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO_FILTER_MAX_NUMBER; i++)
2581         {
2582             base->ERFFEL[i] = (i < ((uint32_t)pConfig->idFilterPairNum * 2U)) ? pConfig->idFilterTable[i] : 0xFFFFFFFFU;
2583         }
2584 
2585         /* Setting Message Reception Priority. */
2586         base->CTRL2 = (pConfig->priority == kFLEXCAN_RxFifoPrioHigh) ? (base->CTRL2 & ~CAN_CTRL2_MRP_MASK) :
2587                                                                        (base->CTRL2 | CAN_CTRL2_MRP_MASK);
2588         /* Enable Enhanced Rx FIFO. */
2589         base->ERFCR |= CAN_ERFCR_ERFEN_MASK;
2590     }
2591     else
2592     {
2593         /* Disable Enhanced Rx FIFO. */
2594         base->ERFCR = 0U;
2595         /* Reset Enhanced Rx FIFO engine and clear flags. */
2596         base->ERFSR |= CAN_ERFSR_ERFCLR_MASK | CAN_ERFSR_ERFUFW_MASK | CAN_ERFSR_ERFOVF_MASK | CAN_ERFSR_ERFWMI_MASK |
2597                        CAN_ERFSR_ERFDA_MASK;
2598         /* Clean all Enhanced Rx FIFO Filter Element registers. */
2599         for (i = 0; i < (uint32_t)FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO_FILTER_MAX_NUMBER; i++)
2600         {
2601             base->ERFFEL[i] = 0xFFFFFFFFU;
2602         }
2603     }
2604 
2605     /* Exit Freeze Mode. */
2606     FLEXCAN_ExitFreezeMode(base);
2607 }
2608 #endif
2609 
2610 #if (defined(FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA) && FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA)
2611 /*!
2612  * brief Enables or disables the FlexCAN Legacy/Enhanced Rx FIFO DMA request.
2613  *
2614  * This function enables or disables the DMA feature of FlexCAN build-in Rx FIFO.
2615  *
2616  * param base FlexCAN peripheral base address.
2617  * param enable true to enable, false to disable.
2618  */
FLEXCAN_EnableRxFifoDMA(CAN_Type * base,bool enable)2619 void FLEXCAN_EnableRxFifoDMA(CAN_Type *base, bool enable)
2620 {
2621     if (enable)
2622     {
2623         /* Enter Freeze Mode. */
2624         FLEXCAN_EnterFreezeMode(base);
2625 
2626         /* Enable FlexCAN DMA. */
2627         base->MCR |= CAN_MCR_DMA_MASK;
2628 
2629         /* Exit Freeze Mode. */
2630         FLEXCAN_ExitFreezeMode(base);
2631     }
2632     else
2633     {
2634         /* Enter Freeze Mode. */
2635         FLEXCAN_EnterFreezeMode(base);
2636 
2637         /* Disable FlexCAN DMA. */
2638         base->MCR &= ~CAN_MCR_DMA_MASK;
2639 
2640         /* Exit Freeze Mode. */
2641         FLEXCAN_ExitFreezeMode(base);
2642     }
2643 }
2644 #endif /* FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA */
2645 
2646 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
2647 /*!
2648  * brief Gets the FlexCAN Memory Error Report registers status.
2649  *
2650  * This function gets the FlexCAN Memory Error Report registers status.
2651  *
2652  * param base FlexCAN peripheral base address.
2653  * param errorStatus Pointer to FlexCAN Memory Error Report registers status structure.
2654  */
FLEXCAN_GetMemoryErrorReportStatus(CAN_Type * base,flexcan_memory_error_report_status_t * errorStatus)2655 void FLEXCAN_GetMemoryErrorReportStatus(CAN_Type *base, flexcan_memory_error_report_status_t *errorStatus)
2656 {
2657     uint32_t temp;
2658     /*  Disable updates of the error report registers. */
2659     base->MECR |= CAN_MECR_RERRDIS_MASK;
2660 
2661     errorStatus->accessAddress = (uint16_t)(base->RERRAR & CAN_RERRAR_ERRADDR_MASK);
2662     errorStatus->errorData     = base->RERRDR;
2663     errorStatus->errorType =
2664         (base->RERRAR & CAN_RERRAR_NCE_MASK) == 0U ? kFLEXCAN_CorrectableError : kFLEXCAN_NonCorrectableError;
2665 
2666     temp = (base->RERRAR & CAN_RERRAR_SAID_MASK) >> CAN_RERRAR_SAID_SHIFT;
2667     switch (temp)
2668     {
2669         case (uint32_t)kFLEXCAN_MoveOutFlexCanAccess:
2670         case (uint32_t)kFLEXCAN_MoveInAccess:
2671         case (uint32_t)kFLEXCAN_TxArbitrationAccess:
2672         case (uint32_t)kFLEXCAN_RxMatchingAccess:
2673         case (uint32_t)kFLEXCAN_MoveOutHostAccess:
2674             errorStatus->accessType = (flexcan_memory_access_type_t)temp;
2675             break;
2676         default:
2677             assert(false);
2678             break;
2679     }
2680 
2681     for (uint32_t i = 0; i < 4U; i++)
2682     {
2683         temp = (base->RERRSYNR & ((uint32_t)CAN_RERRSYNR_SYND0_MASK << (i * 8U))) >> (i * 8U);
2684         errorStatus->byteStatus[i].byteIsRead = (base->RERRSYNR & ((uint32_t)CAN_RERRSYNR_BE0_MASK << (i * 8U))) != 0U;
2685         switch (temp)
2686         {
2687             case CAN_RERRSYNR_SYND0(kFLEXCAN_NoError):
2688             case CAN_RERRSYNR_SYND0(kFLEXCAN_ParityBits0Error):
2689             case CAN_RERRSYNR_SYND0(kFLEXCAN_ParityBits1Error):
2690             case CAN_RERRSYNR_SYND0(kFLEXCAN_ParityBits2Error):
2691             case CAN_RERRSYNR_SYND0(kFLEXCAN_ParityBits3Error):
2692             case CAN_RERRSYNR_SYND0(kFLEXCAN_ParityBits4Error):
2693             case CAN_RERRSYNR_SYND0(kFLEXCAN_DataBits0Error):
2694             case CAN_RERRSYNR_SYND0(kFLEXCAN_DataBits1Error):
2695             case CAN_RERRSYNR_SYND0(kFLEXCAN_DataBits2Error):
2696             case CAN_RERRSYNR_SYND0(kFLEXCAN_DataBits3Error):
2697             case CAN_RERRSYNR_SYND0(kFLEXCAN_DataBits4Error):
2698             case CAN_RERRSYNR_SYND0(kFLEXCAN_DataBits5Error):
2699             case CAN_RERRSYNR_SYND0(kFLEXCAN_DataBits6Error):
2700             case CAN_RERRSYNR_SYND0(kFLEXCAN_DataBits7Error):
2701             case CAN_RERRSYNR_SYND0(kFLEXCAN_AllZeroError):
2702             case CAN_RERRSYNR_SYND0(kFLEXCAN_AllOneError):
2703                 errorStatus->byteStatus[i].bitAffected = (flexcan_byte_error_syndrome_t)temp;
2704                 break;
2705             default:
2706                 errorStatus->byteStatus[i].bitAffected = kFLEXCAN_NonCorrectableErrors;
2707                 break;
2708         }
2709     }
2710 
2711     /*  Re-enable updates of the error report registers. */
2712     base->MECR &= CAN_MECR_RERRDIS_MASK;
2713 }
2714 #endif
2715 
2716 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032)
2717 /*!
2718  * FlexCAN: A frame with wrong ID or payload is transmitted into
2719  * the CAN bus when the Message Buffer under transmission is
2720  * either aborted or deactivated while the CAN bus is in the Bus Idle state
2721  *
2722  * This function to do workaround for ERR006032
2723  *
2724  * param base FlexCAN peripheral base address.
2725  * param mbIdx The FlexCAN Message Buffer index.
2726  */
FLEXCAN_ERRATA_6032(CAN_Type * base,volatile uint32_t * mbCSAddr)2727 static void FLEXCAN_ERRATA_6032(CAN_Type *base, volatile uint32_t *mbCSAddr)
2728 {
2729     uint32_t dbg_temp   = 0U;
2730     uint32_t u32TempCS  = 0U;
2731     uint32_t u32Timeout = DELAY_BUSIDLE;
2732     /*disable ALL interrupts to prevent any context switching*/
2733     uint32_t irqMask = DisableGlobalIRQ();
2734     dbg_temp         = (uint32_t)(base->DBG1);
2735     switch (dbg_temp & CAN_DBG1_CFSM_MASK)
2736     {
2737         case RXINTERMISSION:
2738             if (CBN_VALUE3 == (dbg_temp & CAN_DBG1_CBN_MASK))
2739             {
2740                 /*wait until CFSM is different from RXINTERMISSION */
2741                 while (RXINTERMISSION == (base->DBG1 & CAN_DBG1_CFSM_MASK))
2742                 {
2743                     __NOP();
2744                 }
2745             }
2746             break;
2747         case TXINTERMISSION:
2748             if (CBN_VALUE3 == (dbg_temp & CAN_DBG1_CBN_MASK))
2749             {
2750                 /*wait until CFSM is different from TXINTERMISSION*/
2751                 while (TXINTERMISSION == (base->DBG1 & CAN_DBG1_CFSM_MASK))
2752                 {
2753                     __NOP();
2754                 }
2755             }
2756             break;
2757         default:
2758             /* To avoid MISRA-C 2012 rule 16.4 issue. */
2759             break;
2760     }
2761     /*Anyway, BUSIDLE need to delay*/
2762     if (BUSIDLE == (base->DBG1 & CAN_DBG1_CFSM_MASK))
2763     {
2764         while (u32Timeout-- > 0U)
2765         {
2766             __NOP();
2767         }
2768 
2769         /*Write 0x0 into Code field of CS word.*/
2770         u32TempCS = (uint32_t)(*mbCSAddr);
2771         u32TempCS &= ~CAN_CS_CODE_MASK;
2772         *mbCSAddr = u32TempCS;
2773     }
2774     /*restore interruption*/
2775     EnableGlobalIRQ(irqMask);
2776 }
2777 #endif
2778 
2779 /*!
2780  * brief Writes a FlexCAN Message to the Transmit Message Buffer.
2781  *
2782  * This function writes a CAN Message to the specified Transmit Message Buffer
2783  * and changes the Message Buffer state to start CAN Message transmit. After
2784  * that the function returns immediately.
2785  *
2786  * param base FlexCAN peripheral base address.
2787  * param mbIdx The FlexCAN Message Buffer index.
2788  * param pTxFrame Pointer to CAN message frame to be sent.
2789  * retval kStatus_Success - Write Tx Message Buffer Successfully.
2790  * retval kStatus_Fail    - Tx Message Buffer is currently in use.
2791  */
FLEXCAN_WriteTxMb(CAN_Type * base,uint8_t mbIdx,const flexcan_frame_t * pTxFrame)2792 status_t FLEXCAN_WriteTxMb(CAN_Type *base, uint8_t mbIdx, const flexcan_frame_t *pTxFrame)
2793 {
2794     /* Assertion. */
2795     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
2796     assert(NULL != pTxFrame);
2797     assert(pTxFrame->length <= 8U);
2798 #if !defined(NDEBUG)
2799     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
2800 #endif
2801 
2802     uint32_t cs_temp = 0;
2803     status_t status;
2804 
2805     /* Check if Message Buffer is available. */
2806     if (CAN_CS_CODE(kFLEXCAN_TxMbDataOrRemote) != (base->MB[mbIdx].CS & CAN_CS_CODE_MASK))
2807     {
2808 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032)
2809         FLEXCAN_ERRATA_6032(base, &(base->MB[mbIdx].CS));
2810 #endif
2811         /* Inactive Tx Message Buffer. */
2812         base->MB[mbIdx].CS = (base->MB[mbIdx].CS & ~CAN_CS_CODE_MASK) | CAN_CS_CODE(kFLEXCAN_TxMbInactive);
2813 
2814         /* Fill Message ID field. */
2815         base->MB[mbIdx].ID = pTxFrame->id;
2816 
2817         /* Fill Message Format field. */
2818         if ((uint32_t)kFLEXCAN_FrameFormatExtend == pTxFrame->format)
2819         {
2820             cs_temp |= CAN_CS_SRR_MASK | CAN_CS_IDE_MASK;
2821         }
2822 
2823         /* Fill Message Type field. */
2824         if ((uint32_t)kFLEXCAN_FrameTypeRemote == pTxFrame->type)
2825         {
2826             cs_temp |= CAN_CS_RTR_MASK;
2827         }
2828 
2829         cs_temp |= CAN_CS_CODE(kFLEXCAN_TxMbDataOrRemote) | CAN_CS_DLC(pTxFrame->length);
2830 
2831         /* Load Message Payload. */
2832         base->MB[mbIdx].WORD0 = pTxFrame->dataWord0;
2833         base->MB[mbIdx].WORD1 = pTxFrame->dataWord1;
2834 
2835         /* Activate Tx Message Buffer. */
2836         base->MB[mbIdx].CS = cs_temp;
2837 
2838 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
2839      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
2840         base->MB[FLEXCAN_GetFirstValidMb(base)].CS = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
2841         base->MB[FLEXCAN_GetFirstValidMb(base)].CS = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
2842 #endif
2843 
2844         status = kStatus_Success;
2845     }
2846     else
2847     {
2848         /* Tx Message Buffer is activated, return immediately. */
2849         status = kStatus_Fail;
2850     }
2851 
2852     return status;
2853 }
2854 
2855 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
2856 /*!
2857  * brief Writes a FlexCAN FD Message to the Transmit Message Buffer.
2858  *
2859  * This function writes a CAN FD Message to the specified Transmit Message Buffer
2860  * and changes the Message Buffer state to start CAN FD Message transmit. After
2861  * that the function returns immediately.
2862  *
2863  * param base FlexCAN peripheral base address.
2864  * param mbIdx The FlexCAN FD Message Buffer index.
2865  * param pTxFrame Pointer to CAN FD message frame to be sent.
2866  * retval kStatus_Success - Write Tx Message Buffer Successfully.
2867  * retval kStatus_Fail    - Tx Message Buffer is currently in use.
2868  */
FLEXCAN_WriteFDTxMb(CAN_Type * base,uint8_t mbIdx,const flexcan_fd_frame_t * pTxFrame)2869 status_t FLEXCAN_WriteFDTxMb(CAN_Type *base, uint8_t mbIdx, const flexcan_fd_frame_t *pTxFrame)
2870 {
2871     /* Assertion. */
2872     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
2873     assert(NULL != pTxFrame);
2874 #if !defined(NDEBUG)
2875     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
2876 #endif
2877 
2878     status_t status;
2879     uint32_t cs_temp      = 0;
2880     uint8_t cnt           = 0;
2881     uint32_t can_cs       = 0;
2882     uint8_t payload_dword = 1;
2883     uint32_t dataSize     = (base->FDCTRL & CAN_FDCTRL_MBDSR0_MASK) >> CAN_FDCTRL_MBDSR0_SHIFT;
2884 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
2885      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
2886     uint32_t availoffset = FLEXCAN_GetFDMailboxOffset(base, FLEXCAN_GetFirstValidMb(base));
2887 #endif
2888     volatile uint32_t *mbAddr = &(base->MB[0].CS);
2889     uint32_t offset           = FLEXCAN_GetFDMailboxOffset(base, mbIdx);
2890 
2891     can_cs = mbAddr[offset];
2892     /* Check if Message Buffer is available. */
2893     if (CAN_CS_CODE(kFLEXCAN_TxMbDataOrRemote) != (can_cs & CAN_CS_CODE_MASK))
2894     {
2895 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032)
2896         FLEXCAN_ERRATA_6032(base, &(mbAddr[offset]));
2897 #endif
2898         /* Inactive Tx Message Buffer and Fill Message ID field. */
2899         mbAddr[offset]      = (can_cs & ~CAN_CS_CODE_MASK) | CAN_CS_CODE(kFLEXCAN_TxMbInactive);
2900         mbAddr[offset + 1U] = pTxFrame->id;
2901 
2902         /* Fill Message Format field. */
2903         if ((uint32_t)kFLEXCAN_FrameFormatExtend == pTxFrame->format)
2904         {
2905             cs_temp |= CAN_CS_SRR_MASK | CAN_CS_IDE_MASK;
2906         }
2907 
2908         /* Fill Message Type field. */
2909         if ((uint32_t)kFLEXCAN_FrameTypeRemote == pTxFrame->type)
2910         {
2911             cs_temp |= CAN_CS_RTR_MASK;
2912         }
2913 
2914         cs_temp |= CAN_CS_CODE(kFLEXCAN_TxMbDataOrRemote) | CAN_CS_DLC(pTxFrame->length) | CAN_CS_EDL(pTxFrame->edl) |
2915                    CAN_CS_BRS(pTxFrame->brs);
2916 
2917         /* Calculate the DWORD number, dataSize 0/1/2/3 corresponds to 8/16/32/64
2918            Bytes payload. */
2919         for (cnt = 0; cnt < (dataSize + 1U); cnt++)
2920         {
2921             payload_dword *= 2U;
2922         }
2923 
2924         /* Load Message Payload and Activate Tx Message Buffer. */
2925         for (cnt = 0; cnt < payload_dword; cnt++)
2926         {
2927             mbAddr[offset + 2U + cnt] = pTxFrame->dataWord[cnt];
2928         }
2929         mbAddr[offset] = cs_temp;
2930 
2931 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
2932      (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
2933         mbAddr[availoffset] = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
2934         mbAddr[availoffset] = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
2935 #endif
2936 
2937         status = kStatus_Success;
2938     }
2939     else
2940     {
2941         /* Tx Message Buffer is activated, return immediately. */
2942         status = kStatus_Fail;
2943     }
2944 
2945     return status;
2946 }
2947 #endif
2948 
2949 /*!
2950  * brief Reads a FlexCAN Message from Receive Message Buffer.
2951  *
2952  * This function reads a CAN message from a specified Receive Message Buffer.
2953  * The function fills a receive CAN message frame structure with
2954  * just received data and activates the Message Buffer again.
2955  * The function returns immediately.
2956  *
2957  * param base FlexCAN peripheral base address.
2958  * param mbIdx The FlexCAN Message Buffer index.
2959  * param pRxFrame Pointer to CAN message frame structure for reception.
2960  * retval kStatus_Success            - Rx Message Buffer is full and has been read successfully.
2961  * retval kStatus_FLEXCAN_RxOverflow - Rx Message Buffer is already overflowed and has been read successfully.
2962  * retval kStatus_Fail               - Rx Message Buffer is empty.
2963  */
FLEXCAN_ReadRxMb(CAN_Type * base,uint8_t mbIdx,flexcan_frame_t * pRxFrame)2964 status_t FLEXCAN_ReadRxMb(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *pRxFrame)
2965 {
2966     /* Assertion. */
2967     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
2968     assert(NULL != pRxFrame);
2969 #if !defined(NDEBUG)
2970     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
2971 #endif
2972 
2973     uint32_t cs_temp;
2974     uint32_t rx_code;
2975     status_t status;
2976 
2977     /* Read CS field of Rx Message Buffer to lock Message Buffer. */
2978     cs_temp = base->MB[mbIdx].CS;
2979     /* Get Rx Message Buffer Code field. */
2980     rx_code = (cs_temp & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT;
2981 
2982     /* Check to see if Rx Message Buffer is full. */
2983     if (((uint32_t)kFLEXCAN_RxMbFull == rx_code) || ((uint32_t)kFLEXCAN_RxMbOverrun == rx_code))
2984     {
2985         /* Store Message ID. */
2986         pRxFrame->id = base->MB[mbIdx].ID & (CAN_ID_EXT_MASK | CAN_ID_STD_MASK);
2987 
2988         /* Get the message ID and format. */
2989         pRxFrame->format = (cs_temp & CAN_CS_IDE_MASK) != 0U ? (uint8_t)kFLEXCAN_FrameFormatExtend :
2990                                                                (uint8_t)kFLEXCAN_FrameFormatStandard;
2991 
2992         /* Get the message type. */
2993         pRxFrame->type =
2994             (cs_temp & CAN_CS_RTR_MASK) != 0U ? (uint8_t)kFLEXCAN_FrameTypeRemote : (uint8_t)kFLEXCAN_FrameTypeData;
2995 
2996         /* Get the message length. */
2997         pRxFrame->length = (uint8_t)((cs_temp & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
2998 
2999         /* Get the time stamp. */
3000         pRxFrame->timestamp = (uint16_t)((cs_temp & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
3001 
3002         /* Store Message Payload. */
3003         pRxFrame->dataWord0 = base->MB[mbIdx].WORD0;
3004         pRxFrame->dataWord1 = base->MB[mbIdx].WORD1;
3005 
3006         /* Read free-running timer to unlock Rx Message Buffer. */
3007         (void)base->TIMER;
3008 
3009         if ((uint32_t)kFLEXCAN_RxMbFull == rx_code)
3010         {
3011             status = kStatus_Success;
3012         }
3013         else
3014         {
3015             status = kStatus_FLEXCAN_RxOverflow;
3016         }
3017     }
3018     else
3019     {
3020         /* Read free-running timer to unlock Rx Message Buffer. */
3021         (void)base->TIMER;
3022 
3023         status = kStatus_Fail;
3024     }
3025 
3026     return status;
3027 }
3028 
3029 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
3030 /*!
3031  * brief Reads a FlexCAN FD Message from Receive Message Buffer.
3032  *
3033  * This function reads a CAN FD message from a specified Receive Message Buffer.
3034  * The function fills a receive CAN FD message frame structure with
3035  * just received data and activates the Message Buffer again.
3036  * The function returns immediately.
3037  *
3038  * param base FlexCAN peripheral base address.
3039  * param mbIdx The FlexCAN FD Message Buffer index.
3040  * param pRxFrame Pointer to CAN FD message frame structure for reception.
3041  * retval kStatus_Success            - Rx Message Buffer is full and has been read successfully.
3042  * retval kStatus_FLEXCAN_RxOverflow - Rx Message Buffer is already overflowed and has been read successfully.
3043  * retval kStatus_Fail               - Rx Message Buffer is empty.
3044  */
FLEXCAN_ReadFDRxMb(CAN_Type * base,uint8_t mbIdx,flexcan_fd_frame_t * pRxFrame)3045 status_t FLEXCAN_ReadFDRxMb(CAN_Type *base, uint8_t mbIdx, flexcan_fd_frame_t *pRxFrame)
3046 {
3047     /* Assertion. */
3048     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
3049     assert(NULL != pRxFrame);
3050 #if !defined(NDEBUG)
3051     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
3052 #endif
3053 
3054     status_t status;
3055     uint32_t cs_temp;
3056     uint8_t rx_code;
3057     uint8_t cnt     = 0;
3058     uint32_t can_id = 0;
3059     uint32_t dataSize;
3060     dataSize                  = (base->FDCTRL & CAN_FDCTRL_MBDSR0_MASK) >> CAN_FDCTRL_MBDSR0_SHIFT;
3061     uint8_t payload_dword     = 1;
3062     volatile uint32_t *mbAddr = &(base->MB[0].CS);
3063     uint32_t offset           = FLEXCAN_GetFDMailboxOffset(base, mbIdx);
3064 
3065     /* Read CS field of Rx Message Buffer to lock Message Buffer. */
3066     cs_temp = mbAddr[offset];
3067     can_id  = mbAddr[offset + 1U];
3068 
3069     /* Get Rx Message Buffer Code field. */
3070     rx_code = (uint8_t)((cs_temp & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT);
3071 
3072     /* Check to see if Rx Message Buffer is full. */
3073     if (((uint8_t)kFLEXCAN_RxMbFull == rx_code) || ((uint8_t)kFLEXCAN_RxMbOverrun == rx_code))
3074     {
3075         /* Store Message ID. */
3076         pRxFrame->id = can_id & (CAN_ID_EXT_MASK | CAN_ID_STD_MASK);
3077 
3078         /* Get the message ID and format. */
3079         pRxFrame->format = (cs_temp & CAN_CS_IDE_MASK) != 0U ? (uint8_t)kFLEXCAN_FrameFormatExtend :
3080                                                                (uint8_t)kFLEXCAN_FrameFormatStandard;
3081 
3082         /* Get Bit Rate Switch flag. */
3083         pRxFrame->brs = (cs_temp & CAN_CS_BRS_MASK) != 0U ? 1U : 0U;
3084 
3085         /* Get Extended Data Length flag. */
3086         pRxFrame->edl = (cs_temp & CAN_CS_EDL_MASK) != 0U ? 1U : 0U;
3087 
3088         /* Get the message type. */
3089         pRxFrame->type =
3090             (cs_temp & CAN_CS_RTR_MASK) != 0U ? (uint8_t)kFLEXCAN_FrameTypeRemote : (uint8_t)kFLEXCAN_FrameTypeData;
3091 
3092         /* Get the message length. */
3093         pRxFrame->length = (uint8_t)((cs_temp & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
3094 
3095         /* Get the time stamp. */
3096         pRxFrame->timestamp = (uint16_t)((cs_temp & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
3097 
3098         /* Calculate the DWORD number, dataSize 0/1/2/3 corresponds to 8/16/32/64
3099            Bytes payload. */
3100         for (cnt = 0; cnt < (dataSize + 1U); cnt++)
3101         {
3102             payload_dword *= 2U;
3103         }
3104 
3105         /* Store Message Payload. */
3106         for (cnt = 0; cnt < payload_dword; cnt++)
3107         {
3108             pRxFrame->dataWord[cnt] = mbAddr[offset + 2U + cnt];
3109         }
3110 
3111         /* Read free-running timer to unlock Rx Message Buffer. */
3112         (void)base->TIMER;
3113 
3114         if ((uint32_t)kFLEXCAN_RxMbFull == rx_code)
3115         {
3116             status = kStatus_Success;
3117         }
3118         else
3119         {
3120             status = kStatus_FLEXCAN_RxOverflow;
3121         }
3122     }
3123     else
3124     {
3125         /* Read free-running timer to unlock Rx Message Buffer. */
3126         (void)base->TIMER;
3127 
3128         status = kStatus_Fail;
3129     }
3130 
3131     return status;
3132 }
3133 #endif
3134 
3135 /*!
3136  * brief Reads a FlexCAN Message from Legacy Rx FIFO.
3137  *
3138  * This function reads a CAN message from the FlexCAN Legacy Rx FIFO.
3139  *
3140  * param base FlexCAN peripheral base address.
3141  * param pRxFrame Pointer to CAN message frame structure for reception.
3142  * retval kStatus_Success - Read Message from Rx FIFO successfully.
3143  * retval kStatus_Fail    - Rx FIFO is not enabled.
3144  */
FLEXCAN_ReadRxFifo(CAN_Type * base,flexcan_frame_t * pRxFrame)3145 status_t FLEXCAN_ReadRxFifo(CAN_Type *base, flexcan_frame_t *pRxFrame)
3146 {
3147     /* Assertion. */
3148     assert(NULL != pRxFrame);
3149 
3150     uint32_t cs_temp;
3151     status_t status;
3152 
3153     /* Check if Legacy Rx FIFO is Enabled. */
3154     if (0U != (base->MCR & CAN_MCR_RFEN_MASK))
3155     {
3156         /* Read CS field of Rx Message Buffer to lock Message Buffer. */
3157         cs_temp = base->MB[0].CS;
3158 
3159         /* Read data from Rx FIFO output port. */
3160         /* Store Message ID. */
3161         pRxFrame->id = base->MB[0].ID & (CAN_ID_EXT_MASK | CAN_ID_STD_MASK);
3162 
3163         /* Get the message ID and format. */
3164         pRxFrame->format = (cs_temp & CAN_CS_IDE_MASK) != 0U ? (uint8_t)kFLEXCAN_FrameFormatExtend :
3165                                                                (uint8_t)kFLEXCAN_FrameFormatStandard;
3166 
3167         /* Get the message type. */
3168         pRxFrame->type =
3169             (cs_temp & CAN_CS_RTR_MASK) != 0U ? (uint8_t)kFLEXCAN_FrameTypeRemote : (uint8_t)kFLEXCAN_FrameTypeData;
3170 
3171         /* Get the message length. */
3172         pRxFrame->length = (uint8_t)((cs_temp & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
3173 
3174         /* Get the time stamp. */
3175         pRxFrame->timestamp = (uint16_t)((cs_temp & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
3176 
3177         /* Store Message Payload. */
3178         pRxFrame->dataWord0 = base->MB[0].WORD0;
3179         pRxFrame->dataWord1 = base->MB[0].WORD1;
3180 
3181         /* Store ID Filter Hit Index. */
3182         pRxFrame->idhit = (uint16_t)(base->RXFIR & CAN_RXFIR_IDHIT_MASK);
3183 
3184         /* Read free-running timer to unlock Rx Message Buffer. */
3185         (void)base->TIMER;
3186 
3187         status = kStatus_Success;
3188     }
3189     else
3190     {
3191         status = kStatus_Fail;
3192     }
3193 
3194     return status;
3195 }
3196 
3197 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
3198 /*!
3199  * brief Reads a FlexCAN Message from Enhanced Rx FIFO.
3200  *
3201  * This function reads a CAN or CAN FD message from the FlexCAN Enhanced Rx FIFO.
3202  *
3203  * param base FlexCAN peripheral base address.
3204  * param pRxFrame Pointer to CAN FD message frame structure for reception.
3205  * retval kStatus_Success - Read Message from Rx FIFO successfully.
3206  * retval kStatus_Fail    - Rx FIFO is not enabled.
3207  */
FLEXCAN_ReadEnhancedRxFifo(CAN_Type * base,flexcan_fd_frame_t * pRxFrame)3208 status_t FLEXCAN_ReadEnhancedRxFifo(CAN_Type *base, flexcan_fd_frame_t *pRxFrame)
3209 {
3210     /* Assertion. */
3211     assert(NULL != pRxFrame);
3212 
3213     status_t status;
3214     uint32_t idHitOff;
3215 
3216     /* Check if Enhanced Rx FIFO is Enabled. */
3217     if (0U != (base->ERFCR & CAN_ERFCR_ERFEN_MASK))
3218     {
3219         /* Enhanced Rx FIFO ID HIT offset is changed dynamically according to data length code (DLC) . */
3220         idHitOff = (DLC_LENGTH_DECODE(((flexcan_fd_frame_t *)E_RX_FIFO(base))->length) + 3U) / 4U + 3U;
3221         /* Copy CAN FD Message from Enhanced Rx FIFO, should use the DLC value to identify the bytes that belong to the
3222          * message which is being read. */
3223         (void)memcpy((void *)pRxFrame, (void *)(uint32_t *)E_RX_FIFO(base), sizeof(uint32_t) * idHitOff);
3224         pRxFrame->idhit = pRxFrame->dataWord[idHitOff - 3U];
3225         /* Clear the unused frame data. */
3226         for (uint32_t i = (idHitOff - 3U); i < 16U; i++)
3227         {
3228             pRxFrame->dataWord[i] = 0x0;
3229         }
3230 
3231         /* Clear data available flag to let FlexCAN know one frame has been read from the Enhanced Rx FIFO. */
3232         base->ERFSR = CAN_ERFSR_ERFDA_MASK;
3233         status      = kStatus_Success;
3234     }
3235     else
3236     {
3237         status = kStatus_Fail;
3238     }
3239 
3240     return status;
3241 }
3242 #endif
3243 
3244 /*!
3245  * brief Performs a polling send transaction on the CAN bus.
3246  *
3247  * note  A transfer handle does not need to be created  before calling this API.
3248  *
3249  * param base FlexCAN peripheral base pointer.
3250  * param mbIdx The FlexCAN Message Buffer index.
3251  * param pTxFrame Pointer to CAN message frame to be sent.
3252  * retval kStatus_Success - Write Tx Message Buffer Successfully.
3253  * retval kStatus_Fail    - Tx Message Buffer is currently in use.
3254  */
FLEXCAN_TransferSendBlocking(CAN_Type * base,uint8_t mbIdx,flexcan_frame_t * pTxFrame)3255 status_t FLEXCAN_TransferSendBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *pTxFrame)
3256 {
3257     status_t status;
3258 
3259     /* Write Tx Message Buffer to initiate a data sending. */
3260     if (kStatus_Success == FLEXCAN_WriteTxMb(base, mbIdx, (const flexcan_frame_t *)(uintptr_t)pTxFrame))
3261     {
3262         /* Wait until CAN Message send out. */
3263 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
3264         if (mbIdx >= 64U)
3265         {
3266             while (0U == FLEXCAN_GetHigh64MbStatusFlags(base, (uint64_t)1U << (mbIdx - 64U)))
3267             {
3268             }
3269             FLEXCAN_ClearHigh64MbStatusFlags(base, (uint64_t)1U << (mbIdx - 64U));
3270         }
3271         else
3272         {
3273             while (0U == FLEXCAN_GetMbStatusFlags(base, (uint64_t)1U << mbIdx))
3274             {
3275             }
3276             FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << mbIdx);
3277         }
3278 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER) && FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)
3279         while (0U == FLEXCAN_GetMbStatusFlags(base, (uint64_t)1U << mbIdx))
3280         {
3281         }
3282         FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << mbIdx);
3283 #else
3284         while (0U == FLEXCAN_GetMbStatusFlags(base, (uint32_t)1U << mbIdx))
3285         {
3286         }
3287         FLEXCAN_ClearMbStatusFlags(base, (uint32_t)1U << mbIdx);
3288 #endif
3289 
3290         /*After TX MB tranfered success, update the Timestamp from MB[mbIdx].CS register*/
3291         pTxFrame->timestamp = (uint16_t)((base->MB[mbIdx].CS & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
3292 
3293         status = kStatus_Success;
3294     }
3295     else
3296     {
3297         status = kStatus_Fail;
3298     }
3299 
3300     return status;
3301 }
3302 
3303 /*!
3304  * brief Performs a polling receive transaction on the CAN bus.
3305  *
3306  * note  A transfer handle does not need to be created  before calling this API.
3307  *
3308  * param base FlexCAN peripheral base pointer.
3309  * param mbIdx The FlexCAN Message Buffer index.
3310  * param pRxFrame Pointer to CAN message frame structure for reception.
3311  * retval kStatus_Success            - Rx Message Buffer is full and has been read successfully.
3312  * retval kStatus_FLEXCAN_RxOverflow - Rx Message Buffer is already overflowed and has been read successfully.
3313  * retval kStatus_Fail               - Rx Message Buffer is empty.
3314  */
FLEXCAN_TransferReceiveBlocking(CAN_Type * base,uint8_t mbIdx,flexcan_frame_t * pRxFrame)3315 status_t FLEXCAN_TransferReceiveBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *pRxFrame)
3316 {
3317 /* Wait until Rx Message Buffer non-empty. */
3318 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
3319     if (mbIdx >= 64U)
3320     {
3321         while (0U == FLEXCAN_GetHigh64MbStatusFlags(base, (uint64_t)1U << (mbIdx - 64U)))
3322         {
3323         }
3324         FLEXCAN_ClearHigh64MbStatusFlags(base, (uint64_t)1U << (mbIdx - 64U));
3325     }
3326     else
3327     {
3328         while (0U == FLEXCAN_GetMbStatusFlags(base, (uint64_t)1U << mbIdx))
3329         {
3330         }
3331         FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << mbIdx);
3332     }
3333 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER) && FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)
3334     while (0U == FLEXCAN_GetMbStatusFlags(base, (uint64_t)1U << mbIdx))
3335     {
3336     }
3337     FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << mbIdx);
3338 #else
3339     while (0U == FLEXCAN_GetMbStatusFlags(base, (uint32_t)1U << mbIdx))
3340     {
3341     }
3342     FLEXCAN_ClearMbStatusFlags(base, (uint32_t)1U << mbIdx);
3343 #endif
3344 
3345     /* Read Received CAN Message. */
3346     return FLEXCAN_ReadRxMb(base, mbIdx, pRxFrame);
3347 }
3348 
3349 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
3350 /*!
3351  * brief Performs a polling send transaction on the CAN bus.
3352  *
3353  * note  A transfer handle does not need to be created before calling this API.
3354  *
3355  * param base FlexCAN peripheral base pointer.
3356  * param mbIdx The FlexCAN FD Message Buffer index.
3357  * param pTxFrame Pointer to CAN FD message frame to be sent.
3358  * retval kStatus_Success - Write Tx Message Buffer Successfully.
3359  * retval kStatus_Fail    - Tx Message Buffer is currently in use.
3360  */
FLEXCAN_TransferFDSendBlocking(CAN_Type * base,uint8_t mbIdx,flexcan_fd_frame_t * pTxFrame)3361 status_t FLEXCAN_TransferFDSendBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_fd_frame_t *pTxFrame)
3362 {
3363     status_t status;
3364 
3365     /* Write Tx Message Buffer to initiate a data sending. */
3366     if (kStatus_Success == FLEXCAN_WriteFDTxMb(base, mbIdx, (const flexcan_fd_frame_t *)(uintptr_t)pTxFrame))
3367     {
3368         /* Wait until CAN Message send out. */
3369 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
3370         if (mbIdx >= 64U)
3371         {
3372             while (0U == FLEXCAN_GetHigh64MbStatusFlags(base, (uint64_t)1U << (mbIdx - 64U)))
3373             {
3374             }
3375             FLEXCAN_ClearHigh64MbStatusFlags(base, (uint64_t)1U << (mbIdx - 64U));
3376         }
3377         else
3378         {
3379             while (0U == FLEXCAN_GetMbStatusFlags(base, (uint64_t)1U << mbIdx))
3380             {
3381             }
3382             FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << mbIdx);
3383         }
3384 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER) && FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)
3385         while (0U == FLEXCAN_GetMbStatusFlags(base, (uint64_t)1U << mbIdx))
3386         {
3387         }
3388         FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << mbIdx);
3389 #else
3390         while (0U == FLEXCAN_GetMbStatusFlags(base, (uint32_t)1U << mbIdx))
3391         {
3392         }
3393         FLEXCAN_ClearMbStatusFlags(base, (uint32_t)1U << mbIdx);
3394 #endif
3395         /*After TX MB tranfered success, update the Timestamp from base->MB[offset for CAN FD].CS register*/
3396         volatile uint32_t *mbAddr = &(base->MB[0].CS);
3397         uint32_t offset           = FLEXCAN_GetFDMailboxOffset(base, mbIdx);
3398         pTxFrame->timestamp       = (uint16_t)((mbAddr[offset] & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
3399 
3400         status = kStatus_Success;
3401     }
3402     else
3403     {
3404         status = kStatus_Fail;
3405     }
3406 
3407     return status;
3408 }
3409 
3410 /*!
3411  * brief Performs a polling receive transaction on the CAN bus.
3412  *
3413  * note  A transfer handle does not need to be created before calling this API.
3414  *
3415  * param base FlexCAN peripheral base pointer.
3416  * param mbIdx The FlexCAN FD Message Buffer index.
3417  * param pRxFrame Pointer to CAN FD message frame structure for reception.
3418  * retval kStatus_Success            - Rx Message Buffer is full and has been read successfully.
3419  * retval kStatus_FLEXCAN_RxOverflow - Rx Message Buffer is already overflowed and has been read successfully.
3420  * retval kStatus_Fail               - Rx Message Buffer is empty.
3421  */
FLEXCAN_TransferFDReceiveBlocking(CAN_Type * base,uint8_t mbIdx,flexcan_fd_frame_t * pRxFrame)3422 status_t FLEXCAN_TransferFDReceiveBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_fd_frame_t *pRxFrame)
3423 {
3424 /* Wait until Rx Message Buffer non-empty. */
3425 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
3426     if (mbIdx >= 64U)
3427     {
3428         while (0U == FLEXCAN_GetHigh64MbStatusFlags(base, (uint64_t)1U << (mbIdx - 64U)))
3429         {
3430         }
3431         FLEXCAN_ClearHigh64MbStatusFlags(base, (uint64_t)1U << (mbIdx - 64U));
3432     }
3433     else
3434     {
3435         while (0U == FLEXCAN_GetMbStatusFlags(base, (uint64_t)1U << mbIdx))
3436         {
3437         }
3438         FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << mbIdx);
3439     }
3440 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER) && FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)
3441     while (0U == FLEXCAN_GetMbStatusFlags(base, (uint64_t)1U << mbIdx))
3442     {
3443     }
3444     FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << mbIdx);
3445 #else
3446     while (0U == FLEXCAN_GetMbStatusFlags(base, (uint32_t)1U << mbIdx))
3447     {
3448     }
3449     FLEXCAN_ClearMbStatusFlags(base, (uint32_t)1U << mbIdx);
3450 #endif
3451 
3452     /* Read Received CAN Message. */
3453     return FLEXCAN_ReadFDRxMb(base, mbIdx, pRxFrame);
3454 }
3455 #endif
3456 
3457 /*!
3458  * brief Performs a polling receive transaction from Legacy Rx FIFO on the CAN bus.
3459  *
3460  * note  A transfer handle does not need to be created before calling this API.
3461  *
3462  * param base FlexCAN peripheral base pointer.
3463  * param pRxFrame Pointer to CAN message frame structure for reception.
3464  * retval kStatus_Success - Read Message from Rx FIFO successfully.
3465  * retval kStatus_Fail    - Rx FIFO is not enabled.
3466  */
FLEXCAN_TransferReceiveFifoBlocking(CAN_Type * base,flexcan_frame_t * pRxFrame)3467 status_t FLEXCAN_TransferReceiveFifoBlocking(CAN_Type *base, flexcan_frame_t *pRxFrame)
3468 {
3469     status_t rxFifoStatus;
3470 
3471     /* Wait until Legacy Rx FIFO non-empty. */
3472     while (0U == FLEXCAN_GetMbStatusFlags(base, (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag))
3473     {
3474     }
3475 
3476     /* Read data from Legacy Rx FIFO. */
3477     rxFifoStatus = FLEXCAN_ReadRxFifo(base, pRxFrame);
3478 
3479     /* Clean Rx Fifo available flag. */
3480     FLEXCAN_ClearMbStatusFlags(base, (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag);
3481 
3482     return rxFifoStatus;
3483 }
3484 
3485 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
3486 /*!
3487  * brief Performs a polling receive transaction from Enhanced Rx FIFO on the CAN bus.
3488  *
3489  * note  A transfer handle does not need to be created before calling this API.
3490  *
3491  * param base FlexCAN peripheral base pointer.
3492  * param pRxFrame Pointer to CAN FD message frame structure for reception.
3493  * retval kStatus_Success - Read Message from Rx FIFO successfully.
3494  * retval kStatus_Fail    - Rx FIFO is not enabled.
3495  */
FLEXCAN_TransferReceiveEnhancedFifoBlocking(CAN_Type * base,flexcan_fd_frame_t * pRxFrame)3496 status_t FLEXCAN_TransferReceiveEnhancedFifoBlocking(CAN_Type *base, flexcan_fd_frame_t *pRxFrame)
3497 {
3498     status_t rxFifoStatus;
3499 
3500     /* Wait until Enhanced Rx FIFO non-empty. */
3501     while (0U == (FLEXCAN_GetStatusFlags(base) & (uint64_t)kFLEXCAN_ERxFifoDataAvlIntFlag))
3502     {
3503     }
3504 
3505     /* Read data from Enhanced Rx FIFO */
3506     rxFifoStatus = FLEXCAN_ReadEnhancedRxFifo(base, pRxFrame);
3507 
3508     return rxFifoStatus;
3509 }
3510 #endif
3511 
3512 /*!
3513  * brief Initializes the FlexCAN handle.
3514  *
3515  * This function initializes the FlexCAN handle, which can be used for other FlexCAN
3516  * transactional APIs. Usually, for a specified FlexCAN instance,
3517  * call this API once to get the initialized handle.
3518  *
3519  * param base FlexCAN peripheral base address.
3520  * param handle FlexCAN handle pointer.
3521  * param callback The callback function.
3522  * param userData The parameter of the callback function.
3523  */
FLEXCAN_TransferCreateHandle(CAN_Type * base,flexcan_handle_t * handle,flexcan_transfer_callback_t callback,void * userData)3524 void FLEXCAN_TransferCreateHandle(CAN_Type *base,
3525                                   flexcan_handle_t *handle,
3526                                   flexcan_transfer_callback_t callback,
3527                                   void *userData)
3528 {
3529     assert(NULL != handle);
3530 
3531     uint8_t instance;
3532 
3533     /* Clean FlexCAN transfer handle. */
3534     (void)memset(handle, 0, sizeof(*handle));
3535 
3536     /* Get instance from peripheral base address. */
3537     instance = (uint8_t)FLEXCAN_GetInstance(base);
3538 
3539     /* Save the context in global variables to support the double weak mechanism. */
3540     s_flexcanHandle[instance] = handle;
3541 
3542     /* Register Callback function. */
3543     handle->callback = callback;
3544     handle->userData = userData;
3545 
3546     s_flexcanIsr = FLEXCAN_TransferHandleIRQ;
3547 
3548     /* We Enable Error & Status interrupt here, because this interrupt just
3549      * report current status of FlexCAN module through Callback function.
3550      * It is insignificance without a available callback function.
3551      */
3552     if (handle->callback != NULL)
3553     {
3554         FLEXCAN_EnableInterrupts(
3555             base, (uint32_t)kFLEXCAN_BusOffInterruptEnable | (uint32_t)kFLEXCAN_ErrorInterruptEnable |
3556                       (uint32_t)kFLEXCAN_RxWarningInterruptEnable | (uint32_t)kFLEXCAN_TxWarningInterruptEnable
3557 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_WAKMSK_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_WAKMSK_SUPPORT)
3558                       |(uint32_t)kFLEXCAN_WakeUpInterruptEnable
3559 #endif
3560 #if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE)
3561                       | (uint64_t)kFLEXCAN_PNMatchWakeUpInterruptEnable |
3562                       (uint64_t)kFLEXCAN_PNTimeoutWakeUpInterruptEnable
3563 #endif
3564 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
3565 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_HANCEI_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_HANCEI_SUPPORT)
3566                     | (uint64_t)kFLEXCAN_HostAccessNCErrorInterruptEnable |
3567 #endif
3568 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_FANCEI_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_FANCEI_SUPPORT)
3569                     (uint64_t)kFLEXCAN_FlexCanAccessNCErrorInterruptEnable |
3570 #endif
3571 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_CEI_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_CEI_SUPPORT)
3572                     (uint64_t)kFLEXCAN_HostOrFlexCanCErrorInterruptEnable
3573 #endif
3574 #endif
3575         );
3576     }
3577     else
3578     {
3579         FLEXCAN_DisableInterrupts(
3580             base, (uint32_t)kFLEXCAN_BusOffInterruptEnable | (uint32_t)kFLEXCAN_ErrorInterruptEnable |
3581                       (uint32_t)kFLEXCAN_RxWarningInterruptEnable | (uint32_t)kFLEXCAN_TxWarningInterruptEnable
3582 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_WAKMSK_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_WAKMSK_SUPPORT)
3583                       |(uint32_t)kFLEXCAN_WakeUpInterruptEnable
3584 #endif
3585 #if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE)
3586                       | (uint64_t)kFLEXCAN_PNMatchWakeUpInterruptEnable |
3587                       (uint64_t)kFLEXCAN_PNTimeoutWakeUpInterruptEnable
3588 #endif
3589 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
3590 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_HANCEI_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_HANCEI_SUPPORT)
3591                     | (uint64_t)kFLEXCAN_HostAccessNCErrorInterruptEnable |
3592 #endif
3593 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_FANCEI_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_FANCEI_SUPPORT)
3594                     (uint64_t)kFLEXCAN_FlexCanAccessNCErrorInterruptEnable |
3595 #endif
3596 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_CEI_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_CEI_SUPPORT)
3597                     (uint64_t)kFLEXCAN_HostOrFlexCanCErrorInterruptEnable
3598 #endif
3599 #endif
3600         );
3601     }
3602 
3603     /* Enable interrupts in NVIC. */
3604     (void)EnableIRQ((IRQn_Type)(s_flexcanRxWarningIRQ[instance]));
3605     (void)EnableIRQ((IRQn_Type)(s_flexcanTxWarningIRQ[instance]));
3606     (void)EnableIRQ((IRQn_Type)(s_flexcanWakeUpIRQ[instance]));
3607     (void)EnableIRQ((IRQn_Type)(s_flexcanErrorIRQ[instance]));
3608     (void)EnableIRQ((IRQn_Type)(s_flexcanBusOffIRQ[instance]));
3609     (void)EnableIRQ((IRQn_Type)(s_flexcanMbIRQ[instance]));
3610 }
3611 
3612 /*!
3613  * brief Sends a message using IRQ.
3614  *
3615  * This function sends a message using IRQ. This is a non-blocking function, which returns
3616  * right away. When messages have been sent out, the send callback function is called.
3617  *
3618  * param base FlexCAN peripheral base address.
3619  * param handle FlexCAN handle pointer.
3620  * param pMbXfer FlexCAN Message Buffer transfer structure. See the #flexcan_mb_transfer_t.
3621  * retval kStatus_Success        Start Tx Message Buffer sending process successfully.
3622  * retval kStatus_Fail           Write Tx Message Buffer failed.
3623  * retval kStatus_FLEXCAN_TxBusy Tx Message Buffer is in use.
3624  */
FLEXCAN_TransferSendNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_mb_transfer_t * pMbXfer)3625 status_t FLEXCAN_TransferSendNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *pMbXfer)
3626 {
3627     /* Assertion. */
3628     assert(NULL != handle);
3629     assert(NULL != pMbXfer);
3630     assert(pMbXfer->mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
3631 #if !defined(NDEBUG)
3632     assert(!FLEXCAN_IsMbOccupied(base, pMbXfer->mbIdx));
3633 #endif
3634 
3635     status_t status;
3636 
3637     /* Check if Message Buffer is idle. */
3638     if ((uint8_t)kFLEXCAN_StateIdle == handle->mbState[pMbXfer->mbIdx])
3639     {
3640         /* Distinguish transmit type. */
3641         if ((uint32_t)kFLEXCAN_FrameTypeRemote == pMbXfer->frame->type)
3642         {
3643             handle->mbState[pMbXfer->mbIdx] = (uint8_t)kFLEXCAN_StateTxRemote;
3644         }
3645         else
3646         {
3647             handle->mbState[pMbXfer->mbIdx] = (uint8_t)kFLEXCAN_StateTxData;
3648         }
3649 
3650         if (kStatus_Success ==
3651             FLEXCAN_WriteTxMb(base, pMbXfer->mbIdx, (const flexcan_frame_t *)(uintptr_t)pMbXfer->frame))
3652         {
3653             /* Enable Message Buffer Interrupt. */
3654 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
3655             if (pMbXfer->mbIdx >= 64U)
3656             {
3657                 FLEXCAN_EnableHigh64MbInterrupts(base, (uint64_t)1U << (pMbXfer->mbIdx - 64U));
3658             }
3659             else
3660             {
3661                 FLEXCAN_EnableMbInterrupts(base, (uint64_t)1U << pMbXfer->mbIdx);
3662             }
3663 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
3664             FLEXCAN_EnableMbInterrupts(base, (uint64_t)1U << pMbXfer->mbIdx);
3665 #else
3666             FLEXCAN_EnableMbInterrupts(base, (uint32_t)1U << pMbXfer->mbIdx);
3667 #endif
3668             status = kStatus_Success;
3669         }
3670         else
3671         {
3672             handle->mbState[pMbXfer->mbIdx] = (uint8_t)kFLEXCAN_StateIdle;
3673             status                          = kStatus_Fail;
3674         }
3675     }
3676     else
3677     {
3678         status = kStatus_FLEXCAN_TxBusy;
3679     }
3680 
3681     return status;
3682 }
3683 
3684 /*!
3685  * brief Receives a message using IRQ.
3686  *
3687  * This function receives a message using IRQ. This is non-blocking function, which returns
3688  * right away. When the message has been received, the receive callback function is called.
3689  *
3690  * param base FlexCAN peripheral base address.
3691  * param handle FlexCAN handle pointer.
3692  * param pMbXfer FlexCAN Message Buffer transfer structure. See the #flexcan_mb_transfer_t.
3693  * retval kStatus_Success        - Start Rx Message Buffer receiving process successfully.
3694  * retval kStatus_FLEXCAN_RxBusy - Rx Message Buffer is in use.
3695  */
FLEXCAN_TransferReceiveNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_mb_transfer_t * pMbXfer)3696 status_t FLEXCAN_TransferReceiveNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *pMbXfer)
3697 {
3698     status_t status;
3699 
3700     /* Assertion. */
3701     assert(NULL != handle);
3702     assert(NULL != pMbXfer);
3703     assert(pMbXfer->mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
3704 #if !defined(NDEBUG)
3705     assert(!FLEXCAN_IsMbOccupied(base, pMbXfer->mbIdx));
3706 #endif
3707 
3708     /* Check if Message Buffer is idle. */
3709     if ((uint8_t)kFLEXCAN_StateIdle == handle->mbState[pMbXfer->mbIdx])
3710     {
3711         handle->mbState[pMbXfer->mbIdx] = (uint8_t)kFLEXCAN_StateRxData;
3712 
3713         /* Register Message Buffer. */
3714         handle->mbFrameBuf[pMbXfer->mbIdx] = pMbXfer->frame;
3715 
3716         /* Enable Message Buffer Interrupt. */
3717 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
3718         if (pMbXfer->mbIdx >= 64U)
3719         {
3720             FLEXCAN_EnableHigh64MbInterrupts(base, (uint64_t)1U << (pMbXfer->mbIdx - 64U));
3721         }
3722         else
3723         {
3724             FLEXCAN_EnableMbInterrupts(base, (uint64_t)1U << pMbXfer->mbIdx);
3725         }
3726 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
3727         FLEXCAN_EnableMbInterrupts(base, (uint64_t)1U << pMbXfer->mbIdx);
3728 #else
3729         FLEXCAN_EnableMbInterrupts(base, (uint32_t)1U << pMbXfer->mbIdx);
3730 #endif
3731 
3732         status = kStatus_Success;
3733     }
3734     else
3735     {
3736         status = kStatus_FLEXCAN_RxBusy;
3737     }
3738 
3739     return status;
3740 }
3741 
3742 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
3743 /*!
3744  * brief Sends a message using IRQ.
3745  *
3746  * This function sends a message using IRQ. This is a non-blocking function, which returns
3747  * right away. When messages have been sent out, the send callback function is called.
3748  *
3749  * param base FlexCAN peripheral base address.
3750  * param handle FlexCAN handle pointer.
3751  * param pMbXfer FlexCAN FD Message Buffer transfer structure. See the #flexcan_mb_transfer_t.
3752  * retval kStatus_Success        Start Tx Message Buffer sending process successfully.
3753  * retval kStatus_Fail           Write Tx Message Buffer failed.
3754  * retval kStatus_FLEXCAN_TxBusy Tx Message Buffer is in use.
3755  */
FLEXCAN_TransferFDSendNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_mb_transfer_t * pMbXfer)3756 status_t FLEXCAN_TransferFDSendNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *pMbXfer)
3757 {
3758     /* Assertion. */
3759     assert(NULL != handle);
3760     assert(NULL != pMbXfer);
3761     assert(pMbXfer->mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
3762 #if !defined(NDEBUG)
3763     assert(!FLEXCAN_IsMbOccupied(base, pMbXfer->mbIdx));
3764 #endif
3765 
3766     status_t status;
3767 
3768     /* Check if Message Buffer is idle. */
3769     if ((uint8_t)kFLEXCAN_StateIdle == handle->mbState[pMbXfer->mbIdx])
3770     {
3771         /* Distinguish transmit type. */
3772         if ((uint32_t)kFLEXCAN_FrameTypeRemote == pMbXfer->framefd->type)
3773         {
3774             handle->mbState[pMbXfer->mbIdx] = (uint8_t)kFLEXCAN_StateTxRemote;
3775         }
3776         else
3777         {
3778             handle->mbState[pMbXfer->mbIdx] = (uint8_t)kFLEXCAN_StateTxData;
3779         }
3780 
3781         if (kStatus_Success ==
3782             FLEXCAN_WriteFDTxMb(base, pMbXfer->mbIdx, (const flexcan_fd_frame_t *)(uintptr_t)pMbXfer->framefd))
3783         {
3784             /* Enable Message Buffer Interrupt. */
3785 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
3786             if (pMbXfer->mbIdx >= 64U)
3787             {
3788                 FLEXCAN_EnableHigh64MbInterrupts(base, (uint64_t)1U << (pMbXfer->mbIdx - 64U));
3789             }
3790             else
3791             {
3792                 FLEXCAN_EnableMbInterrupts(base, (uint64_t)1U << pMbXfer->mbIdx);
3793             }
3794 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
3795             FLEXCAN_EnableMbInterrupts(base, (uint64_t)1U << pMbXfer->mbIdx);
3796 #else
3797             FLEXCAN_EnableMbInterrupts(base, (uint32_t)1U << pMbXfer->mbIdx);
3798 #endif
3799 
3800             status = kStatus_Success;
3801         }
3802         else
3803         {
3804             handle->mbState[pMbXfer->mbIdx] = (uint8_t)kFLEXCAN_StateIdle;
3805             status                          = kStatus_Fail;
3806         }
3807     }
3808     else
3809     {
3810         status = kStatus_FLEXCAN_TxBusy;
3811     }
3812 
3813     return status;
3814 }
3815 
3816 /*!
3817  * brief Receives a message using IRQ.
3818  *
3819  * This function receives a message using IRQ. This is non-blocking function, which returns
3820  * right away. When the message has been received, the receive callback function is called.
3821  *
3822  * param base FlexCAN peripheral base address.
3823  * param handle FlexCAN handle pointer.
3824  * param pMbXfer FlexCAN FD Message Buffer transfer structure. See the #flexcan_mb_transfer_t.
3825  * retval kStatus_Success        - Start Rx Message Buffer receiving process successfully.
3826  * retval kStatus_FLEXCAN_RxBusy - Rx Message Buffer is in use.
3827  */
FLEXCAN_TransferFDReceiveNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_mb_transfer_t * pMbXfer)3828 status_t FLEXCAN_TransferFDReceiveNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *pMbXfer)
3829 {
3830     /* Assertion. */
3831     assert(NULL != handle);
3832     assert(NULL != pMbXfer);
3833     assert(pMbXfer->mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
3834 #if !defined(NDEBUG)
3835     assert(!FLEXCAN_IsMbOccupied(base, pMbXfer->mbIdx));
3836 #endif
3837 
3838     status_t status;
3839 
3840     /* Check if Message Buffer is idle. */
3841     if ((uint8_t)kFLEXCAN_StateIdle == handle->mbState[pMbXfer->mbIdx])
3842     {
3843         handle->mbState[pMbXfer->mbIdx] = (uint8_t)kFLEXCAN_StateRxData;
3844 
3845         /* Register Message Buffer. */
3846         handle->mbFDFrameBuf[pMbXfer->mbIdx] = pMbXfer->framefd;
3847 
3848         /* Enable Message Buffer Interrupt. */
3849 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
3850         if (pMbXfer->mbIdx >= 64U)
3851         {
3852             FLEXCAN_EnableHigh64MbInterrupts(base, (uint64_t)1U << (pMbXfer->mbIdx - 64U));
3853         }
3854         else
3855         {
3856             FLEXCAN_EnableMbInterrupts(base, (uint64_t)1U << pMbXfer->mbIdx);
3857         }
3858 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
3859         FLEXCAN_EnableMbInterrupts(base, (uint64_t)1U << pMbXfer->mbIdx);
3860 #else
3861         FLEXCAN_EnableMbInterrupts(base, (uint32_t)1U << pMbXfer->mbIdx);
3862 #endif
3863 
3864         status = kStatus_Success;
3865     }
3866     else
3867     {
3868         status = kStatus_FLEXCAN_RxBusy;
3869     }
3870 
3871     return status;
3872 }
3873 #endif
3874 
3875 /*!
3876  * brief Receives a message from Legacy Rx FIFO using IRQ.
3877  *
3878  * This function receives a message using IRQ. This is a non-blocking function, which returns
3879  * right away. When all messages have been received, the receive callback function is called.
3880  *
3881  * param base FlexCAN peripheral base address.
3882  * param handle FlexCAN handle pointer.
3883  * param pFifoXfer FlexCAN Rx FIFO transfer structure. See the ref flexcan_fifo_transfer_t.
3884  * retval kStatus_Success            - Start Rx FIFO receiving process successfully.
3885  * retval kStatus_FLEXCAN_RxFifoBusy - Rx FIFO is currently in use.
3886  */
FLEXCAN_TransferReceiveFifoNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_fifo_transfer_t * pFifoXfer)3887 status_t FLEXCAN_TransferReceiveFifoNonBlocking(CAN_Type *base,
3888                                                 flexcan_handle_t *handle,
3889                                                 flexcan_fifo_transfer_t *pFifoXfer)
3890 {
3891     /* Assertion. */
3892     assert(NULL != handle);
3893     assert(NULL != pFifoXfer);
3894 
3895     status_t status;
3896     uint32_t irqMask = (uint32_t)kFLEXCAN_RxFifoOverflowFlag | (uint32_t)kFLEXCAN_RxFifoWarningFlag;
3897 
3898     /* Check if Message Buffer is idle. */
3899     if ((uint8_t)kFLEXCAN_StateIdle == handle->rxFifoState)
3900     {
3901         handle->rxFifoState = (uint8_t)kFLEXCAN_StateRxFifo;
3902 
3903         /* Register Message Buffer. */
3904         handle->rxFifoFrameBuf         = pFifoXfer->frame;
3905         handle->rxFifoFrameNum         = pFifoXfer->frameNum;
3906         handle->rxFifoTransferTotalNum = pFifoXfer->frameNum;
3907 
3908         if (handle->rxFifoTransferTotalNum < 5U)
3909         {
3910             /* Enable data available interrupt. */
3911             irqMask |= (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag;
3912         }
3913 
3914         /* Enable Message Buffer Interrupt. */
3915         FLEXCAN_EnableMbInterrupts(base, irqMask);
3916 
3917         status = kStatus_Success;
3918     }
3919     else
3920     {
3921         status = kStatus_FLEXCAN_RxFifoBusy;
3922     }
3923 
3924     return status;
3925 }
3926 
3927 /*!
3928  * brief Gets the Legacy Rx Fifo transfer status during a interrupt non-blocking receive.
3929  *
3930  * param base FlexCAN peripheral base address.
3931  * param handle FlexCAN handle pointer.
3932  * param count Number of CAN messages receive so far by the non-blocking transaction.
3933  * retval kStatus_InvalidArgument count is Invalid.
3934  * retval kStatus_Success Successfully return the count.
3935  */
3936 
FLEXCAN_TransferGetReceiveFifoCount(CAN_Type * base,flexcan_handle_t * handle,size_t * count)3937 status_t FLEXCAN_TransferGetReceiveFifoCount(CAN_Type *base, flexcan_handle_t *handle, size_t *count)
3938 {
3939     assert(NULL != handle);
3940 
3941     status_t result = kStatus_Success;
3942 
3943     if (handle->rxFifoState == (uint32_t)kFLEXCAN_StateIdle)
3944     {
3945         result = kStatus_NoTransferInProgress;
3946     }
3947     else
3948     {
3949         *count = handle->rxFifoTransferTotalNum - handle->rxFifoFrameNum;
3950     }
3951 
3952     return result;
3953 }
3954 
3955 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
3956 /*!
3957  * brief Receives a message from Enhanced Rx FIFO using IRQ.
3958  *
3959  * This function receives a message using IRQ. This is a non-blocking function, which returns
3960  * right away. When all messages have been received, the receive callback function is called.
3961  *
3962  * param base FlexCAN peripheral base address.
3963  * param handle FlexCAN handle pointer.
3964  * param pFifoXfer FlexCAN Rx FIFO transfer structure. See the ref flexcan_fifo_transfer_t.
3965  * retval kStatus_Success            - Start Rx FIFO receiving process successfully.
3966  * retval kStatus_FLEXCAN_RxFifoBusy - Rx FIFO is currently in use.
3967  */
FLEXCAN_TransferReceiveEnhancedFifoNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_fifo_transfer_t * pFifoXfer)3968 status_t FLEXCAN_TransferReceiveEnhancedFifoNonBlocking(CAN_Type *base,
3969                                                         flexcan_handle_t *handle,
3970                                                         flexcan_fifo_transfer_t *pFifoXfer)
3971 {
3972     /* Assertion. */
3973     assert(NULL != handle);
3974     assert(NULL != pFifoXfer);
3975 
3976     status_t status;
3977     uint32_t watermark = ((base->ERFCR & CAN_ERFCR_ERFWM_MASK) >> CAN_ERFCR_ERFWM_SHIFT) + 1U;
3978     uint64_t irqMask =
3979         (uint64_t)kFLEXCAN_ERxFifoUnderflowInterruptEnable | (uint64_t)kFLEXCAN_ERxFifoOverflowInterruptEnable;
3980 
3981     /* Check if Enhanced Rx FIFO is idle. */
3982     if ((uint8_t)kFLEXCAN_StateIdle == handle->rxFifoState)
3983     {
3984         handle->rxFifoState = (uint8_t)kFLEXCAN_StateRxFifo;
3985 
3986         /* Register Message Buffer. */
3987         handle->rxFifoFDFrameBuf       = pFifoXfer->framefd;
3988         handle->rxFifoFrameNum         = pFifoXfer->frameNum;
3989         handle->rxFifoTransferTotalNum = pFifoXfer->frameNum;
3990 
3991         if (handle->rxFifoTransferTotalNum >= watermark)
3992         {
3993             /* Enable watermark interrupt. */
3994             irqMask |= (uint64_t)kFLEXCAN_ERxFifoWatermarkInterruptEnable;
3995         }
3996         else
3997         {
3998             /* Enable data available interrupt. */
3999             irqMask |= (uint64_t)kFLEXCAN_ERxFifoDataAvlInterruptEnable;
4000         }
4001         /* Enable Enhanced Rx FIFO Interrupt. */
4002         FLEXCAN_EnableInterrupts(base, irqMask);
4003 
4004         status = kStatus_Success;
4005     }
4006     else
4007     {
4008         status = kStatus_FLEXCAN_RxFifoBusy;
4009     }
4010 
4011     return status;
4012 }
4013 #endif
4014 
4015 /*!
4016  * brief Aborts the interrupt driven message send process.
4017  *
4018  * This function aborts the interrupt driven message send process.
4019  *
4020  * param base FlexCAN peripheral base address.
4021  * param handle FlexCAN handle pointer.
4022  * param mbIdx The FlexCAN Message Buffer index.
4023  */
FLEXCAN_TransferAbortSend(CAN_Type * base,flexcan_handle_t * handle,uint8_t mbIdx)4024 void FLEXCAN_TransferAbortSend(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx)
4025 {
4026     uint16_t timestamp;
4027 
4028     /* Assertion. */
4029     assert(NULL != handle);
4030     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
4031 #if !defined(NDEBUG)
4032     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
4033 #endif
4034     /* Disable Message Buffer Interrupt. */
4035 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
4036     if (mbIdx >= 64U)
4037     {
4038         FLEXCAN_DisableHigh64MbInterrupts(base, (uint64_t)1U << (mbIdx - 64U));
4039     }
4040     else
4041     {
4042         FLEXCAN_DisableMbInterrupts(base, (uint64_t)1U << mbIdx);
4043     }
4044 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
4045     FLEXCAN_DisableMbInterrupts(base, (uint64_t)1U << mbIdx);
4046 #else
4047     FLEXCAN_DisableMbInterrupts(base, (uint32_t)1U << mbIdx);
4048 #endif
4049 
4050     /* Update the TX frame 's time stamp by MB[mbIdx].cs. */
4051     timestamp                = (uint16_t)((base->MB[mbIdx].CS & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
4052     handle->timestamp[mbIdx] = timestamp;
4053 
4054     /* Clean Message Buffer. */
4055     FLEXCAN_SetTxMbConfig(base, mbIdx, true);
4056 
4057     handle->mbState[mbIdx] = (uint8_t)kFLEXCAN_StateIdle;
4058 }
4059 
4060 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
4061 /*!
4062  * brief Aborts the interrupt driven message send process.
4063  *
4064  * This function aborts the interrupt driven message send process.
4065  *
4066  * param base FlexCAN peripheral base address.
4067  * param handle FlexCAN handle pointer.
4068  * param mbIdx The FlexCAN FD Message Buffer index.
4069  */
FLEXCAN_TransferFDAbortSend(CAN_Type * base,flexcan_handle_t * handle,uint8_t mbIdx)4070 void FLEXCAN_TransferFDAbortSend(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx)
4071 {
4072     volatile uint32_t *mbAddr;
4073     uint32_t offset;
4074     uint16_t timestamp;
4075 
4076     /* Assertion. */
4077     assert(NULL != handle);
4078     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
4079 #if !defined(NDEBUG)
4080     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
4081 #endif
4082 
4083     /* Disable Message Buffer Interrupt. */
4084 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
4085     if (mbIdx >= 64U)
4086     {
4087         FLEXCAN_DisableHigh64MbInterrupts(base, (uint64_t)1U << (mbIdx - 64U));
4088     }
4089     else
4090     {
4091         FLEXCAN_DisableMbInterrupts(base, (uint64_t)1U << mbIdx);
4092     }
4093 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
4094     FLEXCAN_DisableMbInterrupts(base, (uint64_t)1U << mbIdx);
4095 #else
4096     FLEXCAN_DisableMbInterrupts(base, (uint32_t)1U << mbIdx);
4097 #endif
4098 
4099     /* Update the TX frame 's time stamp by base->MB[offset for CAN FD].CS. */
4100     mbAddr                   = &(base->MB[0].CS);
4101     offset                   = FLEXCAN_GetFDMailboxOffset(base, mbIdx);
4102     timestamp                = (uint16_t)((mbAddr[offset] & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
4103     handle->timestamp[mbIdx] = timestamp;
4104 
4105     /* Clean Message Buffer. */
4106     FLEXCAN_SetFDTxMbConfig(base, mbIdx, true);
4107 
4108     handle->mbState[mbIdx] = (uint8_t)kFLEXCAN_StateIdle;
4109 }
4110 
4111 /*!
4112  * brief Aborts the interrupt driven message receive process.
4113  *
4114  * This function aborts the interrupt driven message receive process.
4115  *
4116  * param base FlexCAN peripheral base address.
4117  * param handle FlexCAN handle pointer.
4118  * param mbIdx The FlexCAN FD Message Buffer index.
4119  */
FLEXCAN_TransferFDAbortReceive(CAN_Type * base,flexcan_handle_t * handle,uint8_t mbIdx)4120 void FLEXCAN_TransferFDAbortReceive(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx)
4121 {
4122     /* Assertion. */
4123     assert(NULL != handle);
4124     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
4125 #if !defined(NDEBUG)
4126     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
4127 #endif
4128 
4129     /* Disable Message Buffer Interrupt. */
4130 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
4131     if (mbIdx >= 64U)
4132     {
4133         FLEXCAN_DisableHigh64MbInterrupts(base, (uint64_t)1U << (mbIdx - 64U));
4134     }
4135     else
4136     {
4137         FLEXCAN_DisableMbInterrupts(base, (uint64_t)1U << mbIdx);
4138     }
4139 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
4140     FLEXCAN_DisableMbInterrupts(base, (uint64_t)1U << mbIdx);
4141 #else
4142     FLEXCAN_DisableMbInterrupts(base, (uint32_t)1U << mbIdx);
4143 #endif
4144 
4145     /* Un-register handle. */
4146     handle->mbFDFrameBuf[mbIdx] = NULL;
4147     handle->mbState[mbIdx]      = (uint8_t)kFLEXCAN_StateIdle;
4148 }
4149 #endif
4150 
4151 /*!
4152  * brief Aborts the interrupt driven message receive process.
4153  *
4154  * This function aborts the interrupt driven message receive process.
4155  *
4156  * param base FlexCAN peripheral base address.
4157  * param handle FlexCAN handle pointer.
4158  * param mbIdx The FlexCAN Message Buffer index.
4159  */
FLEXCAN_TransferAbortReceive(CAN_Type * base,flexcan_handle_t * handle,uint8_t mbIdx)4160 void FLEXCAN_TransferAbortReceive(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx)
4161 {
4162     /* Assertion. */
4163     assert(NULL != handle);
4164     assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
4165 #if !defined(NDEBUG)
4166     assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
4167 #endif
4168 
4169     /* Disable Message Buffer Interrupt. */
4170 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
4171     if (mbIdx >= 64U)
4172     {
4173         FLEXCAN_DisableHigh64MbInterrupts(base, (uint64_t)1U << (mbIdx - 64U));
4174     }
4175     else
4176     {
4177         FLEXCAN_DisableMbInterrupts(base, (uint64_t)1U << mbIdx);
4178     }
4179 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
4180     FLEXCAN_DisableMbInterrupts(base, (uint64_t)1U << mbIdx);
4181 #else
4182     FLEXCAN_DisableMbInterrupts(base, (uint32_t)1U << mbIdx);
4183 #endif
4184 
4185     /* Un-register handle. */
4186     handle->mbFrameBuf[mbIdx] = NULL;
4187     handle->mbState[mbIdx]    = (uint8_t)kFLEXCAN_StateIdle;
4188 }
4189 
4190 /*!
4191  * brief Aborts the interrupt driven message receive from Legacy Rx FIFO process.
4192  *
4193  * This function aborts the interrupt driven message receive from Legacy Rx FIFO process.
4194  *
4195  * param base FlexCAN peripheral base address.
4196  * param handle FlexCAN handle pointer.
4197  */
FLEXCAN_TransferAbortReceiveFifo(CAN_Type * base,flexcan_handle_t * handle)4198 void FLEXCAN_TransferAbortReceiveFifo(CAN_Type *base, flexcan_handle_t *handle)
4199 {
4200     /* Assertion. */
4201     assert(NULL != handle);
4202 
4203     /* Check if Rx FIFO is enabled. */
4204     if (0U != (base->MCR & CAN_MCR_RFEN_MASK))
4205     {
4206         /* Disable Rx Message FIFO Interrupts. */
4207         FLEXCAN_DisableMbInterrupts(base, (uint32_t)kFLEXCAN_RxFifoOverflowFlag | (uint32_t)kFLEXCAN_RxFifoWarningFlag |
4208                                               (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag);
4209 
4210         /* Un-register handle. */
4211         handle->rxFifoFrameBuf = NULL;
4212         /* Clear transfer count. */
4213         handle->rxFifoFrameNum         = 0U;
4214         handle->rxFifoTransferTotalNum = 0U;
4215     }
4216 
4217     handle->rxFifoState = (uint8_t)kFLEXCAN_StateIdle;
4218 }
4219 
4220 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
4221 /*!
4222  * brief Aborts the interrupt driven message receive from Enhanced Rx FIFO process.
4223  *
4224  * This function aborts the interrupt driven message receive from Rx FIFO process.
4225  *
4226  * param base FlexCAN peripheral base address.
4227  * param handle FlexCAN handle pointer.
4228  */
FLEXCAN_TransferAbortReceiveEnhancedFifo(CAN_Type * base,flexcan_handle_t * handle)4229 void FLEXCAN_TransferAbortReceiveEnhancedFifo(CAN_Type *base, flexcan_handle_t *handle)
4230 {
4231     /* Assertion. */
4232     assert(NULL != handle);
4233 
4234     /* Check if Enhanced Rx FIFO is enabled. */
4235     if (0U != (base->ERFCR & CAN_ERFCR_ERFEN_MASK))
4236     {
4237         /* Disable all Rx Message FIFO interrupts. */
4238         FLEXCAN_DisableInterrupts(base, (uint64_t)kFLEXCAN_ERxFifoUnderflowInterruptEnable |
4239                                             (uint64_t)kFLEXCAN_ERxFifoOverflowInterruptEnable |
4240                                             (uint64_t)kFLEXCAN_ERxFifoWatermarkInterruptEnable |
4241                                             (uint64_t)kFLEXCAN_ERxFifoDataAvlInterruptEnable);
4242 
4243         /* Un-register handle. */
4244         handle->rxFifoFDFrameBuf = NULL;
4245         /* Clear transfer count. */
4246         handle->rxFifoFrameNum         = 0U;
4247         handle->rxFifoTransferTotalNum = 0U;
4248     }
4249 
4250     handle->rxFifoState = (uint8_t)kFLEXCAN_StateIdle;
4251 }
4252 #endif
4253 
4254 /*!
4255  * brief Gets the detail index of Mailbox's Timestamp by handle.
4256  *
4257  * Then function can only be used when calling non-blocking Data transfer (TX/RX) API,
4258  * After TX/RX data transfer done (User can get the status by handler's callback function),
4259  * we can get the detail index of Mailbox's timestamp by handle,
4260  * Detail non-blocking data transfer API (TX/RX) contain.
4261  *   -FLEXCAN_TransferSendNonBlocking
4262  *   -FLEXCAN_TransferFDSendNonBlocking
4263  *   -FLEXCAN_TransferReceiveNonBlocking
4264  *   -FLEXCAN_TransferFDReceiveNonBlocking
4265  *   -FLEXCAN_TransferReceiveFifoNonBlocking
4266  *
4267  * param handle FlexCAN handle pointer.
4268  * param mbIdx The FlexCAN FD Message Buffer index.
4269  * return the index of mailbox 's timestamp stored in the handle.
4270  *
4271  */
FLEXCAN_GetTimeStamp(flexcan_handle_t * handle,uint8_t mbIdx)4272 uint32_t FLEXCAN_GetTimeStamp(flexcan_handle_t *handle, uint8_t mbIdx)
4273 {
4274     /* Assertion. */
4275     assert(NULL != handle);
4276 
4277     return (uint32_t)(handle->timestamp[mbIdx]);
4278 }
4279 
4280 /*!
4281  * brief Check unhandle interrupt events
4282  *
4283  * param base FlexCAN peripheral base address.
4284  * return TRUE if unhandled interrupt action exist, FALSE if no unhandlered interrupt action exist.
4285  */
FLEXCAN_CheckUnhandleInterruptEvents(CAN_Type * base)4286 static bool FLEXCAN_CheckUnhandleInterruptEvents(CAN_Type *base)
4287 {
4288     uint64_t tempmask;
4289     uint64_t tempflag;
4290     bool fgRet = false;
4291 
4292     if (0U == (FLEXCAN_GetStatusFlags(base) &
4293                (FLEXCAN_ERROR_AND_STATUS_INIT_FLAG
4294 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_SLFWAK_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_SLFWAK_SUPPORT)
4295                | FLEXCAN_WAKE_UP_FLAG
4296 #endif
4297                | FLEXCAN_MEMORY_ENHANCED_RX_FIFO_INIT_FLAG)))
4298     {
4299         /* If no error, wake_up or enhanced RX FIFO status, Checking whether exist MB interrupt status and legacy RX
4300          * FIFO interrupt status */
4301         tempmask = (uint64_t)base->IMASK1;
4302         tempflag = (uint64_t)base->IFLAG1;
4303 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
4304         tempmask |= ((uint64_t)base->IMASK2) << 32;
4305         tempflag |= ((uint64_t)base->IFLAG2) << 32;
4306 #endif
4307         fgRet = (0U != (tempmask & tempflag));
4308 #if defined(CAN_IMASK3_BUF95TO64M_MASK)
4309         if (0U != (base->IMASK3 & base->IFLAG3))
4310         {
4311             fgRet = true;
4312         }
4313 #endif
4314 #if defined(CAN_IMASK4_BUF127TO96M_MASK)
4315         if (0U != (base->IMASK4 & base->IFLAG4))
4316         {
4317             fgRet = true;
4318         }
4319 #endif
4320     }
4321 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
4322     else if (0U != (FLEXCAN_GetStatusFlags(base) & FLEXCAN_MEMORY_ENHANCED_RX_FIFO_INIT_FLAG))
4323     {
4324         /* Checking whether exist enhanced RX FIFO interrupt status. */
4325         tempmask = (uint64_t)base->ERFIER;
4326         tempflag = (uint64_t)base->ERFSR;
4327         fgRet    = (0U != (tempmask & tempflag));
4328     }
4329 #endif
4330     else
4331     {
4332         /* Exist error or wake up flag. */
4333         fgRet = true;
4334     }
4335 
4336     return fgRet;
4337 }
4338 
4339 /*!
4340  * brief Sub Handler Legacy Rx FIFO Trasfered Events
4341  *
4342  * param base FlexCAN peripheral base address.
4343  * param handle FlexCAN handle pointer.
4344  * param result The MB flag number.
4345  *
4346  * return the status after handle transfered event.
4347  */
FLEXCAN_SubHandlerForLegacyRxFIFO(CAN_Type * base,flexcan_handle_t * handle,uint32_t result)4348 static status_t FLEXCAN_SubHandlerForLegacyRxFIFO(CAN_Type *base, flexcan_handle_t *handle, uint32_t result)
4349 {
4350     uint32_t u32mask = 1;
4351     status_t status  = kStatus_FLEXCAN_UnHandled;
4352 
4353     switch (u32mask << result)
4354     {
4355         case kFLEXCAN_RxFifoOverflowFlag:
4356             status = kStatus_FLEXCAN_RxFifoOverflow;
4357             break;
4358 
4359         case kFLEXCAN_RxFifoWarningFlag:
4360             if ((handle->rxFifoFrameNum > 5U) && (0U != (base->IFLAG1 & (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag)))
4361             {
4362                 for (uint32_t i = 0; i < 5UL; i++)
4363                 {
4364                     status = FLEXCAN_ReadRxFifo(base, handle->rxFifoFrameBuf);
4365                     /*
4366                      * $Branch Coverage Justification$
4367                      * (kStatus_Success != status) not covered. $ref flexcan_c_ref_1$.
4368                      */
4369                     if (kStatus_Success == status)
4370                     {
4371                         /* Align the current rxfifo timestamp to the timestamp array by handle. */
4372                         handle->timestamp[i] = handle->rxFifoFrameBuf->timestamp;
4373                         handle->rxFifoFrameBuf++;
4374                         handle->rxFifoFrameNum--;
4375                         /* Clean Rx Fifo available flag to discard the frame that has been read. */
4376                         FLEXCAN_ClearMbStatusFlags(base, (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag);
4377                     }
4378                     else
4379                     {
4380                         /*
4381                          * $Line Coverage Justification$
4382                          * $ref flexcan_c_ref_1$.
4383                          */
4384                         return kStatus_FLEXCAN_RxFifoDisabled;
4385                     }
4386                 }
4387                 if (handle->rxFifoFrameNum < 5UL)
4388                 {
4389                     /* Enable data avaliable interrupt. */
4390                     FLEXCAN_EnableMbInterrupts(base, (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag);
4391                 }
4392                 status = kStatus_FLEXCAN_RxFifoBusy;
4393             }
4394             else
4395             {
4396                 /* Should enter case kFLEXCAN_RxFifoFrameAvlFlag but not, means previous transfer may have
4397                  * overflow*/
4398                 status = kStatus_FLEXCAN_RxFifoWarning;
4399             }
4400             break;
4401 
4402         case kFLEXCAN_RxFifoFrameAvlFlag:
4403             /* Whether still has CAN messages remaining to be received. */
4404             if (handle->rxFifoFrameNum > 0U)
4405             {
4406                 status = FLEXCAN_ReadRxFifo(base, handle->rxFifoFrameBuf);
4407                 /*
4408                  * $Branch Coverage Justification$
4409                  * (kStatus_Success != status) not covered. $ref flexcan_c_ref_1$.
4410                  */
4411                 if (kStatus_Success == status)
4412                 {
4413                     /* Align the current (index 0) rxfifo timestamp to the timestamp array by handle. */
4414                     handle->timestamp[0] = handle->rxFifoFrameBuf->timestamp;
4415                     handle->rxFifoFrameBuf++;
4416                     handle->rxFifoFrameNum--;
4417                 }
4418                 else
4419                 {
4420                     /*
4421                      * $Line Coverage Justification$
4422                      * $ref flexcan_c_ref_1$.
4423                      */
4424                     return kStatus_FLEXCAN_RxFifoDisabled;
4425                 }
4426             }
4427             if (handle->rxFifoFrameNum == 0U)
4428             {
4429                 /* Stop receiving Ehanced Rx FIFO when the transmission is over. */
4430                 FLEXCAN_TransferAbortReceiveFifo(base, handle);
4431                 status = kStatus_FLEXCAN_RxFifoIdle;
4432             }
4433             else
4434             {
4435                 /* Continue use data avaliable interrupt. */
4436                 status = kStatus_FLEXCAN_RxFifoBusy;
4437             }
4438             break;
4439 
4440         default:
4441             status = kStatus_FLEXCAN_UnHandled;
4442             break;
4443     }
4444 
4445     return status;
4446 }
4447 
4448 /*!
4449  * brief Sub Handler Message Buffer Trasfered Events
4450  *
4451  * param base FlexCAN peripheral base address.
4452  * param handle FlexCAN handle pointer.
4453  * param result The MB flag number.
4454  *
4455  * return the status after handle transfered event.
4456  */
FLEXCAN_SubHandlerForMB(CAN_Type * base,flexcan_handle_t * handle,uint32_t result)4457 static status_t FLEXCAN_SubHandlerForMB(CAN_Type *base, flexcan_handle_t *handle, uint32_t result)
4458 {
4459     status_t status = kStatus_FLEXCAN_UnHandled;
4460 
4461     /* Get current State of Message Buffer. */
4462     switch (handle->mbState[result])
4463     {
4464         /* Solve Rx Data Frame. */
4465         case (uint8_t)kFLEXCAN_StateRxData:
4466 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
4467             if (0U != (base->MCR & CAN_MCR_FDEN_MASK))
4468             {
4469                 status = FLEXCAN_ReadFDRxMb(base, (uint8_t)result, handle->mbFDFrameBuf[result]);
4470                 if ((kStatus_Success == status) || (kStatus_FLEXCAN_RxOverflow == status))
4471                 {
4472                     /* Align the current index of RX MB timestamp to the timestamp array by handle. */
4473                     handle->timestamp[result] = handle->mbFDFrameBuf[result]->timestamp;
4474 
4475                     if (kStatus_Success == status)
4476                     {
4477                         status = kStatus_FLEXCAN_RxIdle;
4478                     }
4479                 }
4480             }
4481             else
4482 #endif
4483             {
4484                 status = FLEXCAN_ReadRxMb(base, (uint8_t)result, handle->mbFrameBuf[result]);
4485                 if ((kStatus_Success == status) || (kStatus_FLEXCAN_RxOverflow == status))
4486                 {
4487                     /* Align the current index of RX MB timestamp to the timestamp array by handle. */
4488                     handle->timestamp[result] = handle->mbFrameBuf[result]->timestamp;
4489 
4490                     if (kStatus_Success == status)
4491                     {
4492                         status = kStatus_FLEXCAN_RxIdle;
4493                     }
4494                 }
4495             }
4496 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
4497             if (0U != (base->MCR & CAN_MCR_FDEN_MASK))
4498             {
4499                 FLEXCAN_TransferFDAbortReceive(base, handle, (uint8_t)result);
4500             }
4501             else
4502 #endif
4503             {
4504                 FLEXCAN_TransferAbortReceive(base, handle, (uint8_t)result);
4505             }
4506             break;
4507 
4508         /* Sove Rx Remote Frame.  User need to Read the frame in Mail box in time by Read from MB API. */
4509         case (uint8_t)kFLEXCAN_StateRxRemote:
4510             status = kStatus_FLEXCAN_RxRemote;
4511 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
4512             if (0U != (base->MCR & CAN_MCR_FDEN_MASK))
4513             {
4514                 FLEXCAN_TransferFDAbortReceive(base, handle, (uint8_t)result);
4515             }
4516             else
4517 #endif
4518             {
4519                 FLEXCAN_TransferAbortReceive(base, handle, (uint8_t)result);
4520             }
4521             break;
4522 
4523         /* Solve Tx Data Frame. */
4524         case (uint8_t)kFLEXCAN_StateTxData:
4525             status = kStatus_FLEXCAN_TxIdle;
4526 #if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
4527             if (0U != (base->MCR & CAN_MCR_FDEN_MASK))
4528             {
4529                 FLEXCAN_TransferFDAbortSend(base, handle, (uint8_t)result);
4530             }
4531             else
4532 #endif
4533             {
4534                 FLEXCAN_TransferAbortSend(base, handle, (uint8_t)result);
4535             }
4536             break;
4537 
4538         /* Solve Tx Remote Frame. */
4539         case (uint8_t)kFLEXCAN_StateTxRemote:
4540             handle->mbState[result] = (uint8_t)kFLEXCAN_StateRxRemote;
4541             status                  = kStatus_FLEXCAN_TxSwitchToRx;
4542             break;
4543 
4544         default:
4545             status = kStatus_FLEXCAN_UnHandled;
4546             break;
4547     }
4548 
4549     return status;
4550 }
4551 
4552 /*!
4553  * brief Sub Handler Data Trasfered Events
4554  *
4555  * param base FlexCAN peripheral base address.
4556  * param handle FlexCAN handle pointer.
4557  * param pResult Pointer to the Handle result.
4558  *
4559  * return the status after handle each data transfered event.
4560  */
FLEXCAN_SubHandlerForDataTransfered(CAN_Type * base,flexcan_handle_t * handle,uint32_t * pResult)4561 static status_t FLEXCAN_SubHandlerForDataTransfered(CAN_Type *base, flexcan_handle_t *handle, uint32_t *pResult)
4562 {
4563     status_t status = kStatus_FLEXCAN_UnHandled;
4564     uint32_t result = 0xFFU;
4565 
4566 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
4567     uint32_t intflag[4] = {(base->IMASK1 & base->IFLAG1), (base->IMASK2 & base->IFLAG2), 0U, 0U};
4568 #if defined(CAN_IMASK3_BUF95TO64M_MASK)
4569     intflag[2] = base->IMASK3 & base->IFLAG3;
4570 #endif
4571 #if defined(CAN_IMASK4_BUF127TO96M_MASK)
4572     intflag[3] = base->IMASK4 & base->IFLAG4;
4573 #endif
4574 #else
4575     uint32_t intflag = base->IMASK1 & base->IFLAG1;
4576 #endif
4577 
4578     /* For this implementation, we solve the Message with lowest MB index first. */
4579 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
4580     for (uint32_t i = 0U; i < 4U; i++)
4581     {
4582         if (intflag[i] != 0U)
4583         {
4584             for (uint32_t j = 0U; j < 32U; j++)
4585             {
4586                 if (0UL != (intflag[i] & ((uint32_t)1UL << j)))
4587                 {
4588                     result = i * 32U + j;
4589                     break;
4590                 }
4591             }
4592             break;
4593         }
4594     }
4595 #else
4596     for (result = 0U; result < (uint32_t)FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); result++)
4597     {
4598         if (0UL != (intflag & ((uint32_t)1UL << result)))
4599         {
4600             break;
4601         }
4602     }
4603 #endif
4604 
4605     /* find Message to deal with. */
4606     if (result < (uint32_t)FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base))
4607     {
4608         /* Solve Legacy Rx FIFO interrupt. */
4609         if (((uint8_t)kFLEXCAN_StateIdle != handle->rxFifoState) && (result <= (uint32_t)CAN_IFLAG1_BUF7I_SHIFT) &&
4610             ((base->MCR & CAN_MCR_RFEN_MASK) != 0U))
4611         {
4612             status = FLEXCAN_SubHandlerForLegacyRxFIFO(base, handle, result);
4613             /*
4614              * $Branch Coverage Justification$
4615              * (status == kStatus_FLEXCAN_RxFifoDisabled) not covered. $ref flexcan_c_ref_1$.
4616              */
4617             if (status == kStatus_FLEXCAN_RxFifoDisabled)
4618             {
4619                 /*
4620                  * $Line Coverage Justification$
4621                  * $ref flexcan_c_ref_1$.
4622                  */
4623                 return status;
4624             }
4625         }
4626         else
4627         {
4628             status = FLEXCAN_SubHandlerForMB(base, handle, result);
4629         }
4630 
4631         /* Clear resolved Message Buffer IRQ. */
4632 #if (defined(FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB) && FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB)
4633         if (result >= 64U)
4634         {
4635             FLEXCAN_ClearHigh64MbStatusFlags(base, (uint64_t)1U << (result - 64U));
4636         }
4637         else
4638         {
4639             FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << result);
4640         }
4641 #elif (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
4642         FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1U << result);
4643 #else
4644         FLEXCAN_ClearMbStatusFlags(base, (uint32_t)1U << result);
4645 #endif
4646     }
4647 
4648     *pResult = result;
4649 
4650     return status;
4651 }
4652 
4653 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
4654 /*!
4655  * brief Sub Handler Ehanced Rx FIFO event
4656  *
4657  * param base FlexCAN peripheral base address.
4658  * param handle FlexCAN handle pointer.
4659  * param flags FlexCAN interrupt flags.
4660  *
4661  * return the status after handle Ehanced Rx FIFO event.
4662  */
FLEXCAN_SubHandlerForEhancedRxFifo(CAN_Type * base,flexcan_handle_t * handle,uint64_t flags)4663 static status_t FLEXCAN_SubHandlerForEhancedRxFifo(CAN_Type *base, flexcan_handle_t *handle, uint64_t flags)
4664 {
4665     uint32_t watermark = ((base->ERFCR & CAN_ERFCR_ERFWM_MASK) >> CAN_ERFCR_ERFWM_SHIFT) + 1U;
4666     uint32_t transferFrames;
4667 
4668     status_t status;
4669     /* Solve Ehanced Rx FIFO interrupt. */
4670     if ((0u != (flags & (uint64_t)kFLEXCAN_ERxFifoUnderflowIntFlag)) &&
4671         (0u != (base->ERFIER & CAN_ERFIER_ERFUFWIE_MASK)))
4672     {
4673         status = kStatus_FLEXCAN_RxFifoUnderflow;
4674         FLEXCAN_ClearStatusFlags(base, (uint64_t)kFLEXCAN_ERxFifoUnderflowIntFlag);
4675     }
4676     else if ((0u != (flags & (uint64_t)kFLEXCAN_ERxFifoOverflowIntFlag)) &&
4677              (0u != (base->ERFIER & CAN_ERFIER_ERFOVFIE_MASK)))
4678     {
4679         status = kStatus_FLEXCAN_RxFifoOverflow;
4680         FLEXCAN_ClearStatusFlags(base, (uint64_t)kFLEXCAN_ERxFifoOverflowIntFlag);
4681     }
4682     else if ((0u != (flags & (uint64_t)kFLEXCAN_ERxFifoWatermarkIntFlag)) &&
4683              (0u != (base->ERFIER & CAN_ERFIER_ERFWMIIE_MASK)))
4684     {
4685         /* Whether the number of CAN messages remaining to be received is greater than the watermark. */
4686         transferFrames = (handle->rxFifoFrameNum > watermark) ? watermark : handle->rxFifoFrameNum;
4687 
4688         for (uint32_t i = 0; i < transferFrames; i++)
4689         {
4690             status = FLEXCAN_ReadEnhancedRxFifo(base, handle->rxFifoFDFrameBuf);
4691 
4692             if (kStatus_Success == status)
4693             {
4694                 handle->rxFifoFDFrameBuf++;
4695                 handle->rxFifoFrameNum--;
4696                 /* Clear data Watermark flag due to has read back one frame. */
4697                 base->ERFSR = CAN_ERFSR_ERFWMI_MASK;
4698             }
4699             else
4700             {
4701                 return kStatus_FLEXCAN_RxFifoDisabled;
4702             }
4703         }
4704         if (handle->rxFifoFrameNum == 0U)
4705         {
4706             /* Stop receiving Ehanced Rx FIFO when the transmission is over. */
4707             FLEXCAN_TransferAbortReceiveEnhancedFifo(base, handle);
4708             status = kStatus_FLEXCAN_RxFifoIdle;
4709         }
4710         else if (handle->rxFifoFrameNum < watermark)
4711         {
4712             /* Disable watermark interrupt and enable data avaliable interrupt. */
4713             FLEXCAN_DisableInterrupts(base, (uint64_t)kFLEXCAN_ERxFifoWatermarkInterruptEnable);
4714             FLEXCAN_EnableInterrupts(base, (uint64_t)kFLEXCAN_ERxFifoDataAvlInterruptEnable);
4715             status = kStatus_FLEXCAN_RxFifoBusy;
4716         }
4717         else
4718         {
4719             /* Continue use watermark interrupt. */
4720             status = kStatus_FLEXCAN_RxFifoBusy;
4721         }
4722     }
4723     else
4724     {
4725         /* Data available status, check Whether still has CAN messages remaining to be received. */
4726         if (handle->rxFifoFrameNum > 0U)
4727         {
4728             status = FLEXCAN_ReadEnhancedRxFifo(base, handle->rxFifoFDFrameBuf);
4729 
4730             if (kStatus_Success == status)
4731             {
4732                 handle->rxFifoFDFrameBuf++;
4733                 handle->rxFifoFrameNum--;
4734             }
4735             else
4736             {
4737                 return kStatus_FLEXCAN_RxFifoDisabled;
4738             }
4739         }
4740         if (handle->rxFifoFrameNum == 0U)
4741         {
4742             /* Stop receiving Ehanced Rx FIFO when the transmission is over. */
4743             FLEXCAN_TransferAbortReceiveEnhancedFifo(base, handle);
4744             status = kStatus_FLEXCAN_RxFifoIdle;
4745         }
4746         else
4747         {
4748             /* Continue use data avaliable interrupt. */
4749             status = kStatus_FLEXCAN_RxFifoBusy;
4750         }
4751     }
4752     return status;
4753 }
4754 #endif
4755 
4756 /*!
4757  * brief FlexCAN IRQ handle function.
4758  *
4759  * This function handles the FlexCAN Error, the Message Buffer, and the Rx FIFO IRQ request.
4760  *
4761  * param base FlexCAN peripheral base address.
4762  * param handle FlexCAN handle pointer.
4763  */
FLEXCAN_TransferHandleIRQ(CAN_Type * base,flexcan_handle_t * handle)4764 void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle)
4765 {
4766     /* Assertion. */
4767     assert(NULL != handle);
4768 
4769     status_t status;
4770     uint32_t mbNum = 0xFFU;
4771 #if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE) ||                   \
4772     (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) || \
4773     (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
4774     uint64_t result = 0U;
4775 #else
4776     uint32_t result = 0U;
4777 #endif
4778     do
4779     {
4780         /* Get Current FlexCAN Module Error and Status. */
4781         result = FLEXCAN_GetStatusFlags(base);
4782 
4783         /* To handle FlexCAN Error and Status Interrupt first. */
4784         if (0U != (result & FLEXCAN_ERROR_AND_STATUS_INIT_FLAG))
4785         {
4786             status = kStatus_FLEXCAN_ErrorStatus;
4787             /* Clear FlexCAN Error and Status Interrupt. */
4788             FLEXCAN_ClearStatusFlags(base, FLEXCAN_ERROR_AND_STATUS_INIT_FLAG);
4789         }
4790 #if !(defined(FSL_FEATURE_FLEXCAN_HAS_NO_SLFWAK_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_NO_SLFWAK_SUPPORT)
4791         else if (0U != (result & FLEXCAN_WAKE_UP_FLAG))
4792         {
4793             status = kStatus_FLEXCAN_WakeUp;
4794             FLEXCAN_ClearStatusFlags(base, FLEXCAN_WAKE_UP_FLAG);
4795         }
4796 #endif
4797 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
4798         else if (0U != (FLEXCAN_EFIFO_STATUS_UNMASK(result & FLEXCAN_MEMORY_ENHANCED_RX_FIFO_INIT_FLAG) & base->ERFIER))
4799         {
4800             status = FLEXCAN_SubHandlerForEhancedRxFifo(base, handle, result);
4801         }
4802 #endif
4803         else
4804         {
4805             /* To handle Message Buffer or Legacy Rx FIFO transfer. */
4806             status = FLEXCAN_SubHandlerForDataTransfered(base, handle, &mbNum);
4807             result = mbNum;
4808         }
4809 
4810         /* Calling Callback Function if has one. */
4811         if (handle->callback != NULL)
4812         {
4813             handle->callback(base, handle, status, result, handle->userData);
4814         }
4815     } while (FLEXCAN_CheckUnhandleInterruptEvents(base));
4816 }
4817 
4818 #if defined(CAN0)
4819 void CAN0_DriverIRQHandler(void);
CAN0_DriverIRQHandler(void)4820 void CAN0_DriverIRQHandler(void)
4821 {
4822     assert(NULL != s_flexcanHandle[0]);
4823 
4824     s_flexcanIsr(CAN0, s_flexcanHandle[0]);
4825     SDK_ISR_EXIT_BARRIER;
4826 }
4827 #endif
4828 
4829 #if defined(CAN1)
4830 void CAN1_DriverIRQHandler(void);
CAN1_DriverIRQHandler(void)4831 void CAN1_DriverIRQHandler(void)
4832 {
4833     assert(NULL != s_flexcanHandle[1]);
4834 
4835     s_flexcanIsr(CAN1, s_flexcanHandle[1]);
4836     SDK_ISR_EXIT_BARRIER;
4837 }
4838 #endif
4839 
4840 #if defined(CAN2)
4841 void CAN2_DriverIRQHandler(void);
CAN2_DriverIRQHandler(void)4842 void CAN2_DriverIRQHandler(void)
4843 {
4844     assert(NULL != s_flexcanHandle[2]);
4845 
4846     s_flexcanIsr(CAN2, s_flexcanHandle[2]);
4847     SDK_ISR_EXIT_BARRIER;
4848 }
4849 #endif
4850 
4851 #if defined(CAN3)
4852 void CAN3_DriverIRQHandler(void);
CAN3_DriverIRQHandler(void)4853 void CAN3_DriverIRQHandler(void)
4854 {
4855     assert(NULL != s_flexcanHandle[3]);
4856 
4857     s_flexcanIsr(CAN3, s_flexcanHandle[3]);
4858     SDK_ISR_EXIT_BARRIER;
4859 }
4860 #endif
4861 
4862 #if defined(CAN4)
4863 void CAN4_DriverIRQHandler(void);
CAN4_DriverIRQHandler(void)4864 void CAN4_DriverIRQHandler(void)
4865 {
4866     assert(NULL != s_flexcanHandle[4]);
4867 
4868     s_flexcanIsr(CAN4, s_flexcanHandle[4]);
4869     SDK_ISR_EXIT_BARRIER;
4870 }
4871 #endif
4872 
4873 #if defined(DMA__CAN0)
4874 void DMA_FLEXCAN0_INT_DriverIRQHandler(void);
DMA_FLEXCAN0_INT_DriverIRQHandler(void)4875 void DMA_FLEXCAN0_INT_DriverIRQHandler(void)
4876 {
4877     assert(NULL != s_flexcanHandle[FLEXCAN_GetInstance(DMA__CAN0)]);
4878 
4879     s_flexcanIsr(DMA__CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA__CAN0)]);
4880     SDK_ISR_EXIT_BARRIER;
4881 }
4882 #endif
4883 
4884 #if defined(DMA__CAN1)
4885 void DMA_FLEXCAN1_INT_DriverIRQHandler(void);
DMA_FLEXCAN1_INT_DriverIRQHandler(void)4886 void DMA_FLEXCAN1_INT_DriverIRQHandler(void)
4887 {
4888     assert(NULL != s_flexcanHandle[FLEXCAN_GetInstance(DMA__CAN1)]);
4889 
4890     s_flexcanIsr(DMA__CAN1, s_flexcanHandle[FLEXCAN_GetInstance(DMA__CAN1)]);
4891     SDK_ISR_EXIT_BARRIER;
4892 }
4893 #endif
4894 
4895 #if defined(DMA__CAN2)
4896 void DMA_FLEXCAN2_INT_DriverIRQHandler(void);
DMA_FLEXCAN2_INT_DriverIRQHandler(void)4897 void DMA_FLEXCAN2_INT_DriverIRQHandler(void)
4898 {
4899     assert(NULL != s_flexcanHandle[FLEXCAN_GetInstance(DMA__CAN2)]);
4900 
4901     s_flexcanIsr(DMA__CAN2, s_flexcanHandle[FLEXCAN_GetInstance(DMA__CAN2)]);
4902     SDK_ISR_EXIT_BARRIER;
4903 }
4904 #endif
4905 
4906 #if defined(ADMA__CAN0)
4907 void ADMA_FLEXCAN0_INT_DriverIRQHandler(void);
ADMA_FLEXCAN0_INT_DriverIRQHandler(void)4908 void ADMA_FLEXCAN0_INT_DriverIRQHandler(void)
4909 {
4910     assert(NULL != s_flexcanHandle[FLEXCAN_GetInstance(ADMA__CAN0)]);
4911 
4912     s_flexcanIsr(ADMA__CAN0, s_flexcanHandle[FLEXCAN_GetInstance(ADMA__CAN0)]);
4913     SDK_ISR_EXIT_BARRIER;
4914 }
4915 #endif
4916 
4917 #if defined(ADMA__CAN1)
4918 void ADMA_FLEXCAN1_INT_DriverIRQHandler(void);
ADMA_FLEXCAN1_INT_DriverIRQHandler(void)4919 void ADMA_FLEXCAN1_INT_DriverIRQHandler(void)
4920 {
4921     assert(NULL != s_flexcanHandle[FLEXCAN_GetInstance(ADMA__CAN1)]);
4922 
4923     s_flexcanIsr(ADMA__CAN1, s_flexcanHandle[FLEXCAN_GetInstance(ADMA__CAN1)]);
4924     SDK_ISR_EXIT_BARRIER;
4925 }
4926 #endif
4927 
4928 #if defined(ADMA__CAN2)
4929 void ADMA_FLEXCAN2_INT_DriverIRQHandler(void);
ADMA_FLEXCAN2_INT_DriverIRQHandler(void)4930 void ADMA_FLEXCAN2_INT_DriverIRQHandler(void)
4931 {
4932     assert(NULL != s_flexcanHandle[FLEXCAN_GetInstance(ADMA__CAN2)]);
4933 
4934     s_flexcanIsr(ADMA__CAN2, s_flexcanHandle[FLEXCAN_GetInstance(ADMA__CAN2)]);
4935     SDK_ISR_EXIT_BARRIER;
4936 }
4937 #endif
4938 
4939 #if defined(FLEXCAN1)
CAN_FD1_DriverIRQHandler(void)4940 void CAN_FD1_DriverIRQHandler(void)
4941 {
4942     assert(NULL != s_flexcanHandle[1]);
4943 
4944     s_flexcanIsr(FLEXCAN1, s_flexcanHandle[1]);
4945     SDK_ISR_EXIT_BARRIER;
4946 }
4947 #endif
4948 
4949 #if defined(FLEXCAN2)
CAN_FD2_DriverIRQHandler(void)4950 void CAN_FD2_DriverIRQHandler(void)
4951 {
4952     assert(NULL != s_flexcanHandle[2]);
4953 
4954     s_flexcanIsr(FLEXCAN2, s_flexcanHandle[2]);
4955     SDK_ISR_EXIT_BARRIER;
4956 }
4957 #endif
4958