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