
/*
 **********************************************************************************************************************
 * Includes
 **********************************************************************************************************************
 */
#include "NvM.h"
#include "NvM_Cfg_SchM.h"

#include "NvM_Prv_Job.h"
#include "NvM_Prv_Crc.h"
#include "NvM_Prv_BlockData.h"
#include "NvM_Prv_JobResource.h"

/*
 **********************************************************************************************************************
 * Declarations
 **********************************************************************************************************************
 */
#define NVM_START_SEC_CODE
#include "NvM_MemMap.h"

static void NvM_Prv_JobRecalcRamBlkCrc_DoCrc(NvM_Prv_stJob_ten* stJob_pen,
                                             NvM_Prv_JobResult_tst* JobResult_pst,
                                             NvM_Prv_JobData_tst const* JobData_pcst);

#define NVM_STOP_SEC_CODE
#include "NvM_MemMap.h"

/*
 **********************************************************************************************************************
 * Code
 **********************************************************************************************************************
 */
#define NVM_START_SEC_CODE
#include "NvM_MemMap.h"

NvM_Prv_Job_State_tpfct NvM_Prv_JobRecalcRamBlkCrc_GetStateFct(NvM_Prv_stJob_ten* stJob_pen)
{
    NvM_Prv_Job_State_tpfct JobRecalcRamBlkCrc_State_pfct = NULL_PTR;

    switch (*stJob_pen)
    {
        case NvM_Prv_stJob_Idle_e:
        case NvM_Prv_stRecalcRamBlkCrc_Do_e:
            JobRecalcRamBlkCrc_State_pfct = NvM_Prv_JobRecalcRamBlkCrc_DoCrc;
            // set job state to ease debugging and to avoid MISRA warning that stJob_pen can be a pointer to const
            *stJob_pen = NvM_Prv_stRecalcRamBlkCrc_Do_e;
        break;

        default:
            JobRecalcRamBlkCrc_State_pfct = NULL_PTR;
        break;
    }

    return JobRecalcRamBlkCrc_State_pfct;
}

static void NvM_Prv_JobRecalcRamBlkCrc_DoCrc(NvM_Prv_stJob_ten* stJob_pen,
                                             NvM_Prv_JobResult_tst* JobResult_pst,
                                             NvM_Prv_JobData_tst const* JobData_pcst)
{
    JobResult_pst->Result_en = NvM_Prv_JobResult_Succeeded_e;

#if (defined(NVM_CALC_RAM_BLOCK_CRC) && (NVM_CALC_RAM_BLOCK_CRC == STD_ON))

    *JobData_pcst->IntBuffer_st.UsedSizeInBytes_pu16 = NvM_Prv_GetBlockSize(JobData_pcst->idBlock_uo);
    NvM_Prv_JobResource_DoStateMachine(NvM_Prv_idJobResource_Crc_e, stJob_pen, JobResult_pst, JobData_pcst);
    *stJob_pen = NvM_Prv_stRecalcRamBlkCrc_Do_e;

    if (NvM_Prv_JobResult_Pending_e != JobResult_pst->Result_en)
    {
        // Recalculation finished -> update block status
        SchM_Enter_NvM_Main();

        if (NvM_Prv_Block_IsRamCrcRecalcPending(JobData_pcst->idBlock_uo))
        {
            // RAM block CRC recalculation was not interrupted by application ->
            // set calculated RAM block CRC
            uint8 maskBitsToChange_u8 = NVM_BLOCK_STATE_RAM_CRC_NEW_DATA | NVM_BLOCK_STATE_RAM_CRC_RECALC_PENDING;
            uint8 maskBitsNewValue_u8;

            if (NvM_Prv_Crc_CheckRamBlockCrc(JobData_pcst->idBlock_uo, &JobData_pcst->Crc_un))
            {
                // user has written the same data into the permanent RAM block
                // -> NvM shall shall NOT write data during next NvM_WriteAll
                maskBitsNewValue_u8 = 0;
            }
            else
            {
                // user has written new data into the permanent RAM block
                // -> NvM shall shall write data during next NvM_WriteAll
                maskBitsNewValue_u8 = NVM_BLOCK_STATE_RAM_CRC_NEW_DATA;
            }

            NvM_Prv_Block_SetState(JobData_pcst->idBlock_uo, maskBitsToChange_u8, maskBitsNewValue_u8);
            NvM_Prv_Crc_SetRamBlockCrc(JobData_pcst->idBlock_uo, &JobData_pcst->Crc_un);
        }

        SchM_Exit_NvM_Main();

        *stJob_pen = NvM_Prv_stJob_Finished_e;
    }

#else
    (void)JobData_pcst;
    *stJob_pen = NvM_Prv_stJob_Finished_e;
#endif
}

#define NVM_STOP_SEC_CODE
#include "NvM_MemMap.h"

