/* * Copyright (c) Texas Instruments Incorporated 2016 * * 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. * */ /** * \file mcan.c * * \brief This file contains the implementation of the APIs present in the * device abstraction layer file of MCAN. * This also contains some related macros. */ /* ========================================================================== */ /* Include Files */ /* ========================================================================== */ #include #include "inc/stw_types.h" #include "inc/stw_dataTypes.h" #include "inc/hw_types_mcan.h" #include "mcan.h" #include "debug.h" /* ========================================================================== */ /* 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) /* ========================================================================== */ /* Structures and Enums */ /* ========================================================================== */ /* None */ /* ========================================================================== */ /* Internal Function Declarations */ /* ========================================================================== */ /** * \brief This API will unblock write access to write protected registers. * * \param baseAddr Base Address of the MCAN Registers. * * \return None. */ static void MCAN_writeProtectedRegAccessUnlock(uint32_t baseAddr); /** * \brief This API will block write access to write protected registers. * * \param baseAddr Base Address of the MCAN Registers. * * \return None. */ static void MCAN_writeProtectedRegAccessLock(uint32_t baseAddr); /** * \brief This API will load the register from ECC memory bank. * * \param baseAddr Base Address of the MCAN Registers. * \param regOffset Offset of the register to read. * * \return None. */ static void MCAN_eccLoadRegister(uint32_t baseAddr, uint32_t regOffset); /** * \brief This API will read the message object from Message RAM. * * \param baseAddr Base Address of the MCAN Registers. * \param elemAddr Address of the message object. * \param elem Message Object. * Refer struct #MCAN_RxBufElement. * * \return None. */ static void MCAN_readMsg(uint32_t baseAddr, uint32_t elemAddr, MCAN_RxBufElement *elem); /** * \brief This API will write the message object to Message RAM. * * \param baseAddr 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 MCAN_writeMsg(uint32_t baseAddr, uint32_t elemAddr, const 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 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 MCAN_getMsgObjSize(uint32_t elemSize); /* ========================================================================== */ /* Global Variables */ /* ========================================================================== */ /* None */ /* ========================================================================== */ /* Function Definitions */ /* ========================================================================== */ uint32_t MCAN_isInReset(uint32_t baseAddr) { uint32_t reset; uint32_t state; reset = HW_RD_FIELD32(baseAddr + MCAN_MCANSS_STAT, MCAN_MCANSS_STAT_RESET); if(1U == reset) { state = (uint32_t) TRUE; } else { state = (uint32_t) FALSE; } return state; } uint32_t MCAN_isFDOpEnable(uint32_t baseAddr) { uint32_t fdoe; uint32_t state; fdoe = HW_RD_FIELD32(baseAddr + MCAN_MCANSS_STAT, MCAN_MCANSS_STAT_ENABLE_FDOE); if(1U == fdoe) { state = (uint32_t) TRUE; } else { state = (uint32_t) FALSE; } return state; } uint32_t MCAN_isMemInitDone(uint32_t baseAddr) { uint32_t memInit; uint32_t state; memInit = HW_RD_FIELD32(baseAddr + MCAN_MCANSS_STAT, MCAN_MCANSS_STAT_MEM_INIT_DONE); if(1U == memInit) { state = (uint32_t) TRUE; } else { state = (uint32_t) FALSE; } return state; } void MCAN_setOpMode(uint32_t baseAddr, uint32_t mode) { HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_INIT, mode); } uint32_t MCAN_getOpMode(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_INIT)); } int32_t MCAN_init(uint32_t baseAddr, const MCAN_InitParams *initParams) { int32_t status; uint32_t regVal; /* Configure MCAN wakeup and clock stop controls */ regVal = HW_RD_REG32(baseAddr + MCAN_MCANSS_CTRL); HW_SET_FIELD32(regVal, MCAN_MCANSS_CTRL_WAKEUPREQEN, initParams->wkupReqEnable); HW_SET_FIELD32(regVal, MCAN_MCANSS_CTRL_AUTOWAKEUP, initParams->autoWkupEnable); HW_SET_FIELD32(regVal, MCAN_MCANSS_CTRL_EMUEN, initParams->emulationEnable); HW_WR_REG32(baseAddr + MCAN_MCANSS_CTRL, regVal); MCAN_writeProtectedRegAccessUnlock(baseAddr); /* Configure MCAN mode(FD vs Classic CAN operation) and controls */ regVal = HW_RD_REG32(baseAddr + 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(baseAddr + MCAN_CCCR, regVal); if((MCAN_TDCR_TDCF_MAX >= initParams->tdcConfig.tdcf) && (MCAN_TDCR_TDCO_MAX >= initParams->tdcConfig.tdco) && (MCAN_RWD_WDC_MAX >= initParams->wdcPreload)) { /* Configure Transceiver Delay Compensation */ HW_WR_FIELD32(baseAddr + MCAN_TDCR, MCAN_TDCR_TDCF, initParams->tdcConfig.tdcf); HW_WR_FIELD32(baseAddr + MCAN_TDCR, MCAN_TDCR_TDCO, initParams->tdcConfig.tdco); /* Configure MSG RAM watchdog counter preload value */ HW_WR_FIELD32(baseAddr + MCAN_RWD, MCAN_RWD_WDC, initParams->wdcPreload); /* Enable/Disable Transceiver Delay Compensation */ HW_WR_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_TDC, initParams->tdcEnable); status = STW_SOK; } else { status = STW_EFAIL; } MCAN_writeProtectedRegAccessLock(baseAddr); return status; } int32_t MCAN_config(uint32_t baseAddr, const MCAN_ConfigParams *configParams) { int32_t status; MCAN_writeProtectedRegAccessUnlock(baseAddr); /* Configure MCAN control registers */ HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_MON, configParams->monEnable); HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_ASM, configParams->asmEnable); /* Configure Global Filter */ HW_WR_FIELD32(baseAddr + MCAN_GFC, MCAN_GFC_RRFE, configParams->filterConfig.rrfe); HW_WR_FIELD32(baseAddr + MCAN_GFC, MCAN_GFC_RRFS, configParams->filterConfig.rrfs); HW_WR_FIELD32(baseAddr + MCAN_GFC, MCAN_GFC_ANFE, configParams->filterConfig.anfe); HW_WR_FIELD32(baseAddr + MCAN_GFC, MCAN_GFC_ANFS, configParams->filterConfig.anfs); if((MCAN_TSCC_TCP_MAX >= configParams->tsPrescalar) && (MCAN_TOCC_TOP_MAX >= configParams->timeoutPreload)) { /* Configure Time-stamp counter */ HW_WR_FIELD32(baseAddr + MCAN_TSCC, MCAN_TSCC_TSS, configParams->tsSelect); HW_WR_FIELD32(baseAddr + MCAN_TSCC, MCAN_TSCC_TCP, (configParams->tsPrescalar - 1U)); /* Configure Time-out counter */ HW_WR_FIELD32(baseAddr + MCAN_TOCC, MCAN_TOCC_TOS, configParams->timeoutSelect); HW_WR_FIELD32(baseAddr + MCAN_TOCC, MCAN_TOCC_TOP, configParams->timeoutPreload); /* Enable Time-out counter */ HW_WR_FIELD32(baseAddr + MCAN_TOCC, MCAN_TOCC_ETOC, configParams->timeoutCntEnable); status = STW_SOK; } else { status = STW_EFAIL; } MCAN_writeProtectedRegAccessLock(baseAddr); return status; } void MCAN_eccConfig(uint32_t baseAddr, const MCAN_ECCConfigParams *configParams) { MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_CONTROL); HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_CONTROL, MCAN_ECC_AGGR_CONTROL_ECC_CHECK, configParams->enableChk); MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_CONTROL); HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_CONTROL, MCAN_ECC_AGGR_CONTROL_ECC_ENABLE, configParams->enable); MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_CONTROL); HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_CONTROL, MCAN_ECC_AGGR_CONTROL_ENABLE_RMW, configParams->enableRdModWr); MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_CONTROL); } int32_t MCAN_setBitTime(uint32_t baseAddr, const MCAN_BitTimingParams *configParams) { int32_t status; MCAN_writeProtectedRegAccessUnlock(baseAddr); if((MCAN_NBTP_NSJW_MAX >= configParams->nomSynchJumpWidth) && (MCAN_NBTP_NTSEG2_MAX >= configParams->nomTimeSeg2) && (MCAN_NBTP_NTSEG1_MAX >= configParams->nomTimeSeg1) && (MCAN_NBTP_NBRP_MAX >= configParams->nomRatePrescalar)) { HW_WR_FIELD32(baseAddr + MCAN_NBTP, MCAN_NBTP_NSJW, configParams->nomSynchJumpWidth); HW_WR_FIELD32(baseAddr + MCAN_NBTP, MCAN_NBTP_NTSEG2, configParams->nomTimeSeg2); HW_WR_FIELD32(baseAddr + MCAN_NBTP, MCAN_NBTP_NTSEG1, configParams->nomTimeSeg1); HW_WR_FIELD32(baseAddr + MCAN_NBTP, MCAN_NBTP_NBRP, configParams->nomRatePrescalar); status = STW_SOK; } else { status = STW_EFAIL; } if(STW_SOK == status) { if((MCAN_DBTP_DSJW_MAX >= configParams->dataSynchJumpWidth) && (MCAN_DBTP_DTSEG2_MAX >= configParams->dataTimeSeg2) && (MCAN_DBTP_DTSEG1_MAX >= configParams->dataTimeSeg1) && (MCAN_DBTP_DBRP_MAX >= configParams->dataRatePrescalar)) { HW_WR_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_DSJW, configParams->dataSynchJumpWidth); HW_WR_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_DTSEG2, configParams->dataTimeSeg2); HW_WR_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_DTSEG1, configParams->dataTimeSeg1); HW_WR_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_DBRP, configParams->dataRatePrescalar); status = STW_SOK; } else { status = STW_EFAIL; } } MCAN_writeProtectedRegAccessLock(baseAddr); return status; } int32_t MCAN_msgRAMConfig(uint32_t baseAddr, const MCAN_MsgRAMConfigParams *msgRAMConfigParams) { int32_t status; uint32_t elemNum = 0U; MCAN_writeProtectedRegAccessUnlock(baseAddr); /* Configure Message Filters section */ if(0U != msgRAMConfigParams->lss) { HW_WR_FIELD32(baseAddr + MCAN_SIDFC, MCAN_SIDFC_FLSSA, (msgRAMConfigParams->flssa >> 2U)); HW_WR_FIELD32(baseAddr + MCAN_SIDFC, MCAN_SIDFC_LSS, msgRAMConfigParams->lss); } if(0U != msgRAMConfigParams->lse) { HW_WR_FIELD32(baseAddr + MCAN_XIDFC, MCAN_XIDFC_FLESA, (msgRAMConfigParams->flesa >> 2U)); HW_WR_FIELD32(baseAddr + MCAN_XIDFC, MCAN_XIDFC_LSE, msgRAMConfigParams->lse); } /* Configure Rx FIFO 0 section */ if(0U != msgRAMConfigParams->rxFIFO0size) { HW_WR_FIELD32(baseAddr + MCAN_RXF0C, MCAN_RXF0C_F0SA, (msgRAMConfigParams->rxFIFO0startAddr >> 2U)); HW_WR_FIELD32(baseAddr + MCAN_RXF0C, MCAN_RXF0C_F0S, msgRAMConfigParams->rxFIFO0size); HW_WR_FIELD32(baseAddr + MCAN_RXF0C, MCAN_RXF0C_F0WM, msgRAMConfigParams->rxFIFO0waterMark); HW_WR_FIELD32(baseAddr + MCAN_RXF0C, MCAN_RXF0C_F0OM, msgRAMConfigParams->rxFIFO0OpMode); /* Configure Rx FIFO0 elements size */ HW_WR_FIELD32(baseAddr + MCAN_RXESC, MCAN_RXESC_F0DS, msgRAMConfigParams->rxFIFO0ElemSize); } /* Configure Rx FIFO 1 section */ if(0U != msgRAMConfigParams->rxFIFO1size) { HW_WR_FIELD32(baseAddr + MCAN_RXF1C, MCAN_RXF1C_F1SA, (msgRAMConfigParams->rxFIFO1startAddr >> 2U)); HW_WR_FIELD32(baseAddr + MCAN_RXF1C, MCAN_RXF1C_F1S, msgRAMConfigParams->rxFIFO1size); HW_WR_FIELD32(baseAddr + MCAN_RXF1C, MCAN_RXF1C_F1WM, msgRAMConfigParams->rxFIFO1waterMark); HW_WR_FIELD32(baseAddr + MCAN_RXF1C, MCAN_RXF1C_F1OM, msgRAMConfigParams->rxFIFO1OpMode); /* Configure Rx FIFO1 elements size */ HW_WR_FIELD32(baseAddr + MCAN_RXESC, MCAN_RXESC_F1DS, msgRAMConfigParams->rxFIFO1ElemSize); } /* Configure Rx Buffer Start Address */ HW_WR_FIELD32(baseAddr + MCAN_RXBC, MCAN_RXBC_RBSA, (msgRAMConfigParams->rxBufStartAddr >> 2U)); /* Configure Rx Buffer elements size */ HW_WR_FIELD32(baseAddr + MCAN_RXESC, MCAN_RXESC_RBDS, msgRAMConfigParams->rxBufElemSize); /* Configure Tx Event FIFO section */ if(0U != msgRAMConfigParams->txEventFIFOSize) { HW_WR_FIELD32(baseAddr + MCAN_TXEFC, MCAN_TXEFC_EFSA, (msgRAMConfigParams->txEventFIFOStartAddr >> 2U)); HW_WR_FIELD32(baseAddr + MCAN_TXEFC, MCAN_TXEFC_EFS, msgRAMConfigParams->txEventFIFOSize); HW_WR_FIELD32(baseAddr + 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(baseAddr + MCAN_TXBC, MCAN_TXBC_TBSA, (msgRAMConfigParams->txStartAddr >> 2U)); HW_WR_FIELD32(baseAddr + MCAN_TXBC, MCAN_TXBC_NDTB, msgRAMConfigParams->txBufNum); HW_WR_FIELD32(baseAddr + MCAN_TXBC, MCAN_TXBC_TFQS, msgRAMConfigParams->txFIFOSize); HW_WR_FIELD32(baseAddr + MCAN_TXBC, MCAN_TXBC_TFQM, msgRAMConfigParams->txBufMode); /* Configure Tx Buffer/FIFO0/FIFO1 elements size */ HW_WR_FIELD32(baseAddr + MCAN_TXESC, MCAN_TXESC_TBDS, msgRAMConfigParams->txBufElemSize); status = STW_SOK; } else { status = STW_EFAIL; } MCAN_writeProtectedRegAccessLock(baseAddr); return status; } int32_t MCAN_setExtIDAndMask(uint32_t baseAddr, uint32_t idMask) { int32_t status; if(MCAN_XIDAM_EIDM_MAX >= idMask) { MCAN_writeProtectedRegAccessUnlock(baseAddr); HW_WR_FIELD32(baseAddr + MCAN_XIDAM, MCAN_XIDAM_EIDM, idMask); MCAN_writeProtectedRegAccessLock(baseAddr); status = STW_SOK; } else { status = STW_EFAIL; } return status; } void MCAN_writeMsgRam(uint32_t baseAddr, uint32_t memType, uint32_t bufNum, const MCAN_TxBufElement *elem) { uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U; uint32_t idx = 0U, enableMod = 0U; if(MCAN_MEM_TYPE_BUF == memType) { idx = bufNum; enableMod = 1U; } if(MCAN_MEM_TYPE_FIFO == memType) { idx = HW_RD_FIELD32(baseAddr + MCAN_TXFQS, MCAN_TXFQS_TFQPI); enableMod = 1U; } if(1U == enableMod) { startAddr = HW_RD_FIELD32(baseAddr + MCAN_TXBC, MCAN_TXBC_TBSA); elemSize = HW_RD_FIELD32(baseAddr + MCAN_TXESC, MCAN_TXESC_TBDS); startAddr = (uint32_t) (startAddr << 2U); elemSize = MCAN_getMsgObjSize(elemSize); elemSize *= 4U; elemAddr = startAddr + (elemSize * idx); elemAddr += MCAN_MCAN_MSG_MEM; MCAN_writeMsg(baseAddr, elemAddr, elem); } } int32_t MCAN_txBufAddReq(uint32_t baseAddr, uint32_t bufNum) { int32_t status; uint32_t regVal; if(MCANSS_TX_BUFFER_MAX > bufNum) { regVal = HW_RD_REG32(baseAddr + 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. MCAN_writeProtectedRegAccessLock(baseAddr); HW_WR_REG32(baseAddr + MCAN_TXBAR, regVal); status = STW_SOK; } else { status = STW_EFAIL; } return status; } void MCAN_getNewDataStatus(uint32_t baseAddr, MCAN_RxNewDataStatus *newDataStatus) { newDataStatus->statusLow = HW_RD_REG32(baseAddr + MCAN_NDAT1); newDataStatus->statusHigh = HW_RD_REG32(baseAddr + MCAN_NDAT2); } void MCAN_clearNewDataStatus(uint32_t baseAddr, const MCAN_RxNewDataStatus *newDataStatus) { HW_WR_REG32(baseAddr + MCAN_NDAT1, newDataStatus->statusLow); HW_WR_REG32(baseAddr + MCAN_NDAT2, newDataStatus->statusHigh); } void MCAN_readMsgRam(uint32_t baseAddr, uint32_t memType, uint32_t bufNum, uint32_t fifoNum, MCAN_RxBufElement *elem) { uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U; uint32_t enableMod = 0U, idx = 0U; if(MCAN_MEM_TYPE_BUF == memType) { startAddr = HW_RD_FIELD32(baseAddr + MCAN_RXBC, MCAN_RXBC_RBSA); elemSize = HW_RD_FIELD32(baseAddr + MCAN_RXESC, MCAN_RXESC_RBDS); idx = bufNum; enableMod = 1U; } if(MCAN_MEM_TYPE_FIFO == memType) { switch (fifoNum) { case MCAN_RX_FIFO_NUM_0: startAddr = HW_RD_FIELD32(baseAddr + MCAN_RXF0C, MCAN_RXF0C_F0SA); elemSize = HW_RD_FIELD32(baseAddr + MCAN_RXESC, MCAN_RXESC_F0DS); idx = HW_RD_FIELD32(baseAddr + MCAN_RXF0S, MCAN_RXF0S_F0GI); enableMod = 1U; break; case MCAN_RX_FIFO_NUM_1: startAddr = HW_RD_FIELD32(baseAddr + MCAN_RXF1C, MCAN_RXF1C_F1SA); elemSize = HW_RD_FIELD32(baseAddr + MCAN_RXESC, MCAN_RXESC_F1DS); idx = HW_RD_FIELD32(baseAddr + MCAN_RXF1S, MCAN_RXF1S_F1GI); enableMod = 1U; break; default: /* Invalid option */ break; } } if(1U == enableMod) { startAddr = (uint32_t) (startAddr << 2U); elemSize = MCAN_getMsgObjSize(elemSize); elemSize *= 4U; elemAddr = startAddr + (elemSize * idx); elemAddr += MCAN_MCAN_MSG_MEM; MCAN_readMsg(baseAddr, elemAddr, elem); } } void MCAN_readTxEventFIFO(uint32_t baseAddr, MCAN_TxEventFIFOElement *txEventElem) { uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U; uint32_t idx = 0U, regVal; startAddr = HW_RD_FIELD32(baseAddr + MCAN_TXEFC, MCAN_TXEFC_EFSA); elemSize = MCANSS_TX_EVENT_FIFO_SIZE_WORDS; idx = HW_RD_FIELD32(baseAddr + 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(baseAddr + 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(baseAddr + 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 MCAN_addStdMsgIDFilter(uint32_t baseAddr, uint32_t filtNum, const MCAN_StdMsgIDFilterElement *elem) { uint32_t startAddr, elemAddr, regVal; startAddr = HW_RD_FIELD32(baseAddr + 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(baseAddr + elemAddr, regVal); } void MCAN_addExtMsgIDFilter(uint32_t baseAddr, uint32_t filtNum, const MCAN_ExtMsgIDFilterElement *elem) { uint32_t startAddr, elemAddr, regVal; startAddr = HW_RD_FIELD32(baseAddr + 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(baseAddr + 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(baseAddr + elemAddr, regVal); } void MCAN_lpbkModeEnable(uint32_t baseAddr, uint32_t lpbkMode, uint32_t enable) { MCAN_writeProtectedRegAccessUnlock(baseAddr); if(TRUE == enable) { HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_TEST, 0x1U); HW_WR_FIELD32(baseAddr + MCAN_TEST, MCAN_TEST_LBCK, enable); if(MCAN_LPBK_MODE_INTERNAL == lpbkMode) { HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_MON, 0x1U); } } else { HW_WR_FIELD32(baseAddr + MCAN_TEST, MCAN_TEST_LBCK, enable); HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_TEST, 0x0U); if(MCAN_LPBK_MODE_INTERNAL == lpbkMode) { HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_MON, 0x0U); } } MCAN_writeProtectedRegAccessLock(baseAddr); } void MCAN_getErrCounters(uint32_t baseAddr, MCAN_ErrCntStatus *errCounter) { errCounter->transErrLogCnt = HW_RD_FIELD32(baseAddr + MCAN_ECR, MCAN_ECR_TEC); errCounter->recErrCnt = HW_RD_FIELD32(baseAddr + MCAN_ECR, MCAN_ECR_REC); errCounter->rpStatus = HW_RD_FIELD32(baseAddr + MCAN_ECR, MCAN_ECR_RP); errCounter->canErrLogCnt = HW_RD_FIELD32(baseAddr + MCAN_ECR, MCAN_ECR_CEL); } void MCAN_getProtocolStatus(uint32_t baseAddr, MCAN_ProtocolStatus *protStatus) { uint32_t regVal; regVal = HW_RD_REG32(baseAddr + 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 MCAN_enableIntr(uint32_t baseAddr, uint32_t intrMask, uint32_t enable) { uint32_t regVal; if(TRUE == enable) { regVal = HW_RD_REG32(baseAddr + MCAN_IE); regVal |= intrMask; HW_WR_REG32(baseAddr + MCAN_IE, regVal); } else { regVal = HW_RD_REG32(baseAddr + MCAN_IE); regVal &= ~intrMask; HW_WR_REG32(baseAddr + MCAN_IE, regVal); } } void MCAN_selectIntrLine(uint32_t baseAddr, uint32_t intrMask, uint32_t lineNum) { uint32_t regVal; if(MCAN_INTR_LINE_NUM_0 == lineNum) { regVal = HW_RD_REG32(baseAddr + MCAN_ILS); regVal &= ~intrMask; HW_WR_REG32(baseAddr + MCAN_ILS, regVal); } else { regVal = HW_RD_REG32(baseAddr + MCAN_ILS); regVal |= intrMask; HW_WR_REG32(baseAddr + MCAN_ILS, regVal); } } uint32_t MCAN_getIntrLineSelectStatus(uint32_t baseAddr) { return(HW_RD_REG32(baseAddr + MCAN_ILS)); } void MCAN_enableIntrLine(uint32_t baseAddr, uint32_t lineNum, uint32_t enable) { uint32_t regVal; lineNum &= MCANSS_INTR_LINE_EN_MASK; regVal = HW_RD_REG32(baseAddr + MCAN_ILE); regVal &= ~((uint32_t) 0x1U << lineNum); regVal |= (uint32_t) (enable << lineNum); HW_WR_REG32(baseAddr + MCAN_ILE, regVal); } uint32_t MCAN_getIntrStatus(uint32_t baseAddr) { return(HW_RD_REG32(baseAddr + MCAN_IR)); } void MCAN_clearIntrStatus(uint32_t baseAddr, uint32_t intrMask) { HW_WR_REG32(baseAddr + MCAN_IR, intrMask); } void MCAN_getHighPriorityMsgStatus(uint32_t baseAddr, MCAN_HighPriorityMsgInfo *hpm) { hpm->bufIdx = HW_RD_FIELD32(baseAddr + MCAN_HPMS, MCAN_HPMS_BIDX); hpm->msi = HW_RD_FIELD32(baseAddr + MCAN_HPMS, MCAN_HPMS_MSI); hpm->filterIdx = HW_RD_FIELD32(baseAddr + MCAN_HPMS, MCAN_HPMS_FIDX); hpm->filterList = HW_RD_FIELD32(baseAddr + MCAN_HPMS, MCAN_HPMS_FLST); } void MCAN_getRxFIFOStatus(uint32_t baseAddr, MCAN_RxFIFOStatus *fifoStatus) { uint32_t regVal; switch (fifoStatus->num) { case MCAN_RX_FIFO_NUM_0: regVal = HW_RD_REG32(baseAddr + 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 MCAN_RX_FIFO_NUM_1: regVal = HW_RD_REG32(baseAddr + 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 MCAN_writeRxFIFOAck(uint32_t baseAddr, uint32_t fifoNum, uint32_t idx) { int32_t status; uint32_t size; switch (fifoNum) { case MCAN_RX_FIFO_NUM_0: size = HW_RD_FIELD32(baseAddr + MCAN_RXF0C, MCAN_RXF0C_F0S); if(size >= idx) { HW_WR_FIELD32(baseAddr + MCAN_RXF0A, MCAN_RXF0A_F0AI, idx); status = STW_SOK; } else { status = STW_EFAIL; } break; case MCAN_RX_FIFO_NUM_1: size = HW_RD_FIELD32(baseAddr + MCAN_RXF1C, MCAN_RXF1C_F1S); if(size >= idx) { HW_WR_FIELD32(baseAddr + MCAN_RXF1A, MCAN_RXF1A_F1AI, idx); status = STW_SOK; } else { status = STW_EFAIL; } break; default: status = STW_EFAIL; break; } return status; } void MCAN_getTxFIFOQueStatus(uint32_t baseAddr, MCAN_TxFIFOStatus *fifoStatus) { uint32_t regVal; regVal = HW_RD_REG32(baseAddr + 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_TFQPI); fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_TXFQS_TFQF); } uint32_t MCAN_getTxBufReqPend(uint32_t baseAddr) { return(HW_RD_REG32(baseAddr + MCAN_TXBRP)); } int32_t MCAN_txBufCancellationReq(uint32_t baseAddr, uint32_t buffNum) { int32_t status; uint32_t regVal; if(MCANSS_TX_BUFFER_MAX > buffNum) { regVal = HW_RD_REG32(baseAddr + 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. MCAN_writeProtectedRegAccessLock(baseAddr); HW_WR_REG32(baseAddr + MCAN_TXBCR, regVal); status = STW_SOK; } else { status = STW_EFAIL; } return status; } uint32_t MCAN_getTxBufTransmissionStatus(uint32_t baseAddr) { return(HW_RD_REG32(baseAddr + MCAN_TXBTO)); } uint32_t MCAN_txBufCancellationStatus(uint32_t baseAddr) { return(HW_RD_REG32(baseAddr + MCAN_TXBCF)); } int32_t MCAN_txBufTransIntrEnable(uint32_t baseAddr, uint32_t bufNum, uint32_t enable) { int32_t status; uint32_t regVal; if(MCANSS_TX_BUFFER_MAX > bufNum) { if(TRUE == enable) { regVal = HW_RD_REG32(baseAddr + MCAN_TXBTIE); regVal |= ((uint32_t) 1U << bufNum); HW_WR_REG32(baseAddr + MCAN_TXBTIE, regVal); } else { regVal = HW_RD_REG32(baseAddr + MCAN_TXBTIE); regVal &= ~((uint32_t) 0x1U << bufNum); HW_WR_REG32(baseAddr + MCAN_TXBTIE, regVal); } status = STW_SOK; } else { status = STW_EFAIL; } return status; } int32_t MCAN_getTxBufCancellationIntrEnable(uint32_t baseAddr, uint32_t bufNum, uint32_t enable) { int32_t status; uint32_t regVal; if(MCANSS_TX_BUFFER_MAX > bufNum) { if(TRUE == enable) { regVal = HW_RD_REG32(baseAddr + MCAN_TXBCIE); regVal |= ((uint32_t) 0x1U << bufNum); HW_WR_REG32(baseAddr + MCAN_TXBCIE, regVal); } else { regVal = HW_RD_REG32(baseAddr + MCAN_TXBCIE); regVal &= ~((uint32_t) 0x1U << bufNum); HW_WR_REG32(baseAddr + MCAN_TXBCIE, regVal); } status = STW_SOK; } else { status = STW_EFAIL; } return status; } void MCAN_getTxEventFIFOStatus(uint32_t baseAddr, MCAN_TxEventFIFOStatus *fifoStatus) { uint32_t regVal; regVal = HW_RD_REG32(baseAddr + 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 MCAN_addClockStopRequest(uint32_t baseAddr, uint32_t enable) { if(TRUE == enable) { HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CSR, 0x1U); } else { HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CSR, 0x0U); } } int32_t MCAN_writeTxEventFIFOAck(uint32_t baseAddr, uint32_t idx) { int32_t status; uint32_t size; size = HW_RD_FIELD32(baseAddr + MCAN_TXEFC, MCAN_TXEFC_EFS); if(size >= idx) { HW_WR_FIELD32(baseAddr + MCAN_TXEFA, MCAN_TXEFA_EFAI, idx); status = STW_SOK; } else { status = STW_EFAIL; } return status; } void MCAN_eccForceError(uint32_t baseAddr, const MCAN_ECCErrForceParams *eccErr) { uint32_t regVal; if((eccErr->errType == MCAN_ECC_ERR_TYPE_SEC) || (eccErr->errType == MCAN_ECC_ERR_TYPE_DED)) { MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_ERROR_CTRL1); regVal = HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_ERROR_CTRL1); HW_SET_FIELD32(regVal, MCAN_ECC_AGGR_ERROR_CTRL1_ECC_ROW, eccErr->rowNum); HW_WR_REG32(baseAddr + MCAN_ECC_AGGR_ERROR_CTRL1, regVal); MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_ERROR_CTRL2); regVal = HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_ERROR_CTRL2); HW_SET_FIELD32(regVal, MCAN_ECC_AGGR_ERROR_CTRL2_ECC_BIT1, eccErr->bit1); HW_SET_FIELD32(regVal, MCAN_ECC_AGGR_ERROR_CTRL2_ECC_BIT2, eccErr->bit2); HW_WR_REG32(baseAddr + MCAN_ECC_AGGR_ERROR_CTRL2, regVal); MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_CONTROL); regVal = HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_CONTROL); HW_SET_FIELD32(regVal, MCAN_ECC_AGGR_CONTROL_FORCE_N_ROW, eccErr->errForce); HW_SET_FIELD32(regVal, MCAN_ECC_AGGR_CONTROL_ERROR_ONCE, eccErr->errOnce); if(eccErr->errType == MCAN_ECC_ERR_TYPE_SEC) { HW_SET_FIELD32(regVal, MCAN_ECC_AGGR_CONTROL_FORCE_SEC, 0x1U); } else if(eccErr->errType == MCAN_ECC_ERR_TYPE_DED) { HW_SET_FIELD32(regVal, MCAN_ECC_AGGR_CONTROL_FORCE_DED, 0x1U); } else { /* MISRA C Compliance */ } HW_WR_REG32(baseAddr + MCAN_ECC_AGGR_CONTROL, regVal); MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_CONTROL); } } void MCAN_eccGetErrorStatus(uint32_t baseAddr, MCAN_ECCErrStatus *eccErr) { uint32_t regVal; MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_ERROR_STATUS1); regVal = HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_ERROR_STATUS1); eccErr->secErr = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_ERROR_STATUS1_ECC_SEC); eccErr->dedErr = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_ERROR_STATUS1_ECC_DED); eccErr->bit1 = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_ERROR_STATUS1_ECC_BIT1); MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_ERROR_STATUS2); regVal = HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_ERROR_STATUS2); eccErr->row = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_ERROR_STATUS2_ECC_ROW); } void MCAN_eccClearErrorStatus(uint32_t baseAddr, uint32_t errType) { MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_ERROR_STATUS1); switch (errType) { case MCAN_ECC_ERR_TYPE_SEC: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_ERROR_STATUS1, MCAN_ECC_AGGR_ERROR_STATUS1_CLR_ECC_SEC, 0x1U); break; case MCAN_ECC_ERR_TYPE_DED: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_ERROR_STATUS1, MCAN_ECC_AGGR_ERROR_STATUS1_CLR_ECC_DED, 0x1U); break; default: /* Invalid option */ break; } MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_ERROR_STATUS1); } void MCAN_eccWriteEOI(uint32_t baseAddr, uint32_t errType) { switch (errType) { case MCAN_ECC_ERR_TYPE_SEC: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_EOI_REG, MCAN_ECC_AGGR_SEC_EOI_REG_WR, 0x1U); break; case MCAN_ECC_ERR_TYPE_DED: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_EOI_REG, MCAN_ECC_AGGR_DED_EOI_REG_WR, 0x1U); break; default: /* Invalid option */ break; } } void MCAN_eccEnableIntr(uint32_t baseAddr, uint32_t errType, uint32_t enable) { if(TRUE == enable) { switch (errType) { case MCAN_ECC_ERR_TYPE_SEC: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_ENABLE_SET_REG0, MCAN_ECC_AGGR_SEC_ENABLE_SET_REG0_MSGMEM, 0x1U); break; case MCAN_ECC_ERR_TYPE_DED: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_ENABLE_SET_REG0, MCAN_ECC_AGGR_DED_ENABLE_SET_REG0_MSGMEM, 0x1U); break; default: /* Invalid option */ break; } } else { switch (errType) { case MCAN_ECC_ERR_TYPE_SEC: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_ENABLE_CLR_REG0, MCAN_ECC_AGGR_SEC_ENABLE_CLR_REG0_MSGMEM, 0x1U); break; case MCAN_ECC_ERR_TYPE_DED: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_ENABLE_CLR_REG0, MCAN_ECC_AGGR_DED_ENABLE_CLR_REG0_MSGMEM, 0x1U); break; default: /* Invalid option */ break; } } } uint32_t MCAN_eccGetIntrStatus(uint32_t baseAddr, uint32_t errType) { uint32_t retVal = 0U; switch (errType) { case MCAN_ECC_ERR_TYPE_SEC: retVal = HW_RD_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_STATUS_REG0, MCAN_ECC_AGGR_SEC_STATUS_REG0_MSGMEM_PEND); break; case MCAN_ECC_ERR_TYPE_DED: retVal = HW_RD_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_STATUS_REG0, MCAN_ECC_AGGR_DED_STATUS_REG0_MSGMEM_PEND); break; default: retVal = 0U; break; } return retVal; } void MCAN_eccClearIntrStatus(uint32_t baseAddr, uint32_t errType) { switch (errType) { case MCAN_ECC_ERR_TYPE_SEC: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_STATUS_REG0, MCAN_ECC_AGGR_SEC_STATUS_REG0_MSGMEM_PEND, 0x1U); break; case MCAN_ECC_ERR_TYPE_DED: HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_STATUS_REG0, MCAN_ECC_AGGR_DED_STATUS_REG0_MSGMEM_PEND, 0x1U); break; default: break; } } void MCAN_extTSCounterConfig(uint32_t baseAddr, uint32_t prescalar) { HW_WR_FIELD32(baseAddr + MCAN_MCANSS_EXT_TS_PRESCALER, MCAN_MCANSS_EXT_TS_PRESCALER, prescalar); } void MCAN_extTSCounterEnable(uint32_t baseAddr, uint32_t enable) { HW_WR_FIELD32(baseAddr + MCAN_MCANSS_CTRL, MCAN_MCANSS_CTRL_EXT_TS_CNTR_EN, enable); } void MCAN_extTSEnableIntr(uint32_t baseAddr, uint32_t enable) { if(TRUE == enable) { HW_WR_FIELD32(baseAddr + MCAN_MCANSS_IE, MCAN_MCANSS_IE_EXT_TS_CNTR_OVFL, 1U); } else { HW_WR_FIELD32(baseAddr + MCAN_MCANSS_IECS, MCAN_MCANSS_IECS_EXT_TS_CNTR_OVFL, 1U); } } void MCAN_extTSWriteEOI(uint32_t baseAddr) { HW_WR_FIELD32(baseAddr + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, 0x1U); } uint32_t MCAN_extTSGetUnservicedIntrCount(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_MCANSS_EXT_TS_UNSERVICED_INTR_CNTR, MCAN_MCANSS_EXT_TS_UNSERVICED_INTR_CNTR)); } /* ========================================================================== */ /* Advance Functions */ /* ========================================================================== */ void MCAN_getRevisionId(uint32_t baseAddr, MCAN_RevisionId *revId) { uint32_t regVal; regVal = HW_RD_REG32(baseAddr + MCAN_MCANSS_PID); revId->minor = HW_GET_FIELD(regVal, MCAN_MCANSS_PID_MINOR); revId->custom = HW_GET_FIELD(regVal, MCAN_MCANSS_PID_CUSTOM); revId->major = HW_GET_FIELD(regVal, MCAN_MCANSS_PID_MAJOR); revId->rtlRev = HW_GET_FIELD(regVal, MCAN_MCANSS_PID_RTL); revId->modId = HW_GET_FIELD(regVal, MCAN_MCANSS_PID_MODULE_ID); revId->bu = HW_GET_FIELD(regVal, MCAN_MCANSS_PID_BU); revId->scheme = HW_GET_FIELD(regVal, MCAN_MCANSS_PID_SCHEME); regVal = HW_RD_REG32(baseAddr + 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 MCAN_getClockStopAck(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CSR)); } void MCAN_extTSSetRawStatus(uint32_t baseAddr) { HW_WR_FIELD32(baseAddr + MCAN_MCANSS_IRS, MCAN_MCANSS_IRS_EXT_TS_CNTR_OVFL, 1U); } void MCAN_extTSClearRawStatus(uint32_t baseAddr) { HW_WR_FIELD32(baseAddr + MCAN_MCANSS_ICS, MCAN_MCANSS_ICS_EXT_TS_CNTR_OVFL, 1U); } uint32_t MCAN_getRxPinState(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_TEST, MCAN_TEST_RX)); } void MCAN_setTxPinState(uint32_t baseAddr, uint32_t state) { MCAN_writeProtectedRegAccessUnlock(baseAddr); HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_TEST, 0x1U); HW_WR_FIELD32(baseAddr + MCAN_TEST, MCAN_TEST_TX, state); MCAN_writeProtectedRegAccessLock(baseAddr); } uint32_t MCAN_getTxPinState(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_TEST, MCAN_TEST_TX)); } uint32_t MCAN_getTSCounterVal(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_TSCV, MCAN_TSCV_TSC)); } uint32_t MCAN_getClkStopAck(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CSA)); } void MCAN_getBitTime(uint32_t baseAddr, MCAN_BitTimingParams *configParams) { configParams->nomSynchJumpWidth = HW_RD_FIELD32(baseAddr + MCAN_NBTP, MCAN_NBTP_NSJW); configParams->nomTimeSeg2 = HW_RD_FIELD32(baseAddr + MCAN_NBTP, MCAN_NBTP_NTSEG2); configParams->nomTimeSeg1 = HW_RD_FIELD32(baseAddr + MCAN_NBTP, MCAN_NBTP_NTSEG1); configParams->nomRatePrescalar = HW_RD_FIELD32(baseAddr + MCAN_NBTP, MCAN_NBTP_NBRP); configParams->dataSynchJumpWidth = HW_RD_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_DSJW); configParams->dataTimeSeg2 = HW_RD_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_DTSEG2); configParams->dataTimeSeg1 = HW_RD_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_DTSEG1); configParams->dataRatePrescalar = HW_RD_FIELD32(baseAddr + MCAN_DBTP, MCAN_DBTP_DBRP); } void MCAN_resetTSCounter(uint32_t baseAddr) { HW_WR_FIELD32(baseAddr + MCAN_TSCV, MCAN_TSCV_TSC, 0x0U); } uint32_t MCAN_getTOCounterVal(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_TOCV, MCAN_TOCV_TOC)); } void MCAN_eccAggrGetRevisionId(uint32_t baseAddr, MCAN_ECCAggrRevisionId *revId) { uint32_t regVal; regVal = HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_REVISION); revId->minor = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_REVISION_REVMIN); revId->custom = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_REVISION_CUSTOM); revId->major = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_REVISION_REVMAJ); revId->rtlRev = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_REVISION_REVRTL); revId->modId = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_REVISION_MODULE_ID); revId->bu = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_REVISION_BU); revId->scheme = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_REVISION_SCHEME); } void MCAN_eccWrapGetRevisionId(uint32_t baseAddr, MCAN_ECCWrapRevisionId *revId) { uint32_t regVal; MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_WRAP_REVISION); regVal = HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_WRAP_REVISION); revId->minor = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_WRAP_REVISION_REVMIN); revId->custom = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_WRAP_REVISION_CUSTOM); revId->major = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_WRAP_REVISION_REVMAJ); revId->rtlRev = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_WRAP_REVISION_REVRTL); revId->modId = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_WRAP_REVISION_MODULE_ID); revId->bu = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_WRAP_REVISION_BU); revId->scheme = HW_GET_FIELD(regVal, MCAN_ECC_AGGR_WRAP_REVISION_SCHEME); } uint32_t MCAN_extTSIsIntrEnable(uint32_t baseAddr) { uint32_t status; if(1U == HW_RD_FIELD32(baseAddr + MCAN_MCANSS_IES, MCAN_MCANSS_IES_EXT_TS_CNTR_OVFL)) { status = (uint32_t) TRUE; } else { status = (uint32_t) FALSE; } return status; } uint32_t MCAN_getEndianVal(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_ENDN, MCAN_ENDN_ETV)); } uint32_t MCAN_getExtIDANDMassk(uint32_t baseAddr) { return(HW_RD_FIELD32(baseAddr + MCAN_XIDAM, MCAN_XIDAM_EIDM)); } /* ========================================================================== */ /* Internal Functions */ /* ========================================================================== */ static void MCAN_writeProtectedRegAccessUnlock(uint32_t baseAddr) { HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CCE, 0x1U); } static void MCAN_writeProtectedRegAccessLock(uint32_t baseAddr) { HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CCE, 0x0U); } static void MCAN_eccLoadRegister(uint32_t baseAddr, uint32_t regOffset) { uint32_t regVal = 0U, offset; offset = regOffset & 0xFFU; regVal |= ((uint32_t)MCANSS_MSG_RAM_NUM << MCAN_ECC_AGGR_VECTOR_SHIFT); regVal |= (offset << MCAN_ECC_AGGR_VECTOR_RD_SVBUS_ADDRESS_SHIFT); regVal |= ((uint32_t)1U << MCAN_ECC_AGGR_VECTOR_RD_SVBUS_SHIFT); HW_WR_REG32(baseAddr + MCAN_ECC_AGGR_VECTOR, regVal); while(MCAN_ECC_AGGR_VECTOR_RD_SVBUS_DONE_MASK != (HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_VECTOR) & MCAN_ECC_AGGR_VECTOR_RD_SVBUS_DONE_MASK)) {} } static void MCAN_readMsg(uint32_t baseAddr, uint32_t elemAddr, MCAN_RxBufElement *elem) { uint32_t regVal = 0U, loopCnt = 0U; regVal = HW_RD_REG32(baseAddr + 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(baseAddr + 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 <= (MCAN_getDataSize(elem->dlc) - loopCnt)) && (0U != (MCAN_getDataSize(elem->dlc) - loopCnt))) { ASSERT((loopCnt + 3) < MCAN_MAX_PAYLOAD_BYTES); regVal = HW_RD_REG32(baseAddr + 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 < (MCAN_getDataSize(elem->dlc) - loopCnt)) { ASSERT((loopCnt + 2) < MCAN_MAX_PAYLOAD_BYTES); regVal = HW_RD_REG32(baseAddr + 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 MCAN_writeMsg(uint32_t baseAddr, uint32_t elemAddr, const 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(baseAddr + 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(baseAddr + elemAddr, regVal); elemAddr += 4U; loopCnt = 0U; /* Framing words out of the payload bytes and writing it to message RAM */ while((4U <= (MCAN_getDataSize(elem->dlc) - loopCnt)) && (0U != (MCAN_getDataSize(elem->dlc) - loopCnt))) { ASSERT((loopCnt + 3) < MCAN_MAX_PAYLOAD_BYTES); 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(baseAddr + elemAddr, regVal); elemAddr += 4U; loopCnt += 4U; } /* Framing a word out of remaining payload bytes and writing it to * message RAM */ if(0U < (MCAN_getDataSize(elem->dlc) - loopCnt)) { ASSERT((loopCnt + 3) < MCAN_MAX_PAYLOAD_BYTES); 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(baseAddr + elemAddr, regVal); } } static uint32_t 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}; ASSERT(dlc < 16); return(dataSize[dlc]); } static uint32_t MCAN_getMsgObjSize(uint32_t elemSize) { uint32_t objSize[8] = {4, 5, 6, 7, 8, 10, 14, 18}; ASSERT(elemSize < 8); return(objSize[elemSize]); }