/**
*   @file    Mcem_Fccu.c
*   @implements     Mcem_Fccu.c_Artifact
*
*   @version 1.0.0
*
*   @brief   AUTOSAR Mcem - FCCUv2 IP layer
*   @details Implementation of the internal FCCUv2 IP layer API
*
*   @addtogroup MCEM_MODULE
*   @{
*/
/*==================================================================================================
*   Project              : AUTOSAR 4.3 MCAL
*   Platform             : PA
*   Peripheral           : Fccu
*   Dependencies         : none
*
*   Autosar Version      : 4.3.1
*   Autosar Revision     : ASR_REL_4_3_REV_0001
*   Autosar Conf.Variant :
*   SW Version           : 1.0.0
*   Build Version        : MPC5777C_MCAL_1_0_0_RTM_ASR_REL_4_3_REV_0001_20190315
*
*   (c) Copyright 2006-2016 Freescale Semiconductor, Inc. 
*       Copyright 2017-2019 NXP
*   All Rights Reserved.
==================================================================================================*/
/*==================================================================================================
==================================================================================================*/

#ifdef __cplusplus
extern "C"{
#endif

/**
 *
 * @page misra_violations MISRA-C:2004 violations
 *
 * @section Mcem_Fccu_c_REF_1
 * Violates MISRA 2004 Required Rule 19.15, Precautions shall be taken in order to prevent the
 * contents of a header file being included twice
 * This is not a violation since all header files are protected against multiple inclusions
 *
 * @section Mcem_Fccu_c_REF_2
 * Violates MISRA 2004 Required Rule 11.1, Conversions shall not be performed between a pointer...
 * Unvoidable when addressing memory mapped registers
 *
 * @section Mcem_Fccu_c_REF_3
 * Violates MISRA 2004 Required Rule 1.4, Allow at least 31 character significance.
 * External identifiers are not distinct in the first 6 characters due to AUTOSAR compatibility
 *
 * @section Mcem_Fccu_c_REF_4
 * Violates MISRA 2004 Advisory Rule 19.1, #include statements in a file should only be preceded by other
 * preprocessor directives or comments.
 * Violated due to AUTOSAR requirement MEMMAP003.
 *
 * @section Mcem_Fccu_c_REF_5
 * Violates MISRA 2004 Advisory Rule 11.3, A cast should not be performed between a pointer type and an integral type
 * Unvoidable when addressing memory mapped registers.
 *
 * @section Mcem_Fccu_c_REF_6
 * Violates MISRA 2004 Required Rule 19.4, C macros shall only expand to a braced initialiser, a constant, a parenthesised,
 * expression, a type qualifier, a storage class specifier, or a do-while-zero construct.
 * Need wrap naming to a Base function.
 *
 * @section Mcem_Fccu_c_REF_7
 * Violates MISRA 2004 Advisory Rule 19.7, Function-like macro defined is required for expand the expression of Mcal_Trusted_Call
 *
 * @section Mcem_Fccu_c_REF_8
 * Violates MISRA 2004 Required Rule 8.10, All declarations and definitions of objects 
 * or functions at file scope shall have internal linkage unless external linkage is required.
 * Possibly unused public API
 *
 * @section [global]
 * Violates MISRA 2004 Required Rule 5.1, Exceeds 31 characters due to AUTOSAR compatibility
 *
 */

/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "CDD_Mcem_Cfg.h"

#ifdef MCEM_FCCU_REG_PROT_AVAILABLE
    /* @violates @ref Mcem_Fccu_c_REF_6 MISRA 2004 Required Rule 19.4, necessary defined to be used */
    #define USER_MODE_REG_PROT_ENABLED   (MCEM_ENABLE_USER_MODE_SUPPORT)
#else
    #define USER_MODE_REG_PROT_ENABLED (STD_OFF)
#endif


#include "SilRegMacros.h"
#include "Mcem_Fccu.h"

/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/

#define FCCU_VENDOR_ID_C                      43
#define FCCU_AR_RELEASE_MAJOR_VERSION_C       4
#define FCCU_AR_RELEASE_MINOR_VERSION_C       3
/* @violates @ref Mcem_Fccu_c_REF_3 31 character significance */
#define FCCU_AR_RELEASE_REVISION_VERSION_C    1
#define FCCU_SW_MAJOR_VERSION_C               1
#define FCCU_SW_MINOR_VERSION_C               0
#define FCCU_SW_PATCH_VERSION_C               0

/*==================================================================================================
*                                     FILE VERSION CHECKS
==================================================================================================*/
/* Check if current file and FCCU header file are of the same vendor */
#if (FCCU_VENDOR_ID_C != FCCU_VENDOR_ID)
    #error "Mcem_Fccu.c and Mcem_Fccu.h have different Vendor ids"
#endif
/* Check if current file and Mcem_Fccu.h header file are of the same Autosar version */
#if ((FCCU_AR_RELEASE_MAJOR_VERSION_C    != FCCU_AR_RELEASE_MAJOR_VERSION) || \
     (FCCU_AR_RELEASE_MINOR_VERSION_C    != FCCU_AR_RELEASE_MINOR_VERSION) || \
     (FCCU_AR_RELEASE_REVISION_VERSION_C != FCCU_AR_RELEASE_REVISION_VERSION))
    #error "AutoSar Version Numbers of Mcem_Fccu.c and Mcem_Fccu.h are different"
#endif
/* Check if current file and Mcem_Fccu.h header file are of the same Software version */
#if ((FCCU_SW_MAJOR_VERSION_C != FCCU_SW_MAJOR_VERSION) || \
     (FCCU_SW_MINOR_VERSION_C != FCCU_SW_MINOR_VERSION) || \
     (FCCU_SW_PATCH_VERSION_C != FCCU_SW_PATCH_VERSION))
    #error "Software Version Numbers of Mcem_Fccu.c and Mcem_Fccu.h are different"
#endif

/* Check if current file and CDD_Mcem_Cfg.h header file are of the same vendor */
#if (FCCU_VENDOR_ID_C != CDD_MCEM_VENDOR_ID_CFG)
    #error "Mcem_Fccu.c and CDD_Mcem_Cfg.h have different Vendor ids"
#endif
/* Check if current file and CDD_Mcem_Cfg.h header file are of the same Autosar version */
#if ((FCCU_AR_RELEASE_MAJOR_VERSION_C != CDD_MCEM_AR_RELEASE_MAJOR_VERSION_CFG) || \
     (FCCU_AR_RELEASE_MINOR_VERSION_C != CDD_MCEM_AR_RELEASE_MINOR_VERSION_CFG) || \
     (FCCU_AR_RELEASE_REVISION_VERSION_C != CDD_MCEM_AR_RELEASE_REVISION_VERSION_CFG))
    #error "AutoSar Version Numbers of Mcem_Fccu.c and CDD_Mcem_Cfg.h are different"
#endif
/* Check if current file and CDD_Mcem_Cfg.h header file are of the same Software version */
#if ((FCCU_SW_MAJOR_VERSION_C != CDD_MCEM_SW_MAJOR_VERSION_CFG) || \
     (FCCU_SW_MINOR_VERSION_C != CDD_MCEM_SW_MINOR_VERSION_CFG) || \
     (FCCU_SW_PATCH_VERSION_C != CDD_MCEM_SW_PATCH_VERSION_CFG))
    #error "Software Version Numbers of Mcem_Fccu.c and CDD_Mcem_Cfg.h are different"
#endif

#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    /* Check if current file and SilRegMacros.h header file are of the same Autosar version */
    #if ((FCCU_AR_RELEASE_MAJOR_VERSION_C    != SILREGMACROS_AR_RELEASE_MAJOR_VERSION) || \
         (FCCU_AR_RELEASE_MINOR_VERSION_C    != SILREGMACROS_AR_RELEASE_MINOR_VERSION))
        #error "AutoSar Version Numbers of Mcem_Fccu.c and SilRegMacros.h are different"
    #endif
#endif
/*==================================================================================================
*                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/


/*==================================================================================================
*                                       LOCAL MACROS
==================================================================================================*/
#if (STD_ON == MCEM_ENABLE_USER_MODE_SUPPORT)
    /* @violates @ref Mcem_Fccu_c_REF_6 MISRA 2004 Required Rule 19.4, C macros shall only expand to a braced initialiser,  a constant, a parenthesised expression */
    /* @violates @ref Mcem_Fccu_c_REF_7 MISRA 2004 Advisory Rule 19.7, Function-like macro defined. */
    #define Call_Mcem_Fccu_UnlockTrans()      Mcal_Trusted_Call(Mcem_Fccu_UnlockTrans)
#else
    /* @violates @ref Mcem_Fccu_c_REF_6 MISRA 2004 Required Rule 19.4, C macros shall only expand to a braced initialiser,  a constant, a parenthesised expression */
    /* @violates @ref Mcem_Fccu_c_REF_7 MISRA 2004 Advisory Rule 19.7, Function-like macro defined. */
    #define Call_Mcem_Fccu_UnlockTrans()      Mcem_Fccu_UnlockTrans()
#endif
/*==================================================================================================
*                                      LOCAL CONSTANTS
==================================================================================================*/


/*==================================================================================================
*                                      LOCAL VARIABLES
==================================================================================================*/


/*==================================================================================================
*                                      GLOBAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                      GLOBAL VARIABLES
==================================================================================================*/
#define MCEM_START_SEC_VAR_INIT_BOOLEAN
/* @violates @ref Mcem_Fccu_c_REF_1 precautions to prevent the contents of a header file being included twice */
#include "Mcem_MemMap.h"

/**
* @brief          Fccu Configuration Timeout expired
* @details        Specify if during configuration the timeout expired.A specific value that hardlock the FCCU IP.
*
*/
volatile VAR(boolean, MCEM_VAR) Fccu_bCfgTimeoutExpired = (boolean)FALSE;

#ifdef ERR_IPV_FCCU_0002
#if ERR_IPV_FCCU_0002 == STD_ON
/**
* @brief          Flag indicating at least one configured NCF has NMI reaction enabled
* @details        Computed from the configuration data during FCCU initialization.
*/
static VAR(boolean, MCEM_VAR) Fccu_AnyNFCWithNMI = (boolean)FALSE;
#endif
#endif /* defined (ERR_IPV_FCCU_0002) */

#define MCEM_STOP_SEC_VAR_INIT_BOOLEAN
/* @violates @ref Mcem_Fccu_c_REF_1 precautions to prevent the contents of a header file being included twice */
/* @violates @ref Mcem_Fccu_c_REF_4 only preprocessor statements and comments before "#include". */
#include "Mcem_MemMap.h"

#define MCEM_START_SEC_VAR_INIT_UNSPECIFIED
/* @violates @ref Mcem_Fccu_c_REF_1 precautions to prevent the contents of a header file being included twice */
/* @violates @ref Mcem_Fccu_c_REF_4 only preprocessor statements and comments before "#include". */
#include "Mcem_MemMap.h"

static P2CONST(Fccu_ConfigType, AUTOMATIC, MCEM_APPL_CONST) Mcem_Fccu_pCurrentConfigPtr = NULL_PTR;

#define MCEM_STOP_SEC_VAR_INIT_UNSPECIFIED
/* @violates @ref Mcem_Fccu_c_REF_1 precautions to prevent the contents of a header file being included twice */
/* @violates @ref Mcem_Fccu_c_REF_4 only preprocessor statements and comments before "#include". */
#include "Mcem_MemMap.h"

/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
#define MCEM_START_SEC_CODE
/* @violates @ref Mcem_Fccu_c_REF_1 precautions to prevent the contents of a header file being included twice */
/* @violates @ref Mcem_Fccu_c_REF_4 only preprocessor statements and comments before "#include". */
#include "Mcem_MemMap.h"

LOCAL_INLINE FUNC(Std_ReturnType, MCEM_CODE) Mcem_Fccu_WaitToComplete( void );
LOCAL_INLINE FUNC(Std_ReturnType, MCEM_CODE) Fccu_TestAndLockFCCUAccess( VAR(boolean, AUTOMATIC) bNmiCall );


LOCAL_INLINE FUNC(void, MCEM_CODE) Mcem_Fccu_UnlockFCCUAccess( VAR(boolean, AUTOMATIC) bNmiCall );

static FUNC(Fccu_FaultStatusType, MCEM_CODE) Mcem_Fccu_ReadFaultStatus(VAR(Mcem_FaultType, AUTOMATIC) nFaultId, VAR(boolean, AUTOMATIC) bNmiCall);

/*==================================================================================================
*                                       LOCAL FUNCTIONS
==================================================================================================*/

/**
* @brief Test FCCU activity status and acquire exclusive access if idle
* @details Function tests ongoing FCCU operation and acquires exclusive access if no operation is ongoing
* @return         Std_ReturnType
* @retval         E_OK Acquires exclusive access to the FCCU if no operation is ongoing
* @retval         E_NOT_OK Fails and exits the critical section
* 
*/
LOCAL_INLINE FUNC(Std_ReturnType, MCEM_CODE) Fccu_TestAndLockFCCUAccess( VAR(boolean, AUTOMATIC) bNmiCall )
{
    VAR(Std_ReturnType, MCEM_VAR) nReturnValue = (Std_ReturnType)E_OK;
    VAR(uint32, MCEM_VAR) regValue; 

    if ((boolean)TRUE != bNmiCall)
    {
        SuspendAllInterrupts();
    }
    
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    regValue =  REG_READ32(FCCU_CTRL_ADDR32);        
    regValue &= FCCU_OPS_MASK_U32;             
    
    if ( FCCU_OPS_IN_PROGRESS_U32 == regValue )
    {
        if ((boolean)TRUE != bNmiCall)
        {
            ResumeAllInterrupts();
        }
        nReturnValue = (Std_ReturnType)E_NOT_OK;
    }
    return nReturnValue;
}

/**
* @brief Test FCCU activity status and acquire exclusive access if idle
* @details Function tests ongoing FCCU operation and acquires exclusive access if no operation is ongoing
* @return         Std_ReturnType
* @retval         E_OK Acquires exclusive access to the FCCU if no operation is ongoing
* @retval         E_NOT_OK Fails and exits the critical section
* 
*/
LOCAL_INLINE FUNC(void, MCEM_CODE) Mcem_Fccu_UnlockFCCUAccess( VAR(boolean, AUTOMATIC) bNmiCall )
{

    if ((boolean)TRUE != bNmiCall)
    {
        ResumeAllInterrupts();
    }
}

/**
* @brief Wait for a completion of the FCCU internal operation
* @details Function waits for the internal FCCU operation completion or until a
*          guarding counter is exhausted.
* @return         Std_ReturnType
* @retval         E_OK Operation finished properly
* @retval         E_NOT_OK otherwise
* 
*/
LOCAL_INLINE FUNC(Std_ReturnType, MCEM_CODE) Mcem_Fccu_WaitToComplete( void )
{
    VAR(Std_ReturnType, MCEM_VAR) nReturnValue = (Std_ReturnType)E_NOT_OK;
    VAR(uint32, MCEM_VAR) regValue;                      
    VAR(uint8, MCEM_VAR)  loopCounter = 0U;
    
    do 
    {                           
        /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
        /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
        regValue =  REG_READ32(FCCU_CTRL_ADDR32);        
        regValue &= FCCU_OPS_MASK_U32;             
        loopCounter++;                                  
    } while ( (FCCU_OPS_IN_PROGRESS_U32 == regValue) && (loopCounter < FCCU_MAX_LOOP_COUNT_U8) );
        
    if ( FCCU_OPS_SUCCESSFUL_U32 == regValue )
    {
        nReturnValue = (Std_ReturnType)E_OK;
    }
    return nReturnValue;
    
} 


/*==================================================================================================
*                                       GLOBAL FUNCTIONS
==================================================================================================*/

/*================================================================================================*/

/**
* @brief          Execute FCCU operation and configures other bitfields in CTRL register.
* @details        Execute a specific FCCU internal operation - change the state to CONFIG or NORMAL, read 
*                 frozen registers, clear fault flags, etc. Function waits for the operation completion
*                 (or until a timeout occurs).
* @param[in]      nOpType       Operation type
* @param[in]      u32CtrlConfig Configuration of other bitfields in CTRL register to be configured
* @return         Std_ReturnType
* @retval         E_OK Operation finished properly
* @retval         E_NOT_OK otherwise
*
* @api            
*
*/
FUNC(Std_ReturnType, MCEM_CODE) Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg
(
    VAR(FccuOpType,AUTOMATIC) nOpType,
    VAR(uint32,    AUTOMATIC) u32CtrlConfig,
    VAR(boolean, AUTOMATIC) bNmiCall
)
{
    volatile VAR(Std_ReturnType, MCEM_VAR)nReturnValue = (Std_ReturnType)E_NOT_OK;
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    VAR(uint32, MCEM_VAR)u32CtrlReg = REG_READ32(FCCU_CTRL_ADDR32);  
    /* Keep only the values of glitch filter related bitfields in the CTRL register */
    u32CtrlReg &= (FCCU_CTRL_GLITCH_FILTER_BYPASS_MASK_U32 | FCCU_CTRL_GLITCH_FILTER_WIDTH_MASK_U32);
    MCAL_FAULT_INJECTION_POINT(FIP_T_MCEM_FCCU_EXECUTE_OPERATION_FP1);
    
    /* Test operation is not in progress and enter exclusive area */
    if ( (Std_ReturnType)E_OK == Fccu_TestAndLockFCCUAccess(bNmiCall) )
    {
        switch (nOpType)
        {
            case FCCU_ENTER_CONFIG_STATE:
            {
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_CTRLK_ADDR32,FCCU_OP1_KEY_U32);
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_CTRL_ADDR32, (uint32)nOpType | u32CtrlConfig | FCCU_CTRL_DEFAULT_VALUES_MASK);
                break;
            }
            case FCCU_ENTER_NORMAL_STATE:
            {
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_CTRLK_ADDR32,FCCU_OP2_KEY_U32);
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_CTRL_ADDR32, (uint32)nOpType | u32CtrlReg | FCCU_CTRL_DEFAULT_VALUES_MASK);
                break;
            }
            case FCCU_READ_FCCU_STATE:
            case FCCU_READ_N2AF_STATUS:
            case FCCU_READ_A2FF_STATUS:
            case FCCU_READ_N2FF_STATUS:
            case FCCU_READ_F2AF_STATUS:
            case FCCU_READ_FCCU_SCFS:
            case FCCU_READ_NCFS:
            case FCCU_CLEAR_FREEZE_STATUS_REGS:
            case FCCU_CLEAR_OPERATION_STATUS:
            case FCCU_READ_ALARM_TIMER:
            case FCCU_READ_CFG_TIMER:
            {
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_CTRL_ADDR32, (uint32)nOpType | u32CtrlReg | FCCU_CTRL_DEFAULT_VALUES_MASK);
                break;
            }
            default:
            {
                break;
            }
        }
        /* Free the exclusive access */
        /* @violates @ref Mcem_Fccu_c_REF_10 side effect of a function */
        Mcem_Fccu_UnlockFCCUAccess(bNmiCall);
        
        MCAL_FAULT_INJECTION_POINT(MCEM_FIP_5_SET_IDLE);
        

        /* wait to complete the operation */
        nReturnValue = Mcem_Fccu_WaitToComplete();
    }
    else
    {
        nReturnValue = (Std_ReturnType)E_NOT_OK;
    }
    
    return nReturnValue;
}



/**
* @brief          FCCU Init function
* @details        Initialization function for the FCCU IP
*
* @param[in]  pConfigPtr  Configuration pointer used for initialization
*
* @return         Std_ReturnType 
* @retval E_OK                Initialization was executed correctly                  
* @retval E_NOT_OK            Initialization was not executed correctly
*
* @api           
* 
* @note           Additionally, all pending (asserted) faults are cleared (FCCU_NCF_Sn)
*
* @implements     Fccu_Init_Activity
*
*/

FUNC(Std_ReturnType, MCEM_CODE) Mcem_Fccu_Init
(
    P2CONST(Fccu_ConfigType, AUTOMATIC, MCEM_APPL_CONST) pConfigPtr
)
{
    volatile VAR(Std_ReturnType, MCEM_VAR)nReturnValue = (Std_ReturnType)E_NOT_OK;
    VAR(uint32, MCEM_VAR)u32RegisterValue     = FCCU_NO_ERRORS_U32;
    VAR(uint32, MCEM_VAR)u32ReadBack          = FCCU_NO_ERRORS_U32;
    VAR(uint8,  MCEM_VAR)uBank;

    Mcem_Fccu_pCurrentConfigPtr = pConfigPtr;
#ifdef ERR_IPV_FCCU_0002
#if ERR_IPV_FCCU_0002 == STD_ON
    /* set the NCF-with-NMI flag by default */
    Fccu_AnyNFCWithNMI = (boolean)TRUE;
#endif
#endif
    /* set to FALSE to eliminate unwanted TIMEOUT_ISR */
    Fccu_bCfgTimeoutExpired = (boolean)FALSE;

#if (STD_ON == MCEM_ENABLE_USER_MODE_SUPPORT)
  #ifdef MCEM_FCCU_REG_PROT_AVAILABLE
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    if ((uint8)0U == GET_USER_ACCESS_ALLOWED(FCCU_BASEADDR))
    {
        Mcal_Trusted_Call(Mcem_Fccu_SetUserAccess);
    }
  #endif
#endif
    
    /* Read errors */
    nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_NCFS, FCCU_NO_CTRL_REG_CONFIGURATION, (boolean)FALSE);
    /* clear pending faults in all NCF_Sn registers */
    for ( uBank=0U; ((Std_ReturnType)E_OK == nReturnValue) && (uBank < FCCU_FAULT_REGISTER_COUNT); uBank++ )
    {
        /* Test operation is not in progress and enter exclusive area */
        if ( (Std_ReturnType)E_OK == Fccu_TestAndLockFCCUAccess((boolean)FALSE) )
        {
     
            /* Read NCF_Sn status register*/
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            u32ReadBack = REG_READ32(FCCU_NCF_S_ADDR32( uBank ));
            /* Clear first FCCU Error register*/
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            REG_WRITE32(FCCU_NCFK_ADDR32,FCCU_NCF_CLR_KEY_U32);
            /* Clear all pending faults (W1C) */
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            REG_WRITE32(FCCU_NCF_S_ADDR32( uBank ), u32ReadBack);
            
            /* Free the exclusive access */
            Mcem_Fccu_UnlockFCCUAccess((boolean)FALSE);
            MCAL_FAULT_INJECTION_POINT(FIP_T_MCEM_FCCU_INIT_FP4_LOOPx);            
                
            /* wait to complete the operation */
            nReturnValue = Mcem_Fccu_WaitToComplete();
        } 
        else
        {
            nReturnValue = (Std_ReturnType)E_NOT_OK;
        }               
    }

    if ( (Std_ReturnType)E_OK == nReturnValue )
    {
        Call_Mcem_Fccu_UnlockTrans();
        /* Write configuration timeout - Time protection on Init*/
        /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
        /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
        REG_WRITE32(FCCU_CFG_TO_ADDR32, pConfigPtr->Fault_Cfg_TO);
        /* Enable Configuration Timeout Interrupt */
        /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
        /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
        REG_WRITE32(FCCU_IRQ_EN_ADDR32,pConfigPtr->Fault_Irq_EN);

        
        /* Enter CONFIG State */
        nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_ENTER_CONFIG_STATE, pConfigPtr->Ctrl_Glitch_Filter, (boolean)FALSE);
    }
    if ( (Std_ReturnType)E_OK == nReturnValue )
    {
        /*check if the status changed */
        nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_FCCU_STATE, FCCU_NO_CTRL_REG_CONFIGURATION, (boolean)FALSE);
    }
    if ( (Std_ReturnType)E_OK == nReturnValue )
    {
        /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
        /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
        u32RegisterValue = REG_READ32(FCCU_STAT_ADDR32);
        u32RegisterValue &= FCCU_STATUS_MASK_U32;
        MCAL_FAULT_INJECTION_POINT(FIP_D_MCEM_FCCU_INIT_FP8);        
        if (FCCU_CONFIG_STATE_U32 == u32RegisterValue)
        {
            /* Write configuration register - state after reset and output pin config*/
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
        #ifdef ERR_IPV_FCCU_0004
        #if (ERR_IPV_FCCU_0004 == STD_ON)            
            REG_WRITE32(FCCU_CFG_ADDR32,pConfigPtr->Fault_Config & FCCU_CFG_DIS_AFTER_RESET_BIT_MASK_U32);      
        #endif
        #else
            REG_WRITE32(FCCU_CFG_ADDR32,pConfigPtr->Fault_Config); 
        #endif
            /*Write the value of configuration timer*/
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            REG_WRITE32(FCCU_NCF_TO_ADDR32,pConfigPtr->Fault_Ncf_TO);

            /* Set Delta_T timer value for output pin signaling*/
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            REG_WRITE32(FCCU_DELTA_T_ADDR32,pConfigPtr->Fault_DeltaT & FCCU_DELTA_T_RESERVED_MASK_U32);

         
            for ( uBank=0U; (uBank < FCCU_FAULT_REGISTER_COUNT); uBank++ )
            {
                /* Enable faults*/
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_NCF_E_ADDR32( uBank ),0x00000000U);
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_NCF_E_ADDR32( uBank ),pConfigPtr->Fault_Ncf_E[ uBank ]);
                
                /* Set recovery type for each fault*/
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_NCF_CFG_ADDR32( uBank ),pConfigPtr->Fault_Ncf_Cfg[ uBank ]);
                
                /* Enable recovery timeout for each fault */
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_NCF_TOE_ADDR32( uBank ),0x00000000U);
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_NCF_TOE_ADDR32( uBank ),pConfigPtr->Fault_Ncf_TOE[ uBank ]);
                
                /* Enable Alarm Interrupt for each fault */
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_IRQ_ALARM_EN_ADDR32( uBank ),pConfigPtr->Fault_Alarm_EN[ uBank ]);
                
                /* Enable NMI Interrupt for each fault */
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_NMI_EN_ADDR32( uBank ),pConfigPtr->Fault_Nmi_EN[ uBank ]);
    
                /* Enable Output signaling for each fault */
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_EOUT_SIG_EN_ADDR32( uBank ),pConfigPtr->Fault_EoutSig_EN[ uBank ]);
            }
            
            
            for ( uBank=0U; (uBank < FCCU_FAULT_STATE_REGISTER_COUNT); uBank++ )
            {
                /* Set reaction type for each fault */
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                REG_WRITE32(FCCU_NCFS_CFG_ADDR32( uBank ),pConfigPtr->Fault_Ncfs_Cfg[ uBank ]);
            }
            MCAL_FAULT_INJECTION_POINT(MCEM_FIP_1_SET_DELAY);            
            /* Enter NORMAL State */
            nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_ENTER_NORMAL_STATE, FCCU_NO_CTRL_REG_CONFIGURATION, (boolean)FALSE);
/* Handle erratum e10900: if the platform is affected */
#ifdef ERR_IPV_FCCU_0004
#if (ERR_IPV_FCCU_0004 == STD_ON)
            nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_ENTER_CONFIG_STATE, pConfigPtr->Ctrl_Glitch_Filter, (boolean)FALSE);
            if ( (Std_ReturnType)E_OK == nReturnValue )
            {
                /*check if the status changed */
                nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_FCCU_STATE, FCCU_NO_CTRL_REG_CONFIGURATION, (boolean)FALSE);
            }
            if ( (Std_ReturnType)E_OK == nReturnValue )
            {
                /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                u32RegisterValue = REG_READ32(FCCU_STAT_ADDR32);
                u32RegisterValue &= FCCU_STATUS_MASK_U32;   
                if (FCCU_CONFIG_STATE_U32 == u32RegisterValue)
                {
                    /* Write configuration register - state after reset and output pin config*/
                    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                    REG_RMW32(FCCU_CFG_ADDR32, FCCU_CFG_EN_AFTER_RESET_BIT_MASK_U32, pConfigPtr->Fault_Config);
                    /* Enter NORMAL State */
                    nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_ENTER_NORMAL_STATE, FCCU_NO_CTRL_REG_CONFIGURATION, (boolean)FALSE);
                }
            }
#endif
#endif
/* Handle erratum e7227 if the platform is affected */
#ifdef ERR_IPV_FCCU_0003
#if (ERR_IPV_FCCU_0003 == STD_ON)
#if (STD_ON==MCEM_DEV_ERROR_DETECT)       
            MCAL_FAULT_INJECTION_POINT(FIP_T_MCEM_FCCU_INIT_FP11);
            if ( ((Std_ReturnType)E_OK) == nReturnValue )
            {
                /*Check if the status is FAULT */
                /*It mean that still having fault is pending*/
                nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_FCCU_STATE, FCCU_NO_CTRL_REG_CONFIGURATION, (boolean)FALSE);
                if( ((Std_ReturnType)E_OK) == nReturnValue )
                {
                    u32RegisterValue = REG_READ32(FCCU_STAT_ADDR32);
                    u32RegisterValue &= FCCU_STATUS_MASK_U32;
                    if (FCCU_FAULT_STATE_U32 == u32RegisterValue)
                    {
                        /* Read errors */
                        nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_NCFS, FCCU_NO_CTRL_REG_CONFIGURATION, (boolean)TRUE);
                        if( ((Std_ReturnType)E_OK) == nReturnValue )
                        {
                            for ( uBank = 0U; (uBank < FCCU_FAULT_REGISTER_COUNT); uBank++ )
                            {
                                if ( (Std_ReturnType)E_OK == Fccu_TestAndLockFCCUAccess((boolean)FALSE) )
                                {
                                    /* Read NCF_Sn status register*/
                                    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
                                    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
                                    u32RegisterValue = REG_READ32(FCCU_NCF_S_ADDR32( uBank ));
                                    u32RegisterValue &= Mcem_au32StaticFaultMasks[uBank];
                                    if ( 0UL != u32RegisterValue)
                                    {
                                    #if (STD_ON == MCEM_DEM_EXTENDED_DATA)
                                        /* FP11 - Failure Point 11 */
                                        nReturnValue = (Std_ReturnType)ID_MCEM_FCCU_INIT_FP11_U8;
                                        /* Dem extended data will contain:
                                        - the FP (failure point) identifier */
                                        u8DemExtDataLength = MCEM_DEM_EXT_DATA_LENGTH_2BYTES_U8;
                                    #endif
                                        break;
                                    }
                                    else
                                    {
                                        /*do nothing*/
                                    }    
                                    /* Free the exclusive access */
                                    Mcem_Fccu_UnlockFCCUAccess((boolean)FALSE);
                                    /* wait to complete the operation */
                                    nReturnValue = Mcem_Fccu_WaitToComplete();
                                } 
                                else
                                {
                                    nReturnValue = (Std_ReturnType)E_NOT_OK;
                                }
                            }
                        }
                    }
                }
            }
#endif            
#endif
#endif /* defined (ERR_IPV_FCCU_0003) */
/* Handle erratum e5922 if the platform is affected */
#ifdef ERR_IPV_FCCU_0002
#if ERR_IPV_FCCU_0002 == STD_ON
            /* If initialization went OK so far... */
            if ( ((Std_ReturnType)E_OK) == nReturnValue )
            {  
                /* clear the NCF-with-NMI flag  */
                Fccu_AnyNFCWithNMI = (boolean)FALSE;
                
                /* ...compute the any-NCF-with-NMI flag from the configuration */
                for ( uBank=0U; ((uBank < FCCU_FAULT_REGISTER_COUNT) && ((boolean)FALSE == Fccu_AnyNFCWithNMI)); uBank++ )
                {
                     Fccu_AnyNFCWithNMI = (boolean)(0UL != (pConfigPtr->Fault_Ncf_E[ uBank ] & pConfigPtr->Fault_Nmi_EN[ uBank ]));
                }
            }
#endif
#endif /* defined (ERR_IPV_FCCU_0002) */

        }
        else
        {
            nReturnValue = (Std_ReturnType)E_NOT_OK;
        }
    }
    if ( (Std_ReturnType)E_OK == nReturnValue )
    {
        MCAL_FAULT_INJECTION_POINT(FIP_T_MCEM_FCCU_INIT_FP9);
        /*check if the status changed */
        nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_FCCU_STATE, FCCU_NO_CTRL_REG_CONFIGURATION, (boolean)FALSE);
    }
    if ( (Std_ReturnType)E_OK == nReturnValue )
    {
        /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
        /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
        u32RegisterValue = REG_READ32(FCCU_STAT_ADDR32);
        u32RegisterValue &= FCCU_STATUS_MASK_U32;
        if (FCCU_CFG_TO_IRQ_U32 == (pConfigPtr->Fault_Irq_EN & FCCU_CFG_TO_IRQ_U32))
        {

        if ( ((boolean)FALSE == Fccu_bCfgTimeoutExpired) && (FCCU_NORMAL_STATE_U32 == u32RegisterValue) )
        {
            nReturnValue = (Std_ReturnType)E_OK;
        }
        else
        {
            nReturnValue = (Std_ReturnType)E_NOT_OK;
            /* FCCU not configured */
            Fccu_bCfgTimeoutExpired = (boolean)FALSE;
            }
        }
        else
        {
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            u32ReadBack = (uint32)(REG_READ32(FCCU_IRQ_STAT_ADDR32) & FCCU_CFG_TO_IRQ_U32);
            if ( (FCCU_CFG_TO_IRQ_U32 != u32ReadBack) && (FCCU_NORMAL_STATE_U32 == u32RegisterValue) )
            {
                nReturnValue = (Std_ReturnType)E_OK;            
            }
        }
    }

    return nReturnValue;
}


/**
* @brief          Get Errors function
* @details        Function gets logged errors from the FCCU IP, and stores them in the Error container
*
* @param[out]     pFaultContainer  Error container where the errors will be stored
* @param[out]     pFaultAccumulator  Accumulator where all fault bits are aggregated
*
* @return         Std_ReturnType 
* @retval E_OK                Fault status was fetched properly
* @retval E_NOT_OK            Error occured
*
* @api           
* 
*/
FUNC(Std_ReturnType, MCEM_CODE) Mcem_Fccu_GetErrors
(
    VAR(uint32,AUTOMATIC) pFaultContainer[],
    P2VAR(uint32,AUTOMATIC,MCEM_APPL_DATA) pFaultAccumulator,
    VAR(boolean, AUTOMATIC) bNmiCall
)
{
    VAR(Std_ReturnType, MCEM_VAR) nReturnValue = (Std_ReturnType)E_NOT_OK;
    VAR(uint8, MCEM_VAR) uBank;
    static CONST(uint32, MCEM_CONST) u32FccuNcfSnRegMask[2U] = {0xFFFFFFFFUL,0xFFFFFFFFUL};
    
#if (STD_ON == MCEM_ENABLE_USER_MODE_SUPPORT)
  #ifdef MCEM_FCCU_REG_PROT_AVAILABLE
    if ((boolean)TRUE != bNmiCall)
    {
        /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
        /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
        if ((uint8)0U == GET_USER_ACCESS_ALLOWED(FCCU_BASEADDR, FCCU_PERIPH_SIZE_U32))
        {
            Mcal_Trusted_Call(Mcem_Fccu_SetUserAccess);
        }
    }
  #endif
#endif
    /* Read non-critical fault registers */
    nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_NCFS, FCCU_NO_CTRL_REG_CONFIGURATION, bNmiCall);
    
    if ( (Std_ReturnType)E_OK == nReturnValue )
    {
        for ( uBank=0U; (uBank < FCCU_FAULT_REGISTER_COUNT); uBank++ )
        {
            /* Read and store fault status for each fault */
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            /* Mask unused register bit-fields not to return out of range faults */
            pFaultContainer[ uBank ]=REG_READ32(FCCU_NCF_S_ADDR32( uBank )) & u32FccuNcfSnRegMask[ uBank ];
            /* Accumulate all faults */
            *pFaultAccumulator |= pFaultContainer[ uBank ];
        }
    }
    
    return nReturnValue;
}


/**
* @brief          Clear fault function
* @details        Function shall clear error flag for a specified fault.
*
* @param[in]      nFaultId     The ID of the fault that shall be cleared
*                             
* @return         Std_ReturnType
* @retval E_OK                Fault was cleared successfully
* @retval E_NOT_OK            Fault was not cleared.
*
* @api
*
* @implements     Fccu_ClearFault_Activity        
*/
FUNC(Std_ReturnType, MCEM_CODE) Mcem_Fccu_ClearFault
(
    VAR(Mcem_FaultType, AUTOMATIC) nFaultId, VAR(boolean, AUTOMATIC) bNmiCall
)
{
    VAR(Std_ReturnType, MCEM_VAR) nReturnValue = (Std_ReturnType)E_NOT_OK;
    VAR(uint8, MCEM_VAR)u8RegisterPosition     = nFaultId >> FCCU_REG_SHIFT_U8;
    VAR(uint8, MCEM_VAR)u8BitPosition          = nFaultId & FCCU_REG_MASK_U8;
    VAR(uint32, MCEM_VAR)u32RegisterValue;
#if (STD_ON == MCEM_ENABLE_USER_MODE_SUPPORT)
  #ifdef MCEM_FCCU_REG_PROT_AVAILABLE
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    if ((uint8)0U == GET_USER_ACCESS_ALLOWED(FCCU_BASEADDR)
    {
        Mcal_Trusted_Call(Mcem_Fccu_SetUserAccess);
    }
  #endif
#endif

    /* Read errors */
    nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_NCFS, FCCU_NO_CTRL_REG_CONFIGURATION, bNmiCall); 
    if ( (Std_ReturnType)E_OK == nReturnValue )
    {           

        /* Test operation is not in progress and enter exclusive area */
        if ( (Std_ReturnType)E_OK == Fccu_TestAndLockFCCUAccess(bNmiCall) )
        {
            /* Calculate bit mask */
            u32RegisterValue = ((uint32)FCCU_SHIFT_BIT_U32 << u8BitPosition);
            /* Unlock fault clearing */
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            REG_WRITE32(FCCU_NCFK_ADDR32,FCCU_NCF_CLR_KEY_U32);
            /* Clear the fault */
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            REG_WRITE32(FCCU_NCF_S_ADDR32(u8RegisterPosition), u32RegisterValue);
            
            /* Free the exclusive access */
            /* @violates @ref Mcem_Fccu_c_REF_10 side effect of a function */
            Mcem_Fccu_UnlockFCCUAccess(bNmiCall);
            MCAL_FAULT_INJECTION_POINT(FIP_T_MCEM_FCCU_CLEAR_FAULT_FP3);
            
            /* Wait clearing to complete */
            nReturnValue = Mcem_Fccu_WaitToComplete();
            if ( (Std_ReturnType)E_OK == nReturnValue )
            {
                MCAL_FAULT_INJECTION_POINT(FIP_T_MCEM_FCCU_CLEAR_FAULT_FP4);
                if (FCCU_FAULT_NOT_ASSERTED != Mcem_Fccu_ReadFaultStatus(nFaultId, bNmiCall))
                {
                    nReturnValue = (Std_ReturnType)E_NOT_OK;
                }
            }
        }
        else
        {
            nReturnValue = (Std_ReturnType)E_NOT_OK;
        }
    }
    return nReturnValue;
}



/**
* @brief          Read fault status function
* @details        Function check the status for a certain fault.
*
* @param[in]      nFaultId     Id of the fault
*
* @return         Fccu_FaultStatusType
* @retval FCCU_FAULT_ASSERTED            The fault is asserted
* @retval FCCU_FAULT_NOT_ASSERTED         The fault is not asserted
*
*/
static FUNC(Fccu_FaultStatusType, MCEM_CODE) Mcem_Fccu_ReadFaultStatus
(
    VAR(Mcem_FaultType, AUTOMATIC) nFaultId,
    VAR(boolean, AUTOMATIC) bNmiCall
)
{
    VAR(Fccu_FaultStatusType, MCEM_VAR)nReturnValue  = FCCU_FAULT_NOT_AVAILABLE;
    VAR(uint8, MCEM_VAR)u8RegisterPosition       = nFaultId >> FCCU_REG_SHIFT_U8;
    VAR(uint8, MCEM_VAR)u8BitPosition            = nFaultId & FCCU_REG_MASK_U8;
    VAR(uint32, MCEM_VAR)u32RegisterValue        = FCCU_NO_ERRORS_U32;

    
    /* Read Errors */
    if ( (Std_ReturnType)E_OK == Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg(FCCU_READ_NCFS, FCCU_NO_CTRL_REG_CONFIGURATION, bNmiCall ))
    {
        /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
        /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
        u32RegisterValue = REG_READ32(FCCU_NCF_S_ADDR32(u8RegisterPosition));

        if (FCCU_NO_ERRORS_U32 != ((FCCU_SHIFT_BIT_U32 << u8BitPosition) & u32RegisterValue))
        {
            nReturnValue = FCCU_FAULT_ASSERTED;
        }
        else
        {
            nReturnValue = FCCU_FAULT_NOT_ASSERTED;
        }
    }
    return nReturnValue;
}



/**
* @brief          Inject fault function
* @details        Inject the fault in the FCCU
*
* @param[in]      nFaultId     ID of the fault that shall be injected
*                            
* @return         void
*
* @api            
*  
*/
FUNC(void, MCEM_CODE) Mcem_Fccu_InjectFault
(
    VAR(Mcem_FaultType, AUTOMATIC) nFaultId
)
{
    /* Inject Fake non-critical fault */
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    REG_WRITE32(FCCU_NCFF_ADDR32, nFaultId);
}

/**
* @brief          Check if a fault ID is valid
* @details        Check if a fault ID is valid
*
* @param[in]      nFaultId     ID of the fault that shall be injected
*                            
* @return         void
*
* @api            
*  
*/
FUNC(boolean, MCEM_CODE) Mcem_Fccu_CheckValidFault
(
    VAR(Mcem_FaultType, AUTOMATIC) nFaultId
)
{
    VAR(boolean, AUTOMATIC) bReturnValue = (boolean)FALSE;
    
    if ((Mcem_Fccu_pCurrentConfigPtr->Fault_Ncf_E[nFaultId >> MCEM_FAULT_CONTAINER_SHIFT]) & (1UL << ((nFaultId)&MCEM_FAULT_CONTAINER_MASK)))
    {
        bReturnValue = (boolean)TRUE;
    }
    return (bReturnValue);
}

/**
* @brief          Fccu lock configuration function
* @details        Use this function to hard lock the configuration of FCCU
*
* @return         void
*
* @api           
*  
*/
FUNC(void, MCEM_CODE) Mcem_Fccu_LockConfiguration( void )
{
    /* Write permanent lock key and lock FCCU configuration */
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    REG_WRITE32(FCCU_PERMNT_LOCK_ADDR32,FCCU_PERM_LOCK_KEY_U32);
}


/**
* @brief          Check whether an NMI has originated from the FCCU
* @details        Function checks whether the FCCU is the source of NMI request.
*
* @return         Std_ReturnType (extended) 
* @retval E_FCCU_SPURIOUS_NMI   The initialized MCEM (FCCU) might trigger a spurious interrupt.
* @retval E_OK                  The NMI request originates in initialized MCEM (FCCU).
* @retval E_NOT_OK              Othewise (non-FCCU related NMI, FCCU malfunction).
*
* @note           In case the preconditions for erratum e5922 are fulfilled, the user NMI handler has to 
*                 call Mcem_GetErrors() function to check whether there is at least one pending fault.
*
* @pre              MCEM/FCCU has been initialized
*/
FUNC(Std_ReturnType, MCEM_CODE) Mcem_Fccu_CheckNMI( void )
{
    VAR(Std_ReturnType, MCEM_VAR) nReturnValue = (Std_ReturnType)E_NOT_OK;
    VAR(uint32, MCEM_VAR) u32RegisterValue;
    VAR(boolean, MCEM_VAR) bSvcLowerPrio = (boolean)FALSE;
    
    MCAL_FAULT_INJECTION_POINT(MCEM_FIP_3_SET_IDLE);
#ifdef MCEM_FCCU_EXTRA_NMI_API
  #if (STD_ON == MCEM_FCCU_EXTRA_NMI_API)
    bSvcLowerPrio = (boolean)TRUE;
  #endif /* MCEM_FCCU_EXTRA_NMI_API == STD_ON */
#endif /* defined MCEM_FCCU_EXTRA_NMI_API */
    /* check the FCCU_IRQ_STAT.NMI flag first */
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    u32RegisterValue = REG_READ32( FCCU_IRQ_STAT_ADDR32 );
    MCAL_FAULT_INJECTION_POINT(MCEM_FIP_2_SET_NMIFLAG);
    if ( (uint32)0UL != (u32RegisterValue & FCCU_NMI_IRQ_MASK_U32) )
    {
        /* NMI IRQ asserted, read the FCCU status */
        nReturnValue = Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg( FCCU_READ_FCCU_STATE, FCCU_NO_CTRL_REG_CONFIGURATION, bSvcLowerPrio);
        if ( ((Std_ReturnType)E_OK) == nReturnValue )
        {
            /* Check whether the FCCU is in the FAULT state */
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            u32RegisterValue = REG_READ32( FCCU_STAT_ADDR32 );
            u32RegisterValue &= FCCU_STATUS_MASK_U32;
            if ( FCCU_FAULT_STATE_U32 == u32RegisterValue )
            {
                /* FCCU has generated the NMI IRQ */
                nReturnValue = (Std_ReturnType)E_OK;
#ifdef ERR_IPV_FCCU_0002
#if ERR_IPV_FCCU_0002 == STD_ON
                /* In case of erratum e5922 affected device, additionally check for spurious IRQ */
                if ( (boolean)FALSE == Fccu_AnyNFCWithNMI )
                {
                    /* No NCF has NMI enabled, i.e. this is a positively identified spurious IRQ */
                    nReturnValue = E_FCCU_SPURIOUS_NMI;
                }
#endif    /* ERR_IPV_FCCU_0002 == STD_ON */
#endif /* defined (ERR_IPV_FCCU_0002) */

            }             /* FCCU in fault state */
        }                 /* read FCCU operation result */
    }                     /* NMI IRQ asserted */
#ifdef ERR_IPV_FCCU_0002
#if ERR_IPV_FCCU_0002 == STD_ON
    /* It seems the information about asserted NMI_STAT in case of e5922 SpNMIRQ is not correct.
       As a result, check the precomputed NCF_NMI_ENx flag and return the suspect spurious IRQ 
       eventually. Another step is required in the NMI handler -- NCF states shall be checked 
       whether there's a pending NCF situation to finally confirm the e5922-related spurious NMIRQ.
    */
    else
    {
        /* NMI IRQ not asserted, read the FCCU status anyway */
        if ( ((Std_ReturnType)E_OK) == Mcem_Fccu_ExecuteOperationAndConfigureCtrlReg( FCCU_READ_FCCU_STATE, FCCU_NO_CTRL_REG_CONFIGURATION ), bSvcLowerPrio )
        {
            /* Check whether the FCCU is in the FAULT state */
            /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
            /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
            u32RegisterValue = REG_READ32( FCCU_STAT_ADDR32 );
            u32RegisterValue &= FCCU_STATUS_MASK_U32;
            if ( (FCCU_FAULT_STATE_U32 == u32RegisterValue) && ((boolean)FALSE == Fccu_AnyNFCWithNMI) )
            {
                /* No NCF has NMI enabled and FCCU is in FAULT state, i.e. this is a suspect spurious IRQ */
                nReturnValue = E_FCCU_SPURIOUS_NMI;
            }
        }
    }
#endif    /* ERR_IPV_FCCU_0002 == STD_ON */
#endif /* defined (ERR_IPV_FCCU_0002) */
    return nReturnValue;
}

#if (STD_ON == MCEM_ENABLE_USER_MODE_SUPPORT)
    #ifdef MCEM_FCCU_REG_PROT_AVAILABLE
/**
* @brief Do configure REG_PROT for FCCU
* @details Function will do configure REG_PROT for FCCU running in user mode
* 
*/
/* @violates @ref Mcem_Fccu_c_REF_8 Public API */
FUNC(void, MCEM_CODE) Mcem_Fccu_SetUserAccess( void )
{
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    SET_USER_ACCESS_ALLOWED(FCCU_BASEADDR);
}
    #endif
#endif


/**
* @brief Do unlock Transient configuration
* @details Function write key to unlock Transient Configuration
* 
*/
/* @violates @ref Mcem_Fccu_c_REF_8 Public API */
FUNC(void, MCEM_CODE) Mcem_Fccu_UnlockTrans( void )
{
    /* Unlock FCCU transient lock */
    /* @violates @ref Mcem_Fccu_c_REF_2 Pointer conversion */
    /* @violates @ref Mcem_Fccu_c_REF_5 Pointer conversion */
    REG_WRITE32(FCCU_TRANS_LOCK_ADDR32, FCCU_TRANS_LOCK_KEY_U32);
}

#define MCEM_STOP_SEC_CODE
/* @violates @ref Mcem_Fccu_c_REF_1 precautions to prevent the contents of a header file being included twice */
/* @violates @ref Mcem_Fccu_c_REF_4 only preprocessor statements and comments before "#include". */
#include "Mcem_MemMap.h"

#ifdef __cplusplus
}
#endif

/** @} */
