1846 lines
65 KiB
C
1846 lines
65 KiB
C
/*
|
|
* 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 <stdint.h>
|
|
#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 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);
|
|
|
|
/* ========================================================================== */
|
|
/* Global Variables */
|
|
/* ========================================================================== */
|
|
|
|
/* None */
|
|
|
|
/* ========================================================================== */
|
|
/* Function Definitions */
|
|
/* ========================================================================== */
|
|
|
|
void MCAN_selectClockSource(uint32_t baseAddr, MCAN_ClockSource source)
|
|
{
|
|
//
|
|
// Determine the CAN controller and set specified clock source
|
|
//
|
|
EALLOW;
|
|
|
|
switch(baseAddr)
|
|
{
|
|
case MCANA_DRIVER_BASE:
|
|
HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) =
|
|
(HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) &
|
|
~SYSCTL_CLKSRCCTL2_MCANABITCLKSEL_M) |
|
|
((uint16_t)source << SYSCTL_CLKSRCCTL2_MCANABITCLKSEL_S);
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
//
|
|
// Do nothing. Not a valid mode value.
|
|
//
|
|
break;
|
|
}
|
|
|
|
EDIS;
|
|
|
|
}
|
|
|
|
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((uint32_t)MCAN_MEM_TYPE_BUF == memType)
|
|
{
|
|
idx = bufNum;
|
|
enableMod = 1U;
|
|
}
|
|
if((uint32_t)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((uint32_t)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((uint32_t)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((uint32_t)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((uint32_t)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((uint32_t)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_clearInterrupt(uint32_t baseAddr, uint16_t intrNum)
|
|
{
|
|
HW_WR_FIELD32(baseAddr + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, intrNum);
|
|
}
|
|
|
|
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 == (uint32_t)MCAN_ECC_ERR_TYPE_SEC) ||
|
|
(eccErr->errType == (uint32_t)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 == (uint32_t)MCAN_ECC_ERR_TYPE_SEC)
|
|
{
|
|
HW_SET_FIELD32(regVal,
|
|
MCAN_ECC_AGGR_CONTROL_FORCE_SEC,
|
|
0x1U);
|
|
}
|
|
else if(eccErr->errType == (uint32_t)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_getExtIDANDMask(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 + 3U) < 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 + 2U) < 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 + 3U) < 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 + 3U) < 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 < 16U);
|
|
return(dataSize[dlc]);
|
|
}
|
|
|
|
uint32_t MCAN_getMsgObjSize(uint32_t elemSize)
|
|
{
|
|
uint32_t objSize[8] = {4, 5, 6, 7, 8, 10, 14, 18};
|
|
ASSERT(elemSize < 8U);
|
|
return(objSize[elemSize]);
|
|
}
|