/* * 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 ******************************************************************************/