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