

/*
 **********************************************************************************************************************
 * Includes
 **********************************************************************************************************************
 */

#include "Fee.h"

/* Disable the Fee common part when the Fs1 is selected - currently the Fs1 is a complete Fee */
#if(defined(FEE_PRV_CFG_SELECTED_FS) && (1 != FEE_PRV_CFG_SELECTED_FS))

#include "Fee_Prv.h"
#include "Fee_Cfg_SchM.h"

# if (STD_ON == FEE_DEV_ERROR_DETECT)
#include "Det.h"
# endif

/*
 **********************************************************************************************************************
 * Defines/Macros
 **********************************************************************************************************************
*/

/* Protection selectable via Fee_Cfg_SchM.h to save code */
# ifndef FEE_RB_USE_PROTECTION
#define FEE_RB_USE_PROTECTION   (TRUE)
# endif


/* Temporary work around till the feature is made configurable */
# if (10 == FEE_PRV_CFG_SELECTED_FS)
/* For Fee1x, there is no delay in background task execution (same as Fee1.0) */
#define FEE_PRV_MFCALLS_BEFORE_BACKGROUND_ACTION (0u)
# else
/* Debounce active only for Fee2 and Fee3 */
#define FEE_PRV_MFCALLS_BEFORE_BACKGROUND_ACTION (100u)
# endif

/*
 **********************************************************************************************************************
 * Variables
 **********************************************************************************************************************
 */

#define FEE_START_SEC_VAR_CLEARED_8
#include "Fee_MemMap.h"
/* Flag to hold the main function access status */
static volatile boolean Fee_Prv_flgUsedSema_vb;
/* Flag to hold the debug information, Reentrant MainFunction */
static volatile boolean Fee_Prv_dbgReentrantMainFunction_vb;
#define FEE_STOP_SEC_VAR_CLEARED_8
#include "Fee_MemMap.h"

#define FEE_START_SEC_VAR_CLEARED_16
#include "Fee_MemMap.h"
/* Do not start directly with expensive maintenance actions */
static uint16 Fee_Prv_BackgroundDebounceCntr_u16;
#define FEE_STOP_SEC_VAR_CLEARED_16
#include "Fee_MemMap.h"

#define FEE_START_SEC_VAR_CLEARED_UNSPECIFIED
#include "Fee_MemMap.h"
static Fee_Rb_WorkingStateType_ten Fee_Prv_WorkingState_en;
#define FEE_STOP_SEC_VAR_CLEARED_UNSPECIFIED
#include "Fee_MemMap.h"

#define FEE_START_SEC_VAR_INIT_UNSPECIFIED
#include "Fee_MemMap.h"
Fee_Prv_DriverState_ten Fee_Prv_DriverState_en    = FEE_PRV_DRIVERSTATE_UNINIT_E;
MemIf_ModeType          Fee_Prv_DriverModeActv_en = MEMIF_MODE_SLOW;
#if (FEE_AR_RELEASE_MAJOR_VERSION == 4) && (FEE_AR_RELEASE_MINOR_VERSION >=4)
/* From Autosar 4.4 and newer */
MemIf_ModeType          Fee_Prv_DriverModeReqd_en = MEMIF_MODE_SLOW;
#endif
#define FEE_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "Fee_MemMap.h"

#define FEE_START_SEC_VAR_INIT_UNSPECIFIED
#include "Fee_MemMap.h"
/* Pointer to the order which is currently being processed */
static Fee_Prv_OrderJob_tst * Fee_Prv_ProcCurrentOrder_pcst = NULL_PTR;
/* Background operations are not allowed */
static Fee_Prv_BackgroundState_ten Fee_Prv_BackgroundState_en = FEE_PRV_BACKGROUNDSTATE_DISABLED;
#define FEE_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "Fee_MemMap.h"

/*
 **********************************************************************************************************************
 * Static Declaration
 **********************************************************************************************************************
 */

#define FEE_START_SEC_CODE
#include "Fee_MemMap.h"


/*
 **********************************************************************************************************************
 * Inline declarations
 **********************************************************************************************************************
*/

LOCAL_INLINE void Fee_Prv_ProcAcceptNewJob(void);
LOCAL_INLINE Fee_Prv_DriverState_ten Fee_Prv_ProcStartNewJob(void);
LOCAL_INLINE MemIf_JobResultType Fee_Prv_ProcProcessCurrentJob(void);
LOCAL_INLINE MemIf_JobResultType Fee_Prv_ProcProcessIdle(void);
LOCAL_INLINE void Fee_Prv_ProcInitResetAllVariables(void);
LOCAL_INLINE boolean Fee_Prv_TryToGetLock(void);
LOCAL_INLINE void Fee_Prv_ReleaseLock(void);
LOCAL_INLINE void Fee_Prv_MainFunctionIntern(void);
LOCAL_INLINE Fee_Rb_WorkingStateType_ten Fee_Prv_ProcCalcWorkingState(void);

/*
 **********************************************************************************************************************
 * Implementation
 **********************************************************************************************************************
 */

/*
 * \brief   Checks global flag for re-entrant invocation of main function, and reports such error to DET if enabled.
 *
 * \return  Availability of lock
 * \retval  TRUE  if lock is available, i.e. no re-entrant invocation of main function.
 * \retval  FALSE if lock is not available, i.e. re-entrant invocation of main function.
 */
LOCAL_INLINE boolean Fee_Prv_TryToGetLock(void)
{
    /* Return variable */
    boolean isLockAvailable_b = FALSE;

# if(FEE_RB_USE_PROTECTION != FALSE)
    /* Disable interrupts */
    SchM_Enter_Fee_Order();
# endif

    /* Is the main function not invoked yet? */
    if(!Fee_Prv_flgUsedSema_vb)
    {
        /* Reserve it and allow its execution */
        Fee_Prv_flgUsedSema_vb = TRUE;
        isLockAvailable_b = TRUE;
    }

# if(FEE_RB_USE_PROTECTION != FALSE)
    /* Enable interrupts */
    SchM_Exit_Fee_Order();
# endif

    /* Re-entrant invocation of main function? */
    if(!isLockAvailable_b)
    {
        /* Set the debug flag for the detection of reentrant main function */
        Fee_Prv_dbgReentrantMainFunction_vb = TRUE;

        Fee_Prv_LibDetReport(FEE_SID_MAINFUNCTION, FEE_E_BUSY);
    }

# if(FEE_RB_USE_PROTECTION == FALSE)
    /* Protection disabled, only detection by default */
    isLockAvailable_b = TRUE;
# endif

    return(isLockAvailable_b);
}

/**
 * \brief   Resets the flag having re-entrant information.
 */
LOCAL_INLINE void Fee_Prv_ReleaseLock(void)
{
    /* Reset the access flag */
    Fee_Prv_flgUsedSema_vb = FALSE;

    return;
}

/*
 * \brief   Disables execution of background operations.
 */
void Fee_Prv_ProcDisableBackground(void)
{
    Fee_Prv_BackgroundState_en = FEE_PRV_BACKGROUNDSTATE_DISABLED;

    return;
}

/*
 * \brief   Enables execution of background operations.
 */
void Fee_Prv_ProcEnableBackground(void)
{
    Fee_Prv_BackgroundState_en = FEE_PRV_BACKGROUNDSTATE_ENABLED_ACTIVE;

    return;
}

/*
 * \brief   The main function does the actual work of the Fee. The more often it is scheduled the faster the Fee is.
 */
void Fee_MainFunction(void)
{
    /* Local flag to store the lock accuring status */
    boolean flgUsed_b = FALSE;

    /* Check for re-entrant invocation of main function */
    flgUsed_b = Fee_Prv_TryToGetLock();

    /* Lock obtained, i.e. no re-entrant invocation of main function? */
    if(flgUsed_b)
    {
        /* Main function can be invoked */
        Fee_Prv_MainFunctionIntern();

        /* Release the lock */
        Fee_Prv_ReleaseLock();
    }

    return;
}

/*
 * \brief   The internal main function does the actual work of the Fee.
 */
LOCAL_INLINE void Fee_Prv_MainFunctionIntern(void)
{
    /* Local variable */
    MemIf_JobResultType result_en = MEMIF_JOB_PENDING;

    /*
     * Measure main function execution time.
     * Attention: The result is not the actual time the main function really needed since it can be interrupted.
     *            Nevertheless it is a good indicator for debugging purposes.
     */
    Fee_Prv_DbgWatchStart(&Fee_Prv_DbgInfo_st.time_st.procMain_st);

    /* Reset the effort limitation */
    Fee_Prv_LibEffortReset();

    /*
     * Get the next order from the order unit.
     * Prioritization is done by the order unit, NvM has higher priority before any adapter.
     */
    if(NULL_PTR == Fee_Prv_ProcCurrentOrder_pcst)
    {
        /* If currently no job is active, accept new one and cancel ongoing background activity */
        Fee_Prv_ProcAcceptNewJob();
    }

    /* Check whether a new order can be started */
    if(FEE_PRV_DRIVERSTATE_IDLE_E == Fee_Prv_DriverState_en)
    {
# if (FEE_AR_RELEASE_MAJOR_VERSION == 4) && (FEE_AR_RELEASE_MINOR_VERSION >=4) && (STD_ON == FEE_SET_MODE_SUPPORTED)
        /* From Autosar 4.4 and newer */
        if(Fee_Prv_DriverModeActv_en != Fee_Prv_DriverModeReqd_en)
        {
            Fee_Prv_OrderSetMode(Fee_Prv_DriverModeReqd_en);
        }
# endif
        /* A new order is available? */
        if(NULL_PTR != Fee_Prv_ProcCurrentOrder_pcst)
        {
            /* Background enabled but sleeping? */
            if(FEE_PRV_BACKGROUNDSTATE_ENABLED_SLEEPING == Fee_Prv_BackgroundState_en)
            {
                /* Activate background */
                Fee_Prv_BackgroundState_en = FEE_PRV_BACKGROUNDSTATE_ENABLED_ACTIVE;
            }

            /* Wind up debounce counter */
            Fee_Prv_BackgroundDebounceCntr_u16 = FEE_PRV_MFCALLS_BEFORE_BACKGROUND_ACTION;

            /* Start the order in the Fs and set the appropriate driver state */
            Fee_Prv_DriverState_en = Fee_Prv_ProcStartNewJob();
        }
    }

    /* Based on the driver state left the Fs do the work */
    result_en = Fee_Prv_ProcProcessCurrentJob();

    /*
     * In case the driver state is not already IDLE and result is not MEMIF_JOB_PENDING any more,
     * reset the driver state to IDLE
     */
    if((FEE_PRV_DRIVERSTATE_IDLE_E != Fee_Prv_DriverState_en) &&
       (MEMIF_JOB_PENDING          != result_en))
    {
        /* If an order was finished inform the order unit */
        if((NULL_PTR                           != Fee_Prv_ProcCurrentOrder_pcst) &&
           (FEE_PRV_DRIVERSTATE_BACKGROUND_E   != Fee_Prv_DriverState_en       ))
        {
            Fee_Prv_OrderEnd(Fee_Prv_ProcCurrentOrder_pcst, result_en);
        }

        /* In case of Stop mode, do not put the state machine back to idle. */
        if(FEE_PRV_DRIVERSTATE_ENTER_STOP_MODE_E != Fee_Prv_DriverState_en)
        {
            Fee_Prv_ProcCurrentOrder_pcst   = NULL_PTR;
            Fee_Prv_DriverState_en          = FEE_PRV_DRIVERSTATE_IDLE_E;
        }
    }

    /* Background enabled? */
    if(FEE_PRV_BACKGROUNDSTATE_DISABLED != Fee_Prv_BackgroundState_en)
    {
        /* Execute cyclic debugging actions */
        Fee_Prv_DbgMainFunction();
    }

    /* Call working state calculation and set private copy */
    Fee_Prv_WorkingState_en = Fee_Prv_ProcCalcWorkingState();

    /* Stop timing measurement of main function */
    Fee_Prv_DbgWatchStop(&Fee_Prv_DbgInfo_st.time_st.procMain_st, FALSE);

    return;
}

/*
 * \brief   Asks the order unit for an available order and cancels an ongoing background activity.
 */
LOCAL_INLINE void Fee_Prv_ProcAcceptNewJob(void)
{
    Fee_Prv_ProcCurrentOrder_pcst = Fee_Prv_OrderBegin();

    /* Order available and background activity ongoing? */
    if( (NULL_PTR != Fee_Prv_ProcCurrentOrder_pcst) && (FEE_PRV_DRIVERSTATE_BACKGROUND_E == Fee_Prv_DriverState_en) )
    {
        /* Cancel background activity */
        Fee_Prv_FsIfCancel();
    }

    return;
}

/*
 * \brief   Starts the order requested from the order unit by triggering the filesystem specific handler function.
 *
 * \return  New driver state for processing the order.
 */
LOCAL_INLINE Fee_Prv_DriverState_ten Fee_Prv_ProcStartNewJob(void)
{
    /* Return variable */
    Fee_Prv_DriverState_ten stNewFeeDriverState_en;

    /* Check pending order type */
    switch(Fee_Prv_ProcCurrentOrder_pcst->type_en)
    {
        /* Start processing read order */
        case FEE_PRV_ORDERTYPE_READ_E:
        {
            Fee_Prv_FsIfRead(Fee_Prv_ProcCurrentOrder_pcst);
            stNewFeeDriverState_en = FEE_PRV_DRIVERSTATE_READ_E;
        }
        break;

        /* Start processing write order */
        case FEE_PRV_ORDERTYPE_WRITE_E:
        {
            Fee_Prv_FsIfWrite(Fee_Prv_ProcCurrentOrder_pcst);
            stNewFeeDriverState_en = FEE_PRV_DRIVERSTATE_WRITE_E;
        }
        break;

        /* Start processing invalidation order */
        case FEE_PRV_ORDERTYPE_INVALIDATE_E:
        {
            Fee_Prv_FsIfInvalidateBlock(Fee_Prv_ProcCurrentOrder_pcst);
            stNewFeeDriverState_en = FEE_PRV_DRIVERSTATE_INVALIDATEBLOCK_E;
        }
        break;

        /* Start processing block maintenance order */
        case FEE_PRV_ORDERTYPE_BLOCKMAINTENANCE_E:
        {
            Fee_Prv_FsIfRbMaintainBlock(Fee_Prv_ProcCurrentOrder_pcst);
            stNewFeeDriverState_en = FEE_PRV_DRIVERSTATE_BLOCKMAINTENANCE_E;
        }
        break;

        /* Trigger a reorganization */
        case FEE_PRV_ORDERTYPE_TRIGGERREORG_E:
        {
            Fee_Prv_FsIfRbTriggerReorg();
            stNewFeeDriverState_en = FEE_PRV_DRIVERSTATE_TRIGGERREORG_E;
        }
        break;

        /* Enter into stop mode */
        case FEE_PRV_ORDERTYPE_ENTER_STOP_MODE_E:
        {
            stNewFeeDriverState_en = FEE_PRV_DRIVERSTATE_ENTER_STOP_MODE_E;
        }
        break;

        /* Invalid order */
        default:
        {
            Fee_Prv_OrderEnd(Fee_Prv_ProcCurrentOrder_pcst, MEMIF_JOB_FAILED);
            stNewFeeDriverState_en = FEE_PRV_DRIVERSTATE_IDLE_E;
        }
        break;
    }

    return(stNewFeeDriverState_en);
}

/*
 * \brief   Processes the current job based on the selected Fee_Prv_DriverState_en.
 *
 * \return  Forwards the return value of the called filesystem specific function.
 */
LOCAL_INLINE MemIf_JobResultType Fee_Prv_ProcProcessCurrentJob(void)
{
    /* Return variable */
    MemIf_JobResultType result_en;

    switch(Fee_Prv_DriverState_en)
    {
        case FEE_PRV_DRIVERSTATE_IDLE_E:                result_en = Fee_Prv_ProcProcessIdle();          break;
        case FEE_PRV_DRIVERSTATE_BACKGROUND_E:          result_en = Fee_Prv_FsIfBackground();           break;
        case FEE_PRV_DRIVERSTATE_READ_E:                result_en = Fee_Prv_FsIfReadDo();               break;
        case FEE_PRV_DRIVERSTATE_WRITE_E:               result_en = Fee_Prv_FsIfWriteDo();              break;
        case FEE_PRV_DRIVERSTATE_INVALIDATEBLOCK_E:     result_en = Fee_Prv_FsIfInvalidateBlockDo();    break;
        case FEE_PRV_DRIVERSTATE_BLOCKMAINTENANCE_E:    result_en = Fee_Prv_FsIfRbMaintainBlockDo();    break;
        case FEE_PRV_DRIVERSTATE_TRIGGERREORG_E:        result_en = Fee_Prv_FsIfRbTriggerReorgDo();     break;
        case FEE_PRV_DRIVERSTATE_ENTER_STOP_MODE_E:     result_en = MEMIF_JOB_OK;                       break;
        default:                                        result_en = MEMIF_JOB_FAILED;                   break;
    }

    return (result_en);
}

/*
 * \brief   Gets called if the Fee is idle. If background is active, ask the Fs for required background activities.
 *
 * \return  Forwards the return value of the called filesystem specific background function.
 */
LOCAL_INLINE MemIf_JobResultType Fee_Prv_ProcProcessIdle(void)
{
    /* Return variable */
    MemIf_JobResultType result_en;

    /* In case the Fee is currently IDLE, check whether any maintenance functions can be executed in the background */
    if(FEE_PRV_BACKGROUNDSTATE_ENABLED_ACTIVE == Fee_Prv_BackgroundState_en)
    {
        /* Debouncing done? */
        if(0u == Fee_Prv_BackgroundDebounceCntr_u16)
        {
            /* Call Fs-specific background function */
            result_en = Fee_Prv_FsIfBackground();

            /* Fs-specific background function has already completed successfully? */
            if(MEMIF_JOB_OK == result_en)
            {
                /* Put background operations back to sleep */
                Fee_Prv_BackgroundState_en = FEE_PRV_BACKGROUNDSTATE_ENABLED_SLEEPING;
            }
            /* Fs-specific background function not yet complete? */
            else if(MEMIF_JOB_PENDING == result_en)
            {
                /* Continue the Fs-specific background processing */
                Fee_Prv_DriverState_en = FEE_PRV_DRIVERSTATE_BACKGROUND_E;
            }
            /* Fs-specific background function has failed? */
            else
            {
                /* Do nothing */
            }
        }
        /* Debouncing not yet done? */
        else
        {
            /* Before starting a background action, debounce a little to ensure that it does not start immediately */
            Fee_Prv_BackgroundDebounceCntr_u16--;
            result_en = MEMIF_JOB_OK;
        }
    }
    else
    {
        /* FEE_PRV_BACKGROUNDSTATE_DISABLED / FEE_PRV_BACKGROUNDSTATE_ENABLED_SLEEPING : Do nothing */
        result_en = MEMIF_JOB_OK;
    }

    return(result_en);
}

/*
 * \brief   Initializes the Fee.
 *
 * \param   ConfigPtr: Reference to postbuild variant. Has to be NULL_PTR because the Fee is not postbuild selectable.
 */

# if (FEE_AR42_API_COMPLIANCE == STD_ON)
/*MR12 RULE 8.13 VIOLATION: AR4.2 defines this function prototype with a non-constant pointer*/
void Fee_Init(Fee_ConfigType const * ConfigPtr)
# else
void Fee_Init(void)
# endif
{
    /* Ignore AR4.2 Config Pointer because Postcompile configuration is not possible */
# if (FEE_AR42_API_COMPLIANCE == STD_ON)
    (void)ConfigPtr;
# endif

    /* Reset variables inside Fee common component */
    Fee_Prv_ProcInitResetAllVariables();

    /* Measure the filesystem init time */
    Fee_Prv_DbgWatchStart(&Fee_Prv_DbgInfo_st.time_st.procInit_st);

    Fee_Prv_DriverState_en = FEE_PRV_DRIVERSTATE_INIT_E;

    /* Do not limit the effort to spend in the init - full speed is required */
    Fee_Prv_LibUseEffortLimit(FALSE);

    /*
     * Set the medium synchronous.
     * That means the flash is polled and Fls_MainFunction calls are triggered until flash jobs are finished.
     */
    Fee_Prv_MediumSetSync(TRUE);

    /* Initialize the file system - this will take the most time */
    if(E_OK == Fee_Prv_FsIfInit())
    {
        /* Finally set the driver state to IDLE */
        Fee_Prv_DriverState_en = FEE_PRV_DRIVERSTATE_IDLE_E;

        Fee_Prv_DbgWatchStop(&Fee_Prv_DbgInfo_st.time_st.procInit_st, FALSE);

        /* If enabled read the debug block */
        Fee_Prv_DbgBlockRead();

        /* Stop the system if a block was lost */
        Fee_Prv_DbgCheckLayout();

        /* Disable sync mode operation */
        Fee_Prv_MediumSetSync(FALSE);
    }
    else
    {
        /* Driver init was not successful --> uninit the Fee */
        Fee_Prv_DriverState_en = FEE_PRV_DRIVERSTATE_UNINIT_E;

        /* Report DET error */
        Fee_Prv_OrderDetModuleInitFail(FEE_SID_INIT);
    }

    return;
}

/*
 * \brief   Calls the unit specific init functions for resetting all units' variables.
 */
LOCAL_INLINE void Fee_Prv_ProcInitResetAllVariables(void)
{
    /* Reset this unit's variables */
    Fee_Prv_ProcCurrentOrder_pcst      = NULL_PTR;
    Fee_Prv_DriverState_en             = FEE_PRV_DRIVERSTATE_UNINIT_E;
    Fee_Prv_DriverModeActv_en          = MEMIF_MODE_SLOW;
    Fee_Prv_BackgroundDebounceCntr_u16 = FEE_PRV_MFCALLS_BEFORE_BACKGROUND_ACTION;
    Fee_Prv_ProcDisableBackground();

    /* Reset other units' variables */
    Fee_Prv_DbgInit();
    Fee_Prv_LibInit();
    Fee_Prv_MediumInit();
    Fee_Prv_OrderInit();

    return;
}

/*
 * \brief   Mark end of the Fee init. After calling this function background activities are allowed.
 *          Also the Fee is set in a more cooperative mode to make sure task duration constraints are not violated.
 */
void Fee_Rb_EndInit(void)
{
    /* Fee shall be initalized when calling this function */
    if(E_OK == Fee_Prv_OrderDetCheckModuleInit(FEE_SID_RB_END_INIT))
    {
        Fee_Prv_LibUseEffortLimit(TRUE);
        Fee_Prv_ProcEnableBackground();
    }

    return;
}

/*
 * \brief   Calculates the current Fee working state.
 */
LOCAL_INLINE Fee_Rb_WorkingStateType_ten Fee_Prv_ProcCalcWorkingState(void)
{
    Fee_Rb_WorkingStateType_ten stRetVal_en;
    Fee_Prv_DriverState_ten stFeeDriverState_en = Fee_Prv_DriverState_en;

    switch(stFeeDriverState_en)
    {
        case FEE_PRV_DRIVERSTATE_UNINIT_E:
        case FEE_PRV_DRIVERSTATE_INIT_E:
        case FEE_PRV_DRIVERSTATE_IDLE_E:
        {
            stRetVal_en = FEE_RB_IDLE_E;
        }
        break;

        case FEE_PRV_DRIVERSTATE_READ_E:
        {
            stRetVal_en = FEE_RB_READ_MODE_E;
        }
        break;

        case FEE_PRV_DRIVERSTATE_ENTER_STOP_MODE_E:
        {
            stRetVal_en = FEE_RB_STOPMODE_E;
        }
        break;

        case FEE_PRV_DRIVERSTATE_BACKGROUND_E:
        {
            // check if background erase operation is ongoing
            if(Fee_Prv_FsIfRbIsSectorEraseOngoing())
            {
                stRetVal_en = FEE_RB_SECTOR_ERASE_E;
            }
            // check if background soft reorganisation operation is ongoing
            else if (Fee_Prv_FsIfRbIsSoftReorgOngoing())
            {
                stRetVal_en = FEE_RB_SOFT_SECTOR_REORG_MODE_E;
            }
            else
            {
                stRetVal_en = FEE_RB_IDLE_E;
            }
        }
        break;

        /* FEE_PRV_DRIVERSTATE_WRITE_E */
        /* FEE_PRV_DRIVERSTATE_INVALIDATEBLOCK_E */
        /* FEE_PRV_DRIVERSTATE_BLOCKMAINTENANCE_E */
        /* FEE_PRV_DRIVERSTATE_TRIGGERREORG_E */
        default:
        {
            /* check for hard reorg, because this can happen during a write, invalidate or maintain job */
            if(Fee_Prv_FsIfRbIsHardReorgOngoing())
            {
                stRetVal_en = FEE_RB_HARD_SECTOR_REORG_MODE_E;
            }
            else if(Fee_Prv_FsIfRbIsSectorEraseOngoing())
            {
                stRetVal_en = FEE_RB_SECTOR_ERASE_E;
            }
            else
            {
                switch(stFeeDriverState_en)
                {
                    case FEE_PRV_DRIVERSTATE_WRITE_E:
                    {
                        /* all FSx */
                        stRetVal_en = FEE_RB_WRITE_MODE_E;
                    }
                    break;
                    case FEE_PRV_DRIVERSTATE_INVALIDATEBLOCK_E:
                    {
                        /* all FSx */
                        stRetVal_en = FEE_RB_INVALIDATE_MODE_E;
                    }
                    break;
                    case FEE_PRV_DRIVERSTATE_BLOCKMAINTENANCE_E:
                    {
                        /* FS1x + FS3 only */
                        stRetVal_en = FEE_RB_MAINTAIN_MODE_E;
                    }
                    break;
                    /* FEE_PRV_DRIVERSTATE_TRIGGERREORG_E - Fs1x only */
                    default:
                    {
                        stRetVal_en = FEE_RB_IDLE_E;
                    }
                    break;
                }
            }
        }
        break;
    }

    return(stRetVal_en);
}

/*
 * \brief   Returns the current Fee working state.
 */
Fee_Rb_WorkingStateType_ten Fee_Rb_GetWorkingState(void)
{
    Fee_Rb_WorkingStateType_ten stRetVal_en;

    if(E_OK == Fee_Prv_OrderDetCheckModuleInit(FEE_SID_RB_GET_WORKING_STATE))
    {
        stRetVal_en = Fee_Prv_WorkingState_en;
    }
    else
    {
        stRetVal_en = FEE_RB_IDLE_E;
    }

    return(stRetVal_en);
}

#define FEE_STOP_SEC_CODE
#include "Fee_MemMap.h"

/* 1 != FEE_PRV_CFG_SELECTED_FS */
#endif
