PeripheralDriver_Flagchip_F.../Src/module_driver_flexcan.c

3551 lines
116 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file module_driver_flexcan.h
* @author Flagchip
* @brief FLEXCAN driver source code
* @version 2.0.0
* @date 2024-08-20
*
* SDK Version: 2.6.0
*
* @copyright Copyright (c) 2020-2024 Flagchip Semiconductors Co., Ltd.
*
*/
/*********************************************************************************
* Revision History:
* Version Date Initials CR# Descriptions
* --------- ---------- ------------ ---------- ---------------
* 2.0.0 2024-04-20 Flagchip038 N/A First version
* 2.0.1 2024-09-08 Flagchip038 N/A Update PNET check process
* 2.0.2 2024-10-20 Flagchip038 N/A Add FlexCAN Errata 001 fix
* 2.1.0 2024-11-20 Flagchip038 N/A Add clear flag interrupt macro
* 2.2.0 2025-02-20 Flagchip038 N/A Fix extended id SRR bit = 0 issue
*********************************************************************************/
#include "module_driver_flexcan.h" /* include peripheral declarations */
#if FLEXCAN_INSTANCE_COUNT > 0U
/* ################################################################################## */
/* ####################################### Macro #################################### */
#ifndef NULL
#define NULL ((void *)0)
#endif
#define FLEXCAN_ESR1_ERROR_OK_MASK 0x40080u
#define USE_CBT_NORMAL
#define TQ_NUM_IPT 2U
#define TQ_SYNC_NUM 1U
/* Ctrl1 */
#define TQ_NUM_CTRL1_MAX 25U
#define TQ_NUM_CTRL1_MIN 8U
#define CTRL1_PRESDIV_MAX 256U
#define CTRL1_PRESDIV_MIN 1U
#define CTRL1_RJW_MAX 4U
#define CTRL1_RJW_MIN 1U
#define CTRL1_PROPSEG_MAX 8U
#define CTRL1_PROPSEG_MIN 1U
#define CTRL1_PSEG1_MAX 8U
#define CTRL1_PSEG1_MIN 1U
#define CTRL1_TIMERSEGMENT1_MAX 16U
#define CTRL1_TIMERSEGMENT1_MIN 2U
#define CTRL1_PSEG2_MAX 8U
#define CTRL1_PSEG2_MIN 2U
/* CBT */
#define TQ_NUM_CBT_MAX 25U /* 80U */
#define TQ_NUM_CBT_MIN 8U
#define CBT_PRESDIV_MAX 1024U
#define CBT_PRESDIV_MIN 1U
#define CBT_RJW_MAX 32U
#define CBT_RJW_MIN 1U
#define CBT_PROPSEG_MAX 64U
#define CBT_PROPSEG_MIN 1U
#define CBT_PSEG1_MAX 32U
#define CBT_PSEG1_MIN 1U
#define CBT_TIMERSEGMENT1_MAX 96U
#define CBT_TIMERSEGMENT1_MIN 2U
#define CBT_PSEG2_MAX 32U
#define CBT_PSEG2_MIN 2U
/* FDCBT */
#define TQ_NUM_FDCBT_MAX 25U
#define TQ_NUM_FDCBT_MIN 5U
#define FDCBT_PRESDIV_MAX 1024U
#define FDCBT_PRESDIV_MIN 1U
#define FDCBT_RJW_MAX 8U
#define FDCBT_RJW_MIN 1U
#define FDCBT_PROPSEG_MAX 31U
#define FDCBT_PROPSEG_MIN 0U
#define FDCBT_PSEG1_MAX 8U
#define FDCBT_PSEG1_MIN 1U
#define FDCBT_TIMERSEGMENT1_MAX 39U
#define FDCBT_TIMERSEGMENT1_MIN 2U
#define FDCBT_PSEG2_MAX 8U
#define FDCBT_PSEG2_MIN 2U
#define CAN_ONEMB_WORD_NUM 4U /* one MB is 4*4=16bytes */
typedef struct
{
const uint8 u8RFFN; /** CAN2[RFFN] setting value */
const uint8 u8LegacyFilterNum; /** Legacy Fifo Filter Elements number, standard occupies 1, extended occupies 2 */
const uint8 u8MbUsedForLegacyFifo; /** MB number used for legacy rx fifo and filter elements, RXIMR num same to MB */
} FLEXCAN_LegacyFifoFilterType;
/* ################################################################################## */
/* ############################# Local Const Variables ############################## */
/* CAN Instance */
static FLEXCAN_Type *const s_aFlexCan_InstanceTable[FLEXCAN_INSTANCE_COUNT] = FLEXCAN_BASE_PTRS;
static const uint8_t s_aFlexCanFd_SupportTable[FLEXCAN_INSTANCE_COUNT] = FLEXCAN_FD_SUPPORT_PTRS;
static const uint8_t s_aFlexCanEnhancedElementNums[FLEXCAN_INSTANCE_COUNT] = FLEXCAN_ENHANCED_FIFO_ELEMENT_MAX_PTRS;
static const uint8_t s_aFlexCanMbNums[FLEXCAN_INSTANCE_COUNT] = FLEXCAN_MB_NUM_PTRS;
static const uint8_t s_aFlexCanDataLenNums[FLEXCAN_INSTANCE_COUNT] = FLEXCAN_FD_DATALEN_RANGE_NUM_PTRS;
static const uint8_t s_aFlexCanEnhancedDepthp[FLEXCAN_INSTANCE_COUNT] = FLEXCAN_ENHANCED_FIFO_DEPTH_PTRS;
static const uint8_t s_aFlexCanGateNumSizes[FLEXCAN_INSTANCE_COUNT] = FLEXCAN_GATE_BUFNUM_PTRS;
static const uint8_t s_aFlexCanIflagMaskSizes[FLEXCAN_INSTANCE_COUNT] = FLEXCAN_IFLAGMASK_NUM_PTRS;
static const uint8_t s_aFlexCanPnetSupportTable[FLEXCAN_INSTANCE_COUNT]=FLEXCAN_PNET_SUPPORT_PTRS;
/* CAN Legacy FIFO Filter check array */
static const FLEXCAN_LegacyFifoFilterType s_aFlexCan_LegacyFilterCheckTable[FLEXCAN_LEGACY_FIFO_NUM_TABLE_LENGTH] = FLEXCAN_LEGACY_FIFO_PTRS;
#ifdef FLEXCAN_ERRATA_TRANSMIT_LIMIT
#if FLEXCAN_ERRATA_TRANSMIT_LIMIT == STD_ON
static const uint8_t s_aFlexCan_TransmitLimit_List[FLEXCAN_ERRATA_TRANSMIT_LM_LIST_LEN] = FLEXCAN_ERRATA_TRANSMIT_LM_LIST;
#endif
#else
#define FLEXCAN_ERRATA_TRANSMIT_LIMIT STD_OFF
#endif
/* ################################################################################## */
/* ########################### Local Prototype Functions ############################ */
/* ################################################################################## */
/* ########################### Global Prototype Functions ########################### */
/* ################################################################################## */
/* ################################ Local Functions ################################# */
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/**
* @brief Check FLEXCAN instance
*
* @param pCanHandle Can Handle point
* @return FLEXCAN_E_OK is OK
*/
LOCAL_INLINE FLEXCAN_ErrorType FLEXCAN_LL_CheckInstance(FLEXCAN_InstanceType eCanInstance)
{
FLEXCAN_ErrorType tRetVal;
if ((uint8_t)eCanInstance < FLEXCAN_INSTANCE_COUNT)
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal = FLEXCAN_E_INVALID_PARAM;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_CHECKINSTANCE, FLEXCAN_E_INVALID_PARAM);
}
return tRetVal;
}
#endif
#if FLEXCAN_ERRATA_TRANSMIT_LIMIT == STD_ON
LOCAL_INLINE uint8_t FLEXCAN_LL_CheckContains(const uint8_t *pList, uint8_t u8Len, uint8_t u8Value)
{
uint8_t u8Index;
uint8_t u8Retval;
u8Retval = 0U;
for(u8Index=0U; u8Index < u8Len; u8Index++)
{
if(pList[u8Index] == u8Value)
{
u8Retval = 1U;
break;
}
}
return u8Retval;
}
#endif
/**
* @brief Check FLEXCAN Fd Support instance
*
* @param pCanHandle Can Handle point
* @return FLEXCAN_E_OK is OK
*/
LOCAL_INLINE FLEXCAN_ErrorType FLEXCAN_LL_CheckFdInstance(uint8_t u8CanIndex)
{
FLEXCAN_ErrorType tRetVal;
if (s_aFlexCanFd_SupportTable[u8CanIndex])
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal = FLEXCAN_E_INVALID_PARAM;
}
return tRetVal;
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/**
* @brief Check Legency Fifo Num
*
* @param u32RxFilterCnt Legency fifo num
* @return FLEXCAN_E_OK is OK
*/
LOCAL_INLINE FLEXCAN_ErrorType FLEXCAN_LL_CheckLengcyFifoNum(uint32_t u32RxFilterCnt)
{
FLEXCAN_ErrorType tRetVal;
if (u32RxFilterCnt % 8 == 0)
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal = FLEXCAN_E_INVALID_PARAM;
}
return tRetVal;
}
#endif
LOCAL_INLINE uint8_t FLEXCAN_LL_GetMbNum(FLEXCAN_HandleType *pCanHandle, const FLEXCAN_InitType *const pInitCfg)
{
uint8_t u8Num;
if(pInitCfg->bEnFd)
{
u8Num = (uint8_t)(s_aFlexCanMbNums[pCanHandle->eInstance]/s_aFlexCanIflagMaskSizes[pCanHandle->eInstance]*16U/(pInitCfg->tMbCfg.aDataWidthRange[0]+8U));
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
u8Num = (uint8_t)(u8Num + s_aFlexCanMbNums[pCanHandle->eInstance]/s_aFlexCanIflagMaskSizes[pCanHandle->eInstance]*16U/(pInitCfg->tMbCfg.aDataWidthRange[1]+8U));
}
#elif FLEXCAN_IFLAGMASK_NUM_MAX > 2U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
u8Num = (uint8_t)(u8Num + s_aFlexCanMbNums[pCanHandle->eInstance]/s_aFlexCanIflagMaskSizes[pCanHandle->eInstance]*16U/(pInitCfg->tMbCfg.aDataWidthRange[2]+8U));
}
#endif
}
else
{
u8Num = s_aFlexCanMbNums[pCanHandle->eInstance];
}
return u8Num;
}
#if 0
LOCAL_INLINE void FLEXCAN_LL_SetMbMask(FLEXCAN_HandleType *pCanHandle, const FLEXCAN_InitType *const pInitCfg)
{
uint8_t u8Index;
uint8_t u8MbCnt;
u8Index = 0U;
u8MbCnt = pInitCfg->tMbCfg.u8MBCnt;
pCanHandle->tStatus.aTxInterruptMask[0] = 0U;
for(u8Index=0U;u8Index<u8MbCnt;u8Index++)
{
if(pInitCfg->tMbCfg.pMBList[u8Index].bEnMBInt)
{
if(u8Index<32U)
{
pCanHandle->tStatus.aTxInterruptMask[0] = (pCanHandle->tStatus.aTxInterruptMask[0] << u8Index) | pCanHandle->tStatus.aTxInterruptMask[0];
pCanHandle->tStatus.aInterruptMask[0] = (pCanHandle->tStatus.aInterruptMask[0] << u8Index) | pCanHandle->tStatus.aInterruptMask[0];
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
else if(u8Index<64U)
{
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
pCanHandle->tStatus.aTxInterruptMask[1] = (pCanHandle->tStatus.aTxInterruptMask[1] << u8Index) | pCanHandle->tStatus.aTxInterruptMask[1];
pCanHandle->tStatus.aInterruptMask[1] = (pCanHandle->tStatus.aInterruptMask[1] << u8Index) | pCanHandle->tStatus.aInterruptMask[1];
}
}
#elif FLEXCAN_IFLAGMASK_NUM_MAX > 2U
else if(u8Index<96U)
{
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
pCanHandle->tStatus.aTxInterruptMask[2] = (pCanHandle->tStatus.aTxInterruptMask[2] << u8Index) | pCanHandle->tStatus.aTxInterruptMask[2];
pCanHandle->tStatus.aInterruptMask[2] = (pCanHandle->tStatus.aInterruptMask[2] << u8Index) | pCanHandle->tStatus.aInterruptMask[2];
}
}
#endif
}
else
{
if(u8Index<32U)
{
pCanHandle->tStatus.aTxPollingMask[0] = (pCanHandle->tStatus.aTxPollingMask[0] << u8Index) | pCanHandle->tStatus.aTxPollingMask[0];
pCanHandle->tStatus.aPollingMask[0] = (pCanHandle->tStatus.aPollingMask[0] << u8Index) | pCanHandle->tStatus.aPollingMask[0];
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
else if(u8Index<64U)
{
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
pCanHandle->tStatus.aTxPollingMask[1] = (pCanHandle->tStatus.aTxPollingMask[1] << u8Index) | pCanHandle->tStatus.aTxPollingMask[1];
pCanHandle->tStatus.aPollingMask[1] = (pCanHandle->tStatus.aPollingMask[1] << u8Index) | pCanHandle->tStatus.aPollingMask[1];
}
}
#elif FLEXCAN_IFLAGMASK_NUM_MAX > 2U
else if(u8Index<96U)
{
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
pCanHandle->tStatus.aTxPollingMask[2] = (pCanHandle->tStatus.aTxPollingMask[2] << u8Index) | pCanHandle->tStatus.aTxPollingMask[2];
pCanHandle->tStatus.aPollingMask[2] = (pCanHandle->tStatus.aPollingMask[2] << u8Index) | pCanHandle->tStatus.aPollingMask[2];
}
}
#endif
}
}
}
#endif
LOCAL_INLINE uint8_t FLEXCAN_LL_GetMbIndexByTxHandle(FLEXCAN_HandleType *pCanHandle, uint8_t u8TxHandle)
{
uint32_t u32Mask;
uint8_t u8Index;
uint8_t u8MbIndex;
uint8_t u8Find;
u8Find = 0U;
u8MbIndex = 0U;
u8Index = 0U;
u32Mask = pCanHandle->tStatus.aTxInterruptMask[0]|pCanHandle->tStatus.aTxPollingMask[0];
while(u32Mask)
{
if((u32Mask & 0x01U) == 0x01U)
{
if(u8Index==u8TxHandle)
{
u8Find = 1U;
break;
}
u8Index++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8MbIndex++;
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
if(u8Find==0U)
{
u32Mask = pCanHandle->tStatus.aTxInterruptMask[1]|pCanHandle->tStatus.aTxPollingMask[1];
while(u32Mask)
{
if((u32Mask&0x01U)==0x01U)
{
if(u8Index==u8TxHandle)
{
u8Find = 1U;
break;
}
u8Index++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8MbIndex++;
}
}
}
#endif
#if FLEXCAN_IFLAGMASK_NUM_MAX > 2U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
if(u8Find==0U)
{
u32Mask = pCanHandle->tStatus.aTxInterruptMask[2]|pCanHandle->tStatus.aTxPollingMask[2];
while(u32Mask)
{
if((u32Mask&0x01U)==0x01U)
{
if(u8Index==u8TxHandle)
{
u8Find = 1U;
break;
}
u8Index++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8MbIndex++;
}
}
}
#endif
if(u8Find==0U)
{
u8MbIndex = 0xFFU;
}
return u8MbIndex;
}
LOCAL_INLINE uint8_t FLEXCAN_LL_GetTxHandleByMbIndex(FLEXCAN_HandleType *pCanHandle, uint8_t u8MbIndex)
{
uint32_t u32Mask;
uint8_t u8Index;
uint8_t u8TxHandle;
uint8_t u8Find;
u8Find = 0U;
u8Index = 0U;
u8TxHandle = 0U;
u32Mask = pCanHandle->tStatus.aTxInterruptMask[0] | pCanHandle->tStatus.aTxPollingMask[0];
while(u32Mask)
{
if((u32Mask & 0x01U) == 0x01U)
{
if(u8Index==u8MbIndex)
{
u8Find = 1U;
break;
}
u8TxHandle++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8Index++;
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
if(u8Find==0U)
{
u32Mask = pCanHandle->tStatus.aTxInterruptMask[1] | pCanHandle->tStatus.aTxPollingMask[1];
while(u32Mask)
{
if((u32Mask & 0x01U) == 0x01U)
{
if(u8Index==u8MbIndex)
{
u8Find = 1U;
break;
}
u8TxHandle++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8Index++;
}
}
}
#endif
#if FLEXCAN_IFLAGMASK_NUM_MAX > 2U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
if(u8Find==0U)
{
u32Mask = pCanHandle->tStatus.aTxInterruptMask[2] | pCanHandle->tStatus.aTxPollingMask[2];
while(u32Mask)
{
if((u32Mask & 0x01U) == 0x01U)
{
if(u8Index==u8MbIndex)
{
u8Find = 1U;
break;
}
u8TxHandle++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8Index++;
}
}
}
#endif
if(u8Find==0U)
{
u8TxHandle = 0xFFU;
}
return u8TxHandle;
}
LOCAL_INLINE uint8_t FLEXCAN_LL_GetRxHandleByMbIndex(FLEXCAN_HandleType *pCanHandle, uint8_t u8MbIndex)
{
uint32_t u32Mask;
uint8_t u8Index;
uint8_t u8RxHandle;
uint8_t u8Find;
u8Find = 0U;
u8Index = 0U;
u8RxHandle = 0U;
u32Mask = pCanHandle->tStatus.aRxInterruptMask[0] | pCanHandle->tStatus.aRxPollingMask[0];
while(u32Mask)
{
if((u32Mask & 0x01U) == 0x01U)
{
if(u8Index==u8MbIndex)
{
u8Find = 1U;
break;
}
u8RxHandle++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8Index++;
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
if(u8Find==0U)
{
u32Mask = pCanHandle->tStatus.aRxInterruptMask[1] | pCanHandle->tStatus.aRxPollingMask[1];
while(u32Mask)
{
if((u32Mask & 0x01U) == 0x01U)
{
if(u8Index==u8MbIndex)
{
u8Find = 1U;
break;
}
u8RxHandle++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8Index++;
}
}
}
#endif
#if FLEXCAN_IFLAGMASK_NUM_MAX > 2U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
if(u8Find==0U)
{
u32Mask = pCanHandle->tStatus.aRxInterruptMask[2] | pCanHandle->tStatus.aRxPollingMask[2];
while(u32Mask)
{
if((u32Mask & 0x01U) == 0x01U)
{
if(u8Index==u8MbIndex)
{
u8Find = 1U;
break;
}
u8RxHandle++;
}
u32Mask = (uint32_t)(u32Mask >> 1U);
u8Index++;
}
}
}
#endif
if(u8Find==0U)
{
u8RxHandle = 0xFFU;
}
return u8RxHandle;
}
/**
* @brief Initial embedded can ram area
*
* @param u8CanIndex CanIndex, Must less than FLEXCAN_INSTANCE_COUNT
*/
static void FLEXCAN_LL_EmbededRam_Init(FLEXCAN_InstanceType eInstance)
{
volatile uint32_t u32Index ;
volatile uint32_t ramAddr;
FLEXCAN_Type *pCan;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[(uint8_t)eInstance];
for (u32Index = 0U; u32Index < s_aFlexCanMbNums[eInstance]*4U; u32Index++)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_MB_RAM_OFFSET, u32Index * 4U);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
for (u32Index = 0U; u32Index < s_aFlexCanMbNums[eInstance]; u32Index++)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_RXIMR_OFFSET, u32Index * 4U);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
for (u32Index = 0U; u32Index < FLEXCAN_RXFIR_TEST_LEN; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_RXFIR_TEST_OFFSET, u32Index);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
for (u32Index = 0U; u32Index < FLEXCAN_MASK_LEN; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_MASK_OFFSET, u32Index);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
for (u32Index = 0U; u32Index < FLEXCAN_SMBTX_LEN; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_SMBTX_OFFSET, u32Index);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
for (u32Index = 0U; u32Index < FLEXCAN_SMBRX0_LEN; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_SMBRX0_OFFSET, u32Index);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
for (u32Index = 0U; u32Index < FLEXCAN_SMBRX1_LEN; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_SMBRX1_OFFSET, u32Index);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
/* only can fd support these memory */
if(s_aFlexCanFd_SupportTable[eInstance])
{
for (u32Index = 0U; u32Index < FLEXCAN_FD_SMBTX_LEN; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_FD_SMBTX_OFFSET, u32Index);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
for (u32Index = 0U; u32Index < FLEXCAN_FD_SMBRX0_LEN; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_FD_SMBRX0_OFFSET, u32Index);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
for (u32Index = 0U; u32Index < FLEXCAN_FD_SMBRX1_LEN; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_FD_SMBRX1_OFFSET, u32Index);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
}
/* only enhanced rx fifo support these memory */
if(s_aFlexCanEnhancedDepthp[eInstance])
{
/** initial rx fifo with fd */
for (u32Index = 0U; u32Index < s_aFlexCanEnhancedDepthp[eInstance]*4U*FLEXCAN_ERX_FIFO_FD_WIDTH; u32Index+=4U)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_ERX_FIFO_OFFSET, u32Index );
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
/* enhanced fifo elements */
for (u32Index = 0U; u32Index < s_aFlexCanEnhancedElementNums[eInstance]; u32Index++)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_ERFFEL_OFFSET, u32Index * 4U);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
}
/* gate buffer */
if(s_aFlexCanGateNumSizes[eInstance])
{
for (u32Index = 0U; u32Index < s_aFlexCanGateNumSizes[eInstance]*2U; u32Index++)
{
ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FLEXCAN_GATEBUF_OFFSET, u32Index * 4U);
FLEXCAN_REG32_CONTENT(ramAddr) = 0U;
}
}
}
/**
* @brief This Function is used to receive Special Message Buffer data
*
* @param pCanHandle Can Handle point
* @param u8RealMbIndex, message buffer index 0...31, if fifo enable, always 0
*/
static void FLEXCAN_LL_ReceiveMb(FLEXCAN_HandleType *pCanHandle, uint8_t u8RealMbIndex)
{
FLEXCAN_Type *pCan;
uint32_t *pSrc;
uint32_t *pDest;
uint8_t u8Index;
uint32_t u32TempAddr;
uint32_t u32WordLen;
uint8_t u8DateLen;
u8DateLen = FLEXCAN_MB_GET_DATALEN(u8RealMbIndex, s_aFlexCanMbNums[pCanHandle->eInstance],s_aFlexCanDataLenNums[pCanHandle->eInstance], pCanHandle->tStatus.aMbDataWidth);
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
pCanHandle->tSettings.pRxBuf->u8CanIndex = pCanHandle->eInstance;
pCanHandle->tSettings.pRxBuf->u8RxHandle = u8RealMbIndex;
/* message buffer 1th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RealMbIndex, u8DateLen, 0U);
pCanHandle->tSettings.pRxBuf->bEnFd = (uint8_t)((FLEXCAN_MB_EDL_GET(u32TempAddr) == 0U) ? 0U : 1U);
pCanHandle->tSettings.pRxBuf->bEnBrs = (uint8_t)((FLEXCAN_MB_BRS_GET(u32TempAddr) == 0U) ? 0U : 1U);
pCanHandle->tSettings.pRxBuf->u32DataLen = FLEXCAN_MB_DLC_GET(u32TempAddr);
pCanHandle->tSettings.pRxBuf->u32DataLen = FLEXCAN_DlcToDataLen(pCanHandle->tSettings.pRxBuf->u32DataLen);
pCanHandle->tSettings.pRxBuf->eFrameType = (FLEXCAN_IdType)(FLEXCAN_MB_IDE_GET(u32TempAddr));
/* message buffer 2th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RealMbIndex, u8DateLen, 4U);
if (pCanHandle->tSettings.pRxBuf->eFrameType)
{
pCanHandle->tSettings.pRxBuf->u32CanId = FLEXCAN_MB_EXTID_GET(u32TempAddr);
}
else
{
pCanHandle->tSettings.pRxBuf->u32CanId = FLEXCAN_MB_STDID_GET(u32TempAddr);
}
pDest = (uint32_t *)pCanHandle->tSettings.pRxBuf->aData;
/* message buffer 3th word */
pSrc = (uint32_t *)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RealMbIndex, u8DateLen, 8U);
u32WordLen = pCanHandle->tSettings.pRxBuf->u32DataLen / 4U + (pCanHandle->tSettings.pRxBuf->u32DataLen % 4U > 0U ? 1U : 0U);
for (u8Index = 0U; u8Index < u32WordLen; u8Index++)
{
/* big endian to little endian */
REV_BYTES_32(pSrc[u8Index], pDest[u8Index]);
}
(void)pCan->TIMER; /* Read TIMER to unlock message buffers */
}
/**
* @brief This Function is used to receive Enhance FIFO Buffer data
*
* @param pCanHandle Can handle point
*/
static void FLEXCAN_LL_ReceiveEnhanceFifo(FLEXCAN_HandleType *pCanHandle)
{
volatile uint32_t *pSrc;
volatile uint32_t *pDest;
uint8_t u8Index;
FLEXCAN_Type *pCan;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
pCanHandle->tSettings.pRxBuf->u8CanIndex = pCanHandle->eInstance;
pCanHandle->tSettings.pRxBuf->bEnFd = (uint8_t)(FLEXCAN_EFIFOMB_EDL_GET());
pCanHandle->tSettings.pRxBuf->bEnBrs = (uint8_t)(FLEXCAN_EFIFOMB_BRS_GET());
pCanHandle->tSettings.pRxBuf->u32DataLen = FLEXCAN_EFIFOMB_DLC_GET();
pCanHandle->tSettings.pRxBuf->u32DataLen = (uint8_t)(FLEXCAN_DlcToDataLen(pCanHandle->tSettings.pRxBuf->u32DataLen));
pCanHandle->tSettings.pRxBuf->eFrameType = (FLEXCAN_IdType)(FLEXCAN_EFIFOMB_IDE_GET());
if (pCanHandle->tSettings.pRxBuf->eFrameType)
{
pCanHandle->tSettings.pRxBuf->u32CanId = FLEXCAN_EFIFOMB_EXTID_GET();
}
else
{
pCanHandle->tSettings.pRxBuf->u32CanId = FLEXCAN_EFIFOMB_STDID_GET();
}
pDest = (uint32_t *)pCanHandle->tSettings.pRxBuf->aData;
/* message buffer 3th word */
pSrc = (volatile uint32_t *)FLEXCAN_EFIFOMB_DATAADDR_GET(0U);
//u32WordLen = pCanHandle->tStatus1.pRxBuf->u32DataLen / 4U + (pCanHandle->tStatus1.pRxBuf->u32DataLen % 4U > 0U ? 1U : 0U);
for (u8Index = 0U; u8Index < 18U; u8Index++)
{
/* big endian to little endian */
REV_BYTES_32(pSrc[u8Index], pDest[u8Index]);
}
//u32WordLen = FLEXCAN_EFIFOMB_HRTIMESTAMP_GET(u32WordLen); /* Read TIMER to unlock message buffers */
/* clear fifo data available status */
FLEXCAN_HWA_ERFSRClearEnhancedFifoFlag(pCan, (FLEXCAN_ERFSR_ERFDA_MASK | FLEXCAN_ERFSR_ERFWMI_MASK));
}
/**
* @brief Polling Legacy Rx FIFO data
*
* @param pCanHandle Can handle point
*/
static void FLEXCAN_LL_PollingLegacyFifoData(FLEXCAN_HandleType *pCanHandle)
{
uint32_t u32Status;
FLEXCAN_Type *pCan;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
/* IFLAG1[BIT5] (Frames available in Rx FIFO) is asserted when there is at least one frame available to be read from the FIFO. */
u32Status = FLEXCAN_HWA_CheckLegacyFifoData(pCan);
while (u32Status != 0U)
{
FLEXCAN_LL_ReceiveMb(pCanHandle, 0);
FLEXCAN_HWA_UnlockMbNoFifoFlag(pCan, (uint32_t)5);
pCanHandle->tSettings.pRxBuf->u8RxHandle = 0xFFU;
#if FLEXCAN_RX_FLAG_CLEAR_FIRST == STD_ON
u32Status = FLEXCAN_HWA_GetFlag1NoFifoFlag(pCan, 5);
pCanHandle->tSettings.pRxNotify(pCanHandle, pCanHandle->tSettings.pRxBuf);
#else
pCanHandle->tSettings.pRxNotify(pCanHandle, pCanHandle->tSettings.pRxBuf);
u32Status = FLEXCAN_HWA_GetFlag1NoFifoFlag(pCan, 5);
#endif
}
}
/**
* @brief Polling Legacy Rx FIFO warning notification
*
* @param pCanHandle Can handle point
*/
static void FLEXCAN_LL_PollingLegacyFifoWarning(FLEXCAN_HandleType *pCanHandle)
{
FLEXCAN_Type *pCan;
FLEXCAN_FifoIssueType tFifoIssue;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
if (FLEXCAN_HWA_CheckLegacyFifoWarning(pCan) != 0U)
{
tFifoIssue.eFifoType = FLEXCAN_LEGACY_FIFO;
tFifoIssue.u8FifoWarings = 1U;
tFifoIssue.u8FifoUnderflow = 0U;
tFifoIssue.u8FifoOverflow = 0U;
#if FLEXCAN_ERROR_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_ClearIFLAG1FifoWarningFlag(pCan);
pCanHandle->tSettings.pFifoIssueNotify(pCanHandle, &tFifoIssue);
#else
pCanHandle->tSettings.pFifoIssueNotify(pCanHandle, &tFifoIssue);
FLEXCAN_HWA_ClearIFLAG1FifoWarningFlag(pCan);
#endif
}
}
/**
* @brief Polling Legacy Rx FIFO warning notification
*
* @param pCanHandle Can handle point
*/
static void FLEXCAN_LL_PollingLegacyFifoError(FLEXCAN_HandleType *pCanHandle)
{
FLEXCAN_Type *pCan;
FLEXCAN_FifoIssueType tFifoIssue;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
if (FLEXCAN_HWA_CheckLegacyFifoDataLost(pCan) != 0U)
{
tFifoIssue.eFifoType = FLEXCAN_LEGACY_FIFO;
tFifoIssue.u8FifoWarings = 0U;
tFifoIssue.u8FifoUnderflow = 0U;
tFifoIssue.u8FifoOverflow = 1U;
#if FLEXCAN_ERROR_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_ClearIFLAG1FifoErrorFlag(pCan);
pCanHandle->tSettings.pFifoIssueNotify(pCanHandle, &tFifoIssue);
#else
pCanHandle->tSettings.pFifoIssueNotify(pCanHandle, &tFifoIssue);
FLEXCAN_HWA_ClearIFLAG1FifoErrorFlag(pCan);
#endif
}
}
/**
* @brief Polling Enhanced Rx FIFO Data
*
* @param pCanHandle Can handle point
*/
static void FLEXCAN_LL_PollingEnhancedFifoData(FLEXCAN_HandleType *pCanHandle)
{
uint32_t u32Status;
FLEXCAN_Type *pCan;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u32Status = FLEXCAN_HWA_ERFSRGetDataValid(pCan);
while (u32Status != 0U)
{
FLEXCAN_LL_ReceiveEnhanceFifo(pCanHandle);
pCanHandle->tSettings.pRxBuf->u8RxHandle = 0xFFU;
#if FLEXCAN_RX_FLAG_CLEAR_FIRST == STD_ON
/* check fd fifo data available */
u32Status = FLEXCAN_HWA_ERFSRGetDataValid(pCan);
pCanHandle->tSettings.pRxNotify(pCanHandle, pCanHandle->tSettings.pRxBuf);
#else
pCanHandle->tSettings.pRxNotify(pCanHandle, pCanHandle->tSettings.pRxBuf);
/* check fd fifo data available */
u32Status = FLEXCAN_HWA_ERFSRGetDataValid(pCan);
#endif
}
}
/**
* @brief Polling Enhanced Rx FIFO error
*
* @param pCanHandle Can handle point
*/
static void FLEXCAN_LL_PollingEnhancedFifoError(FLEXCAN_HandleType *pCanHandle)
{
FLEXCAN_Type *pCan;
FLEXCAN_FifoIssueType tFifoIssue;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
tFifoIssue.eFifoType = FLEXCAN_ENHANCED_FIFO;
tFifoIssue.u8FifoWarings = 0U;
if (FLEXCAN_HWA_ERFSRGetUnderflow(pCan) != 0U)
{
tFifoIssue.u8FifoUnderflow = 1U;
}
else
{
tFifoIssue.u8FifoUnderflow = 0U;
}
if (FLEXCAN_HWA_ERFSRGetOverflow(pCan) != 0U)
{
tFifoIssue.u8FifoOverflow = 1U;
}
else
{
tFifoIssue.u8FifoOverflow = 0U;
}
#if FLEXCAN_ERROR_FLAG_CLEAR_FIRST == STD_ON
if(tFifoIssue.u8FifoUnderflow)
{
FLEXCAN_HWA_ERFSRClrUnderflow(pCan); /* clear underflow */
pCanHandle->tSettings.pFifoIssueNotify(pCanHandle, &tFifoIssue);
}
if(tFifoIssue.u8FifoOverflow)
{
FLEXCAN_HWA_ERFSRClrOverflow(pCan); /* clean overflow */
pCanHandle->tSettings.pFifoIssueNotify(pCanHandle, &tFifoIssue);
}
#else
if(tFifoIssue.u8FifoUnderflow)
{
pCanHandle->tSettings.pFifoIssueNotify(pCanHandle, &tFifoIssue);
FLEXCAN_HWA_ERFSRClrUnderflow(pCan); /* clear underflow */
}
if(tFifoIssue.u8FifoOverflow)
{
pCanHandle->tSettings.pFifoIssueNotify(pCanHandle, &tFifoIssue);
FLEXCAN_HWA_ERFSRClrOverflow(pCan); /* clean overflow */
}
#endif
}
/**
* @brief Set Legacy Rx FIFO
*
* @param pCanHandle Can handle point
* @param pRxFilterList Filter id list
* @param u32RxFilterCnt Filter id list length
* @return FLEXCAN_E_OK is ok
*/
static FLEXCAN_ErrorType FLEXCAN_LL_SetLegacyFifo(FLEXCAN_HandleType *pCanHandle, FLEXCAN_FifoFilterType *pRxFilterList, uint32_t u32RxFilterCnt)
{
FLEXCAN_ErrorType tRetVal;
uint32_t u32Index;
FLEXCAN_Type *pCan;
uint32_t u32ElementNum;
const FLEXCAN_LegacyFifoFilterType *pLegacyFilter = NULL;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
tRetVal = FLEXCAN_LL_CheckLengcyFifoNum(u32RxFilterCnt);
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
pCanHandle->tStatus.u8MbStart = 0U;
/* set legacy fifo */
FLEXCAN_HWA_EnableLegacyFifo(pCan);
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/* filter element number must be multi of 8 */
if ((u32RxFilterCnt % 8U) || (u32RxFilterCnt > FLEXCAN_LEGACY_FIFO_ELEMENT_MAX))
{
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_PARAM);
}
#endif
for (u32Index = 0U; u32Index < sizeof(s_aFlexCan_LegacyFilterCheckTable)/sizeof(s_aFlexCan_LegacyFilterCheckTable[0]); u32Index++)
{
if (s_aFlexCan_LegacyFilterCheckTable[u32Index].u8LegacyFilterNum == u32RxFilterCnt)
{
pLegacyFilter = &s_aFlexCan_LegacyFilterCheckTable[u32Index];
break;
}
}
if(pLegacyFilter==NULL)
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
else
{
/* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 */
/* Format A: RTR IDE | RXIDA (standard =29-19, extended = 29-1) | */
/* Format B: RTR IDE | RXIDB_0 (standart = 29-19, extended = 29-16) MSB compare | RTR IDE|RXIDB_1 (standart = 13-3, extended = 13-0) MSB compare */
/* Format C: RXIDC_0 (std/ext = 31-24) MSB compare | RXIDC_1 (std/ext = 23-16) MSB compare | RXIDC_2 (std/ext =15-8) MSB compare | RXIDC_3 (std/ext =7-0) MSB compare */
/* always format A */
u32ElementNum = 0U;
for (u32Index = 0U; u32Index < u32RxFilterCnt; u32Index++)
{
/* extended id */
if (pRxFilterList[u32Index].eRxFrameType == FLEXCAN_ID_EXT)
{
FLEXCAN_HWA_MbRam(pCan, CAN_ONEMB_WORD_NUM * FLEXCAN_LEGACY_FIFO_FILTER_START + u32Index, (1U << 30) | (pRxFilterList[u32Index].u32RxCanId << 1)); /* id */
if (u32Index < pLegacyFilter->u8MbUsedForLegacyFifo)
{
FLEXCAN_HWA_SetIndividualMask(pCan, u32Index, (1U << 30) | (pRxFilterList[u32Index].u32RxCanIdMask << 1)); /* mask */
}
else /* left used global rx fifo mask */
{
FLEXCAN_HWA_SetFifoGlobalMask(pCan, (1U << 30) | (pRxFilterList[u32Index].u32RxCanIdMask << 1));
}
u32ElementNum += 2U;
}
else /* standard id */
{
FLEXCAN_HWA_MbRam(pCan, CAN_ONEMB_WORD_NUM * FLEXCAN_LEGACY_FIFO_FILTER_START + u32Index, pRxFilterList[u32Index].u32RxCanId << 19); /* id */
if (u32Index < pLegacyFilter->u8MbUsedForLegacyFifo)
{
FLEXCAN_HWA_SetIndividualMask(pCan, u32Index, pRxFilterList[u32Index].u32RxCanIdMask << 19); /* mask */
}
else /* left used global rx fifo mask */
{
FLEXCAN_HWA_SetFifoGlobalMask(pCan, pRxFilterList[u32Index].u32RxCanIdMask << 19);
}
u32ElementNum++;
}
}
if(u32ElementNum > FLEXCAN_LEGACY_FIFO_ELEMENT_MAX)
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
}
else
{
/* set fifo filter num */
FLEXCAN_HWA_SetLegacyFifoFilterNum(pCan, pLegacyFilter->u8RFFN);
/* insert rx filter before tx message buffer, every group filter contains 8 elements(2MBs), at least 2 groups */
pCanHandle->tStatus.u8MbStart = pLegacyFilter->u8MbUsedForLegacyFifo;
}
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
#endif
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
#endif
return tRetVal;
}
/**
* @brief Set Enhanced Rx FIFO
*
* @param pCanHandle Can Handle point
* @param pRxFilterList Filter id list
* @param u32RxFilterCnt Filter id list length
* @param u8WaterMark DMA Wartmark
* @return FLEXCAN_E_OK is ok
*/
static FLEXCAN_ErrorType FLEXCAN_LL_SetEnhancedFifo(FLEXCAN_HandleType *pCanHandle, const FLEXCAN_InitType *const pInitCfg)
{
FLEXCAN_ErrorType tRetVal;
uint32_t u32FilterNum;
uint32_t u32Index;
FLEXCAN_Type *pCan;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
tRetVal = FLEXCAN_LL_CheckFdInstance(pCanHandle->eInstance);
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
uint32_t u32ExtIDFilterNum;
uint32_t u32StdIDFilterNum;
uint32_t u32TempERFCR;
/* current pCan instance */
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
/* Configure the filter elements by writing in the ERFFELn registers (ERFFELn registers are implemented in RAM; thus, they must be explicitly initialized prior to any reception). */
/* standard id filter */
/* 31-30 29-28 27 26-16 15-12 11 10-0 */
/* FSCH=b00 Reserved RTR filter STD ID filter Reserved RTR mask STD ID mask id_filter&id_mask */
/* FSCH=b01 Reserved RTR filter STD ID filter2 Reserved RTR mask STD ID filter1 id filter1<=id<= id filter2 */
/* FSCH=b10 Reserved RTR filter2 STD ID filter2 Reserved RTR filter1 STD ID filter1 id filter1= id = id filter2 */
/* extended id filter */
/* 31-30 29 28-0 */
/* FSCH=00b RTR filter EXT ID filter */
/* Reserved RTR mask EXT ID mask */
/* FSCH=01b RTR filter EXT ID filter2 */
/* Reserved RTR mask EXT ID filter1 */
/* FSCH=10b RTR filter2 EXT ID filter2 */
/* Reserved RTR filter1 EXT ID filter1 */
u32ExtIDFilterNum = 0U;
u32StdIDFilterNum = 0U;
/* set extended id mask first */
for (u32Index = 0U; u32Index < pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.u8RxFilterFifoCnt; u32Index++)
{
if (pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.pRxFilterFifoList[u32Index].eRxFrameType == FLEXCAN_ID_EXT)
{
/* extended id first */
/* pCan->ERFFEL[u32Index] &= 0xFFFFFFFU; */
FLEXCAN_HWA_EnhancedFifoFilter(pCan, u32ExtIDFilterNum * 2U, pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.pRxFilterFifoList[u32Index].u32RxCanId); /* id */
FLEXCAN_HWA_EnhancedFifoFilter(pCan, u32ExtIDFilterNum * 2U + 1U, pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.pRxFilterFifoList[u32Index].u32RxCanIdMask); /* mask */
u32ExtIDFilterNum++;
}
}
/* set standard id mask */
for (u32Index = 0U; u32Index < pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.u8RxFilterFifoCnt; u32Index++)
{
/* standard id */
if (pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.pRxFilterFifoList[u32Index].eRxFrameType == FLEXCAN_ID_STD)
{
FLEXCAN_HWA_EnhancedFifoFilter(pCan, u32ExtIDFilterNum * 2U + u32StdIDFilterNum,
(pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.pRxFilterFifoList[u32Index].u32RxCanId << 16) | pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.pRxFilterFifoList[u32Index].u32RxCanIdMask);
u32StdIDFilterNum++;
}
}
/* standard id number must multiple of 2 */
tRetVal = (FLEXCAN_ErrorType)(tRetVal | ((u32StdIDFilterNum % 2U == 1U) ? FLEXCAN_E_INVALID_PARAM : FLEXCAN_E_OK));
if (tRetVal == FLEXCAN_E_OK)
{
/* total id filter number */
u32FilterNum = u32ExtIDFilterNum*2 + u32StdIDFilterNum;
if(u32FilterNum > s_aFlexCanEnhancedElementNums[pCanHandle->eInstance])
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
}
else
{
/* Write one to ERFSR[ERFCLR] to reset Enhanced Rx FIFO engine */
FLEXCAN_HWA_ERFSRResetEnhancedFifo(pCan);
/* Clear EFRSR[ERFUFW], EFRSR[ERFOVF], EFRSR[ERFWMI], and EFRSR[ERFDA], if they are set. */
FLEXCAN_HWA_ERFSRClearEnhancedFifoFlag(pCan, FLEXCAN_ERFSR_ERFOVF_MASK | FLEXCAN_ERFSR_ERFUFW_MASK | FLEXCAN_ERFSR_ERFWMI_MASK | FLEXCAN_ERFSR_ERFDA_MASK);
/* Write EFRCR[NFE] to configure the total number of enhanced Rx FIFO filter elements to be used in Enhanced Rx FIFO reception. */
/* set rx fifo filter num, (n+1)*2 */
u32TempERFCR = ((u32FilterNum / 2U - 1U) << FLEXCAN_ERFCR_NFE_SHIFT)&FLEXCAN_ERFCR_NFE_MASK;
/* Write ERFCR[NEXIF] to configure the number of extended ID and standard ID filter elements to be used in Enhanced Rx FIFO reception (NEXIF NFE + 1). */
/* set rx fifo extended id filter num, <= NFE+1 */
u32TempERFCR |= (u32ExtIDFilterNum << FLEXCAN_ERFCR_NEXIF_SHIFT)&FLEXCAN_ERFCR_NEXIF_MASK;
u32TempERFCR |= FLEXCAN_ERFCR_ERFWM(pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.u8FifoWaterMark - 1U); /* receive 1 message will indicate to fifo water mark */
u32TempERFCR |= FLEXCAN_ERFCR_DMALW((12U + pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.eFifoDataLength) / 4);
u32TempERFCR |= FLEXCAN_ERFCR_ERFEN_MASK; /* enable enhance fifo dma */
FLEXCAN_HWA_SetERFCR(pCan, u32TempERFCR);
/* set enhanced fifo */
FLEXCAN_HWA_EnableFDFifo(pCan);
/* Configure the Enhanced Rx FIFO watermark by writing ERFCR[ERFWM]. */
/* If interrupts will be used, set the interrupt enables in the ERIER register */
/* If DMA will be used, set MCR[DMA] to enable DMA operation and write ERFCR[DMALW] to configure the number of words to transfer for each Enhanced Rx FIFO data element */
}
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
#endif
return tRetVal;
}
/**
* @brief Configure can receive message box and id filter
*
* @param pCanHandle Can Handle point
* @param pCanHandle Contains CAN Instance, Rx CAN ID and Mask
* @return 0 is ok
*/
static FLEXCAN_ErrorType FLEXCAN_LL_RxFilterConfig(FLEXCAN_HandleType *pCanHandle, const FLEXCAN_InitType *const pInitCfg)
{
FLEXCAN_ErrorType tRetVal;
FLEXCAN_Type *pCan;
FLEXCAN_MbSettingType *pCurRxCfg;
uint32_t u32Mask;
uint8_t u8Index11;
uint8_t u8MaskIndex;
uint8_t u8TxMbIndex;
uint8_t u8RxMbIndex;
uint32_t u32TempAddr;
tRetVal = FLEXCAN_E_OK;
/* current pCan instance */
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
if (pInitCfg->tRxFifoFilterCfg.bEnFifo)
{
if (pInitCfg->tRxFifoFilterCfg.eFifoType == FLEXCAN_LEGACY_FIFO)
{
/* set fifo filter parameter */
tRetVal |= FLEXCAN_LL_SetLegacyFifo(pCanHandle, pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.pRxFilterFifoList, (uint32_t)pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.u8RxFilterFifoCnt);
}
else
{
/* only canfd controller support enhanced fifo features */
if (FLEXCAN_LL_CheckFdInstance(pCanHandle->eInstance) == FLEXCAN_E_OK)
{
tRetVal |= (FLEXCAN_ErrorType)(tRetVal | FLEXCAN_LL_SetEnhancedFifo(pCanHandle, pInitCfg));
}
}
}
if((pInitCfg->tMbCfg.u8MBCnt > 0U) && (pInitCfg->tMbCfg.pMBList == NULL) )
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
if(tRetVal == FLEXCAN_E_OK)
{
for(u8Index11=0U; u8Index11 < s_aFlexCanIflagMaskSizes[pCanHandle->eInstance]; u8Index11++)
{
pCanHandle->tStatus.aTxInterruptMask[u8Index11] = 0U;
pCanHandle->tStatus.aTxPollingMask[u8Index11] = 0U;
pCanHandle->tStatus.aRxInterruptMask[u8Index11] = 0U;
pCanHandle->tStatus.aRxPollingMask[u8Index11] = 0U;
pCanHandle->tStatus.aInterruptMask[u8Index11] = 0U;
pCanHandle->tStatus.aPollingMask[u8Index11] = 0U;
}
/* for tx first. */
u8TxMbIndex = pCanHandle->tStatus.u8MbStart;
for(u8Index11=0U; u8Index11 <pInitCfg->tMbCfg.u8MBCnt; u8Index11++ )
{
if(pInitCfg->tMbCfg.pMBList[u8Index11].bIsTxMB == 1U)
{
#if FLEXCAN_ERRATA_TRANSMIT_LIMIT == STD_ON
if(pInitCfg->tRxFifoFilterCfg.bEnFifo && pInitCfg->tRxFifoFilterCfg.eFifoType == FLEXCAN_ENHANCED_FIFO)
{
while(FLEXCAN_LL_CheckContains(s_aFlexCan_TransmitLimit_List, FLEXCAN_ERRATA_TRANSMIT_LM_LIST_LEN, u8TxMbIndex)==1U)
{
u8TxMbIndex = (uint8_t)(u8TxMbIndex + 1U);
}
}
#endif
if(u8TxMbIndex<32U)
u8MaskIndex = 0U;
else if(u8TxMbIndex<64U)
u8MaskIndex = 1U;
else if(u8TxMbIndex<96U)
u8MaskIndex = 2U;
else
u8MaskIndex = 0U;
if(pInitCfg->tMbCfg.pMBList[u8Index11].bEnMBInt)
{
pCanHandle->tStatus.aTxInterruptMask[u8MaskIndex] = pCanHandle->tStatus.aTxInterruptMask[u8MaskIndex] + (1U<<u8TxMbIndex);
pCanHandle->tStatus.aInterruptMask[u8MaskIndex] = pCanHandle->tStatus.aInterruptMask[u8MaskIndex] + (1U<<u8TxMbIndex);
}
else
{
pCanHandle->tStatus.aTxPollingMask[u8MaskIndex] = pCanHandle->tStatus.aTxPollingMask[u8MaskIndex] + (1U<<u8TxMbIndex);
pCanHandle->tStatus.aPollingMask[u8MaskIndex] = pCanHandle->tStatus.aPollingMask[u8MaskIndex] + (1U<<u8TxMbIndex);
}
u8TxMbIndex = (uint8_t)(u8TxMbIndex + 1U);
}
}
/* for rx first. */
u8RxMbIndex = pCanHandle->tStatus.u8MbStart;
for(u8Index11=0U; u8Index11 <pInitCfg->tMbCfg.u8MBCnt; u8Index11++ )
{
if(pInitCfg->tMbCfg.pMBList[u8Index11].bIsTxMB == 0U)
{
if(u8RxMbIndex<32U)
u8MaskIndex = 0U;
else if(u8RxMbIndex<64U)
u8MaskIndex = 1U;
else if(u8RxMbIndex<96U)
u8MaskIndex = 2U;
else
u8MaskIndex = 0U;
/* is tx occupied */
while((((pCanHandle->tStatus.aTxInterruptMask[u8MaskIndex]>>u8RxMbIndex)&0x01U)==0x01U) || (((pCanHandle->tStatus.aTxPollingMask[u8MaskIndex]>>u8RxMbIndex)&0x01U)==0x01U) )
{
u8RxMbIndex = (uint8_t)(u8RxMbIndex + 1U);
}
if(pInitCfg->tMbCfg.pMBList[u8Index11].bEnMBInt)
{
pCanHandle->tStatus.aRxInterruptMask[u8MaskIndex] = pCanHandle->tStatus.aRxInterruptMask[u8MaskIndex] + (1U<<u8RxMbIndex);
pCanHandle->tStatus.aInterruptMask[u8MaskIndex] = pCanHandle->tStatus.aInterruptMask[u8MaskIndex] + (1U<<u8RxMbIndex);
}
else
{
pCanHandle->tStatus.aRxPollingMask[u8MaskIndex] = pCanHandle->tStatus.aRxPollingMask[u8MaskIndex] + (1U<<u8RxMbIndex);
pCanHandle->tStatus.aPollingMask[u8MaskIndex] = pCanHandle->tStatus.aPollingMask[u8MaskIndex] + (1U<<u8RxMbIndex);
}
uint8_t u8DateLen;
/* ############## current rx pMb #################### */
u8DateLen = FLEXCAN_MB_GET_DATALEN(u8RxMbIndex, s_aFlexCanMbNums[pCanHandle->eInstance],s_aFlexCanDataLenNums[pCanHandle->eInstance], pCanHandle->tStatus.aMbDataWidth);
/* current rx filter */
pCurRxCfg = &(pInitCfg->tMbCfg.pMBList[u8Index11]);
/* message buffer 1th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RxMbIndex, u8DateLen, 0U);
FLEXCAN_MB_IDE_SRR_SET(u32TempAddr, (pCurRxCfg->eRxFrameType == FLEXCAN_ID_STD) ? (pCurRxCfg->eRxFrameType) : (pCurRxCfg->eRxFrameType | FLEXCAN_MB_SRR_MASK_U32));
/* message buffer 2th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RxMbIndex, u8DateLen, 4U);
/* 1. set filter id */
if (pCurRxCfg->eRxFrameType == FLEXCAN_ID_STD)
{
FLEXCAN_MB_STDID_SET(u32TempAddr, pCurRxCfg->u32RxCanId);
u32Mask = pCurRxCfg->u32RxCanIdMask << 18U; /* stardard id left shift 18 bits */
}
else /* extended id filter */
{
FLEXCAN_MB_EXTID_SET(u32TempAddr, pCurRxCfg->u32RxCanId);
u32Mask = pCurRxCfg->u32RxCanIdMask; /* extendex id */
}
/* message buffer 1th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RxMbIndex, u8DateLen, 0U);
/* set code 0x04U to enable rx */
FLEXCAN_MB_CODE_SET(u32TempAddr, 4U);
/* 3. set rx filter u32Mask */
#if 1
{
/* In FRZ mode, init CAN1 16 msg buf filters */
FLEXCAN_HWA_SetIndividualMask(pCan, (uint32_t)u8RxMbIndex, u32Mask);
}
#else
{
/* global u32Mask */
/* Global acceptance u32Mask: check all ID bits */
if (u8RxMbIndex == 14U)
{
FLEXCAN_HWA_SetRx14Mask(pCan, u32Mask);
}
else if (u8RxMbIndex == 15U)
{
FLEXCAN_HWA_SetRx15Mask(pCan, u32Mask);
}
else
{
FLEXCAN_HWA_SetMBGlobalMask(pCan, u32Mask);
}
}
#endif
u8RxMbIndex = (uint8_t)(u8RxMbIndex + 1U);
}
}
if(u8TxMbIndex > u8RxMbIndex)
u8RxMbIndex = u8TxMbIndex;
/* set max pMb number */
FLEXCAN_HWA_AttachMCR(pCan, FLEXCAN_MCR_MAXMB(u8RxMbIndex-1U) /* Maximum pMb index */
| FLEXCAN_MCR_IRMQ(1U)); /* individual Rx masking */
}
return tRetVal;
}
/**
* @brief Configure can interrupt
*
* @param pCanHandle Can Handle point
* @param pIntCfg Contians interrupt enable and call back function points
* @return 0 is ok
*/
static FLEXCAN_ErrorType FLEXCAN_LL_SetInterrupt(FLEXCAN_HandleType *pCanHandle, const FLEXCAN_InitType *const pInitCfg)
{
FLEXCAN_ErrorType tRetVal;
FLEXCAN_Type *pCan;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
/* check buffer point if it is null */
if (((pInitCfg->bEnErrInt == 1U) || (pInitCfg->bEnBusOffInt == 1U) ||
(pInitCfg->bEnWarningInt == 1U) || (pInitCfg->bEnBusOffDoneInt == 1U) ) &&
(pCanHandle->tSettings.pErrorNotify == NULL))
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
// if ((pInitCfg->tMbCfg.bEnTxMBInt == 1U) && (pCanHandle->tSettings.pTxNotify == NULL))
// {
// tRetVal |= FLEXCAN_E_NULL_POINT;
// }
// if ((pInitCfg->tMbCfg.bEnRxMBInt == 1U) && (pCanHandle->tSettings.pRxNotify == NULL))
// {
// tRetVal |= FLEXCAN_E_NULL_POINT;
// }
if(pInitCfg->tRxFifoFilterCfg.bEnFifo)
{
if(pInitCfg->tRxFifoFilterCfg.eFifoType == FLEXCAN_LEGACY_FIFO)
{
if ((pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.bDataAvaliableInt == 1U) && (pCanHandle->tSettings.pRxNotify == NULL))
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
if ((pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.bOverflowInt == 1U) && (pCanHandle->tSettings.pFifoIssueNotify == NULL))
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
if ((pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.bWarningInt == 1U) && (pCanHandle->tSettings.pFifoIssueNotify == NULL))
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
}
else
{
if ((pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.bDataAvaliableInt == 1U) && (pCanHandle->tSettings.pRxNotify == NULL))
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
if ((pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.bOverflowInt == 1U) && (pCanHandle->tSettings.pFifoIssueNotify == NULL))
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
if ((pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.bUnderflowInt == 1U) && (pCanHandle->tSettings.pFifoIssueNotify == NULL))
{
tRetVal |= FLEXCAN_E_NULL_POINT;
}
}
}
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
if (pInitCfg->bEnErrInt)
{
FLEXCAN_HWA_AttachCtrl1(pCan, FLEXCAN_CTRL1_ERRMSK(1U) ); /* error interrupt u32Mask */
if (FLEXCAN_LL_CheckFdInstance(pCanHandle->eInstance) == FLEXCAN_E_OK)
{
FLEXCAN_HWA_AttachCtrl2(pCan, FLEXCAN_CTRL2_ERRMSK_FAST(1U) /* fast error */);
}
}
if (pInitCfg->bEnBusOffInt)
{
FLEXCAN_HWA_AttachCtrl1(pCan, FLEXCAN_CTRL1_BOFFMSK(1U)); /* busoff interrupt u32Mask */
}
if (pInitCfg->bEnBusOffDoneInt)
{
FLEXCAN_HWA_AttachCtrl2(pCan, FLEXCAN_CTRL2_BOFFDONEMSK(1U) /* busoff done interrupt mask */);
}
if (pInitCfg->bEnWarningInt)
{
FLEXCAN_HWA_AttachCtrl1(pCan, FLEXCAN_CTRL1_TWRNMSK(1U) | FLEXCAN_CTRL1_RWRNMSK(1U) /* tx/rx warning interrupt mask */);
}
if (pInitCfg->tRxFifoFilterCfg.bEnFifo)
{
if (pInitCfg->tRxFifoFilterCfg.eFifoType == FLEXCAN_LEGACY_FIFO) /* legacy fifo */
{
FLEXCAN_HWA_SetMask1MbInterrupt(pCan, (uint32_t)(((uint32_t)pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.bDataAvaliableInt)<<5U) |
(uint32_t)(((uint32_t)pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.bWarningInt)<<6U) |
(uint32_t)(((uint32_t)pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.bOverflowInt)<<7U) );
}
else /* enhance fifo */
{
FLEXCAN_HWA_SetERFIER(pCan, FLEXCAN_ERFIER_ERFDAIE(pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.bDataAvaliableInt) |
FLEXCAN_ERFIER_ERFWMIIE(pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.bWaterMarkInt) |
FLEXCAN_ERFIER_ERFOVFIE(pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.bOverflowInt) |
FLEXCAN_ERFIER_ERFUFWIE(pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.bUnderflowInt) );
}
}
/* MB 31-0 IMASK1 */
FLEXCAN_HWA_AttachMask1MbInterrupt(pCan, pCanHandle->tStatus.aInterruptMask[0]);
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
/* MB 63-32 IMASK2 */
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
FLEXCAN_HWA_AttachMask2MbInterrupt(pCan, pCanHandle->tStatus.aInterruptMask[1]);
}
#endif
#if FLEXCAN_IFLAGMASK_NUM_MAX > 2U
/* MB 95-64 IMASK3 */
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
FLEXCAN_HWA_AttachMask3MbInterrupt(pCan, pCanHandle->tStatus.aInterruptMask[2]);
}
#endif
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
#endif
return tRetVal;
}
/**
* @brief Configure can pretended network
*
* @param pCanHandle Contains CAN Instance, Rx CAN ID and Mask
* @param pInitCfg initial parameters
* @return 0 is ok
*/
static inline FLEXCAN_ErrorType FLEXCAN_LL_SetPNETPayload(FLEXCAN_Type *pCan, const FLEXCAN_InitType *const pInitCfg)
{
FLEXCAN_ErrorType tRetVal;
tRetVal = FLEXCAN_E_OK;
if( (pInitCfg->tPnetCfg.tPayloadCfg.u8DataLen1 > 8U ) ||
(pInitCfg->tPnetCfg.tPayloadCfg.u8DataLen2 > 8U) )
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
}
else
{
FLEXCAN_HWA_AttachPNET_PayloadFilterType(pCan, pInitCfg->tPnetCfg.tPayloadCfg.eFilterType);
FLEXCAN_HWA_SetPNET_DlcRange(pCan, pInitCfg->tPnetCfg.tPayloadCfg.u8DataLen1, pInitCfg->tPnetCfg.tPayloadCfg.u8DataLen2);
FLEXCAN_HWA_SetPNET_Payload1Content(pCan,pInitCfg->tPnetCfg.tPayloadCfg.aData1[1],pInitCfg->tPnetCfg.tPayloadCfg.aData1[0]);
if(pInitCfg->tPnetCfg.tPayloadCfg.eFilterType == FLEXCAN_PNET_PAYLOAD_FILTER_SAME)
{
/* FLT_DLC_LO must same to FLT_DLC_HI */
if(pInitCfg->tPnetCfg.tPayloadCfg.u8DataLen1 == pInitCfg->tPnetCfg.tPayloadCfg.u8DataLen2)
{
/* Mask */
FLEXCAN_HWA_SetPNET_Payload2Content(pCan,pInitCfg->tPnetCfg.tPayloadCfg.aData2[1],pInitCfg->tPnetCfg.tPayloadCfg.aData2[0]);
}
else
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
}
}
else if(pInitCfg->tPnetCfg.tPayloadCfg.eFilterType == FLEXCAN_PNET_PAYLOAD_FILTER_GREATER_EQUAL)
{
}
else if(pInitCfg->tPnetCfg.tPayloadCfg.eFilterType == FLEXCAN_PNET_PAYLOAD_FILTER_SMALLER_EQUAL)
{
}
else if(pInitCfg->tPnetCfg.tPayloadCfg.eFilterType == FLEXCAN_PNET_PAYLOAD_FILTER_RANGE)
{
/* Data1 <= data <= Data2 */
FLEXCAN_HWA_SetPNET_Payload2Content(pCan,pInitCfg->tPnetCfg.tPayloadCfg.aData2[1],pInitCfg->tPnetCfg.tPayloadCfg.aData2[0]);
}
else
{
}
}
return tRetVal;
}
/**
* @brief Configure can pretended network
*
* @param pCanHandle Contains CAN Instance, Rx CAN ID and Mask
* @param pInitCfg initial parameters
* @return 0 is ok
*/
static FLEXCAN_ErrorType FLEXCAN_LL_SetPNET(FLEXCAN_HandleType *pCanHandle, const FLEXCAN_InitType *const pInitCfg)
{
FLEXCAN_ErrorType tRetVal;
FLEXCAN_Type *pCan;
tRetVal = FLEXCAN_E_OK;
/* current pCan instance */
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
FLEXCAN_HWA_ClrPNET_CTRL1_PN(pCan);
if(pCanHandle->tSettings.pWakeNotify==NULL)
{
tRetVal = FLEXCAN_E_NULL_POINT;
}
else
{
/* timeout */
if(pInitCfg->tPnetCfg.bTimeoutEn)
{
FLEXCAN_HWA_SetPNET_Timeout(pCan, pInitCfg->tPnetCfg.u16Timeout); /* timeout value, 64 times of can bit time */
FLEXCAN_HWA_AttachPNET_TimeoutInterrupt(pCan); /* timeout interrupt */
}
/* match filter */
if(pInitCfg->tPnetCfg.bFilterEnable)
{
FLEXCAN_HWA_AttachPNET_FilterType(pCan, (uint8_t)pInitCfg->tPnetCfg.ePnetFilterType); /* filter type */
FLEXCAN_HWA_AttachPNET_MatchCount(pCan, pInitCfg->tPnetCfg.u8MatchTimes); /* match count */
FLEXCAN_HWA_AttachPNET_MatchInterrupt(pCan); /* match interrupt */
/* 4 types filter always contain id filter */
FLEXCAN_HWA_AttachPNET_IDFilterType(pCan, pInitCfg->tPnetCfg.tIdCfg.eFilterType); /* id filter type */
FLEXCAN_HWA_SetPNET_ID1(pCan, pInitCfg->tPnetCfg.tIdCfg.tID1.u8IDE, pInitCfg->tPnetCfg.tIdCfg.tID1.u8RTR, pInitCfg->tPnetCfg.tIdCfg.tID1.u32Id);
if(pInitCfg->tPnetCfg.tIdCfg.eFilterType == FLEXCAN_PNET_ID_FILTER_SAME)
{
/* mask */
FLEXCAN_HWA_SetPNET_ID2(pCan, pInitCfg->tPnetCfg.tIdCfg.tID2_Mask.u8IDE, pInitCfg->tPnetCfg.tIdCfg.tID2_Mask.u8RTR, pInitCfg->tPnetCfg.tIdCfg.tID2_Mask.u32Id);
}
else if(pInitCfg->tPnetCfg.tIdCfg.eFilterType == FLEXCAN_PNET_ID_FILTER_GREATER_EQUAL)
{
}
else if(pInitCfg->tPnetCfg.tIdCfg.eFilterType == FLEXCAN_PNET_ID_FILTER_SMALLER_EQUAL)
{
}
else if(pInitCfg->tPnetCfg.tIdCfg.eFilterType == FLEXCAN_PNET_ID_FILTER_RANGE)
{
/* ID1 <= id <= ID2 */
FLEXCAN_HWA_SetPNET_ID2(pCan, pInitCfg->tPnetCfg.tIdCfg.tID2_Mask.u8IDE, pInitCfg->tPnetCfg.tIdCfg.tID2_Mask.u8RTR, pInitCfg->tPnetCfg.tIdCfg.tID2_Mask.u32Id);
}
else
{
}
if(pInitCfg->tPnetCfg.ePnetFilterType == FLEXCAN_PNET_ID_FILTER)
{
}
else if(pInitCfg->tPnetCfg.ePnetFilterType == FLEXCAN_PNET_ID_AND_PAYLOAD_FILTER) /* payload contained */
{
tRetVal |= FLEXCAN_LL_SetPNETPayload(pCan, pInitCfg);
}
else if(pInitCfg->tPnetCfg.ePnetFilterType == FLEXCAN_PNET_ID_FILTER_WITH_NCOUNT)
{
FLEXCAN_HWA_AttachPNET_MatchCount(pCan,pInitCfg->tPnetCfg.u8MatchTimes); /* match times */
}
else if(pInitCfg->tPnetCfg.ePnetFilterType == FLEXCAN_PNET_ID_AND_PAYLOAD_FILTER_WITH_NCOUNT) /* payload contained */
{
FLEXCAN_HWA_AttachPNET_MatchCount(pCan,pInitCfg->tPnetCfg.u8MatchTimes); /* match times */
tRetVal |= FLEXCAN_LL_SetPNETPayload(pCan, pInitCfg);
}
else
{
}
}
}
return tRetVal;
}
/**
* @brief Interrupt check Tx Iflag and return Handler flag
*
* @param pCanHandle Can Handle Point
*/
static void FLEXCAN_LL_InterruptTx(FLEXCAN_HandleType *pCanHandle)
{
uint8_t u8MbIndex;
FLEXCAN_Type *pCan;
uint32_t u32Iflag;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u32Iflag = FLEXCAN_HWA_GetFlag1(pCan) & (pCanHandle->tStatus.aTxInterruptMask[0]);
if(u32Iflag)
{
u8MbIndex = 0U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
#if FLEXCAN_TX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag1(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
#else
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
FLEXCAN_HWA_SetFlag1(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
u32Iflag = FLEXCAN_HWA_GetFlag2(pCan) & (pCanHandle->tStatus.aTxInterruptMask[1]);
if(u32Iflag)
{
u8MbIndex = 32U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
#if FLEXCAN_TX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag2(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
#else
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
FLEXCAN_HWA_SetFlag2(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
}
#endif
#if FLEXCAN_IFLAGMASK_NUM_MAX > 2U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
u32Iflag = FLEXCAN_HWA_GetFlag3(pCan) & (pCanHandle->tStatus.aTxInterruptMask[2]);
if(u32Iflag)
{
u8MbIndex = 64U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
#if FLEXCAN_TX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag3(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
#else
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
FLEXCAN_HWA_SetFlag3(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
}
#endif
}
/**
* @brief Polling Tx Iflag
*
* @param pCanHandle Can Handle Point
*/
static void FLEXCAN_LL_PollingTx(FLEXCAN_HandleType *pCanHandle)
{
uint8_t u8MbIndex;
FLEXCAN_Type *pCan;
uint32_t u32Iflag;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u32Iflag = FLEXCAN_HWA_GetFlag1(pCan) & (pCanHandle->tStatus.aTxPollingMask[0]);
if(u32Iflag)
{
u8MbIndex = 0U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
#if FLEXCAN_TX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag1(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
#else
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
FLEXCAN_HWA_SetFlag1(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
u32Iflag = FLEXCAN_HWA_GetFlag2(pCan) & (pCanHandle->tStatus.aTxPollingMask[1]);
if(u32Iflag)
{
u8MbIndex = 32U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
#if FLEXCAN_TX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag2(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
#else
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
FLEXCAN_HWA_SetFlag2(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
}
#endif
#if FLEXCAN_IFLAGMASK_NUM_MAX > 2U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
u32Iflag = FLEXCAN_HWA_GetFlag3(pCan) & (pCanHandle->tStatus.aTxPollingMask[2]);
if(u32Iflag)
{
u8MbIndex = 64U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
#if FLEXCAN_TX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag3(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
#else
pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex));
FLEXCAN_HWA_SetFlag3(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
}
#endif
}
/**
* @brief Interrupt check Message Buffer Received Data
*
* @param u8CanIndex Can Index, Must less than FLEXCAN_INSTANCE_COUNT
* @param pRxMsgList Message Stored buffer point
*/
static void FLEXCAN_LL_InterruptRx(FLEXCAN_HandleType *pCanHandle)
{
uint8_t u8MbIndex;
FLEXCAN_Type *pCan;
uint32_t u32Iflag;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u32Iflag = FLEXCAN_HWA_GetFlag1(pCan) & (pCanHandle->tStatus.aRxInterruptMask[0]);
if(u32Iflag)
{
u8MbIndex = 0U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
FLEXCAN_LL_ReceiveMb(pCanHandle, u8MbIndex);
pCanHandle->tSettings.pRxBuf->u8RxHandle = FLEXCAN_LL_GetRxHandleByMbIndex(pCanHandle,u8MbIndex);
#if FLEXCAN_RX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag1(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
#else
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
FLEXCAN_HWA_SetFlag1(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
u32Iflag = FLEXCAN_HWA_GetFlag2(pCan) & (pCanHandle->tStatus.aRxInterruptMask[1]);
if(u32Iflag)
{
u8MbIndex = 32U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
FLEXCAN_LL_ReceiveMb(pCanHandle, u8MbIndex);
pCanHandle->tSettings.pRxBuf->u8RxHandle = FLEXCAN_LL_GetRxHandleByMbIndex(pCanHandle,u8MbIndex);
#if FLEXCAN_RX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag2(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
#else
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
FLEXCAN_HWA_SetFlag2(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
}
#endif
#if FLEXCAN_IFLAGMASK_NUM_MAX > 2U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
u32Iflag = FLEXCAN_HWA_GetFlag3(pCan) & (pCanHandle->tStatus.aRxInterruptMask[2]);
if(u32Iflag)
{
u8MbIndex = 64U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
FLEXCAN_LL_ReceiveMb(pCanHandle, u8MbIndex);
pCanHandle->tSettings.pRxBuf->u8RxHandle = FLEXCAN_LL_GetRxHandleByMbIndex(pCanHandle,u8MbIndex);
#if FLEXCAN_RX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag3(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
#else
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
FLEXCAN_HWA_SetFlag3(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
}
#endif
}
/**
* @brief Polling Message Buffer Received Data
*
* @param u8CanIndex Can Index, Must less than FLEXCAN_INSTANCE_COUNT
* @param pRxMsgList Message Stored buffer point
*/
static void FLEXCAN_LL_PollingRx(FLEXCAN_HandleType *pCanHandle)
{
uint8_t u8MbIndex;
FLEXCAN_Type *pCan;
uint32_t u32Iflag;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u32Iflag = FLEXCAN_HWA_GetFlag1(pCan) & (pCanHandle->tStatus.aRxPollingMask[0]);
if(u32Iflag)
{
u8MbIndex = 0U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
FLEXCAN_LL_ReceiveMb(pCanHandle, u8MbIndex);
pCanHandle->tSettings.pRxBuf->u8RxHandle = FLEXCAN_LL_GetRxHandleByMbIndex(pCanHandle,u8MbIndex);
#if FLEXCAN_RX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag1(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
#else
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
FLEXCAN_HWA_SetFlag1(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
#if FLEXCAN_IFLAGMASK_NUM_MAX > 1U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 1U)
{
u32Iflag = FLEXCAN_HWA_GetFlag2(pCan) & (pCanHandle->tStatus.aRxPollingMask[1]);
if(u32Iflag)
{
u8MbIndex = 32U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
FLEXCAN_LL_ReceiveMb(pCanHandle, u8MbIndex);
pCanHandle->tSettings.pRxBuf->u8RxHandle = FLEXCAN_LL_GetRxHandleByMbIndex(pCanHandle,u8MbIndex);
#if FLEXCAN_RX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag2(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
#else
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
FLEXCAN_HWA_SetFlag2(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
}
#endif
#if FLEXCAN_IFLAGMASK_NUM_MAX > 2U
if(s_aFlexCanIflagMaskSizes[pCanHandle->eInstance] > 2U)
{
u32Iflag = FLEXCAN_HWA_GetFlag3(pCan) & (pCanHandle->tStatus.aRxPollingMask[2]);
if(u32Iflag)
{
u8MbIndex = 64U;
while ((u32Iflag != 0U))
{
if ((u32Iflag & 0x01U) == 0x01U)
{
FLEXCAN_LL_ReceiveMb(pCanHandle, u8MbIndex);
pCanHandle->tSettings.pRxBuf->u8RxHandle = FLEXCAN_LL_GetRxHandleByMbIndex(pCanHandle,u8MbIndex);
#if FLEXCAN_RX_FLAG_CLEAR_FIRST == STD_ON
FLEXCAN_HWA_SetFlag3(pCan, 1U<<u8MbIndex);
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
#else
pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]);
FLEXCAN_HWA_SetFlag3(pCan, 1U<<u8MbIndex);
#endif
}
u8MbIndex++;
u32Iflag = u32Iflag >> 1;
}
}
}
#endif
}
/**
* @brief Get can error
*
* @param pCanHandle Can Index, must less than FLEXCAN_INSTANCE_COUNT
* @param bInterrupt if it is called in interrupt, set 1
* @return error structure
*/
static FLEXCAN_ErrorType FLEXCAN_LL_ProcessError(FLEXCAN_HandleType *pCanHandle, uint8_t bInterrupt)
{
FLEXCAN_ErrorType tRetVal;
FLEXCAN_Type *pCan;
FLEXCAN_ErrorInfoType tErrorInfo;
uint32_t u32ECR;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq >= FLEXCAN_SEQUENCE_NOTSTART))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
}
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
tErrorInfo.u32ESR1Value = FLEXCAN_HWA_GetErrorInfo(pCan);
u32ECR = FLEXCAN_HWA_GetErrorCount(pCan);
tErrorInfo.u32ESR1Value &= FLEXCAN_ESR1_BIT1ERR_FAST_MASK | FLEXCAN_ESR1_BIT0ERR_FAST_MASK | FLEXCAN_ESR1_CRCERR_FAST_MASK | FLEXCAN_ESR1_FRMERR_FAST_MASK |
FLEXCAN_ESR1_STFERR_FAST_MASK |
FLEXCAN_ESR1_ERROVR_MASK | FLEXCAN_ESR1_ERRINT_FAST_MASK | FLEXCAN_ESR1_BOFFDONEINT_MASK | FLEXCAN_ESR1_TWRNINT_MASK | FLEXCAN_ESR1_RWRNINT_MASK |
FLEXCAN_ESR1_BIT1ERR_MASK | FLEXCAN_ESR1_BIT0ERR_MASK | FLEXCAN_ESR1_ACKERR_MASK | FLEXCAN_ESR1_CRCERR_MASK | FLEXCAN_ESR1_FRMERR_MASK | FLEXCAN_ESR1_STFERR_MASK |
FLEXCAN_ESR1_TXWRN_MASK | FLEXCAN_ESR1_RXWRN_MASK | FLEXCAN_ESR1_FLTCONF_MASK | FLEXCAN_ESR1_BOFFINT_MASK | FLEXCAN_ESR1_ERRINT_MASK;
if (tErrorInfo.u32ESR1Value)
{
FLEXCAN_HWA_ClrErrorInfo(pCan, tErrorInfo.u32ESR1Value);
}
tErrorInfo.u32RxErrCnt = (u32ECR & FLEXCAN_ECR_RXERRCNT_MASK) >> FLEXCAN_ECR_RXERRCNT_SHIFT;
tErrorInfo.u32RxErrCnt_Fast = (u32ECR & FLEXCAN_ECR_RXERRCNT_FAST_MASK) >> FLEXCAN_ECR_RXERRCNT_FAST_SHIFT;
tErrorInfo.u32TxErrCnt = (u32ECR & FLEXCAN_ECR_TXERRCNT_MASK) >> FLEXCAN_ECR_TXERRCNT_SHIFT;
tErrorInfo.u32TxErrCnt_Fast = (u32ECR & FLEXCAN_ECR_TXERRCNT_FAST_MASK) >> FLEXCAN_ECR_TXERRCNT_FAST_SHIFT;
u32ECR = (tErrorInfo.u32ESR1Value & (FLEXCAN_ESR1_BOFFINT_MASK | FLEXCAN_ESR1_ERRINT_MASK));
if (u32ECR && bInterrupt)
{
pCanHandle->tSettings.pErrorNotify(pCanHandle, &tErrorInfo);
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
else
{
PROCESS_UNUSED_VAR(tErrorInfo);
PROCESS_UNUSED_VAR(u32ECR);
}
#endif
return tRetVal;
}
/**
* @brief Get can pet message
*
* @param pCanHandle Can Index, must less than FLEXCAN_INSTANCE_COUNT
* @return error structure
*/
static void FLEXCAN_LL_ProcessPNET(FLEXCAN_HandleType *pCanHandle)
{
FLEXCAN_Type *pCan;
pCan = s_aFlexCan_InstanceTable[(uint8_t)pCanHandle->eInstance];
FLEXCAN_HWA_CheckPNETAck(pCan, 0U, 1000);
if( (pCanHandle->tSettings.pWakeNotify != NULL) && (pCanHandle->tSettings.pWakeMsg != NULL) )
{
uint32_t u32Temp;
u32Temp = FLEXCAN_HWA_ChkPNET_TimeoutInterrupt(pCan);
/* timeout wake-up */
if(u32Temp > 0U)
{
pCanHandle->tSettings.pWakeMsg->u8CanIndex = pCanHandle->eInstance;
pCanHandle->tSettings.pWakeMsg->eWakeupSrc = FLEXCAN_PENT_WAKEUP_SRC_TIMEOUT;
pCanHandle->tSettings.pWakeNotify(pCanHandle, pCanHandle->tSettings.pWakeMsg);
FLEXCAN_HWA_ClrPNET_TimeoutFlag(pCan);
}
u32Temp = FLEXCAN_HWA_ChkPNET_MatchInterrupt(pCan);
/* match wake-up */
if(u32Temp > 0U)
{
pCanHandle->tSettings.pWakeMsg->u8CanIndex = pCanHandle->eInstance;
pCanHandle->tSettings.pWakeMsg->eWakeupSrc = FLEXCAN_PENT_WAKEUP_SRC_MATCH;
u32Temp = FLEXCAN_HWA_GetPNET_MatchCount(pCan);
if(u32Temp > 4U)
{
u32Temp = 4U; /* wake-up store max 4 frames */
}
uint32_t u32TempAddr;
uint32_t u32Index;
uint32_t u32WordLen;
uint32_t *pSrc;
uint32_t *pDest;
for(u32Index = 0U; u32Index < u32Temp; u32Index++)
{
u32TempAddr = FLEXCAN_HWA_PNETRamAddr(pCan, u32Index);
pCanHandle->tSettings.pWakeMsg->u32DataLen = FLEXCAN_MB_DLC_GET(u32TempAddr);
pCanHandle->tSettings.pWakeMsg->u32DataLen = FLEXCAN_DlcToDataLen(pCanHandle->tSettings.pWakeMsg->u32DataLen);
pCanHandle->tSettings.pWakeMsg->eFrameType = (FLEXCAN_IdType)(FLEXCAN_MB_IDE_GET(u32TempAddr));
/* message buffer 2th word */
u32TempAddr = u32TempAddr + 4U;
if (pCanHandle->tSettings.pWakeMsg->eFrameType)
{
pCanHandle->tSettings.pWakeMsg->u32CanId = FLEXCAN_MB_EXTID_GET(u32TempAddr);
}
else
{
pCanHandle->tSettings.pWakeMsg->u32CanId = FLEXCAN_MB_STDID_GET(u32TempAddr);
}
pDest = (uint32_t *)pCanHandle->tSettings.pWakeMsg->aData;
/* message buffer 3th word */
pSrc = (uint32_t*)(u32TempAddr + 4U);
u32WordLen = pCanHandle->tSettings.pWakeMsg->u32DataLen / 4U + (pCanHandle->tSettings.pWakeMsg->u32DataLen % 4U > 0U ? 1U : 0U);
for (u32TempAddr = 0U; u32TempAddr < u32WordLen; u32TempAddr++)
{
/* big endian to little endian */
REV_BYTES_32(pSrc[u32TempAddr], pDest[u32TempAddr]);
}
}
pCanHandle->tSettings.pWakeNotify(pCanHandle, pCanHandle->tSettings.pWakeMsg);
FLEXCAN_HWA_ClrPNET_MatchFlag(pCan);
}
}
}
/* ################################################################################## */
/* ################################ Global Functions ################################ */
/**
* @brief Get CAN Data width number for current can
* MBDSR0..MBDSRn
*
* @param pCanHandle Can Handle point
* @return data width array number
*/
uint8_t FLEXCAN_GetDataWidthArrayLen(FLEXCAN_HandleType *pCanHandle)
{
return s_aFlexCanDataLenNums[pCanHandle->eInstance];
}
/**
* @brief Initializes Error Correction Code (ECC) injection for FlexCAN module.
*
* @details Configures the FlexCAN module for ECC error injection by:
* - Disabling module disable mode (MCR[MDIS])
* - Enabling ECC register write access (CTRL2[ECRWRE])
* - Configuring error injection address and data pattern
* - Enabling ECC error injection interrupts and mechanisms
*
* @param pCanHandle Pointer to FlexCAN instance handle
* @param erro_inject_addr Error injection address (written to ERRIAR register)
* @param data_pattern_bit Data pattern for error injection (written to ERRIDPR register)
*/
void FLEXCAN_EccInjectionInit(FLEXCAN_HandleType *pCanHandle, uint32_t erro_inject_addr, uint8_t data_pattern_bit)
{
FLEXCAN_Type *pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
//To ensure coherence among error injection registers and avoid spurious error injections
//MECR[HAERRIE] and MECR[FAERRIE] must be cleared
pCan->MCR &= ~FLEXCAN_MCR_MDIS_MASK;
pCan->CTRL2 |= FLEXCAN_CTRL2_ECRWRE_MASK;
pCan->MECR &= ~FLEXCAN_MECR_ECRWRDIS_MASK;
pCan->MECR &= ~(FLEXCAN_MECR_FAERRIE_MASK | FLEXCAN_MECR_HAERRIE_MASK);
//Error Injection configuration
pCan->ERRIAR = erro_inject_addr;
pCan->ERRIDPR = data_pattern_bit;
//
pCan->MECR |= (FLEXCAN_MECR_FAERRIE_MASK | FLEXCAN_MECR_HAERRIE_MASK | FLEXCAN_MECR_CEI_MSK_MASK);
}
/**
* @brief Deinitializes Error Correction Code (ECC) injection for FlexCAN module.
*
* @details Disables ECC error injection by:
* - Clearing error injection interrupts (MECR[FAERRIE|HAERRIE])
* - Disabling ECC register write access (CTRL2[ECRWRE])
*
* @param pCanHandle Pointer to FlexCAN instance handle
*/
void FLEXCAN_EccInjectionDeInit(FLEXCAN_HandleType *pCanHandle)
{
FLEXCAN_Type *pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
pCan->MECR &= ~(FLEXCAN_MECR_FAERRIE_MASK | FLEXCAN_MECR_HAERRIE_MASK);
pCan->CTRL2 &= ~FLEXCAN_CTRL2_ECRWRE_MASK;
}
/**
* @brief Initial CAN
*
* @param pCanHandle Can Handle point
* @param pInitCfg clock, baud-rate, canfd, data length and so on.
* @return 0 is ok, others are not ok
*/
FLEXCAN_ErrorType FLEXCAN_Init(FLEXCAN_HandleType *pCanHandle, const FLEXCAN_InitType *const pInitCfg)
{
FLEXCAN_ErrorType tRetVal;
uint32_t u32TempCtrl1;
uint32_t u32TempMcr;
FLEXCAN_Type *pCan;
uint32_t u32FdCtrl = 0U;
uint32_t u32Eprs;
uint32_t u32Encbt;
uint32_t u32Edcbt = 0U;
uint8_t u8DataWidthNum;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
if ((pCanHandle == NULL) || (pInitCfg == NULL))
{
tRetVal = FLEXCAN_E_NULL_POINT;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_NULL_POINT);
}
else
{
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq == FLEXCAN_SEQUENCE_DEINIT))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_SEQUENCE);
}
if(pInitCfg->tRxFifoFilterCfg.bEnFifo)
{
/* legacy only support non-fd */
if (pInitCfg->tRxFifoFilterCfg.eFifoType == FLEXCAN_LEGACY_FIFO)
{
if (pInitCfg->bEnFd == 1U)
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_PARAM);
}
else
{
/* the filter number must be multi of 8 */
if(pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.u8RxFilterFifoCnt%8)
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_PARAM);
}
}
}
else /* enhanced fifo */
{
if (pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.u8FifoWaterMark > s_aFlexCanEnhancedDepthp[pCanHandle->eInstance])
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_PARAM);
}
else
{
/* the filter number must be multi of 2 */
if(pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.u8RxFilterFifoCnt%2)
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_PARAM);
}
}
}
}
}
u8DataWidthNum = FLEXCAN_GetDataWidthArrayLen(pCanHandle);
#endif
/* copy data width number to status */
for(u8DataWidthNum=0U; u8DataWidthNum<FLEXCAN_FD_DATALEN_RANGE_NUM_MAX; u8DataWidthNum++)
{
if (pInitCfg->bEnFd == 0U)
{
pCanHandle->tStatus.aMbDataWidth[u8DataWidthNum] = FLEXCAN_DATAWIDTH_8;
}
else
{
pCanHandle->tStatus.aMbDataWidth[u8DataWidthNum] = pInitCfg->tMbCfg.aDataWidthRange[u8DataWidthNum];
}
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
if (tRetVal == FLEXCAN_E_OK)
{
#endif
pCan = s_aFlexCan_InstanceTable[(uint8_t)pCanHandle->eInstance];
tRetVal = FLEXCAN_E_OK;
if (pInitCfg->bEnFd == 0U)
{
/* when pCan fd enabled, pCan normal bit set by CBT !!!! */
u32Eprs = FLEXCAN_EPRS_ENPRESDIV(pInitCfg->tNormalBaud.u32Presdiv - 1U);
u32Encbt = FLEXCAN_ENCBT_NRJW(pInitCfg->tNormalBaud.u32Rjw - 1U) |
FLEXCAN_ENCBT_NTSEG2(pInitCfg->tNormalBaud.u32Pseg2 - 1U) |
FLEXCAN_ENCBT_NTSEG1(pInitCfg->tNormalBaud.u32Pseg1 + pInitCfg->tNormalBaud.u32Propseg - 1U) ;
}
else
{
u32FdCtrl = FLEXCAN_FDCTRL_FDRATE(pInitCfg->bEnFd);
u32FdCtrl = (uint32_t)(u32FdCtrl | FLEXCAN_HWA_CalDataWidth((uint8_t*)pInitCfg->tMbCfg.aDataWidthRange));
u32Eprs = FLEXCAN_EPRS_ENPRESDIV(pInitCfg->tNormalBaud.u32Presdiv - 1U) |
FLEXCAN_EPRS_EDPRESDIV(pInitCfg->tFdBaud.u32Presdiv - 1U);
u32Encbt = FLEXCAN_ENCBT_NRJW(pInitCfg->tNormalBaud.u32Rjw - 1U) |
FLEXCAN_ENCBT_NTSEG2(pInitCfg->tNormalBaud.u32Pseg2 - 1U) |
FLEXCAN_ENCBT_NTSEG1(pInitCfg->tNormalBaud.u32Pseg1 + pInitCfg->tNormalBaud.u32Propseg - 1U);
u32Edcbt = FLEXCAN_EDCBT_DRJW(pInitCfg->tFdBaud.u32Rjw - 1U) |
FLEXCAN_EDCBT_DTSEG2(pInitCfg->tFdBaud.u32Pseg2 - 1U) |
FLEXCAN_EDCBT_DTSEG1(pInitCfg->tFdBaud.u32Pseg1 + pInitCfg->tFdBaud.u32Propseg - 1U);
}
FLEXCAN_HWA_SetMcrDisable(pCan, TRUE);
FLEXCAN_HWA_SetCtrl1(pCan, 0U);
FLEXCAN_HWA_SetCtrl1BaudSrc(pCan, pInitCfg->eClkSrcSel);
FLEXCAN_HWA_SetMcrDisable(pCan, FALSE);
/* mcr->B.bitMDIS = 0; */
FLEXCAN_HWA_SetHaltFreeze(pCan);
/* wait for bitFRZACK=1 on freeze mode entry/exit */
if (FLEXCAN_HWA_WaitMcrFreezen(pCan, 10000U) != 0U)
{
tRetVal |= FLEXCAN_E_TIMEOUT;
}
else
{
FLEXCAN_HWA_SetCtrl2(pCan,
FLEXCAN_CTRL2_WRMFRZ(1U) | /* initial ram ecc */
FLEXCAN_CTRL2_TASD(20U) |
FLEXCAN_CTRL2_ISOCANFDEN(1U) |
FLEXCAN_CTRL2_BTE(1U)
);
/* when pCan fd disabled, pCan normal bit set by CTRL1 !!!! */
u32TempCtrl1 = FLEXCAN_CTRL1_CLKSRC(pInitCfg->eClkSrcSel) | FLEXCAN_CTRL1_LOM(pInitCfg->bListenOnly) | FLEXCAN_CTRL1_BOFFREC(pInitCfg->bEnAutoRec);
if (!pInitCfg->bEnFd)
{
FLEXCAN_HWA_SetEPRS(pCan, u32Eprs);
FLEXCAN_HWA_SetENCBT(pCan, u32Encbt);
}
else
{
FLEXCAN_HWA_SetFDCTRL(pCan, u32FdCtrl);
FLEXCAN_HWA_SetEPRS(pCan, u32Eprs);
FLEXCAN_HWA_SetENCBT(pCan, u32Encbt);
FLEXCAN_HWA_SetEDCBT(pCan, u32Edcbt);
}
FLEXCAN_HWA_SetCtrl1(pCan, u32TempCtrl1);
if (pInitCfg->bEnSsp != 0)
{
FLEXCAN_HWA_SetETDC(pCan,
FLEXCAN_ETDC_ETDCEN(1U) |
FLEXCAN_ETDC_ETDCOFF((pInitCfg->tFdBaud.u32Propseg + pInitCfg->tFdBaud.u32Pseg1 + 1)*pInitCfg->tFdBaud.u32Presdiv) /* (sync+propseg+pseg1)presdiv */
);
}
/* initial RAM to avoid ECC error */
FLEXCAN_LL_EmbededRam_Init(pCanHandle->eInstance);
u32TempMcr = FLEXCAN_MCR_MDIS(0) | /* enable pCan module */
FLEXCAN_MCR_FRZ(1) | /* not frozen */
FLEXCAN_MCR_HALT(1) | /* not halt */
FLEXCAN_MCR_SOFTRST(0) | /* not reset */
FLEXCAN_MCR_SUPV(1) | /* supervisor mode */
FLEXCAN_MCR_WRNEN(0) | /* wake up disable */
FLEXCAN_MCR_SRXDIS(1) | /* self reception disable */
FLEXCAN_MCR_IRMQ(0) | /* individual Rx masking */
FLEXCAN_MCR_PNET_EN(0) | /* Pretended Networking Enable */
FLEXCAN_MCR_LPRIOEN(0) | /* Local Priority disable */
FLEXCAN_MCR_AEN(1) | /* abort disable */
FLEXCAN_MCR_FDEN(pInitCfg->bEnFd) | /* CAN FD enable */
FLEXCAN_MCR_IDAM(0) | /* ID Acceptance Mode for Rx FIFO, format A */
FLEXCAN_MCR_MAXMB(0); /* Max number of Message Buffer, num 31 is the 32th MB */
if(pInitCfg->tRxFifoFilterCfg.bEnFifo)
{
if(pInitCfg->tRxFifoFilterCfg.eFifoType == FLEXCAN_LEGACY_FIFO) /* legacy fifo */
{
u32TempMcr |= FLEXCAN_MCR_DMA(pInitCfg->tRxFifoFilterCfg.tLegacyFifoCfg.bEnFifoDMA); /* DMA enable */
u32TempMcr |= FLEXCAN_MCR_RFEN(1U); /* Legacy RX FIFO, only when canfd not enable */
}
else /* enhanced fifo */
{
u32TempMcr |= FLEXCAN_MCR_DMA(pInitCfg->tRxFifoFilterCfg.tEnhancedFifoCfg.bEnFifoDMA); /* DMA enable */
}
}
FLEXCAN_HWA_SetMCR(pCan, u32TempMcr); /* Negate FlexCAN 1 halt state for 32 MBs */
}
tRetVal |= FLEXCAN_LL_RxFilterConfig(pCanHandle, pInitCfg);
/* check mb total number */
if(FLEXCAN_LL_GetMbNum(pCanHandle, pInitCfg)<(pCanHandle->tStatus.u8MbStart+pInitCfg->tMbCfg.u8MBCnt))
{
tRetVal |= FLEXCAN_E_MB_OUTOFRANGE;
}
if (tRetVal == FLEXCAN_E_OK)
{
tRetVal |= FLEXCAN_LL_SetInterrupt(pCanHandle, pInitCfg);
}
if (tRetVal == FLEXCAN_E_OK)
{
pCanHandle->tStatus.eStatusSeq = FLEXCAN_SEQUENCE_NOTSTART;
}
/* Pretended Network for Wake-up in STOP Mode */
if(pInitCfg->tPnetCfg.bPNetEnable)
{
/* check pnet if it is supported */
if(s_aFlexCanPnetSupportTable[pCanHandle->eInstance]==0U)
{
tRetVal |= FLEXCAN_E_UNSUPPORT_PARAM;
}
else
{
tRetVal |= FLEXCAN_LL_SetPNET(pCanHandle, pInitCfg);
FLEXCAN_HWA_AttachMCR(pCan, FLEXCAN_MCR_PNET_EN_MASK);
/* FLEXCAN_HWA_CheckPNETAck(pCan, 1U, 1000); */
}
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
else
{
PROCESS_UNUSED_VAR(u32FdCtrl);
}
#endif
return tRetVal;
}
/**
* @brief De-initial can instance
*
* @param pCanHandle Can Handle point
* @return 0 is ok, others are not ok
*/
FLEXCAN_ErrorType FLEXCAN_DeInit(FLEXCAN_HandleType *pCanHandle)
{
FLEXCAN_ErrorType tRetVal;
uint32_t u32TempMcr;
FLEXCAN_Type *pCan;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if (tRetVal == FLEXCAN_E_OK)
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_SEQUENCE);
}
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
FLEXCAN_HWA_SetHaltFreeze(pCan);
/* wait for bitFRZACK=1 on freeze mode entry/exit */
if (FLEXCAN_HWA_WaitMcrFreezen(pCan, 10000U) != 0U)
{
tRetVal |= FLEXCAN_E_TIMEOUT;
}
else
{
if (s_aFlexCanFd_SupportTable[pCanHandle->eInstance])
{
FLEXCAN_HWA_DisableFDFifo(pCan);
}
FLEXCAN_HWA_DisableLegacyFifo(pCan);
if(1U == s_aFlexCanPnetSupportTable[pCanHandle->eInstance])
{
FLEXCAN_HWA_ClrPNET_CTRL1_PN(pCan);
}
u32TempMcr = FLEXCAN_MCR_MDIS(1) | /* enable pCan module */
FLEXCAN_MCR_FRZ(0) | /* not frozen */
FLEXCAN_MCR_RFEN(0U) | /* RX FIFO disable */
FLEXCAN_MCR_HALT(0) | /* not halt */
FLEXCAN_MCR_SOFTRST(1) | /* not reset */
FLEXCAN_MCR_SUPV(1) | /* supervisor mode */
FLEXCAN_MCR_WRNEN(0) | /* wake up disable */
FLEXCAN_MCR_SRXDIS(1) | /* self reception disable */
FLEXCAN_MCR_IRMQ(0) | /* individual Rx masking */
FLEXCAN_MCR_DMA(0) | /* DMA enable */
FLEXCAN_MCR_PNET_EN(0) | /* Pretended Networking Enable */
FLEXCAN_MCR_LPRIOEN(0) | /* Local Priority disable */
FLEXCAN_MCR_AEN(0) | /* abort disable */
FLEXCAN_MCR_FDEN(0) | /* CAN FD enable */
FLEXCAN_MCR_IDAM(0) | /* ID Acceptance Mode for Rx FIFO, format A */
FLEXCAN_MCR_MAXMB(0); /* Max number of Message Buffer, num 31 is the 32th MB */
FLEXCAN_HWA_SetCtrl1(pCan, 0U);
FLEXCAN_HWA_SetMCR(pCan, u32TempMcr); /* Negate FlexCAN 1 halt state for 32 MBs */
pCanHandle->tStatus.eStatusSeq = FLEXCAN_SEQUENCE_DEINIT;
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
#endif
return tRetVal;
}
/**
* @brief Start can instance
*
* @param pCanHandle Can Handle point
* @return 0 is ok
*/
FLEXCAN_ErrorType FLEXCAN_Start(FLEXCAN_HandleType *pCanHandle)
{
FLEXCAN_ErrorType tRetVal;
uint32_t u32TempMcr;
FLEXCAN_Type *pCan;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq == FLEXCAN_SEQUENCE_NOTSTART))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_SEQUENCE);
}
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u32TempMcr = FLEXCAN_HWA_GetMCR(pCan);
u32TempMcr &= ~(FLEXCAN_MCR_FRZ(1U) | /* not frozen */
FLEXCAN_MCR_HALT(1U) /* not halt */
/*| FLEXCAN_MCR_SUPV(1) user mode */
); /* not reset */
FLEXCAN_HWA_SetMCR(pCan, u32TempMcr);
if (FLEXCAN_HWA_WaitMcrExitFreezen(pCan, 10000U) != 0U)
{
tRetVal |= FLEXCAN_E_TIMEOUT;
}
else
{
if (FLEXCAN_HWA_WaitMcrReady(pCan, 10000U) != 0U)
{
tRetVal |= FLEXCAN_E_TIMEOUT;
}
else
{
pCanHandle->tStatus.eStatusSeq = FLEXCAN_SEQUENCE_STARTED;
}
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
#endif
return tRetVal;
}
/**
* @brief Stop can instance
*
* @param pCanHandle Can Handle point
*/
FLEXCAN_ErrorType FLEXCAN_Stop(FLEXCAN_HandleType *pCanHandle)
{
FLEXCAN_ErrorType tRetVal;
uint32_t u32TempMcr;
FLEXCAN_Type *pCan;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && ((uint8_t)(pCanHandle->tStatus.eStatusSeq) >= (uint8_t)(FLEXCAN_SEQUENCE_NOTSTART)))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_SEQUENCE);
}
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
/* set started state */
pCanHandle->tStatus.eStatusSeq = FLEXCAN_SEQUENCE_NOTSTART;
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u32TempMcr = FLEXCAN_HWA_GetMCR(pCan);
u32TempMcr |= FLEXCAN_MCR_FRZ(1U) | /* not frozen */
FLEXCAN_MCR_HALT(1U) /* not halt */
/*| FLEXCAN_MCR_SUPV(1) user mode */
; /* not reset */
FLEXCAN_HWA_SetMCR(pCan, u32TempMcr);
/* must wait */
if (FLEXCAN_HWA_WaitMcrFreezen(pCan, 10000U) != 0U)
{
tRetVal |= FLEXCAN_E_TIMEOUT;
}
else
{
/* must wait */
if (FLEXCAN_HWA_WaitMcrNoReady(pCan, 10000U) != 0U)
{
tRetVal |= FLEXCAN_E_TIMEOUT;
}
else
{
}
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
#endif
return tRetVal;
}
/**
* @brief Transmit data, if tx disable, must call FLEXCAN_TransmitProcess after transmiting
*
* @param pCanHandle Can Handle point
* @param pTxMsg contains CAN instance, CAN ID, CAN FD and CAN data.
* @return 0 is ok
*/
FLEXCAN_ErrorType FLEXCAN_TransmitData(FLEXCAN_HandleType *pCanHandle, const FLEXCAN_TxMsgType *const pTxMsg)
{
FLEXCAN_ErrorType tRetVal;
uint32_t *pSrc;
uint32_t *pDest;
uint32_t u32Index;
FLEXCAN_Type *pCan;
uint8_t u8TxRealMbIndex;
uint32_t u32WordLen;
uint32_t u32TempAddr;
uint32_t u32Code;
uint8_t u8DateLen;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq == FLEXCAN_SEQUENCE_STARTED))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_SEQUENCE);
}
if (pTxMsg == NULL)
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
}
else
{
/* check buffer point if it is null */
if (&(pTxMsg->aData) == NULL)
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
}
else
{
}
}
if ((pTxMsg->bEnFd == 1U) && (s_aFlexCanFd_SupportTable[pCanHandle->eInstance]==0U))
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
}
if (tRetVal == FLEXCAN_E_OK)
{
#else
tRetVal = FLEXCAN_E_OK;
#endif
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u8TxRealMbIndex = FLEXCAN_LL_GetMbIndexByTxHandle(pCanHandle, pTxMsg->u8TxHandle);
if (u8TxRealMbIndex == 0xFFU)
{
tRetVal = FLEXCAN_E_INVALID_PARAM;
}
else
{
u8DateLen = FLEXCAN_MB_GET_DATALEN(u8TxRealMbIndex, s_aFlexCanMbNums[pCanHandle->eInstance], s_aFlexCanDataLenNums[pCanHandle->eInstance], pCanHandle->tStatus.aMbDataWidth);
if (pTxMsg->u32DataLen > u8DateLen)
{
tRetVal |= FLEXCAN_E_INVALID_PARAM;
}
/* message buffer 1th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, u8DateLen, 0U);
u32Code = FLEXCAN_MB_CODE_GET(u32TempAddr);
if ((0x8 != u32Code) && (0U != u32Code))
{
tRetVal = FLEXCAN_E_BUSY;
}
else
{
/* message buffer 1th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, u8DateLen, 0U);
/* clear last value */
FLEXCAN_REG32_CONTENT(u32TempAddr) = 0U;
FLEXCAN_MB_EDL_SET(u32TempAddr, pTxMsg->bEnFd);
FLEXCAN_MB_BRS_SET(u32TempAddr, pTxMsg->bEnBrs);
/* DLC */
u32Index = FLEXCAN_DataLenToDlc(pTxMsg->u32DataLen);
FLEXCAN_MB_DLC_SET(u32TempAddr, u32Index);
if (pTxMsg->eFrameType == FLEXCAN_ID_STD)
{
/* SRR & IDE */
FLEXCAN_MB_IDE_SRR_SET(u32TempAddr, pTxMsg->eFrameType);
}
else /* extended id */
{
/* SRR & IDE */
FLEXCAN_MB_IDE_SRR_SET(u32TempAddr, pTxMsg->eFrameType | FLEXCAN_MB_SRR_MASK_U32); /* extended id must set SRR=1 */
}
/* message buffer 2th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, u8DateLen, 4U);
/* clear last value */
FLEXCAN_REG32_CONTENT(u32TempAddr) = 0U;
/* standard id */
if (pTxMsg->eFrameType == FLEXCAN_ID_STD)
{
FLEXCAN_MB_STDID_SET(u32TempAddr, pTxMsg->u32CanId);
}
else /* extended id */
{
FLEXCAN_MB_EXTID_SET(u32TempAddr, pTxMsg->u32CanId);
}
FLEXCAN_MB_PRIO_SET(u32TempAddr, 0U);
pSrc = (uint32_t *)(uint32_t)(&(pTxMsg->aData[0]));
/* message buffer 3th word */
pDest = (uint32_t *)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, u8DateLen, 8U);
u32WordLen = pTxMsg->u32DataLen / 4U + (pTxMsg->u32DataLen % 4U > 0U ? 1U : 0U);
/* revert data to little endian */
for (u32Index = 0U; u32Index < u32WordLen; u32Index++)
{
/* big endian to little endian */
REV_BYTES_32(pSrc[u32Index], pDest[u32Index]);
}
/* message buffer 1th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, u8DateLen, 0U);
/* CODE set 0x0C to transmit */
FLEXCAN_MB_CODE_SET(u32TempAddr, 0x0CU);
}
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
else
{
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_TRANSMIT, FLEXCAN_E_INVALID_PARAM);
}
#endif
return tRetVal;
}
/**
* @brief Abort transmit with special transmit handler
*
* @param pCanHandle Can Handle point
* @param u8TxHandle Transmit handler
* @return 0 is ok
*/
FLEXCAN_ErrorType FLEXCAN_TransmitAbort(FLEXCAN_HandleType *pCanHandle, uint8_t u8TxHandle)
{
FLEXCAN_ErrorType tRetVal;
FLEXCAN_Type *pCan;
uint8_t u8TxRealMbIndex;
uint32_t u32TempAddr;
uint8_t u8DateLen;
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq == FLEXCAN_SEQUENCE_STARTED))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_INIT, FLEXCAN_E_INVALID_SEQUENCE);
}
if (tRetVal == FLEXCAN_E_OK)
{
#endif
pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[pCanHandle->eInstance];
u8TxRealMbIndex = FLEXCAN_LL_GetMbIndexByTxHandle(pCanHandle, u8TxHandle);
if (u8TxRealMbIndex == 0xFFU)
{
tRetVal = FLEXCAN_E_INVALID_PARAM;
}
else
{
u8DateLen = FLEXCAN_MB_GET_DATALEN(u8TxRealMbIndex, s_aFlexCanMbNums[pCanHandle->eInstance], s_aFlexCanDataLenNums[pCanHandle->eInstance], pCanHandle->tStatus.aMbDataWidth);
/* message buffer 1th word */
u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, u8DateLen, 0U);
/* CODE set 0x09 to aborting transmit */
FLEXCAN_MB_CODE_SET(u32TempAddr, 0x09U);
tRetVal = FLEXCAN_E_OK;
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
#endif
return tRetVal;
}
/**
* @brief Transfer Data length to DLC
*
* @param u32DataLen data length
* @return DLC
*/
uint32_t FLEXCAN_DataLenToDlc(uint32_t u32DataLen)
{
uint32_t u32Dlc;
switch (u32DataLen)
{
case 0U:
case 1U:
case 2U:
case 3U:
case 4U:
case 5U:
case 6U:
case 7U:
case 8U:
{
u32Dlc = u32DataLen;
}
break;
case 12U:
{
u32Dlc = 9U;
}
break;
case 16U:
{
u32Dlc = 10U;
}
break;
case 20U:
{
u32Dlc = 11U;
}
break;
case 24U:
{
u32Dlc = 12U;
}
break;
case 32U:
{
u32Dlc = 13U;
}
break;
case 48U:
{
u32Dlc = 14U;
}
break;
case 64U:
{
u32Dlc = 15U;
}
break;
default:
u32Dlc = 0U;
break;
}
return u32Dlc;
}
/**
* @brief Transfer DLC to Data length
*
* @param u32Dlc DLC Data Length
* @return
*/
uint32_t FLEXCAN_DlcToDataLen(uint32_t u32Dlc)
{
uint32_t u32DataLen;
switch (u32Dlc)
{
case 0U:
case 1U:
case 2U:
case 3U:
case 4U:
case 5U:
case 6U:
case 7U:
case 8U:
{
u32DataLen = u32Dlc;
}
break;
case 9U:
{
u32DataLen = 12U;
}
break;
case 10U:
{
u32DataLen = 16U;
}
break;
case 11U:
{
u32DataLen = 20U;
}
break;
case 12U:
{
u32DataLen = 24U;
}
break;
case 13U:
{
u32DataLen = 32U;
}
break;
case 14U:
{
u32DataLen = 48U;
}
break;
case 15U:
{
u32DataLen = 64U;
}
break;
default:
u32DataLen = 0U;
break;
}
return u32DataLen;
}
/* ################################################################################## */
/* ############################## Interrupt Services ################################ */
/**
* @brief Can process for interrupt
*
* @param pCanHandle Can handle point
*/
void FLEXCAN_InterruptProcess(FLEXCAN_HandleType *pCanHandle)
{
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
FLEXCAN_ErrorType tRetVal;
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq >= FLEXCAN_SEQUENCE_NOTSTART))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
}
if (tRetVal == FLEXCAN_E_OK)
{
#endif
FLEXCAN_Type *pCan;
pCan = s_aFlexCan_InstanceTable[(uint8_t)pCanHandle->eInstance];
#if FLEXCAN_INTERRUPT_ERROR_SPLIT == STD_OFF
if(FLEXCAN_HWA_CheckErrorInterrupt(pCan))
{
/* check error interrupt */
FLEXCAN_LL_ProcessError(pCanHandle, 0U);
}
#endif
/* check transmit interrupt */
FLEXCAN_LL_InterruptTx(pCanHandle);
/* check receive interrupt */
FLEXCAN_LL_InterruptRx(pCanHandle);
/* check legacy fifo interrupt */
if (FLEXCAN_HWA_CheckLegacyFifoEn(pCan))
{
/* get fifo data only when dma disable */
if(!FLEXCAN_HWA_CheckFifoDma(pCan))
{
if(FLEXCAN_HWA_CheckLegacyFifoDataInterrupt(pCan))
{
FLEXCAN_LL_PollingLegacyFifoData(pCanHandle);
}
}
if(FLEXCAN_HWA_CheckLegacyFifoWarningInterrupt(pCan))
{
FLEXCAN_LL_PollingLegacyFifoWarning(pCanHandle);
}
if(FLEXCAN_HWA_CheckLegacyFifoErrorInterrupt(pCan))
{
FLEXCAN_LL_PollingLegacyFifoError(pCanHandle);
}
}
if(FLEXCAN_LL_CheckFdInstance(pCanHandle->eInstance) == 0)
{
/* check enhanced fifo interrupt */
if (FLEXCAN_HWA_CheckEnhancedFIFOEn(pCan))
{
if(FLEXCAN_HWA_CheckEnhancedFifoDataInterrupt(pCan))
{
FLEXCAN_LL_PollingEnhancedFifoData(pCanHandle);
}
if(FLEXCAN_HWA_CheckEnhancedFifoErrorInterrupt(pCan))
{
FLEXCAN_LL_PollingEnhancedFifoError(pCanHandle);
}
}
}
FLEXCAN_LL_ProcessPNET(pCanHandle);
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
else
{
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_PROCESS, FLEXCAN_E_INVALID_PARAM);
}
#endif
}
/**
* @brief Can process for polling
*
* @param pCanHandle Can handle point
*/
void FLEXCAN_PollingProcess(FLEXCAN_HandleType *pCanHandle)
{
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
FLEXCAN_ErrorType tRetVal;
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq >= FLEXCAN_SEQUENCE_NOTSTART))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
}
if (tRetVal == FLEXCAN_E_OK)
{
#endif
FLEXCAN_Type *pCan;
pCan = s_aFlexCan_InstanceTable[(uint8_t)pCanHandle->eInstance];
#if FLEXCAN_INTERRUPT_ERROR_SPLIT == STD_OFF
if(!FLEXCAN_HWA_CheckErrorInterrupt(pCan))
{
/* check error interrupt */
FLEXCAN_LL_ProcessError(pCanHandle, 0U);
}
#endif
/* check transmit interrupt */
FLEXCAN_LL_PollingTx(pCanHandle);
FLEXCAN_LL_PollingRx(pCanHandle);
/* check legacy fifo interrupt */
if (FLEXCAN_HWA_CheckLegacyFifoEn(pCan))
{
/* get fifo data only when dma disable */
if(!FLEXCAN_HWA_CheckFifoDma(pCan))
{
if(FLEXCAN_HWA_CheckLegacyFifoDataPolling(pCan))
{
FLEXCAN_LL_PollingLegacyFifoData(pCanHandle);
}
}
if(FLEXCAN_HWA_CheckLegacyFifoWarningPolling(pCan))
{
FLEXCAN_LL_PollingLegacyFifoWarning(pCanHandle);
}
if(FLEXCAN_HWA_CheckLegacyFifoErrorPolling(pCan))
{
FLEXCAN_LL_PollingLegacyFifoError(pCanHandle);
}
}
if(FLEXCAN_LL_CheckFdInstance(pCanHandle->eInstance) == 0)
{
/* check enhanced fifo interrupt */
if (FLEXCAN_HWA_CheckEnhancedFIFOEn(pCan))
{
if(FLEXCAN_HWA_CheckEnhancedFifoDataPolling(pCan))
{
FLEXCAN_LL_PollingEnhancedFifoData(pCanHandle);
}
if(FLEXCAN_HWA_CheckEnhancedFifoErrorPolling(pCan))
{
FLEXCAN_LL_PollingEnhancedFifoError(pCanHandle);
}
}
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
else
{
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_PROCESS, FLEXCAN_E_INVALID_PARAM);
}
#endif
}
/**
* @brief Can Error process for interrupt
*
* @param pCanHandle Can handle point
*/
void FLEXCAN_InterruptErrorProcess(FLEXCAN_HandleType *pCanHandle)
{
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
FLEXCAN_ErrorType tRetVal;
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq >= FLEXCAN_SEQUENCE_NOTSTART))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
}
if (tRetVal == FLEXCAN_E_OK)
{
#endif
FLEXCAN_Type *pCan;
pCan = s_aFlexCan_InstanceTable[(uint8_t)pCanHandle->eInstance];
if (FLEXCAN_HWA_CheckErrorInterrupt(pCan))
{
/* check error interrupt */
FLEXCAN_LL_ProcessError(pCanHandle, 1U);
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
else
{
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_PROCESS, FLEXCAN_E_INVALID_PARAM);
}
#endif
}
/**
* @brief Can Error process for polling
*
* @param pCanHandle Can handle point
*/
void FLEXCAN_PollingErrorProcess(FLEXCAN_HandleType *pCanHandle)
{
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
FLEXCAN_ErrorType tRetVal;
/* check parameter */
tRetVal = FLEXCAN_LL_CheckInstance(pCanHandle->eInstance);
if ((tRetVal == FLEXCAN_E_OK) && (pCanHandle->tStatus.eStatusSeq >= FLEXCAN_SEQUENCE_NOTSTART))
{
tRetVal = FLEXCAN_E_OK;
}
else
{
tRetVal |= FLEXCAN_E_INVALID_SEQUENCE;
}
if (tRetVal == FLEXCAN_E_OK)
{
#endif
FLEXCAN_Type *pCan;
pCan = s_aFlexCan_InstanceTable[(uint8_t)pCanHandle->eInstance];
if (!FLEXCAN_HWA_CheckErrorInterrupt(pCan))
{
/* check error interrupt */
FLEXCAN_LL_ProcessError(pCanHandle, 0U);
}
#if FLEXCAN_DEV_ERROR_REPORT == STD_ON
}
else
{
FLEXCAN_ReportDevError(FLEXCAN_DET_ERROR_ID_FUNC_PROCESS, FLEXCAN_E_INVALID_PARAM);
}
#endif
}
#endif