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