http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f8f2ebbf/hw/mcu/nxp/src/ext/sdk-2.0-frdm-k64f_b160321/devices/MK64F12/drivers/fsl_flexcan.c ---------------------------------------------------------------------- diff --git a/hw/mcu/nxp/src/ext/sdk-2.0-frdm-k64f_b160321/devices/MK64F12/drivers/fsl_flexcan.c b/hw/mcu/nxp/src/ext/sdk-2.0-frdm-k64f_b160321/devices/MK64F12/drivers/fsl_flexcan.c new file mode 100644 index 0000000..5a1028b --- /dev/null +++ b/hw/mcu/nxp/src/ext/sdk-2.0-frdm-k64f_b160321/devices/MK64F12/drivers/fsl_flexcan.c @@ -0,0 +1,1314 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_flexcan.h" + +/******************************************************************************* + * Definitons + ******************************************************************************/ + +#define FLEXCAN_TIME_QUANTA_NUM (10) + +/*! @brief FlexCAN Internal State. */ +enum _flexcan_state +{ + kFLEXCAN_StateIdle = 0x0, /*!< MB/RxFIFO idle.*/ + kFLEXCAN_StateRxData = 0x1, /*!< MB receiving.*/ + kFLEXCAN_StateRxRemote = 0x2, /*!< MB receiving remote reply.*/ + kFLEXCAN_StateTxData = 0x3, /*!< MB transmitting.*/ + kFLEXCAN_StateTxRemote = 0x4, /*!< MB transmitting remote request.*/ + kFLEXCAN_StateRxFifo = 0x5, /*!< RxFIFO receiving.*/ +}; + +/*! @brief FlexCAN message buffer CODE for Rx buffers. */ +enum _flexcan_mb_code_rx +{ + kFLEXCAN_RxMbInactive = 0x0, /*!< MB is not active.*/ + kFLEXCAN_RxMbFull = 0x2, /*!< MB is full.*/ + kFLEXCAN_RxMbEmpty = 0x4, /*!< MB is active and empty.*/ + kFLEXCAN_RxMbOverrun = 0x6, /*!< MB is overwritten into a full buffer.*/ + kFLEXCAN_RxMbBusy = 0x8, /*!< FlexCAN is updating the contents of the MB.*/ + /*! The CPU must not access the MB.*/ + kFLEXCAN_RxMbRanswer = 0xA, /*!< A frame was configured to recognize a Remote Request Frame */ + /*! and transmit a Response Frame in return.*/ + kFLEXCAN_RxMbNotUsed = 0xF, /*!< Not used.*/ +}; + +/*! @brief FlexCAN message buffer CODE FOR Tx buffers. */ +enum _flexcan_mb_code_tx +{ + kFLEXCAN_TxMbInactive = 0x8, /*!< MB is not active.*/ + kFLEXCAN_TxMbAbort = 0x9, /*!< MB is aborted.*/ + kFLEXCAN_TxMbDataOrRemote = 0xC, /*!< MB is a TX Data Frame(when MB RTR = 0) or */ + /*!< MB is a TX Remote Request Frame (when MB RTR = 1).*/ + kFLEXCAN_TxMbTanswer = 0xE, /*!< MB is a TX Response Request Frame from */ + /*! an incoming Remote Request Frame.*/ + kFLEXCAN_TxMbNotUsed = 0xF, /*!< Not used.*/ +}; + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! + * @brief Get the FlexCAN instance from peripheral base address. + * + * @param base FlexCAN peripheral base address. + * @return FlexCAN instance. + */ +uint32_t FLEXCAN_GetInstance(CAN_Type *base); + +/*! + * @brief Enter FlexCAN Fraze Mode. + * + * This function makes the FlexCAN work under Fraze Mode. + * + * @param base FlexCAN peripheral base address. + */ +static void FLEXCAN_EnterFrazeMode(CAN_Type *base); + +/*! + * @brief Exit FlexCAN Fraze Mode. + * + * This function makes the FlexCAN leave Fraze Mode. + * + * @param base FlexCAN peripheral base address. + */ +static void FLEXCAN_ExitFrazeMode(CAN_Type *base); + +/*! + * @brief Check if Message Buffer is occupied by Rx FIFO. + * + * This function check if Message Buffer is occupied by Rx FIFO. + * + * @param base FlexCAN peripheral base address. + * @param mbIdx The FlexCAN Message Buffer index. + */ +static bool FLEXCAN_IsMbOccupied(CAN_Type *base, uint8_t mbIdx); + +/*! + * @brief Check if Message Buffer interrupt is enabled. + * + * This function check if Message Buffer interrupt is enabled. + * + * @param base FlexCAN peripheral base address. + * @param mbIdx The FlexCAN Message Buffer index. + */ +static bool FLEXCAN_IsMbIntEnabled(CAN_Type *base, uint8_t mbIdx); + +/*! + * @brief Reset the FlexCAN Instance. + * + * Restores the FlexCAN module to reset state, notice that this function + * will set all the registers to reset state so the FlexCAN module can not work + * after calling this API. + * + * @param base FlexCAN peripheral base address. +*/ +static void FLEXCAN_Reset(CAN_Type *base); + +/*! + * @brief Set Baud Rate of FlexCAN. + * + * This function set the baud rate of FlexCAN. + * + * @param base FlexCAN peripheral base address. + * @param sourceClock_Hz Source Clock in Hz. + * @param baudRate_Bps Baud Rate in Bps. + */ +static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Bps); + +/******************************************************************************* + * Variables + ******************************************************************************/ +/* Array of FlexCAN handle. */ +static flexcan_handle_t *s_flexcanHandle[FSL_FEATURE_SOC_FLEXCAN_COUNT]; + +/* Array of FlexCAN peripheral base address. */ +static CAN_Type *const s_flexcanBases[] = CAN_BASE_PTRS; + +/* Array of FlexCAN IRQ number. */ +static const IRQn_Type s_flexcanRxWarningIRQ[] = CAN_Rx_Warning_IRQS; +static const IRQn_Type s_flexcanTxWarningIRQ[] = CAN_Tx_Warning_IRQS; +static const IRQn_Type s_flexcanWakeUpIRQ[] = CAN_Wake_Up_IRQS; +static const IRQn_Type s_flexcanErrorIRQ[] = CAN_Error_IRQS; +static const IRQn_Type s_flexcanBusOffIRQ[] = CAN_Bus_Off_IRQS; +static const IRQn_Type s_flexcanMbIRQ[] = CAN_ORed_Message_buffer_IRQS; + +/* Array of FlexCAN clock name. */ +static const clock_ip_name_t s_flexcanClock[] = FLEXCAN_CLOCKS; + +/******************************************************************************* + * Code + ******************************************************************************/ + +uint32_t FLEXCAN_GetInstance(CAN_Type *base) +{ + uint32_t instance; + + /* Find the instance index from base address mappings. */ + for (instance = 0; instance < FSL_FEATURE_SOC_FLEXCAN_COUNT; instance++) + { + if (s_flexcanBases[instance] == base) + { + break; + } + } + + assert(instance < FSL_FEATURE_SOC_FLEXCAN_COUNT); + + return instance; +} + +static void FLEXCAN_EnterFrazeMode(CAN_Type *base) +{ + /* Set Freeze, Halt bits. */ + base->MCR |= CAN_MCR_FRZ_MASK | CAN_MCR_HALT_MASK; + + /* Wait until the FlexCAN Module enter freeze mode. */ + while (!(base->MCR & CAN_MCR_FRZACK_MASK)) + { + } +} + +static void FLEXCAN_ExitFrazeMode(CAN_Type *base) +{ + /* Clear Freeze, Halt bits. */ + base->MCR &= ~(CAN_MCR_FRZ_MASK | CAN_MCR_HALT_MASK); + + /* Wait until the FlexCAN Module exit freeze mode. */ + while (base->MCR & CAN_MCR_FRZACK_MASK) + { + } +} + +static bool FLEXCAN_IsMbOccupied(CAN_Type *base, uint8_t mbIdx) +{ + uint8_t lastOccupiedMb; + + /* Is Rx FIFO enabled? */ + if (base->MCR & CAN_MCR_RFEN_MASK) + { + /* Get RFFN value. */ + lastOccupiedMb = ((base->CTRL2 & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT); + /* Calculate the number of last Message Buffer occupied by Rx FIFO. */ + lastOccupiedMb = ((lastOccupiedMb + 1) * 2) + 5; + + if (mbIdx <= lastOccupiedMb) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } +} + +static bool FLEXCAN_IsMbIntEnabled(CAN_Type *base, uint8_t mbIdx) +{ + /* Assertion. */ + assert(mbIdx < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base)); + +#if (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) + if (mbIdx < 32) + { +#endif + if (base->IMASK1 & ((uint32_t)(1 << mbIdx))) + { + return true; + } + else + { + return false; + } +#if (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) + } + else + { + if (base->IMASK2 & ((uint32_t)(1 << (mbIdx - 32)))) + return true; + else + return false; + } +#endif +} + +static void FLEXCAN_Reset(CAN_Type *base) +{ + /* The module must should be first exit from low power + * mode, and then soft reset can be applied. + */ + assert(!(base->MCR & CAN_MCR_MDIS_MASK)); + + uint8_t i; + +#if (FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT != 0) + /* De-assert DOZE Enable Bit. */ + base->MCR &= ~CAN_MCR_DOZE_MASK; +#endif + + /* Wait until FlexCAN exit from any Low Power Mode. */ + while (base->MCR & CAN_MCR_LPMACK_MASK) + { + } + + /* Assert Soft Reset Signal. */ + base->MCR |= CAN_MCR_SOFTRST_MASK; + /* Wait until FlexCAN reset completes. */ + while (base->MCR & CAN_MCR_SOFTRST_MASK) + { + } + +/* Reset MCR rigister. */ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER) && FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER) + base->MCR |= CAN_MCR_WRNEN_MASK | CAN_MCR_WAKSRC_MASK | + CAN_MCR_MAXMB(FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1); +#else + base->MCR |= CAN_MCR_WRNEN_MASK | CAN_MCR_MAXMB(FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1); +#endif + + /* Reset CTRL1 and CTRL2 rigister. */ + base->CTRL1 = CAN_CTRL1_SMP_MASK; + base->CTRL2 = CAN_CTRL2_TASD(0x16) | CAN_CTRL2_RRS_MASK | CAN_CTRL2_EACEN_MASK; + + /* Clean all individual Rx Mask of Message Buffers. */ + for (i = 0; i < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); i++) + { + base->RXIMR[i] = 0x3FFFFFFF; + } + + /* Clean Global Mask of Message Buffers. */ + base->RXMGMASK = 0x3FFFFFFF; + /* Clean Global Mask of Message Buffer 14. */ + base->RX14MASK = 0x3FFFFFFF; + /* Clean Global Mask of Message Buffer 15. */ + base->RX15MASK = 0x3FFFFFFF; + /* Clean Global Mask of Rx FIFO. */ + base->RXFGMASK = 0x3FFFFFFF; + + /* Clean all Message Buffer CS fields. */ + for (i = 0; i < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); i++) + { + base->MB[i].CS = 0x0; + } +} + +static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Bps) +{ + flexcan_timing_config_t timingConfig; + uint32_t priDiv = baudRate_Bps * FLEXCAN_TIME_QUANTA_NUM; + + /* Assertion: Desired baud rate is too high. */ + assert(baudRate_Bps <= 1000000U); + /* Assertion: Source clock should greater than baud rate * FLEXCAN_TIME_QUANTA_NUM. */ + assert(priDiv <= sourceClock_Hz); + + if (0 == priDiv) + { + priDiv = 1; + } + + priDiv = (sourceClock_Hz / priDiv) - 1; + + /* Desired baud rate is too low. */ + if (priDiv > 0xFF) + { + priDiv = 0xFF; + } + + /* FlexCAN timing setting formula: + * FLEXCAN_TIME_QUANTA_NUM = 1 + (PSEG1 + 1) + (PSEG2 + 1) + (PROPSEG + 1); + */ + timingConfig.preDivider = priDiv; + timingConfig.phaseSeg1 = 3; + timingConfig.phaseSeg2 = 2; + timingConfig.propSeg = 1; + timingConfig.rJumpwidth = 1; + + /* Update actual timing characteristic. */ + FLEXCAN_SetTimingConfig(base, &timingConfig); +} + +void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz) +{ + uint32_t mcrTemp; + + /* Assertion. */ + assert(config); + assert((config->maxMbNum > 0) && (config->maxMbNum <= FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base))); + + /* Enable FlexCAN clock. */ + CLOCK_EnableClock(s_flexcanClock[FLEXCAN_GetInstance(base)]); + + /* Disable FlexCAN Module. */ + FLEXCAN_Enable(base, false); + + /* Protocol-Engine clock source selection, This bit must be set + * when FlexCAN Module in Disable Mode. + */ + base->CTRL1 = (kFLEXCAN_ClkSrcOsc == config->clkSrc) ? base->CTRL1 & ~CAN_CTRL1_CLKSRC_MASK : + base->CTRL1 | CAN_CTRL1_CLKSRC_MASK; + + /* Enable FlexCAN Module for configuartion. */ + FLEXCAN_Enable(base, true); + + /* Reset to known status. */ + FLEXCAN_Reset(base); + + /* Save current MCR value. */ + mcrTemp = base->MCR; + + /* Set the maximum number of Message Buffers */ + mcrTemp = (mcrTemp & ~CAN_MCR_MAXMB_MASK) | CAN_MCR_MAXMB(config->maxMbNum - 1); + + /* Enable Loop Back Mode? */ + base->CTRL1 = (config->enableLoopBack) ? base->CTRL1 | CAN_CTRL1_LPB_MASK : base->CTRL1 & ~CAN_CTRL1_LPB_MASK; + + /* Enable Self Wake Up Mode? */ + mcrTemp = (config->enableSelfWakeup) ? mcrTemp | CAN_MCR_SLFWAK_MASK : mcrTemp & ~CAN_MCR_SLFWAK_MASK; + + /* Enable Individual Rx Masking? */ + mcrTemp = (config->enableIndividMask) ? mcrTemp | CAN_MCR_IRMQ_MASK : mcrTemp & ~CAN_MCR_IRMQ_MASK; + +#if (defined(FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) + /* Enable Doze Mode? */ + mcrTemp = (config->enableDoze) ? mcrTemp | CAN_MCR_DOZE_MASK : mcrTemp & ~CAN_MCR_DOZE_MASK; +#endif + + /* Save MCR Configuation. */ + base->MCR = mcrTemp; + + /* Baud Rate Configuration.*/ + FLEXCAN_SetBaudRate(base, sourceClock_Hz, config->baudRate); +} + +void FLEXCAN_Deinit(CAN_Type *base) +{ + /* Reset all Register Contents. */ + FLEXCAN_Reset(base); + + /* Disable FlexCAN module. */ + FLEXCAN_Enable(base, false); + + /* Disable FlexCAN clock. */ + CLOCK_DisableClock(s_flexcanClock[FLEXCAN_GetInstance(base)]); +} + +void FLEXCAN_GetDefaultConfig(flexcan_config_t *config) +{ + /* Assertion. */ + assert(config); + + /* Initialize FlexCAN Module config struct with default value. */ + config->clkSrc = kFLEXCAN_ClkSrcOsc; + config->baudRate = 125000U; + config->maxMbNum = 16; + config->enableLoopBack = false; + config->enableSelfWakeup = false; + config->enableIndividMask = false; +#if (defined(FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) + config->enableDoze = false; +#endif +} + +void FLEXCAN_SetTimingConfig(CAN_Type *base, const flexcan_timing_config_t *config) +{ + /* Assertion. */ + assert(config); + + /* Enter Fraze Mode. */ + FLEXCAN_EnterFrazeMode(base); + + /* Cleaning previous Timing Setting. */ + base->CTRL1 &= ~(CAN_CTRL1_PRESDIV_MASK | CAN_CTRL1_RJW_MASK | CAN_CTRL1_PSEG1_MASK | CAN_CTRL1_PSEG2_MASK | + CAN_CTRL1_PROPSEG_MASK); + + /* Updating Timing Setting according to configuration structure. */ + base->CTRL1 |= + (CAN_CTRL1_PRESDIV(config->preDivider) | CAN_CTRL1_RJW(config->rJumpwidth) | + CAN_CTRL1_PSEG1(config->phaseSeg1) | CAN_CTRL1_PSEG2(config->phaseSeg2) | CAN_CTRL1_PROPSEG(config->propSeg)); + + /* Exit Fraze Mode. */ + FLEXCAN_ExitFrazeMode(base); +} + +void FlEXCAN_SetRxMbGlobalMask(CAN_Type *base, uint32_t mask) +{ + /* Enter Fraze Mode. */ + FLEXCAN_EnterFrazeMode(base); + + /* Setting Rx Message Buffer Global Mask value. */ + base->RXMGMASK = mask; + base->RX14MASK = mask; + base->RX15MASK = mask; + + /* Exit Fraze Mode. */ + FLEXCAN_ExitFrazeMode(base); +} + +void FlEXCAN_SetRxFifoGlobalMask(CAN_Type *base, uint32_t mask) +{ + /* Enter Fraze Mode. */ + FLEXCAN_EnterFrazeMode(base); + + /* Setting Rx FIFO Global Mask value. */ + base->RXFGMASK = mask; + + /* Exit Fraze Mode. */ + FLEXCAN_ExitFrazeMode(base); +} + +void FlEXCAN_SetRxIndividualMask(CAN_Type *base, uint8_t maskIdx, uint32_t mask) +{ + assert(maskIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + + /* Enter Fraze Mode. */ + FLEXCAN_EnterFrazeMode(base); + + /* Setting Rx Individual Mask value. */ + base->RXIMR[maskIdx] = mask; + + /* Exit Fraze Mode. */ + FLEXCAN_ExitFrazeMode(base); +} + +void FLEXCAN_SetTxMbConfig(CAN_Type *base, uint8_t mbIdx, bool enable) +{ + /* Assertion. */ + assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + + if (FLEXCAN_IsMbOccupied(base, mbIdx)) + { + assert(false); + } + + /* Inactivate Message Buffer. */ + if (enable) + { + base->MB[mbIdx].CS = CAN_CS_CODE(kFLEXCAN_TxMbInactive); + } + else + { + base->MB[mbIdx].CS = 0; + } + + /* Clean Message Buffer content. */ + base->MB[mbIdx].ID = 0x0; + base->MB[mbIdx].WORD0 = 0x0; + base->MB[mbIdx].WORD1 = 0x0; +} + +void FLEXCAN_SetRxMbConfig(CAN_Type *base, uint8_t mbIdx, const flexcan_rx_mb_config_t *config, bool enable) +{ + /* Assertion. */ + assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + assert(((config) || (false == enable))); + + uint32_t cs_temp = 0; + + if (FLEXCAN_IsMbOccupied(base, mbIdx)) + { + assert(false); + } + + /* Inactivate Message Buffer. */ + base->MB[mbIdx].CS = 0; + + /* Clean Message Buffer content. */ + base->MB[mbIdx].ID = 0x0; + base->MB[mbIdx].WORD0 = 0x0; + base->MB[mbIdx].WORD1 = 0x0; + + if (enable) + { + /* Setup Message Buffer ID. */ + base->MB[mbIdx].ID = config->id; + + /* Setup Message Buffer format. */ + if (kFLEXCAN_FrameFormatExtend == config->format) + { + cs_temp |= CAN_CS_IDE_MASK; + } + + /* Setup Message Buffer type. */ + if (kFLEXCAN_FrameTypeRemote == config->type) + { + cs_temp |= CAN_CS_RTR_MASK; + } + + /* Activate Rx Message Buffer. */ + cs_temp |= CAN_CS_CODE(kFLEXCAN_RxMbEmpty); + base->MB[mbIdx].CS = cs_temp; + } +} + +void FlEXCAN_SetRxFifoConfig(CAN_Type *base, const flexcan_rx_fifo_config_t *config, bool enable) +{ + /* Assertion. */ + assert((config) || (false == enable)); + + volatile uint32_t *idFilterRegion = (volatile uint32_t *)(&base->MB[6].CS); + uint8_t setup_mb, i, rffn = 0; + + /* Enter Fraze Mode. */ + FLEXCAN_EnterFrazeMode(base); + + if (enable) + { + assert(config->idFilterNum <= 128); + + /* Get the setup_mb value. */ + setup_mb = (base->MCR & CAN_MCR_MAXMB_MASK) >> CAN_MCR_MAXMB_SHIFT; + setup_mb = (setup_mb < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base)) ? + setup_mb : + FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); + + /* Determine RFFN value. */ + for (i = 0; i <= 0xF; i++) + { + if ((8 * (i + 1)) >= config->idFilterNum) + { + rffn = i; + assert(((setup_mb - 8) - (2 * rffn)) > 0); + + base->CTRL2 = (base->CTRL2 & ~CAN_CTRL2_RFFN_MASK) | CAN_CTRL2_RFFN(rffn); + break; + } + } + } + else + { + rffn = (base->CTRL2 & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT; + } + + /* Clean ID filter table occuyied Message Buffer Region. */ + rffn = (rffn + 1) * 8; + for (i = 0; i < rffn; i++) + { + idFilterRegion[i] = 0x0; + } + + if (enable) + { + /* Disable unused Rx FIFO Filter. */ + for (i = config->idFilterNum; i < rffn; i++) + { + idFilterRegion[i] = 0xFFFFFFFFU; + } + + /* Copy ID filter table to Message Buffer Region. */ + for (i = 0; i < config->idFilterNum; i++) + { + idFilterRegion[i] = config->idFilterTable[i]; + } + + /* Setup ID Fitlter Type. */ + switch (config->idFilterType) + { + case kFLEXCAN_RxFifoFilterTypeA: + base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x0); + break; + case kFLEXCAN_RxFifoFilterTypeB: + base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x1); + break; + case kFLEXCAN_RxFifoFilterTypeC: + base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x2); + break; + case kFLEXCAN_RxFifoFilterTypeD: + /* All frames rejected. */ + base->MCR = (base->MCR & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0x3); + break; + default: + break; + } + + /* Setting Message Reception Priority. */ + base->CTRL2 = (config->priority == kFLEXCAN_RxFifoPrioHigh) ? base->CTRL2 & ~CAN_CTRL2_MRP_MASK : + base->CTRL2 | CAN_CTRL2_MRP_MASK; + + /* Enable Rx Message FIFO. */ + base->MCR |= CAN_MCR_RFEN_MASK; + } + else + { + /* Disable Rx Message FIFO. */ + base->MCR &= ~CAN_MCR_RFEN_MASK; + + /* Clean MB0 ~ MB5. */ + FLEXCAN_SetRxMbConfig(base, 0, NULL, false); + FLEXCAN_SetRxMbConfig(base, 1, NULL, false); + FLEXCAN_SetRxMbConfig(base, 2, NULL, false); + FLEXCAN_SetRxMbConfig(base, 3, NULL, false); + FLEXCAN_SetRxMbConfig(base, 4, NULL, false); + FLEXCAN_SetRxMbConfig(base, 5, NULL, false); + } + + /* Exit Fraze Mode. */ + FLEXCAN_ExitFrazeMode(base); +} + +#if (defined(FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA) && FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA) +void FLEXCAN_EnableRxFifoDMA(CAN_Type *base, bool enable) +{ + if (enable) + { + /* Enter Fraze Mode. */ + FLEXCAN_EnterFrazeMode(base); + + /* Enable FlexCAN DMA. */ + base->MCR |= CAN_MCR_DMA_MASK; + + /* Exit Fraze Mode. */ + FLEXCAN_ExitFrazeMode(base); + } + else + { + /* Enter Fraze Mode. */ + FLEXCAN_EnterFrazeMode(base); + + /* Disable FlexCAN DMA. */ + base->MCR &= ~CAN_MCR_DMA_MASK; + + /* Exit Fraze Mode. */ + FLEXCAN_ExitFrazeMode(base); + } +} +#endif /* FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA */ + +status_t FLEXCAN_WriteTxMb(CAN_Type *base, uint8_t mbIdx, const flexcan_frame_t *txFrame) +{ + /* Assertion. */ + assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + assert(txFrame); + assert(txFrame->length <= 8); + + uint32_t cs_temp = 0; + + if (FLEXCAN_IsMbOccupied(base, mbIdx)) + { + assert(false); + } + + /* Check if Message Buffer is available. */ + if (CAN_CS_CODE(kFLEXCAN_TxMbDataOrRemote) != (base->MB[mbIdx].CS & CAN_CS_CODE_MASK)) + { + /* Inactive Tx Message Buffer. */ + base->MB[mbIdx].CS = (base->MB[mbIdx].CS & ~CAN_CS_CODE_MASK) | CAN_CS_CODE(kFLEXCAN_TxMbInactive); + + /* Fill Message ID field. */ + base->MB[mbIdx].ID = txFrame->id; + + /* Fill Message Format field. */ + if (kFLEXCAN_FrameFormatExtend == txFrame->format) + { + cs_temp |= CAN_CS_SRR_MASK | CAN_CS_IDE_MASK; + } + + /* Fill Message Type field. */ + if (kFLEXCAN_FrameTypeRemote == txFrame->type) + { + cs_temp |= CAN_CS_RTR_MASK; + } + + cs_temp |= CAN_CS_CODE(kFLEXCAN_TxMbDataOrRemote) | CAN_CS_DLC(txFrame->length); + + /* Load Message Payload. */ + base->MB[mbIdx].WORD0 = txFrame->dataWord0; + base->MB[mbIdx].WORD1 = txFrame->dataWord1; + + /* Activate Tx Message Buffer. */ + base->MB[mbIdx].CS = cs_temp; + + return kStatus_Success; + } + else + { + /* Tx Message Buffer is activated, return immediately. */ + return kStatus_Fail; + } +} + +status_t FLEXCAN_ReadRxMb(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *rxFrame) +{ + /* Assertion. */ + assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + assert(rxFrame); + + uint32_t cs_temp; + uint8_t rx_code; + + if (FLEXCAN_IsMbOccupied(base, mbIdx)) + { + assert(false); + } + + /* Read CS field of Rx Message Buffer to lock Message Buffer. */ + cs_temp = base->MB[mbIdx].CS; + /* Get Rx Message Buffer Code field. */ + rx_code = (cs_temp & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT; + + /* Check to see if Rx Message Buffer is full. */ + if ((kFLEXCAN_RxMbFull == rx_code) || (kFLEXCAN_RxMbOverrun == rx_code)) + { + /* Store Message ID. */ + rxFrame->id = base->MB[mbIdx].ID & (CAN_ID_EXT_MASK | CAN_ID_STD_MASK); + + /* Get the message ID and format. */ + rxFrame->format = (cs_temp & CAN_CS_IDE_MASK) ? kFLEXCAN_FrameFormatExtend : kFLEXCAN_FrameFormatStandard; + + /* Get the message type. */ + rxFrame->type = (cs_temp & CAN_CS_RTR_MASK) ? kFLEXCAN_FrameTypeRemote : kFLEXCAN_FrameTypeData; + + /* Get the message length. */ + rxFrame->length = (cs_temp & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT; + + /* Store Message Payload. */ + rxFrame->dataWord0 = base->MB[mbIdx].WORD0; + rxFrame->dataWord1 = base->MB[mbIdx].WORD1; + + /* Read free-running timer to unlock Rx Message Buffer. */ + (void)base->TIMER; + + if (kFLEXCAN_RxMbFull == rx_code) + { + return kStatus_Success; + } + else + { + return kStatus_FLEXCAN_RxOverflow; + } + } + else + { + /* Read free-running timer to unlock Rx Message Buffer. */ + (void)base->TIMER; + + return kStatus_Fail; + } +} + +status_t FlEXCAN_ReadRxFifo(CAN_Type *base, flexcan_frame_t *rxFrame) +{ + /* Assertion. */ + assert(rxFrame); + + uint32_t cs_temp; + + /* Check if Rx FIFO is Enabled. */ + if (base->MCR & CAN_MCR_RFEN_MASK) + { + /* Read CS field of Rx Message Buffer to lock Message Buffer. */ + cs_temp = base->MB[0].CS; + + /* Read data from Rx FIFO output port. */ + /* Store Message ID. */ + rxFrame->id = base->MB[0].ID & (CAN_ID_EXT_MASK | CAN_ID_STD_MASK); + + /* Get the message ID and format. */ + rxFrame->format = (cs_temp & CAN_CS_IDE_MASK) ? kFLEXCAN_FrameFormatExtend : kFLEXCAN_FrameFormatStandard; + + /* Get the message type. */ + rxFrame->type = (cs_temp & CAN_CS_RTR_MASK) ? kFLEXCAN_FrameTypeRemote : kFLEXCAN_FrameTypeData; + + /* Get the message length. */ + rxFrame->length = (cs_temp & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT; + + /* Store Message Payload. */ + rxFrame->dataWord0 = base->MB[0].WORD0; + rxFrame->dataWord1 = base->MB[0].WORD1; + + /* Store ID Filter Hit Index. */ + rxFrame->idhit = (uint8_t)(base->RXFIR & CAN_RXFIR_IDHIT_MASK); + + /* Read free-running timer to unlock Rx Message Buffer. */ + (void)base->TIMER; + + return kStatus_Success; + } + else + { + return kStatus_Fail; + } +} + +status_t FlEXCAN_TransferSendBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *txFrame) +{ + /* Write Tx Message Buffer to initiate a data sending. */ + if (kStatus_Success == FLEXCAN_WriteTxMb(base, mbIdx, txFrame)) + { + /* Wait until CAN Message send out. */ + while (!FLEXCAN_GetMbStatusFlags(base, 1 << mbIdx)) + { + } + + /* Clean Tx Message Buffer Flag. */ + FLEXCAN_ClearMbStatusFlags(base, 1 << mbIdx); + + return kStatus_Success; + } + else + { + return kStatus_Fail; + } +} + +status_t FlEXCAN_TransferReceiveBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *rxFrame) +{ + /* Wait until Rx Message Buffer non-empty. */ + while (!FLEXCAN_GetMbStatusFlags(base, 1 << mbIdx)) + { + } + + /* Clean Rx Message Buffer Flag. */ + FLEXCAN_ClearMbStatusFlags(base, 1 << mbIdx); + + /* Read Received CAN Message. */ + return FLEXCAN_ReadRxMb(base, mbIdx, rxFrame); +} + +status_t FlEXCAN_TransferReceiveFifoBlocking(CAN_Type *base, flexcan_frame_t *rxFrame) +{ + status_t rxFifoStatus; + + /* Wait until Rx FIFO non-empty. */ + while (!FLEXCAN_GetMbStatusFlags(base, kFLEXCAN_RxFifoFrameAvlFlag)) + { + } + + /* */ + rxFifoStatus = FlEXCAN_ReadRxFifo(base, rxFrame); + + /* Clean Rx Fifo available flag. */ + FLEXCAN_ClearMbStatusFlags(base, kFLEXCAN_RxFifoFrameAvlFlag); + + return rxFifoStatus; +} + +void FLEXCAN_TransferCreateHandle(CAN_Type *base, + flexcan_handle_t *handle, + flexcan_transfer_callback_t callback, + void *userData) +{ + assert(handle); + + uint8_t instance; + + /* Clean FlexCAN transfer handle. */ + memset(handle, 0, sizeof(*handle)); + + /* Get instance from peripheral base address. */ + instance = FLEXCAN_GetInstance(base); + + /* Save the context in global variables to support the double weak mechanism. */ + s_flexcanHandle[instance] = handle; + + /* Register Callback function. */ + handle->callback = callback; + handle->userData = userData; + + /* We Enable Error & Status interrupt here, because this interrupt just + * report current status of FlexCAN module through Callback function. + * It is insignificance without a available callback function. + */ + if (handle->callback != NULL) + { + FLEXCAN_EnableInterrupts(base, kFLEXCAN_BusOffInterruptEnable | kFLEXCAN_ErrorInterruptEnable | + kFLEXCAN_RxWarningInterruptEnable | kFLEXCAN_TxWarningInterruptEnable | + kFLEXCAN_WakeUpInterruptEnable); + } + else + { + FLEXCAN_DisableInterrupts(base, kFLEXCAN_BusOffInterruptEnable | kFLEXCAN_ErrorInterruptEnable | + kFLEXCAN_RxWarningInterruptEnable | kFLEXCAN_TxWarningInterruptEnable | + kFLEXCAN_WakeUpInterruptEnable); + } + + /* Enable interrupts in NVIC. */ + EnableIRQ((IRQn_Type)(s_flexcanRxWarningIRQ[instance])); + EnableIRQ((IRQn_Type)(s_flexcanTxWarningIRQ[instance])); + EnableIRQ((IRQn_Type)(s_flexcanWakeUpIRQ[instance])); + EnableIRQ((IRQn_Type)(s_flexcanErrorIRQ[instance])); + EnableIRQ((IRQn_Type)(s_flexcanBusOffIRQ[instance])); + EnableIRQ((IRQn_Type)(s_flexcanMbIRQ[instance])); +} + +status_t FLEXCAN_TransferSendNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *xfer) +{ + /* Assertion. */ + assert(handle); + assert(xfer); + assert(xfer->mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + + if (FLEXCAN_IsMbOccupied(base, xfer->mbIdx)) + { + assert(false); + } + + /* Check if Message Buffer is idle. */ + if (kFLEXCAN_StateIdle == handle->mbState[xfer->mbIdx]) + { + /* Distinguish transmit type. */ + if (kFLEXCAN_FrameTypeRemote == xfer->frame->type) + { + handle->mbState[xfer->mbIdx] = kFLEXCAN_StateTxRemote; + + /* Register user Frame buffer to receive remote Frame. */ + handle->mbFrameBuf[xfer->mbIdx] = xfer->frame; + } + else + { + handle->mbState[xfer->mbIdx] = kFLEXCAN_StateTxData; + } + + if (kStatus_Success == FLEXCAN_WriteTxMb(base, xfer->mbIdx, xfer->frame)) + { + /* Enable Message Buffer Interrupt. */ + FLEXCAN_EnableMbInterrupts(base, 1 << xfer->mbIdx); + + return kStatus_Success; + } + else + { + handle->mbState[xfer->mbIdx] = kFLEXCAN_StateIdle; + return kStatus_Fail; + } + } + else + { + return kStatus_FLEXCAN_TxBusy; + } +} + +status_t FLEXCAN_TransferReceiveNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *xfer) +{ + /* Assertion. */ + assert(handle); + assert(xfer); + assert(xfer->mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + + if (FLEXCAN_IsMbOccupied(base, xfer->mbIdx)) + { + assert(false); + } + + /* Check if Message Buffer is idle. */ + if (kFLEXCAN_StateIdle == handle->mbState[xfer->mbIdx]) + { + handle->mbState[xfer->mbIdx] = kFLEXCAN_StateRxData; + + /* Register Message Buffer. */ + handle->mbFrameBuf[xfer->mbIdx] = xfer->frame; + + /* Enable Message Buffer Interrupt. */ + FLEXCAN_EnableMbInterrupts(base, 1 << xfer->mbIdx); + + return kStatus_Success; + } + else + { + return kStatus_FLEXCAN_RxBusy; + } +} + +status_t FLEXCAN_TransferReceiveFifoNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_fifo_transfer_t *xfer) +{ + /* Assertion. */ + assert(handle); + assert(xfer); + + /* Check if Message Buffer is idle. */ + if (kFLEXCAN_StateIdle == handle->rxFifoState) + { + handle->rxFifoState = kFLEXCAN_StateRxFifo; + + /* Register Message Buffer. */ + handle->rxFifoFrameBuf = xfer->frame; + + /* Enable Message Buffer Interrupt. */ + FLEXCAN_EnableMbInterrupts( + base, kFLEXCAN_RxFifoOverflowFlag | kFLEXCAN_RxFifoWarningFlag | kFLEXCAN_RxFifoFrameAvlFlag); + + return kStatus_Success; + } + else + { + return kStatus_FLEXCAN_RxFifoBusy; + } +} + +void FLEXCAN_TransferAbortSend(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx) +{ + /* Assertion. */ + assert(handle); + assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + + if (FLEXCAN_IsMbOccupied(base, mbIdx)) + { + assert(false); + } + + /* Disable Message Buffer Interrupt. */ + FLEXCAN_DisableMbInterrupts(base, 1 << mbIdx); + + /* Un-register handle. */ + handle->mbFrameBuf[mbIdx] = 0x0; + + /* Clean Message Buffer. */ + FLEXCAN_SetTxMbConfig(base, mbIdx, true); + + handle->mbState[mbIdx] = kFLEXCAN_StateIdle; +} + +void FLEXCAN_TransferAbortReceive(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx) +{ + /* Assertion. */ + assert(handle); + assert(mbIdx <= (base->MCR & CAN_MCR_MAXMB_MASK)); + + if (FLEXCAN_IsMbOccupied(base, mbIdx)) + { + assert(false); + } + + /* Disable Message Buffer Interrupt. */ + FLEXCAN_DisableMbInterrupts(base, 1 << mbIdx); + + /* Un-register handle. */ + handle->mbFrameBuf[mbIdx] = 0x0; + handle->mbState[mbIdx] = kFLEXCAN_StateIdle; +} + +void FLEXCAN_TransferAbortReceiveFifo(CAN_Type *base, flexcan_handle_t *handle) +{ + /* Assertion. */ + assert(handle); + + /* Check if Rx FIFO is enabled. */ + if (base->MCR & CAN_MCR_RFEN_MASK) + { + /* Disable Rx Message FIFO Interrupts. */ + FLEXCAN_DisableMbInterrupts( + base, kFLEXCAN_RxFifoOverflowFlag | kFLEXCAN_RxFifoWarningFlag | kFLEXCAN_RxFifoFrameAvlFlag); + + /* Un-register handle. */ + handle->rxFifoFrameBuf = 0x0; + } + + handle->rxFifoState = kFLEXCAN_StateIdle; +} + +void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle) +{ + /* Assertion. */ + assert(handle); + + status_t status = kStatus_FLEXCAN_UnHandled; + uint32_t result; + + /* Store Current FlexCAN Module Error and Status. */ + result = base->ESR1; + + do + { + /* Solve FlexCAN Error and Status Interrupt. */ + if (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | + kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)) + { + status = kStatus_FLEXCAN_ErrorStatus; + + /* Clear FlexCAN Error and Status Interrupt. */ + FLEXCAN_ClearStatusFlags(base, kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | + kFLEXCAN_BusOffIntFlag | kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag); + } + /* Solve FlexCAN Rx FIFO & Message Buffer Interrupt. */ + else + { + /* For this implementation, we solve the Message with lowest MB index first. */ + for (result = 0; result < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); result++) + { + /* Get the lowest unhandled Message Buffer */ + if ((FLEXCAN_GetMbStatusFlags(base, 1 << result)) && (FLEXCAN_IsMbIntEnabled(base, result))) + { + break; + } + } + + /* Does not find Message to deal with. */ + if (result == FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base)) + { + break; + } + + /* Solve Rx FIFO interrupt. */ + if ((kFLEXCAN_StateIdle != handle->rxFifoState) && ((1 << result) <= kFLEXCAN_RxFifoOverflowFlag)) + { + switch (1 << result) + { + case kFLEXCAN_RxFifoOverflowFlag: + status = kStatus_FLEXCAN_RxFifoOverflow; + break; + + case kFLEXCAN_RxFifoWarningFlag: + status = kStatus_FLEXCAN_RxFifoWarning; + break; + + case kFLEXCAN_RxFifoFrameAvlFlag: + status = FlEXCAN_ReadRxFifo(base, handle->rxFifoFrameBuf); + if (kStatus_Success == status) + { + status = kStatus_FLEXCAN_RxFifoIdle; + } + FLEXCAN_TransferAbortReceiveFifo(base, handle); + break; + + default: + status = kStatus_FLEXCAN_UnHandled; + break; + } + } + else + { + /* Get current State of Message Buffer. */ + switch (handle->mbState[result]) + { + /* Solve Rx Data Frame. */ + case kFLEXCAN_StateRxData: + status = FLEXCAN_ReadRxMb(base, result, handle->mbFrameBuf[result]); + if (kStatus_Success == status) + { + status = kStatus_FLEXCAN_RxIdle; + } + FLEXCAN_TransferAbortReceive(base, handle, result); + break; + + /* Solve Rx Remote Frame. */ + case kFLEXCAN_StateRxRemote: + status = FLEXCAN_ReadRxMb(base, result, handle->mbFrameBuf[result]); + if (kStatus_Success == status) + { + status = kStatus_FLEXCAN_RxIdle; + } + FLEXCAN_TransferAbortReceive(base, handle, result); + break; + + /* Solve Tx Data Frame. */ + case kFLEXCAN_StateTxData: + status = kStatus_FLEXCAN_TxIdle; + FLEXCAN_TransferAbortSend(base, handle, result); + break; + + /* Solve Tx Remote Frame. */ + case kFLEXCAN_StateTxRemote: + handle->mbState[result] = kFLEXCAN_StateRxRemote; + status = kStatus_FLEXCAN_TxSwitchToRx; + break; + + default: + status = kStatus_FLEXCAN_UnHandled; + break; + } + } + + /* Clear resolved Message Buffer IRQ. */ + FLEXCAN_ClearMbStatusFlags(base, 1 << result); + } + + /* Calling Callback Function if has one. */ + if (handle->callback != NULL) + { + handle->callback(base, handle, status, result, handle->userData); + } + + /* Reset return status */ + status = kStatus_FLEXCAN_UnHandled; + + /* Store Current FlexCAN Module Error and Status. */ + result = base->ESR1; + } +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) + while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFFFFFFFFFU)) || + (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | + kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); +#else + while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) || + (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | + kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); +#endif +} + +#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 0) +void CAN0_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[0]); + + FLEXCAN_TransferHandleIRQ(CAN0, s_flexcanHandle[0]); +} +#endif + +#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 1) +void CAN1_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[1]); + + FLEXCAN_TransferHandleIRQ(CAN1, s_flexcanHandle[1]); +} +#endif + +#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 2) +void CAN2_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[2]); + + FLEXCAN_TransferHandleIRQ(CAN2, s_flexcanHandle[2]); +} +#endif + +#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 3) +void CAN3_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[3]); + + FLEXCAN_TransferHandleIRQ(CAN3, s_flexcanHandle[3]); +} +#endif + +#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 4) +void CAN4_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[4]); + + FLEXCAN_TransferHandleIRQ(CAN4, s_flexcanHandle[4]); +} +#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f8f2ebbf/hw/mcu/nxp/src/ext/sdk-2.0-frdm-k64f_b160321/devices/MK64F12/drivers/fsl_flexcan.h ---------------------------------------------------------------------- diff --git a/hw/mcu/nxp/src/ext/sdk-2.0-frdm-k64f_b160321/devices/MK64F12/drivers/fsl_flexcan.h b/hw/mcu/nxp/src/ext/sdk-2.0-frdm-k64f_b160321/devices/MK64F12/drivers/fsl_flexcan.h new file mode 100644 index 0000000..b0dee77 --- /dev/null +++ b/hw/mcu/nxp/src/ext/sdk-2.0-frdm-k64f_b160321/devices/MK64F12/drivers/fsl_flexcan.h @@ -0,0 +1,1053 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _FSL_FLEXCAN_H_ +#define _FSL_FLEXCAN_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup flexcan_driver + * @{ + */ + +/*! @file*/ + +/****************************************************************************** + * Definitions + *****************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief FlexCAN driver version 2.1.0. */ +#define FLEXCAN_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*@}*/ + +/*! @brief FlexCAN Frame ID helper macro. */ +#define FLEXCAN_ID_STD(id) \ + (((uint32_t)(((uint32_t)(id)) << CAN_ID_STD_SHIFT)) & CAN_ID_STD_MASK) /*!< Standard Frame ID helper macro. */ +#define FLEXCAN_ID_EXT(id) \ + (((uint32_t)(((uint32_t)(id)) << CAN_ID_EXT_SHIFT)) & \ + (CAN_ID_EXT_MASK | CAN_ID_STD_MASK)) /*!< Extend Frame ID helper macro. */ + +/*! @brief FlexCAN Rx Message Buffer Mask helper macro. */ +#define FLEXCAN_RX_MB_STD_MASK(id, rtr, ide) \ + (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ + FLEXCAN_ID_STD(id)) /*!< Standard Rx Message Buffer Mask helper macro. */ +#define FLEXCAN_RX_MB_EXT_MASK(id, rtr, ide) \ + (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ + FLEXCAN_ID_EXT(id)) /*!< Extend Rx Message Buffer Mask helper macro. */ + +/*! @brief FlexCAN Rx FIFO Mask helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_A(id, rtr, ide) \ + (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ + (FLEXCAN_ID_STD(id) << 1)) /*!< Standard Rx FIFO Mask helper macro Type A helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_HIGH(id, rtr, ide) \ + (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ + (FLEXCAN_ID_STD(id) << 16)) /*!< Standard Rx FIFO Mask helper macro Type B upper part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_LOW(id, rtr, ide) \ + (((uint32_t)((uint32_t)(rtr) << 15) | (uint32_t)((uint32_t)(ide) << 14)) | \ + FLEXCAN_ID_STD(id)) /*!< Standard Rx FIFO Mask helper macro Type B lower part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_HIGH(id) \ + ((FLEXCAN_ID_STD(id) & 0x7F8) << 21) /*!< Standard Rx FIFO Mask helper macro Type C upper part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_HIGH(id) \ + ((FLEXCAN_ID_STD(id) & 0x7F8) << 13) /*!< Standard Rx FIFO Mask helper macro Type C mid-upper part helper macro. \ + */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_LOW(id) \ + ((FLEXCAN_ID_STD(id) & 0x7F8) << 5) /*!< Standard Rx FIFO Mask helper macro Type C mid-lower part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_LOW(id) \ + ((FLEXCAN_ID_STD(id) & 0x7F8) >> 3) /*!< Standard Rx FIFO Mask helper macro Type C lower part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_A(id, rtr, ide) \ + (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ + (FLEXCAN_ID_EXT(id) << 1)) /*!< Extend Rx FIFO Mask helper macro Type A helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_B_HIGH(id, rtr, ide) \ + ( \ + ((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ + ((FLEXCAN_ID_EXT(id) & 0x1FFF8000) \ + << 1)) /*!< Extend Rx FIFO Mask helper macro Type B upper part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_B_LOW(id, rtr, ide) \ + (((uint32_t)((uint32_t)(rtr) << 15) | (uint32_t)((uint32_t)(ide) << 14)) | \ + ((FLEXCAN_ID_EXT(id) & 0x1FFF8000) >> \ + 15)) /*!< Extend Rx FIFO Mask helper macro Type B lower part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_C_HIGH(id) \ + ((FLEXCAN_ID_EXT(id) & 0x1FE00000) << 3) /*!< Extend Rx FIFO Mask helper macro Type C upper part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_C_MID_HIGH(id) \ + ((FLEXCAN_ID_EXT(id) & 0x1FE00000) >> \ + 5) /*!< Extend Rx FIFO Mask helper macro Type C mid-upper part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_C_MID_LOW(id) \ + ((FLEXCAN_ID_EXT(id) & 0x1FE00000) >> \ + 13) /*!< Extend Rx FIFO Mask helper macro Type C mid-lower part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_C_LOW(id) \ + ((FLEXCAN_ID_EXT(id) & 0x1FE00000) >> 21) /*!< Extend Rx FIFO Mask helper macro Type C lower part helper macro. */ + +/*! @brief FlexCAN Rx FIFO Filter helper macro. */ +#define FLEXCAN_RX_FIFO_STD_FILTER_TYPE_A(id, rtr, ide) \ + FLEXCAN_RX_FIFO_STD_MASK_TYPE_A(id, rtr, ide) /*!< Standard Rx FIFO Filter helper macro Type A helper macro. */ +#define FLEXCAN_RX_FIFO_STD_FILTER_TYPE_B_HIGH(id, rtr, ide) \ + FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_HIGH( \ + id, rtr, ide) /*!< Standard Rx FIFO Filter helper macro Type B upper part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_FILTER_TYPE_B_LOW(id, rtr, ide) \ + FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_LOW( \ + id, rtr, ide) /*!< Standard Rx FIFO Filter helper macro Type B lower part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_FILTER_TYPE_C_HIGH(id) \ + FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_HIGH( \ + id) /*!< Standard Rx FIFO Filter helper macro Type C upper part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_FILTER_TYPE_C_MID_HIGH(id) \ + FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_HIGH( \ + id) /*!< Standard Rx FIFO Filter helper macro Type C mid-upper part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_FILTER_TYPE_C_MID_LOW(id) \ + FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_LOW( \ + id) /*!< Standard Rx FIFO Filter helper macro Type C mid-lower part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_FILTER_TYPE_C_LOW(id) \ + FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_LOW(id) /*!< Standard Rx FIFO Filter helper macro Type C lower part helper macro. \ + */ +#define FLEXCAN_RX_FIFO_EXT_FILTER_TYPE_A(id, rtr, ide) \ + FLEXCAN_RX_FIFO_EXT_MASK_TYPE_A(id, rtr, ide) /*!< Extend Rx FIFO Filter helper macro Type A helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_FILTER_TYPE_B_HIGH(id, rtr, ide) \ + FLEXCAN_RX_FIFO_EXT_MASK_TYPE_B_HIGH( \ + id, rtr, ide) /*!< Extend Rx FIFO Filter helper macro Type B upper part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_FILTER_TYPE_B_LOW(id, rtr, ide) \ + FLEXCAN_RX_FIFO_EXT_MASK_TYPE_B_LOW( \ + id, rtr, ide) /*!< Extend Rx FIFO Filter helper macro Type B lower part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_FILTER_TYPE_C_HIGH(id) \ + FLEXCAN_RX_FIFO_EXT_MASK_TYPE_C_HIGH(id) /*!< Extend Rx FIFO Filter helper macro Type C upper part helper macro. \ + */ +#define FLEXCAN_RX_FIFO_EXT_FILTER_TYPE_C_MID_HIGH(id) \ + FLEXCAN_RX_FIFO_EXT_MASK_TYPE_C_MID_HIGH( \ + id) /*!< Extend Rx FIFO Filter helper macro Type C mid-upper part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_FILTER_TYPE_C_MID_LOW(id) \ + FLEXCAN_RX_FIFO_EXT_MASK_TYPE_C_MID_LOW( \ + id) /*!< Extend Rx FIFO Filter helper macro Type C mid-lower part helper macro. */ +#define FLEXCAN_RX_FIFO_EXT_FILTER_TYPE_C_LOW(id) \ + FLEXCAN_RX_FIFO_EXT_MASK_TYPE_C_LOW(id) /*!< Extend Rx FIFO Filter helper macro Type C lower part helper macro. */ + +/*! @brief FlexCAN transfer status. */ +enum _flexcan_status +{ + kStatus_FLEXCAN_TxBusy = MAKE_STATUS(kStatusGroup_FLEXCAN, 0), /*!< Tx Message Buffer is Busy. */ + kStatus_FLEXCAN_TxIdle = MAKE_STATUS(kStatusGroup_FLEXCAN, 1), /*!< Tx Message Buffer is Idle. */ + kStatus_FLEXCAN_TxSwitchToRx = MAKE_STATUS( + kStatusGroup_FLEXCAN, 2), /*!< Remote Message is send out and Message buffer changed to Receive one. */ + kStatus_FLEXCAN_RxBusy = MAKE_STATUS(kStatusGroup_FLEXCAN, 3), /*!< Rx Message Buffer is Busy. */ + kStatus_FLEXCAN_RxIdle = MAKE_STATUS(kStatusGroup_FLEXCAN, 4), /*!< Rx Message Buffer is Idle. */ + kStatus_FLEXCAN_RxOverflow = MAKE_STATUS(kStatusGroup_FLEXCAN, 5), /*!< Rx Message Buffer is Overflowed. */ + kStatus_FLEXCAN_RxFifoBusy = MAKE_STATUS(kStatusGroup_FLEXCAN, 6), /*!< Rx Message FIFO is Busy. */ + kStatus_FLEXCAN_RxFifoIdle = MAKE_STATUS(kStatusGroup_FLEXCAN, 7), /*!< Rx Message FIFO is Idle. */ + kStatus_FLEXCAN_RxFifoOverflow = MAKE_STATUS(kStatusGroup_FLEXCAN, 8), /*!< Rx Message FIFO is overflowed. */ + kStatus_FLEXCAN_RxFifoWarning = MAKE_STATUS(kStatusGroup_FLEXCAN, 0), /*!< Rx Message FIFO is almost overflowed. */ + kStatus_FLEXCAN_ErrorStatus = MAKE_STATUS(kStatusGroup_FLEXCAN, 10), /*!< FlexCAN Module Error and Status. */ + kStatus_FLEXCAN_UnHandled = MAKE_STATUS(kStatusGroup_FLEXCAN, 11), /*!< UnHadled Interrupt asserted. */ +}; + +/*! @brief FlexCAN frame format. */ +typedef enum _flexcan_frame_format +{ + kFLEXCAN_FrameFormatStandard = 0x0U, /*!< Standard frame format attribute. */ + kFLEXCAN_FrameFormatExtend = 0x1U, /*!< Extend frame format attribute. */ +} flexcan_frame_format_t; + +/*! @brief FlexCAN frame type. */ +typedef enum _flexcan_frame_type +{ + kFLEXCAN_FrameTypeData = 0x0U, /*!< Data frame type attribute. */ + kFLEXCAN_FrameTypeRemote = 0x1U, /*!< Remote frame type attribute. */ +} flexcan_frame_type_t; + +/*! @brief FlexCAN clock source. */ +typedef enum _flexcan_clock_source +{ + kFLEXCAN_ClkSrcOsc = 0x0U, /*!< FlexCAN Protocol Engine clock from Oscillator. */ + kFLEXCAN_ClkSrcPeri = 0x1U, /*!< FlexCAN Protocol Engine clock from Peripheral Clock. */ +} flexcan_clock_source_t; + +/*! @brief FlexCAN Rx Fifo Filter type. */ +typedef enum _flexcan_rx_fifo_filter_type +{ + kFLEXCAN_RxFifoFilterTypeA = 0x0U, /*!< One full ID (standard and extended) per ID Filter element. */ + kFLEXCAN_RxFifoFilterTypeB = + 0x1U, /*!< Two full standard IDs or two partial 14-bit ID slices per ID Filter Table element. */ + kFLEXCAN_RxFifoFilterTypeC = + 0x2U, /*!< Four partial 8-bit Standard or extended ID slices per ID Filter Table element. */ + kFLEXCAN_RxFifoFilterTypeD = 0x3U, /*!< All frames rejected. */ +} flexcan_rx_fifo_filter_type_t; + +/*! + * @brief FlexCAN Rx FIFO priority + * + * The matching process starts from the Rx MB(or Rx FIFO) with higher priority. + * If no MB(or Rx FIFO filter) is satisfied, the matching process goes on with + * the Rx FIFO(or Rx MB) with lower priority. + */ +typedef enum _flexcan_rx_fifo_priority +{ + kFLEXCAN_RxFifoPrioLow = 0x0U, /*!< Matching process start from Rx Message Buffer first*/ + kFLEXCAN_RxFifoPrioHigh = 0x1U, /*!< Matching process start from Rx FIFO first*/ +} flexcan_rx_fifo_priority_t; + +/*! + * @brief FlexCAN interrupt configuration structure, default settings all disabled. + * + * This structure contains the settings for all of the FlexCAN Module interrupt configurations. + * Note: FlexCAN Message Buffers and Rx FIFO have their own interrupts. + */ +enum _flexcan_interrupt_enable +{ + kFLEXCAN_BusOffInterruptEnable = CAN_CTRL1_BOFFMSK_MASK, /*!< Bus Off interrupt. */ + kFLEXCAN_ErrorInterruptEnable = CAN_CTRL1_ERRMSK_MASK, /*!< Error interrupt. */ + kFLEXCAN_RxWarningInterruptEnable = CAN_CTRL1_RWRNMSK_MASK, /*!< Rx Warning interrupt. */ + kFLEXCAN_TxWarningInterruptEnable = CAN_CTRL1_TWRNMSK_MASK, /*!< Tx Warning interrupt. */ + kFLEXCAN_WakeUpInterruptEnable = CAN_MCR_WAKMSK_MASK, /*!< Wake Up interrupt. */ +}; + +/*! + * @brief FlexCAN status flags. + * + * This provides constants for the FlexCAN status flags for use in the FlexCAN functions. + * Note: The CPU read action clears FlEXCAN_ErrorFlag, therefore user need to + * read FlEXCAN_ErrorFlag and distinguish which error is occur using + * @ref _flexcan_error_flags enumerations. + */ +enum _flexcan_flags +{ + kFLEXCAN_SynchFlag = CAN_ESR1_SYNCH_MASK, /*!< CAN Synchronization Status. */ + kFLEXCAN_TxWarningIntFlag = CAN_ESR1_TWRNINT_MASK, /*!< Tx Warning Interrupt Flag. */ + kFLEXCAN_RxWarningIntFlag = CAN_ESR1_RWRNINT_MASK, /*!< Rx Warning Interrupt Flag. */ + kFLEXCAN_TxErrorWarningFlag = CAN_ESR1_TXWRN_MASK, /*!< Tx Error Warning Status. */ + kFLEXCAN_RxErrorWarningFlag = CAN_ESR1_RXWRN_MASK, /*!< Rx Error Warning Status. */ + kFLEXCAN_IdleFlag = CAN_ESR1_IDLE_MASK, /*!< CAN IDLE Status Flag. */ + kFLEXCAN_FaultConfinementFlag = CAN_ESR1_FLTCONF_MASK, /*!< Fault Confinement State Flag. */ + kFLEXCAN_TransmittingFlag = CAN_ESR1_TX_MASK, /*!< FlexCAN In Transmission Status. */ + kFLEXCAN_ReceivingFlag = CAN_ESR1_RX_MASK, /*!< FlexCAN In Reception Status. */ + kFLEXCAN_BusOffIntFlag = CAN_ESR1_BOFFINT_MASK, /*!< Bus Off Interrupt Flag. */ + kFLEXCAN_ErrorIntFlag = CAN_ESR1_ERRINT_MASK, /*!< Error Interrupt Flag. */ + kFLEXCAN_WakeUpIntFlag = CAN_ESR1_WAKINT_MASK, /*!< Wake-Up Interrupt Flag. */ + kFLEXCAN_ErrorFlag = CAN_ESR1_BIT1ERR_MASK | /*!< All FlexCAN Error Status. */ + CAN_ESR1_BIT0ERR_MASK | + CAN_ESR1_ACKERR_MASK | CAN_ESR1_CRCERR_MASK | CAN_ESR1_FRMERR_MASK | CAN_ESR1_STFERR_MASK, +}; + +/*! + * @brief FlexCAN error status flags. + * + * The FlexCAN Error Status enumerations is used to report current error of the FlexCAN bus. + * This enumerations should be used with KFLEXCAN_ErrorFlag in @ref _flexcan_flags enumerations + * to ditermine which error is generated. + */ +enum _flexcan_error_flags +{ + kFLEXCAN_StuffingError = CAN_ESR1_STFERR_MASK, /*!< Stuffing Error. */ + kFLEXCAN_FormError = CAN_ESR1_FRMERR_MASK, /*!< Form Error. */ + kFLEXCAN_CrcError = CAN_ESR1_CRCERR_MASK, /*!< Cyclic Redundancy Check Error. */ + kFLEXCAN_AckError = CAN_ESR1_ACKERR_MASK, /*!< Received no ACK on transmission. */ + kFLEXCAN_Bit0Error = CAN_ESR1_BIT0ERR_MASK, /*!< Unable to send dominant bit. */ + kFLEXCAN_Bit1Error = CAN_ESR1_BIT1ERR_MASK, /*!< Unable to send recessive bit. */ +}; + +/*! + * @brief FlexCAN Rx FIFO status flags. + * + * The FlexCAN Rx FIFO Status enumerations are used to determine the status of the + * Rx FIFO. Because Rx FIFO occupy the MB0 ~ MB7 (Rx Fifo filter also occupies + * more Message Buffer space), Rx FIFO status flags are mapped to the corresponding + * Message Buffer status flags. + */ +enum _flexcan_rx_fifo_flags +{ + kFLEXCAN_RxFifoOverflowFlag = CAN_IFLAG1_BUF7I_MASK, /*!< Rx FIFO overflow flag. */ + kFLEXCAN_RxFifoWarningFlag = CAN_IFLAG1_BUF6I_MASK, /*!< Rx FIFO almost full flag. */ + kFLEXCAN_RxFifoFrameAvlFlag = CAN_IFLAG1_BUF5I_MASK, /*!< Frames available in Rx FIFO flag. */ +}; + +#if defined(__CC_ARM) +#pragma anon_unions +#endif +/*! @brief FlexCAN message frame structure. */ +typedef struct _flexcan_frame +{ + struct + { + uint32_t timestamp : 16; /*!< FlexCAN internal Free-Running Counter Time Stamp. */ + uint32_t length : 4; /*!< CAN frame payload length in bytes(Range: 0~8). */ + uint32_t type : 1; /*!< CAN Frame Type(DATA or REMOTE). */ + uint32_t format : 1; /*!< CAN Frame Identifier(STD or EXT format). */ + uint32_t reserve1 : 1; /*!< Reserved for placeholder. */ + uint32_t idhit : 9; /*!< CAN Rx FIFO filter hit id(This value is only used in Rx FIFO receive mode). */ + }; + struct + { + uint32_t id : 29; /*!< CAN Frame Identifier, should be set using FLEXCAN_ID_EXT() or FLEXCAN_ID_STD() macro. */ + uint32_t reserve2 : 3; /*!< Reserved for place holder. */ + }; + union + { + struct + { + uint32_t dataWord0; /*!< CAN Frame payload word0. */ + uint32_t dataWord1; /*!< CAN Frame payload word1. */ + }; + struct + { + uint8_t dataByte3; /*!< CAN Frame payload byte3. */ + uint8_t dataByte2; /*!< CAN Frame payload byte2. */ + uint8_t dataByte1; /*!< CAN Frame payload byte1. */ + uint8_t dataByte0; /*!< CAN Frame payload byte0. */ + uint8_t dataByte7; /*!< CAN Frame payload byte7. */ + uint8_t dataByte6; /*!< CAN Frame payload byte6. */ + uint8_t dataByte5; /*!< CAN Frame payload byte5. */ + uint8_t dataByte4; /*!< CAN Frame payload byte4. */ + }; + }; +} flexcan_frame_t; + +/*! @brief FlexCAN module configuration structure. */ +typedef struct _flexcan_config +{ + uint32_t baudRate; /*!< FlexCAN baud rate in bps. */ + flexcan_clock_source_t clkSrc; /*!< Clock source for FlexCAN Protocol Engine. */ + uint8_t maxMbNum; /*!< The maximum number of Message Buffers used by user. */ + bool enableLoopBack; /*!< Enable or Disable Loop Back Self Test Mode. */ + bool enableSelfWakeup; /*!< Enable or Disable Self Wakeup Mode. */ + bool enableIndividMask; /*!< Enable or Disable Rx Individual Mask. */ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) && FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT) + bool enableDoze; /*!< Enable or Disable Doze Mode. */ +#endif +} flexcan_config_t; + +/*! @brief FlexCAN protocol timing characteristic configuration structure. */ +typedef struct _flexcan_timing_config +{ + uint8_t preDivider; /*!< Clock Pre-scaler Division Factor. */ + uint8_t rJumpwidth; /*!< Re-sync Jump Width. */ + uint8_t phaseSeg1; /*!< Phase Segment 1. */ + uint8_t phaseSeg2; /*!< Phase Segment 2. */ + uint8_t propSeg; /*!< Propagation Segment. */ +} flexcan_timing_config_t; + +/*! + * @brief FlexCAN Receive Message Buffer configuration structure + * + * This structure is used as the parameter of FLEXCAN_SetRxMbConfig() function. + * The FLEXCAN_SetRxMbConfig() function is used to configure FlexCAN Receive + * Message Buffer. The function abort previous receiving process, clean the + * Message Buffer and activate the Rx Message Buffer using given Message Buffer + * setting. + */ +typedef struct _flexcan_rx_mb_config +{ + uint32_t id; /*!< CAN Message Buffer Frame Identifier, should be set using + FLEXCAN_ID_EXT() or FLEXCAN_ID_STD() macro. */ + flexcan_frame_format_t format; /*!< CAN Frame Identifier format(Standard of Extend). */ + flexcan_frame_type_t type; /*!< CAN Frame Type(Data or Remote). */ +} flexcan_rx_mb_config_t; + +/*! @brief FlexCAN Rx FIFO configure structure. */ +typedef struct _flexcan_rx_fifo_config +{ + uint32_t *idFilterTable; /*!< Pointer to FlexCAN Rx FIFO identifier filter table. */ + uint8_t idFilterNum; /*!< The quantity of filter elements. */ + flexcan_rx_fifo_filter_type_t idFilterType; /*!< The FlexCAN Rx FIFO Filter type. */ + flexcan_rx_fifo_priority_t priority; /*!< The FlexCAN Rx FIFO receive priority. */ +} flexcan_rx_fifo_config_t; + +/*! @brief FlexCAN Message Buffer transfer. */ +typedef struct _flexcan_mb_transfer +{ + flexcan_frame_t *frame; /*!< The buffer of CAN Message to be transfer. */ + uint8_t mbIdx; /*!< The index of Message buffer used to transfer Message. */ +} flexcan_mb_transfer_t; + +/*! @brief FlexCAN Rx FIFO transfer. */ +typedef struct _flexcan_fifo_transfer +{ + flexcan_frame_t *frame; /*!< The buffer of CAN Message to be received from Rx FIFO. */ +} flexcan_fifo_transfer_t; + +/*! @brief FlexCAN handle structure definition. */ +typedef struct _flexcan_handle flexcan_handle_t; + +/*! @brief FlexCAN transfer callback function. + * + * The FlexCAN transfer callback returns a value from the underlying layer. + * If the status equals to kStatus_FLEXCAN_ErrorStatus, the result parameter is the Content of + * FlexCAN status register which can be used to get the working status(or error status) of FlexCAN module. + * If the status equals to other FlexCAN Message Buffer transfer status, the result is the index of + * Message Buffer that generate transfer event. + * If the status equals to other FlexCAN Message Buffer transfer status, the result is meaningless and should be + * Ignored. + */ +typedef void (*flexcan_transfer_callback_t)( + CAN_Type *base, flexcan_handle_t *handle, status_t status, uint32_t result, void *userData); + +/*! @brief FlexCAN handle structure. */ +struct _flexcan_handle +{ + flexcan_transfer_callback_t callback; /*!< Callback function. */ + void *userData; /*!< FlexCAN callback function parameter.*/ + flexcan_frame_t *volatile mbFrameBuf[CAN_WORD1_COUNT]; + /*!< The buffer for received data from Message Buffers. */ + flexcan_frame_t *volatile rxFifoFrameBuf; /*!< The buffer for received data from Rx FIFO. */ + volatile uint8_t mbState[CAN_WORD1_COUNT]; /*!< Message Buffer transfer state. */ + volatile uint8_t rxFifoState; /*!< Rx FIFO transfer state. */ +}; + +/****************************************************************************** + * API + *****************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name Initialization and deinitialization + * @{ + */ + +/*! + * @brief Initializes a FlexCAN instance. + * + * This function initializes the FlexCAN module with user-defined settings. + * This example shows how to set up the flexcan_config_t parameters and how + * to call the FLEXCAN_Init function by passing in these parameters: + * @code + * flexcan_config_t flexcanConfig; + * flexcanConfig.clkSrc = KFLEXCAN_ClkSrcOsc; + * flexcanConfig.baudRate = 125000U; + * flexcanConfig.maxMbNum = 16; + * flexcanConfig.enableLoopBack = false; + * flexcanConfig.enableSelfWakeup = false; + * flexcanConfig.enableIndividMask = false; + * flexcanConfig.enableDoze = false; + * FLEXCAN_Init(CAN0, &flexcanConfig, 8000000UL); + * @endcode + * + * @param base FlexCAN peripheral base address. + * @param config Pointer to user-defined configuration structure. + * @param sourceClock_Hz FlexCAN Protocol Engine clock source frequency in Hz. + */ +void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz); + +/*! + * @brief De-initializes a FlexCAN instance. + * + * This function disable the FlexCAN module clock and set all register value + * to reset value. + * + * @param base FlexCAN peripheral base address. + */ +void FLEXCAN_Deinit(CAN_Type *base); + +/*! + * @brief Get the default configuration structure. + * + * This function initializes the FlexCAN configure structure to default value. The default + * value are: + * flexcanConfig->clkSrc = KFLEXCAN_ClkSrcOsc; + * flexcanConfig->baudRate = 125000U; + * flexcanConfig->maxMbNum = 16; + * flexcanConfig->enableLoopBack = false; + * flexcanConfig->enableSelfWakeup = false; + * flexcanConfig->enableIndividMask = false; + * flexcanConfig->enableDoze = false; + * + * @param config Pointer to FlexCAN configuration structure. + */ +void FLEXCAN_GetDefaultConfig(flexcan_config_t *config); + +/* @} */ + +/*! + * @name Configuration. + * @{ + */ + +/*! + * @brief Sets the FlexCAN protocol timing characteristic. + * + * This function gives user settings to CAN bus timing characteristic. + * The function is for an experienced user. For less experienced users, call + * the FLEXCAN_Init() and fill the baud rate field with a desired value. + * This provides the default timing characteristics to the module. + * + * Note that calling FLEXCAN_SetTimingConfig() overrides the baud rate set + * in FLEXCAN_Init(). + * + * @param base FlexCAN peripheral base address. + * @param config Pointer to the timing configuration structure. + */ +void FLEXCAN_SetTimingConfig(CAN_Type *base, const flexcan_timing_config_t *config); + +/*! + * @brief Sets the FlexCAN receive message buffer global mask. + * + * This function sets the global mask for FlexCAN message buffer in a matching process. + * The configuration is only effective when the Rx individual mask is disabled in the FLEXCAN_Init(). + * + * @param base FlexCAN peripheral base address. + * @param mask Rx Message Buffer Global Mask value. + */ +void FlEXCAN_SetRxMbGlobalMask(CAN_Type *base, uint32_t mask); + +/*! + * @brief Sets the FlexCAN receive FIFO global mask. + * + * This function sets the global mask for FlexCAN FIFO in a matching process. + * + * @param base FlexCAN peripheral base address. + * @param mask Rx Fifo Global Mask value. + */ +void FlEXCAN_SetRxFifoGlobalMask(CAN_Type *base, uint32_t mask); + +/*! + * @brief Sets the FlexCAN receive individual mask. + * + * This function sets the individual mask for FlexCAN matching process. + * The configuration is only effective when the Rx individual mask is enabled in FLEXCAN_Init(). + * If Rx FIFO is disabled, the individual mask is applied to the corresponding Message Buffer. + * If Rx FIFO is enabled, the individual mask for Rx FIFO occupied Message Buffer is applied to + * the Rx Filter with same index. What calls for special attention is that only the first 32 + * individual masks can be used as Rx FIFO filter mask. + * + * @param base FlexCAN peripheral base address. + * @param maskIdx The Index of individual Mask. + * @param mask Rx Individual Mask value. + */ +void FlEXCAN_SetRxIndividualMask(CAN_Type *base, uint8_t maskIdx, uint32_t mask); + +/*! + * @brief Configures a FlexCAN transmit message buffer. + * + * This function aborts the previous transmission, cleans the Message Buffer, and + * configures it as a Transmit Message Buffer. + * + * @param base FlexCAN peripheral base address. + * @param mbIdx The Message Buffer index. + * @param enable Enable/Disable Tx Message Buffer. + * - true: Enable Tx Message Buffer. + * - false: Disable Tx Message Buffer. + */ +void FLEXCAN_SetTxMbConfig(CAN_Type *base, uint8_t mbIdx, bool enable); + +/*! + * @brief Configures a FlexCAN Receive Message Buffer. + * + * This function cleans a FlexCAN build-in Message Buffer and configures it + * as a Receive Message Buffer. + * + * @param base FlexCAN peripheral base address. + * @param mbIdx The Message Buffer index. + * @param config Pointer to FlexCAN Message Buffer configuration structure. + * @param enable Enable/Disable Rx Message Buffer. + * - true: Enable Rx Message Buffer. + * - false: Disable Rx Message Buffer. + */ +void FLEXCAN_SetRxMbConfig(CAN_Type *base, uint8_t mbIdx, const flexcan_rx_mb_config_t *config, bool enable); + +/*! + * @brief Configures the FlexCAN Rx FIFO. + * + * This function configures the Rx FIFO with given Rx FIFO configuration. + * + * @param base FlexCAN peripheral base address. + * @param config Pointer to FlexCAN Rx FIFO configuration structure. + * @param enable Enable/Disable Rx FIFO. + * - true: Enable Rx FIFO. + * - false: Disable Rx FIFO. + */ +void FlEXCAN_SetRxFifoConfig(CAN_Type *base, const flexcan_rx_fifo_config_t *config, bool enable); + +/* @} */ + +/*! + * @name Status + * @{ + */ + +/*! + * @brief Gets the FlexCAN module interrupt flags. + * + * This function gets all FlexCAN status flags. The flags are returned as the logical + * OR value of the enumerators @ref _flexcan_flags. To check the specific status, + * compare the return value with enumerators in @ref _flexcan_flags. + * + * @param base FlexCAN peripheral base address. + * @return FlexCAN status flags which are ORed by the enumerators in the _flexcan_flags. + */ +static inline uint32_t FLEXCAN_GetStatusFlags(CAN_Type *base) +{ + return base->ESR1; +} + +/*! + * @brief Clears status flags with the provided mask. + * + * This function clears the FlexCAN status flags with a provided mask. An automatically cleared flag + * can't be cleared by this function. + * + * @param base FlexCAN peripheral base address. + * @param mask The status flags to be cleared, it is logical OR value of @ref _flexcan_flags. + */ +static inline void FLEXCAN_ClearStatusFlags(CAN_Type *base, uint32_t mask) +{ + /* Write 1 to clear status flag. */ + base->ESR1 = mask; +} + +/*! + * @brief Gets the FlexCAN Bus Error Counter value. + * + * This function gets the FlexCAN Bus Error Counter value for both Tx and + * Rx direction. These values may be needed in the upper layer error handling. + * + * @param base FlexCAN peripheral base address. + * @param txErrBuf Buffer to store Tx Error Counter value. + * @param rxErrBuf Buffer to store Rx Error Counter value. + */ +static inline void FlEXCAN_GetBusErrCount(CAN_Type *base, uint8_t *txErrBuf, uint8_t *rxErrBuf) +{ + if (txErrBuf) + { + *txErrBuf = (uint8_t)((base->ECR & CAN_ECR_TXERRCNT_MASK) >> CAN_ECR_TXERRCNT_SHIFT); + } + + if (rxErrBuf) + { + *rxErrBuf = (uint8_t)((base->ECR & CAN_ECR_RXERRCNT_MASK) >> CAN_ECR_RXERRCNT_SHIFT); + } +} + +/*! + * @brief Gets the FlexCAN Message Buffer interrupt flags. + * + * This function gets the interrupt flags of a given Message Buffers. + * + * @param base FlexCAN peripheral base address. + * @param mask The ORed FlexCAN Message Buffer mask. + * @return The status of given Message Buffers. + */ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) +static inline uint64_t FLEXCAN_GetMbStatusFlags(CAN_Type *base, uint64_t mask) +#else +static inline uint32_t FLEXCAN_GetMbStatusFlags(CAN_Type *base, uint32_t mask) +#endif +{ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) + return ((((uint64_t)base->IFLAG1) & mask) | ((((uint64_t)base->IFLAG2) << 32) & mask)); +#else + return (base->IFLAG1 & mask); +#endif +} + +/*! + * @brief Clears the FlexCAN Message Buffer interrupt flags. + * + * This function clears the interrupt flags of a given Message Buffers. + * + * @param base FlexCAN peripheral base address. + * @param mask The ORed FlexCAN Message Buffer mask. + */ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) +static inline void FLEXCAN_ClearMbStatusFlags(CAN_Type *base, uint64_t mask) +#else +static inline void FLEXCAN_ClearMbStatusFlags(CAN_Type *base, uint32_t mask) +#endif +{ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) + base->IFLAG1 = (uint32_t)(mask & 0xFFFFFFFF); + base->IFLAG2 = (uint32_t)(mask >> 32); +#else + base->IFLAG1 = mask; +#endif +} + +/* @} */ + +/*! + * @name Interrupts + * @{ + */ + +/*! + * @brief Enables FlexCAN interrupts according to provided mask. + * + * This function enables the FlexCAN interrupts according to provided mask. The mask + * is a logical OR of enumeration members, see @ref _flexcan_interrupt_enable. + * + * @param base FlexCAN peripheral base address. + * @param mask The interrupts to enable. Logical OR of @ref _flexcan_interrupt_enable. + */ +static inline void FLEXCAN_EnableInterrupts(CAN_Type *base, uint32_t mask) +{ + /* Solve Wake Up Interrupt. */ + if (mask & kFLEXCAN_WakeUpInterruptEnable) + { + base->MCR |= CAN_MCR_WAKMSK_MASK; + } + + /* Solve others. */ + base->CTRL1 |= (mask & (~((uint32_t)kFLEXCAN_WakeUpInterruptEnable))); +} + +/*! + * @brief Disables FlexCAN interrupts according to provided mask. + * + * This function disables the FlexCAN interrupts according to provided mask. The mask + * is a logical OR of enumeration members, see @ref _flexcan_interrupt_enable. + * + * @param base FlexCAN peripheral base address. + * @param mask The interrupts to disable. Logical OR of @ref _flexcan_interrupt_enable. + */ +static inline void FLEXCAN_DisableInterrupts(CAN_Type *base, uint32_t mask) +{ + /* Solve Wake Up Interrupt. */ + if (mask & kFLEXCAN_WakeUpInterruptEnable) + { + base->MCR &= ~CAN_MCR_WAKMSK_MASK; + } + + /* Solve others. */ + base->CTRL1 &= ~(mask & (~((uint32_t)kFLEXCAN_WakeUpInterruptEnable))); +} + +/*! + * @brief Enables FlexCAN Message Buffer interrupts. + * + * This function enables the interrupts of given Message Buffers + * + * @param base FlexCAN peripheral base address. + * @param mask The ORed FlexCAN Message Buffer mask. + */ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) +static inline void FLEXCAN_EnableMbInterrupts(CAN_Type *base, uint64_t mask) +#else +static inline void FLEXCAN_EnableMbInterrupts(CAN_Type *base, uint32_t mask) +#endif +{ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) + base->IMASK1 |= (uint32_t)(mask & 0xFFFFFFFF); + base->IMASK2 |= (uint32_t)(mask >> 32); +#else + base->IMASK1 |= mask; +#endif +} + +/*! + * @brief Disables FlexCAN Message Buffer interrupts. + * + * This function disables the interrupts of given Message Buffers + * + * @param base FlexCAN peripheral base address. + * @param mask The ORed FlexCAN Message Buffer mask. + */ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) +static inline void FLEXCAN_DisableMbInterrupts(CAN_Type *base, uint64_t mask) +#else +static inline void FLEXCAN_DisableMbInterrupts(CAN_Type *base, uint32_t mask) +#endif +{ +#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) + base->IMASK1 &= ~((uint32_t)(mask & 0xFFFFFFFF)); + base->IMASK2 &= ~((uint32_t)(mask >> 32)); +#else + base->IMASK1 &= ~mask; +#endif +} + +/* @} */ + +#if (defined(FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA) && FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA) +/*! + * @name DMA Control + * @{ + */ + +/*! + * @brief Enables or disables the FlexCAN Rx FIFO DMA request. + * + * This function enables or disables the DMA feature of FlexCAN build-in Rx FIFO. + * + * @param base FlexCAN peripheral base address. + * @param enable true to enable, false to disable. + */ +void FLEXCAN_EnableRxFifoDMA(CAN_Type *base, bool enable); + +/*! + * @brief Gets the Rx FIFO Head address. + * + * This function returns the FlexCAN Rx FIFO Head address, which is mainly used for the DMA/eDMA use case. + * + * @param base FlexCAN peripheral base address. + * @return FlexCAN Rx FIFO Head address. + */ +static inline uint32_t FLEXCAN_GetRxFifoHeadAddr(CAN_Type *base) +{ + return (uint32_t) & (base->MB[0].CS); +} + +/* @} */ +#endif /* FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA */ + +/*! + * @name Bus Operations + * @{ + */ + +/*! + * @brief Enables or disables the FlexCAN module operation. + * + * This function enables or disables the FlexCAN module. + * + * @param base FlexCAN base pointer. + * @param enable true to enable, false to disable. + */ +static inline void FLEXCAN_Enable(CAN_Type *base, bool enable) +{ + if (enable) + { + base->MCR &= ~CAN_MCR_MDIS_MASK; + + /* Wait FlexCAN exit from low-power mode. */ + while (base->MCR & CAN_MCR_LPMACK_MASK) + { + } + } + else + { + base->MCR |= CAN_MCR_MDIS_MASK; + + /* Wait FlexCAN enter low-power mode. */ + while (!(base->MCR & CAN_MCR_LPMACK_MASK)) + { + } + } +} + +/*! + * @brief Writes a FlexCAN Message to Transmit Message Buffer. + * + * This function writes a CAN Message to the specified Transmit Message Buffer + * and changes the Message Buffer state to start CAN Message transmit. After + * that the function returns immediately. + * + * @param base FlexCAN peripheral base address. + * @param mbIdx The FlexCAN Message Buffer index. + * @param txFrame Pointer to CAN message frame to be sent. + * @retval kStatus_Success - Write Tx Message Buffer Successfully. + * @retval kStatus_Fail - Tx Message Buffer is currently in use. + */ +status_t FLEXCAN_WriteTxMb(CAN_Type *base, uint8_t mbIdx, const flexcan_frame_t *txFrame); + +/*! + * @brief Reads a FlexCAN Message from Receive Message Buffer. + * + * This function reads a CAN message from a specified Receive Message Buffer. + * The function fills a receive CAN message frame structure with + * just received data and activates the Message Buffer again. + * The function returns immediately. + * + * @param base FlexCAN peripheral base address. + * @param mbIdx The FlexCAN Message Buffer index. + * @param rxFrame Pointer to CAN message frame structure for reception. + * @retval kStatus_Success - Rx Message Buffer is full and has been read successfully. + * @retval kStatus_FLEXCAN_RxOverflow - Rx Message Buffer is already overflowed and has been read successfully. + * @retval kStatus_Fail - Rx Message Buffer is empty. + */ +status_t FLEXCAN_ReadRxMb(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *rxFrame); + +/*! + * @brief Reads a FlexCAN Message from Rx FIFO. + * + * This function reads a CAN message from the FlexCAN build-in Rx FIFO. + * + * @param base FlexCAN peripheral base address. + * @param rxFrame Pointer to CAN message frame structure for reception. + * @retval kStatus_Success - Read Message from Rx FIFO successfully. + * @retval kStatus_Fail - Rx FIFO is not enabled. + */ +status_t FlEXCAN_ReadRxFifo(CAN_Type *base, flexcan_frame_t *rxFrame); + +/* @} */ + +/*! + * @name Transactional + * @{ + */ + +/*! + * @brief Performs a polling send transaction on the CAN bus. + * + * Note that a transfer handle does not need to be created before calling this API. + * + * @param base FlexCAN peripheral base pointer. + * @param mbIdx The FlexCAN Message Buffer index. + * @param txFrame Pointer to CAN message frame to be sent. + * @retval kStatus_Success - Write Tx Message Buffer Successfully. + * @retval kStatus_Fail - Tx Message Buffer is currently in use. + */ +status_t FlEXCAN_TransferSendBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *txFrame); + +/*! + * @brief Performs a polling receive transaction on the CAN bus. + * + * Note that a transfer handle does not need to be created before calling this API. + * + * @param base FlexCAN peripheral base pointer. + * @param mbIdx The FlexCAN Message Buffer index. + * @param rxFrame Pointer to CAN message frame structure for reception. + * @retval kStatus_Success - Rx Message Buffer is full and has been read successfully. + * @retval kStatus_FLEXCAN_RxOverflow - Rx Message Buffer is already overflowed and has been read successfully. + * @retval kStatus_Fail - Rx Message Buffer is empty. + */ +status_t FlEXCAN_TransferReceiveBlocking(CAN_Type *base, uint8_t mbIdx, flexcan_frame_t *rxFrame); + +/*! + * @brief Performs a polling receive transaction from Rx FIFO on the CAN bus. + * + * Note that a transfer handle does not need to be created before calling this API. + * + * @param base FlexCAN peripheral base pointer. + * @param rxFrame Pointer to CAN message frame structure for reception. + * @retval kStatus_Success - Read Message from Rx FIFO successfully. + * @retval kStatus_Fail - Rx FIFO is not enabled. + */ +status_t FlEXCAN_TransferReceiveFifoBlocking(CAN_Type *base, flexcan_frame_t *rxFrame); + +/*! + * @brief Initializes the FlexCAN handle. + * + * This function initializes the FlexCAN handle which can be used for other FlexCAN + * transactional APIs. Usually, for a specified FlexCAN instance, + * call this API once to get the initialized handle. + * + * @param base FlexCAN peripheral base address. + * @param handle FlexCAN handle pointer. + * @param callback The callback function. + * @param userData The parameter of the callback function. + */ +void FLEXCAN_TransferCreateHandle(CAN_Type *base, + flexcan_handle_t *handle, + flexcan_transfer_callback_t callback, + void *userData); + +/*! + * @brief Sends a message using IRQ. + * + * This function sends a message using IRQ. This is a non-blocking function, which returns + * right away. When messages have been sent out, the send callback function is called. + * + * @param base FlexCAN peripheral base address. + * @param handle FlexCAN handle pointer. + * @param xfer FlexCAN Message Buffer transfer structure. See the #flexcan_mb_transfer_t. + * @retval kStatus_Success Start Tx Message Buffer sending process successfully. + * @retval kStatus_Fail Write Tx Message Buffer failed. + * @retval kStatus_FLEXCAN_TxBusy Tx Message Buffer is in use. + */ +status_t FLEXCAN_TransferSendNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *xfer); + +/*! + * @brief Receives a message using IRQ. + * + * This function receives a message using IRQ. This is non-blocking function, which returns + * right away. When the message has been received, the receive callback function is called. + * + * @param base FlexCAN peripheral base address. + * @param handle FlexCAN handle pointer. + * @param xfer FlexCAN Message Buffer transfer structure. See the #flexcan_mb_transfer_t. + * @retval kStatus_Success - Start Rx Message Buffer receiving process successfully. + * @retval kStatus_FLEXCAN_RxBusy - Rx Message Buffer is in use. + */ +status_t FLEXCAN_TransferReceiveNonBlocking(CAN_Type *base, flexcan_handle_t *handle, flexcan_mb_transfer_t *xfer); + +/*! + * @brief Receives a message from Rx FIFO using IRQ. + * + * This function receives a message using IRQ. This is a non-blocking function, which returns + * right away. When all messages have been received, the receive callback function is called. + * + * @param base FlexCAN peripheral base address. + * @param handle FlexCAN handle pointer. + * @param xfer FlexCAN Rx FIFO transfer structure. See the @ref flexcan_fifo_transfer_t. + * @retval kStatus_Success - Start Rx FIFO receiving process successfully. + * @retval kStatus_FLEXCAN_RxFifoBusy - Rx FIFO is currently in use. + */ +status_t FLEXCAN_TransferReceiveFifoNonBlocking(CAN_Type *base, + flexcan_handle_t *handle, + flexcan_fifo_transfer_t *xfer); + +/*! + * @brief Aborts the interrupt driven message send process. + * + * This function aborts the interrupt driven message send process. + * + * @param base FlexCAN peripheral base address. + * @param handle FlexCAN handle pointer. + * @param mbIdx The FlexCAN Message Buffer index. + */ +void FLEXCAN_TransferAbortSend(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx); + +/*! + * @brief Aborts the interrupt driven message receive process. + * + * This function aborts the interrupt driven message receive process. + * + * @param base FlexCAN peripheral base address. + * @param handle FlexCAN handle pointer. + * @param mbIdx The FlexCAN Message Buffer index. + */ +void FLEXCAN_TransferAbortReceive(CAN_Type *base, flexcan_handle_t *handle, uint8_t mbIdx); + +/*! + * @brief Aborts the interrupt driven message receive from Rx FIFO process. + * + * This function aborts the interrupt driven message receive from Rx FIFO process. + * + * @param base FlexCAN peripheral base address. + * @param handle FlexCAN handle pointer. + */ +void FLEXCAN_TransferAbortReceiveFifo(CAN_Type *base, flexcan_handle_t *handle); + +/*! + * @brief FlexCAN IRQ handle function. + * + * This function handles the FlexCAN Error, the Message Buffer, and the Rx FIFO IRQ request. + * + * @param base FlexCAN peripheral base address. + * @param handle FlexCAN handle pointer. + */ +void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* _FSL_FLEXCAN_H_ */