/**
*   @file    Fls_Ac.c
*   @implements Fls_Ac.c_Artifact 
*   @version 1.0.0
*
*   @brief   AUTOSAR Fls - AUTOSAR Module Flash Driver.
*   @details Position independent erase and write access code.
*
*   @addtogroup FLS
*   @{
*/
/*==================================================================================================
*   Project              : AUTOSAR 4.3 MCAL
*   Platform             : PA
*   Peripheral           : IPV_FLASHV2
*   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:2012 violations
*
* @section Fls_Ac_c_REF_1
* Violates MISRA 2012 Required Directive 4.10, Precautions shall be taken in order to prevent the contents of a header file being included more than once.
* This violation is not fixed since the inclusion of <MA>_MemMap.h is as per AUTOSAR requirement [SWS_MemMap_00003].
*
* @section Fls_Ac_c_REF_2
* Violates MISRA 2012 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type.
* The cast is used to access memory mapped registers.
*
* @section Fls_Ac_c_REF_3
* Violates MISRA 2012 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type.
* This violation is due to casting unsigned long to pointer and access these addresses for updating  contents in that address.
*
* @section Fls_Ac_c_REF_4
* Violates MISRA 2012 Advisory Rule 20.1, #Include directives should only be preceded by preprocessor directives or comments.
* <MA>_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR.
*
* @section Fls_Ac_c_REF_5
* Violates MISRA 2012 Required Rule 10.8, The value of a composite expression shall not be cast to a different essential 
* type category or a wider essential type.
* This violation is due to the complex expression (macro) is given as parameter is not evaluated at preprocessing step.
*
* @section Fls_Ac_c_REF_6
* Violates MISRA 2012 Required Rule 8.5, An external object or function shall be declared once in one and only one file
* Because there is need to put the declaration into Fls_Cfg.c and made it accessible for all modules which includes Fls.h/Fls_Cfg.h
*
* @section Fls_Ac_c_REF_7
* Violates MISRA 2012 Advisory Rule 8.7, Functions and objects should not be defined with external linkage if they are referenced in only one translateion unit.
* External linkage required for a global function.
*/


/*==================================================================================================
                                         INCLUDE FILES
 1) system and project includes
 2) needed interfaces from external units
 3) internal and external interfaces from this unit
==================================================================================================*/
#include "Fls.h"
#include "Reg_eSys_FLASHC.h"
#include "StdRegMacros.h"
#if ( (FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON) && (STD_OFF == FLS_TIMEOUT_AS_LOOP) )
#include "Fls_Flash.h"
#endif /* #if ((STD_OFF == FLS_TIMEOUT_AS_LOOP) && (FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON)) */
/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#define FLS_AC_VENDOR_ID_C                      43
#define FLS_AC_AR_RELEASE_MAJOR_VERSION_C       4
#define FLS_AC_AR_RELEASE_MINOR_VERSION_C       3
#define FLS_AC_AR_RELEASE_REVISION_VERSION_C    1
#define FLS_AC_SW_MAJOR_VERSION_C               1
#define FLS_AC_SW_MINOR_VERSION_C               0
#define FLS_AC_SW_PATCH_VERSION_C               0

/*==================================================================================================
*                                     FILE VERSION CHECKS
==================================================================================================*/
/* Check if current file and Fls header file are of the same vendor */
#if (FLS_AC_VENDOR_ID_C != FLS_VENDOR_ID)
    #error "Fls_Ac.c and Fls.h have different vendor ids"
#endif
/* Check if current file and Fls_Ac header file are of the same Autosar version */
#if ((FLS_AC_AR_RELEASE_MAJOR_VERSION_C    != FLS_AR_RELEASE_MAJOR_VERSION) || \
     (FLS_AC_AR_RELEASE_MINOR_VERSION_C    != FLS_AR_RELEASE_MINOR_VERSION) || \
     (FLS_AC_AR_RELEASE_REVISION_VERSION_C != FLS_AR_RELEASE_REVISION_VERSION) \
    )
    #error "AutoSar Version Numbers of Fls_Ac.c and Fls.h are different"
#endif
/* Check if current file and Fls header file are of the same Software version */
#if ((FLS_AC_SW_MAJOR_VERSION_C != FLS_SW_MAJOR_VERSION) || \
     (FLS_AC_SW_MINOR_VERSION_C != FLS_SW_MINOR_VERSION) || \
     (FLS_AC_SW_PATCH_VERSION_C != FLS_SW_PATCH_VERSION) \
    )
    #error "Software Version Numbers of Fls_Ac.c and Fls.h are different"
#endif

/* Check if current file and Reg_eSys_FLASHC header file are of the same vendor */
#if (FLS_AC_VENDOR_ID_C != ESYS_FLASHC_VENDOR_ID)
    #error "Fls_Ac.c and Reg_eSys_FLASHC.h have different vendor ids"
#endif
/* Check if current file and Reg_eSys_FLASHC header file are of the same Autosar version */
#if ((FLS_AC_AR_RELEASE_MAJOR_VERSION_C    != ESYS_FLASHC_AR_RELEASE_MAJOR_VERSION) || \
     (FLS_AC_AR_RELEASE_MINOR_VERSION_C    != ESYS_FLASHC_AR_RELEASE_MINOR_VERSION) || \
     (FLS_AC_AR_RELEASE_REVISION_VERSION_C != ESYS_FLASHC_AR_RELEASE_REVISION_VERSION) \
    )
    #error "AutoSar Version Numbers of Fls_Ac.c and Reg_eSys_FLASHC.h are different"
#endif
/* Check if current file and Reg_eSys_FLASHC header file are of the same Software version */
#if ((FLS_AC_SW_MAJOR_VERSION_C != ESYS_FLASHC_SW_MAJOR_VERSION) || \
     (FLS_AC_SW_MINOR_VERSION_C != ESYS_FLASHC_SW_MINOR_VERSION) || \
     (FLS_AC_SW_PATCH_VERSION_C != ESYS_FLASHC_SW_PATCH_VERSION) \
    )
    #error "Software Version Numbers of Fls_Ac.c and Reg_eSys_FLASHC.h are different"
#endif

/* Check if current file and StdRegMacros header file are of the same Autosar version */
#if ((FLS_AC_AR_RELEASE_MAJOR_VERSION_C    != STDREGMACROS_AR_RELEASE_MAJOR_VERSION) || \
     (FLS_AC_AR_RELEASE_MINOR_VERSION_C    != STDREGMACROS_AR_RELEASE_MINOR_VERSION)  \
    )
    #error "AutoSar Version Numbers of Fls_Ac.c and StdRegMacros.h are different"
#endif
#if ( (FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON) && (STD_OFF == FLS_TIMEOUT_AS_LOOP) )
/* Check if current file and Fls_Flash header file are of the same Autosar version */
#if ((FLS_AC_SW_MAJOR_VERSION_C    != FLS_FLASH_SW_MAJOR_VERSION) || \
     (FLS_AC_SW_MINOR_VERSION_C    != FLS_FLASH_SW_MINOR_VERSION) || \
     (FLS_AC_SW_PATCH_VERSION_C    != FLS_FLASH_SW_PATCH_VERSION) \
    )
    #error "AutoSar Version Numbers of Fls_Ac.c and Fls_Flash.h are different"
#endif
#endif /*#if ((STD_OFF == FLS_TIMEOUT_AS_LOOP) && (FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON))*/
/*==================================================================================================
                                       GLOBAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
                                     FUNCTION PROTOTYPES
==================================================================================================*/
/**
* @brief    Start of Fls section CODE_AC 
*
*/
#define FLS_START_SEC_CODE_AC
/* @violates @ref Fls_Ac_c_REF_1 Precautions shall be taken in order to prevent the contents of a header file being included more than once */
#include "Fls_MemMap.h"

#ifdef _LINARO_C_MPC5777C_ 
    #if (FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON)
    /* @violates @ref Fls_Ac_c_REF_6 An external object or function shall be declared once in one and only one file */
    void Fls_Flash_AccessCode( CONST(uint32, AUTOMATIC) u32RegBaseAddr, P2FUNC(void, FLS_CODE, CallBack)( void ), P2VAR(uint32, AUTOMATIC, FLS_CODE) pTimerCounterAC, P2VAR(uint32, AUTOMATIC, FLS_CODE) pTimerCounterAbort ) __attribute__ ((section (".acfls_code_rom")));
    #else
    /* @violates @ref Fls_Ac_c_REF_6 An external object or function shall be declared once in one and only one file */
    void Fls_Flash_AccessCode( CONST(uint32, AUTOMATIC) u32RegBaseAddr, P2FUNC(void, FLS_CODE, CallBack)( void ) ) __attribute__ ((section (".acfls_code_rom")));
    #endif /* FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON */
#else
    #if (FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON)
    /* @violates @ref Fls_Ac_c_REF_6 An external object or function shall be declared once in one and only one file */
    void Fls_Flash_AccessCode( CONST(uint32, AUTOMATIC) u32RegBaseAddr, P2FUNC(void, FLS_CODE, CallBack)( void ), P2VAR(uint32, AUTOMATIC, FLS_CODE) pTimerCounterAC, P2VAR(uint32, AUTOMATIC, FLS_CODE) pTimerCounterAbort );
    #else
    /* @violates @ref Fls_Ac_c_REF_6 An external object or function shall be declared once in one and only one file */
    void Fls_Flash_AccessCode( CONST(uint32, AUTOMATIC) u32RegBaseAddr, P2FUNC(void, FLS_CODE, CallBack)( void ) );
    #endif /* FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON */
#endif
/*==================================================================================================
                                      GLOBAL FUNCTIONS
==================================================================================================*/
/* Position independent erase access code */
#if (FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON)
/* @violates @ref Fls_Ac_c_REF_7 Functions and objects should not be defined with external linkage if they are referenced in only one translateion unit.*/
void Fls_Flash_AccessCode( CONST(uint32, AUTOMATIC) u32RegBaseAddr, P2FUNC(void, FLS_CODE, CallBack)( void ), P2VAR(uint32, AUTOMATIC, FLS_CODE) pTimerCounterAC, P2VAR(uint32, AUTOMATIC, FLS_CODE) pTimerCounterAbort )
{
    /* start internal erase/program sequence */
    /* 
    * @violates @ref Fls_Ac_c_REF_2 A conversion should not be performed between a pointer to object and an integer type 
    * @violates @ref Fls_Ac_c_REF_3 A cast shall not be performed between pointer to void and an arithmetic type 
    * @violates @ref Fls_Ac_c_REF_5 The value of a composite expression shall not be cast to a different essential 
    * type category or a wider essential type
    */
    REG_BIT_SET32(u32RegBaseAddr + FLASH_MCR_OFFSET, FLASH_MCR_EHV_U32 );
    #if ((FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON) && (STD_OFF == FLS_TIMEOUT_AS_LOOP))
    /* Return  the  current  tick value of the counter via <Value> */
    (void)GetCounterValue((CounterType)FLS_TIMEOUT_COUNTER_NAME, &Fls_u32CurrentValue);
    #endif
    /* wait until operation finishes or write/erase timeout is reached */
    /* 
    * @violates @ref Fls_Ac_c_REF_2 A conversion should not be performed between a pointer to object and an integer type 
    * @violates @ref Fls_Ac_c_REF_3 A cast shall not be performed between pointer to void and an arithmetic type 
    * @violates @ref Fls_Ac_c_REF_5 The value of a composite expression shall not be cast to a different essential 
    * type category or a wider essential type
    */
    while((0U == REG_BIT_GET32(u32RegBaseAddr + FLASH_MCR_OFFSET, FLASH_MCR_DONE_U32 )) && (0U < *pTimerCounterAC))
    {
        #if (STD_OFF == FLS_TIMEOUT_AS_LOOP)
        /*
        * Gets the number of ticks between the current tick value and a previously read tick value.
        * And It shall also return  the  current  tick  value  of  the counter in the <Value> parameter
        */
        (void)GetElapsedValue((CounterType)FLS_TIMEOUT_COUNTER_NAME, &Fls_u32CurrentValue, &Fls_u32ElapsedTime);
        if ((*pTimerCounterAC) > Fls_u32ElapsedTime)
        {
            (*pTimerCounterAC) -= Fls_u32ElapsedTime;   
        }
        else
        {
            (*pTimerCounterAC) = 0U;
        }
        #else
        (*pTimerCounterAC)--;
        #endif
        if (NULL_PTR != CallBack) 
        {
            CallBack();
        }    
    }
    /* disable HV to finalize/abort the operation */
    /* 
    * @violates @ref Fls_Ac_c_REF_2 A conversion should not be performed between a pointer to object and an integer type 
    * @violates @ref Fls_Ac_c_REF_3 A cast shall not be performed between pointer to void and an arithmetic type 
    * @violates @ref Fls_Ac_c_REF_5 The value of a composite expression shall not be cast to a different essential 
    * type category or a wider essential type
    */
    REG_BIT_CLEAR32(u32RegBaseAddr + FLASH_MCR_OFFSET,FLASH_MCR_EHV_U32 );
    #if ((FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON) && (STD_OFF == FLS_TIMEOUT_AS_LOOP))
    /* Return  the  current  tick value of the counter via <Value> */
    (void)GetCounterValue((CounterType)FLS_TIMEOUT_COUNTER_NAME, &Fls_u32CurrentValue);
    #endif
    /* wait until done or abort timeout is reached */
    /* 
    * @violates @ref Fls_Ac_c_REF_2 A conversion should not be performed between a pointer to object and an integer type 
    * @violates @ref Fls_Ac_c_REF_3 A cast shall not be performed between pointer to void and an arithmetic type 
    * @violates @ref Fls_Ac_c_REF_5 The value of a composite expression shall not be cast to a different essential 
    * type category or a wider essential type
    */
    while((0U == REG_BIT_GET32(u32RegBaseAddr + FLASH_MCR_OFFSET, FLASH_MCR_DONE_U32 )) && (0U < *pTimerCounterAbort))
    {
        #if (STD_OFF == FLS_TIMEOUT_AS_LOOP)
        /*
        * Gets the number of ticks between the current tick value and a previously read tick value.
        * And It shall also return  the  current  tick  value  of  the counter in the <Value> parameter
        */
        (void)GetElapsedValue((CounterType)FLS_TIMEOUT_COUNTER_NAME, &Fls_u32CurrentValue, &Fls_u32ElapsedTime);
        if ((*pTimerCounterAbort) > Fls_u32ElapsedTime)
        {
            (*pTimerCounterAbort) -= Fls_u32ElapsedTime;     
        }
        else
        {
            (*pTimerCounterAbort) = 0U;
        }
        #else
        (*pTimerCounterAbort)--;
        #endif
        if (NULL_PTR != CallBack)
        {
            CallBack();
        }
    }
}
#else
/* @violates @ref Fls_Ac_c_REF_7 Functions and objects should not be defined with external linkage if they are referenced in only one translateion unit.*/
void Fls_Flash_AccessCode( CONST(uint32, AUTOMATIC) u32RegBaseAddr, P2FUNC(void, FLS_CODE, CallBack)( void ) )
{
    /* start internal erase/program sequence */
    /* 
    * @violates @ref Fls_Ac_c_REF_2 A conversion should not be performed between a pointer to object and an integer type 
    * @violates @ref Fls_Ac_c_REF_3 A cast shall not be performed between pointer to void and an arithmetic type 
    * @violates @ref Fls_Ac_c_REF_5 The value of a composite expression shall not be cast to a different essential 
    * type category or a wider essential type
    */
    REG_BIT_SET32(u32RegBaseAddr + FLASH_MCR_OFFSET, FLASH_MCR_EHV_U32 );

    /* wait until operation finishes or write/erase timeout is reached */
    /* 
    * @violates @ref Fls_Ac_c_REF_2 A conversion should not be performed between a pointer to object and an integer type 
    * @violates @ref Fls_Ac_c_REF_3 A cast shall not be performed between pointer to void and an arithmetic type 
    * @violates @ref Fls_Ac_c_REF_5 The value of a composite expression shall not be cast to a different essential 
    * type category or a wider essential type
    */
    while(0U == REG_BIT_GET32(u32RegBaseAddr + FLASH_MCR_OFFSET, FLASH_MCR_DONE_U32 ))
    {
        if (NULL_PTR != CallBack)
        {
            CallBack();
        }
    }

    /* disable HV to finalize/abort the operation */
    /* 
    * @violates @ref Fls_Ac_c_REF_2 A conversion should not be performed between a pointer to object and an integer type 
    * @violates @ref Fls_Ac_c_REF_3 A cast shall not be performed between pointer to void and an arithmetic type 
    * @violates @ref Fls_Ac_c_REF_5 The value of a composite expression shall not be cast to a different essential 
    * type category or a wider essential type
    */
    REG_BIT_CLEAR32(u32RegBaseAddr + FLASH_MCR_OFFSET,FLASH_MCR_EHV_U32 );
}
#endif /* FLS_TIMEOUT_SUPERVISION_ENABLED == STD_ON */

/**
* @brief    Stop of Fls section CODE_AC 
*
*/
#define FLS_STOP_SEC_CODE_AC
/* 
* @violates @ref Fls_Ac_c_REF_1 Precautions shall be taken in order to prevent the contents of a header file being included more than once 
* @violates @ref Fls_Ac_c_REF_4 #Include directives should only be preceded by preprocessor directives or comments
*/
#include "Fls_MemMap.h"

#ifdef __cplusplus
}
#endif
