/** * @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;u8IndextMbCfg.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 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<tStatus.aInterruptMask[u8MaskIndex] = pCanHandle->tStatus.aInterruptMask[u8MaskIndex] + (1U<tStatus.aTxPollingMask[u8MaskIndex] = pCanHandle->tStatus.aTxPollingMask[u8MaskIndex] + (1U<tStatus.aPollingMask[u8MaskIndex] = pCanHandle->tStatus.aPollingMask[u8MaskIndex] + (1U<tStatus.u8MbStart; for(u8Index11=0U; u8Index11 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<tStatus.aInterruptMask[u8MaskIndex] = pCanHandle->tStatus.aInterruptMask[u8MaskIndex] + (1U<tStatus.aRxPollingMask[u8MaskIndex] = pCanHandle->tStatus.aRxPollingMask[u8MaskIndex] + (1U<tStatus.aPollingMask[u8MaskIndex] = pCanHandle->tStatus.aPollingMask[u8MaskIndex] + (1U<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<tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); #else pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); FLEXCAN_HWA_SetFlag1(pCan, 1U<> 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<tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); #else pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); FLEXCAN_HWA_SetFlag2(pCan, 1U<> 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<tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); #else pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); FLEXCAN_HWA_SetFlag3(pCan, 1U<> 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<tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); #else pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); FLEXCAN_HWA_SetFlag1(pCan, 1U<> 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<tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); #else pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); FLEXCAN_HWA_SetFlag2(pCan, 1U<> 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<tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); #else pCanHandle->tSettings.pTxNotify(pCanHandle, FLEXCAN_LL_GetTxHandleByMbIndex(pCanHandle, u8MbIndex)); FLEXCAN_HWA_SetFlag3(pCan, 1U<> 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<tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); #else pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); FLEXCAN_HWA_SetFlag1(pCan, 1U<> 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<tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); #else pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); FLEXCAN_HWA_SetFlag2(pCan, 1U<> 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<tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); #else pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); FLEXCAN_HWA_SetFlag3(pCan, 1U<> 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<tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); #else pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); FLEXCAN_HWA_SetFlag1(pCan, 1U<> 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<tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); #else pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); FLEXCAN_HWA_SetFlag2(pCan, 1U<> 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<tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); #else pCanHandle->tSettings.pRxNotify(pCanHandle, &pCanHandle->tSettings.pRxBuf[0]); FLEXCAN_HWA_SetFlag3(pCan, 1U<> 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; u8DataWidthNumbEnFd == 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