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