1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * o Redistributions of source code must retain the above copyright notice, this list
9 * of conditions and the following disclaimer.
10 *
11 * o Redistributions in binary form must reproduce the above copyright notice, this
12 * list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * o Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "fsl_flexcan.h"
32
33 /*******************************************************************************
34 * Definitons
35 ******************************************************************************/
36
37 #define FLEXCAN_TIME_QUANTA_NUM (10)
38
39 /*! @brief FlexCAN Internal State. */
40 enum _flexcan_state
41 {
42 kFLEXCAN_StateIdle = 0x0, /*!< MB/RxFIFO idle.*/
43 kFLEXCAN_StateRxData = 0x1, /*!< MB receiving.*/
44 kFLEXCAN_StateRxRemote = 0x2, /*!< MB receiving remote reply.*/
45 kFLEXCAN_StateTxData = 0x3, /*!< MB transmitting.*/
46 kFLEXCAN_StateTxRemote = 0x4, /*!< MB transmitting remote request.*/
47 kFLEXCAN_StateRxFifo = 0x5, /*!< RxFIFO receiving.*/
48 };
49
50 /*! @brief FlexCAN message buffer CODE for Rx buffers. */
51 enum _flexcan_mb_code_rx
52 {
53 kFLEXCAN_RxMbInactive = 0x0, /*!< MB is not active.*/
54 kFLEXCAN_RxMbFull = 0x2, /*!< MB is full.*/
55 kFLEXCAN_RxMbEmpty = 0x4, /*!< MB is active and empty.*/
56 kFLEXCAN_RxMbOverrun = 0x6, /*!< MB is overwritten into a full buffer.*/
57 kFLEXCAN_RxMbBusy = 0x8, /*!< FlexCAN is updating the contents of the MB.*/
58 /*! The CPU must not access the MB.*/
59 kFLEXCAN_RxMbRanswer = 0xA, /*!< A frame was configured to recognize a Remote Request Frame */
60 /*! and transmit a Response Frame in return.*/
61 kFLEXCAN_RxMbNotUsed = 0xF, /*!< Not used.*/
62 };
63
64 /*! @brief FlexCAN message buffer CODE FOR Tx buffers. */
65 enum _flexcan_mb_code_tx
66 {
67 kFLEXCAN_TxMbInactive = 0x8, /*!< MB is not active.*/
68 kFLEXCAN_TxMbAbort = 0x9, /*!< MB is aborted.*/
69 kFLEXCAN_TxMbDataOrRemote = 0xC, /*!< MB is a TX Data Frame(when MB RTR = 0) or */
70 /*!< MB is a TX Remote Request Frame (when MB RTR = 1).*/
71 kFLEXCAN_TxMbTanswer = 0xE, /*!< MB is a TX Response Request Frame from */
72 /*! an incoming Remote Request Frame.*/
73 kFLEXCAN_TxMbNotUsed = 0xF, /*!< Not used.*/
74 };
75
76 /* Typedef for interrupt handler. */
77 typedef void (*flexcan_isr_t)(CAN_Type *base, flexcan_handle_t *handle);
78
79 /*******************************************************************************
80 * Prototypes
81 ******************************************************************************/
82
83 /*!
84 * @brief Get the FlexCAN instance from peripheral base address.
85 *
86 * @param base FlexCAN peripheral base address.
87 * @return FlexCAN instance.
88 */
89 uint32_t FLEXCAN_GetInstance(CAN_Type *base);
90
91 /*!
92 * @brief Enter FlexCAN Freeze Mode.
93 *
94 * This function makes the FlexCAN work under Freeze Mode.
95 *
96 * @param base FlexCAN peripheral base address.
97 */
98 static void FLEXCAN_EnterFreezeMode(CAN_Type *base);
99
100 /*!
101 * @brief Exit FlexCAN Freeze Mode.
102 *
103 * This function makes the FlexCAN leave Freeze Mode.
104 *
105 * @param base FlexCAN peripheral base address.
106 */
107 static void FLEXCAN_ExitFreezeMode(CAN_Type *base);
108
109 #if !defined(NDEBUG)
110 /*!
111 * @brief Check if Message Buffer is occupied by Rx FIFO.
112 *
113 * This function check if Message Buffer is occupied by Rx FIFO.
114 *
115 * @param base FlexCAN peripheral base address.
116 * @param mbIdx The FlexCAN Message Buffer index.
117 */
118 static bool FLEXCAN_IsMbOccupied(CAN_Type *base, uint8_t mbIdx);
119 #endif
120
121 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641)
122 /*!
123 * @brief Get the first valid Message buffer ID of give FlexCAN instance.
124 *
125 * This function is a helper function for Errata 5641 workaround.
126 *
127 * @param base FlexCAN peripheral base address.
128 * @return The first valid Message Buffer Number.
129 */
130 static uint32_t FLEXCAN_GetFirstValidMb(CAN_Type *base);
131 #endif
132
133 /*!
134 * @brief Check if Message Buffer interrupt is enabled.
135 *
136 * This function check if Message Buffer interrupt is enabled.
137 *
138 * @param base FlexCAN peripheral base address.
139 * @param mbIdx The FlexCAN Message Buffer index.
140 */
141 static bool FLEXCAN_IsMbIntEnabled(CAN_Type *base, uint8_t mbIdx);
142
143 /*!
144 * @brief Reset the FlexCAN Instance.
145 *
146 * Restores the FlexCAN module to reset state, notice that this function
147 * will set all the registers to reset state so the FlexCAN module can not work
148 * after calling this API.
149 *
150 * @param base FlexCAN peripheral base address.
151 */
152 static void FLEXCAN_Reset(CAN_Type *base);
153
154 /*!
155 * @brief Set Baud Rate of FlexCAN.
156 *
157 * This function set the baud rate of FlexCAN.
158 *
159 * @param base FlexCAN peripheral base address.
160 * @param sourceClock_Hz Source Clock in Hz.
161 * @param baudRate_Bps Baud Rate in Bps.
162 */
163 static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Bps);
164
165 /*******************************************************************************
166 * Variables
167 ******************************************************************************/
168
169 /* Array of FlexCAN peripheral base address. */
170 static CAN_Type *const s_flexcanBases[] = CAN_BASE_PTRS;
171
172 /* Array of FlexCAN IRQ number. */
173 static const IRQn_Type s_flexcanRxWarningIRQ[] = CAN_Rx_Warning_IRQS;
174 static const IRQn_Type s_flexcanTxWarningIRQ[] = CAN_Tx_Warning_IRQS;
175 static const IRQn_Type s_flexcanWakeUpIRQ[] = CAN_Wake_Up_IRQS;
176 static const IRQn_Type s_flexcanErrorIRQ[] = CAN_Error_IRQS;
177 static const IRQn_Type s_flexcanBusOffIRQ[] = CAN_Bus_Off_IRQS;
178 static const IRQn_Type s_flexcanMbIRQ[] = CAN_ORed_Message_buffer_IRQS;
179
180 /* Array of FlexCAN handle. */
181 static flexcan_handle_t *s_flexcanHandle[ARRAY_SIZE(s_flexcanBases)];
182
183 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
184 /* Array of FlexCAN clock name. */
185 static const clock_ip_name_t s_flexcanClock[] = FLEXCAN_CLOCKS;
186 #if defined(FLEXCAN_PERIPH_CLOCKS)
187 /* Array of FlexCAN serial clock name. */
188 static const clock_ip_name_t s_flexcanPeriphClock[] = FLEXCAN_PERIPH_CLOCKS;
189 #endif /* FLEXCAN_PERIPH_CLOCKS */
190 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
191
192 /* FlexCAN ISR for transactional APIs. */
193 static flexcan_isr_t s_flexcanIsr;
194
195 /*******************************************************************************
196 * Code
197 ******************************************************************************/
198
FLEXCAN_GetInstance(CAN_Type * base)199 uint32_t FLEXCAN_GetInstance(CAN_Type *base)
200 {
201 uint32_t instance;
202
203 /* Find the instance index from base address mappings. */
204 for (instance = 0; instance < ARRAY_SIZE(s_flexcanBases); instance++)
205 {
206 if (s_flexcanBases[instance] == base)
207 {
208 break;
209 }
210 }
211
212 assert(instance < ARRAY_SIZE(s_flexcanBases));
213
214 return instance;
215 }
216
FLEXCAN_EnterFreezeMode(CAN_Type * base)217 static void FLEXCAN_EnterFreezeMode(CAN_Type *base)
218 {
219 /* Set Freeze, Halt bits. */
220 base->MCR |= CAN_MCR_HALT_MASK;
221
222 /* Wait until the FlexCAN Module enter freeze mode. */
223 while (!(base->MCR & CAN_MCR_FRZACK_MASK))
224 {
225 }
226 }
227
FLEXCAN_ExitFreezeMode(CAN_Type * base)228 static void FLEXCAN_ExitFreezeMode(CAN_Type *base)
229 {
230 /* Clear Freeze, Halt bits. */
231 base->MCR &= ~CAN_MCR_HALT_MASK;
232
233 /* Wait until the FlexCAN Module exit freeze mode. */
234 while (base->MCR & CAN_MCR_FRZACK_MASK)
235 {
236 }
237 }
238
239 #if !defined(NDEBUG)
FLEXCAN_IsMbOccupied(CAN_Type * base,uint8_t mbIdx)240 static bool FLEXCAN_IsMbOccupied(CAN_Type *base, uint8_t mbIdx)
241 {
242 uint8_t lastOccupiedMb;
243
244 /* Is Rx FIFO enabled? */
245 if (base->MCR & CAN_MCR_RFEN_MASK)
246 {
247 /* Get RFFN value. */
248 lastOccupiedMb = ((base->CTRL2 & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT);
249 /* Calculate the number of last Message Buffer occupied by Rx FIFO. */
250 lastOccupiedMb = ((lastOccupiedMb + 1) * 2) + 5;
251
252 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641)
253 if (mbIdx <= (lastOccupiedMb + 1))
254 #else
255 if (mbIdx <= lastOccupiedMb)
256 #endif
257 {
258 return true;
259 }
260 else
261 {
262 return false;
263 }
264 }
265 else
266 {
267 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641)
268 if (0 == mbIdx)
269 {
270 return true;
271 }
272 else
273 {
274 return false;
275 }
276 #else
277 return false;
278 #endif
279 }
280 }
281 #endif
282
283 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641)
FLEXCAN_GetFirstValidMb(CAN_Type * base)284 static uint32_t FLEXCAN_GetFirstValidMb(CAN_Type *base)
285 {
286 uint32_t firstValidMbNum;
287
288 if (base->MCR & CAN_MCR_RFEN_MASK)
289 {
290 firstValidMbNum = ((base->CTRL2 & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT);
291 firstValidMbNum = ((firstValidMbNum + 1) * 2) + 6;
292 }
293 else
294 {
295 firstValidMbNum = 0;
296 }
297
298 return firstValidMbNum;
299 }
300 #endif
301
FLEXCAN_IsMbIntEnabled(CAN_Type * base,uint8_t mbIdx)302 static bool FLEXCAN_IsMbIntEnabled(CAN_Type *base, uint8_t mbIdx)
303 {
304 /* Assertion. */
305 assert(mbIdx < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base));
306
307 #if (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
308 if (mbIdx < 32)
309 {
310 #endif
311 if (base->IMASK1 & ((uint32_t)(1 << mbIdx)))
312 {
313 return true;
314 }
315 else
316 {
317 return false;
318 }
319 #if (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
320 }
321 else
322 {
323 if (base->IMASK2 & ((uint32_t)(1 << (mbIdx - 32))))
324 {
325 return true;
326 }
327 else
328 {
329 return false;
330 }
331 }
332 #endif
333 }
334
FLEXCAN_Reset(CAN_Type * base)335 static void FLEXCAN_Reset(CAN_Type *base)
336 {
337 /* The module must should be first exit from low power
338 * mode, and then soft reset can be applied.
339 */
340 assert(!(base->MCR & CAN_MCR_MDIS_MASK));
341
342 uint8_t i;
343
344 #if (FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT != 0)
345 /* De-assert DOZE Enable Bit. */
346 base->MCR &= ~CAN_MCR_DOZE_MASK;
347 #endif
348
349 /* Wait until FlexCAN exit from any Low Power Mode. */
350 while (base->MCR & CAN_MCR_LPMACK_MASK)
351 {
352 }
353
354 /* Assert Soft Reset Signal. */
355 base->MCR |= CAN_MCR_SOFTRST_MASK;
356 /* Wait until FlexCAN reset completes. */
357 while (base->MCR & CAN_MCR_SOFTRST_MASK)
358 {
359 }
360
361 /* Reset MCR rigister. */
362 #if (defined(FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER) && FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER)
363 base->MCR |= CAN_MCR_WRNEN_MASK | CAN_MCR_WAKSRC_MASK |
364 CAN_MCR_MAXMB(FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1);
365 #else
366 base->MCR |= CAN_MCR_WRNEN_MASK | CAN_MCR_MAXMB(FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1);
367 #endif
368
369 /* Reset CTRL1 and CTRL2 rigister. */
370 base->CTRL1 = CAN_CTRL1_SMP_MASK;
371 base->CTRL2 = CAN_CTRL2_TASD(0x16) | CAN_CTRL2_RRS_MASK | CAN_CTRL2_EACEN_MASK;
372
373 /* Clean all individual Rx Mask of Message Buffers. */
374 for (i = 0; i < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); i++)
375 {
376 base->RXIMR[i] = 0x3FFFFFFF;
377 }
378
379 /* Clean Global Mask of Message Buffers. */
380 base->RXMGMASK = 0x3FFFFFFF;
381 /* Clean Global Mask of Message Buffer 14. */
382 base->RX14MASK = 0x3FFFFFFF;
383 /* Clean Global Mask of Message Buffer 15. */
384 base->RX15MASK = 0x3FFFFFFF;
385 /* Clean Global Mask of Rx FIFO. */
386 base->RXFGMASK = 0x3FFFFFFF;
387
388 /* Clean all Message Buffer CS fields. */
389 for (i = 0; i < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); i++)
390 {
391 base->MB[i].CS = 0x0;
392 }
393 }
394
FLEXCAN_SetBaudRate(CAN_Type * base,uint32_t sourceClock_Hz,uint32_t baudRate_Bps)395 static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Bps)
396 {
397 flexcan_timing_config_t timingConfig;
398 uint32_t priDiv = baudRate_Bps * FLEXCAN_TIME_QUANTA_NUM;
399
400 /* Assertion: Desired baud rate is too high. */
401 assert(baudRate_Bps <= 1000000U);
402 /* Assertion: Source clock should greater than baud rate * FLEXCAN_TIME_QUANTA_NUM. */
403 assert(priDiv <= sourceClock_Hz);
404
405 if (0 == priDiv)
406 {
407 priDiv = 1;
408 }
409
410 priDiv = (sourceClock_Hz / priDiv) - 1;
411
412 /* Desired baud rate is too low. */
413 if (priDiv > 0xFF)
414 {
415 priDiv = 0xFF;
416 }
417
418 /* FlexCAN timing setting formula:
419 * FLEXCAN_TIME_QUANTA_NUM = 1 + (PSEG1 + 1) + (PSEG2 + 1) + (PROPSEG + 1);
420 */
421 timingConfig.preDivider = priDiv;
422 timingConfig.phaseSeg1 = 3;
423 timingConfig.phaseSeg2 = 2;
424 timingConfig.propSeg = 1;
425 timingConfig.rJumpwidth = 1;
426
427 /* Update actual timing characteristic. */
428 FLEXCAN_SetTimingConfig(base, &timingConfig);
429 }
430
FLEXCAN_Init(CAN_Type * base,const flexcan_config_t * config,uint32_t sourceClock_Hz)431 void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz)
432 {
433 uint32_t mcrTemp;
434 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
435 uint32_t instance;
436 #endif
437
438 /* Assertion. */
439 assert(config);
440 assert((config->maxMbNum > 0) && (config->maxMbNum <= FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base)));
441
442 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
443 instance = FLEXCAN_GetInstance(base);
444 /* Enable FlexCAN clock. */
445 CLOCK_EnableClock(s_flexcanClock[instance]);
446 #if defined(FLEXCAN_PERIPH_CLOCKS)
447 /* Enable FlexCAN serial clock. */
448 CLOCK_EnableClock(s_flexcanPeriphClock[instance]);
449 #endif /* FLEXCAN_PERIPH_CLOCKS */
450 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
451
452 #if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE
453 /* Disable FlexCAN Module. */
454 FLEXCAN_Enable(base, false);
455
456 /* Protocol-Engine clock source selection, This bit must be set
457 * when FlexCAN Module in Disable Mode.
458 */
459 base->CTRL1 = (kFLEXCAN_ClkSrcOsc == config->clkSrc) ? base->CTRL1 & ~CAN_CTRL1_CLKSRC_MASK :
460 base->CTRL1 | CAN_CTRL1_CLKSRC_MASK;
461 #endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */
462
463 /* Enable FlexCAN Module for configuartion. */
464 FLEXCAN_Enable(base, true);
465
466 /* Reset to known status. */
467 FLEXCAN_Reset(base);
468
469 /* Save current MCR value and enable to enter Freeze mode(enabled by default). */
470 mcrTemp = base->MCR;
471
472 /* Set the maximum number of Message Buffers */
473 mcrTemp = (mcrTemp & ~CAN_MCR_MAXMB_MASK) | CAN_MCR_MAXMB(config->maxMbNum - 1);
474
475 /* Enable Loop Back Mode? */
476 base->CTRL1 = (config->enableLoopBack) ? base->CTRL1 | CAN_CTRL1_LPB_MASK : base->CTRL1 & ~CAN_CTRL1_LPB_MASK;
477
478 /* Enable Self Wake Up Mode? */
479 mcrTemp = (config->enableSelfWakeup) ? mcrTemp | CAN_MCR_SLFWAK_MASK : mcrTemp & ~CAN_MCR_SLFWAK_MASK;
480
481 /* Enable Individual Rx Masking? */
482 mcrTemp = (config->enableIndividMask) ? mcrTemp | CAN_MCR_IRMQ_MASK : mcrTemp & ~CAN_MCR_IRMQ_MASK;
483
484 #if (defined(FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT)
485 /* Enable Doze Mode? */
486 mcrTemp = (config->enableDoze) ? mcrTemp | CAN_MCR_DOZE_MASK : mcrTemp & ~CAN_MCR_DOZE_MASK;
487 #endif
488
489 /* Save MCR Configuation. */
490 base->MCR = mcrTemp;
491
492 /* Baud Rate Configuration.*/
493 FLEXCAN_SetBaudRate(base, sourceClock_Hz, config->baudRate);
494 }
495
FLEXCAN_Deinit(CAN_Type * base)496 void FLEXCAN_Deinit(CAN_Type *base)
497 {
498 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
499 uint32_t instance;
500 #endif
501 /* Reset all Register Contents. */
502 FLEXCAN_Reset(base);
503
504 /* Disable FlexCAN module. */
505 FLEXCAN_Enable(base, false);
506
507 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
508 instance = FLEXCAN_GetInstance(base);
509 #if defined(FLEXCAN_PERIPH_CLOCKS)
510 /* Disable FlexCAN serial clock. */
511 CLOCK_DisableClock(s_flexcanPeriphClock[instance]);
512 #endif /* FLEXCAN_PERIPH_CLOCKS */
513 /* Disable FlexCAN clock. */
514 CLOCK_DisableClock(s_flexcanClock[instance]);
515 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
516 }
517
FLEXCAN_GetDefaultConfig(flexcan_config_t * config)518 void FLEXCAN_GetDefaultConfig(flexcan_config_t *config)
519 {
520 /* Assertion. */
521 assert(config);
522
523 /* Initialize FlexCAN Module config struct with default value. */
524 #if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE
525 config->clkSrc = kFLEXCAN_ClkSrcOsc;
526 #endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */
527 config->baudRate = 125000U;
528 config->maxMbNum = 16;
529 config->enableLoopBack = false;
530 config->enableSelfWakeup = false;
531 config->enableIndividMask = false;
532 #if (defined(FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT)
533 config->enableDoze = false;
534 #endif
535 }
536
FLEXCAN_SetTimingConfig(CAN_Type * base,const flexcan_timing_config_t * config)537 void FLEXCAN_SetTimingConfig(CAN_Type *base, const flexcan_timing_config_t *config)
538 {
539 /* Assertion. */
540 assert(config);
541
542 /* Enter Freeze Mode. */
543 FLEXCAN_EnterFreezeMode(base);
544
545 /* Cleaning previous Timing Setting. */
546 base->CTRL1 &= ~(CAN_CTRL1_PRESDIV_MASK | CAN_CTRL1_RJW_MASK | CAN_CTRL1_PSEG1_MASK | CAN_CTRL1_PSEG2_MASK |
547 CAN_CTRL1_PROPSEG_MASK);
548
549 /* Updating Timing Setting according to configuration structure. */
550 base->CTRL1 |=
551 (CAN_CTRL1_PRESDIV(config->preDivider) | CAN_CTRL1_RJW(config->rJumpwidth) |
552 CAN_CTRL1_PSEG1(config->phaseSeg1) | CAN_CTRL1_PSEG2(config->phaseSeg2) | CAN_CTRL1_PROPSEG(config->propSeg));
553
554 /* Exit Freeze Mode. */
555 FLEXCAN_ExitFreezeMode(base);
556 }
557
FLEXCAN_SetRxMbGlobalMask(CAN_Type * base,uint32_t mask)558 void FLEXCAN_SetRxMbGlobalMask(CAN_Type *base, uint32_t mask)
559 {
560 /* Enter Freeze Mode. */
561 FLEXCAN_EnterFreezeMode(base);
562
563 /* Setting Rx Message Buffer Global Mask value. */
564 base->RXMGMASK = mask;
565 base->RX14MASK = mask;
566 base->RX15MASK = mask;
567
568 /* Exit Freeze Mode. */
569 FLEXCAN_ExitFreezeMode(base);
570 }
571
FLEXCAN_SetRxFifoGlobalMask(CAN_Type * base,uint32_t mask)572 void FLEXCAN_SetRxFifoGlobalMask(CAN_Type *base, uint32_t mask)
573 {
574 /* Enter Freeze Mode. */
575 FLEXCAN_EnterFreezeMode(base);
576
577 /* Setting Rx FIFO Global Mask value. */
578 base->RXFGMASK = mask;
579
580 /* Exit Freeze Mode. */
581 FLEXCAN_ExitFreezeMode(base);
582 }
583
FLEXCAN_SetRxIndividualMask(CAN_Type * base,uint8_t maskIdx,uint32_t mask)584 void FLEXCAN_SetRxIndividualMask(CAN_Type *base, uint8_t maskIdx, uint32_t mask)
585 {
586 assert(maskIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
587
588 /* Enter Freeze Mode. */
589 FLEXCAN_EnterFreezeMode(base);
590
591 /* Setting Rx Individual Mask value. */
592 base->RXIMR[maskIdx] = mask;
593
594 /* Exit Freeze Mode. */
595 FLEXCAN_ExitFreezeMode(base);
596 }
597
FLEXCAN_SetTxMbConfig(CAN_Type * base,uint8_t mbIdx,bool enable)598 void FLEXCAN_SetTxMbConfig(CAN_Type *base, uint8_t mbIdx, bool enable)
599 {
600 /* Assertion. */
601 assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
602 assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
603
604 /* Inactivate Message Buffer. */
605 if (enable)
606 {
607 base->MB[mbIdx].CS = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
608 }
609 else
610 {
611 base->MB[mbIdx].CS = 0;
612 }
613
614 /* Clean Message Buffer content. */
615 base->MB[mbIdx].ID = 0x0;
616 base->MB[mbIdx].WORD0 = 0x0;
617 base->MB[mbIdx].WORD1 = 0x0;
618 }
619
FLEXCAN_SetRxMbConfig(CAN_Type * base,uint8_t mbIdx,const flexcan_rx_mb_config_t * config,bool enable)620 void FLEXCAN_SetRxMbConfig(CAN_Type *base, uint8_t mbIdx, const flexcan_rx_mb_config_t *config, bool enable)
621 {
622 /* Assertion. */
623 assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
624 assert(((config) || (false == enable)));
625 assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
626
627 uint32_t cs_temp = 0;
628
629 /* Inactivate Message Buffer. */
630 base->MB[mbIdx].CS = 0;
631
632 /* Clean Message Buffer content. */
633 base->MB[mbIdx].ID = 0x0;
634 base->MB[mbIdx].WORD0 = 0x0;
635 base->MB[mbIdx].WORD1 = 0x0;
636
637 if (enable)
638 {
639 /* Setup Message Buffer ID. */
640 base->MB[mbIdx].ID = config->id;
641
642 /* Setup Message Buffer format. */
643 if (kFLEXCAN_FrameFormatExtend == config->format)
644 {
645 cs_temp |= CAN_CS_IDE_MASK;
646 }
647
648 /* Setup Message Buffer type. */
649 if (kFLEXCAN_FrameTypeRemote == config->type)
650 {
651 cs_temp |= CAN_CS_RTR_MASK;
652 }
653
654 /* Activate Rx Message Buffer. */
655 cs_temp |= CAN_CS_CODE(kFLEXCAN_RxMbEmpty);
656 base->MB[mbIdx].CS = cs_temp;
657 }
658 }
659
FLEXCAN_SetRxFifoConfig(CAN_Type * base,const flexcan_rx_fifo_config_t * config,bool enable)660 void FLEXCAN_SetRxFifoConfig(CAN_Type *base, const flexcan_rx_fifo_config_t *config, bool enable)
661 {
662 /* Assertion. */
663 assert((config) || (false == enable));
664
665 volatile uint32_t *idFilterRegion = (volatile uint32_t *)(&base->MB[6].CS);
666 uint8_t setup_mb, i, rffn = 0;
667
668 /* Enter Freeze Mode. */
669 FLEXCAN_EnterFreezeMode(base);
670
671 if (enable)
672 {
673 assert(config->idFilterNum <= 128);
674
675 /* Get the setup_mb value. */
676 setup_mb = (base->MCR & CAN_MCR_MAXMB_MASK) >> CAN_MCR_MAXMB_SHIFT;
677 setup_mb = (setup_mb < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base)) ?
678 setup_mb :
679 FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base);
680
681 /* Determine RFFN value. */
682 for (i = 0; i <= 0xF; i++)
683 {
684 if ((8 * (i + 1)) >= config->idFilterNum)
685 {
686 rffn = i;
687 assert(((setup_mb - 8) - (2 * rffn)) > 0);
688
689 base->CTRL2 = (base->CTRL2 & ~CAN_CTRL2_RFFN_MASK) | CAN_CTRL2_RFFN(rffn);
690 break;
691 }
692 }
693 }
694 else
695 {
696 rffn = (base->CTRL2 & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT;
697 }
698
699 /* Clean ID filter table occuyied Message Buffer Region. */
700 rffn = (rffn + 1) * 8;
701 for (i = 0; i < rffn; i++)
702 {
703 idFilterRegion[i] = 0x0;
704 }
705
706 if (enable)
707 {
708 /* Disable unused Rx FIFO Filter. */
709 for (i = config->idFilterNum; i < rffn; i++)
710 {
711 idFilterRegion[i] = 0xFFFFFFFFU;
712 }
713
714 /* Copy ID filter table to Message Buffer Region. */
715 for (i = 0; i < config->idFilterNum; i++)
716 {
717 idFilterRegion[i] = config->idFilterTable[i];
718 }
719
720 /* Setup ID Fitlter Type. */
721 switch (config->idFilterType)
722 {
723 case kFLEXCAN_RxFifoFilterTypeA:
724 base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x0);
725 break;
726 case kFLEXCAN_RxFifoFilterTypeB:
727 base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x1);
728 break;
729 case kFLEXCAN_RxFifoFilterTypeC:
730 base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x2);
731 break;
732 case kFLEXCAN_RxFifoFilterTypeD:
733 /* All frames rejected. */
734 base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x3);
735 break;
736 default:
737 break;
738 }
739
740 /* Setting Message Reception Priority. */
741 base->CTRL2 = (config->priority == kFLEXCAN_RxFifoPrioHigh) ? base->CTRL2 & ~CAN_CTRL2_MRP_MASK :
742 base->CTRL2 | CAN_CTRL2_MRP_MASK;
743
744 /* Enable Rx Message FIFO. */
745 base->MCR |= CAN_MCR_RFEN_MASK;
746 }
747 else
748 {
749 /* Disable Rx Message FIFO. */
750 base->MCR &= ~CAN_MCR_RFEN_MASK;
751
752 /* Clean MB0 ~ MB5. */
753 FLEXCAN_SetRxMbConfig(base, 0, NULL, false);
754 FLEXCAN_SetRxMbConfig(base, 1, NULL, false);
755 FLEXCAN_SetRxMbConfig(base, 2, NULL, false);
756 FLEXCAN_SetRxMbConfig(base, 3, NULL, false);
757 FLEXCAN_SetRxMbConfig(base, 4, NULL, false);
758 FLEXCAN_SetRxMbConfig(base, 5, NULL, false);
759 }
760
761 /* Exit Freeze Mode. */
762 FLEXCAN_ExitFreezeMode(base);
763 }
764
765 #if (defined(FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA) && FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA)
FLEXCAN_EnableRxFifoDMA(CAN_Type * base,bool enable)766 void FLEXCAN_EnableRxFifoDMA(CAN_Type *base, bool enable)
767 {
768 if (enable)
769 {
770 /* Enter Freeze Mode. */
771 FLEXCAN_EnterFreezeMode(base);
772
773 /* Enable FlexCAN DMA. */
774 base->MCR |= CAN_MCR_DMA_MASK;
775
776 /* Exit Freeze Mode. */
777 FLEXCAN_ExitFreezeMode(base);
778 }
779 else
780 {
781 /* Enter Freeze Mode. */
782 FLEXCAN_EnterFreezeMode(base);
783
784 /* Disable FlexCAN DMA. */
785 base->MCR &= ~CAN_MCR_DMA_MASK;
786
787 /* Exit Freeze Mode. */
788 FLEXCAN_ExitFreezeMode(base);
789 }
790 }
791 #endif /* FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA */
792
FLEXCAN_WriteTxMb(CAN_Type * base,uint8_t mbIdx,const flexcan_frame_t * txFrame)793 status_t FLEXCAN_WriteTxMb(CAN_Type *base, uint8_t mbIdx, const flexcan_frame_t *txFrame)
794 {
795 /* Assertion. */
796 assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
797 assert(txFrame);
798 assert(txFrame->length <= 8);
799 assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
800
801 uint32_t cs_temp = 0;
802
803 /* Check if Message Buffer is available. */
804 if (CAN_CS_CODE(kFLEXCAN_TxMbDataOrRemote) != (base->MB[mbIdx].CS & CAN_CS_CODE_MASK))
805 {
806 /* Inactive Tx Message Buffer. */
807 base->MB[mbIdx].CS = (base->MB[mbIdx].CS & ~CAN_CS_CODE_MASK) | CAN_CS_CODE(kFLEXCAN_TxMbInactive);
808
809 /* Fill Message ID field. */
810 base->MB[mbIdx].ID = txFrame->id;
811
812 /* Fill Message Format field. */
813 if (kFLEXCAN_FrameFormatExtend == txFrame->format)
814 {
815 cs_temp |= CAN_CS_SRR_MASK | CAN_CS_IDE_MASK;
816 }
817
818 /* Fill Message Type field. */
819 if (kFLEXCAN_FrameTypeRemote == txFrame->type)
820 {
821 cs_temp |= CAN_CS_RTR_MASK;
822 }
823
824 cs_temp |= CAN_CS_CODE(kFLEXCAN_TxMbDataOrRemote) | CAN_CS_DLC(txFrame->length);
825
826 /* Load Message Payload. */
827 base->MB[mbIdx].WORD0 = txFrame->dataWord0;
828 base->MB[mbIdx].WORD1 = txFrame->dataWord1;
829
830 /* Activate Tx Message Buffer. */
831 base->MB[mbIdx].CS = cs_temp;
832
833 #if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641)
834 base->MB[FLEXCAN_GetFirstValidMb(base)].CS = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
835 base->MB[FLEXCAN_GetFirstValidMb(base)].CS = CAN_CS_CODE(kFLEXCAN_TxMbInactive);
836 #endif
837
838 return kStatus_Success;
839 }
840 else
841 {
842 /* Tx Message Buffer is activated, return immediately. */
843 return kStatus_Fail;
844 }
845 }
846
FLEXCAN_ReadRxMb(CAN_Type * base,uint8_t mbIdx,flexcan_frame_t * rxFrame)847 status_t FLEXCAN_ReadRxMb(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *rxFrame)
848 {
849 /* Assertion. */
850 assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
851 assert(rxFrame);
852 assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
853
854 uint32_t cs_temp;
855 uint8_t rx_code;
856
857 /* Read CS field of Rx Message Buffer to lock Message Buffer. */
858 cs_temp = base->MB[mbIdx].CS;
859 /* Get Rx Message Buffer Code field. */
860 rx_code = (cs_temp & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT;
861
862 /* Check to see if Rx Message Buffer is full. */
863 if ((kFLEXCAN_RxMbFull == rx_code) || (kFLEXCAN_RxMbOverrun == rx_code))
864 {
865 /* Store Message ID. */
866 rxFrame->id = base->MB[mbIdx].ID & (CAN_ID_EXT_MASK | CAN_ID_STD_MASK);
867
868 /* Get the message ID and format. */
869 rxFrame->format = (cs_temp & CAN_CS_IDE_MASK) ? kFLEXCAN_FrameFormatExtend : kFLEXCAN_FrameFormatStandard;
870
871 /* Get the message type. */
872 rxFrame->type = (cs_temp & CAN_CS_RTR_MASK) ? kFLEXCAN_FrameTypeRemote : kFLEXCAN_FrameTypeData;
873
874 /* Get the message length. */
875 rxFrame->length = (cs_temp & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT;
876
877 /* Store Message Payload. */
878 rxFrame->dataWord0 = base->MB[mbIdx].WORD0;
879 rxFrame->dataWord1 = base->MB[mbIdx].WORD1;
880
881 /* Read free-running timer to unlock Rx Message Buffer. */
882 (void)base->TIMER;
883
884 if (kFLEXCAN_RxMbFull == rx_code)
885 {
886 return kStatus_Success;
887 }
888 else
889 {
890 return kStatus_FLEXCAN_RxOverflow;
891 }
892 }
893 else
894 {
895 /* Read free-running timer to unlock Rx Message Buffer. */
896 (void)base->TIMER;
897
898 return kStatus_Fail;
899 }
900 }
901
FLEXCAN_ReadRxFifo(CAN_Type * base,flexcan_frame_t * rxFrame)902 status_t FLEXCAN_ReadRxFifo(CAN_Type *base, flexcan_frame_t *rxFrame)
903 {
904 /* Assertion. */
905 assert(rxFrame);
906
907 uint32_t cs_temp;
908
909 /* Check if Rx FIFO is Enabled. */
910 if (base->MCR & CAN_MCR_RFEN_MASK)
911 {
912 /* Read CS field of Rx Message Buffer to lock Message Buffer. */
913 cs_temp = base->MB[0].CS;
914
915 /* Read data from Rx FIFO output port. */
916 /* Store Message ID. */
917 rxFrame->id = base->MB[0].ID & (CAN_ID_EXT_MASK | CAN_ID_STD_MASK);
918
919 /* Get the message ID and format. */
920 rxFrame->format = (cs_temp & CAN_CS_IDE_MASK) ? kFLEXCAN_FrameFormatExtend : kFLEXCAN_FrameFormatStandard;
921
922 /* Get the message type. */
923 rxFrame->type = (cs_temp & CAN_CS_RTR_MASK) ? kFLEXCAN_FrameTypeRemote : kFLEXCAN_FrameTypeData;
924
925 /* Get the message length. */
926 rxFrame->length = (cs_temp & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT;
927
928 /* Store Message Payload. */
929 rxFrame->dataWord0 = base->MB[0].WORD0;
930 rxFrame->dataWord1 = base->MB[0].WORD1;
931
932 /* Store ID Filter Hit Index. */
933 rxFrame->idhit = (uint8_t)(base->RXFIR & CAN_RXFIR_IDHIT_MASK);
934
935 /* Read free-running timer to unlock Rx Message Buffer. */
936 (void)base->TIMER;
937
938 return kStatus_Success;
939 }
940 else
941 {
942 return kStatus_Fail;
943 }
944 }
945
FLEXCAN_TransferSendBlocking(CAN_Type * base,uint8_t mbIdx,flexcan_frame_t * txFrame)946 status_t FLEXCAN_TransferSendBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *txFrame)
947 {
948 /* Write Tx Message Buffer to initiate a data sending. */
949 if (kStatus_Success == FLEXCAN_WriteTxMb(base, mbIdx, txFrame))
950 {
951 /* Wait until CAN Message send out. */
952 while (!FLEXCAN_GetMbStatusFlags(base, 1 << mbIdx))
953 {
954 }
955
956 /* Clean Tx Message Buffer Flag. */
957 FLEXCAN_ClearMbStatusFlags(base, 1 << mbIdx);
958
959 return kStatus_Success;
960 }
961 else
962 {
963 return kStatus_Fail;
964 }
965 }
966
FLEXCAN_TransferReceiveBlocking(CAN_Type * base,uint8_t mbIdx,flexcan_frame_t * rxFrame)967 status_t FLEXCAN_TransferReceiveBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *rxFrame)
968 {
969 /* Wait until Rx Message Buffer non-empty. */
970 while (!FLEXCAN_GetMbStatusFlags(base, 1 << mbIdx))
971 {
972 }
973
974 /* Clean Rx Message Buffer Flag. */
975 FLEXCAN_ClearMbStatusFlags(base, 1 << mbIdx);
976
977 /* Read Received CAN Message. */
978 return FLEXCAN_ReadRxMb(base, mbIdx, rxFrame);
979 }
980
FLEXCAN_TransferReceiveFifoBlocking(CAN_Type * base,flexcan_frame_t * rxFrame)981 status_t FLEXCAN_TransferReceiveFifoBlocking(CAN_Type *base, flexcan_frame_t *rxFrame)
982 {
983 status_t rxFifoStatus;
984
985 /* Wait until Rx FIFO non-empty. */
986 while (!FLEXCAN_GetMbStatusFlags(base, kFLEXCAN_RxFifoFrameAvlFlag))
987 {
988 }
989
990 /* */
991 rxFifoStatus = FLEXCAN_ReadRxFifo(base, rxFrame);
992
993 /* Clean Rx Fifo available flag. */
994 FLEXCAN_ClearMbStatusFlags(base, kFLEXCAN_RxFifoFrameAvlFlag);
995
996 return rxFifoStatus;
997 }
998
FLEXCAN_TransferCreateHandle(CAN_Type * base,flexcan_handle_t * handle,flexcan_transfer_callback_t callback,void * userData)999 void FLEXCAN_TransferCreateHandle(CAN_Type *base,
1000 flexcan_handle_t *handle,
1001 flexcan_transfer_callback_t callback,
1002 void *userData)
1003 {
1004 assert(handle);
1005
1006 uint8_t instance;
1007
1008 /* Clean FlexCAN transfer handle. */
1009 memset(handle, 0, sizeof(*handle));
1010
1011 /* Get instance from peripheral base address. */
1012 instance = FLEXCAN_GetInstance(base);
1013
1014 /* Save the context in global variables to support the double weak mechanism. */
1015 s_flexcanHandle[instance] = handle;
1016
1017 /* Register Callback function. */
1018 handle->callback = callback;
1019 handle->userData = userData;
1020
1021 s_flexcanIsr = FLEXCAN_TransferHandleIRQ;
1022
1023 /* We Enable Error & Status interrupt here, because this interrupt just
1024 * report current status of FlexCAN module through Callback function.
1025 * It is insignificance without a available callback function.
1026 */
1027 if (handle->callback != NULL)
1028 {
1029 FLEXCAN_EnableInterrupts(base, kFLEXCAN_BusOffInterruptEnable | kFLEXCAN_ErrorInterruptEnable |
1030 kFLEXCAN_RxWarningInterruptEnable | kFLEXCAN_TxWarningInterruptEnable |
1031 kFLEXCAN_WakeUpInterruptEnable);
1032 }
1033 else
1034 {
1035 FLEXCAN_DisableInterrupts(base, kFLEXCAN_BusOffInterruptEnable | kFLEXCAN_ErrorInterruptEnable |
1036 kFLEXCAN_RxWarningInterruptEnable | kFLEXCAN_TxWarningInterruptEnable |
1037 kFLEXCAN_WakeUpInterruptEnable);
1038 }
1039
1040 /* Enable interrupts in NVIC. */
1041 EnableIRQ((IRQn_Type)(s_flexcanRxWarningIRQ[instance]));
1042 EnableIRQ((IRQn_Type)(s_flexcanTxWarningIRQ[instance]));
1043 EnableIRQ((IRQn_Type)(s_flexcanWakeUpIRQ[instance]));
1044 EnableIRQ((IRQn_Type)(s_flexcanErrorIRQ[instance]));
1045 EnableIRQ((IRQn_Type)(s_flexcanBusOffIRQ[instance]));
1046 EnableIRQ((IRQn_Type)(s_flexcanMbIRQ[instance]));
1047 }
1048
FLEXCAN_TransferSendNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_mb_transfer_t * xfer)1049 status_t FLEXCAN_TransferSendNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *xfer)
1050 {
1051 /* Assertion. */
1052 assert(handle);
1053 assert(xfer);
1054 assert(xfer->mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
1055 assert(!FLEXCAN_IsMbOccupied(base, xfer->mbIdx));
1056
1057 /* Check if Message Buffer is idle. */
1058 if (kFLEXCAN_StateIdle == handle->mbState[xfer->mbIdx])
1059 {
1060 /* Distinguish transmit type. */
1061 if (kFLEXCAN_FrameTypeRemote == xfer->frame->type)
1062 {
1063 handle->mbState[xfer->mbIdx] = kFLEXCAN_StateTxRemote;
1064
1065 /* Register user Frame buffer to receive remote Frame. */
1066 handle->mbFrameBuf[xfer->mbIdx] = xfer->frame;
1067 }
1068 else
1069 {
1070 handle->mbState[xfer->mbIdx] = kFLEXCAN_StateTxData;
1071 }
1072
1073 if (kStatus_Success == FLEXCAN_WriteTxMb(base, xfer->mbIdx, xfer->frame))
1074 {
1075 /* Enable Message Buffer Interrupt. */
1076 FLEXCAN_EnableMbInterrupts(base, 1 << xfer->mbIdx);
1077
1078 return kStatus_Success;
1079 }
1080 else
1081 {
1082 handle->mbState[xfer->mbIdx] = kFLEXCAN_StateIdle;
1083 return kStatus_Fail;
1084 }
1085 }
1086 else
1087 {
1088 return kStatus_FLEXCAN_TxBusy;
1089 }
1090 }
1091
FLEXCAN_TransferReceiveNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_mb_transfer_t * xfer)1092 status_t FLEXCAN_TransferReceiveNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *xfer)
1093 {
1094 /* Assertion. */
1095 assert(handle);
1096 assert(xfer);
1097 assert(xfer->mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
1098 assert(!FLEXCAN_IsMbOccupied(base, xfer->mbIdx));
1099
1100 /* Check if Message Buffer is idle. */
1101 if (kFLEXCAN_StateIdle == handle->mbState[xfer->mbIdx])
1102 {
1103 handle->mbState[xfer->mbIdx] = kFLEXCAN_StateRxData;
1104
1105 /* Register Message Buffer. */
1106 handle->mbFrameBuf[xfer->mbIdx] = xfer->frame;
1107
1108 /* Enable Message Buffer Interrupt. */
1109 FLEXCAN_EnableMbInterrupts(base, 1 << xfer->mbIdx);
1110
1111 return kStatus_Success;
1112 }
1113 else
1114 {
1115 return kStatus_FLEXCAN_RxBusy;
1116 }
1117 }
1118
FLEXCAN_TransferReceiveFifoNonBlocking(CAN_Type * base,flexcan_handle_t * handle,flexcan_fifo_transfer_t * xfer)1119 status_t FLEXCAN_TransferReceiveFifoNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_fifo_transfer_t *xfer)
1120 {
1121 /* Assertion. */
1122 assert(handle);
1123 assert(xfer);
1124
1125 /* Check if Message Buffer is idle. */
1126 if (kFLEXCAN_StateIdle == handle->rxFifoState)
1127 {
1128 handle->rxFifoState = kFLEXCAN_StateRxFifo;
1129
1130 /* Register Message Buffer. */
1131 handle->rxFifoFrameBuf = xfer->frame;
1132
1133 /* Enable Message Buffer Interrupt. */
1134 FLEXCAN_EnableMbInterrupts(
1135 base, kFLEXCAN_RxFifoOverflowFlag | kFLEXCAN_RxFifoWarningFlag | kFLEXCAN_RxFifoFrameAvlFlag);
1136
1137 return kStatus_Success;
1138 }
1139 else
1140 {
1141 return kStatus_FLEXCAN_RxFifoBusy;
1142 }
1143 }
1144
FLEXCAN_TransferAbortSend(CAN_Type * base,flexcan_handle_t * handle,uint8_t mbIdx)1145 void FLEXCAN_TransferAbortSend(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx)
1146 {
1147 /* Assertion. */
1148 assert(handle);
1149 assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
1150 assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
1151
1152 /* Disable Message Buffer Interrupt. */
1153 FLEXCAN_DisableMbInterrupts(base, 1 << mbIdx);
1154
1155 /* Un-register handle. */
1156 handle->mbFrameBuf[mbIdx] = 0x0;
1157
1158 /* Clean Message Buffer. */
1159 FLEXCAN_SetTxMbConfig(base, mbIdx, true);
1160
1161 handle->mbState[mbIdx] = kFLEXCAN_StateIdle;
1162 }
1163
FLEXCAN_TransferAbortReceive(CAN_Type * base,flexcan_handle_t * handle,uint8_t mbIdx)1164 void FLEXCAN_TransferAbortReceive(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx)
1165 {
1166 /* Assertion. */
1167 assert(handle);
1168 assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK));
1169 assert(!FLEXCAN_IsMbOccupied(base, mbIdx));
1170
1171 /* Disable Message Buffer Interrupt. */
1172 FLEXCAN_DisableMbInterrupts(base, 1 << mbIdx);
1173
1174 /* Un-register handle. */
1175 handle->mbFrameBuf[mbIdx] = 0x0;
1176 handle->mbState[mbIdx] = kFLEXCAN_StateIdle;
1177 }
1178
FLEXCAN_TransferAbortReceiveFifo(CAN_Type * base,flexcan_handle_t * handle)1179 void FLEXCAN_TransferAbortReceiveFifo(CAN_Type *base, flexcan_handle_t *handle)
1180 {
1181 /* Assertion. */
1182 assert(handle);
1183
1184 /* Check if Rx FIFO is enabled. */
1185 if (base->MCR & CAN_MCR_RFEN_MASK)
1186 {
1187 /* Disable Rx Message FIFO Interrupts. */
1188 FLEXCAN_DisableMbInterrupts(
1189 base, kFLEXCAN_RxFifoOverflowFlag | kFLEXCAN_RxFifoWarningFlag | kFLEXCAN_RxFifoFrameAvlFlag);
1190
1191 /* Un-register handle. */
1192 handle->rxFifoFrameBuf = 0x0;
1193 }
1194
1195 handle->rxFifoState = kFLEXCAN_StateIdle;
1196 }
1197
FLEXCAN_TransferHandleIRQ(CAN_Type * base,flexcan_handle_t * handle)1198 void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle)
1199 {
1200 /* Assertion. */
1201 assert(handle);
1202
1203 status_t status = kStatus_FLEXCAN_UnHandled;
1204 uint32_t result;
1205
1206 /* Store Current FlexCAN Module Error and Status. */
1207 result = base->ESR1;
1208
1209 do
1210 {
1211 /* Solve FlexCAN Error and Status Interrupt. */
1212 if (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag |
1213 kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag))
1214 {
1215 status = kStatus_FLEXCAN_ErrorStatus;
1216
1217 /* Clear FlexCAN Error and Status Interrupt. */
1218 FLEXCAN_ClearStatusFlags(base, kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag |
1219 kFLEXCAN_BusOffIntFlag | kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag);
1220 }
1221 /* Solve FlexCAN Rx FIFO & Message Buffer Interrupt. */
1222 else
1223 {
1224 /* For this implementation, we solve the Message with lowest MB index first. */
1225 for (result = 0; result < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); result++)
1226 {
1227 /* Get the lowest unhandled Message Buffer */
1228 if ((FLEXCAN_GetMbStatusFlags(base, 1 << result)) && (FLEXCAN_IsMbIntEnabled(base, result)))
1229 {
1230 break;
1231 }
1232 }
1233
1234 /* Does not find Message to deal with. */
1235 if (result == FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base))
1236 {
1237 break;
1238 }
1239
1240 /* Solve Rx FIFO interrupt. */
1241 if ((kFLEXCAN_StateIdle != handle->rxFifoState) && ((1 << result) <= kFLEXCAN_RxFifoOverflowFlag))
1242 {
1243 switch (1 << result)
1244 {
1245 case kFLEXCAN_RxFifoOverflowFlag:
1246 status = kStatus_FLEXCAN_RxFifoOverflow;
1247 break;
1248
1249 case kFLEXCAN_RxFifoWarningFlag:
1250 status = kStatus_FLEXCAN_RxFifoWarning;
1251 break;
1252
1253 case kFLEXCAN_RxFifoFrameAvlFlag:
1254 status = FLEXCAN_ReadRxFifo(base, handle->rxFifoFrameBuf);
1255 if (kStatus_Success == status)
1256 {
1257 status = kStatus_FLEXCAN_RxFifoIdle;
1258 }
1259 FLEXCAN_TransferAbortReceiveFifo(base, handle);
1260 break;
1261
1262 default:
1263 status = kStatus_FLEXCAN_UnHandled;
1264 break;
1265 }
1266 }
1267 else
1268 {
1269 /* Get current State of Message Buffer. */
1270 switch (handle->mbState[result])
1271 {
1272 /* Solve Rx Data Frame. */
1273 case kFLEXCAN_StateRxData:
1274 status = FLEXCAN_ReadRxMb(base, result, handle->mbFrameBuf[result]);
1275 if (kStatus_Success == status)
1276 {
1277 status = kStatus_FLEXCAN_RxIdle;
1278 }
1279 FLEXCAN_TransferAbortReceive(base, handle, result);
1280 break;
1281
1282 /* Solve Rx Remote Frame. */
1283 case kFLEXCAN_StateRxRemote:
1284 status = FLEXCAN_ReadRxMb(base, result, handle->mbFrameBuf[result]);
1285 if (kStatus_Success == status)
1286 {
1287 status = kStatus_FLEXCAN_RxIdle;
1288 }
1289 FLEXCAN_TransferAbortReceive(base, handle, result);
1290 break;
1291
1292 /* Solve Tx Data Frame. */
1293 case kFLEXCAN_StateTxData:
1294 status = kStatus_FLEXCAN_TxIdle;
1295 FLEXCAN_TransferAbortSend(base, handle, result);
1296 break;
1297
1298 /* Solve Tx Remote Frame. */
1299 case kFLEXCAN_StateTxRemote:
1300 handle->mbState[result] = kFLEXCAN_StateRxRemote;
1301 status = kStatus_FLEXCAN_TxSwitchToRx;
1302 break;
1303
1304 default:
1305 status = kStatus_FLEXCAN_UnHandled;
1306 break;
1307 }
1308 }
1309
1310 /* Clear resolved Message Buffer IRQ. */
1311 FLEXCAN_ClearMbStatusFlags(base, 1 << result);
1312 }
1313
1314 /* Calling Callback Function if has one. */
1315 if (handle->callback != NULL)
1316 {
1317 handle->callback(base, handle, status, result, handle->userData);
1318 }
1319
1320 /* Reset return status */
1321 status = kStatus_FLEXCAN_UnHandled;
1322
1323 /* Store Current FlexCAN Module Error and Status. */
1324 result = base->ESR1;
1325 }
1326 #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
1327 while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFFFFFFFFFU)) ||
1328 (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag |
1329 kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag))));
1330 #else
1331 while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) ||
1332 (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag |
1333 kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag))));
1334 #endif
1335 }
1336
1337 #if defined(CAN0)
CAN0_DriverIRQHandler(void)1338 void CAN0_DriverIRQHandler(void)
1339 {
1340 assert(s_flexcanHandle[0]);
1341
1342 s_flexcanIsr(CAN0, s_flexcanHandle[0]);
1343 }
1344 #endif
1345
1346 #if defined(CAN1)
CAN1_DriverIRQHandler(void)1347 void CAN1_DriverIRQHandler(void)
1348 {
1349 assert(s_flexcanHandle[1]);
1350
1351 s_flexcanIsr(CAN1, s_flexcanHandle[1]);
1352 }
1353 #endif
1354
1355 #if defined(CAN2)
CAN2_DriverIRQHandler(void)1356 void CAN2_DriverIRQHandler(void)
1357 {
1358 assert(s_flexcanHandle[2]);
1359
1360 s_flexcanIsr(CAN2, s_flexcanHandle[2]);
1361 }
1362 #endif
1363
1364 #if defined(CAN3)
CAN3_DriverIRQHandler(void)1365 void CAN3_DriverIRQHandler(void)
1366 {
1367 assert(s_flexcanHandle[3]);
1368
1369 s_flexcanIsr(CAN3, s_flexcanHandle[3]);
1370 }
1371 #endif
1372
1373 #if defined(CAN4)
CAN4_DriverIRQHandler(void)1374 void CAN4_DriverIRQHandler(void)
1375 {
1376 assert(s_flexcanHandle[4]);
1377
1378 s_flexcanIsr(CAN4, s_flexcanHandle[4]);
1379 }
1380 #endif
1381
1382 #if defined(DMA_CAN0)
DMA_FLEXCAN0_DriverIRQHandler(void)1383 void DMA_FLEXCAN0_DriverIRQHandler(void)
1384 {
1385 assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN0)]);
1386
1387 s_flexcanIsr(DMA_CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN0)]);
1388 }
1389 #endif
1390
1391 #if defined(DMA_CAN1)
DMA_FLEXCAN1_DriverIRQHandler(void)1392 void DMA_FLEXCAN1_DriverIRQHandler(void)
1393 {
1394 assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN1)]);
1395
1396 s_flexcanIsr(DMA_CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN1)]);
1397 }
1398 #endif
1399
1400 #if defined(DMA_CAN2)
DMA_FLEXCAN2_DriverIRQHandler(void)1401 void DMA_FLEXCAN2_DriverIRQHandler(void)
1402 {
1403 assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN2)]);
1404
1405 s_flexcanIsr(DMA_CAN2, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN2)]);
1406 }
1407 #endif
1408