| /* |
| * 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 "flexcan.h" |
| |
| /******************************************************************************* |
| * Definitions |
| ******************************************************************************/ |
| |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT (31U) /*! format A&B RTR mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT (30U) /*! format A&B IDE mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_RTR_SHIFT (15U) /*! format B RTR-2 mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_IDE_SHIFT (14U) /*! format B IDE-2 mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_MASK (0x3FFFFFFFU) /*! format A extended mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_SHIFT (1U) /*! format A extended shift.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_MASK (0x3FF80000U) /*! format A standard mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_SHIFT (19U) /*! format A standard shift.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK (0x3FFFU) /*! format B extended mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT1 (16U) /*! format B extended mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT2 (0U) /*! format B extended mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK (0x7FFU) /*! format B standard mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT1 (19U) /*! format B standard shift1.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT2 (3U) /*! format B standard shift2.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_MASK (0xFFU) /*! format C mask.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT1 (24U) /*! format C shift1.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT2 (16U) /*! format C shift2.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT3 (8U) /*! format C shift3.*/ |
| #define FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT4 (0U) /*! format C shift4.*/ |
| #define FLEXCAN_BYTE_DATA_FIELD_MASK (0xFFU) /*! masks for byte data field.*/ |
| #define RxFifoFilterElementNum(x) ((x + 1) * 8) |
| |
| /******************************************************************************* |
| * Code |
| ******************************************************************************/ |
| |
| /******************************************************************************* |
| * FLEXCAN Freeze control function |
| ******************************************************************************/ |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_EnterFreezeMode |
| * Description : Set FlexCAN module enter freeze mode. |
| * |
| *END**************************************************************************/ |
| static void FLEXCAN_EnterFreezeMode(CAN_Type* base) |
| { |
| /* Set Freeze, Halt */ |
| CAN_MCR_REG(base) |= CAN_MCR_FRZ_MASK; |
| CAN_MCR_REG(base) |= CAN_MCR_HALT_MASK; |
| /* Wait for entering the freeze mode */ |
| while (!(CAN_MCR_REG(base) & CAN_MCR_FRZ_ACK_MASK)); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_ExitFreezeMode |
| * Description : Set FlexCAN module exit freeze mode. |
| * |
| *END**************************************************************************/ |
| static void FLEXCAN_ExitFreezeMode(CAN_Type* base) |
| { |
| /* De-assert Freeze Mode */ |
| CAN_MCR_REG(base) &= ~CAN_MCR_HALT_MASK; |
| CAN_MCR_REG(base) &= ~CAN_MCR_FRZ_MASK; |
| /* Wait for exit the freeze mode */ |
| while (CAN_MCR_REG(base) & CAN_MCR_FRZ_ACK_MASK); |
| } |
| |
| /******************************************************************************* |
| * FlexCAN Initialization and Configuration functions |
| ******************************************************************************/ |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_Init |
| * Description : Initialize Flexcan module with given initialize structure. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_Init(CAN_Type* base, const flexcan_init_config_t* initConfig) |
| { |
| assert(initConfig); |
| |
| /* Enable Flexcan module */ |
| FLEXCAN_Enable(base); |
| |
| /* Reset Flexcan module register content to default value */ |
| FLEXCAN_Deinit(base); |
| |
| /* Set maximum MessageBox numbers and |
| * Initialize all message buffers as inactive |
| */ |
| FLEXCAN_SetMaxMsgBufNum(base, initConfig->maxMsgBufNum); |
| |
| /* Initialize Flexcan module timing character */ |
| FLEXCAN_SetTiming(base, &initConfig->timing); |
| |
| /* Set desired operating mode */ |
| FLEXCAN_SetOperatingMode(base, initConfig->operatingMode); |
| |
| /* Disable Flexcan module */ |
| FLEXCAN_Disable(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_Deinit |
| * Description : This function reset Flexcan module register content to its |
| * default value. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_Deinit(CAN_Type* base) |
| { |
| uint32_t i; |
| |
| /* Reset the FLEXCAN module */ |
| CAN_MCR_REG(base) |= CAN_MCR_SOFT_RST_MASK; |
| /* Wait for reset cycle to complete */ |
| while (CAN_MCR_REG(base) & CAN_MCR_SOFT_RST_MASK); |
| |
| /* Assert Flexcan module Freeze */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* Reset CTRL1 Register */ |
| CAN_CTRL1_REG(base) = 0x0; |
| |
| /* Reset CTRL2 Register */ |
| CAN_CTRL2_REG(base) = 0x0; |
| |
| /* Reset All Message Buffer Content */ |
| for (i = 0; i < CAN_CS_COUNT; i++) |
| { |
| base->MB[i].CS = 0x0; |
| base->MB[i].ID = 0x0; |
| base->MB[i].WORD0 = 0x0; |
| base->MB[i].WORD1 = 0x0; |
| } |
| |
| /* Reset Rx Individual Mask */ |
| for (i = 0; i < CAN_RXIMR_COUNT; i++) |
| CAN_RXIMR_REG(base, i) = 0x0; |
| |
| /* Reset Rx Mailboxes Global Mask */ |
| CAN_RXMGMASK_REG(base) = 0xFFFFFFFF; |
| |
| /* Reset Rx Buffer 14 Mask */ |
| CAN_RX14MASK_REG(base) = 0xFFFFFFFF; |
| |
| /* Reset Rx Buffer 15 Mask */ |
| CAN_RX15MASK_REG(base) = 0xFFFFFFFF; |
| |
| /* Rx FIFO Global Mask */ |
| CAN_RXFGMASK_REG(base) = 0xFFFFFFFF; |
| |
| /* Disable all MB interrupts */ |
| CAN_IMASK1_REG(base) = 0x0; |
| CAN_IMASK2_REG(base) = 0x0; |
| |
| // Clear all MB interrupt flags |
| CAN_IFLAG1_REG(base) = 0xFFFFFFFF; |
| CAN_IFLAG2_REG(base) = 0xFFFFFFFF; |
| |
| // Clear all Error interrupt flags |
| CAN_ESR1_REG(base) = 0xFFFFFFFF; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_Enable |
| * Description : This function is used to Enable the Flexcan Module. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_Enable(CAN_Type* base) |
| { |
| /* Enable clock */ |
| CAN_MCR_REG(base) &= ~CAN_MCR_MDIS_MASK; |
| /* Wait until enabled */ |
| while (CAN_MCR_REG(base) & CAN_MCR_LPM_ACK_MASK); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_Disable |
| * Description : This function is used to Disable the CAN Module. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_Disable(CAN_Type* base) |
| { |
| /* Disable clock*/ |
| CAN_MCR_REG(base) |= CAN_MCR_MDIS_MASK; |
| /* Wait until disabled */ |
| while (!(CAN_MCR_REG(base) & CAN_MCR_LPM_ACK_MASK)); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetTiming |
| * Description : Sets the FlexCAN time segments for setting up bit rate. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetTiming(CAN_Type* base, const flexcan_timing_t* timing) |
| { |
| assert(timing); |
| |
| /* Assert Flexcan module Freeze */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* Set Flexcan module Timing Character */ |
| CAN_CTRL1_REG(base) &= ~(CAN_CTRL1_PRESDIV_MASK | \ |
| CAN_CTRL1_RJW_MASK | \ |
| CAN_CTRL1_PSEG1_MASK | \ |
| CAN_CTRL1_PSEG2_MASK | \ |
| CAN_CTRL1_PROP_SEG_MASK); |
| CAN_CTRL1_REG(base) |= (CAN_CTRL1_PRESDIV(timing->preDiv) | \ |
| CAN_CTRL1_RJW(timing->rJumpwidth) | \ |
| CAN_CTRL1_PSEG1(timing->phaseSeg1) | \ |
| CAN_CTRL1_PSEG2(timing->phaseSeg2) | \ |
| CAN_CTRL1_PROP_SEG(timing->propSeg)); |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetOperatingMode |
| * Description : Set operation mode. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetOperatingMode(CAN_Type* base, uint8_t mode) |
| { |
| assert((mode & flexcanNormalMode) || |
| (mode & flexcanListenOnlyMode) || |
| (mode & flexcanLoopBackMode)); |
| |
| /* Assert Freeze mode*/ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (mode & flexcanNormalMode) |
| CAN_MCR_REG(base) &= ~CAN_MCR_SUPV_MASK; |
| else |
| CAN_MCR_REG(base) |= CAN_MCR_SUPV_MASK; |
| |
| if (mode & flexcanListenOnlyMode) |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_LOM_MASK; |
| else |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_LOM_MASK; |
| |
| if (mode & flexcanLoopBackMode) |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_LPB_MASK; |
| else |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_LPB_MASK; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetMaxMsgBufNum |
| * Description : Set the maximum number of Message Buffers. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetMaxMsgBufNum(CAN_Type* base, uint32_t bufNum) |
| { |
| assert((bufNum <= CAN_CS_COUNT) && (bufNum > 0)); |
| |
| /* Assert Freeze mode*/ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* Set the maximum number of MBs*/ |
| CAN_MCR_REG(base) = (CAN_MCR_REG(base) & (~CAN_MCR_MAXMB_MASK)) | CAN_MCR_MAXMB(bufNum-1); |
| |
| /* De-assert Freeze Mode*/ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetAbortCmd |
| * Description : Set the Transmit abort feature enablement. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetAbortCmd(CAN_Type* base, bool enable) |
| { |
| /* Assert Freeze mode*/ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (enable) |
| CAN_MCR_REG(base) |= CAN_MCR_AEN_MASK; |
| else |
| CAN_MCR_REG(base) &= ~CAN_MCR_AEN_MASK; |
| |
| /* De-assert Freeze Mode*/ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetLocalPrioCmd |
| * Description : Set the local transmit priority enablement. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetLocalPrioCmd(CAN_Type* base, bool enable) |
| { |
| /* Assert Freeze mode*/ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (enable) |
| { |
| CAN_MCR_REG(base) |= CAN_MCR_LPRIO_EN_MASK; |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_LBUF_MASK; |
| } |
| else |
| { |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_LBUF_MASK; |
| CAN_MCR_REG(base) &= ~CAN_MCR_LPRIO_EN_MASK; |
| } |
| |
| /* De-assert Freeze Mode*/ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetMatchPrioCmd |
| * Description : Set the Rx matching process priority. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetMatchPrioCmd(CAN_Type* base, bool priority) |
| { |
| /* Assert Freeze mode*/ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (priority) |
| CAN_CTRL2_REG(base) |= CAN_CTRL2_MRP_MASK; |
| else |
| CAN_CTRL2_REG(base) &= ~CAN_CTRL2_MRP_MASK; |
| |
| /* De-assert Freeze Mode*/ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /******************************************************************************* |
| * FlexCAN Message buffer control functions |
| ******************************************************************************/ |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_GetMsgBufPtr |
| * Description : Get message buffer pointer for transition. |
| * |
| *END**************************************************************************/ |
| flexcan_msgbuf_t* FLEXCAN_GetMsgBufPtr(CAN_Type* base, uint8_t msgBufIdx) |
| { |
| assert(msgBufIdx < CAN_CS_COUNT); |
| |
| return (flexcan_msgbuf_t*) &base->MB[msgBufIdx]; |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_LockRxMsgBuf |
| * Description : Locks the FlexCAN Rx message buffer. |
| * |
| *END**************************************************************************/ |
| bool FLEXCAN_LockRxMsgBuf(CAN_Type* base, uint8_t msgBufIdx) |
| { |
| volatile uint32_t temp; |
| |
| /* Check if the MB to be Locked is enabled */ |
| if (msgBufIdx > (CAN_MCR_REG(base) & CAN_MCR_MAXMB_MASK)) |
| return false; |
| |
| /* ARM Core read MB's CS to lock MB */ |
| temp = base->MB[msgBufIdx].CS; |
| |
| /* Read temp itself to avoid ARMGCC warning */ |
| temp++; |
| |
| return true; |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_UnlockAllRxMsgBuf |
| * Description : Unlocks the FlexCAN Rx message buffer. |
| * |
| *END**************************************************************************/ |
| uint16_t FLEXCAN_UnlockAllRxMsgBuf(CAN_Type* base) |
| { |
| /* Read Free Running Timer to unlock all MessageBox */ |
| return CAN_TIMER_REG(base); |
| } |
| |
| /******************************************************************************* |
| * FlexCAN Interrupts and flags management functions |
| ******************************************************************************/ |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetMsgBufIntCmd |
| * Description : Enables/Disables the FlexCAN Message Buffer interrupt. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetMsgBufIntCmd(CAN_Type* base, uint8_t msgBufIdx, bool enable) |
| { |
| volatile uint32_t* interruptMaskPtr; |
| uint8_t index; |
| |
| assert(msgBufIdx < CAN_CS_COUNT); |
| |
| if (msgBufIdx > 0x31) |
| { |
| index = msgBufIdx - 32; |
| interruptMaskPtr = &base->IMASK2; |
| } |
| else |
| { |
| index = msgBufIdx; |
| interruptMaskPtr = &base->IMASK1; |
| } |
| |
| if (enable) |
| *interruptMaskPtr |= 0x1 << index; |
| else |
| *interruptMaskPtr &= ~(0x1 << index); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_GetMsgBufStatusFlag |
| * Description : Gets the individual FlexCAN MB interrupt flag. |
| * |
| *END**************************************************************************/ |
| bool FLEXCAN_GetMsgBufStatusFlag(CAN_Type* base, uint8_t msgBufIdx) |
| { |
| volatile uint32_t* interruptFlagPtr; |
| volatile uint8_t index; |
| |
| assert(msgBufIdx < CAN_CS_COUNT); |
| |
| if (msgBufIdx > 0x31) |
| { |
| index = msgBufIdx - 32; |
| interruptFlagPtr = &base->IFLAG2; |
| } |
| else |
| { |
| index = msgBufIdx; |
| interruptFlagPtr = &base->IFLAG1; |
| } |
| |
| return (bool)((*interruptFlagPtr >> index) & 0x1); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_ClearMsgBufStatusFlag |
| * Description : Clears the interrupt flag of the message buffers. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_ClearMsgBufStatusFlag(CAN_Type* base, uint32_t msgBufIdx) |
| { |
| volatile uint8_t index; |
| |
| assert(msgBufIdx < CAN_CS_COUNT); |
| |
| if (msgBufIdx > 0x31) |
| { |
| index = msgBufIdx - 32; |
| /* write 1 to clear. */ |
| base->IFLAG2 = 0x1 << index; |
| } |
| else |
| { |
| index = msgBufIdx; |
| /* write 1 to clear. */ |
| base->IFLAG1 = 0x1 << index; |
| } |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetErrIntCmd |
| * Description : Enables error interrupt of the FlexCAN module. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetErrIntCmd(CAN_Type* base, uint32_t errorType, bool enable) |
| { |
| assert((errorType & flexcanIntRxWarning) || |
| (errorType & flexcanIntTxWarning) || |
| (errorType & flexcanIntWakeUp) || |
| (errorType & flexcanIntBusOff) || |
| (errorType & flexcanIntError)); |
| |
| if (enable) |
| { |
| if (errorType & flexcanIntRxWarning) |
| { |
| CAN_MCR_REG(base) |= CAN_MCR_WRN_EN_MASK; |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_RWRN_MSK_MASK; |
| } |
| |
| if (errorType & flexcanIntTxWarning) |
| { |
| CAN_MCR_REG(base) |= CAN_MCR_WRN_EN_MASK; |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_TWRN_MSK_MASK; |
| } |
| |
| if (errorType & flexcanIntWakeUp) |
| CAN_MCR_REG(base) |= CAN_MCR_WAK_MSK_MASK; |
| |
| if (errorType & flexcanIntBusOff) |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_BOFF_MSK_MASK; |
| |
| if (errorType & flexcanIntError) |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_ERR_MSK_MASK; |
| } |
| else |
| { |
| if (errorType & flexcanIntRxWarning) |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_RWRN_MSK_MASK; |
| |
| if (errorType & flexcanIntTxWarning) |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_TWRN_MSK_MASK; |
| |
| if (errorType & flexcanIntWakeUp) |
| CAN_MCR_REG(base) &= ~CAN_MCR_WAK_MSK_MASK; |
| |
| if (errorType & flexcanIntBusOff) |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_BOFF_MSK_MASK; |
| |
| if (errorType & flexcanIntError) |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_ERR_MSK_MASK; |
| } |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_GetErrStatusFlag |
| * Description : Gets the FlexCAN module interrupt flag. |
| * |
| *END**************************************************************************/ |
| uint32_t FLEXCAN_GetErrStatusFlag(CAN_Type* base, uint32_t errFlags) |
| { |
| return CAN_ESR1_REG(base) & errFlags; |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_ClearErrStatusFlag |
| * Description : Clears the interrupt flag of the FlexCAN module. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_ClearErrStatusFlag(CAN_Type* base, uint32_t errorType) |
| { |
| /* The Interrupt flag must be cleared by writing it to '1'. |
| * Writing '0' has no effect. |
| */ |
| CAN_ESR1_REG(base) = errorType; |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_GetErrCounter |
| * Description : Get the error counter of FlexCAN module. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_GetErrCounter(CAN_Type* base, uint8_t* txError, uint8_t* rxError) |
| { |
| *txError = CAN_ECR_REG(base) & CAN_ECR_Tx_Err_Counter_MASK; |
| *rxError = (CAN_ECR_REG(base) & CAN_ECR_Rx_Err_Counter_MASK) >> \ |
| CAN_ECR_Rx_Err_Counter_SHIFT; |
| } |
| |
| /******************************************************************************* |
| * Rx FIFO management functions |
| ******************************************************************************/ |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_EnableRxFifo |
| * Description : Enables the Rx FIFO. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_EnableRxFifo(CAN_Type* base, uint8_t numOfFilters) |
| { |
| uint8_t maxNumMb; |
| |
| assert(numOfFilters <= 0xF); |
| |
| /* Set Freeze mode*/ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* Set the number of the RX FIFO filters needed*/ |
| CAN_CTRL2_REG(base) = (CAN_CTRL2_REG(base) & ~CAN_CTRL2_RFFN_MASK) | CAN_CTRL2_RFFN(numOfFilters); |
| |
| /* Enable RX FIFO*/ |
| CAN_MCR_REG(base) |= CAN_MCR_RFEN_MASK; |
| |
| /* RX FIFO global mask*/ |
| CAN_RXFGMASK_REG(base) = CAN_RXFGMASK_FGM31_FGM0_MASK; |
| |
| maxNumMb = (CAN_MCR_REG(base) & CAN_MCR_MAXMB_MASK) + 1; |
| |
| for (uint8_t i = 0; i < maxNumMb; i++) |
| { |
| /* RX individual mask*/ |
| CAN_RXIMR_REG(base,i) = CAN_RXIMR0_RXIMR63_MI31_MI0_MASK; |
| } |
| |
| /* De-assert Freeze Mode*/ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_DisableRxFifo |
| * Description : Disables the Rx FIFO. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_DisableRxFifo(CAN_Type* base) |
| { |
| /* Set Freeze mode*/ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* Disable RX FIFO*/ |
| CAN_MCR_REG(base) &= ~CAN_MCR_RFEN_MASK; |
| |
| /* De-assert Freeze Mode*/ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxFifoFilterNum |
| * Description : Set the number of the Rx FIFO filters. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxFifoFilterNum(CAN_Type* base, uint32_t numOfFilters) |
| { |
| assert(numOfFilters <= 0xF); |
| |
| /* Set Freeze mode*/ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* Set the number of RX FIFO ID filters*/ |
| CAN_CTRL2_REG(base) = (CAN_CTRL2_REG(base) & ~CAN_CTRL2_RFFN_MASK) | CAN_CTRL2_RFFN(numOfFilters); |
| |
| /* De-assert Freeze Mode*/ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxFifoFilter |
| * Description : Set the FlexCAN Rx FIFO fields. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxFifoFilter(CAN_Type* base, uint32_t idFormat, flexcan_id_table_t *idFilterTable) |
| { |
| /* Set RX FIFO ID filter table elements*/ |
| uint32_t i, j, numOfFilters; |
| uint32_t val1 = 0, val2 = 0, val = 0; |
| volatile uint32_t *filterTable; |
| |
| numOfFilters = (CAN_CTRL2_REG(base) & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT; |
| /* Rx FIFO Ocuppied First Message Box is MB6 */ |
| filterTable = (volatile uint32_t *)&(base->MB[6]); |
| |
| CAN_MCR_REG(base) |= CAN_MCR_IDAM(idFormat); |
| |
| switch (idFormat) |
| { |
| case flexcanRxFifoIdElementFormatA: |
| /* One full ID (standard and extended) per ID Filter Table element.*/ |
| if (idFilterTable->isRemoteFrame) |
| { |
| val = (uint32_t)0x1 << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT; |
| } |
| if (idFilterTable->isExtendedFrame) |
| { |
| val |= 0x1 << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT; |
| } |
| for (i = 0; i < RxFifoFilterElementNum(numOfFilters); i++) |
| { |
| if(idFilterTable->isExtendedFrame) |
| { |
| filterTable[i] = val + ((*(idFilterTable->idFilter + i)) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_SHIFT & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_MASK); |
| }else |
| { |
| filterTable[i] = val + ((*(idFilterTable->idFilter + i)) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_SHIFT & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_MASK); |
| } |
| } |
| break; |
| case flexcanRxFifoIdElementFormatB: |
| /* Two full standard IDs or two partial 14-bit (standard and extended) IDs*/ |
| /* per ID Filter Table element.*/ |
| if (idFilterTable->isRemoteFrame) |
| { |
| val1 = (uint32_t)0x1 << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT; |
| val2 = 0x1 << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_RTR_SHIFT; |
| } |
| if (idFilterTable->isExtendedFrame) |
| { |
| val1 |= 0x1 << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT; |
| val2 |= 0x1 << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_IDE_SHIFT; |
| } |
| j = 0; |
| for (i = 0; i < RxFifoFilterElementNum(numOfFilters); i++) |
| { |
| if (idFilterTable->isExtendedFrame) |
| { |
| filterTable[i] = val1 + (((*(idFilterTable->idFilter + j)) & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT1); |
| filterTable[i] |= val2 + (((*(idFilterTable->idFilter + j + 1)) & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT2); |
| }else |
| { |
| filterTable[i] = val1 + (((*(idFilterTable->idFilter + j)) & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT1); |
| filterTable[i] |= val2 + (((*(idFilterTable->idFilter + j + 1)) & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT2); |
| } |
| j = j + 2; |
| } |
| break; |
| case flexcanRxFifoIdElementFormatC: |
| /* Four partial 8-bit Standard IDs per ID Filter Table element.*/ |
| j = 0; |
| for (i = 0; i < RxFifoFilterElementNum(numOfFilters); i++) |
| { |
| filterTable[i] = (((*(idFilterTable->idFilter + j)) & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_MASK) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT1); |
| filterTable[i] = (((*(idFilterTable->idFilter + j + 1)) & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_MASK) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT2); |
| filterTable[i] = (((*(idFilterTable->idFilter + j + 2)) & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_MASK) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT3); |
| filterTable[i] = (((*(idFilterTable->idFilter + j + 3)) & |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_MASK) << |
| FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT4); |
| j = j + 4; |
| } |
| break; |
| case flexcanRxFifoIdElementFormatD: |
| /* All frames rejected.*/ |
| break; |
| } |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_GetRxFifoPtr |
| * Description : Gets the FlexCAN Rx FIFO data pointer. |
| * |
| *END**************************************************************************/ |
| flexcan_msgbuf_t* FLEXCAN_GetRxFifoPtr(CAN_Type* base) |
| { |
| /* Rx-Fifo occupy MB0 ~ MB5 */ |
| return (flexcan_msgbuf_t*)&base->MB; |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_GetRxFifoInfo |
| * Description : Set the FlexCAN RX Fifo global mask. |
| * |
| *END**************************************************************************/ |
| uint16_t FLEXCAN_GetRxFifoInfo(CAN_Type* base) |
| { |
| return CAN_RXFIR_REG(base) & CAN_RXFIR_IDHIT_MASK; |
| } |
| |
| /******************************************************************************* |
| * Rx Mask Setting functions |
| ******************************************************************************/ |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxMaskMode |
| * Description : Set the Rx masking mode. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxMaskMode(CAN_Type* base, uint32_t mode) |
| { |
| assert((mode == flexcanRxMaskGlobal) || |
| (mode == flexcanRxMaskIndividual)); |
| |
| /* Assert Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (mode == flexcanRxMaskIndividual) |
| CAN_MCR_REG(base) |= CAN_MCR_IRMQ_MASK; |
| else |
| CAN_MCR_REG(base) &= ~CAN_MCR_IRMQ_MASK; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxMaskRtrCmd |
| * Description : Set the remote trasmit request mask enablement. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxMaskRtrCmd(CAN_Type* base, bool enable) |
| { |
| /* Assert Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (enable) |
| CAN_CTRL2_REG(base) |= CAN_CTRL2_EACEN_MASK; |
| else |
| CAN_CTRL2_REG(base) &= ~CAN_CTRL2_EACEN_MASK; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxGlobalMask |
| * Description : Set the FlexCAN RX global mask. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxGlobalMask(CAN_Type* base, uint32_t mask) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* load mask */ |
| CAN_RXMGMASK_REG(base) = mask; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxIndividualMask |
| * Description : Set the FlexCAN Rx individual mask for ID filtering in |
| * the Rx MBs and the Rx FIFO. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxIndividualMask(CAN_Type* base, uint32_t msgBufIdx, uint32_t mask) |
| { |
| assert(msgBufIdx < CAN_RXIMR_COUNT); |
| |
| /* Assert Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| CAN_RXIMR_REG(base,msgBufIdx) = mask; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxMsgBuff14Mask |
| * Description : Set the FlexCAN RX Message Buffer BUF14 mask. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxMsgBuff14Mask(CAN_Type* base, uint32_t mask) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* load mask */ |
| CAN_RX14MASK_REG(base) = mask; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxMsgBuff15Mask |
| * Description : Set the FlexCAN RX Message Buffer BUF15 mask. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxMsgBuff15Mask(CAN_Type* base, uint32_t mask) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* load mask */ |
| CAN_RX15MASK_REG(base) = mask; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxFifoGlobalMask |
| * Description : Set the FlexCAN RX Fifo global mask. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxFifoGlobalMask(CAN_Type* base, uint32_t mask) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| /* load mask */ |
| CAN_RXFGMASK_REG(base) = mask; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /******************************************************************************* |
| * Misc. Functions |
| ******************************************************************************/ |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetSelfWakeUpCmd |
| * Description : Enable/disable the FlexCAN self wakeup feature. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetSelfWakeUpCmd(CAN_Type* base, bool lpfEnable, bool enable) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (lpfEnable) |
| CAN_MCR_REG(base) |= CAN_MCR_WAK_SRC_MASK; |
| else |
| CAN_MCR_REG(base) &= ~CAN_MCR_WAK_SRC_MASK; |
| |
| if (enable) |
| CAN_MCR_REG(base) |= CAN_MCR_SLF_WAK_MASK; |
| else |
| CAN_MCR_REG(base) &= ~CAN_MCR_SLF_WAK_MASK; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetSelfReceptionCmd |
| * Description : Enable/disable the FlexCAN self reception feature. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetSelfReceptionCmd(CAN_Type* base, bool enable) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (enable) |
| CAN_MCR_REG(base) &= ~CAN_MCR_SRX_DIS_MASK; |
| else |
| CAN_MCR_REG(base) |= CAN_MCR_SRX_DIS_MASK; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetRxVoteCmd |
| * Description : Enable/disable the enhance FlexCAN Rx vote. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetRxVoteCmd(CAN_Type* base, bool enable) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (enable) |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_SMP_MASK; |
| else |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_SMP_MASK; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetAutoBusOffRecoverCmd |
| * Description : Enable/disable the Auto Busoff recover feature. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetAutoBusOffRecoverCmd(CAN_Type* base, bool enable) |
| { |
| if (enable) |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_BOFF_MSK_MASK; |
| else |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_BOFF_MSK_MASK; |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetTimeSyncCmd |
| * Description : Enable/disable the Time Sync feature. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetTimeSyncCmd(CAN_Type* base, bool enable) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (enable) |
| CAN_CTRL1_REG(base) |= CAN_CTRL1_TSYN_MASK; |
| else |
| CAN_CTRL1_REG(base) &= ~CAN_CTRL1_TSYN_MASK; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /*FUNCTION********************************************************************** |
| * |
| * Function Name : FLEXCAN_SetAutoRemoteResponseCmd |
| * Description : Enable/disable the Auto Remote Response feature. |
| * |
| *END**************************************************************************/ |
| void FLEXCAN_SetAutoRemoteResponseCmd(CAN_Type* base, bool enable) |
| { |
| /* Set Freeze mode */ |
| FLEXCAN_EnterFreezeMode(base); |
| |
| if (enable) |
| CAN_CTRL2_REG(base) &= ~CAN_CTRL2_RRS_MASK; |
| else |
| CAN_CTRL2_REG(base) |= CAN_CTRL2_RRS_MASK; |
| |
| /* De-assert Freeze Mode */ |
| FLEXCAN_ExitFreezeMode(base); |
| } |
| |
| /******************************************************************************* |
| * EOF |
| ******************************************************************************/ |