/*!
* @file     Wdg.c
*
* @version  1.0.0
*
* @brief    This file contains AUTOSAR WDG Driver APIs definition
*
* @attention
*
* Project Name      : AUTOSAR MCAL
*
* Platform          : Arm
*
* Autosar Standard  : Classic Platform 4.4.0
*
* Compiled Version  : G32A10xx_MCAL_1_0_0_01-Otc-25
*
* Copyright (C) 2026 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (Geehy Semiconductor Software License Agreement).
*
* The program is only for reference, which is distributed in the hope
* that it will be usefull and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the Geehy Semiconductor Software License Agreement for the governing permissions
* and limitations under the License.
*/

#ifdef __cplusplus
extern "C"{
#endif

#include "Wdg_Hw.h"
#include "SchM_Wdg.h"
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    #include "Det.h"
#endif

#if (STD_ON == WDG_INSTANCE0)

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup WDG_Driver
  * @brief WDG driver modules
  @{
*/

/** @defgroup WDG_Macros
  @{
*/
/**************************************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
**************************************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define WDG_VENDOR_ID                      0x00C1U
/** Module ID of this module, as defined in the BSW Module List. */
#define WDG_MODULE_ID                      0x0066U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define WDG_AR_RELEASE_MAJOR_VERSION       0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define WDG_AR_RELEASE_MINOR_VERSION       0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define WDG_AR_RELEASE_REVISION_VERSION    0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define WDG_SW_MAJOR_VERSION               0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define WDG_SW_MINOR_VERSION               0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define WDG_SW_PATCH_VERSION               0x00U

/**@} end of group WDG_Macros */

/**************************************************************************************************
                    VERSION INFOMATION VERIFICATION
**************************************************************************************************/
/* Make sure the vendor id is the same between Wdg.c and Wdg_Hw.h */
#if (WDG_VENDOR_ID != WDG_HW_H_VENDOR_ID)
    #error "Vendor id mismatch between Wdg.c and Wdg_Hw.h."
#endif
/* Make sure the AUTOSAR major version number is the same between Wdg.c and Wdg_Hw.h */
#if (WDG_AR_RELEASE_MAJOR_VERSION != WDG_HW_H_AR_RELEASE_MAJOR_VERSION) 
    #error "AUTOSAR Major Version Number mismatch between Wdg.c and Wdg_Hw.h."
#endif
/* Make sure the AUTOSAR minor version number is the same between Wdg.c and Wdg_Hw.h */
#if (WDG_AR_RELEASE_MINOR_VERSION != WDG_HW_H_AR_RELEASE_MINOR_VERSION) 
    #error "AUTOSAR Minor Version Number mismatch between Wdg.c and Wdg_Hw.h."
#endif
/* Make sure the AUTOSAR revision version number is the same between Wdg.c and Wdg_Hw.h */
#if (WDG_AR_RELEASE_REVISION_VERSION != WDG_HW_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR Revision Version Number mismatch between Wdg.c and Wdg_Hw.h."
#endif
/* Make sure the software major version number is the same between Wdg.c and Wdg_Hw.h */
#if (WDG_SW_MAJOR_VERSION != WDG_HW_H_SW_MAJOR_VERSION)
    #error "Software Major Version Number mismatch between Wdg.c and Wdg_Hw.h."
#endif
/* Make sure the software minor version number is the same between Wdg.c and Wdg_Hw.h */
#if (WDG_SW_MINOR_VERSION != WDG_HW_H_SW_MINOR_VERSION) 
    #error "Software Minor Version Number mismatch between Wdg.c and Wdg_Hw.h."
#endif
/* Make sure the software patch version number is the same between Wdg.c and Wdg_Hw.h */
#if (WDG_SW_PATCH_VERSION != WDG_HW_H_SW_PATCH_VERSION)
    #error "Software Patch Version Number mismatch between Wdg.c and Wdg_Hw.h."
#endif

#ifdef ENABLE_INTERMODULE_MCAL_CHECK
    /* Make sure the AUTOSAR major version number is the same between Wdg.c and SchM_Wdg.h */
    #if (WDG_AR_RELEASE_MAJOR_VERSION != SCHM_WDG_H_AR_RELEASE_MAJOR_VERSION) 
        #error "AUTOSAR Major Version Number mismatch between Wdg.c and SchM_Wdg.h."
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Wdg.c and SchM_Wdg.h */
    #if (WDG_AR_RELEASE_MINOR_VERSION != SCHM_WDG_H_AR_RELEASE_MINOR_VERSION) 
        #error "AUTOSAR Minor Version Number mismatch between Wdg.c and SchM_Wdg.h."
    #endif
#endif

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    /* Make sure the AUTOSAR major version number is the same between Wdg.c and Det.h */
    #if (WDG_AR_RELEASE_MAJOR_VERSION != DET_H_AR_RELEASE_MAJOR_VERSION) 
        #error "AUTOSAR Major Version Number mismatch between Wdg.c and Det.h."
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Wdg.c and Det.h */
    #if (WDG_AR_RELEASE_MINOR_VERSION != DET_H_AR_RELEASE_MINOR_VERSION) 
        #error "AUTOSAR Minor Version Number mismatch between Wdg.c and Det.h."
    #endif
#endif

/**************************************************************************************************
                    CONSTANT DEFINITION
**************************************************************************************************/
#define WDG_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Wdg_MemMap.h"

/** @defgroup WDG_Variable
  @{
*/

/** constant used to store wdg configuration information */
static P2CONST(Wdg_ConfigType, WDG_VAR, WDG_APPL_CONST) g_wdgConfigInfoPtr[WDG_INSTANCES_SUPPORT_NUMBER];

/**@} end of group WDG_Variable */

#define WDG_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Wdg_MemMap.h"

/**************************************************************************************************
                    LOCAL VARIABLE
**************************************************************************************************/
#define WDG_START_SEC_VAR_INIT_UNSPECIFIED
#include "Wdg_MemMap.h"

/** @defgroup WDG_Variable
  @{
*/

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
/** Variable used to store wdg status */
static VAR(Wdg_ModuleStatusType, WDG_VAR) g_wdgStatus[WDG_INSTANCES_SUPPORT_NUMBER] = {WDG_UNINIT};
#endif

/**@} end of group WDG_Variable */

#define WDG_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "Wdg_MemMap.h"

#define WDG_START_SEC_VAR_INIT_32
#include "Wdg_MemMap.h"

/** @defgroup WDG_Variable
  @{
*/

#if (STD_ON == WDG_USE_GPT)
/** Variable used to store wdg Timeout */
static VAR(uint32, WDG_VAR) g_wdgTimeout[WDG_INSTANCES_SUPPORT_NUMBER] = {(uint32)0x0};
/** Variable used to store GPT Timeout */
static VAR(uint32, WDG_VAR) g_gptTickValue[WDG_INSTANCES_SUPPORT_NUMBER] = {(uint32)0x0};
#endif

/**@} end of group WDG_Variable */

#define WDG_STOP_SEC_VAR_INIT_32
#include "Wdg_MemMap.h"

/**************************************************************************************************
                    LOCAL FUNCTION DECLARATION
**************************************************************************************************/
#ifdef WDG_RUN_AREA_ROM
#define WDG_START_SEC_CODE
#else
#define WDG_START_SEC_RAMCODE
#endif
#include "Wdg_MemMap.h"

/** @defgroup WDG_Fuctions
  @{
*/

LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateTargetMode(VAR(WdgIf_ModeType, AUTOMATIC) wdgTargetMode,
                                                                   VAR(Wdg_ServiceIdType, AUTOMATIC) serviceId,
                                                                   VAR(Wdg_ErrorIdType, AUTOMATIC) errorId,
                                                                 CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE)  Wdg_CheckSetStatus(CONST(Wdg_ServiceIdType, AUTOMATIC)   serviceId,
                                                                CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);

LOCAL_INLINE FUNC(void, WDG_CODE)  Wdg_SetStatusBeforeAPIExit(VAR(Std_ReturnType, AUTOMATIC) result,
                                                            CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);

LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE)  Wdg_ValidateInitPara
                                             (P2CONST(Wdg_ConfigType, AUTOMATIC, WDG_APPL_CONST) pConfigPtr,
                                                CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);

LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateTrigerConditionEnviroment
                                            (CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);
#endif

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
#if (STD_ON == WDG_USE_GPT)
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateTimeoutScope(VAR(uint16, AUTOMATIC) wdgTimeoutValue,
                                                                   CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);
#endif
#endif

#if ((STD_ON == WDG_VERSION_INFO_API) && (STD_ON == WDG_DET_ERROR_DETECT_ENABLE))
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateGetVersionInfoPtr
                                           (P2CONST(Std_VersionInfoType, AUTOMATIC, WDG_APPL_CONST) pWdgVersioninfo,
                                              CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);
#endif

#if (STD_ON == WDG_USE_GPT)
LOCAL_INLINE FUNC(void, WDG_CODE)  Wdg_ClearCNTGptTimeout(CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);
#endif

#ifdef WDG_CHECK_CONFIG_REFRESH
#if (STD_ON == WDG_CHECK_CONFIG_REFRESH)
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateSetModeUpdate(CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId);
#endif
#endif

#if (STD_ON == WDG_USE_GPT)
#ifdef WDG_INSTANCE0
#if (STD_ON == WDG_INSTANCE0)
FUNC(void, WDG_CODE) Wdg_GptCallbackFunction0(void);
#endif
#endif
#endif

/**************************************************************************************************
                    LOCAL FUNCTION
**************************************************************************************************/
/*!
* @brief           Validate set mode update enviroment.
*
* @param[in]       wdgInstanceId    wdg specific instance
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK
*/
#ifdef WDG_CHECK_CONFIG_REFRESH
#if (STD_ON == WDG_CHECK_CONFIG_REFRESH)
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateSetModeUpdate(CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_OK;

    if ((Std_ReturnType)E_OK != Wdg_Hw_CheckReconfig(wdgInstanceId))
    {
#if (STD_ON == WDG_DEM_ERROR_DETECT)
        if((uint32)STD_ON == g_wdgEModeFailed.state)
        {
            (void) Dem_SetEventStatus((Dem_EventIdType)g_wdgEModeFailed.id, DEM_EVENT_STATUS_FAILED);
        }
        else
        {
            /* do nothing */
        }
#endif
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId], (uint8)SID_WDG_SETMODE, (uint8)WDG_E_PARAM_MODE);
#endif
        checkResult = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
#if (STD_ON == WDG_DEM_ERROR_DETECT)
        if((uint32)STD_ON == g_wdgEModeFailed.state)
        {
            (void) Dem_SetEventStatus((Dem_EventIdType)g_wdgEModeFailed.id, DEM_EVENT_STATUS_PASSED);
        }
        else
        {
            /* do nothing */
        }
#endif
    }

    return checkResult;
}
#endif
#endif

/*!
* @brief           Validate channel mode enviroment.
*
* @param[in]       wdgTargetMode    wdg target mode
*                  serviceId        wdg service Id
*                  errorId          wdg error Id
*                  wdgInstanceId    wdg specific instance
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK
*/
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateTargetMode(VAR(WdgIf_ModeType, AUTOMATIC)  wdgTargetMode,
                                                                   VAR(Wdg_ServiceIdType, AUTOMATIC) serviceId,
                                                                   VAR(Wdg_ErrorIdType, AUTOMATIC)  errorId,
                                                                 CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_OK;
    VAR(boolean, AUTOMATIC) targetModeImproper = (boolean)FALSE;

    if (!((WDGIF_SLOW_MODE == wdgTargetMode) || (WDGIF_FAST_MODE == wdgTargetMode)))
    {
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId], (uint8)serviceId, (uint8)errorId);
#else
        (void)serviceId;
        (void)errorId;
#endif
        targetModeImproper = (boolean)TRUE;
        checkResult = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        if ((Std_ReturnType)E_NOT_OK ==
             Wdg_Hw_CheckWindowCfg(g_wdgConfigInfoPtr[wdgInstanceId]->wdgModeParameter[wdgTargetMode], wdgInstanceId))
        {
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
            (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId], (uint8)serviceId, (uint8)errorId);
#endif
            targetModeImproper  = (boolean)TRUE;
            checkResult = (Std_ReturnType)E_NOT_OK;
        }
        else
        {
            /* do nothing */
        }
    }
#if (STD_ON == WDG_DEM_ERROR_DETECT)
    if((uint32)STD_ON == g_wdgEModeFailed.state)
    {
        if((boolean)TRUE == targetModeImproper)
        {
            (void) Dem_SetEventStatus((Dem_EventIdType)g_wdgEModeFailed.id, DEM_EVENT_STATUS_FAILED);
        }
        else
        {
            (void) Dem_SetEventStatus((Dem_EventIdType)g_wdgEModeFailed.id, DEM_EVENT_STATUS_PASSED);
        }
    }
    else
    {
        /* do nothing */
    }
#else
    (void)targetModeImproper;
#endif

    return checkResult;
}

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
/*!
* @brief           Check and set wdg status.
*
* @param[in]       serviceId         wdg service id.
*                  wdgInstanceId     wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK
*/
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE)  Wdg_CheckSetStatus(CONST(Wdg_ServiceIdType, AUTOMATIC) serviceId,
                                                                CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_OK;

    SchM_Enter_Wdg_WDG_CRITICAL_SECTION4();

    if(((g_wdgStatus[wdgInstanceId] == WDG_UNINIT) && (SID_WDG_INIT != serviceId)) ||
        (g_wdgStatus[wdgInstanceId] == WDG_IS_INITIALIZING) || 
        (g_wdgStatus[wdgInstanceId] == WDG_BUSY))
    {
        (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId], (uint8)serviceId, (uint8)WDG_E_DRIVER_STATE);

        checkResult = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        g_wdgStatus[wdgInstanceId] = (SID_WDG_INIT == serviceId) ? WDG_IS_INITIALIZING : WDG_BUSY;
    }

    SchM_Exit_Wdg_WDG_CRITICAL_SECTION4();

    return checkResult;
}

/*!
* @brief           Set wdg status before API exit.
*
* @param[in]       result            check result.
*                  wdgInstanceId     wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          None
*/
LOCAL_INLINE FUNC(void, WDG_CODE) Wdg_SetStatusBeforeAPIExit(VAR(Std_ReturnType, AUTOMATIC) result,
                                                           CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    SchM_Enter_Wdg_WDG_CRITICAL_SECTION5();

    if ((Std_ReturnType)E_OK == result)
    {
        g_wdgStatus[wdgInstanceId] = WDG_IDLE;
    }
    else
    {
        if (WDG_BUSY == g_wdgStatus[wdgInstanceId])
        {
            g_wdgStatus[wdgInstanceId] = WDG_IDLE;
        }
        else
        {
            if (NULL_PTR == g_wdgConfigInfoPtr[wdgInstanceId])
            {
                g_wdgStatus[wdgInstanceId] = WDG_UNINIT;
            }
            else
            {
                g_wdgStatus[wdgInstanceId] = WDG_IDLE;
            }
        }
    }

    SchM_Exit_Wdg_WDG_CRITICAL_SECTION5();
}

/*!
* @brief           Validate Initial Parameter.
*
* @param[in]       pConfigPtr     point to initial ptr.
*                  wdgInstanceId  wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK
*/
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateInitPara
                                            (P2CONST(Wdg_ConfigType, AUTOMATIC, WDG_APPL_CONST) pConfigPtr,
                                               CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_OK;

    if (NULL_PTR == pConfigPtr)
    {
        (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId],
                              (uint8)SID_WDG_INIT, (uint8)WDG_E_INIT_FAILED);

        checkResult = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        if (wdgInstanceId != pConfigPtr->wdgInstanceId)
        {
            (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId],
                                  (uint8)SID_WDG_INIT, (uint8)WDG_E_PARAM_POINTER);

            checkResult = (Std_ReturnType)E_NOT_OK;
        }
        else
        {
            /* do nothing */
        }
    }

    return checkResult;
}

/*!
* @brief           Validate triger condition enviroment.
*
* @param[in]       wdgInstanceId  wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK
*/
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateTrigerConditionEnviroment(CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_OK;

    if ((g_wdgStatus[wdgInstanceId] == WDG_UNINIT) || (g_wdgStatus[wdgInstanceId] == WDG_IS_INITIALIZING ))
    {
        (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId],
                              (uint8)SID_WDG_SETTRIGGERCONDITION, (uint8)WDG_E_DRIVER_STATE);

        checkResult = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        /* do nothing */
    }

    return checkResult;
}
#endif

/*!
* @brief           Validate whether timeout value is bigger than the maximal value.
*
* @param[in]       wdgTimeoutValue    wdg target timeout
*                  wdgInstanceId      wdg specific instance
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK
*/
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
#if (STD_ON == WDG_USE_GPT)
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateTimeoutScope(VAR(uint16, AUTOMATIC) wdgTimeoutValue,
                                                                   CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_OK;

    if (wdgTimeoutValue > (uint16)WDG_MAX_TIMEOUT)
    {
        (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId],
                              (uint8)SID_WDG_SETTRIGGERCONDITION, (uint8)WDG_E_PARAM_TIMEOUT);

        checkResult = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        /* do nothing */
    }

    return checkResult;
}
#endif
#endif

/*!
* @brief           Validate Wdg_GetVersionInfo() parameter whether is NULL_PTR.
*
* @param[in]       pWdgVersioninfo     Wdg_GetVersionInfo()'s parameter
*                  wdgInstanceId       wdg specific instance
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK
*/
#if ((STD_ON == WDG_VERSION_INFO_API) && (STD_ON == WDG_DET_ERROR_DETECT_ENABLE))
LOCAL_INLINE FUNC(Std_ReturnType, WDG_CODE) Wdg_ValidateGetVersionInfoPtr
                                           (P2CONST(Std_VersionInfoType, AUTOMATIC, WDG_APPL_CONST) pWdgVersioninfo,
                                            CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_OK;

    if (NULL_PTR == pWdgVersioninfo)
    {
        (void)Det_ReportError((uint16)WDG_H_MODULE_ID, (uint8)g_wdgIndex[wdgInstanceId],
                              (uint8)SID_WDG_GETVERSION,(uint8)WDG_E_PARAM_POINTER);

        checkResult = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        /* do nothing */
    }

    return checkResult;
}
#endif

#if (STD_ON == WDG_USE_GPT)
/*!
* @brief           Clear WDT_CNT value when Gpt timeout arrive.
*
* @param[in]       wdgInstanceId     wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          None
*/
LOCAL_INLINE FUNC(void, WDG_CODE) Wdg_ClearCNTGptTimeout(CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(uint32, AUTOMATIC) newWdgTimeout = 0U;

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    VAR(Std_ReturnType, AUTOMATIC) checkResult = Wdg_CheckSetStatus(SID_WDG_TRIGGER, wdgInstanceId);

    if ((Std_ReturnType)E_OK == checkResult)
    {
#endif
        SchM_Enter_Wdg_WDG_CRITICAL_SECTION0();

        if( g_wdgTimeout[wdgInstanceId] < g_gptTickValue[wdgInstanceId])
        {
            MCAL_FAULT_INJECTION_POINT(T_WDG_INJ_TG_0);
            SchM_Exit_Wdg_WDG_CRITICAL_SECTION0();
            Gpt_StopTimer(g_wdgConfigInfoPtr[wdgInstanceId]->wdgGptChannelId);
        }
        else
        {
            newWdgTimeout = g_wdgTimeout[wdgInstanceId] - g_gptTickValue[wdgInstanceId];
            g_wdgTimeout[wdgInstanceId] = newWdgTimeout;
            SchM_Exit_Wdg_WDG_CRITICAL_SECTION0();
            Wdg_Hw_ReloadCounter(wdgInstanceId);
        }
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    }
    else
    {
        /* do nothing */
    }

    Wdg_SetStatusBeforeAPIExit(checkResult, wdgInstanceId);
#endif
}

/*!
* @brief           Gpt callback function.
*
* @param[in]       None
* @param[out]      None
* @param[in,out]   None
*
* @retval          None
*/
#ifdef WDG_INSTANCE0
#if (STD_ON == WDG_INSTANCE0)
FUNC(void, WDG_CODE) Wdg_GptCallbackFunction0(void)
{
    Wdg_ClearCNTGptTimeout(Wdg_Instance0);
}
#endif
#endif
#endif

/**************************************************************************************************
                    GLOBAL FUNCTIONS
**************************************************************************************************/
/*!
* @brief           This function is defined by AUTOSAR, which is used to check the wdg module version.
*                  The version information includes: Module Id, Vendor Id, Vendor specific version numbers.
*
* @param[in]       None
* @param[out]      None
* @param[in,out]   versioninfo   Pointer to the version information stored.
*
* @retval          None
*
* @note            Reentrant
*/
#if (STD_ON == WDG_VERSION_INFO_API)
FUNC(void, WDG_CODE) Wdg_GetVersionInfo(P2VAR(Std_VersionInfoType, AUTOMATIC, WDG_APPL_DATA) versioninfo)
{
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    if ((Std_ReturnType)E_OK != Wdg_ValidateGetVersionInfoPtr(versioninfo, Wdg_Instance0))
    {
        /* do nothing */
    }
    else
#endif
    {
        (versioninfo)->vendorID         = (uint16)WDG_H_VENDOR_ID;
        (versioninfo)->moduleID         = (uint16)WDG_H_MODULE_ID;
        (versioninfo)->sw_major_version = (uint8) WDG_H_SW_MAJOR_VERSION;
        (versioninfo)->sw_minor_version = (uint8) WDG_H_SW_MINOR_VERSION;
        (versioninfo)->sw_patch_version = (uint8) WDG_H_SW_PATCH_VERSION;
    }
}
#endif

#if (STD_ON == WDG_USE_GPT)
/*!
* @brief           This function is defined by AUTOSAR, which is used to modify the feeding interval.
*                  The paramter is in milliseconds.
*
* @param[in]       timeout     timeout value for setting the trigger counter.
* @param[out]      None
* @param[in,out]   None
*
* @retval          None
*
* @note            Non Reentrant
*/
FUNC(void, WDG_CODE) Wdg_SetTriggerCondition(CONST(uint16, WDG_CONST) timeout)
{
    VAR(Gpt_ValueType, AUTOMATIC) elapsedTime = (Gpt_ValueType)0;

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    if ((Std_ReturnType)E_OK == Wdg_ValidateTrigerConditionEnviroment(Wdg_Instance0))
    {
#endif
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
        if ((Std_ReturnType)E_OK == Wdg_ValidateTimeoutScope(timeout, Wdg_Instance0))
        {
#endif
            SchM_Enter_Wdg_WDG_CRITICAL_SECTION3();

            elapsedTime = Gpt_GetTimeElapsed(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptChannelId);

            if (((uint16)(elapsedTime) > g_wdgTimeout[Wdg_Instance0]) || ((uint16)0 == timeout))
            {
                /* set timeout value as 0 */
                g_wdgTimeout[Wdg_Instance0] = (uint32)0;
                SchM_Exit_Wdg_WDG_CRITICAL_SECTION3();
                /* Stop the Gpt timer */
                Gpt_StopTimer(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptChannelId);
            }
            else
            {   
                /* Calculate timeout value */
                g_wdgTimeout[Wdg_Instance0] = (uint32)(timeout *
                                               g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptSourceClock) + elapsedTime;
                SchM_Exit_Wdg_WDG_CRITICAL_SECTION3();
            }
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
        }
        else
        {
            /* do nothing */
        }
#endif
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    }
    else
    {
        /* do nothing */
    }
#endif
}
#else
/*!
* @brief           This function is defined by AUTOSAR, which is used to reset wdg counter.
*
* @param[in]       None
* @param[out]      None
* @param[in,out]   None
*
* @retval          None
*
* @note            Non Reentrant
*/
FUNC(void, WDG_CODE) Wdg_SetTriggerCondition(void)
{
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    if ((Std_ReturnType)E_NOT_OK == Wdg_ValidateTrigerConditionEnviroment(Wdg_Instance0))
    {
        /* do nothing */
    }
    else
#endif
    {
        Wdg_Hw_ReloadCounter(Wdg_Instance0);
    }
}
#endif

/*!
* @brief           This function is defined by AUTOSAR, which is used to change wdg mode.
*                  This function change the wdg mode according to the paramter. After execute this function,
*                  wdg module will work in new mode.
*
* @param[in]       Mode   One of the following can be selected: WDGIF_SLOW_MODE, WDGIF_FAST_MODE.
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK.
*
* @note            Non Reentrant
*/
FUNC(Std_ReturnType, WDG_CODE) Wdg_SetMode(CONST(WdgIf_ModeType, WDG_CONST) Mode)
{
#if (STD_ON == WDG_USE_GPT)
    VAR(uint32, AUTOMATIC) tempTime = 0U;
    VAR(Gpt_ValueType, AUTOMATIC) elapsedTime = (Gpt_ValueType)0;
    VAR(uint32, AUTOMATIC) gptTick = 0U;
#endif
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_NOT_OK;
    VAR(Std_ReturnType, AUTOMATIC) returnValue = (Std_ReturnType)E_NOT_OK;

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    checkResult = Wdg_CheckSetStatus(SID_WDG_SETMODE, Wdg_Instance0);
    if ((Std_ReturnType)E_OK == checkResult)
    {
#endif
        MCAL_FAULT_INJECTION_POINT(T_WDG_INJ_START);
        checkResult = Wdg_ValidateTargetMode(Mode, SID_WDG_SETMODE, WDG_E_PARAM_MODE, Wdg_Instance0);
        if ((Std_ReturnType)E_OK == checkResult)
        {
#ifdef WDG_CHECK_CONFIG_REFRESH
#if (STD_ON == WDG_CHECK_CONFIG_REFRESH)
            checkResult = Wdg_ValidateSetModeUpdate(Wdg_Instance0);
            if ((Std_ReturnType)E_OK == checkResult)
            {
#endif
#endif

#if (STD_ON == WDG_USE_GPT)
                gptTick = Wdg_Hw_Init(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgModeParameter[Mode], Wdg_Instance0);
                gptTick = (gptTick / (g_wdgConfigInfoPtr[Wdg_Instance0]->wdgModeParameter[Mode]->wdgTimerClock));
                gptTick = gptTick * (g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptSourceClock);
                Gpt_StopTimer(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptChannelId);
                elapsedTime = Gpt_GetTimeElapsed(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptChannelId);

                SchM_Enter_Wdg_WDG_CRITICAL_SECTION2();
                tempTime = (g_wdgTimeout[Wdg_Instance0] < elapsedTime) ? ((uint32)0) : (g_wdgTimeout[Wdg_Instance0] - elapsedTime);
                g_wdgTimeout[Wdg_Instance0] = tempTime;
                SchM_Exit_Wdg_WDG_CRITICAL_SECTION2();

                g_gptTickValue[Wdg_Instance0] = gptTick;

                /* Gpt begin work*/
                Gpt_StartTimer(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptChannelId,g_gptTickValue[Wdg_Instance0]);
#else
                (void)Wdg_Hw_Init(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgModeParameter[Mode], Wdg_Instance0);
#endif
                returnValue = (Std_ReturnType)E_OK;
#ifdef WDG_CHECK_CONFIG_REFRESH
#if (STD_ON == WDG_CHECK_CONFIG_REFRESH)
            }
            else
            {
                /* do nothing */
            }
#endif
#endif
        }
        else
        {
            /* do nothing */
        }
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    }
    else
    {
        /* do nothing */
    }
    Wdg_SetStatusBeforeAPIExit(checkResult, Wdg_Instance0);
#endif

    MCAL_FAULT_INJECTION_POINT(T_WDG_INJ_STOP);

    return returnValue;
}

/*!
* @brief           This function is defined by AUTOSAR, which is used to initialize the wdg module.
*                  After execute this function, wdg module will work.
*
* @param[in]       ConfigPtr     Pointer to a kind of wdg setting.
* @param[out]      None
* @param[in,out]   None
*
* @retval          None
*
* @note            Non Reentrant
*/
FUNC(void, WDG_CODE) Wdg_Init(P2CONST(Wdg_ConfigType, AUTOMATIC, WDG_APPL_CONST) ConfigPtr)
{
#if (STD_ON == WDG_USE_GPT)
    VAR(uint32 , AUTOMATIC) gptTick = 0U;
#endif
    VAR(Std_ReturnType, AUTOMATIC) checkResult = E_OK;

#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    checkResult = Wdg_CheckSetStatus(SID_WDG_INIT, Wdg_Instance0);
    if ((Std_ReturnType)E_OK == checkResult)
    {
#endif
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
        checkResult = Wdg_ValidateInitPara(ConfigPtr, Wdg_Instance0);
        if ((Std_ReturnType)E_OK == checkResult)
        {
#endif
            g_wdgConfigInfoPtr[Wdg_Instance0] = ConfigPtr;

            checkResult = Wdg_ValidateTargetMode(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgInitMode,
                                                 SID_WDG_INIT, WDG_E_PARAM_CONFIG, Wdg_Instance0);
            if ((Std_ReturnType)E_OK == checkResult)
            {
#if (STD_ON == WDG_USE_GPT)
                Gpt_StopTimer(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptChannelId);

                /* Set g_gptTickValue value */
                gptTick = Wdg_Hw_Init(g_wdgConfigInfoPtr[Wdg_Instance0]->
                          wdgModeParameter[g_wdgConfigInfoPtr[Wdg_Instance0]->wdgInitMode], Wdg_Instance0);
                gptTick = gptTick * (g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptSourceClock);
                gptTick = (gptTick/(g_wdgConfigInfoPtr[Wdg_Instance0]->
                          wdgModeParameter[g_wdgConfigInfoPtr[Wdg_Instance0]->wdgInitMode]->wdgTimerClock));
                g_gptTickValue[Wdg_Instance0] = gptTick;
                /* Gpt module */
                Gpt_EnableNotification(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptChannelId);
                Gpt_StartTimer(g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptChannelId, gptTick);
                /* Set g_wdgTimeout value */
                SchM_Enter_Wdg_WDG_CRITICAL_SECTION1();
                g_wdgTimeout[Wdg_Instance0] = (uint32)(WDG_INITIAL_TIMEOUT * (g_wdgConfigInfoPtr[Wdg_Instance0]->wdgGptSourceClock));
                SchM_Exit_Wdg_WDG_CRITICAL_SECTION1();
#else
                (void)Wdg_Hw_Init(g_wdgConfigInfoPtr[Wdg_Instance0]->
                      wdgModeParameter[g_wdgConfigInfoPtr[Wdg_Instance0]->wdgInitMode], Wdg_Instance0);
#endif
            }
            else
            {
                g_wdgConfigInfoPtr[Wdg_Instance0] = NULL_PTR;
            }
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
        }
        else
        {
            /* do nothing */
        }
#endif
#if (STD_ON == WDG_DET_ERROR_DETECT_ENABLE)
    }
    else
    {
        /* do nothing */
    }

    Wdg_SetStatusBeforeAPIExit(checkResult, Wdg_Instance0);
#endif
}

/**@} end of group WDG_Fuctions */

#ifdef WDG_RUN_AREA_ROM
#define WDG_STOP_SEC_CODE
#else
#define WDG_STOP_SEC_RAMCODE
#endif
#include "Wdg_MemMap.h"

#endif

#ifdef __cplusplus
}
#endif

/**@} end of group WDG_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */
