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