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