ADM/GW/RTD/src/FlexCAN_Ip.c
2024-08-08 10:00:15 +09:00

4394 lines
163 KiB
C

/*
* FlexCAN_Ip.c
*
* Created on: Apr 9, 2020
* Author: nxf31634
*/
/**
* @file FlexCAN_Ip.c
* @brief FlexCAN Driver File
* @addtogroup FlexCAN
* @{
*/
/*==================================================================================================
* Project : RTD AUTOSAR 4.4
* Platform : CORTEXM
* Peripheral : FLEXCAN
* Dependencies :
*
* Autosar Version : 4.4.0
* Autosar Revision : ASR_REL_4_4_REV_0000
* Autosar Conf.Variant :
* SW Version : 0.9.0
* Build Version : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326
*
* (c) Copyright 2020 - 2021 NXP Semiconductors
* All Rights Reserved.
*
* NXP Confidential. This software is owned or controlled by NXP and may only be
* used strictly in accordance with the applicable license terms. By expressly
* accepting such terms or by downloading, installing, activating and/or otherwise
* using the software, you are agreeing that you have read, and that you agree to
* comply with and are bound by, such license terms. If you do not agree to be
* bound by the applicable license terms, then you may not retain, install,
* activate or otherwise use the software.
==================================================================================================*/
/*==================================================================================================
* INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "FlexCAN_Ip.h"
#include "Devassert.h"
#include "FlexCAN_Ip_Irq.h"
#include "FlexCAN_Ip_HwAccess.h"
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
#include "Dma_Ip.h"
#endif
#if (STD_ON == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE)
#define USER_MODE_REG_PROT_ENABLED (STD_ON)
#include "RegLockMacros.h"
#endif /* (STD_ON == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE) */
#include "SchM_Can.h"
#ifdef MCAL_ENABLE_FAULT_INJECTION
#include "Mcal.h"
#endif
/*==================================================================================================
* SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#define FLEXCAN_IP_VENDOR_ID_C 43
#define FLEXCAN_IP_AR_RELEASE_MAJOR_VERSION_C 4
#define FLEXCAN_IP_AR_RELEASE_MINOR_VERSION_C 4
#define FLEXCAN_IP_AR_RELEASE_REVISION_VERSION_C 0
#define FLEXCAN_IP_SW_MAJOR_VERSION_C 0
#define FLEXCAN_IP_SW_MINOR_VERSION_C 9
#define FLEXCAN_IP_SW_PATCH_VERSION_C 0
/*==================================================================================================
* FILE VERSION CHECKS
==================================================================================================*/
/* Check if current file and FlexCAN_Ip.h header file are of the same vendor */
#if (FLEXCAN_IP_VENDOR_ID_C != FLEXCAN_IP_VENDOR_ID_H)
#error "FlexCAN_Ip.c and FlexCAN_Ip.h have different vendor ids"
#endif
/* Check if current file and FlexCAN_Ip.h header file are of the same Autosar version */
#if ((FLEXCAN_IP_AR_RELEASE_MAJOR_VERSION_C != FLEXCAN_IP_AR_RELEASE_MAJOR_VERSION_H) || \
(FLEXCAN_IP_AR_RELEASE_MINOR_VERSION_C != FLEXCAN_IP_AR_RELEASE_MINOR_VERSION_H) || \
(FLEXCAN_IP_AR_RELEASE_REVISION_VERSION_C != FLEXCAN_IP_AR_RELEASE_REVISION_VERSION_H))
#error "AutoSar Version Numbers of FlexCAN_Ip.c and FlexCAN_Ip.h are different"
#endif
/* Check if current file and FlexCAN_Ip.h header file are of the same Software version */
#if ((FLEXCAN_IP_SW_MAJOR_VERSION_C != FLEXCAN_IP_SW_MAJOR_VERSION_H) || \
(FLEXCAN_IP_SW_MINOR_VERSION_C != FLEXCAN_IP_SW_MINOR_VERSION_H) || \
(FLEXCAN_IP_SW_PATCH_VERSION_C != FLEXCAN_IP_SW_PATCH_VERSION_H))
#error "Software Version Numbers of FlexCAN_Ip.c and FlexCAN_Ip.h are different"
#endif
/* Check if current file and FlexCAN_Ip_Irq.h header file are of the same vendor */
#if (FLEXCAN_IP_VENDOR_ID_C != FLEXCAN_IP_IRQ_VENDOR_ID_H)
#error "FlexCAN_Ip.c and FlexCAN_Ip_Irq.h have different vendor ids"
#endif
/* Check if current file and FlexCAN_Ip_Irq.h header file are of the same Autosar version */
#if ((FLEXCAN_IP_AR_RELEASE_MAJOR_VERSION_C != FLEXCAN_IP_IRQ_AR_RELEASE_MAJOR_VERSION_H) || \
(FLEXCAN_IP_AR_RELEASE_MINOR_VERSION_C != FLEXCAN_IP_IRQ_AR_RELEASE_MINOR_VERSION_H) || \
(FLEXCAN_IP_AR_RELEASE_REVISION_VERSION_C != FLEXCAN_IP_IRQ_AR_RELEASE_REVISION_VERSION_H))
#error "AutoSar Version Numbers of FlexCAN_Ip.c and FlexCAN_Ip_Irq.h are different"
#endif
/* Check if current file and FlexCAN_Ip_Irq.h header file are of the same Software version */
#if ((FLEXCAN_IP_SW_MAJOR_VERSION_C != FLEXCAN_IP_IRQ_SW_MAJOR_VERSION_H) || \
(FLEXCAN_IP_SW_MINOR_VERSION_C != FLEXCAN_IP_IRQ_SW_MINOR_VERSION_H) || \
(FLEXCAN_IP_SW_PATCH_VERSION_C != FLEXCAN_IP_IRQ_SW_PATCH_VERSION_H))
#error "Software Version Numbers of FlexCAN_Ip.c and FlexCAN_Ip_Irq.h are different"
#endif
/* Check if current file and FlexCAN_Ip_HwAccess.h header file are of the same vendor */
#if (FLEXCAN_IP_VENDOR_ID_C != FLEXCAN_IP_HWACCESS_VENDOR_ID_H)
#error "FlexCAN_Ip.c and FlexCAN_Ip_HwAccess.h have different vendor ids"
#endif
/* Check if current file and FlexCAN_Ip_HwAccess.h header file are of the same Autosar version */
#if ((FLEXCAN_IP_AR_RELEASE_MAJOR_VERSION_C != FLEXCAN_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION_H) || \
(FLEXCAN_IP_AR_RELEASE_MINOR_VERSION_C != FLEXCAN_IP_HWACCESS_AR_RELEASE_MINOR_VERSION_H) || \
(FLEXCAN_IP_AR_RELEASE_REVISION_VERSION_C != FLEXCAN_IP_HWACCESS_AR_RELEASE_REVISION_VERSION_H))
#error "AutoSar Version Numbers of FlexCAN_Ip.c and FlexCAN_Ip_HwAccess.h are different"
#endif
/* Check if current file and FlexCAN_Ip_HwAccess.h header file are of the same Software version */
#if ((FLEXCAN_IP_SW_MAJOR_VERSION_C != FLEXCAN_IP_HWACCESS_SW_MAJOR_VERSION_H) || \
(FLEXCAN_IP_SW_MINOR_VERSION_C != FLEXCAN_IP_HWACCESS_SW_MINOR_VERSION_H) || \
(FLEXCAN_IP_SW_PATCH_VERSION_C != FLEXCAN_IP_HWACCESS_SW_PATCH_VERSION_H))
#error "Software Version Numbers of FlexCAN_Ip.c and FlexCAN_Ip_HwAccess.h are different"
#endif
#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
/* Check if current file and SchM_Can header file are of the same version */
#endif
/*==================================================================================================
* LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/
/*==================================================================================================
* LOCAL MACROS
==================================================================================================*/
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
#define CAN_ENHANCE_TRASNFER_DIMENSION_LIST (13U)
#endif /* (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) */
#define CAN_TRASNFER_DIMENSION_LIST (10U)
#endif /*(FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)*/
/*==================================================================================================
* LOCAL CONSTANTS
==================================================================================================*/
/*==================================================================================================
* GLOBAL CONSTANTS
==================================================================================================*/
/*==================================================================================================
* GLOBAL VARIABLES
==================================================================================================*/
#define CAN_START_SEC_CONST_UNSPECIFIED
#include "Can_MemMap.h"
/* Table of base addresses for CAN instances. */
static FLEXCAN_Type * const g_Flexcan_Ip_aBase[] = FLEXCAN_BASE_PTRS;
#define CAN_STOP_SEC_CONST_UNSPECIFIED
#include "Can_MemMap.h"
#define CAN_START_SEC_VAR_INIT_UNSPECIFIED_NO_CACHEABLE
#include "Can_MemMap.h"
/* Pointer to runtime state structure.*/
static Flexcan_Ip_StateType * g_flexcan_Ip_StatePtr[FLEXCAN_INSTANCE_COUNT];
#define CAN_STOP_SEC_VAR_INIT_UNSPECIFIED_NO_CACHEABLE
#include "Can_MemMap.h"
#define CAN_START_SEC_CODE
#include "Can_MemMap.h"
/*==================================================================================================
* LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
/* Init legacy, enhanced fifo if requested, if no fifo request, return success. */
static Flexcan_Ip_StatusType FlexCAN_InitRxFifo(FLEXCAN_Type * pBase, const Flexcan_Ip_ConfigType * Flexcan_Ip_pData);
/* Init basically controller , this function is called in FlexCAN_Ip_Init only */
static Flexcan_Ip_StatusType FlexCAN_InitController(FLEXCAN_Type * pBase, const Flexcan_Ip_ConfigType * Flexcan_Ip_pData);
static Flexcan_Ip_StatusType FlexCAN_StartRxMessageBufferData(uint8 instance,
uint8 mb_idx,
Flexcan_Ip_MsgBuffType * data,
boolean isPolling);
static Flexcan_Ip_StatusType FlexCAN_StartSendData(uint8 Flexcan_Ip_u8Instance,
uint8 mb_idx,
const Flexcan_Ip_DataInfoType * tx_info,
uint32 msg_id,
const uint8 * mb_data);
static Flexcan_Ip_StatusType FlexCAN_StartRxMessageFifoData(uint8 instance,
Flexcan_Ip_MsgBuffType * data);
static Flexcan_Ip_StatusType FlexCAN_ProccessLegacyRxFIFO(uint8 u8Instance, uint32 u32TimeoutMs);
static void FlexCAN_IRQHandlerRxMB(uint8 instance,
uint32 mb_idx);
static void FlexCAN_IRQHandlerTxMB(uint8 u8Instance, uint32 u32MbIdx);
static inline void FlexCAN_IRQHandlerRxFIFO(uint8 instance,
uint32 mb_idx);
static inline void FlexCAN_ProcessSpuriousInterruptMB(uint8 instance, uint32 startMbIdx, uint32 endMbIdx);
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
static void DMA_Can_Callback(uint8 instance);
#endif
#if (STD_ON == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE)
static void FlexCAN_SetUserAccessAllowed(const FLEXCAN_Type * pBase);
static void FlexCAN_ClrUserAccessAllowed(const FLEXCAN_Type * pBase);
#endif
static Flexcan_Ip_StatusType FlexCAN_AbortTxTransfer(uint8 u8Instance, uint8 mb_idx);
static void FlexCAN_AbortRxTransfer(uint8 u8Instance, uint8 mb_idx);
static void FlexCAN_CompleteRxMessageFifoData(uint8 instance);
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
static void FlexCAN_IRQHandlerEnhancedRxFIFO(uint8 instance, uint32 intType);
static inline boolean FlexCAN_ProcessIRQHandlerEnhancedRxFIFO(uint8 u8Instance, boolean bIsSpuriousIntPrevious);
static void FlexCAN_CompleteRxMessageEnhancedFifoData(uint8 instance);
static Flexcan_Ip_StatusType FlexCAN_StartRxMessageEnhancedFifoData(uint8 instance,
Flexcan_Ip_MsgBuffType * data);
static Flexcan_Ip_StatusType FlexCAN_ProccessEnhancedRxFifo(uint8 u8Instance, uint32 u32TimeoutMs);
/*==================================================================================================
* LOCAL FUNCTIONS
==================================================================================================*/
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_InitRxFifo
* Description : Initialize fifo and dma if requested.
*
* This is not a public API as it is called from other driver functions.
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_InitRxFifo(FLEXCAN_Type * pBase, const Flexcan_Ip_ConfigType * Flexcan_Ip_pData)
{
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
/* Enable RxFIFO feature, if requested. This might fail if the FD mode is enabled. */
if (Flexcan_Ip_pData->is_rx_fifo_needed)
{
eResult = FlexCAN_EnableRxFifo(pBase, (uint32)Flexcan_Ip_pData->num_id_filters);
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
/* Enable Enhanced RxFIFO feature, if requested.
* This might fail if the current CAN instance does not support Enhaneced RxFIFO or the Rx FIFO is enabled. */
if ((FLEXCAN_STATUS_SUCCESS == eResult) && (Flexcan_Ip_pData->is_enhanced_rx_fifo_needed))
{
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
if (Flexcan_Ip_pData->transfer_type == FLEXCAN_RXFIFO_USING_DMA)
{
eResult = FlexCAN_EnableEnhancedRxFifo(pBase,
(uint32)Flexcan_Ip_pData->num_enhanced_std_id_filters,
(uint32)Flexcan_Ip_pData->num_enhanced_ext_id_filters,
(uint32)0U); /* for dma, each a frame received -> a minor loop */
}
else
#endif /* FEATURE_CAN_HAS_DMA_ENABLE */
{
eResult = FlexCAN_EnableEnhancedRxFifo(pBase,
(uint32)Flexcan_Ip_pData->num_enhanced_std_id_filters,
(uint32)Flexcan_Ip_pData->num_enhanced_ext_id_filters,
(uint32)Flexcan_Ip_pData->num_enhanced_watermark);
}
}
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
if (FLEXCAN_STATUS_SUCCESS == eResult)
{
/* Enable DMA support for RxFIFO transfer, if requested. */
if (Flexcan_Ip_pData->transfer_type == FLEXCAN_RXFIFO_USING_DMA)
{
if (((pBase->MCR & FLEXCAN_MCR_RFEN_MASK) >> FLEXCAN_MCR_RFEN_SHIFT) != 0U)
{
FlexCAN_SetRxFifoDMA(pBase, TRUE);
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
else if (FlexCAN_IsEnhancedRxFifoAvailable(pBase))
{
if (FlexCAN_IsEnhancedRxFifoEnabled(pBase))
{
FlexCAN_SetRxFifoDMA(pBase, TRUE);
FlexCAN_ConfigEnhancedRxFifoDMA(pBase, 20U); /* always transfer 80 bytes (DMALW = 19)*/
}
else
{
eResult = FLEXCAN_STATUS_ERROR;
}
}
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
else
{
eResult = FLEXCAN_STATUS_ERROR;
}
}
else
{
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
if (FlexCAN_IsEnhancedRxFifoAvailable(pBase))
{
/* Clear Enhanced Rx FIFO status.*/
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(pBase, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(pBase, CAN_ENHANCED_RXFIFO_WATERMARK);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(pBase, CAN_ENHANCED_RXFIFO_OVERFLOW);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(pBase, CAN_ENHANCED_RXFIFO_UNDERFLOW);
/* Clear the Enhanced RX FIFO engine */
FlexCAN_ClearEnhancedRxFifoEngine(pBase);
}
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
FlexCAN_SetRxFifoDMA(pBase, FALSE);
}
}
#endif /* FEATURE_CAN_HAS_DMA_ENABLE */
return eResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_InitController
* Description : Initialize basically controller.
*
* This is not a public API as it is called from other driver functions.
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_InitController(FLEXCAN_Type * pBase, const Flexcan_Ip_ConfigType * Flexcan_Ip_pData)
{
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
if (FlexCAN_IsEnabled(pBase))
{
/* To enter Disable Mode requires FreezMode first */
eResult = FlexCAN_EnterFreezeMode(pBase);
if(FLEXCAN_STATUS_SUCCESS == eResult)
{
eResult = FlexCAN_Disable(pBase);
}
}
if(FLEXCAN_STATUS_SUCCESS == eResult)
{
/* Start critical section: implementation depends on integrator */
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_00();
/* Enable FlexCAN Module need to perform SoftReset & ClearRam */
pBase->MCR &= ~FLEXCAN_MCR_MDIS_MASK;
/* End critical section: implementation depends on integrator */
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_00();
/* Initialize FLEXCAN device */
eResult = FlexCAN_Init(pBase);
if (eResult != FLEXCAN_STATUS_SUCCESS)
{
/* To enter Disable Mode requires FreezMode first */
(void)FlexCAN_EnterFreezeMode(pBase);
(void)FlexCAN_Disable(pBase);
}
else
{
#if (FEATURE_CAN_HAS_MEM_ERR_DET == STD_ON)
/* Disable the Protection again because is enabled by soft reset */
FlexCAN_DisableMemErrorDetection(pBase);
#endif
/* Enable/Disable FD and check FD was set as expected. Setting FD as enabled
* might fail if the current CAN instance does not support FD. */
FlexCAN_SetFDEnabled(pBase, Flexcan_Ip_pData->fd_enable, Flexcan_Ip_pData->bitRateSwitch);
/* No more required, I don't expect any other NPIs with and without Interfaces with FD support
* if (FLEXCAN_IsFDEnabled(base) != Flexcan_Ip_pData->fd_enable)
{
return FLEXCAN_STATUS_ERROR;
}*/
/* configure depends on controller options. */
FlexCAN_ConfigCtrlOptions(pBase, Flexcan_Ip_pData->ctrlOptions);
/* Disable the self reception feature if FlexCAN is not in loopback mode. */
if (Flexcan_Ip_pData->flexcanMode != FLEXCAN_LOOPBACK_MODE)
{
FlexCAN_SetSelfReception(pBase, FALSE);
}
/* Init legacy fifo, enhanced fifo if requested. */
eResult = FlexCAN_InitRxFifo(pBase, Flexcan_Ip_pData);
if (eResult != FLEXCAN_STATUS_SUCCESS)
{
/* To enter Disable Mode requires FreezMode first */
(void)FlexCAN_EnterFreezeMode(pBase);
(void)FlexCAN_Disable(pBase);
}
else
{
#if (FEATURE_CAN_HAS_FD == STD_ON)
/* Set payload size. */
FlexCAN_SetPayloadSize(pBase, &Flexcan_Ip_pData->payload);
#endif /* FEATURE_CAN_HAS_FD */
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
eResult = FlexCAN_SetMaxMsgBuffNum(pBase, Flexcan_Ip_pData->max_num_mb);
if (eResult != FLEXCAN_STATUS_SUCCESS)
{
/* To enter Disable Mode requires FreezMode first */
(void)FlexCAN_EnterFreezeMode(pBase);
(void)FlexCAN_Disable(pBase);
}
#else
(void)FlexCAN_SetMaxMsgBuffNum(pBase, Flexcan_Ip_pData->max_num_mb);
#endif /* FLEXCAN_DEV_ERROR_DETECT */
}
}
}
return eResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_CompleteRxMessageEnhancedFifoData
* Description : Finish up a receive by completing the process of receiving
* data and disabling the interrupt.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static void FlexCAN_CompleteRxMessageEnhancedFifoData(uint8 instance)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
uint32 u32MbCnt = 0U;
uint8 j;
Flexcan_Ip_MsgBuffType * fifo_message = NULL_PTR;
uint32 * msgData_32 = NULL_PTR;
uint8 flexcan_mb_dlc_value = 0U;
uint8 can_dlc_payload = 0U;
uint8 can_real_payload = 0U;
#endif /* FEATURE_CAN_HAS_DMA_ENABLE */
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(FlexCAN_IsEnhancedRxFifoAvailable(base));
#endif /* (FLEXCAN_DEV_ERROR_DETECT == STD_ON) */
if (state->enhancedFifoOutput.isPolling == FALSE)
{
/* Reset to default value to avoid re-enable when calling Ip_EnableInterrupt */
state->enhancedFifoOutput.isPolling = TRUE;
/* Disable Enhanced RX FIFO interrupts*/
FlexCAN_SetEnhancedRxFifoIntAll(base, FALSE);
}
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
else if (state->transferType == FLEXCAN_RXFIFO_USING_DMA)
{
Dma_Ip_LogicChannelStatusType dmaStatus;
Dma_Ip_GetLogicChannelStatus(state->rxFifoDMAChannel, &dmaStatus);
if (dmaStatus.ChStateValue == DMA_IP_CH_ERROR_STATE)
{
(void)Dma_Ip_SetLogicChannelCommand(state->rxFifoDMAChannel, DMA_IP_CH_CLEAR_ERROR);
state->enhancedFifoOutput.state = FLEXCAN_MB_DMA_ERROR;
}
(void)Dma_Ip_SetLogicChannelCommand(state->rxFifoDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
if (state->enhancedFifoOutput.state != FLEXCAN_MB_DMA_ERROR)
{
fifo_message = state->enhancedFifoOutput.pMBmessage;
msgData_32 = (uint32 *)fifo_message->data;
for (u32MbCnt = 0U; u32MbCnt < state->u32NumOfMbTransferByDMA; u32MbCnt++)
{
/* Adjust the ID if it is not extended */
if (((fifo_message->cs) & CAN_CS_IDE_MASK) == 0U)
{
fifo_message->msgId = fifo_message->msgId >> CAN_ID_STD_SHIFT;
}
/* Extract the data length */
flexcan_mb_dlc_value = (uint8)((fifo_message->cs & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
can_dlc_payload = FlexCAN_ComputePayloadSize(flexcan_mb_dlc_value);
can_real_payload = 0U;
/* Extract the IDHIT and Time Stamp */
if ((fifo_message->cs & CAN_CS_RTR_MASK) != 0U)
{
can_real_payload = 0U;
}
else
{
can_real_payload = can_dlc_payload;
}
uint8 idhit_offset = (can_real_payload >> 2U) + (((can_real_payload % 4U) != 0U) ? 1U : 0U);
#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
/* Extract the Time Stamp */
if (FLEXCAN_IsHRTimeStampEnabled(base))
{
fifo_message->time_stamp = (uint32)(msgData_32[idhit_offset + 1U]);
}
else
#endif /* FEATURE_CAN_HAS_HR_TIMER */
{
fifo_message->time_stamp = (uint32)((fifo_message->cs & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
}
/* Extract the IDHIT */
fifo_message->id_hit = (uint8)(((msgData_32[idhit_offset]) & CAN_ENHANCED_IDHIT_MASK) >> CAN_ENHANCED_IDHIT_SHIFT);
/* Extract the dataLen */
fifo_message->dataLen = can_dlc_payload;
/* Reverse the endianness */
for (j = 0U; j < idhit_offset; j++)
{
FlexcanSwapBytesInWord(msgData_32[j], msgData_32[j]);
}
fifo_message++;
msgData_32 = (uint32 *)fifo_message->data;
}
}
else
{
/* If Enhanced Rx FIFO has Pending Request that generated error,
* the EnhancedRxFIFO need to be empty to activate DMA */
FlexCAN_ClearOutputEnhanceFIFO(base);
}
}
else
{
/* avoid misra */
}
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
/* Clear enhanced rx fifo message*/
state->enhancedFifoOutput.pMBmessage = NULL_PTR;
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
if (state->enhancedFifoOutput.state != FLEXCAN_MB_DMA_ERROR)
{
state->enhancedFifoOutput.state = FLEXCAN_MB_IDLE;
if ((state->callback != NULL_PTR) && (state->transferType == FLEXCAN_RXFIFO_USING_DMA))
{
state->callback(instance, FLEXCAN_EVENT_DMA_COMPLETE, FLEXCAN_MB_ENHANCED_RXFIFO, state);
}
}
else
{
if (state->callback != NULL_PTR)
{
state->callback((uint8)instance, FLEXCAN_EVENT_DMA_ERROR, FLEXCAN_MB_ENHANCED_RXFIFO, state);
}
}
#else /* if FEATURE_CAN_HAS_DMA_ENABLE */
state->enhancedFifoOutput.state = FLEXCAN_MB_IDLE;
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_StartRxMessageEnhancedFifoData
* Description : Initiate (start) a receive by beginning the process of
* receiving data and enabling the interrupt.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_StartRxMessageEnhancedFifoData(uint8 instance,
Flexcan_Ip_MsgBuffType * data)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif /* (FLEXCAN_DEV_ERROR_DETECT == STD_ON) */
/* Start receiving fifo */
if (state->enhancedFifoOutput.state == FLEXCAN_MB_RX_BUSY)
{
eResult = FLEXCAN_STATUS_BUSY;
}
else
{
state->enhancedFifoOutput.state = FLEXCAN_MB_RX_BUSY;
/* This will get filled by the interrupt handler */
state->enhancedFifoOutput.pMBmessage = data;
if (state->transferType == FLEXCAN_RXFIFO_USING_INTERRUPTS)
{
state->enhancedFifoOutput.isPolling = FALSE;
if ((boolean)TRUE == state->isIntActive)
{
/* Enable All Enhanced RX FIFO interrupts*/
FlexCAN_SetEnhancedRxFifoIntAll(base, TRUE);
}
}
if (state->transferType == FLEXCAN_RXFIFO_USING_POLLING)
{
state->enhancedFifoOutput.isPolling = TRUE;
}
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
if (state->transferType == FLEXCAN_RXFIFO_USING_DMA)
{
/* reset to default to avoid enabling interrupt */
state->enhancedFifoOutput.isPolling = TRUE;
Dma_Ip_ReturnType edmaStatus;
Dma_Ip_LogicChannelTransferListType trasfer[CAN_ENHANCE_TRASNFER_DIMENSION_LIST] = {
{
.Param = DMA_IP_CH_SET_SOURCE_ADDRESS,
.Value = ((uint32)base + (uint32)FEATURE_CAN_ENHANCED_FIFO_RAM_OFFSET),
},
{
.Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET ,
.Value = 4,
},
{
.Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE,
.Value = DMA_IP_TRANSFER_SIZE_4_BYTE,
},
{
.Param = DMA_IP_CH_SET_DESTINATION_ADDRESS,
.Value = (uint32)(state->enhancedFifoOutput.pMBmessage),
},
{
.Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET,
.Value = 4,
},
{
.Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE,
.Value = DMA_IP_TRANSFER_SIZE_4_BYTE,
},
{
.Param = DMA_IP_CH_SET_MINORLOOP_SIZE,
.Value = 80,
},
{
.Param = DMA_IP_CH_SET_MAJORLOOP_COUNT,
.Value = state->u32NumOfMbTransferByDMA,
},
{
.Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT,
.Value = 1,
},
{
.Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST,
.Value = 1,
},
{
.Param = DMA_IP_CH_SET_MINORLOOP_EN_SRC_OFFSET,
.Value = 1, /* enable for src address: after each minor loop, jump back to output of enhance fifo */
},
{
.Param = DMA_IP_CH_SET_MINORLOOP_EN_DST_OFFSET,
.Value = 0, /* disable for dst address: after each minor loop: standing on next element of pMBmessage array */
},
{
.Param = DMA_IP_CH_SET_MINORLOOP_SIGNED_OFFSET,
.Value = (uint32)((sint32)(-80)), /* enable for src address: after each minor loop, jump back to output of enhance fifo */
}
};
edmaStatus = Dma_Ip_SetLogicChannelTransferList(state->rxFifoDMAChannel, &trasfer[0], CAN_ENHANCE_TRASNFER_DIMENSION_LIST);
if (edmaStatus != DMA_IP_STATUS_SUCCESS)
{
state->enhancedFifoOutput.state = FLEXCAN_MB_IDLE;
eResult = FLEXCAN_STATUS_ERROR;
}
else
{
edmaStatus = Dma_Ip_SetLogicChannelCommand(state->rxFifoDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
if (edmaStatus != DMA_IP_STATUS_SUCCESS)
{
state->enhancedFifoOutput.state = FLEXCAN_MB_IDLE;
eResult = FLEXCAN_STATUS_ERROR;
}
}
}
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
}
return eResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_ProccessEnhancedRxFifo
* Description : This function will process the enhanced RxFIFO in blocking mode.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_ProccessEnhancedRxFifo(uint8 u8Instance, uint32 u32TimeoutMs)
{
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StateType * pState = g_flexcan_Ip_StatePtr[u8Instance];
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
uint32 timeStart = 0U;
uint32 timeElapsed = 0U;
uint32 mS2Ticks = OsIf_MicrosToTicks((u32TimeoutMs * 1000U), CAN_SERVICE_TIMEOUT_TYPE);
uint32 u32intType = 0U;
timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
while (FLEXCAN_MB_RX_BUSY == pState->enhancedFifoOutput.state)
{
if (FLEXCAN_RXFIFO_USING_POLLING == pState->transferType)
{
for (u32intType = CAN_ENHANCED_RXFIFO_UNDERFLOW; \
u32intType >= CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE; \
u32intType--)
{
if (FlexCAN_GetEnhancedRxFIFOStatusFlag(pBase, u32intType) != 0U)
{
FlexCAN_IRQHandlerEnhancedRxFIFO(u8Instance, u32intType);
}
}
}
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
if (timeElapsed >= mS2Ticks)
{
eResult = FLEXCAN_STATUS_TIMEOUT;
break;
}
}
if ((FLEXCAN_STATUS_TIMEOUT == eResult) && (FLEXCAN_RXFIFO_USING_POLLING != pState->transferType))
{
/* Disable Enhanced RX FIFO interrupts*/
FlexCAN_SetEnhancedRxFifoIntAll(pBase, (boolean)FALSE);
#if FEATURE_CAN_HAS_DMA_ENABLE
/* Check if transfer is done over DMA and stop transfer */
if ((FLEXCAN_MB_RX_BUSY == pState->enhancedFifoOutput.state) && (FLEXCAN_RXFIFO_USING_DMA == pState->transferType))
{
(void)Dma_Ip_SetLogicChannelCommand(pState->rxFifoDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
/* Reset Entire Enhance FIFO if timeout occurred */
if (FLEXCAN_MB_RX_BUSY == pState->enhancedFifoOutput.state)
{
#if ((STD_ON == FLEXCAN_ENABLE_USER_MODE_SUPPORT) && (STD_OFF == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE))
OsIf_Trusted_Call1param(FlexCAN_ClearOutputEnhanceFIFO, pBase);
#else
FlexCAN_ClearOutputEnhanceFIFO(pBase);
#endif
}
}
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
}
switch (pState->enhancedFifoOutput.state)
{
case FLEXCAN_MB_RX_BUSY:
pState->enhancedFifoOutput.state = FLEXCAN_MB_IDLE;
break;
case FLEXCAN_MB_IDLE:
eResult = FLEXCAN_STATUS_SUCCESS;
break;
#if FEATURE_CAN_HAS_DMA_ENABLE
case FLEXCAN_MB_DMA_ERROR:
eResult = FLEXCAN_STATUS_ERROR;
break;
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
default:
eResult = FLEXCAN_STATUS_ERROR;
break;
}
return eResult;
}
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_ProccessLegacyRxFIFO
* Description : This function will process the enhanced RxFIFO in blocking mode.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_ProccessLegacyRxFIFO(uint8 u8Instance, uint32 u32TimeoutMs)
{
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StateType * pState = g_flexcan_Ip_StatePtr[u8Instance];
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
uint32 timeStart = 0U;
uint32 timeElapsed = 0U;
uint32 mS2Ticks = OsIf_MicrosToTicks((u32TimeoutMs * 1000U), CAN_SERVICE_TIMEOUT_TYPE);
uint32 u32intType = 0U;
timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
while (FLEXCAN_MB_RX_BUSY == pState->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state)
{
if (FLEXCAN_RXFIFO_USING_POLLING == pState->transferType)
{
for (u32intType = CAN_LEGACY_RXFIFO_OVERFLOW; \
u32intType >= CAN_LEGACY_RXFIFO_FRAME_AVAILABLE; \
u32intType--)
{
if (FlexCAN_GetBuffStatusFlag(pBase, u32intType) != 0U)
{
FlexCAN_IRQHandlerRxFIFO(u8Instance, u32intType);
}
}
}
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
if (timeElapsed >= mS2Ticks)
{
eResult = FLEXCAN_STATUS_TIMEOUT;
break;
}
}
if ((FLEXCAN_STATUS_TIMEOUT == eResult) && (FLEXCAN_RXFIFO_USING_POLLING != pState->transferType))
{
/* Disable RX FIFO interrupts*/
(void)FlexCAN_SetMsgBuffIntCmd(pBase, u8Instance, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE, (boolean)FALSE, pState->isIntActive);
(void)FlexCAN_SetMsgBuffIntCmd(pBase, u8Instance, CAN_LEGACY_RXFIFO_WARNING, (boolean)FALSE, pState->isIntActive);
(void)FlexCAN_SetMsgBuffIntCmd(pBase, u8Instance, CAN_LEGACY_RXFIFO_OVERFLOW, (boolean)FALSE, pState->isIntActive);
#if FEATURE_CAN_HAS_DMA_ENABLE
/* Check if transfer is done over DMA and stop transfer */
if ((FLEXCAN_MB_RX_BUSY == pState->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state) && (FLEXCAN_RXFIFO_USING_DMA == pState->transferType))
{
/* This function always return status success */
(void)Dma_Ip_SetLogicChannelCommand(pState->rxFifoDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
}
#endif
}
switch (pState->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state)
{
case FLEXCAN_MB_RX_BUSY:
pState->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_IDLE;
break;
case FLEXCAN_MB_IDLE:
eResult = FLEXCAN_STATUS_SUCCESS;
break;
#if FEATURE_CAN_HAS_DMA_ENABLE
case FLEXCAN_MB_DMA_ERROR:
eResult = FLEXCAN_STATUS_ERROR;
break;
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
default:
eResult = FLEXCAN_STATUS_ERROR;
break;
}
return eResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_DRV_StartRxMessageBufferData
* Description : Initiate (start) a receive by beginning the process of
* receiving data and enabling the interrupt.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_StartRxMessageBufferData(uint8 instance,
uint8 mb_idx,
Flexcan_Ip_MsgBuffType * data,
boolean isPolling)
{
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#endif
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
if ((boolean)TRUE == FlexCAN_IsMbOutOfRange(base, mb_idx, state->bIsLegacyFifoEn, state->u32MaxMbNum))
{
result = FLEXCAN_STATUS_BUFF_OUT_OF_RANGE;
}
else
{
#endif
/* Start receiving mailbox */
if (state->mbs[mb_idx].state != FLEXCAN_MB_IDLE)
{
result = FLEXCAN_STATUS_BUSY;
}
else
{
state->mbs[mb_idx].state = FLEXCAN_MB_RX_BUSY;
state->mbs[mb_idx].pMBmessage = data;
state->mbs[mb_idx].isPolling = isPolling;
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
}
#endif
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_DRV_StartSendData
* Description : Initiate (start) a transmit by beginning the process of
* sending data.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_StartSendData(uint8 Flexcan_Ip_u8Instance,
uint8 mb_idx,
const Flexcan_Ip_DataInfoType * tx_info,
uint32 msg_id,
const uint8 * mb_data)
{
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_MsbuffCodeStatusType cs;
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[Flexcan_Ip_u8Instance];
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[Flexcan_Ip_u8Instance];
/* aici e ilogic ca nu are rost sa faci checkul dupa ce ai alocat aiurea */
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(Flexcan_Ip_u8Instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(tx_info != NULL_PTR);
if ((boolean)TRUE == FlexCAN_IsMbOutOfRange(base, mb_idx, state->bIsLegacyFifoEn, state->u32MaxMbNum))
{
eResult = FLEXCAN_STATUS_BUFF_OUT_OF_RANGE;
}
else
{
#endif
if (state->mbs[mb_idx].state != FLEXCAN_MB_IDLE)
{
eResult = FLEXCAN_STATUS_BUSY;
}
else
{
/* Clear message buffer flag */
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
state->mbs[mb_idx].state = FLEXCAN_MB_TX_BUSY;
state->mbs[mb_idx].time_stamp = 0U;
state->mbs[mb_idx].isPolling = tx_info->is_polling;
state->mbs[mb_idx].isRemote = tx_info->is_remote;
cs.dataLen = tx_info->data_length;
cs.msgIdType = tx_info->msg_id_type;
#if (FEATURE_CAN_HAS_FD == STD_ON)
cs.fd_enable = tx_info->fd_enable;
cs.fd_padding = tx_info->fd_padding;
cs.enable_brs = tx_info->enable_brs;
#endif
if (tx_info->is_remote)
{
cs.code = (uint32)FLEXCAN_TX_REMOTE;
}
else
{
cs.code = (uint32)FLEXCAN_TX_DATA;
}
FlexCAN_SetTxMsgBuff(base, mb_idx, &cs, msg_id, mb_data, FALSE);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
}
#endif
return eResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_StartRxMessageFifoData
* Description : Initiate (start) a receive by beginning the process of
* receiving data and enabling the interrupt.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_StartRxMessageFifoData(uint8 instance,
Flexcan_Ip_MsgBuffType * data)
{
FLEXCAN_Type * base = NULL_PTR;
Flexcan_Ip_StateType * state = NULL_PTR;
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
base = g_Flexcan_Ip_aBase[instance];
state = g_flexcan_Ip_StatePtr[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
/* Check if RxFIFO feature is enabled */
if (state->bIsLegacyFifoEn == FALSE)
{
eResult = FLEXCAN_STATUS_ERROR;
}
else
{
#endif
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
if (state->transferType == FLEXCAN_RXFIFO_USING_DMA)
{
if (state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state == FLEXCAN_MB_DMA_ERROR)
{
/* Check if FIFO has Pending Request that generated error,
* the RxFIFO need to be empty to activate DMA */
#if ((STD_ON == FLEXCAN_ENABLE_USER_MODE_SUPPORT) && (STD_OFF == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE))
OsIf_Trusted_Call1param(FlexCAN_ClearOutputLegacyFIFO, base);
#else
FlexCAN_ClearOutputLegacyFIFO(base);
#endif
/* Change status of MB to be reconfigured with DMA transfer */
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_IDLE;
}
}
#endif /* FEATURE_CAN_HAS_DMA_ENABLE */
/* Start receiving fifo */
if (state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state != FLEXCAN_MB_IDLE)
{
eResult = FLEXCAN_STATUS_BUSY;
}
else
{
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_RX_BUSY;
if (state->transferType == FLEXCAN_RXFIFO_USING_POLLING)
{
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].isPolling = TRUE;
}
/* This will get filled by the interrupt handler */
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage = data;
if (state->transferType == FLEXCAN_RXFIFO_USING_INTERRUPTS)
{
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].isPolling = FALSE;
/* Enable RX FIFO interrupts*/
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, CAN_LEGACY_RXFIFO_WARNING, TRUE, state->isIntActive);
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, CAN_LEGACY_RXFIFO_OVERFLOW, TRUE, state->isIntActive);
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE, TRUE, state->isIntActive);
}
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
if (state->transferType == FLEXCAN_RXFIFO_USING_DMA)
{
Dma_Ip_ReturnType edmaStatus;
Dma_Ip_LogicChannelTransferListType trasfer[CAN_TRASNFER_DIMENSION_LIST] = {
{
.Param = DMA_IP_CH_SET_SOURCE_ADDRESS,
.Value = (uint32)FlexCAN_GetMsgBuffRegion(base, FLEXCAN_MB_HANDLE_RXFIFO)
},
{
.Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET ,
.Value = 4,
},
{
.Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE,
.Value = DMA_IP_TRANSFER_SIZE_4_BYTE,
},
{
.Param = DMA_IP_CH_SET_DESTINATION_ADDRESS,
.Value = (uint32)(state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage)
},
{
.Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET,
.Value = 4,
},
{
.Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE,
.Value = DMA_IP_TRANSFER_SIZE_4_BYTE,
},
{
.Param = DMA_IP_CH_SET_MINORLOOP_SIZE,
.Value = 16,
},
{
.Param = DMA_IP_CH_SET_MAJORLOOP_COUNT,
.Value = 1,
},
{
.Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT,
.Value = 1,
},
{
.Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST,
.Value = 1,
},
};
edmaStatus = Dma_Ip_SetLogicChannelTransferList(state->rxFifoDMAChannel, &trasfer[0], CAN_TRASNFER_DIMENSION_LIST);
if (edmaStatus != DMA_IP_STATUS_SUCCESS)
{
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_IDLE;
eResult = FLEXCAN_STATUS_ERROR;
}
else
{
edmaStatus = Dma_Ip_SetLogicChannelCommand(state->rxFifoDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
if (edmaStatus != DMA_IP_STATUS_SUCCESS)
{
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_IDLE;
eResult = FLEXCAN_STATUS_ERROR;
}
}
}
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
}
#endif
return eResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_IRQHandlerRxMB
* Description : Process IRQHandler in case of Rx MessageBuffer selection
* for CAN interface.
*
* This is not a public API as it is called whenever an interrupt and receive
* individual MB occurs
*END**************************************************************************/
static void FlexCAN_IRQHandlerRxMB(uint8 instance,
uint32 mb_idx)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
Flexcan_Ip_MsgBuffType data;
boolean bCurrentIntStat = (boolean)FALSE;
/* If use pass NULL_PTR, they can get data in callback function by getting state->mbs[mb_idx].pMBmessage */
if (NULL_PTR == state->mbs[mb_idx].pMBmessage)
{
state->mbs[mb_idx].pMBmessage = &data;
}
/* Lock RX message buffer and RX FIFO*/
FlexCAN_LockRxMsgBuff(base, mb_idx);
/* Get RX MB field values*/
FlexCAN_GetMsgBuff(base, mb_idx, state->mbs[mb_idx].pMBmessage);
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
/* Unlock RX message buffer and RX FIFO*/
FlexCAN_UnlockRxMsgBuff(base);
state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
bCurrentIntStat = state->mbs[mb_idx].isPolling;
/* Invoke callback */
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_RX_COMPLETE, mb_idx, state);
}
if ((FLEXCAN_MB_IDLE == state->mbs[mb_idx].state) && ((boolean)FALSE == state->mbs[mb_idx].isPolling))
{
/* callback is not called, need to reset to default value */
state->mbs[mb_idx].isPolling = (boolean)TRUE;
/* Disable the transmitter data register empty interrupt for case: mb is interrupt (it was not use in above callback with the same index) */
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, mb_idx, FALSE, state->isIntActive);
}
else if (((boolean)FALSE == bCurrentIntStat) && ((boolean)TRUE == state->mbs[mb_idx].isPolling))
{
/* Disable the transmitter data register empty interrupt for case: switch from interrupt to polling for the same MB (called in above callback with same mb index) */
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, mb_idx, FALSE, state->isIntActive);
}
else
{
/* Prevent misra */
/* When processing type change from POLL->POLL or INTERRUPT -> INTERRUPT(this Mb is used continously in callback), no need to disable interrupt in the ISR */
}
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_IRQHandlerTxMB
* Description : Process IRQHandler in case of Tx MessageBuffer selection
* for CAN interface.
* note: just using in interrupt mode
* This is not a public API as it is called whenever an interrupt and receive
* individual MB occurs
*END**************************************************************************/
static void FlexCAN_IRQHandlerTxMB(uint8 u8Instance, uint32 u32MbIdx)
{
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
Flexcan_Ip_StateType * pState = g_flexcan_Ip_StatePtr[u8Instance];
Flexcan_Ip_MsgBuffType mb;
boolean bCurrentIntStat = (boolean)FALSE;
if (pState->mbs[u32MbIdx].isRemote)
{
FlexCAN_LockRxMsgBuff(pBase, u32MbIdx);
FlexCAN_GetMsgBuff(pBase, u32MbIdx, &mb);
FlexCAN_UnlockRxMsgBuff(pBase);
pState->mbs[u32MbIdx].time_stamp = mb.time_stamp;
/* If the frame was a remote frame, clear the flag only if the response was
* not received yet. If the response was received, leave the flag set in order
* to be handled when the user calls FLEXCAN_DRV_RxMessageBuffer. */
if (((mb.cs & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT) == (uint32)FLEXCAN_RX_EMPTY)
{
FlexCAN_ClearMsgBuffIntStatusFlag(pBase, u32MbIdx);
}
}
else
{
pState->mbs[u32MbIdx].time_stamp = FlexCAN_GetMsgBuffTimestamp(pBase, u32MbIdx);
FlexCAN_UnlockRxMsgBuff(pBase);
FlexCAN_ClearMsgBuffIntStatusFlag(pBase, u32MbIdx);
}
pState->mbs[u32MbIdx].state = FLEXCAN_MB_IDLE;
bCurrentIntStat = pState->mbs[u32MbIdx].isPolling;
/* Invoke callback */
if (pState->callback != NULL_PTR)
{
pState->callback(u8Instance, FLEXCAN_EVENT_TX_COMPLETE, u32MbIdx, pState);
}
if ((FLEXCAN_MB_IDLE == pState->mbs[u32MbIdx].state) && ((boolean)FALSE == pState->mbs[u32MbIdx].isPolling))
{
/* callback is not called, need to reset to default value */
pState->mbs[u32MbIdx].isPolling = (boolean)TRUE;
/* Disable the transmitter data register empty interrupt for case: mb is interrupt (it was not use in above callback with the same index) */
(void)FlexCAN_SetMsgBuffIntCmd(pBase, u8Instance, u32MbIdx, FALSE, pState->isIntActive);
}
else if (((boolean)FALSE == bCurrentIntStat) && ((boolean)TRUE == pState->mbs[u32MbIdx].isPolling))
{
/* Disable the transmitter data register empty interrupt for case: switch from interrupt to polling for the same MB (called in above callback with same mb index) */
(void)FlexCAN_SetMsgBuffIntCmd(pBase, u8Instance, u32MbIdx, FALSE, pState->isIntActive);
}
else
{
/* Prevent misra */
/* When processing type change from POLL->POLL or INTERRUPT -> INTERRUPT(this Mb is used continously in callback), no need to disable interrupt in the ISR */
}
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_IRQHandlerRxFIFO
* Description : Process IRQHandler in case of RxFIFO mode selection for CAN interface.
*
*END**************************************************************************/
static inline void FlexCAN_IRQHandlerRxFIFO(uint8 instance,
uint32 mb_idx)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
Flexcan_Ip_MsgBuffType data;
/* If use pass NULL_PTR, they can get data in callback function by getting state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage */
if (NULL_PTR == state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage)
{
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage = &data;
}
switch (mb_idx)
{
case CAN_LEGACY_RXFIFO_FRAME_AVAILABLE:
if (state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state == FLEXCAN_MB_RX_BUSY)
{
/* Get RX FIFO field values */
FlexCAN_ReadRxFifo(base, state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage);
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_IDLE;
/* Invoke callback */
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_RXFIFO_COMPLETE, FLEXCAN_MB_HANDLE_RXFIFO, state);
}
if (state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state == FLEXCAN_MB_IDLE)
{
/* reset to default value */
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].isPolling = (boolean)TRUE;
/* Complete receive data */
FlexCAN_CompleteRxMessageFifoData(instance);
}
}
break;
case CAN_LEGACY_RXFIFO_WARNING:
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
/* Invoke callback */
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_RXFIFO_WARNING, FLEXCAN_MB_HANDLE_RXFIFO, state);
}
break;
case CAN_LEGACY_RXFIFO_OVERFLOW:
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
/* Invoke callback */
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_RXFIFO_OVERFLOW, FLEXCAN_MB_HANDLE_RXFIFO, state);
}
break;
default:
/* Do Nothing */
break;
}
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_ProcessSpuriousInterruptMB
* Description : clear Iflag when spurious interrupt occurred.
* note: just use in FlexCAN_IRQHandler
*END**************************************************************************/
static inline void FlexCAN_ProcessSpuriousInterruptMB(uint8 instance, uint32 startMbIdx, uint32 endMbIdx)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
uint32 mb_idx = 0U;
uint32 u32MbHandle = 0U;
/* Process spurious interrupt */
for (mb_idx = startMbIdx; mb_idx <= endMbIdx; mb_idx++)
{
if (((uint8)0U != FlexCAN_GetBuffStatusFlag(base, mb_idx)) && ((uint8)0U == FlexCAN_GetBuffStatusImask(base, mb_idx)))
{
u32MbHandle = mb_idx;
if (((boolean)TRUE == state->bIsLegacyFifoEn) && (mb_idx <= CAN_LEGACY_RXFIFO_OVERFLOW))
{
u32MbHandle = (uint32)FLEXCAN_MB_HANDLE_RXFIFO;
}
if (((boolean)FALSE == state->mbs[u32MbHandle].isPolling))
{
/* clear the MB flag */
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
if (FLEXCAN_MB_TX_BUSY == state->mbs[u32MbHandle].state)
{
/* reset to default state */
state->mbs[u32MbHandle].state = FLEXCAN_MB_IDLE;
state->mbs[u32MbHandle].isPolling = (boolean)TRUE;
}
}
}
}
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_ProcessIRQHandlerEnhancedRxFIFO
* Description : Process IRQHandler in case of Enhanced RxFIFO mode selection for CAN interface.
* note: just use in FlexCAN_IRQHandler
*END**************************************************************************/
static inline boolean FlexCAN_ProcessIRQHandlerEnhancedRxFIFO(uint8 u8Instance, boolean bIsSpuriousIntPrevious)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[u8Instance];
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[u8Instance];
uint32 u32intType = 0U;
boolean bIsSpuriousInt = bIsSpuriousIntPrevious;
/* Get the interrupts that are enabled and ready */
for (u32intType = CAN_ENHANCED_RXFIFO_UNDERFLOW; u32intType >= CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE; u32intType--)
{
if ((uint8)0U != FlexCAN_GetEnhancedRxFIFOStatusFlag(base, u32intType))
{
if ((uint8)0U != FlexCAN_GetEnhancedRxFIFOIntStatusFlag(base, u32intType))
{
FlexCAN_IRQHandlerEnhancedRxFIFO(u8Instance, u32intType);
bIsSpuriousInt = (boolean)FALSE;
}
/* just process spurious interrupt when no real interrupt at all */
else if (((boolean)TRUE == bIsSpuriousInt) && ((boolean)FALSE == state->enhancedFifoOutput.isPolling))
{
/* Process spurious interrupt */
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, u32intType);
}
else
{
/* prevent misra */
}
}
}
return bIsSpuriousInt;
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_IRQHandlerEnhancedRxFIFO
* Description : Process IRQHandler in case of Enhanced RxFIFO mode selection for CAN interface.
*
* Implements : FLEXCAN_IRQHandlerEnyhancedRxFIFO_Activity
*END**************************************************************************/
static void FlexCAN_IRQHandlerEnhancedRxFIFO(uint8 instance,
uint32 intType)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
Flexcan_Ip_MsgBuffType data;
switch (intType)
{
case CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE:
if (state->enhancedFifoOutput.state == FLEXCAN_MB_RX_BUSY)
{
/* If use pass NULL_PTR, they can get data in callback function by getting state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage */
if (NULL_PTR == state->enhancedFifoOutput.pMBmessage)
{
state->enhancedFifoOutput.pMBmessage = &data;
}
/* Get Enhanced RX FIFO field values */
FlexCAN_ReadEnhancedRxFifo(base, state->enhancedFifoOutput.pMBmessage);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, intType);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_WATERMARK);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_OVERFLOW);
state->enhancedFifoOutput.state = FLEXCAN_MB_IDLE;
/* Invoke callback */
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_ENHANCED_RXFIFO_COMPLETE, FLEXCAN_MB_ENHANCED_RXFIFO, state);
}
if (state->enhancedFifoOutput.state == FLEXCAN_MB_IDLE)
{
/* Complete receive data */
FlexCAN_CompleteRxMessageEnhancedFifoData(instance);
}
}
break;
case CAN_ENHANCED_RXFIFO_WATERMARK:
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, intType);
/* Invoke callback */
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_ENHANCED_RXFIFO_WATERMARK, FLEXCAN_MB_ENHANCED_RXFIFO, state);
}
break;
case CAN_ENHANCED_RXFIFO_OVERFLOW:
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, intType);
/* Invoke callback */
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_ENHANCED_RXFIFO_OVERFLOW, FLEXCAN_MB_ENHANCED_RXFIFO, state);
}
break;
case CAN_ENHANCED_RXFIFO_UNDERFLOW:
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, intType);
/* Invoke callback */
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_ENHANCED_RXFIFO_UNDERFLOW, FLEXCAN_MB_ENHANCED_RXFIFO, state);
}
break;
default:
/* Do Nothing */
break;
}
}
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
static void DMA_Can_Callback(uint8 instance)
{
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
if (TRUE == FlexCAN_IsEnhancedRxFifoAvailable(base))
{
if (TRUE == FlexCAN_IsEnhancedRxFifoEnabled(base))
{
/* Need to add handler for Enhaced RxFifoDataDMA */
FlexCAN_CompleteRxMessageEnhancedFifoData(instance);
}
else
{
FlexCAN_CompleteRxMessageFifoData(instance);
}
}
else
#endif
{
FlexCAN_CompleteRxMessageFifoData(instance);
}
}
#endif
#if (STD_ON == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE)
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_SetUserAccessAllowed
* Description : Sets the UAA bit in REG_PROT to make the instance accessible
* in user mode.
*
* This is not a public API as it is called from other driver functions.
*END**************************************************************************/
static void FlexCAN_SetUserAccessAllowed(const FLEXCAN_Type * pBase)
{
SET_USER_ACCESS_ALLOWED((uint32)pBase, FLEXCAN_PROT_MEM_U32);
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_ClrUserAccessAllowed
* Description : Clears the UAA bit in REG_PROT to make the instance accessible
* in user mode.
*
* This is not a public API as it is called from other driver functions.
*END**************************************************************************/
static void FlexCAN_ClrUserAccessAllowed(const FLEXCAN_Type * pBase)
{
CLR_USER_ACCESS_ALLOWED((uint32)pBase, FLEXCAN_PROT_MEM_U32);
}
#endif /* (STD_ON == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE) */
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_AbortTxTransfer
* Description : Abort transfer for Tx buffer.
*
* This is not a public API as it is called from other driver functions.
*END**************************************************************************/
static Flexcan_Ip_StatusType FlexCAN_AbortTxTransfer(uint8 u8Instance, uint8 mb_idx)
{
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[u8Instance];
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
uint32 timeStart = 0U;
uint32 timeElapsed = 0U;
uint32 flexcan_mb_config = 0;
uint32 uS2Ticks = 0U;
volatile uint32 * flexcan_mb = NULL_PTR;
flexcan_mb = FlexCAN_GetMsgBuffRegion(pBase, mb_idx);
flexcan_mb_config = * flexcan_mb;
/* Reset the code */
flexcan_mb_config &= (~CAN_CS_CODE_MASK);
flexcan_mb_config |= (uint32)(((uint32)FLEXCAN_TX_ABORT & (uint32)0x1F) << (uint8)CAN_CS_CODE_SHIFT) & (uint32)CAN_CS_CODE_MASK;
*flexcan_mb = flexcan_mb_config;
/* Wait to finish abort operation */
uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
while (FlexCAN_GetBuffStatusFlag(pBase, mb_idx) == 0U)
{
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
if (timeElapsed >= uS2Ticks)
{
result = FLEXCAN_STATUS_TIMEOUT;
break;
}
}
if (result != FLEXCAN_STATUS_TIMEOUT)
{
flexcan_mb_config = *flexcan_mb;
/* Check if the MBs have been safely Inactivated */
if (((flexcan_mb_config & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT) == (uint32)FLEXCAN_TX_INACTIVE)
{
/* Transmission have occurred */
result = FLEXCAN_STATUS_NO_TRANSFER_IN_PROGRESS;
}
if (((flexcan_mb_config & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT) == (uint32)FLEXCAN_TX_ABORT)
{
/* Transmission have been aborted */
result = FLEXCAN_STATUS_SUCCESS;
}
}
/* Clear message buffer flag */
FlexCAN_ClearMsgBuffIntStatusFlag(pBase, mb_idx);
state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_AbortRxTransfer
* Description : Abort transfer for Rx normal or legacy fifo if enabled.
*
* This is not a public API as it is called from other driver functions.
*END**************************************************************************/
static void FlexCAN_AbortRxTransfer(uint8 u8Instance,
uint8 mb_idx)
{
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[u8Instance];
uint32 val1 = 0U;
uint32 val2 = 0U;
uint32 flexcan_mb_config = 0;
volatile uint32 * flexcan_mb = NULL_PTR;
state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
/* Check if fifo enabled */
if ((boolean)TRUE == state->bIsLegacyFifoEn)
{
/* Get the number of RX FIFO Filters*/
val1 = (((pBase->CTRL2) & FLEXCAN_CTRL2_RFFN_MASK) >> FLEXCAN_CTRL2_RFFN_SHIFT);
/* Get the number if MBs occupied by RX FIFO and ID filter table*/
/* the Rx FIFO occupies the memory space originally reserved for MB0-5*/
/* Every number of RFFN means 8 number of RX FIFO filters*/
/* and every 4 number of RX FIFO filters occupied one MB*/
val2 = RxFifoOcuppiedLastMsgBuff(val1);
if (mb_idx > val2)
{
/* This operation is not allowed for MB that are part of RxFIFO */
flexcan_mb = FlexCAN_GetMsgBuffRegion(pBase, mb_idx);
flexcan_mb_config = * flexcan_mb;
/* Reset the code and unlock the MB */
flexcan_mb_config &= (uint32)(~CAN_CS_CODE_MASK);
flexcan_mb_config |= (uint32)(((uint32)FLEXCAN_RX_INACTIVE & (uint32)0x1F) << (uint8)CAN_CS_CODE_SHIFT) & (uint32)CAN_CS_CODE_MASK;
*flexcan_mb = flexcan_mb_config;
/* Reconfigure The MB as left by RxMBconfig */
flexcan_mb_config &= (~CAN_CS_CODE_MASK);
flexcan_mb_config |= (uint32)(((uint32)FLEXCAN_RX_EMPTY & (uint32)0x1F) << (uint8)CAN_CS_CODE_SHIFT) & (uint32)CAN_CS_CODE_MASK;
*flexcan_mb = flexcan_mb_config;
}
if (FLEXCAN_MB_HANDLE_RXFIFO == mb_idx)
{
FLEXCAN_ClearMsgBuffIntCmd(pBase, u8Instance, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE, state->isIntActive);
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
if (state->transferType == FLEXCAN_RXFIFO_USING_DMA)
{
(void)Dma_Ip_SetLogicChannelCommand(state->rxFifoDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
}
#endif
}
}
else
{
/* This operation is not allowed for MB that are part of RxFIFO */
flexcan_mb = FlexCAN_GetMsgBuffRegion(pBase, mb_idx);
flexcan_mb_config = * flexcan_mb;
/* Reset the code and unlock the MB */
flexcan_mb_config &= (~CAN_CS_CODE_MASK);
flexcan_mb_config |= (uint32)(((uint32)FLEXCAN_RX_INACTIVE & (uint32)0x1F) << (uint8)CAN_CS_CODE_SHIFT) & (uint32)CAN_CS_CODE_MASK;
*flexcan_mb = flexcan_mb_config;
/* Reconfigure The MB as left by RxMBconfig */
flexcan_mb_config &= (~CAN_CS_CODE_MASK);
flexcan_mb_config |= (uint32)(((uint32)FLEXCAN_RX_EMPTY & (uint32)0x1F) << (uint8)CAN_CS_CODE_SHIFT) & (uint32)CAN_CS_CODE_MASK;
*flexcan_mb = flexcan_mb_config;
}
/* Clear message buffer flag */
FlexCAN_ClearMsgBuffIntStatusFlag(pBase, mb_idx);
}
/*==================================================================================================
* GLOBAL FUNCTIONS
==================================================================================================*/
/* implements FlexCAN_Ip_Init_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_Init_Privileged(uint8 Flexcan_Ip_u8Instance,
Flexcan_Ip_StateType * Flexcan_Ip_pState,
const Flexcan_Ip_ConfigType * Flexcan_Ip_pData)
{
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[Flexcan_Ip_u8Instance];
uint32 i;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(Flexcan_Ip_u8Instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(Flexcan_Ip_pData != NULL_PTR);
#endif
#if (STD_ON == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE)
/* Set the UAA bit in REG_PROT to make the instance accessible in user mode */
if (Flexcan_Ip_u8Instance < FLEXCAN_CTRL_REG_PROT_SUPPORT_U8)
{
OsIf_Trusted_Call1param(FlexCAN_SetUserAccessAllowed, pBase);
}
#endif
eResult = FlexCAN_InitController(pBase, Flexcan_Ip_pData);
if (FLEXCAN_STATUS_SUCCESS == eResult)
{
/* Enable the use of extended bit time definitions */
FlexCAN_EnableExtCbt(pBase, Flexcan_Ip_pData->fd_enable);
if(Flexcan_Ip_pData->enhCbtEnable)
{
/* Start critical section: implementation depends on integrator */
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_00();
/* Enable Enhanced CBT time segments */
pBase->CTRL2 |= FLEXCAN_CTRL2_BTE_MASK;
FlexCAN_SetEnhancedNominalTimeSegments(pBase, &Flexcan_Ip_pData->bitrate);
#if (FEATURE_CAN_HAS_FD == STD_ON)
if (Flexcan_Ip_pData->fd_enable)
{
FlexCAN_SetEnhancedDataTimeSegments(pBase, &Flexcan_Ip_pData->bitrate_cbt);
}
#endif
/* End critical section: implementation depends on integrator */
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_00();
}
else
{
/* Start critical section: implementation depends on integrator */
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_00();
/* Disable Enhanced CBT time segments */
pBase->CTRL2 &= ~FLEXCAN_CTRL2_BTE_MASK;
#if (FEATURE_CAN_HAS_FD == STD_ON)
/* Set bit rate. */
if (Flexcan_Ip_pData->fd_enable)
{
/* Write Normal bit time configuration to CBT register */
FlexCAN_SetExtendedTimeSegments(pBase, &Flexcan_Ip_pData->bitrate);
/* Write Data bit time configuration to FDCBT register */
FlexCAN_SetFDTimeSegments(pBase, &Flexcan_Ip_pData->bitrate_cbt);
}
else
{
/* Write Normal bit time configuration to CTRL1 register */
FlexCAN_SetTimeSegments(pBase, &Flexcan_Ip_pData->bitrate);
}
#endif
/* End critical section: implementation depends on integrator */
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_00();
}
/* Select mode */
FlexCAN_SetOperationMode(pBase, Flexcan_Ip_pData->flexcanMode);
#if (STD_ON == FLEXCAN_ENABLE_USER_MODE_SUPPORT)
#if (STD_ON == FEATURE_CAN_HAS_SUPV)
pBase->MCR = (pBase->MCR & ~FLEXCAN_MCR_SUPV_MASK) | FLEXCAN_MCR_SUPV(0U);
#endif
#endif
/* Leave driver in FreezMode if successfully initialized */
eResult = FlexCAN_EnterFreezeMode(pBase);
if (FLEXCAN_STATUS_SUCCESS == eResult)
{
#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
FlexCAN_ConfigTimestamp(pBase, (Flexcan_Ip_TimeStampConfigType *)&Flexcan_Ip_pData->time_stamp);
#endif /* (FEATURE_CAN_HAS_HR_TIMER == STD_ON) */
for (i = 0; i < (uint8)FEATURE_CAN_MAX_MB_NUM; i++)
{
/* Check if blocking need to be any more present in sync\async discussions */
/* Sync up isPolling status with hw (Imask), at the begining all Imask = 0 => isPolling = TRUE */
Flexcan_Ip_pState->mbs[i].isPolling = (boolean)TRUE;
Flexcan_Ip_pState->mbs[i].pMBmessage = NULL_PTR;
Flexcan_Ip_pState->mbs[i].state = FLEXCAN_MB_IDLE;
Flexcan_Ip_pState->mbs[i].time_stamp = 0U;
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
/* Sync up isPolling status with hw (Imask), at the begining all Imask = 0 => isPolling = TRUE */
Flexcan_Ip_pState->enhancedFifoOutput.isPolling = (boolean)TRUE;
Flexcan_Ip_pState->enhancedFifoOutput.state = FLEXCAN_MB_IDLE;
#endif
Flexcan_Ip_pState->transferType = Flexcan_Ip_pData->transfer_type;
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
Flexcan_Ip_pState->rxFifoDMAChannel = Flexcan_Ip_pData->rxFifoDMAChannel;
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
Flexcan_Ip_pState->u32NumOfMbTransferByDMA = Flexcan_Ip_pData->num_enhanced_watermark;
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
#endif
/* Clear Callbacks in case of autovariables garbage */
Flexcan_Ip_pState->callback = Flexcan_Ip_pData->Callback;
Flexcan_Ip_pState->callbackParam = NULL_PTR;
Flexcan_Ip_pState->error_callback = Flexcan_Ip_pData->ErrorCallback;
Flexcan_Ip_pState->errorCallbackParam = NULL_PTR;
Flexcan_Ip_pState->bIsLegacyFifoEn = Flexcan_Ip_pData->is_rx_fifo_needed;
Flexcan_Ip_pState->u32MaxMbNum = Flexcan_Ip_pData->max_num_mb;
Flexcan_Ip_pState->isIntActive = TRUE;
/* Save runtime structure pointers so irq handler can point to the correct state structure */
g_flexcan_Ip_StatePtr[Flexcan_Ip_u8Instance] = Flexcan_Ip_pState;
}
}
return eResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_DRV_Send
* Description : This function sends a CAN frame using a configured message
* buffer. The function returns immediately. If a callback is installed, it will
* be invoked after the frame was sent.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_Send_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_Send(uint8 instance,
uint8 mb_idx,
const Flexcan_Ip_DataInfoType * tx_info,
uint32 msg_id,
const uint8 * mb_data)
{
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_ERROR;
#if (CAN_MB_INTERRUPT_SUPPORT == STD_ON)
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
#else
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#endif
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(tx_info != NULL_PTR);
#endif
if(!FlexCAN_IsListenOnlyModeEnabled(base))
{
result = FlexCAN_StartSendData(instance, mb_idx, tx_info, msg_id, mb_data);
#if (CAN_MB_INTERRUPT_SUPPORT == STD_ON)
if ((FLEXCAN_STATUS_SUCCESS == result) && (FALSE == tx_info->is_polling))
{
/* Enable message buffer interrupt*/
result = FlexCAN_SetMsgBuffIntCmd(base, instance, mb_idx, TRUE, state->isIntActive);
}
#endif
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ConfigMb
* Description : Configure a Rx message buffer.
* This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
* the function will make sure if the MB requested is not occupied by RX FIFO
* and ID filter table. Then this function will set up the message buffer fields,
* configure the message buffer code for Rx message buffer as NOT_USED, enable
* the Message Buffer interrupt, configure the message buffer code for Rx
* message buffer as INACTIVE, copy user's buffer into the message buffer data
* area, and configure the message buffer code for Rx message buffer as EMPTY.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_ConfigRxMb_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_ConfigRxMb(uint8 instance,
uint8 mb_idx,
const Flexcan_Ip_DataInfoType * rx_info,
uint32 msg_id)
{
Flexcan_Ip_StatusType eResult = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_MsbuffCodeStatusType cs;
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(rx_info != NULL_PTR);
if ((boolean)TRUE == FlexCAN_IsMbOutOfRange(base, mb_idx, state->bIsLegacyFifoEn, state->u32MaxMbNum))
{
eResult = FLEXCAN_STATUS_BUFF_OUT_OF_RANGE;
}
else
{
#endif
/* Clear the message buffer flag if previous remained triggered */
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
cs.dataLen = rx_info->data_length;
cs.msgIdType = rx_info->msg_id_type;
#if (FEATURE_CAN_HAS_FD == STD_ON)
cs.fd_enable = rx_info->fd_enable;
#endif
/* Initialize rx mb*/
cs.code = (uint32)FLEXCAN_RX_NOT_USED;
FlexCAN_SetRxMsgBuff(base, mb_idx, &cs, msg_id);
/* Initialize receive MB*/
cs.code = (uint32)FLEXCAN_RX_INACTIVE;
FlexCAN_SetRxMsgBuff(base, mb_idx, &cs, msg_id);
/* Set up FlexCAN message buffer fields for receiving data*/
cs.code = (uint32)FLEXCAN_RX_EMPTY;
FlexCAN_SetRxMsgBuff(base, mb_idx, &cs, msg_id);
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
}
#endif
return eResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_Receive
* Description : This function receives a CAN frame into a configured message
* buffer. The function returns immediately. If a callback is installed, it will
* be invoked after the frame was received and read into the specified buffer.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_Receive_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_Receive(uint8 instance,
uint8 mb_idx,
Flexcan_Ip_MsgBuffType * data,
boolean isPolling)
{
Flexcan_Ip_StatusType result;
#if (CAN_MB_INTERRUPT_SUPPORT == STD_ON)
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
#endif
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
result = FlexCAN_StartRxMessageBufferData(instance, mb_idx, data, isPolling);
#if (CAN_MB_INTERRUPT_SUPPORT == STD_ON)
if ((result == FLEXCAN_STATUS_SUCCESS) && (FALSE == isPolling))
{
/* Enable MB interrupt*/
result = FlexCAN_SetMsgBuffIntCmd(base, instance, mb_idx, TRUE, state->isIntActive);
}
#endif
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ReceiveBlocking
* Description : This function receives a CAN frame into a configured message
* buffer. The function blocks until either a frame was received, or the
* specified timeout expired.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_ReceiveBlocking_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_ReceiveBlocking(uint8 instance,
uint8 mb_idx,
Flexcan_Ip_MsgBuffType * data,
boolean isPolling,
uint32 u32TimeoutMs)
{
Flexcan_Ip_StatusType result;
uint32 timeStart = 0U;
uint32 timeElapsed = 0U;
uint32 mS2Ticks = OsIf_MicrosToTicks((u32TimeoutMs * 1000U), CAN_SERVICE_TIMEOUT_TYPE);
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
#if (CAN_MB_INTERRUPT_SUPPORT == STD_ON)
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#else
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#endif
result = FlexCAN_StartRxMessageBufferData(instance, mb_idx, data, isPolling);
#if (CAN_MB_INTERRUPT_SUPPORT == STD_ON)
if ((result == FLEXCAN_STATUS_SUCCESS) && (FALSE == isPolling))
{
/* Enable MB interrupt*/
result = FlexCAN_SetMsgBuffIntCmd(base, instance, mb_idx, TRUE, state->isIntActive);
}
#endif
if (FLEXCAN_STATUS_SUCCESS == result)
{
timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
while (FLEXCAN_MB_RX_BUSY == state->mbs[mb_idx].state)
{
if (TRUE == isPolling)
{
if (FlexCAN_GetBuffStatusFlag(base, mb_idx) != 0U)
{
FlexCAN_IRQHandlerRxMB(instance, mb_idx);
}
}
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
if (timeElapsed >= mS2Ticks)
{
result = FLEXCAN_STATUS_TIMEOUT;
break;
}
}
}
if ((FLEXCAN_STATUS_TIMEOUT == result) && (FALSE == isPolling))
{
#if (CAN_MB_INTERRUPT_SUPPORT == STD_ON)
/* Disable Mb interrupt*/
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, mb_idx, (boolean)FALSE, state->isIntActive);
#endif
}
if ((FLEXCAN_STATUS_BUFF_OUT_OF_RANGE != result) && (FLEXCAN_STATUS_BUSY != result))
{
if ((FLEXCAN_MB_IDLE == state->mbs[mb_idx].state))
{
result = FLEXCAN_STATUS_SUCCESS;
}
else
{
state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
result = FLEXCAN_STATUS_TIMEOUT;
}
}
return result;
}
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
void DMA_Can_Callback0(void)
{ DMA_Can_Callback(0U); }
#if FLEXCAN_INSTANCE_COUNT > 1U
void DMA_Can_Callback1(void)
{ DMA_Can_Callback(1U); }
#endif
#if FLEXCAN_INSTANCE_COUNT > 2U
void DMA_Can_Callback2(void)
{ DMA_Can_Callback(2U); }
#endif
#if FLEXCAN_INSTANCE_COUNT > 3U
void DMA_Can_Callback3(void)
{ DMA_Can_Callback(3U); }
#endif
#if FLEXCAN_INSTANCE_COUNT > 4U
void DMA_Can_Callback4(void)
{ DMA_Can_Callback(4U); }
#endif
#if FLEXCAN_INSTANCE_COUNT > 5U
void DMA_Can_Callback5(void)
{ DMA_Can_Callback(5U); }
#endif
#if FLEXCAN_INSTANCE_COUNT > 6U
void DMA_Can_Callback6(void)
{ DMA_Can_Callback(6U); }
#endif
#endif /* FEATURE_CAN_HAS_DMA_ENABLE */
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_RxFifo
* Description : This function receives a CAN frame using the Rx FIFO or
* Enhanced Rx FIFO (if available and enabled). If use Enhanced Rx FIFO, the size of
* the data array will be considered the same as the configured FIFO watermark.
* The function returns immediately. If a callback is installed, it will be invoked
* after the frame was received and read into the specified buffer.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_RxFifo_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_RxFifo(uint8 instance,
Flexcan_Ip_MsgBuffType * data)
{
#ifdef MCAL_ENABLE_FAULT_INJECTION
/* Fault injection point to test dma error event */
MCAL_FAULT_INJECTION_POINT(CAN_FIP_0_DMA_ERROR_EVENT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
if (TRUE == FlexCAN_IsEnhancedRxFifoAvailable(base))
{
if (TRUE == FlexCAN_IsEnhancedRxFifoEnabled(base))
{
result = FlexCAN_StartRxMessageEnhancedFifoData(instance, data);
}
else
{
result = FlexCAN_StartRxMessageFifoData(instance, data);
}
}
else
#endif /*FEATURE_CAN_HAS_ENHANCED_RX_FIFO*/
{
result = FlexCAN_StartRxMessageFifoData(instance, data);
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_RxFifoBlocking
* Description : This function receives a CAN frame using the Rx FIFO or
* Enhanced Rx FIFO (if available and enabled). If use Enhanced Rx FIFO, the size of
* the data array will be considered the same as the configured FIFO watermark.
* The function blocks until either a frame was received, or the specified timeout expired.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_RxFifoBlocking_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_RxFifoBlocking(uint8 instance, Flexcan_Ip_MsgBuffType *data, uint32 timeout)
{
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
if (TRUE == FlexCAN_IsEnhancedRxFifoAvailable(base))
{
if (TRUE == FlexCAN_IsEnhancedRxFifoEnabled(base))
{
result = FlexCAN_StartRxMessageEnhancedFifoData(instance, data);
if (FLEXCAN_STATUS_SUCCESS == result)
{
result = FlexCAN_ProccessEnhancedRxFifo(instance, timeout);
}
}
else
{
result = FlexCAN_StartRxMessageFifoData(instance, data);
if (FLEXCAN_STATUS_SUCCESS == result)
{
result = FlexCAN_ProccessLegacyRxFIFO(instance, timeout);
}
}
}
else
#endif /*FEATURE_CAN_HAS_ENHANCED_RX_FIFO*/
{
result = FlexCAN_StartRxMessageFifoData(instance, data);
if (FLEXCAN_STATUS_SUCCESS == result)
{
result = FlexCAN_ProccessLegacyRxFIFO(instance, timeout);
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ConfigRxFifo
* Description : Confgure RX FIFO ID filter table elements.
* This function will confgure RX FIFO ID filter table elements, and enable RX
* FIFO interrupts.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_ConfigRxFifo_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_ConfigRxFifo_Privileged(uint8 instance,
Flexcan_Ip_RxFifoIdElementFormatType id_format,
const Flexcan_Ip_IdTableType * id_filter_table)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
/* Initialize rx fifo*/
FlexCAN_SetRxFifoFilter(pBase, id_format, id_filter_table);
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ConfigEnhancedRxFifo
* Description : Confgure Enhanced RX FIFO ID filter table elements.
* This function will confgure Enhanced RX FIFO ID filter table elements, and enable Enhanced RX
* FIFO interrupts.
*END**************************************************************************/
/* implements FlexCAN_Ip_ConfigEnhancedRxFifo_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_ConfigEnhancedRxFifo_Privileged(uint8 instance,
const Flexcan_Ip_EnhancedIdTableType * id_filter_table)
{
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(FlexCAN_IsEnhancedRxFifoAvailable(pBase));
DevAssert(id_filter_table != NULL_PTR);
#endif
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
/* Initialize rx fifo*/
FlexCAN_SetEnhancedRxFifoFilter(pBase, id_filter_table);
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
#endif /* (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) */
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ConfigRemoteResponseMb
* Description : Configures a transmit message buffer for remote frame
* response. This function will first check if RX FIFO is enabled. If RX FIFO is
* enabled, the function will make sure if the MB requested is not occupied by
* the RX FIFO and ID filter table. Then this function will set up the message
* buffer fields, configure the message buffer code for Tx buffer as RX_RANSWER,
* and enable the Message Buffer interrupt if required by user.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_ConfigRemoteResponseMb_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_ConfigRemoteResponseMb(uint8 instance,
uint8 mb_idx,
const Flexcan_Ip_DataInfoType *tx_info,
uint32 msg_id,
const uint8 *mb_data)
{
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_MsbuffCodeStatusType cs;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
const Flexcan_Ip_StateType * const state = g_flexcan_Ip_StatePtr[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(tx_info != NULL_PTR);
if ((boolean)TRUE == FlexCAN_IsMbOutOfRange(pBase, mb_idx, state->bIsLegacyFifoEn, state->u32MaxMbNum))
{
result = FLEXCAN_STATUS_BUFF_OUT_OF_RANGE;
}
#endif
if (FLEXCAN_STATUS_SUCCESS == result)
{
/* Initialize transmit mb*/
cs.dataLen = tx_info->data_length;
cs.msgIdType = tx_info->msg_id_type;
cs.code = (uint32)FLEXCAN_RX_RANSWER;
#if (FEATURE_CAN_HAS_FD == STD_ON)
cs.fd_enable = (boolean)FALSE;
#endif
FlexCAN_ClearMsgBuffIntStatusFlag(pBase, mb_idx);
FlexCAN_SetTxMsgBuff(pBase, mb_idx, &cs, msg_id, mb_data, tx_info->is_remote);
if (tx_info->is_polling == FALSE)
{
/* Enable MB interrupt*/
result = FlexCAN_SetMsgBuffIntCmd(pBase, instance, mb_idx, TRUE, state->isIntActive);
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetTransferStatus
* Description : This function returns whether the previous FLEXCAN receive is
* completed.
* When performing a non-blocking receive, the user can call this function to
* ascertain the state of the current receive progress: in progress (or busy)
* or complete (success). In case Enhanced Rx Fifo, mb_idx will be 255.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetTransferStatus_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_GetTransferStatus(uint8 instance,
uint8 mb_idx)
{
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_ERROR;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert((mb_idx < (uint8)FEATURE_CAN_MAX_MB_NUM) || (mb_idx == 255u));
#endif
if (mb_idx < (uint8)FEATURE_CAN_MAX_MB_NUM)
{
if (state->mbs[mb_idx].state == FLEXCAN_MB_IDLE)
{
status = FLEXCAN_STATUS_SUCCESS;
}
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
else if (state->mbs[mb_idx].state == FLEXCAN_MB_DMA_ERROR)
{
status = FLEXCAN_STATUS_ERROR;
}
#endif
else
{
status = FLEXCAN_STATUS_BUSY;
}
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
else
{
if (state->enhancedFifoOutput.state == FLEXCAN_MB_IDLE)
{
status = FLEXCAN_STATUS_SUCCESS;
}
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
else if (state->enhancedFifoOutput.state == FLEXCAN_MB_DMA_ERROR)
{
status = FLEXCAN_STATUS_ERROR;
}
#endif
else
{
status = FLEXCAN_STATUS_BUSY;
}
}
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
return status;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_CompleteRxMessageFifoData
* Description : Finish up a receive by completing the process of receiving
* data and disabling the interrupt.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static void FlexCAN_CompleteRxMessageFifoData(uint8 instance)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
if (state->transferType == FLEXCAN_RXFIFO_USING_INTERRUPTS)
{
/* Disable RX FIFO interrupts*/
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE, FALSE, state->isIntActive);
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, CAN_LEGACY_RXFIFO_WARNING, FALSE, state->isIntActive);
(void)FlexCAN_SetMsgBuffIntCmd(base, instance, CAN_LEGACY_RXFIFO_OVERFLOW, FALSE, state->isIntActive);
}
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
else if (state->transferType == FLEXCAN_RXFIFO_USING_DMA)
{
Dma_Ip_LogicChannelStatusType dmaStatus;
Dma_Ip_GetLogicChannelStatus(state->rxFifoDMAChannel, &dmaStatus);
if (dmaStatus.ChStateValue == DMA_IP_CH_ERROR_STATE)
{
(void)Dma_Ip_SetLogicChannelCommand(state->rxFifoDMAChannel, DMA_IP_CH_CLEAR_ERROR);
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_DMA_ERROR;
}
(void)Dma_Ip_SetLogicChannelCommand(state->rxFifoDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
if (state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state != FLEXCAN_MB_DMA_ERROR)
{
Flexcan_Ip_MsgBuffType * fifo_message = state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage;
uint32 * msgData_32 = (uint32 *)fifo_message->data;
/* Adjust the ID if it is not extended */
if (((fifo_message->cs) & CAN_CS_IDE_MASK) == 0U)
{
fifo_message->msgId = fifo_message->msgId >> CAN_ID_STD_SHIFT;
}
/* Extract the data length */
fifo_message->dataLen = (uint8)((fifo_message->cs & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
/* Extract the IDHIT */
fifo_message->id_hit = (uint8)((fifo_message->cs & CAN_CS_IDHIT_MASK) >> CAN_CS_IDHIT_SHIFT);
/* Extract the Time Stamp */
fifo_message->time_stamp = (uint32)((fifo_message->cs & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
/* Reverse the endianness */
FlexcanSwapBytesInWord(msgData_32[0], msgData_32[0]);
FlexcanSwapBytesInWord(msgData_32[1], msgData_32[1]);
}
}
else
{
/* do nothing when transferType is POLLING */
}
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
/* Clear fifo message*/
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].pMBmessage = NULL_PTR;
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
if (state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state != FLEXCAN_MB_DMA_ERROR)
{
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_IDLE;
if ((state->callback != NULL_PTR) && (state->transferType == FLEXCAN_RXFIFO_USING_DMA))
{
state->callback(instance, FLEXCAN_EVENT_DMA_COMPLETE, FLEXCAN_MB_HANDLE_RXFIFO, state);
}
}
else
{
if (state->callback != NULL_PTR)
{
state->callback(instance, FLEXCAN_EVENT_DMA_ERROR, FLEXCAN_MB_HANDLE_RXFIFO, state);
}
}
#else
state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].state = FLEXCAN_MB_IDLE;
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_IRQHandler
* Description : Interrupt handler for FLEXCAN.
* This handler read data from MB or FIFO, and then clear the interrupt flags.
* This is not a public API as it is called whenever an interrupt occurs.
* Spurious interrupt implementation:
* This handler will process only one Normal Buffers (tx or rx or legacy fifo)
* and Enhance FIFO(if supported). The processing of spurious interrupt will be
* done when there is no real interrupt(both IF and IE are set) at all.
* If a spurious interrupt found:
* - for Rx (Rx normal, Legacy FIFO, Enhanced FIFO): Just clear IF and exit,
* the Buffer is still ready to receive a new Frame.
* - for Tx: Clear IF and reset the Buffer to default state to ready to use in next time.
*END**************************************************************************/
/* implements CAN_X_MB_Y_ISR_Activity */
void FlexCAN_IRQHandler
(
uint8 instance,
uint32 startMbIdx,
uint32 endMbIdx
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
,boolean bEnhancedFifoExisted
#endif
)
{
uint32 u32MbHandle = 0U;
uint32 flag_reg = 0;
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
boolean bIsSpuriousInt = (boolean)TRUE;
/* Get the interrupts that are enabled and ready */
uint32 mb_idx = endMbIdx;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(endMbIdx < (uint8)FEATURE_CAN_MAX_MB_NUM);
#endif
/* Check if instance initialized */
if (NULL_PTR != state)
{
flag_reg = FlexCAN_GetMsgBuffIntStatusFlag(base, mb_idx);
while ((0U == flag_reg) && (mb_idx > startMbIdx))
{
mb_idx--;
flag_reg = FlexCAN_GetMsgBuffIntStatusFlag(base, mb_idx);
}
/* Check Tx/Rx interrupt flag and clear the interrupt */
if (flag_reg != 0U)
{
/* At least one real interrupt -> no process spurious interurpt */
bIsSpuriousInt = (boolean)FALSE;
/* For legacy fifo, mb handler is FLEXCAN_MB_HANDLE_RXFIFO(0) */
u32MbHandle = mb_idx;
if (((boolean)TRUE == state->bIsLegacyFifoEn) && (mb_idx <= CAN_LEGACY_RXFIFO_OVERFLOW))
{
FlexCAN_IRQHandlerRxFIFO(instance, mb_idx);
u32MbHandle = (uint32)FLEXCAN_MB_HANDLE_RXFIFO;
}
else
{
/* Check mailbox completed reception */
if (state->mbs[u32MbHandle].state == FLEXCAN_MB_RX_BUSY)
{
FlexCAN_IRQHandlerRxMB(instance, mb_idx);
}
}
/* Check mailbox completed transmission */
if (state->mbs[u32MbHandle].state == FLEXCAN_MB_TX_BUSY)
{
FlexCAN_IRQHandlerTxMB(instance, mb_idx);
}
/* Check for spurious interrupt */
if (FlexCAN_GetMsgBuffIntStatusFlag(base, mb_idx) != 0U)
{
if (state->mbs[u32MbHandle].state == FLEXCAN_MB_IDLE)
{
/* In case of desynchronized status of the MB to avoid trapping in ISR
* clear the MB flag */
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
}
}
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
if ((boolean)TRUE == bEnhancedFifoExisted)
{
if (((boolean)TRUE == FlexCAN_IsEnhancedRxFifoEnabled(base)) && (FLEXCAN_RXFIFO_USING_INTERRUPTS == state->transferType))
{
bIsSpuriousInt = FlexCAN_ProcessIRQHandlerEnhancedRxFIFO(instance, bIsSpuriousInt);
}
}
#endif /* End of (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) */
/* continue processing spurious interrupt for normal Mb only if enhance fifo interrupt is not existed on ISR or no enhance fifo interrupts occurred */
/* Expectation is that ISR just process one Object (Tx, Rx normal, Rx legacy fifo, Rx enhance fifo) when ISR triggered */
if ((boolean)TRUE == bIsSpuriousInt)
{
FlexCAN_ProcessSpuriousInterruptMB(instance, startMbIdx, endMbIdx);
}
}
else
{
/* Clear all interrupt flags when driver is not initialized */
/* Process spurious interrupt */
for (mb_idx = startMbIdx; mb_idx <= endMbIdx; mb_idx++)
{
/* clear the MB flag */
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
/* Check if Enhance fifo interrupt existed on the ISR! */
if ((boolean)TRUE == bEnhancedFifoExisted)
{
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_WATERMARK);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_OVERFLOW);
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_UNDERFLOW);
}
#endif /* End of (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) */
}
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ClearErrorStatus
* Description : Clears various error conditions detected in the reception and
* transmission of a CAN frame.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_ClearErrorStatus_Activity */
void FlexCAN_Ip_ClearErrorStatus(uint8 instance, uint32 error)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
base->ESR1 = error;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetErrorStatus
* Description : Reports various error conditions detected in the reception and
* transmission of a CAN frame and some general status of the device.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetErrorStatus_Activity */
uint32 FlexCAN_Ip_GetErrorStatus(uint8 instance)
{
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
return (uint32)(base->ESR1);
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetControllerTxErrorCounter
* Description : Reports Transmit error counter for all errors detected in
* transmitted messages.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetControllerTxErrorCounter_Activity */
uint8 FlexCAN_Ip_GetControllerTxErrorCounter(uint8 instance)
{
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
return (uint8)((base->ECR & FLEXCAN_ECR_TXERRCNT_MASK) >> FLEXCAN_ECR_TXERRCNT_SHIFT);
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetControllerRxErrorCounter
* Description : Reports Receive error counter for all errors detected in
* received messages.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetControllerRxErrorCounter_Activity */
uint8 FlexCAN_Ip_GetControllerRxErrorCounter(uint8 instance)
{
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
return (uint8)((base->ECR & FLEXCAN_ECR_RXERRCNT_MASK) >> FLEXCAN_ECR_RXERRCNT_SHIFT);
}
#if (FEATURE_CAN_BUSOFF_ERROR_INTERRUPT_UNIFIED == STD_ON)
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Busoff_Error_IRQHandler
* Description : BusOff and Error interrupt handler for FLEXCAN.
* This is not a public API as it is called whenever an interrupt occurs.
*
*END**************************************************************************/
/* implements CAN_X_BUSOFF_ERROR_ISR_Activity */
void FlexCAN_Busoff_Error_IRQHandler(uint8 instance)
{
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
uint32 u32ErrStatus = 0U;
boolean isSpuriousInt = (boolean)TRUE;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
/* Check if the instance initialized */
if (NULL_PTR != state)
{
/* Get error status to get value updated */
u32ErrStatus = pBase->ESR1;
/* Check spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_ERRINT_MASK))) && ((uint32)0U != (pBase->CTRL1 & ((uint32)FLEXCAN_CTRL1_ERRMSK_MASK))))
{
pBase->ESR1 = FLEXCAN_ESR1_ERRINT_MASK;
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_ERROR, u32ErrStatus, state);
/* Get error status to get value updated due to user may handle ESR1 register */
u32ErrStatus = pBase->ESR1;
}
isSpuriousInt = (boolean)FALSE;
}
#if (FEATURE_CAN_HAS_FD == STD_ON)
/* Check if this is spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_ERRINT_FAST_MASK))) && ((uint32)0U != (pBase->CTRL2 & ((uint32)FLEXCAN_CTRL2_ERRMSK_FAST_MASK))))
{
pBase->ESR1 = FLEXCAN_ESR1_ERRINT_FAST_MASK;
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_ERROR_FAST, u32ErrStatus, state);
/* Get error status to get value updated due to user may handle ESR1 register */
u32ErrStatus = pBase->ESR1;
}
isSpuriousInt = (boolean)FALSE;
}
#endif /* FEATURE_CAN_HAS_FD */
/* Check spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_TWRNINT_MASK))) && ((uint32)0U != (pBase->CTRL1 & ((uint32)FLEXCAN_CTRL1_TWRNMSK_MASK))))
{
pBase->ESR1 = FLEXCAN_ESR1_TWRNINT_MASK;
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_TX_WARNING, u32ErrStatus, state);
/* Get error status to get value updated due to user may handle ESR1 register */
u32ErrStatus = pBase->ESR1;
}
isSpuriousInt = (boolean)FALSE;
}
/* Check spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_RWRNINT_MASK))) && ((uint32)0U != (pBase->CTRL1 & ((uint32)FLEXCAN_CTRL1_RWRNMSK_MASK))))
{
pBase->ESR1 = FLEXCAN_ESR1_RWRNINT_MASK;
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_RX_WARNING, u32ErrStatus, state);
/* Get error status to get value updated due to user may handle ESR1 register */
u32ErrStatus = pBase->ESR1;
}
isSpuriousInt = (boolean)FALSE;
}
/* Check spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_BOFFINT_MASK))) && ((uint32)0U != (pBase->CTRL1 & ((uint32)FLEXCAN_CTRL1_BOFFMSK_MASK))))
{
pBase->ESR1 = FLEXCAN_ESR1_BOFFINT_MASK;
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_BUSOFF, u32ErrStatus, state);
}
isSpuriousInt = (boolean)FALSE;
}
}
if ((boolean)TRUE == isSpuriousInt)
{
pBase->ESR1 = FLEXCAN_ALL_INT;
}
}
#else /* (FEATURE_CAN_BUSOFF_ERROR_INTERRUPT_UNIFIED == STD_OFF) */
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_Error_IRQHandler
* Description : Error interrupt handler for FLEXCAN.
* This is not a public API as it is called whenever an interrupt occurs.
*
*END**************************************************************************/
/* implements CAN_X_ERROR_ISR_Activity */
void FlexCAN_Error_IRQHandler(uint8 instance)
{
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
uint32 u32ErrStatus = 0U;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
/* Check if the instance initialized */
if (NULL_PTR != state)
{
/* Get error status to get value updated */
u32ErrStatus = pBase->ESR1;
/* Check spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_ERRINT_MASK))) && ((uint32)0U != (pBase->CTRL1 & ((uint32)FLEXCAN_CTRL1_ERRMSK_MASK))))
{
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_ERROR, u32ErrStatus, state);
#if (FEATURE_CAN_HAS_FD == STD_ON)
/* Get error status to get value updated due to user may handle ESR1 register */
u32ErrStatus = pBase->ESR1;
#endif /* FEATURE_CAN_HAS_FD */
}
}
#if (FEATURE_CAN_HAS_FD == STD_ON)
/* Check if this is spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_ERRINT_FAST_MASK))) && ((uint32)0U != (pBase->CTRL2 & ((uint32)FLEXCAN_CTRL2_ERRMSK_FAST_MASK))))
{
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_ERROR_FAST, u32ErrStatus, state);
}
}
#endif /* FEATURE_CAN_HAS_FD */
}
/* Clear all other interrupts in ESR1 register (Error, Wakeup) */
FlexCAN_ClearErrIntStatusFlag(pBase);
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_BusOff_IRQHandler
* Description : BusOff and Tx/Rx Warning interrupt handler for FLEXCAN.
* This handler only provides a error status report and invokes the user callback,
* and then clears the interrupt flags.
* This is not a public API as it is called whenever an interrupt occurs.
*
*END**************************************************************************/
/* implements CAN_X_BUSOFF_ISR_Activity */
void FlexCAN_BusOff_IRQHandler(uint8 instance)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
uint32 u32ErrStatus = 0U;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
/* Check If Driver initialized */
if (NULL_PTR != state)
{
/* Get error status to get value updated */
u32ErrStatus = base->ESR1;
/* Check spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_TWRNINT_MASK))) && (0U != (base->CTRL1 & ((uint32)FLEXCAN_CTRL1_TWRNMSK_MASK))))
{
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_TX_WARNING, u32ErrStatus, state);
/* Get error status to get value updated due to user may handle ESR1 register */
u32ErrStatus = base->ESR1;
}
}
/* Check spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_RWRNINT_MASK))) && (0U != (base->CTRL1 & ((uint32)FLEXCAN_CTRL1_RWRNMSK_MASK))))
{
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_RX_WARNING, u32ErrStatus, state);
/* Get error status to get value updated due to user may handle ESR1 register */
u32ErrStatus = base->ESR1;
}
}
/* Check spurious interrupt */
if (((uint32)0U != (u32ErrStatus & ((uint32)FLEXCAN_ESR1_BOFFINT_MASK))) && ((uint32)0U != (base->CTRL1 & ((uint32)FLEXCAN_CTRL1_BOFFMSK_MASK))))
{
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_BUSOFF, u32ErrStatus, state);
}
}
}
/* Clear all BusOff and Tx/Rx Warning interrupts in ESR1 register */
FlexCAN_ClearBusOffIntStatusFlag(base);
}
#endif /* (FEATURE_CAN_BUSOFF_ERROR_INTERRUPT_UNIFIED) */
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SendBlocking
* Description : This function sends a CAN frame using a configured message
* buffer. The function blocks until either the frame was sent, or the specified
* timeout expired.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SendBlocking_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SendBlocking(uint8 instance,
uint8 mb_idx,
const Flexcan_Ip_DataInfoType * tx_info,
uint32 msg_id,
const uint8 * mb_data,
uint32 timeout_ms)
{
Flexcan_Ip_StatusType result;
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
uint32 timeElapsed = 0U;
uint32 mS2Ticks = OsIf_MicrosToTicks((timeout_ms * 1000U), CAN_SERVICE_TIMEOUT_TYPE);
uint32 uS2Ticks = 0U;
uint32 flexcan_mb_config = 0;
volatile uint32 * flexcan_mb = NULL_PTR;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(tx_info != NULL_PTR);
#endif
result = FlexCAN_StartSendData(instance, mb_idx, tx_info, msg_id, mb_data);
if (result == FLEXCAN_STATUS_SUCCESS)
{
while(FlexCAN_GetBuffStatusFlag(base, mb_idx) != 1U)
{
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
if (timeElapsed >= mS2Ticks)
{
result = FLEXCAN_STATUS_TIMEOUT;
break;
}
}
if ((result == FLEXCAN_STATUS_TIMEOUT) && (state->mbs[mb_idx].state != FLEXCAN_MB_IDLE))
{
/* Clear message buffer flag */
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
flexcan_mb = FlexCAN_GetMsgBuffRegion(base, mb_idx);
flexcan_mb_config = * flexcan_mb;
/* Reset the code */
flexcan_mb_config &= (uint32)(~CAN_CS_CODE_MASK);
flexcan_mb_config |= ((uint32)(((uint32)FLEXCAN_TX_ABORT & (uint32)0x1F) << (uint8)CAN_CS_CODE_SHIFT) & (uint32)CAN_CS_CODE_MASK);
*flexcan_mb = flexcan_mb_config;
/* Wait to finish abort operation */
uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
timeElapsed = 0U;
while (FlexCAN_GetBuffStatusFlag(base, mb_idx) == 0U)
{
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
if (timeElapsed >= uS2Ticks)
{
result = FLEXCAN_STATUS_TIMEOUT;
break;
}
}
flexcan_mb_config = *flexcan_mb;
/* Check if the MBs have been safely Inactivated */
if (((flexcan_mb_config & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT) == (uint32)FLEXCAN_TX_INACTIVE)
{
/* Transmission have occurred */
result = FLEXCAN_STATUS_SUCCESS;
}
if (((flexcan_mb_config & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT) == (uint32)FLEXCAN_TX_ABORT)
{
/* Transmission have been aborted */
result = FLEXCAN_STATUS_TIMEOUT;
}
}
/* Clear message buffer flag */
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetRxMbGlobalMask
* Description : Set Rx Message Buffer global mask as the mask value provided.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetRxMbGlobalMask_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetRxMbGlobalMask_Privileged(uint8 instance,
uint32 mask)
{
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FALSE;
#endif
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS)
{
FlexCAN_SetRxMsgBuffGlobalMask(pBase, mask);
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_EnterFreezeMode
* Description : Enter Driver In freeze Mode.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_EnterFreezeMode_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_EnterFreezeMode_Privileged(uint8 instance)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
return FlexCAN_EnterFreezeMode(base);
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ExitFreezeMode
* Description : Exit Driver from freeze Mode.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_ExitFreezeMode_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_ExitFreezeMode_Privileged(uint8 instance)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
return FlexCAN_ExitFreezeMode(base);
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetRxIndividualMask
* Description : Set Rx individual mask as absolute value provided by mask parameter
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetRxIndividualMask_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetRxIndividualMask_Privileged(uint8 instance,
uint8 mb_idx,
uint32 mask)
{
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FALSE;
#endif
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
if ((mb_idx > (((pBase->MCR) & FLEXCAN_MCR_MAXMB_MASK) >> FLEXCAN_MCR_MAXMB_SHIFT)) || (mb_idx >= FLEXCAN_RXIMR_COUNT))
{
result = FLEXCAN_STATUS_BUFF_OUT_OF_RANGE;
}
else
{
#endif
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS)
{
FlexCAN_SetRxIndividualMask(pBase, mb_idx, mask);
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
}
#endif
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetRxFifoGlobalMask
* Description : Set RxFifo Global Mask.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetRxFifoGlobalMask_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetRxFifoGlobalMask_Privileged(uint8 instance,
uint32 mask)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
FlexCAN_SetRxFifoGlobalMask(pBase, mask);
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_Deinit
* Description : Shutdown a FlexCAN module.
* This function will disable all FlexCAN interrupts, and disable the FlexCAN.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_Deinit_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_Deinit_Privileged(uint8 instance)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_ERROR;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
/* Enter Freeze Mode Required before to enter Disabled Mode */
result = FlexCAN_EnterFreezeMode(base);
if (FLEXCAN_STATUS_SUCCESS == result)
{
/* Reset registers */
FlexCAN_SetRegDefaultVal(base);
/* wait for disable */
(void)FlexCAN_Disable(base);
/* Clear state pointer that is checked by FLEXCAN_DRV_Init */
g_flexcan_Ip_StatePtr[instance] = NULL_PTR;
#if (STD_ON == FLEXCAN_SET_USER_ACCESS_ALLOWED_AVAILABLE)
/* Clear the UAA bit in REG_PROT to reset the elevation requirement */
OsIf_Trusted_Call1param(FlexCAN_ClrUserAccessAllowed, base);
#endif
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_MainFunctionRead
* Description : Process received Rx MessageBuffer or RxFifo.
* This function read the messages received as pulling or if the Interrupts are disabled.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_MainFunctionRead_Activity */
void FlexCAN_Ip_MainFunctionRead(uint8 instance, uint8 mb_idx)
{
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
DevAssert((mb_idx < (uint8)FEATURE_CAN_MAX_MB_NUM) || (mb_idx == FLEXCAN_MB_ENHANCED_RXFIFO));
#else
DevAssert(mb_idx < (uint8)FEATURE_CAN_MAX_MB_NUM);
#endif
#endif
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
if ((uint8)FLEXCAN_MB_ENHANCED_RXFIFO == mb_idx)
{
if ((boolean)TRUE == FlexCAN_IsEnhancedRxFifoAvailable(base))
{
if((boolean)TRUE == FlexCAN_IsEnhancedRxFifoEnabled(base))
{
if (FlexCAN_GetEnhancedRxFIFOStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE) != 0U)
{
FlexCAN_IRQHandlerEnhancedRxFIFO(instance, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE);
}
}
}
}
else
{
#endif /* (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) */
if (((boolean)TRUE == state->bIsLegacyFifoEn) && (mb_idx <= CAN_LEGACY_RXFIFO_OVERFLOW))
{
/* just process available legacy fifo event only */
if ((uint8)FLEXCAN_MB_HANDLE_RXFIFO == mb_idx)
{
if (FlexCAN_GetBuffStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE) != 0U)
{
FlexCAN_IRQHandlerRxFIFO(instance, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE);
}
}
}
else
{
if (FlexCAN_GetBuffStatusFlag(base, mb_idx) != 0U)
{
/* Check mailbox completed reception */
if (FLEXCAN_MB_RX_BUSY == state->mbs[mb_idx].state)
{
FlexCAN_IRQHandlerRxMB(instance, mb_idx);
}
}
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
}
#endif /* (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) */
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_MainFunctionBusOff
* Description : Check if BusOff occurred
* This function check the bus off event.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_MainFunctionBusOff_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_MainFunctionBusOff_Privileged(uint8 instance)
{
Flexcan_Ip_StatusType eRetVal = FLEXCAN_STATUS_ERROR;
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
uint32 u32ErrStatus = 0U;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
/* Get error status */
u32ErrStatus = base->ESR1;
if(0U != (u32ErrStatus & FLEXCAN_ESR1_BOFFINT_MASK))
{
/* Invoke callback */
if (state->error_callback != NULL_PTR)
{
state->error_callback(instance, FLEXCAN_EVENT_BUSOFF, u32ErrStatus, state);
}
/* Clear BusOff Status Flag */
base->ESR1 = FLEXCAN_ESR1_BOFFINT_MASK;
eRetVal = FLEXCAN_STATUS_SUCCESS;
}
return eRetVal;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_MainFunctionWrite
* Description : Process transmitted Tx MessageBuffer
* This function check the message if have been sent.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_MainFunctionWrite_Activity */
void FlexCAN_Ip_MainFunctionWrite(uint8 instance, uint8 mb_idx)
{
FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
if (FlexCAN_GetBuffStatusFlag(base, mb_idx) != 0U)
{
state->mbs[mb_idx].time_stamp = FlexCAN_GetMsgBuffTimestamp(base, mb_idx);
FlexCAN_UnlockRxMsgBuff(base);
/* Clear message buffer flag */
FlexCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
}
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetStopMode
* Description : Check if the FlexCAN instance is STOPPED.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetStopMode_Activity */
boolean FlexCAN_Ip_GetStopMode_Privileged(uint8 instance)
{
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
return (((base->MCR & FLEXCAN_MCR_LPMACK_MASK) == FLEXCAN_MCR_LPMACK_MASK) ? TRUE : FALSE);
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetStartMode
* Description : Check if the FlexCAN instance is STARTED.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetStartMode_Activity */
boolean FlexCAN_Ip_GetStartMode_Privileged(uint8 instance)
{
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
return (((base->MCR & (FLEXCAN_MCR_LPMACK_MASK | FLEXCAN_MCR_FRZACK_MASK)) == 0U) ? TRUE : FALSE);
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetStartMode
* Description : Set the FlexCAN instance in START mode.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetStartMode_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetStartMode_Privileged(uint8 instance)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
/* Enable Flexcan Module */
pBase->MCR &= ~FLEXCAN_MCR_MDIS_MASK;
return (FlexCAN_ExitFreezeMode(pBase));
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetStopMode
* Description : Set the FlexCAN instance in STOP mode.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetStopMode_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetStopMode_Privileged(uint8 instance)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
Flexcan_Ip_StatusType status;
status = FlexCAN_EnterFreezeMode(pBase);
if (status == FLEXCAN_STATUS_SUCCESS)
{
/* TODO: deactivate all pending tx, this should be move to IPW */
/* TODO:Clear all flag */
/* TODO: reset MB status */
/* TODO: disable all interrupt */
status = FlexCAN_Disable(pBase);
}
return status;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetRxMaskType
* Description : Set RX masking type.
* This function will set RX masking type as RX global mask or RX individual
* mask.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetRxMaskType_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetRxMaskType_Privileged(uint8 instance,
Flexcan_Ip_RxMaskType type)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
FlexCAN_SetRxMaskType(pBase, type);
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetBitrate
* Description : Set FlexCAN baudrate.
* This function will set up all the time segment values for classical frames or the
* extended time segments. Those time segment values are passed in by the user and
* are based on the required baudrate.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetBitrate_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetBitrate_Privileged(uint8 instance, const Flexcan_Ip_TimeSegmentType * bitrate, boolean enhExt)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(bitrate != NULL_PTR);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
/* Start critical section: implementation depends on integrator */
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_14();
/* Enable the use of extended bit time definitions */
FlexCAN_EnhCbtEnable(pBase, enhExt);
if (enhExt == TRUE)
{
/* Set extended time segments*/
FlexCAN_SetEnhancedNominalTimeSegments(pBase, bitrate);
}
else
{
if (FlexCAN_IsExCbtEnabled(pBase) == TRUE)
{
FlexCAN_SetExtendedTimeSegments(pBase, bitrate);
}
else
{
FlexCAN_SetTimeSegments(pBase, bitrate);
}
}
/* End critical section: implementation depends on integrator */
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_14();
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetBitrate
* Description : Get FlexCAN Baudrate.
* This function will be return the current bit rate settings for classical frames
* or the arbitration phase of FD frames.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetBitrate_Activity */
boolean FlexCAN_Ip_GetBitrate(uint8 instance,
Flexcan_Ip_TimeSegmentType * bitrate)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(bitrate != NULL_PTR);
#endif
const FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean enhCbt = FALSE;
enhCbt = FlexCAN_IsEnhCbtEnabled(pBase);
if (enhCbt == TRUE)
{
FlexCAN_GetEnhancedNominalTimeSegments(pBase, bitrate);
}
else
{
if (TRUE == FlexCAN_IsExCbtEnabled(pBase))
{
/* Get the Extended time segments*/
FlexCAN_GetExtendedTimeSegments(pBase, bitrate);
}
else
{
/* Get the time segments*/
FlexCAN_GetTimeSegments(pBase, bitrate);
}
}
return enhCbt;
}
#if (FEATURE_CAN_HAS_FD == STD_ON)
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ClearTDCFail
* Description : This function clear the TDC Fail flag.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_ClearTDCFail_Activity */
void FlexCAN_Ip_ClearTDCFail_Privileged(uint8 u8Instance)
{
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(u8Instance < FLEXCAN_INSTANCE_COUNT);
#endif
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
if (result == FLEXCAN_STATUS_SUCCESS)
{
/* Check if enhaced CBT is Enabled */
if (FlexCAN_IsEnhCbtEnabled(pBase) == TRUE)
{
pBase->ETDC |= FLEXCAN_ETDC_ETDCFAIL_MASK;
}
else
{
pBase->FDCTRL |= FLEXCAN_FDCTRL_TDCFAIL_MASK;
}
}
if (disabled == TRUE)
{
(void)FlexCAN_Disable(pBase);
}
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetTDCFail
* Description : This function get the value of the TDC Fail flag.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetTDCFail_Activity */
boolean FlexCAN_Ip_GetTDCFail_Privileged(uint8 u8Instance)
{
boolean value=FALSE;
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(u8Instance < FLEXCAN_INSTANCE_COUNT);
#endif
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
if (result == FLEXCAN_STATUS_SUCCESS)
{
/* Check if enhaced CBT is Enabled */
if (FlexCAN_IsEnhCbtEnabled(pBase) == TRUE)
{
value = ((pBase->ETDC & FLEXCAN_ETDC_ETDCFAIL_MASK) == FLEXCAN_ETDC_ETDCFAIL_MASK) ? TRUE : FALSE;
}
else
{
value = ((pBase->FDCTRL & FLEXCAN_FDCTRL_TDCFAIL_MASK) == FLEXCAN_FDCTRL_TDCFAIL_MASK) ? TRUE : FALSE;
}
}
if (disabled == TRUE)
{
(void)FlexCAN_Disable(pBase);
}
return value;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetTDCValue
* Description : This function get the value of the Transceiver Delay Compensation.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetTDCValue_Activity */
uint8 FlexCAN_Ip_GetTDCValue_Privileged(uint8 u8Instance)
{
uint8 value = 0;
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(u8Instance < FLEXCAN_INSTANCE_COUNT);
#endif
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
if (result == FLEXCAN_STATUS_SUCCESS)
{
/* Check if enhaced CBT is Enabled */
if (FlexCAN_IsEnhCbtEnabled(pBase) == TRUE)
{
value = (uint8)((pBase->ETDC& FLEXCAN_ETDC_ETDCVAL_MASK) >> FLEXCAN_ETDC_ETDCVAL_SHIFT);
}
else
{
value = (uint8)((pBase->FDCTRL & FLEXCAN_FDCTRL_TDCVAL_MASK) >> FLEXCAN_FDCTRL_TDCVAL_SHIFT);
}
}
if (disabled == TRUE)
{
(void)FlexCAN_Disable(pBase);
}
return value;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetBitrateCbt
* Description : Set FlexCAN bitrate.
* This function will set up all the time segment values for the data phase of
* FD frames. Those time segment values are passed in by the user and are based
* on the required baudrate.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetBitrateCbt_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetBitrateCbt_Privileged(uint8 instance, const Flexcan_Ip_TimeSegmentType * bitrate,
boolean bitRateSwitch)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(bitrate != NULL_PTR);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
boolean fd_enable = FlexCAN_IsFDEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((fd_enable == FALSE) || ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS)))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
boolean enhCbt = FlexCAN_IsEnhCbtEnabled(pBase);
/* Start critical section: implementation depends on integrator */
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_15();
FlexCAN_SetFDEnabled(pBase, fd_enable, bitRateSwitch);
if (enhCbt == TRUE)
{
FlexCAN_SetEnhancedDataTimeSegments(pBase, bitrate);
}
else
{
/* Set time segments*/
FlexCAN_SetFDTimeSegments(pBase, bitrate);
}
/* End critical section: implementation depends on integrator */
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_15();
}
if ((boolean)TRUE == disabled)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetBitrateFD
* Description : Get FlexCAN baudrate.
* This function will be return the current bit rate settings for the data phase
* of FD frames.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetBitrateFD_Activity */
boolean FlexCAN_Ip_GetBitrateFD(uint8 instance,
Flexcan_Ip_TimeSegmentType * bitrate)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
DevAssert(bitrate != NULL_PTR);
#endif
const FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean enhCbt = FlexCAN_IsEnhCbtEnabled(pBase);
if (enhCbt == TRUE)
{
FlexCAN_GetEnhancedDataTimeSegments(pBase, bitrate);
}
else
{
/* Get the time segments*/
FlexCAN_GetFDTimeSegments(pBase, bitrate);
}
return enhCbt;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetTDCOffset
* Description : Enables/Disables the Transceiver Delay Compensation feature and sets
* the Transceiver Delay Compensation Offset.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetTDCOffset_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetTDCOffset_Privileged(uint8 instance,
boolean enable,
uint8 offset)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
/* Check if enhaced CBT is Enabled */
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_16();
/* End critical section: implementation depends on integrator */
if ((pBase->CTRL2 & FLEXCAN_CTRL2_BTE_MASK) == FLEXCAN_CTRL2_BTE_MASK)
{
FlexCAN_SetEnhancedTDCOffset(pBase, enable, offset);
}
else
{
/* Enable/Disable TDC and set the TDC Offset */
FlexCAN_SetTDCOffset(pBase, enable, offset);
}
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_16();
/* Check if enhaced CBT is Enabled */
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetTxArbitrationStartDelay
* Description : Set FlexCAN Tx Arbitration Start Delay.
* This function will set how many CAN bits the Tx arbitration process start point can
* be delayed from the first bit of CRC field on CAN bus.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetTxArbitrationStartDelay_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetTxArbitrationStartDelay_Privileged(uint8 instance, uint8 value)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
/* Start critical section: implementation depends on integrator */
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_17();
FlexCAN_SetTxArbitrationStartDelay(pBase, value);
/* End critical section: implementation depends on integrator */
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_17();
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetBuffStatusFlag
* Description : Get FlexCAN Message Buffer Status Flag for an operation.
* In case of a complete operation this flag is set.
* In case msgBuff is 255 will return Enhanced Overflow Status Flag.
*END**************************************************************************/
/* implements FlexCAN_Ip_GetBuffStatusFlag_Activity */
boolean FlexCAN_Ip_GetBuffStatusFlag(uint8 instance, uint8 msgBuffIdx)
{
boolean returnResult = TRUE;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
const FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
if (msgBuffIdx == FLEXCAN_MB_ENHANCED_RXFIFO)
{
returnResult = ((FlexCAN_GetEnhancedRxFIFOStatusFlag(pBase, CAN_ENHANCED_RXFIFO_OVERFLOW) == 1U) ? TRUE : FALSE);
}
else
{
returnResult = ((FlexCAN_GetBuffStatusFlag(pBase, msgBuffIdx) == 1U) ? TRUE : FALSE);
}
return returnResult;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ClearBuffStatusFlag
* Description : Clear FlexCAN Message Buffer Status Flag.
* In case msgBuff is 255 will clear Enhanced Overflow Status Flag.
*END**************************************************************************/
/* implements FlexCAN_Ip_ClearBuffStatusFlag_Activity */
void FlexCAN_Ip_ClearBuffStatusFlag(uint8 instance, uint8 msgBuffIdx)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
if (msgBuffIdx == FLEXCAN_MB_ENHANCED_RXFIFO)
{
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(pBase, CAN_ENHANCED_RXFIFO_OVERFLOW);
}
else
{
FlexCAN_ClearMsgBuffIntStatusFlag(pBase, msgBuffIdx);
}
}
#endif
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_EnableInterrupts
* Description : Enable all mb interrupts configured.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_EnableInterrupts_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_EnableInterrupts_Privileged(uint8 u8Instance)
{
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_ERROR;
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[u8Instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(u8Instance < FLEXCAN_INSTANCE_COUNT);
#endif
if ((boolean)TRUE == FlexCAN_IsEnabled(pBase))
{
FlexCAN_EnableInterrupts(pBase, u8Instance);
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
if ((state->enhancedFifoOutput.isPolling == FALSE) && ( TRUE == FlexCAN_IsEnhancedRxFifoAvailable(pBase)))
{ /* Check if Enabled Enhanced Fifo */
if (TRUE == FlexCAN_IsEnhancedRxFifoEnabled(pBase))
{
FlexCAN_SetEnhancedRxFifoIntAll(pBase, TRUE);
}
}
#endif
state->isIntActive = (boolean)TRUE;
result = FLEXCAN_STATUS_SUCCESS;
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_DisableInterrupts
* Description : Enable all interrupts configured.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_DisableInterrupts_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_DisableInterrupts_Privileged(uint8 u8Instance)
{
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_ERROR;
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[u8Instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(u8Instance < FLEXCAN_INSTANCE_COUNT);
#endif
if ((boolean)TRUE == FlexCAN_IsEnabled(pBase))
{
FlexCAN_DisableInterrupts(pBase);
if (TRUE == FlexCAN_IsEnhancedRxFifoAvailable(pBase))
{ /* Check if Enabled Enhanced Fifo */
if (TRUE == FlexCAN_IsEnhancedRxFifoEnabled(pBase))
{
FlexCAN_SetEnhancedRxFifoIntAll(pBase, FALSE);
}
}
state->isIntActive = (boolean)FALSE;
result = FLEXCAN_STATUS_SUCCESS;
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetErrorInt
* Description : Enable\Disable Error or BusOff Interrupt
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetErrorInt_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetErrorInt_Privileged(uint8 u8Instance, Flexcan_Ip_ErrorIntType type, boolean enable)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(u8Instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
if(FLEXCAN_STATUS_SUCCESS == result )
{
switch(type)
{
case FLEXCAN_IP_INT_BUSOFF:
{
FlexCAN_SetErrIntCmd(pBase, FLEXCAN_INT_BUSOFF, enable);
break;
}
case FLEXCAN_IP_INT_ERR:
{
FlexCAN_SetErrIntCmd(pBase, FLEXCAN_INT_ERR, enable);
break;
}
case FLEXCAN_IP_INT_ERR_FAST :
{
FlexCAN_SetErrIntCmd(pBase, FLEXCAN_INT_ERR_FAST, enable);
break;
}
case FLEXCAN_IP_INT_RX_WARNING :
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
if (TRUE != FlexCAN_IsFreezeMode(pBase))
{
result = FLEXCAN_STATUS_ERROR;
}else
#endif
{
FlexCAN_SetErrIntCmd(pBase, FLEXCAN_INT_RX_WARNING, enable);
}
break;
}
case FLEXCAN_IP_INT_TX_WARNING :
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
if (TRUE != FlexCAN_IsFreezeMode(pBase))
{
result = FLEXCAN_STATUS_ERROR;
}else
#endif
{
FlexCAN_SetErrIntCmd(pBase, FLEXCAN_INT_TX_WARNING, enable);
}
break;
}
default:
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert((boolean)FALSE);
/* Should not get here */
#endif
break;
}
}
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_AbortTransfer
* Description : This function shuts down the FLEXCAN by disabling interrupts and
* the transmitter/receiver.
* This function disables the FLEXCAN interrupts, disables the transmitter and
* receiver.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_AbortTransfer_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_AbortTransfer(uint8 u8Instance,
uint8 mb_idx)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(u8Instance < FLEXCAN_INSTANCE_COUNT);
DevAssert((mb_idx < (uint8)FEATURE_CAN_MAX_MB_NUM) || (mb_idx == 255u));
#endif
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[u8Instance];
#if ((FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) && (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON))
Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[u8Instance];
#else
const Flexcan_Ip_StateType * state = g_flexcan_Ip_StatePtr[u8Instance];
#endif /* (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) && (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON) */
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
if (mb_idx < (uint8)FEATURE_CAN_MAX_MB_NUM)
{
if (FLEXCAN_MB_IDLE == state->mbs[mb_idx].state)
{
result = FLEXCAN_STATUS_NO_TRANSFER_IN_PROGRESS;
}
else
{
FLEXCAN_ClearMsgBuffIntCmd(pBase, u8Instance, mb_idx, state->isIntActive);
if (FLEXCAN_MB_TX_BUSY == state->mbs[mb_idx].state)
{
result = FlexCAN_AbortTxTransfer(u8Instance, mb_idx);
}
if (FLEXCAN_MB_RX_BUSY == state->mbs[mb_idx].state)
{
FlexCAN_AbortRxTransfer(u8Instance, mb_idx);
}
}
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
else
{
/* Check if transfer is done over DMA and stop transfer */
if ((state->enhancedFifoOutput.state == FLEXCAN_MB_RX_BUSY) && (state->transferType == FLEXCAN_RXFIFO_USING_DMA))
{
(void)Dma_Ip_SetLogicChannelCommand(state->rxFifoDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
if (state->enhancedFifoOutput.state == FLEXCAN_MB_RX_BUSY)
{
state->enhancedFifoOutput.state = FLEXCAN_MB_IDLE;
}
else
{
return FLEXCAN_STATUS_NO_TRANSFER_IN_PROGRESS;
}
}
else
{
return FLEXCAN_STATUS_NO_TRANSFER_IN_PROGRESS;
}
}
#endif /* if FEATURE_CAN_HAS_DMA_ENABLE */
#endif /* if FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
return result;
}
/* implements FlexCAN_Ip_SetRxMb14Mask_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetRxMb14Mask_Privileged(uint8 instance, uint32 mask)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FALSE;
#endif
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
pBase->RX14MASK = mask;
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/* implements FlexCAN_Ip_SetRxMb15Mask_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetRxMb15Mask_Privileged(uint8 instance, uint32 mask)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FALSE;
#endif
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
pBase->RX15MASK = mask;
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_SetListenOnlyMode
* Description : Set FlexCAN Listen Only.
* This function will enable or disable Listen Only mode.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_SetListenOnlyMode_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_SetListenOnlyMode_Privileged(uint8 instance, const boolean enable)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
FlexCAN_SetListenOnlyMode(pBase, enable);
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_GetListenOnlyMode
* Description : Check if Listen Only mode is ENABLE.
*
*END**************************************************************************/
/* implements FlexCAN_Ip_GetListenOnlyMode_Activity */
boolean FlexCAN_Ip_GetListenOnlyMode(uint8 instance)
{
const FLEXCAN_Type * base = g_Flexcan_Ip_aBase[instance];
return FlexCAN_IsListenOnlyModeEnabled(base);
}
#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
/*FUNCTION**********************************************************************
*
* Function Name : FlexCAN_Ip_ConfigTimeStamp_Privileged
* Description : Timestamp configuration
*
*END**************************************************************************/
/* implements FlexCAN_Ip_ConfigTimeStamp_Activity */
Flexcan_Ip_StatusType FlexCAN_Ip_ConfigTimeStamp_Privileged(uint8 instance, Flexcan_Ip_TimeStampConfigType * time_stamp)
{
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
DevAssert(instance < FLEXCAN_INSTANCE_COUNT);
#endif
Flexcan_Ip_StatusType result = FLEXCAN_STATUS_SUCCESS;
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
FLEXCAN_Type * pBase = g_Flexcan_Ip_aBase[instance];
boolean disabled = !FlexCAN_IsEnabled(pBase);
if (disabled == TRUE)
{
result = FlexCAN_Enable(pBase);
}
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
boolean freeze = FlexCAN_IsFreezeMode(pBase);
if ((freeze == FALSE) && (result == FLEXCAN_STATUS_SUCCESS))
{
result = FLEXCAN_STATUS_ERROR;
}
#endif
if (result == FLEXCAN_STATUS_SUCCESS )
{
FlexCAN_ConfigTimestamp(pBase, time_stamp);
FlexCAN_ConfigTimestampModule(time_stamp);
}
if (disabled == TRUE)
{
status = FlexCAN_Disable(pBase);
if (FLEXCAN_STATUS_SUCCESS != status)
{
result = status;
}
}
return result;
}
#endif
#define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"
/** @} */