/* * Copyright (c) 2021, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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. * * * Neither the name of Texas Instruments Incorporated 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 OWNER 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 #ifdef __MSPM0_HAS_MCAN__ /* ========================================================================== */ /* Macros & Typedefs */ /* ========================================================================== */ /** * \brief MCAN MSG RAM BANK number for ECC AGGR. */ #define MCANSS_MSG_RAM_NUM (0U) /** * \brief Maximum Number of Rx Buffers. */ #define MCANSS_RX_BUFFER_MAX (64U) /** * \brief Maximum Number of Tx Buffers. */ #define MCANSS_TX_BUFFER_MAX (32U) /** * \brief Macro for standard Message ID filter. */ #define MCANSS_STD_ID_FILTER_SIZE_WORDS (1U) /** * \brief Macro for extended Message ID filter. */ #define MCANSS_EXT_ID_FILTER_SIZE_WORDS (2U) /** * \brief Macro for Tx Event FIFO element size. */ #define MCANSS_TX_EVENT_FIFO_SIZE_WORDS (2U) /** * \brief Macro for Interrupt Line enable mask. */ #define MCANSS_INTR_LINE_EN_MASK ((MCAN_ILE_EINT0_MASK | MCAN_ILE_EINT1_MASK)) /** * \brief Mask and shift for Tx Buffers elements. */ #define MCANSS_TX_BUFFER_ELEM_ID_SHIFT (0U) #define MCANSS_TX_BUFFER_ELEM_ID_MASK (0x1FFFFFFFU) #define MCANSS_TX_BUFFER_ELEM_RTR_SHIFT (29U) #define MCANSS_TX_BUFFER_ELEM_RTR_MASK (0x20000000U) #define MCANSS_TX_BUFFER_ELEM_XTD_SHIFT (30U) #define MCANSS_TX_BUFFER_ELEM_XTD_MASK (0x40000000U) #define MCANSS_TX_BUFFER_ELEM_ESI_SHIFT (31U) #define MCANSS_TX_BUFFER_ELEM_ESI_MASK (0x80000000U) #define MCANSS_TX_BUFFER_ELEM_DLC_SHIFT (16U) #define MCANSS_TX_BUFFER_ELEM_DLC_MASK (0x000F0000U) #define MCANSS_TX_BUFFER_ELEM_BRS_SHIFT (20U) #define MCANSS_TX_BUFFER_ELEM_BRS_MASK (0x00100000U) #define MCANSS_TX_BUFFER_ELEM_FDF_SHIFT (21U) #define MCANSS_TX_BUFFER_ELEM_FDF_MASK (0x00200000U) #define MCANSS_TX_BUFFER_ELEM_EFC_SHIFT (23U) #define MCANSS_TX_BUFFER_ELEM_EFC_MASK (0x00800000U) #define MCANSS_TX_BUFFER_ELEM_MM_SHIFT (24U) #define MCANSS_TX_BUFFER_ELEM_MM_MASK (0xFF000000U) /** * \brief Mask and shift for Rx Buffers elements. */ #define MCANSS_RX_BUFFER_ELEM_ID_SHIFT (0U) #define MCANSS_RX_BUFFER_ELEM_ID_MASK (0x1FFFFFFFU) #define MCANSS_RX_BUFFER_ELEM_RTR_SHIFT (29U) #define MCANSS_RX_BUFFER_ELEM_RTR_MASK (0x20000000U) #define MCANSS_RX_BUFFER_ELEM_XTD_SHIFT (30U) #define MCANSS_RX_BUFFER_ELEM_XTD_MASK (0x40000000U) #define MCANSS_RX_BUFFER_ELEM_ESI_SHIFT (31U) #define MCANSS_RX_BUFFER_ELEM_ESI_MASK (0x80000000U) #define MCANSS_RX_BUFFER_ELEM_RXTS_SHIFT (0U) #define MCANSS_RX_BUFFER_ELEM_RXTS_MASK (0x0000FFFFU) #define MCANSS_RX_BUFFER_ELEM_DLC_SHIFT (16U) #define MCANSS_RX_BUFFER_ELEM_DLC_MASK (0x000F0000U) #define MCANSS_RX_BUFFER_ELEM_BRS_SHIFT (20U) #define MCANSS_RX_BUFFER_ELEM_BRS_MASK (0x00100000U) #define MCANSS_RX_BUFFER_ELEM_FDF_SHIFT (21U) #define MCANSS_RX_BUFFER_ELEM_FDF_MASK (0x00200000U) #define MCANSS_RX_BUFFER_ELEM_FIDX_SHIFT (24U) #define MCANSS_RX_BUFFER_ELEM_FIDX_MASK (0x7F000000U) #define MCANSS_RX_BUFFER_ELEM_ANMF_SHIFT (31U) #define MCANSS_RX_BUFFER_ELEM_ANMF_MASK (0x80000000U) /** * \brief Mask and shift for Standard Message ID Filter Elements. */ #define MCANSS_STD_ID_FILTER_SFID2_SHIFT (0U) #define MCANSS_STD_ID_FILTER_SFID2_MASK (0x000003FFU) #define MCANSS_STD_ID_FILTER_SFID1_SHIFT (16U) #define MCANSS_STD_ID_FILTER_SFID1_MASK (0x03FF0000U) #define MCANSS_STD_ID_FILTER_SFEC_SHIFT (27U) #define MCANSS_STD_ID_FILTER_SFEC_MASK (0x38000000U) #define MCANSS_STD_ID_FILTER_SFT_SHIFT (30U) #define MCANSS_STD_ID_FILTER_SFT_MASK (0xC0000000U) /** * \brief Extended Message ID Filter Element. */ #define MCANSS_EXT_ID_FILTER_EFID2_SHIFT (0U) #define MCANSS_EXT_ID_FILTER_EFID2_MASK (0x1FFFFFFFU) #define MCANSS_EXT_ID_FILTER_EFID1_SHIFT (0U) #define MCANSS_EXT_ID_FILTER_EFID1_MASK (0x1FFFFFFFU) #define MCANSS_EXT_ID_FILTER_EFEC_SHIFT (29U) #define MCANSS_EXT_ID_FILTER_EFEC_MASK (0xE0000000U) #define MCANSS_EXT_ID_FILTER_EFT_SHIFT (30U) #define MCANSS_EXT_ID_FILTER_EFT_MASK (0xC0000000U) /** * \brief Mask and shift for Tx Event FIFO elements. */ #define MCANSS_TX_EVENT_FIFO_ELEM_ID_SHIFT (0U) #define MCANSS_TX_EVENT_FIFO_ELEM_ID_MASK (0x1FFFFFFFU) #define MCANSS_TX_EVENT_FIFO_ELEM_RTR_SHIFT (29U) #define MCANSS_TX_EVENT_FIFO_ELEM_RTR_MASK (0x20000000U) #define MCANSS_TX_EVENT_FIFO_ELEM_XTD_SHIFT (30U) #define MCANSS_TX_EVENT_FIFO_ELEM_XTD_MASK (0x40000000U) #define MCANSS_TX_EVENT_FIFO_ELEM_ESI_SHIFT (31U) #define MCANSS_TX_EVENT_FIFO_ELEM_ESI_MASK (0x80000000U) #define MCANSS_TX_EVENT_FIFO_ELEM_TXTS_SHIFT (0U) #define MCANSS_TX_EVENT_FIFO_ELEM_TXTS_MASK (0x0000FFFFU) #define MCANSS_TX_EVENT_FIFO_ELEM_DLC_SHIFT (16U) #define MCANSS_TX_EVENT_FIFO_ELEM_DLC_MASK (0x000F0000U) #define MCANSS_TX_EVENT_FIFO_ELEM_BRS_SHIFT (20U) #define MCANSS_TX_EVENT_FIFO_ELEM_BRS_MASK (0x00100000U) #define MCANSS_TX_EVENT_FIFO_ELEM_FDF_SHIFT (21U) #define MCANSS_TX_EVENT_FIFO_ELEM_FDF_MASK (0x00200000U) #define MCANSS_TX_EVENT_FIFO_ELEM_ET_SHIFT (22U) #define MCANSS_TX_EVENT_FIFO_ELEM_ET_MASK (0x00C00000U) #define MCANSS_TX_EVENT_FIFO_ELEM_MM_SHIFT (24U) #define MCANSS_TX_EVENT_FIFO_ELEM_MM_MASK (0xFF000000U) #define HW_RD_REG32(addr) (uint32_t)(HW_RD_REG32_RAW((uint32_t)(addr))) #define HW_WR_REG32(addr, value) \ (HW_WR_REG32_RAW((uint32_t)(addr), (uint32_t)(value))) #define HW_GET_FIELD(regVal, REG_FIELD) \ (((regVal) & (uint32_t) REG_FIELD##_MASK) >> (uint32_t) REG_FIELD##_OFS) #define HW_SET_FIELD32(regVal, REG_FIELD, fieldVal) \ ((regVal) = ((regVal) & (uint32_t)(~(uint32_t) REG_FIELD##_MASK)) | \ ((((uint32_t)(fieldVal)) << (uint32_t) REG_FIELD##_OFS) & \ (uint32_t) REG_FIELD##_MASK)) #define HW_WR_FIELD32(regAddr, REG_FIELD, fieldVal) \ (HW_WR_FIELD32_RAW((uint32_t)(regAddr), (uint32_t) REG_FIELD##_MASK, \ (uint32_t) REG_FIELD##_OFS, (uint32_t)(fieldVal))) #define HW_RD_FIELD32(regAddr, REG_FIELD) \ (HW_RD_FIELD32_RAW((uint32_t)(regAddr), (uint32_t) REG_FIELD##_MASK, \ (uint32_t) REG_FIELD##_OFS)) #define STW_SOK ((int32_t) 0) #define STW_EFAIL (-((int32_t) 1)) #define STW_EBADARGS (-((int32_t) 2)) #define STW_EINVALID_PARAMS (-((int32_t) 3)) #define STW_ETIMEOUT (-((int32_t) 4)) #define STW_EOUT_OF_RANGE (-((int32_t) 5)) #define STW_EUNSUPPORTED_CMD (-((int32_t) 6)) #define STW_EUNSUPPORTED_OPS (-((int32_t) 7)) #define MCAN_MCAN_MSG_MEM (0x0U) /* To fix Misra-C errors */ #ifndef TRUE #define TRUE ((Bool) 1) #endif #ifndef FALSE #define FALSE ((Bool) 0) #endif /* ========================================================================== */ /* Structures and Enums */ /* ========================================================================== */ /* None */ /* ========================================================================== */ /* Internal Function Declarations */ /* ========================================================================== */ /** * \brief This API will unblock write access to write protected registers. * * \param mcan Base Address of the MCAN Registers. * * \return None. */ static void DL_MCAN_writeProtectedRegAccessUnlock(MCAN_Regs *mcan); /** * \brief This API will block write access to write protected registers. * * \param mcan Base Address of the MCAN Registers. * * \return None. */ static void DL_MCAN_writeProtectedRegAccessLock(MCAN_Regs *mcan); /** * \brief This API will load the register from ECC memory bank. * * \param mcan Base Address of the MCAN Registers. * \param regOffset Offset of the register to read. * * \return None. */ static void DL_MCAN_eccLoadRegister(MCAN_Regs *mcan, uint32_t regOffset); /** * \brief This API will read the message object from Message RAM. * * \param mcan Base Address of the MCAN Registers. * \param elemAddr Address of the message object. * \param elem Message Object. * Refer struct #DL_MCAN_RxBufElement. * * \return None. */ static void DL_MCAN_readMsg( uint32_t mcan, uint32_t elemAddr, DL_MCAN_RxBufElement *elem); /** * \brief This API will write the message object to Message RAM. * * \param mcan Base Address of the MCAN Registers. * \param elemAddr Address of the message object. * \param elem Message Object. * Refer struct #MCAN_TXBufElement. * * \return None. */ static void DL_MCAN_writeMsg( uint32_t mcan, uint32_t elemAddr, const DL_MCAN_TxBufElement *elem); /** * \brief This API will return payload depending on 'dlc' field. * * \param dlc Data Length Code. * * \return data size Size of the payload. */ static uint32_t DL_MCAN_getDataSize(uint32_t dlc); /** * \brief This API will return message object size. * * \param elemSize Element Size. * * \return message object size * Size of the message object stored in Message RAM. */ static uint32_t DL_MCAN_getMsgObjSize(uint32_t elemSize); /** * \brief This function reads a 32-bit value from a hardware register * and returns the value. * * \param addr Address of the memory mapped hardware register. * * \return Unsigned 32-bit value read from a register. */ __STATIC_INLINE uint32_t HW_RD_REG32_RAW(uint32_t addr); /** * \brief This function writes a 32-bit value to a hardware register. * * \param addr Address of the memory mapped hardware register. * \param value unsigned 32-bit value which has to be written to the * register. */ __STATIC_INLINE void HW_WR_REG32_RAW(uint32_t addr, uint32_t value); /** * \brief This function reads a 32 bit register, modifies specific set of * bits and writes back to the register. * * \param addr Address of the memory mapped hardware register. * \param mask Mask for the bit field. * \param shift Bit field shift from LSB. * \param value Value to be written to bit-field. */ __STATIC_INLINE void HW_WR_FIELD32_RAW( uint32_t addr, uint32_t mask, uint32_t shift, uint32_t value); /** * \brief This function reads a 32 bit register, masks specific set of bits * and the left shifted value. * * \param addr Address of the memory mapped hardware register. * \param mask Mask for the bit field. * \param shift Bit field shift from LSB. * * \return Bit-field value (absolute value - shifted to LSB position) */ __STATIC_INLINE uint32_t HW_RD_FIELD32_RAW( uint32_t addr, uint32_t mask, uint32_t shift); /* ========================================================================== */ /* Global Variables */ /* ========================================================================== */ /* None */ /* ========================================================================== */ /* Function Definitions */ /* ========================================================================== */ bool DL_MCAN_isReady(DL_MCAN_INSTANCE instance) { return ((SYSCTL->SOCLOCK.SYSSTATUS & (uint32_t) instance) == (uint32_t) instance); } void DL_MCAN_setClockConfig(MCAN_Regs *mcan, const DL_MCAN_ClockConfig *config) { DL_Common_updateReg(&SYSCTL->SOCLOCK.GENCLKCFG, (uint32_t) config->clockSel, SYSCTL_GENCLKCFG_CANCLKSRC_MASK); mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKDIV = (uint32_t) config->divider; } void DL_MCAN_getClockConfig(MCAN_Regs *mcan, DL_MCAN_ClockConfig *config) { uint32_t clockSource = (SYSCTL->SOCLOCK.GENCLKCFG & SYSCTL_GENCLKCFG_CANCLKSRC_MASK); config->clockSel = (DL_MCAN_FCLK)(clockSource); } bool DL_MCAN_isInReset(const MCAN_Regs *mcan) { uint32_t reset; bool state; reset = HW_RD_FIELD32( &mcan->MCANSS.STAT, MCAN_TI_WRAPPER_PROCESSORS_REGS_STAT_RESET); if (1U == reset) { state = true; } else { state = false; } return state; } bool DL_MCAN_isFDOpEnable(const MCAN_Regs *mcan) { uint32_t fdoe; bool state; fdoe = HW_RD_FIELD32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_STAT, MCAN_TI_WRAPPER_PROCESSORS_REGS_STAT_ENABLE_FDOE); if (1U == fdoe) { state = true; } else { state = false; } return state; } bool DL_MCAN_isMemInitDone(const MCAN_Regs *mcan) { uint32_t memInit; bool state; memInit = HW_RD_FIELD32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_STAT, MCAN_TI_WRAPPER_PROCESSORS_REGS_STAT_MEM_INIT_DONE); if (1U == memInit) { state = true; } else { state = false; } return state; } void DL_MCAN_setOpMode(MCAN_Regs *mcan, uint32_t mode) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_INIT, mode); } uint32_t DL_MCAN_getOpMode(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_INIT)); } int32_t DL_MCAN_init(MCAN_Regs *mcan, const DL_MCAN_InitParams *initParams) { int32_t status; uint32_t regVal; /* Configure MCAN wakeup and clock stop controls */ regVal = HW_RD_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL); HW_SET_FIELD32(regVal, MCAN_TI_WRAPPER_REGS_CTRL_WAKEUPREQEN, initParams->wkupReqEnable); HW_SET_FIELD32(regVal, MCAN_TI_WRAPPER_REGS_CTRL_AUTOWAKEUP, initParams->autoWkupEnable); HW_SET_FIELD32(regVal, MCAN_TI_WRAPPER_REGS_CTRL_DBGSUSP_FREE, initParams->emulationEnable); HW_WR_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL, regVal); DL_MCAN_writeProtectedRegAccessUnlock(mcan); /* Configure MCAN mode(FD vs Classic CAN operation) and controls */ regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_CCCR); HW_SET_FIELD32(regVal, MCAN_CCCR_FDOE, initParams->fdMode); HW_SET_FIELD32(regVal, MCAN_CCCR_BRSE, initParams->brsEnable); HW_SET_FIELD32(regVal, MCAN_CCCR_TXP, initParams->txpEnable); HW_SET_FIELD32(regVal, MCAN_CCCR_EFBI, initParams->efbi); HW_SET_FIELD32(regVal, MCAN_CCCR_PXHD, initParams->pxhddisable); HW_SET_FIELD32(regVal, MCAN_CCCR_DAR, initParams->darEnable); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_CCCR, regVal); if ((DL_MCAN_TDCR_TDCF_MAX >= initParams->tdcConfig.tdcf) && (DL_MCAN_TDCR_TDCO_MAX >= initParams->tdcConfig.tdco) && (DL_MCAN_RWD_WDC_MAX >= initParams->wdcPreload)) { /* Configure Transceiver Delay Compensation */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TDCR, MCAN_TDCR_TDCF, initParams->tdcConfig.tdcf); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TDCR, MCAN_TDCR_TDCO, initParams->tdcConfig.tdco); /* Configure MSG RAM watchdog counter preload value */ HW_WR_FIELD32( &mcan->MCANSS.MCAN.MCAN_RWD, MCAN_RWD_WDC, initParams->wdcPreload); /* Enable/Disable Transceiver Delay Compensation */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_TDC, initParams->tdcEnable); status = STW_SOK; } else { status = STW_EFAIL; } DL_MCAN_writeProtectedRegAccessLock(mcan); return status; } int32_t DL_MCAN_config( MCAN_Regs *mcan, const DL_MCAN_ConfigParams *configParams) { int32_t status; DL_MCAN_writeProtectedRegAccessUnlock(mcan); /* Configure MCAN control registers */ HW_WR_FIELD32( &mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_MON, configParams->monEnable); HW_WR_FIELD32( &mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_ASM, configParams->asmEnable); /* Configure Global Filter */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_GFC, MCAN_GFC_RRFE, configParams->filterConfig.rrfe); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_GFC, MCAN_GFC_RRFS, configParams->filterConfig.rrfs); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_GFC, MCAN_GFC_ANFE, configParams->filterConfig.anfe); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_GFC, MCAN_GFC_ANFS, configParams->filterConfig.anfs); if ((DL_MCAN_TSCC_TCP_MAX >= configParams->tsPrescalar) && (DL_MCAN_TOCC_TOP_MAX >= configParams->timeoutPreload)) { /* Configure Time-stamp counter */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TSCC, MCAN_TSCC_TSS, configParams->tsSelect); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TSCC, MCAN_TSCC_TCP, (configParams->tsPrescalar - 1U)); /* Configure Time-out counter */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TOCC, MCAN_TOCC_TOS, configParams->timeoutSelect); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TOCC, MCAN_TOCC_TOP, configParams->timeoutPreload); /* Enable Time-out counter */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TOCC, MCAN_TOCC_ETOC, configParams->timeoutCntEnable); status = STW_SOK; } else { status = STW_EFAIL; } DL_MCAN_writeProtectedRegAccessLock(mcan); return status; } void DL_MCAN_eccConfig( MCAN_Regs *mcan, const DL_MCAN_ECCConfigParams *configParams) { DL_MCAN_eccLoadRegister(mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER .PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL); HW_WR_FIELD32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL, MCAN_TI_WRAPPER_ECC_REGS_CTRL_ECC_CHECK, configParams->enableChk); DL_MCAN_eccLoadRegister(mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER .PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL); HW_WR_FIELD32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL, MCAN_TI_WRAPPER_ECC_REGS_CTRL_ECC_ENABLE, configParams->enable); DL_MCAN_eccLoadRegister(mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER .PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL); HW_WR_FIELD32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL, MCAN_TI_WRAPPER_ECC_REGS_CTRL_ENABLE_RMW, configParams->enableRdModWr); DL_MCAN_eccLoadRegister(mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER .PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL); } int32_t DL_MCAN_setBitTime( MCAN_Regs *mcan, const DL_MCAN_BitTimingParams *configParams) { int32_t status; DL_MCAN_writeProtectedRegAccessUnlock(mcan); if ((DL_MCAN_NBTP_NSJW_MAX >= configParams->nomSynchJumpWidth) && (DL_MCAN_NBTP_NTSEG2_MAX >= configParams->nomTimeSeg2) && (DL_MCAN_NBTP_NTSEG1_MAX >= configParams->nomTimeSeg1) && (DL_MCAN_NBTP_NBRP_MAX >= configParams->nomRatePrescalar)) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NSJW, configParams->nomSynchJumpWidth); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NTSEG2, configParams->nomTimeSeg2); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NTSEG1, configParams->nomTimeSeg1); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NBRP, configParams->nomRatePrescalar); status = STW_SOK; } else { status = STW_EFAIL; } if (STW_SOK == status) { if ((DL_MCAN_DBTP_DSJW_MAX >= configParams->dataSynchJumpWidth) && (DL_MCAN_DBTP_DTSEG2_MAX >= configParams->dataTimeSeg2) && (DL_MCAN_DBTP_DTSEG1_MAX >= configParams->dataTimeSeg1) && (DL_MCAN_DBTP_DBRP_MAX >= configParams->dataRatePrescalar)) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DSJW, configParams->dataSynchJumpWidth); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DTSEG2, configParams->dataTimeSeg2); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DTSEG1, configParams->dataTimeSeg1); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DBRP, configParams->dataRatePrescalar); status = STW_SOK; } else { status = STW_EFAIL; } } DL_MCAN_writeProtectedRegAccessLock(mcan); return status; } int32_t DL_MCAN_msgRAMConfig( MCAN_Regs *mcan, const DL_MCAN_MsgRAMConfigParams *msgRAMConfigParams) { int32_t status; uint32_t elemNum = 0U; DL_MCAN_writeProtectedRegAccessUnlock(mcan); /* Configure Message Filters section */ if (0U != msgRAMConfigParams->lss) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_SIDFC, MCAN_SIDFC_FLSSA, (msgRAMConfigParams->flssa >> 2U)); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_SIDFC, MCAN_SIDFC_LSS, msgRAMConfigParams->lss); } if (0U != msgRAMConfigParams->lse) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDFC, MCAN_XIDFC_FLESA, (msgRAMConfigParams->flesa >> 2U)); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDFC, MCAN_XIDFC_LSE, msgRAMConfigParams->lse); } /* Configure Rx FIFO 0 section */ if (0U != msgRAMConfigParams->rxFIFO0size) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0SA, (msgRAMConfigParams->rxFIFO0startAddr >> 2U)); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0S, msgRAMConfigParams->rxFIFO0size); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0WM, msgRAMConfigParams->rxFIFO0waterMark); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0OM, msgRAMConfigParams->rxFIFO0OpMode); /* Configure Rx FIFO0 elements size */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_F0DS, msgRAMConfigParams->rxFIFO0ElemSize); } /* Configure Rx FIFO 1 section */ if (0U != msgRAMConfigParams->rxFIFO1size) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1SA, (msgRAMConfigParams->rxFIFO1startAddr >> 2U)); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1S, msgRAMConfigParams->rxFIFO1size); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1WM, msgRAMConfigParams->rxFIFO1waterMark); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1OM, msgRAMConfigParams->rxFIFO1OpMode); /* Configure Rx FIFO1 elements size */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_F1DS, msgRAMConfigParams->rxFIFO1ElemSize); } /* Configure Rx Buffer Start Address */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXBC, MCAN_RXBC_RBSA, (msgRAMConfigParams->rxBufStartAddr >> 2U)); /* Configure Rx Buffer elements size */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_RBDS, msgRAMConfigParams->rxBufElemSize); /* Configure Tx Event FIFO section */ if (0U != msgRAMConfigParams->txEventFIFOSize) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFSA, (msgRAMConfigParams->txEventFIFOStartAddr >> 2U)); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFS, msgRAMConfigParams->txEventFIFOSize); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFWM, msgRAMConfigParams->txEventFIFOWaterMark); } /* Configure Tx Buffer and FIFO/Q section */ elemNum = msgRAMConfigParams->txBufNum + msgRAMConfigParams->txFIFOSize; if ((MCANSS_TX_BUFFER_MAX >= elemNum) && ((0U != msgRAMConfigParams->txBufNum) || (0U != msgRAMConfigParams->txFIFOSize))) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_TBSA, (msgRAMConfigParams->txStartAddr >> 2U)); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_NDTB, msgRAMConfigParams->txBufNum); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_TFQS, msgRAMConfigParams->txFIFOSize); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_TFQM, msgRAMConfigParams->txBufMode); /* Configure Tx Buffer/FIFO0/FIFO1 elements size */ HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXESC, MCAN_TXESC_TBDS, msgRAMConfigParams->txBufElemSize); status = STW_SOK; } else { status = STW_EFAIL; } DL_MCAN_writeProtectedRegAccessLock(mcan); return status; } int32_t DL_MCAN_setExtIDAndMask(MCAN_Regs *mcan, uint32_t idMask) { int32_t status; if (DL_MCAN_XIDAM_EIDM_MAX >= idMask) { DL_MCAN_writeProtectedRegAccessUnlock(mcan); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDAM, MCAN_XIDAM_EIDM, idMask); DL_MCAN_writeProtectedRegAccessLock(mcan); status = STW_SOK; } else { status = STW_EFAIL; } return status; } void DL_MCAN_writeMsgRam(MCAN_Regs *mcan, uint32_t memType, uint32_t bufNum, const DL_MCAN_TxBufElement *elem) { uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U; uint32_t idx = 0U, enableMod = 0U; if (((uint32_t) DL_MCAN_MEM_TYPE_BUF) == memType) { idx = bufNum; enableMod = 1U; } if (((uint32_t) DL_MCAN_MEM_TYPE_FIFO) == memType) { idx = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXFQS, MCAN_TXFQS_TFQP); enableMod = 1U; } if (1U == enableMod) { startAddr = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_TBSA); elemSize = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXESC, MCAN_TXESC_TBDS); startAddr = (uint32_t)(startAddr << 2U); elemSize = DL_MCAN_getMsgObjSize(elemSize); elemSize *= 4U; elemAddr = startAddr + (elemSize * idx); elemAddr += MCAN_MCAN_MSG_MEM; DL_MCAN_writeMsg((uint32_t) mcan, elemAddr, elem); } } int32_t DL_MCAN_TXBufAddReq(MCAN_Regs *mcan, uint32_t bufNum) { int32_t status; uint32_t regVal; if (MCANSS_TX_BUFFER_MAX > bufNum) { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBAR); regVal |= ((uint32_t) 1U << bufNum); /* * For writing to TXBAR CCE bit should be '0'. This need not be * reverted because for other qualified writes this is locked state * and can't be written. */ DL_MCAN_writeProtectedRegAccessLock(mcan); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBAR, regVal); status = STW_SOK; } else { status = STW_EFAIL; } return status; } void DL_MCAN_getNewDataStatus( const MCAN_Regs *mcan, DL_MCAN_RxNewDataStatus *newDataStatus) { newDataStatus->statusLow = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_NDAT1); newDataStatus->statusHigh = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_NDAT2); } void DL_MCAN_clearNewDataStatus( MCAN_Regs *mcan, const DL_MCAN_RxNewDataStatus *newDataStatus) { HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_NDAT1, newDataStatus->statusLow); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_NDAT2, newDataStatus->statusHigh); } void DL_MCAN_readMsgRam(const MCAN_Regs *mcan, uint32_t memType, uint32_t bufNum, uint32_t fifoNum, DL_MCAN_RxBufElement *elem) { uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U; uint32_t enableMod = 0U, idx = 0U; if (((uint32_t) DL_MCAN_MEM_TYPE_BUF) == memType) { startAddr = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXBC, MCAN_RXBC_RBSA); elemSize = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_RBDS); idx = bufNum; enableMod = 1U; } if (((uint32_t) DL_MCAN_MEM_TYPE_FIFO) == memType) { switch (fifoNum) { case ((uint32_t) DL_MCAN_RX_FIFO_NUM_0): startAddr = HW_RD_FIELD32( &mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0SA); elemSize = HW_RD_FIELD32( &mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_F0DS); idx = HW_RD_FIELD32( &mcan->MCANSS.MCAN.MCAN_RXF0S, MCAN_RXF0S_F0GI); enableMod = 1U; break; case ((uint32_t) DL_MCAN_RX_FIFO_NUM_1): startAddr = HW_RD_FIELD32( &mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1SA); elemSize = HW_RD_FIELD32( &mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_F1DS); idx = HW_RD_FIELD32( &mcan->MCANSS.MCAN.MCAN_RXF1S, MCAN_RXF1S_F1GI); enableMod = 1U; break; default: /* Invalid option */ break; } } if (1U == enableMod) { startAddr = (uint32_t)(startAddr << 2U); elemSize = DL_MCAN_getMsgObjSize(elemSize); elemSize *= 4U; elemAddr = startAddr + (elemSize * idx); elemAddr += MCAN_MCAN_MSG_MEM; DL_MCAN_readMsg((uint32_t) mcan, elemAddr, elem); } } void DL_MCAN_readTxEventFIFO( const MCAN_Regs *mcan, DL_MCAN_TxEventFIFOElement *txEventElem) { uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U; uint32_t idx = 0U, regVal; startAddr = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFSA); elemSize = MCANSS_TX_EVENT_FIFO_SIZE_WORDS; idx = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFS, MCAN_TXEFS_EFGI); startAddr = (uint32_t)(startAddr << 2U); elemSize *= 4U; elemAddr = startAddr + (elemSize * idx); elemAddr += MCAN_MCAN_MSG_MEM; regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr)); txEventElem->id = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_ID_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_ID_SHIFT); txEventElem->rtr = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_RTR_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_RTR_SHIFT); txEventElem->xtd = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_XTD_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_XTD_SHIFT); txEventElem->esi = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_ESI_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_ESI_SHIFT); elemAddr += 4U; regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr)); txEventElem->txts = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_TXTS_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_TXTS_SHIFT); txEventElem->dlc = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_DLC_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_DLC_SHIFT); txEventElem->brs = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_BRS_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_BRS_SHIFT); txEventElem->fdf = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_FDF_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_FDF_SHIFT); txEventElem->et = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_ET_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_ET_SHIFT); txEventElem->mm = (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_MM_MASK) >> MCANSS_TX_EVENT_FIFO_ELEM_MM_SHIFT); } void DL_MCAN_addStdMsgIDFilter(MCAN_Regs *mcan, uint32_t filtNum, const DL_MCAN_StdMsgIDFilterElement *elem) { uint32_t startAddr, elemAddr, regVal; startAddr = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_SIDFC, MCAN_SIDFC_FLSSA); startAddr = (uint32_t)(startAddr << 2U); elemAddr = startAddr + (filtNum * MCANSS_STD_ID_FILTER_SIZE_WORDS * 4U); elemAddr += MCAN_MCAN_MSG_MEM; regVal = 0U; regVal |= (uint32_t)(elem->sfid2 << MCANSS_STD_ID_FILTER_SFID2_SHIFT); regVal |= (uint32_t)(elem->sfid1 << MCANSS_STD_ID_FILTER_SFID1_SHIFT); regVal |= (uint32_t)(elem->sfec << MCANSS_STD_ID_FILTER_SFEC_SHIFT); regVal |= (uint32_t)(elem->sft << MCANSS_STD_ID_FILTER_SFT_SHIFT); HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal); } void DL_MCAN_addExtMsgIDFilter(MCAN_Regs *mcan, uint32_t filtNum, const DL_MCAN_ExtMsgIDFilterElement *elem) { uint32_t startAddr, elemAddr, regVal; startAddr = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDFC, MCAN_XIDFC_FLESA); startAddr = (uint32_t)(startAddr << 2U); elemAddr = startAddr + (filtNum * MCANSS_EXT_ID_FILTER_SIZE_WORDS * 4U); elemAddr += MCAN_MCAN_MSG_MEM; regVal = 0U; regVal |= (uint32_t)(elem->efid1 << MCANSS_EXT_ID_FILTER_EFID1_SHIFT); regVal |= (uint32_t)(elem->efec << MCANSS_EXT_ID_FILTER_EFEC_SHIFT); HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal); elemAddr += 4U; regVal = 0U; regVal |= (uint32_t)(elem->efid2 << MCANSS_EXT_ID_FILTER_EFID2_SHIFT); regVal |= (uint32_t)(elem->eft << MCANSS_EXT_ID_FILTER_EFT_SHIFT); HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal); } void DL_MCAN_lpbkModeEnable(MCAN_Regs *mcan, uint32_t lpbkMode, bool enable) { DL_MCAN_writeProtectedRegAccessUnlock(mcan); if (true == enable) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_TEST, 0x1U); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_LBCK, enable); if (((uint32_t) DL_MCAN_LPBK_MODE_INTERNAL) == lpbkMode) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_MON, 0x1U); } } else { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_LBCK, enable); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_TEST, 0x0U); if (((uint32_t) DL_MCAN_LPBK_MODE_INTERNAL) == lpbkMode) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_MON, 0x0U); } } DL_MCAN_writeProtectedRegAccessLock(mcan); } void DL_MCAN_getErrCounters( const MCAN_Regs *mcan, DL_MCAN_ErrCntStatus *errCounter) { errCounter->canErrLogCnt = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ECR, MCAN_ECR_CEL); errCounter->transErrLogCnt = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ECR, MCAN_ECR_TEC); errCounter->recErrCnt = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ECR, MCAN_ECR_REC); errCounter->rpStatus = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ECR, MCAN_ECR_RP); } void DL_MCAN_getProtocolStatus( const MCAN_Regs *mcan, DL_MCAN_ProtocolStatus *protStatus) { uint32_t regVal; regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_PSR); protStatus->lastErrCode = HW_GET_FIELD(regVal, MCAN_PSR_LEC); protStatus->act = HW_GET_FIELD(regVal, MCAN_PSR_ACT); protStatus->errPassive = HW_GET_FIELD(regVal, MCAN_PSR_EP); protStatus->warningStatus = HW_GET_FIELD(regVal, MCAN_PSR_EW); protStatus->busOffStatus = HW_GET_FIELD(regVal, MCAN_PSR_BO); protStatus->dlec = HW_GET_FIELD(regVal, MCAN_PSR_DLEC); protStatus->resi = HW_GET_FIELD(regVal, MCAN_PSR_RESI); protStatus->rbrs = HW_GET_FIELD(regVal, MCAN_PSR_RBRS); protStatus->rfdf = HW_GET_FIELD(regVal, MCAN_PSR_RFDF); protStatus->pxe = HW_GET_FIELD(regVal, MCAN_PSR_PXE); protStatus->tdcv = HW_GET_FIELD(regVal, MCAN_PSR_TDCV); } void DL_MCAN_enableIntr(MCAN_Regs *mcan, uint32_t intrMask, bool enable) { uint32_t regVal; if (true == enable) { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_IE); regVal |= intrMask; HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_IE, regVal); } else { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_IE); regVal &= ~intrMask; HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_IE, regVal); } } void DL_MCAN_selectIntrLine( MCAN_Regs *mcan, uint32_t intrMask, uint32_t lineNum) { uint32_t regVal; if (((uint32_t) DL_MCAN_INTR_LINE_NUM_0) == lineNum) { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_ILS); regVal &= ~intrMask; HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_ILS, regVal); } else { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_ILS); regVal |= intrMask; HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_ILS, regVal); } } uint32_t DL_MCAN_getIntrLineSelectStatus(const MCAN_Regs *mcan) { return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_ILS)); } void DL_MCAN_enableIntrLine(MCAN_Regs *mcan, uint32_t lineNum, bool enable) { uint32_t regVal; lineNum &= MCANSS_INTR_LINE_EN_MASK; regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_ILE); regVal &= ~((uint32_t) 0x1U << lineNum); regVal |= ((uint32_t) enable << lineNum); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_ILE, regVal); } uint32_t DL_MCAN_getIntrStatus(const MCAN_Regs *mcan) { return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_IR)); } void DL_MCAN_clearIntrStatus( MCAN_Regs *mcan, uint32_t intrMask, DL_MCAN_INTR_SRC_MCAN eoi) { HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_IR, intrMask); HW_WR_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_EOI, (uint32_t) eoi); } void DL_MCAN_getHighPriorityMsgStatus( const MCAN_Regs *mcan, DL_MCAN_HighPriorityMsgInfo *hpm) { hpm->bufIdx = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_HPMS, MCAN_HPMS_BIDX); hpm->msi = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_HPMS, MCAN_HPMS_MSI); hpm->filterIdx = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_HPMS, MCAN_HPMS_FIDX); hpm->filterList = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_HPMS, MCAN_HPMS_FLST); } void DL_MCAN_getRxFIFOStatus( const MCAN_Regs *mcan, DL_MCAN_RxFIFOStatus *fifoStatus) { uint32_t regVal; switch (fifoStatus->num) { case ((uint32_t) DL_MCAN_RX_FIFO_NUM_0): regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_RXF0S); fifoStatus->fillLvl = HW_GET_FIELD(regVal, MCAN_RXF0S_F0FL); fifoStatus->getIdx = HW_GET_FIELD(regVal, MCAN_RXF0S_F0GI); fifoStatus->putIdx = HW_GET_FIELD(regVal, MCAN_RXF0S_F0PI); fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_RXF0S_F0F); fifoStatus->msgLost = HW_GET_FIELD(regVal, MCAN_RXF0S_RF0L); break; case ((uint32_t) DL_MCAN_RX_FIFO_NUM_1): regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_RXF1S); fifoStatus->fillLvl = HW_GET_FIELD(regVal, MCAN_RXF1S_F1FL); fifoStatus->getIdx = HW_GET_FIELD(regVal, MCAN_RXF1S_F1GI); fifoStatus->putIdx = HW_GET_FIELD(regVal, MCAN_RXF1S_F1PI); fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_RXF1S_F1F); fifoStatus->msgLost = HW_GET_FIELD(regVal, MCAN_RXF1S_RF1L); break; default: /* Invalid option */ break; } } int32_t DL_MCAN_writeRxFIFOAck(MCAN_Regs *mcan, uint32_t fifoNum, uint32_t idx) { int32_t status; uint32_t size; switch (fifoNum) { case ((uint32_t) DL_MCAN_RX_FIFO_NUM_0): size = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0S); if (size >= idx) { HW_WR_FIELD32( &mcan->MCANSS.MCAN.MCAN_RXF0A, MCAN_RXF0A_F0AI, idx); status = STW_SOK; } else { status = STW_EFAIL; } break; case ((uint32_t) DL_MCAN_RX_FIFO_NUM_1): size = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1S); if (size >= idx) { HW_WR_FIELD32( &mcan->MCANSS.MCAN.MCAN_RXF1A, MCAN_RXF1A_F1AI, idx); status = STW_SOK; } else { status = STW_EFAIL; } break; default: status = STW_EFAIL; break; } return status; } void DL_MCAN_getTxFIFOQueStatus( const MCAN_Regs *mcan, DL_MCAN_TxFIFOStatus *fifoStatus) { uint32_t regVal; regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXFQS); fifoStatus->freeLvl = HW_GET_FIELD(regVal, MCAN_TXFQS_TFFL); fifoStatus->getIdx = HW_GET_FIELD(regVal, MCAN_TXFQS_TFGI); fifoStatus->putIdx = HW_GET_FIELD(regVal, MCAN_TXFQS_TFQP); fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_TXFQS_TFQF); } uint32_t DL_MCAN_getTxBufReqPend(const MCAN_Regs *mcan) { return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBRP)); } int32_t DL_MCAN_txBufCancellationReq(MCAN_Regs *mcan, uint32_t buffNum) { int32_t status; uint32_t regVal; if (MCANSS_TX_BUFFER_MAX > buffNum) { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCR); regVal |= ((uint32_t) 1U << buffNum); /* * For writing to TXBCR CCE bit should be '0'. This need not be * reverted because for other qualified writes this is locked state * and can't be written. */ DL_MCAN_writeProtectedRegAccessLock(mcan); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCR, regVal); status = STW_SOK; } else { status = STW_EFAIL; } return status; } uint32_t DL_MCAN_getTxBufTransmissionStatus(const MCAN_Regs *mcan) { return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTO)); } uint32_t DL_MCAN_txBufCancellationStatus(const MCAN_Regs *mcan) { return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCF)); } int32_t DL_MCAN_TXBufTransIntrEnable( MCAN_Regs *mcan, uint32_t bufNum, bool enable) { int32_t status; uint32_t regVal; if (MCANSS_TX_BUFFER_MAX > bufNum) { if (true == enable) { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTIE); regVal |= ((uint32_t) 1U << bufNum); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTIE, regVal); } else { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTIE); regVal &= ~((uint32_t) 0x1U << bufNum); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTIE, regVal); } status = STW_SOK; } else { status = STW_EFAIL; } return status; } int32_t DL_MCAN_getTxBufCancellationIntrEnable( const MCAN_Regs *mcan, uint32_t bufNum, bool enable) { int32_t status; uint32_t regVal; if (MCANSS_TX_BUFFER_MAX > bufNum) { if (true == enable) { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCIE); regVal |= ((uint32_t) 0x1U << bufNum); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCIE, regVal); } else { regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCIE); regVal &= ~((uint32_t) 0x1U << bufNum); HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCIE, regVal); } status = STW_SOK; } else { status = STW_EFAIL; } return status; } void DL_MCAN_getTxEventFIFOStatus( const MCAN_Regs *mcan, DL_MCAN_TxEventFIFOStatus *fifoStatus) { uint32_t regVal; regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXEFS); fifoStatus->fillLvl = HW_GET_FIELD(regVal, MCAN_TXEFS_EFFL); fifoStatus->getIdx = HW_GET_FIELD(regVal, MCAN_TXEFS_EFGI); fifoStatus->putIdx = HW_GET_FIELD(regVal, MCAN_TXEFS_EFPI); fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_TXEFS_EFF); fifoStatus->eleLost = HW_GET_FIELD(regVal, MCAN_TXEFS_TEFL); } void DL_MCAN_addClockStopRequest(MCAN_Regs *mcan, bool enable) { if (true == enable) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CSR, 0x1U); } else { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CSR, 0x0U); } } int32_t DL_MCAN_writeTxEventFIFOAck(MCAN_Regs *mcan, uint32_t idx) { int32_t status; uint32_t size; size = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFS); if (size >= idx) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFA, MCAN_TXEFA_EFAI, idx); status = STW_SOK; } else { status = STW_EFAIL; } return status; } void DL_MCAN_eccForceError( MCAN_Regs *mcan, const DL_MCAN_ECCErrForceParams *eccErr) { uint32_t regVal; if ((eccErr->errType == ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC)) || (eccErr->errType == ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED))) { DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_CTRL1); regVal = HW_RD_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_CTRL1); HW_SET_FIELD32(regVal, MCAN_ERR_CTRL1_ECC_ROW, eccErr->rowNum); HW_WR_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_CTRL1, regVal); DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_CTRL2); regVal = HW_RD_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_CTRL2); HW_SET_FIELD32(regVal, MCAN_ERR_CTRL2_ECC_BIT1, eccErr->bit1); HW_SET_FIELD32(regVal, MCAN_ERR_CTRL2_ECC_BIT2, eccErr->bit2); HW_WR_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_CTRL2, regVal); DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_CTRL); regVal = HW_RD_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL); HW_SET_FIELD32(regVal, MCAN_TI_WRAPPER_ECC_REGS_CTRL_FORCE_N_ROW, eccErr->errForce); HW_SET_FIELD32( regVal, MCAN_TI_WRAPPER_ECC_REGS_CTRL_ERROR_ONCE, eccErr->errOnce); if (eccErr->errType == ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC)) { HW_SET_FIELD32( regVal, MCAN_TI_WRAPPER_ECC_REGS_CTRL_FORCE_SEC, 0x1U); } else { /* eccErr->errType == ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED) */ HW_SET_FIELD32( regVal, MCAN_TI_WRAPPER_ECC_REGS_CTRL_FORCE_DED, 0x1U); } HW_WR_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL, regVal); DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_CTRL); } } void DL_MCAN_eccGetErrorStatus(MCAN_Regs *mcan, DL_MCAN_ECCErrStatus *eccErr) { uint32_t regVal; DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_STAT1); regVal = HW_RD_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_STAT1); eccErr->secErr = HW_GET_FIELD(regVal, MCAN_ERR_STAT1_ECC_SEC); eccErr->dedErr = HW_GET_FIELD(regVal, MCAN_ERR_STAT1_ECC_DED); eccErr->bit1 = HW_GET_FIELD(regVal, MCAN_ERR_STAT1_ECC_BIT1); DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_STAT2); regVal = HW_RD_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_STAT2); eccErr->row = HW_GET_FIELD(regVal, MCAN_ERR_STAT2_ECC_ROW); } void DL_MCAN_eccClearErrorStatus(MCAN_Regs *mcan, uint32_t errType) { DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_STAT1); switch (errType) { case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_STAT1, MCAN_ERR_STAT1_ECC_SEC, 0x1U); break; case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_STAT1, MCAN_ERR_STAT1_ECC_DED, 0x1U); break; default: /* Invalid option */ break; } DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_ERR_STAT1); } void DL_MCAN_eccWriteEOI(MCAN_Regs *mcan, uint32_t errType) { switch (errType) { case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_SEC_EOI, MCAN_SEC_EOI_EOI_WR, 0x1U); break; case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_DED_EOI, MCAN_DED_EOI_EOI_WR, 0x1U); break; default: /* Invalid option */ break; } } void DL_MCAN_eccEnableIntr(MCAN_Regs *mcan, uint32_t errType, bool enable) { if (true == enable) { switch (errType) { case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_SEC_ENABLE_SET, MCAN_SEC_ENABLE_SET_MSGMEM_ENABLE_SET, 0x1U); break; case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_DED_ENABLE_SET, MCAN_DED_ENABLE_SET_MSGMEM_ENABLE_SET, 0x1U); break; default: /* Invalid option */ break; } } else { switch (errType) { case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_SEC_ENABLE_CLR, MCAN_SEC_ENABLE_CLR_MSGMEM_ENABLE_CLR, 0x1U); break; case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_DED_ENABLE_CLR, MCAN_DED_ENABLE_CLR_MSGMEM_ENABLE_CLR, 0x1U); break; default: /* Invalid option */ break; } } } uint32_t DL_MCAN_eccGetIntrStatus(const MCAN_Regs *mcan, uint32_t errType) { uint32_t retVal = 0U; switch (errType) { case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC): retVal = HW_RD_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS .MCAN_ECC_REGS.MCANERR_SEC_STATUS, MCAN_SEC_STATUS_MSGMEM_PEND); break; case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED): retVal = HW_RD_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS .MCAN_ECC_REGS.MCANERR_DED_STATUS, MCAN_DED_STATUS_MSGMEM_PEND); break; default: retVal = 0U; break; } return retVal; } void DL_MCAN_eccClearIntrStatus(MCAN_Regs *mcan, uint32_t errType) { switch (errType) { case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_SEC_STATUS, MCAN_SEC_STATUS_MSGMEM_PEND, 0x1U); break; case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED): HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_DED_STATUS, MCAN_DED_STATUS_MSGMEM_PEND, 0x1U); break; default: break; } } void DL_MCAN_extTSCounterConfig(MCAN_Regs *mcan, uint32_t prescalar) { HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS .MCANSS_EXT_TS_PRESCALER, MCAN_EXT_TS_PRESCALER_PRESCALER, prescalar); } void DL_MCAN_extTSCounterEnable(MCAN_Regs *mcan, bool enable) { HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL, MCAN_TI_WRAPPER_REGS_CTRL_EXT_TS_CNTR_EN, enable); } void DL_MCAN_extTSEnableIntr(MCAN_Regs *mcan, bool enable) { if (true == enable) { HW_WR_FIELD32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IE, MCAN_TI_WRAPPER_PROCESSORS_REGS_IE_EXT_TS_CNTR_OVFL, 1U); } else { HW_WR_FIELD32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IECS, MCAN_IECS_EXT_TS_CNTR_OVFL, 1U); } } void DL_MCAN_extTSWriteEOI(MCAN_Regs *mcan) { HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_EOI, MCAN_EOI_EOI, 0x1U); } uint32_t DL_MCAN_extTSGetUnservicedIntrCount(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS .MCANSS_EXT_TS_UNSERVICED_INTR_CNTR, MCAN_EXT_TS_UNSERVICED_INTR_CNTR_EXT_TS_INTR_CNTR)); } /* ========================================================================== */ /* Advance Functions */ /* ========================================================================== */ void DL_MCAN_getRevisionId(const MCAN_Regs *mcan, DL_MCAN_RevisionId *revId) { uint32_t regVal; regVal = HW_RD_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_PID); revId->minor = HW_GET_FIELD(regVal, MCAN_PID_MINOR); revId->major = HW_GET_FIELD(regVal, MCAN_PID_MAJOR); revId->modId = HW_GET_FIELD(regVal, MCAN_PID_MODULE_ID); revId->scheme = HW_GET_FIELD(regVal, MCAN_PID_SCHEME); regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_CREL); revId->day = HW_GET_FIELD(regVal, MCAN_CREL_DAY); revId->mon = HW_GET_FIELD(regVal, MCAN_CREL_MON); revId->year = HW_GET_FIELD(regVal, MCAN_CREL_YEAR); revId->subStep = HW_GET_FIELD(regVal, MCAN_CREL_SUBSTEP); revId->step = HW_GET_FIELD(regVal, MCAN_CREL_STEP); revId->rel = HW_GET_FIELD(regVal, MCAN_CREL_REL); } uint32_t DL_MCAN_getClockStopAck(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CSR)); } void DL_MCAN_extTSSetRawStatus(MCAN_Regs *mcan) { HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IRS, MCAN_IRS_EXT_TS_CNTR_OVFL, 1U); } void DL_MCAN_extTSClearRawStatus(MCAN_Regs *mcan) { HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_ICS, MCAN_ICS_EXT_TS_CNTR_OVFL, 1U); } uint32_t DL_MCAN_getRxPinState(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_RX)); } void DL_MCAN_setTxPinState(MCAN_Regs *mcan, uint32_t state) { DL_MCAN_writeProtectedRegAccessUnlock(mcan); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_TEST, 0x1U); HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_TX, state); DL_MCAN_writeProtectedRegAccessLock(mcan); } uint32_t DL_MCAN_getTxPinState(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_TX)); } uint32_t DL_MCAN_getTSCounterVal(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TSCV, MCAN_TSCV_TSC)); } uint32_t DL_MCAN_getClkStopAck(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CSA)); } void DL_MCAN_getBitTime( const MCAN_Regs *mcan, DL_MCAN_BitTimingParams *configParams) { configParams->nomSynchJumpWidth = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NSJW); configParams->nomTimeSeg2 = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NTSEG2); configParams->nomTimeSeg1 = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NTSEG1); configParams->nomRatePrescalar = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NBRP); configParams->dataSynchJumpWidth = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DSJW); configParams->dataTimeSeg2 = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DTSEG2); configParams->dataTimeSeg1 = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DTSEG1); configParams->dataRatePrescalar = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DBRP); } void DL_MCAN_resetTSCounter(MCAN_Regs *mcan) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TSCV, MCAN_TSCV_TSC, 0x0U); } uint32_t DL_MCAN_getTOCounterVal(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TOCV, MCAN_TOCV_TOC)); } void DL_MCAN_eccAggrGetRevisionId( const MCAN_Regs *mcan, DL_MCAN_ECCAggrRevisionId *revId) { uint32_t regVal; regVal = HW_RD_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_REV); revId->minor = HW_GET_FIELD(regVal, MCAN_REV_REVMIN); revId->major = HW_GET_FIELD(regVal, MCAN_REV_REVMAJ); revId->modId = HW_GET_FIELD(regVal, MCAN_REV_MODULE_ID); revId->scheme = HW_GET_FIELD(regVal, MCAN_REV_SCHEME); } void DL_MCAN_eccWrapGetRevisionId( MCAN_Regs *mcan, DL_MCAN_ECCWrapRevisionId *revId) { uint32_t regVal; DL_MCAN_eccLoadRegister( mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_WRAP_REV); regVal = HW_RD_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_WRAP_REV); revId->minor = HW_GET_FIELD(regVal, MCAN_WRAP_REV_REVMIN); revId->major = HW_GET_FIELD(regVal, MCAN_WRAP_REV_REVMAJ); revId->modId = HW_GET_FIELD(regVal, MCAN_WRAP_REV_MODULE_ID); revId->scheme = HW_GET_FIELD(regVal, MCAN_WRAP_REV_SCHEME); } bool DL_MCAN_extTSIsIntrEnable(const MCAN_Regs *mcan) { bool status; if (1U == HW_RD_FIELD32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IES, MCAN_IES_EXT_TS_CNTR_OVFL)) { status = true; } else { status = false; } return status; } uint32_t DL_MCAN_getEndianVal(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ENDN, MCAN_ENDN_ETV)); } uint32_t DL_MCAN_getExtIDANDMask(const MCAN_Regs *mcan) { return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDAM, MCAN_XIDAM_EIDM)); } /* ========================================================================== */ /* Internal Functions */ /* ========================================================================== */ static void DL_MCAN_writeProtectedRegAccessUnlock(MCAN_Regs *mcan) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CCE, 0x1U); } static void DL_MCAN_writeProtectedRegAccessLock(MCAN_Regs *mcan) { HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CCE, 0x0U); } static void DL_MCAN_eccLoadRegister(MCAN_Regs *mcan, uint32_t regOffset) { uint32_t regVal = 0U, offset; offset = regOffset & 0xFFU; regVal |= ((uint32_t) MCANSS_MSG_RAM_NUM << MCAN_VECTOR_ECC_VECTOR_OFS); regVal |= (offset << MCAN_VECTOR_RD_SVBUS_ADDRESS_OFS); regVal |= ((uint32_t) 1U << MCAN_VECTOR_RD_SVBUS_OFS); HW_WR_REG32( &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_VECTOR, regVal); while (MCAN_VECTOR_RD_SVBUS_DONE_MASK != (HW_RD_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS .MCANERR_VECTOR) & MCAN_VECTOR_RD_SVBUS_DONE_MASK)) { } } static void DL_MCAN_readMsg( uint32_t mcan, uint32_t elemAddr, DL_MCAN_RxBufElement *elem) { uint32_t regVal = 0U, loopCnt = 0U; regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr)); elem->id = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_ID_MASK) >> MCANSS_RX_BUFFER_ELEM_ID_SHIFT); elem->rtr = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_RTR_MASK) >> MCANSS_RX_BUFFER_ELEM_RTR_SHIFT); elem->xtd = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_XTD_MASK) >> MCANSS_RX_BUFFER_ELEM_XTD_SHIFT); elem->esi = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_ESI_MASK) >> MCANSS_RX_BUFFER_ELEM_ESI_SHIFT); elemAddr += 4U; regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr)); elem->rxts = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_RXTS_MASK) >> MCANSS_RX_BUFFER_ELEM_RXTS_SHIFT); elem->dlc = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_DLC_MASK) >> MCANSS_RX_BUFFER_ELEM_DLC_SHIFT); elem->brs = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_BRS_MASK) >> MCANSS_RX_BUFFER_ELEM_BRS_SHIFT); elem->fdf = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_FDF_MASK) >> MCANSS_RX_BUFFER_ELEM_FDF_SHIFT); elem->fidx = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_FIDX_MASK) >> MCANSS_RX_BUFFER_ELEM_FIDX_SHIFT); elem->anmf = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_ANMF_MASK) >> MCANSS_RX_BUFFER_ELEM_ANMF_SHIFT); elemAddr += 4U; loopCnt = 0U; /* Reading words from message RAM and forming payload bytes out of it */ while ((4U <= (DL_MCAN_getDataSize(elem->dlc) - loopCnt)) && (0U != (DL_MCAN_getDataSize(elem->dlc) - loopCnt))) { regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr)); elem->data[loopCnt] = (uint16_t)(regVal & 0x000000FFU); elem->data[(loopCnt + 1U)] = (uint16_t)((regVal & 0x0000FF00U) >> 8U); elem->data[(loopCnt + 2U)] = (uint16_t)((regVal & 0x00FF0000U) >> 16U); elem->data[(loopCnt + 3U)] = (uint16_t)((regVal & 0xFF000000U) >> 24U); elemAddr += 4U; loopCnt += 4U; } /* Reading remaining bytes from message RAM */ if (0U < (DL_MCAN_getDataSize(elem->dlc) - loopCnt)) { regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr)); elem->data[loopCnt] = (uint16_t)(regVal & 0x000000FFU); elem->data[(loopCnt + 1U)] = (uint16_t)((regVal & 0x0000FF00U) >> 8U); elem->data[(loopCnt + 2U)] = (uint16_t)((regVal & 0x00FF0000U) >> 16U); } } static void DL_MCAN_writeMsg( uint32_t mcan, uint32_t elemAddr, const DL_MCAN_TxBufElement *elem) { uint32_t regVal = 0, loopCnt = 0U; regVal = 0U; regVal |= (((uint32_t)(elem->id << MCANSS_TX_BUFFER_ELEM_ID_SHIFT)) | ((uint32_t)(elem->rtr << MCANSS_TX_BUFFER_ELEM_RTR_SHIFT)) | ((uint32_t)(elem->xtd << MCANSS_TX_BUFFER_ELEM_XTD_SHIFT)) | ((uint32_t)(elem->esi << MCANSS_TX_BUFFER_ELEM_ESI_SHIFT))); HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal); elemAddr += 4U; regVal = 0U; regVal |= ((uint32_t)(elem->dlc << MCANSS_TX_BUFFER_ELEM_DLC_SHIFT)) | ((uint32_t)(elem->brs << MCANSS_TX_BUFFER_ELEM_BRS_SHIFT)) | ((uint32_t)(elem->fdf << MCANSS_TX_BUFFER_ELEM_FDF_SHIFT)) | ((uint32_t)(elem->efc << MCANSS_TX_BUFFER_ELEM_EFC_SHIFT)) | ((uint32_t)(elem->mm << MCANSS_TX_BUFFER_ELEM_MM_SHIFT)); HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal); elemAddr += 4U; loopCnt = 0U; /* Framing words out of the payload bytes and writing it to message RAM */ while ((4U <= (DL_MCAN_getDataSize(elem->dlc) - loopCnt)) && (0U != (DL_MCAN_getDataSize(elem->dlc) - loopCnt))) { regVal = 0U; regVal |= ((uint32_t) elem->data[loopCnt] | ((uint32_t) elem->data[(loopCnt + 1U)] << 8U) | ((uint32_t) elem->data[(loopCnt + 2U)] << 16U) | ((uint32_t) elem->data[(loopCnt + 3U)] << 24U)); HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal); elemAddr += 4U; loopCnt += 4U; } /* Framing a word out of remaining payload bytes and writing it to * message RAM */ if (0U < (DL_MCAN_getDataSize(elem->dlc) - loopCnt)) { regVal = 0U; regVal |= ((uint32_t) elem->data[loopCnt] | ((uint32_t) elem->data[(loopCnt + 1U)] << 8U) | ((uint32_t) elem->data[(loopCnt + 2U)] << 16U) | ((uint32_t) elem->data[(loopCnt + 3U)] << 24U)); HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal); } } static uint32_t DL_MCAN_getDataSize(uint32_t dlc) { uint32_t dataSize[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64}; return (dataSize[dlc]); } static uint32_t DL_MCAN_getMsgObjSize(uint32_t elemSize) { uint32_t objSize[8] = {4, 5, 6, 7, 8, 10, 14, 18}; return (objSize[elemSize]); } __STATIC_INLINE uint32_t HW_RD_REG32_RAW(uint32_t addr) { uint32_t regVal = *(volatile uint32_t *) addr; return (regVal); } __STATIC_INLINE void HW_WR_REG32_RAW(uint32_t addr, uint32_t value) { *(volatile uint32_t *) addr = value; return; } __STATIC_INLINE void HW_WR_FIELD32_RAW( uint32_t addr, uint32_t mask, uint32_t shift, uint32_t value) { uint32_t regVal = *(volatile uint32_t *) addr; regVal &= (~mask); regVal |= (value << shift) & mask; *(volatile uint32_t *) addr = regVal; return; } __STATIC_INLINE uint32_t HW_RD_FIELD32_RAW( uint32_t addr, uint32_t mask, uint32_t shift) { uint32_t regVal = *(volatile uint32_t *) addr; regVal = (regVal & mask) >> shift; return (regVal); } bool DL_MCAN_saveConfiguration( const MCAN_Regs *mcan, DL_MCAN_backupConfig *ptr) { bool saveState = !ptr->backupRdy; if (saveState) { /* Clock configuration */ ptr->clkDivConf = mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKDIV; ptr->clkConf = mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKCTL; ptr->clkEnConf = mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKEN; /* Interrupt Configuration */ ptr->txBuffTxIntConf = mcan->MCANSS.MCAN.MCAN_TXBTIE; ptr->txBuffCancIntConf = mcan->MCANSS.MCAN.MCAN_TXBCIE; ptr->intLnSelConf = mcan->MCANSS.MCAN.MCAN_ILS; ptr->intLnEnableConf = mcan->MCANSS.MCAN.MCAN_ILE; ptr->ssIntEnConf = mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IE; ptr->intEnConf = mcan->MCANSS.MCAN.MCAN_IE; ptr->intEvnt0Conf = mcan->MCANSS.TI_WRAPPER.MSP.CPU_INT.IMASK; /* MCAN configuration */ ptr->ctrlConf = mcan->MCANSS.MCAN.MCAN_CCCR; ptr->nomBitTimeConf = mcan->MCANSS.MCAN.MCAN_NBTP; ptr->dataBitTimeConf = mcan->MCANSS.MCAN.MCAN_DBTP; ptr->timeCntConf = mcan->MCANSS.MCAN.MCAN_TSCC; ptr->timeCntVal = mcan->MCANSS.MCAN.MCAN_TSCV; ptr->timeOutConf = mcan->MCANSS.MCAN.MCAN_TOCC; ptr->timeOutCntVal = mcan->MCANSS.MCAN.MCAN_TOCV; ptr->txDelCompConf = mcan->MCANSS.MCAN.MCAN_TDCR; ptr->globFiltIDConf = mcan->MCANSS.MCAN.MCAN_GFC; ptr->stdFiltIDConf = mcan->MCANSS.MCAN.MCAN_SIDFC; ptr->exFiltIDConf = mcan->MCANSS.MCAN.MCAN_XIDFC; ptr->exFiltIDMsk = mcan->MCANSS.MCAN.MCAN_XIDAM; ptr->rxFIFO0Conf = mcan->MCANSS.MCAN.MCAN_RXF0C; ptr->rxBuffConf = mcan->MCANSS.MCAN.MCAN_RXBC; ptr->rxFIFO1Conf = mcan->MCANSS.MCAN.MCAN_RXF1C; ptr->rxDataSize = mcan->MCANSS.MCAN.MCAN_RXESC; ptr->txBuffConf = mcan->MCANSS.MCAN.MCAN_TXBC; ptr->txDataSize = mcan->MCANSS.MCAN.MCAN_TXESC; ptr->txEvntFIFOConf = mcan->MCANSS.MCAN.MCAN_TXEFC; ptr->ssCtrlConf = mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL; ptr->preSclConf = mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS .MCANSS_EXT_TS_PRESCALER; ptr->edcVecConf = mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_VECTOR; ptr->edcConf2 = mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL; ptr->edcConf1 = mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_CTRL1; ptr->edcConf0 = mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_CTRL2; ptr->ramWDConf = mcan->MCANSS.MCAN.MCAN_RWD; ptr->testConf = mcan->MCANSS.MCAN.MCAN_TEST; ptr->backupRdy = true; } return saveState; } bool DL_MCAN_restoreConfiguration(MCAN_Regs *mcan, DL_MCAN_backupConfig *ptr) { bool stateRestored = ptr->backupRdy; bool cceState; bool initState; if (stateRestored) { ptr->backupRdy = false; /** * Stores actual state of Configuration Change Enable. CCE will be set * during restore operation and will configure CCE actual state at the * end. */ cceState = ((ptr->ctrlConf & MCAN_CCCR_CCE_MASK) == MCAN_CCCR_CCE_MASK); initState = ((ptr->ctrlConf & MCAN_CCCR_INIT_MASK) == MCAN_CCCR_INIT_MASK); /** * MCAN configuration only overwrittring CCE configuration since INIT * reset value is 0x1. CCE and INIT must be set to 0x1 to allow * reconfiguration of MCAN. */ mcan->MCANSS.MCAN.MCAN_CCCR = (ptr->ctrlConf |= MCAN_CCCR_CCE_MASK); mcan->MCANSS.MCAN.MCAN_NBTP = ptr->nomBitTimeConf; mcan->MCANSS.MCAN.MCAN_DBTP = ptr->dataBitTimeConf; mcan->MCANSS.MCAN.MCAN_TSCC = ptr->timeCntConf; mcan->MCANSS.MCAN.MCAN_TSCV = ptr->timeCntVal; mcan->MCANSS.MCAN.MCAN_TOCC = ptr->timeOutConf; mcan->MCANSS.MCAN.MCAN_TOCV = ptr->timeOutCntVal; mcan->MCANSS.MCAN.MCAN_TDCR = ptr->txDelCompConf; mcan->MCANSS.MCAN.MCAN_GFC = ptr->globFiltIDConf; mcan->MCANSS.MCAN.MCAN_SIDFC = ptr->stdFiltIDConf; mcan->MCANSS.MCAN.MCAN_XIDFC = ptr->exFiltIDConf; mcan->MCANSS.MCAN.MCAN_XIDAM = ptr->exFiltIDMsk; mcan->MCANSS.MCAN.MCAN_RXF0C = ptr->rxFIFO0Conf; mcan->MCANSS.MCAN.MCAN_RXBC = ptr->rxBuffConf; mcan->MCANSS.MCAN.MCAN_RXF1C = ptr->rxFIFO1Conf; mcan->MCANSS.MCAN.MCAN_RXESC = ptr->rxDataSize; mcan->MCANSS.MCAN.MCAN_TXBC = ptr->txBuffConf; mcan->MCANSS.MCAN.MCAN_TXESC = ptr->txDataSize; mcan->MCANSS.MCAN.MCAN_TXEFC = ptr->txEvntFIFOConf; mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL = ptr->ssCtrlConf; mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS .MCANSS_EXT_TS_PRESCALER = ptr->preSclConf; mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_VECTOR = ptr->edcVecConf; mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL = ptr->edcConf2; mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_CTRL1 = ptr->edcConf1; mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_CTRL2 = ptr->edcConf0; mcan->MCANSS.MCAN.MCAN_RWD = ptr->ramWDConf; mcan->MCANSS.MCAN.MCAN_TEST = ptr->testConf; /* Clock configuration */ mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKDIV = ptr->clkDivConf; mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKCTL = ptr->clkConf; mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKEN = ptr->clkEnConf; /* Interrupt Configuration */ mcan->MCANSS.MCAN.MCAN_TXBTIE = ptr->txBuffTxIntConf; mcan->MCANSS.MCAN.MCAN_TXBCIE = ptr->txBuffCancIntConf; mcan->MCANSS.MCAN.MCAN_ILS = ptr->intLnSelConf; mcan->MCANSS.MCAN.MCAN_ILE = ptr->intLnEnableConf; mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IE = ptr->ssIntEnConf; mcan->MCANSS.MCAN.MCAN_IE = ptr->intEnConf; mcan->MCANSS.TI_WRAPPER.MSP.CPU_INT.IMASK = ptr->intEvnt0Conf; /* Restores MCAN configuration change state */ if (false == cceState) { DL_Common_updateReg( &mcan->MCANSS.MCAN.MCAN_CCCR, 0, MCAN_CCCR_CCE_MASK); } else { DL_Common_updateReg(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CCE_MASK, MCAN_CCCR_CCE_MASK); } /* Restores MCAN intialization status */ if (false == initState) { DL_Common_updateReg( &mcan->MCANSS.MCAN.MCAN_CCCR, 0, MCAN_CCCR_INIT_MASK); } else { DL_Common_updateReg(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_INIT_MASK, MCAN_CCCR_INIT_MASK); } } return stateRestored; } #endif /* __MSPM0_HAS_MCAN__ */