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