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