/* ======================================================================
 *   Copyright (C) 2022 Texas Instruments Incorporated
 *
 *   All rights reserved. Property of Texas Instruments Incorporated.
 *   Restricted rights to use, duplicate or disclose this code are
 *   granted through contract.
 *
 *   The program may not be used without the written permission
 *   of Texas Instruments Incorporated or against the terms and conditions
 *   stipulated in the agreement under which this program has been
 *   supplied.
 * ==================================================================== */

/**
 *  \file     Gpt.c
 *
 *  \brief    This file contains GPT MCAL driver
 *
 */
/*  -------------------------------------------------------------------------------------------------------------------
*  FILE DESCRIPTION
*  -------------------------------------------------------------------------------------------------------------------
*         File:  Gpt.c
*    Component:  AM263x MCAL Driver
*       Module:  GptDriver
*    Generator:  None
*
*  Description: This component provides services for initialization and control of the microcontroller internal
*                GPT unit (General Purpose Timer).
*********************************************************************************************************************/

/* ========================================================================== */
/*                                                                       Include Files                                                */
/* ========================================================================== */

/* Requirements : SWS_Gpt_00293 */
#include "Gpt.h"
#include "Gpt_Irq.h"
#include "Gpt_Priv.h"
/*LDRA_NOANALYSIS*/
#include "SchM_Gpt.h"
/* Requirements : SWS_Gpt_00375 */
#include "Det.h"
/*LDRA_ANALYSIS*/


#include "sys_common.h"
#include "hw_ctrl_core.h"


/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/* AUTOSAR version information check has to match definition in header file */
#if ((GPT_AR_RELEASE_MAJOR_VERSION != (4U)) || \
    (GPT_AR_RELEASE_MINOR_VERSION != (3U)) ||  \
    (GPT_AR_RELEASE_REVISION_VERSION != (1U)))
    #error "Gpt: AUTOSAR Version Numbers of Gpt are different!!"
#endif

/* Software version information check has to match definition in header file */
#if ((GPT_SW_MAJOR_VERSION != (0U)) || \
    (GPT_SW_MINOR_VERSION != (9U)))
    #error "Gpt: Software Version Numbers are inconsistent!!"
#endif

/* ========================================================================== */
/*                         Structures and Enums                               */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                 Internal Function Declarations                             */
/* ========================================================================== */
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
void Gpt_reportDetError(uint8 apiId, uint8 errorId);
#endif

void Gpt_reportRuntimeError(uint8 apiId, uint8 errorId);

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */


#define GPT_START_SEC_VAR_NO_INIT_UNSPECIFIED
/*LDRA_INSPECTED 338 S : MISRAC_2012_R.20.1
 * "Reason - Required to comply with AUTOSAR memmap spec " */
/*LDRA_INSPECTED 243 S : MISRAC_2012_D.4.10
 * "Reason - Memmap file cannot have include guard w.r.o autosar spec " */
#include "Gpt_MemMap.h"


VAR(uint32, GPT_DATA) Gpt_IsrIndex[GPT_CFG_MAX_CHANNELS];

/* Variable to indicate the state of the channel */
/*A Channel will be in five states - Uninitialized,Initialized, Running,Stopped,Expired*/
VAR(Gpt_ChannelStateType, GPT_DATA) Gpt_ChannelState[GPT_CFG_MAX_CHANNELS];

#if (STD_ON == GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API)
/* Variable indicate the notification status for each channel (bit wise) */
/* 1 - Notification is enabled for the corresponding channel
* 0 - Notification is disabled for the corresponding channel            */
static VAR (uint16, GPT_DATA) Gpt_ActiveNotifyChannels;
#endif /* (STD_ON == GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API) */

/** \brief Tracks GPT channels mapped to counters */
VAR (uint32, GPT_DATA) Gpt_ChStartTime_map[GPT_CFG_MAX_CHANNELS];


#define GPT_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
/*LDRA_INSPECTED 338 S : MISRAC_2012_R.20.1
 * "Reason - Required to comply with AUTOSAR memmap spec " */
#include "Gpt_MemMap.h"

#define GPT_START_SEC_VAR_INIT_UNSPECIFIED  
/*LDRA_INSPECTED 338 S : MISRAC_2012_R.20.1
 * "Reason - Required to comply with AUTOSAR memmap spec " */
/*LDRA_INSPECTED 243 S : MISRAC_2012_D.4.10
 * "Reason - Memmap file cannot have include guard w.r.o autosar spec " */
#include "Gpt_MemMap.h"

/** \brief GPT driver object */
P2CONST(Gpt_ConfigType, GPT_DATA, GPT_PBCFG) Gpt_Config_pt = NULL_PTR;

/** \brief Helps map channel ids to channel configuration objects */
VAR (uint16, GPT_DATA) Gpt_ChConfig_map[GPT_CFG_MAX_CHANNELS] = {0};

static VAR (Gpt_NotifyType, GPT_DATA) Gpt_ChannelNotifyFunctions[GPT_CFG_MAX_CHANNELS] = { NULL_PTR };
#define GPT_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "Gpt_MemMap.h"

#define GPT_START_SEC_CONST_32
/*LDRA_INSPECTED 338 S : MISRAC_2012_R.20.1
 * "Reason - Required to comply with AUTOSAR memmap spec " */
#include "Gpt_MemMap.h"

/*The Array of pointers to the call notification Functions */
CONST (Gpt_IsrRefType, GPT_CONST) Gpt_IsrNotifyFunctions[CHANNEL_MODES] =
   {
      &Gpt_NotifContIsr,
      &Gpt_NotifSingleIsr,
   };


#define GPT_STOP_SEC_CONST_32
/*LDRA_INSPECTED 338 S : MISRAC_2012_R.20.1
 * "Reason - Required to comply with AUTOSAR memmap spec " */
#include "Gpt_MemMap.h"


/* ========================================================================== */
/*                 Internal Function Declarations                             */
/* ========================================================================== */
static FUNC(void, GPT_CODE) Gpt_SetRegStartTimer(Gpt_ChannelType channel, Gpt_ValueType value );


/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

#define GPT_START_SEC_CODE
/*LDRA_INSPECTED 338 S : MISRAC_2012_R.20.1
 * "Reason - Required to comply with AUTOSAR memmap spec " */
#include "Gpt_MemMap.h"


/* Design : GPT_DesignId_012 */
/* Requirements : SWS_Gpt_00279, SWS_Gpt_00338 */
#if (STD_ON == GPT_CFG_VERSION_INFO_API)
/*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */

FUNC(void, GPT_CODE) Gpt_GetVersionInfo(P2VAR(Std_VersionInfoType,
            AUTOMATIC, GPT_APPL_DATA) VersionInfoPtr)
{
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
    if (NULL_PTR == VersionInfoPtr)
    {
        Gpt_reportDetError(GPT_SID_GET_VERSION_INFO, GPT_E_PARAM_POINTER);
    }
    else
#endif
    {
        VersionInfoPtr->vendorID         = GPT_VENDOR_ID;
        VersionInfoPtr->moduleID         = GPT_MODULE_ID;
        VersionInfoPtr->sw_major_version = (uint8) GPT_SW_MAJOR_VERSION;
        VersionInfoPtr->sw_minor_version = (uint8) GPT_SW_MINOR_VERSION;
        VersionInfoPtr->sw_patch_version = (uint8) GPT_SW_PATCH_VERSION;
    }

    return;
}
#endif /*(STD_ON == GPT_CFG_VERSION_INFO_API)*/



/* Design : GPT_DesignId_004 */
/*
 * Requirements : SWS_Gpt_00280,  SWS_Gpt_00107, SWS_Gpt_00068,SWS_Gpt_00006
 *                SWS_Gpt_00352, SWS_Gpt_00355, SWS_Gpt_00356,
 *                SWS_Gpt_00339, SWS_Gpt_00309, SWS_Gpt_00257, SWS_Gpt_00294
 *                SWS_Gpt_00340
 */
 /*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
/*LDRA_INSPECTED 8 D : MISRAC_2012_R2.2
 * "Reason - Code inspected LDRA tool error " */
FUNC(void, GPT_CODE) Gpt_Init(P2CONST(Gpt_ConfigType, AUTOMATIC,GPT_CONST) configPtr)
{
    Gpt_ChannelType ChannelIdx;
    Gpt_ChannelType Gpt_Channel;
    uint32 tickFreq;
    uint32 Gpt_rtiChAddr;
    uint32 exitCondition = FALSE; /*Used to solve METRICS.E.HIS_Metrics___Max_nesting_level_LEVEL issue*/

    /* configPtr must not be NULL. In case it is NULL report an error and
    * return immediately.*/
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
    if (NULL_PTR == configPtr)
    {
        (void)Gpt_reportDetError(GPT_SID_INIT, GPT_E_PARAM_POINTER);
        exitCondition = TRUE;
    }
    if ((exitCondition == FALSE) && (NULL_PTR != Gpt_Config_pt))
    {
        /* Gpt module must not be initalized. Otherwise call the Det with GPT_E_ALREADY_INITIALIZED */
        /*
        * Requirements : SWS_Gpt_00307:Gpt module must not be initialized.
        * Otherwise call the Det with GPT_E_ALREADY_INITIALIZED
        */
        (void)Gpt_reportDetError(GPT_SID_INIT, GPT_E_ALREADY_INITIALIZED);
        exitCondition = TRUE;

    }
    if (exitCondition == FALSE)
#endif
    {
       Gpt_Config_pt = configPtr;

        /* Reset wakeup Channels */

        /* Reset the Channel notifications*/
#if (STD_ON == GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API)
     Gpt_ActiveNotifyChannels = 0U;
#endif      /* (STD_ON == GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API) */

     /* SWS_Gpt_00068: Only initialize configured resources, that means, only
         * timers listed in the channel configuration structure.
        */

     for ( ChannelIdx = 0U; ChannelIdx < Gpt_Config_pt->ChannelCount; ChannelIdx++ )
     {
        Gpt_Channel = Gpt_Config_pt->ChannelConfig_pt[ChannelIdx].ChannelId;
        if (Gpt_Channel > GPT_RTI_CH_MAX)
        {
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
            (void)Gpt_reportDetError(GPT_SID_INIT, GPT_E_INIT_FAILED);
#endif
            Gpt_Config_pt = NULL_PTR;
            break;
        }
        Gpt_ChConfig_map[Gpt_Channel] = (uint16)ChannelIdx;

        Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(Gpt_Channel);
        tickFreq = Gpt_Config_pt->ChannelConfig_pt[ChannelIdx].GptChannelTickFrequency;
        /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
         * "Reason - Cast for register address " */
        /*LDRA_INSPECTED 105 D : MISRAC_2012_R2.2
         * "Reason - Code inspected LDRA tool error " */
        Gpt_RTIInit_Channel((rtiBASE_t *) Gpt_rtiChAddr, Gpt_Channel, tickFreq);
        Gpt_ChannelState[Gpt_Channel] = GPT_INITIALIZED;
     }
    }
}/*Gpt_Init*/

/* Design : GPT_DesignId_005 */

#if (STD_ON == GPT_CFG_DEINIT_API)
/*
 * Requirements : SWS_Gpt_00281, SWS_Gpt_00008, SWS_Gpt_00105, SWS_Gpt_00162
 *                SWS_Gpt_00308, SWS_Gpt_00194, SWS_Gpt_00363, SWS_Gpt_00234
 *                SWS_Gpt_00220
 */
 /*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
/*LDRA_INSPECTED 8 D : MISRAC_2012_R2.2
 * "Reason - Code inspected LDRA tool error " */

FUNC(void, GPT_CODE) Gpt_DeInit( void )
{
   Gpt_ChannelType ChannelIdx;/*Configured Channel Index*/
   Gpt_ChannelType Gpt_Channel;
   boolean Dev_Error_Flag = FALSE;
   uint32 Gpt_rtiChAddr;

  /* check if the driver has been successfully initialized. if the driver
    * has not been initialized, report an error and return immediately.
    */
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
   if (NULL_PTR == Gpt_Config_pt)
   {
      (void)Gpt_reportDetError(GPT_SID_DEINIT, GPT_E_UNINIT);
      Dev_Error_Flag = TRUE;
   }
#endif
    /*Return from the Api if Dev_Error_Flag is TRUE */
    if (Dev_Error_Flag==FALSE)
    {
          /* Check if any channel is in "Running" state,If true report error and
           *  return from the function*/
          for ( ChannelIdx = 0U; ChannelIdx < Gpt_Config_pt->ChannelCount; ChannelIdx++ )
          {
             Gpt_Channel = Gpt_Config_pt->ChannelConfig_pt[ChannelIdx].ChannelId;
             if (GPT_RUNNING == Gpt_ChannelState[Gpt_Channel])
             {
                /* At least one of the channels is active */
                (void)Gpt_reportRuntimeError( GPT_SID_DEINIT, GPT_E_BUSY );
                 Dev_Error_Flag = TRUE;
                 break;
             }
          }
    }
/* -------------------- DeInit Loop ----------------------------------------*/
      /*
           * SWS_Gpt_00234: If any timer channel is in state "running", the
           * function shall raise the error GPT_E_BUSY.
           */
    if (Dev_Error_Flag==FALSE)
    {
        for ( ChannelIdx = 0U; ChannelIdx < Gpt_Config_pt->ChannelCount; ChannelIdx++ )
        {
            Gpt_Channel = Gpt_Config_pt->ChannelConfig_pt[ChannelIdx].ChannelId;
             Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(Gpt_Channel);

			/*Set the Channel State to "UnInitialized"*/
			Gpt_ChannelState[Gpt_Channel] = GPT_UNINITIALIZED;

			 /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
			  * "Reason - Cast for register address " */
			 /*LDRA_INSPECTED 105 D : MISRAC_2012_R2.2
			  * "Reason - Code inspected LDRA tool error " */
			 Gpt_RTI_DeInit((rtiBASE_t *)Gpt_rtiChAddr, Gpt_Channel);

		} /* End of for */
#if (STD_ON == GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API)
		Gpt_ActiveNotifyChannels = 0U;/* Reset the notification attributes */
#endif /* (STD_ON == GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API) */

		Gpt_Config_pt = NULL_PTR;/* Reset configuration pointer */
    }
} /* Gpt_DeInit */
#endif /* GPT_DEINIT_API */

/* Design : GPT_DesignId_006 */

#if (STD_ON == GPT_CFG_TIME_ELAPSED_API)
/*
 * Requirements : SWS_Gpt_00282, SWS_Gpt_00010, SWS_Gpt_00361, SWS_Gpt_00295
 *                SWS_Gpt_00297, SWS_Gpt_00299, SWS_Gpt_00113, SWS_Gpt_00195
 *                SWS_Gpt_00222, SWS_Gpt_00210, SWS_Gpt_00113, SWS_Gpt_00195
 */
/*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
/*LDRA_INSPECTED 8 D : MISRAC_2012_R2.2
 * "Reason - Code inspected LDRA tool error " */

FUNC(Gpt_ValueType, GPT_CODE) Gpt_GetTimeElapsed( Gpt_ChannelType channel )
{
   Gpt_ValueType     UpdCompare_t = 0U;
   Gpt_ValueType     Compare_t = 0U;
   Gpt_ValueType     FreeRunningCounter_t ;
   Gpt_ChannelMode   ChannelMode_t ;
   Gpt_ValueType     Return_Value = 0U;
   uint32            Gpt_rtiChAddr; 
   uint32            exitCondition = FALSE; /*Used to solve METRICS.E.HIS_Metrics___Max_nesting_level_LEVEL issue*/
      /* Check if the driver has been successfully initialized. If the driver
       * has not been initialized, report an error and return from Api.
       */
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT )
      if (NULL_PTR == Gpt_Config_pt )
      {
         (void)Gpt_reportDetError(GPT_SID_GET_TIME_ELAPSED, GPT_E_UNINIT);
         exitCondition = TRUE;
      }
      /* Check if parameter channel is in valid range. If its value is out
       * of range report an error and return from the function.    */
      if ((exitCondition == FALSE) && (channel > GPT_RTI_CH_MAX))
      {
         (void)Gpt_reportDetError( GPT_SID_GET_TIME_ELAPSED, GPT_E_PARAM_CHANNEL );
         exitCondition = TRUE;
      }
 #endif
 { 
        uint16  channelIdx = Gpt_ChConfig_map[channel];
     /* Check if timer is in "initialized" state, if TRUE return value = 0"*/
     /* SWS_Gpt_00295: If timer is in "initialized" state, by default return value = 0 */
     if ((exitCondition == FALSE) && (GPT_INITIALIZED != Gpt_ChannelState[channel]))
     {
        Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(channel);
        /* Critical section, block the interrupts */
        SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_0();
        /*Read the Counter, update counter and free running counter values of the channel*/

        /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
         * "Reason - Cast for register address " */
        /*LDRA_INSPECTED 91 D : MISRAC_2012_R4.7
         * "Reason - Return value used  " */
        FreeRunningCounter_t = Gpt_GetCounter_Values((rtiBASE_t *)Gpt_rtiChAddr,
         channel, &UpdCompare_t, &Compare_t);

        ChannelMode_t = (Gpt_Config_pt->ChannelConfig_pt[channelIdx].ChannelMode);

        /* SWS_Gpt_00299: Return the target time if the channel is
          * expired, else return the relative difference */
        if (GPT_CH_MODE_ONESHOT == ChannelMode_t)
        {
            if (GPT_EXPIRED == Gpt_ChannelState[channel])
            {
               Return_Value = Mod_Difference (Compare_t, Gpt_ChStartTime_map[channel]);
            }
            else
            {
               Return_Value = Mod_Difference (FreeRunningCounter_t, Gpt_ChStartTime_map[channel]);
            }
        }
        /* Continuous Mode */
        else
        {
           /*Find the relative difference b/w Compare and Free running counter*/
           Return_Value = UpdCompare_t - Mod_Difference (Compare_t, FreeRunningCounter_t);
        }
        /* Critical section, restore the interrupts */
        SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_0();
      }
    }
    return Return_Value;
} /* Gpt_GetTimeElapsed */
#endif /* (STD_ON == GPT_CFG_USE_GET_TIME_ELAPSED) */


/* Design : GPT_DesignId_007 */

#if (STD_ON == GPT_CFG_TIME_REMAINING_API)
/*
 * Requirements : SWS_Gpt_00283, SWS_Gpt_00083, SWS_Gpt_00301, SWS_Gpt_00303
 *                SWS_Gpt_00305, SWS_Gpt_00114, SWS_Gpt_00196, SWS_Gpt_00223
 *                SWS_Gpt_00211
 */
/*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
/*LDRA_INSPECTED 8 D : MISRAC_2012_R2.2
 * "Reason - Code inspected LDRA tool error " */

FUNC(Gpt_ValueType, GPT_CODE) Gpt_GetTimeRemaining( Gpt_ChannelType channel )
{
   Gpt_ValueType     Compare_t = 0U;
   Gpt_ValueType     UpdateCompare_t = 0U;
   Gpt_ChannelMode   ChannelMode_t;
   Gpt_ValueType     FreeRunningCounter_t ;
   uint32            Return_Value = 0U;
   uint32            Gpt_rtiChAddr;
   /* Check if the driver has been successfully initialized. If the driver
    * has not been initialized, report an error and return from Api.
    */
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT )
   if (NULL_PTR == Gpt_Config_pt )
   {
      (void)Gpt_reportDetError(GPT_SID_GET_TIME_REMAINING, GPT_E_UNINIT);
   }
   /* Check if parameter channel is in valid range. If its value is out
    * of range report an error and return from the function.    */
   else if (channel > GPT_RTI_CH_MAX)
   {
      (void)Gpt_reportDetError( GPT_SID_GET_TIME_REMAINING, GPT_E_PARAM_CHANNEL );
   }
   else
#endif
   {
      uint16             channelIdx = Gpt_ChConfig_map[channel];
     /* Check if timer is in "initialized" state, if TRUE return value = 0"*/
     /* SWS_Gpt_00301: If timer is in "initialized" state, by default return value = 0. */
     if (GPT_INITIALIZED != Gpt_ChannelState[channel])
     {
        Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(channel);

        /* Critical section, block the interrupts */
        SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_0();

        /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
        * "Reason - Cast for register address " */
        /*LDRA_INSPECTED 91 D : MISRAC_2012_R4.7
        * "Reason - Return value used  " */
        FreeRunningCounter_t = Gpt_GetCounter_Values((rtiBASE_t *)Gpt_rtiChAddr,
         channel, &UpdateCompare_t, &Compare_t);

        /* Critical section, restore the interrupts */
        SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_0();

        /*Read the channel mode from the channel configuration*/
        ChannelMode_t = (Gpt_Config_pt->ChannelConfig_pt[channelIdx].ChannelMode);

        /*Check if the channel is in Continuous mode, find the remaining time value*/
        /*If the channel is expired in one-shot mode, by default return value = 0, if timer expired */
        /* Klocwork Inspected
         * MISRA.ETYPE.INAPPR.OPERAND.BINOP.2012
         * Reason - Code Readibility and Space Optimization
        */
        Return_Value = ((ChannelMode_t == GPT_CH_MODE_CONTINUOUS) ||
            (GPT_EXPIRED != Gpt_ChannelState[channel])) * Mod_Difference (Compare_t, FreeRunningCounter_t);
      }
    }
    return (Return_Value);
} /* Gpt_GetTimeRemaining */
#endif /* (STD_ON == GPT_CFG_USE_GET_TIME_REMAINING) */

/* Design : GPT_DesignId_008 */
/*
 * Requirements : SWS_Gpt_00284, SWS_Gpt_00274, SWS_Gpt_00275, SWS_Gpt_00115
 *                SWS_Gpt_00364, SWS_Gpt_00212, SWS_Gpt_00218, SWS_Gpt_00224
 *                SWS_Gpt_00084
 */
/*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
FUNC(void, GPT_CODE) Gpt_StartTimer( Gpt_ChannelType channel, Gpt_ValueType value )
{
   
   uint32 exitCondition = FALSE; /*Used to solve METRICS.E.HIS_Metrics___Max_nesting_level_LEVEL issue*/
   /* Check if the driver has been successfully initialized. If the driver
    * has not been initialized, report an error and return immediately.
    */
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
   if (NULL_PTR == Gpt_Config_pt)
   {
      (void)Gpt_reportDetError(GPT_SID_START_TIMER, GPT_E_UNINIT);
      exitCondition = TRUE;
   }
   /* Check if parameter channel is in valid range and not in Uninitialized mode. If its value is out
    * of range report an error and set flag.
    */
   if ((exitCondition == FALSE) && (( channel > GPT_RTI_CH_MAX) ||
           (GPT_UNINITIALIZED == Gpt_ChannelState[channel])))
   {
      (void)Gpt_reportDetError( GPT_SID_START_TIMER, GPT_E_PARAM_CHANNEL );
      exitCondition = TRUE;
   }
   /* Check if parameter value is in valid range. If "0" is specified as
    * value, report an error and set flag.
    */
   if ((exitCondition == FALSE) && ((value == 0U) || (value == MAX_RESOLUTION)) )
   {
      (void)Gpt_reportDetError ( GPT_SID_START_TIMER, GPT_E_PARAM_VALUE );
      exitCondition = TRUE;
   }
#endif
   if (exitCondition == FALSE)
   {
       /*Check if channel is running, report error GPT_E_BUSY if channel already in "Running" state*/
       if (GPT_RUNNING == Gpt_ChannelState[channel])
       {
          (void)Gpt_reportRuntimeError( GPT_SID_START_TIMER, GPT_E_BUSY );
       }
       else
       {
          uint16 channelIdx = Gpt_ChConfig_map[channel];
          /* Critical section, block the interrupts */
          SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_0();

		  /*Set the channel mode for notification index*/
		  Gpt_IsrIndex[channel] = (uint32)Gpt_Config_pt->ChannelConfig_pt[channelIdx].ChannelMode;

		  /*Set the register settings required to start selected channel with defined target time*/
		  /* Requirements : SWS_Gpt_00329, SWS_Gpt_00186, SWS_Gpt_00330 */
		  Gpt_SetRegStartTimer(channel, value);

		  /*Set the channel state to "Running"*/
		  /* SWS_Gpt_00364: Set the channel state to "Running"*/
		  Gpt_ChannelState[channel] = GPT_RUNNING;

		  /* Critical section, restore the interrupts */
		  SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_0();

        }/*if (Dev_Error_Flag == FALSE)*/
   }

}/* Gpt_StartTimer */

/*LDRA_INSPECTED 65 D : MISRAC_2012_R.2.2
 * "Reason - Void function does have side effect. It is updating  GPT register "
 **/
static FUNC(void, GPT_CODE) Gpt_SetRegStartTimer(Gpt_ChannelType channel, Gpt_ValueType value )
{
   Gpt_ChannelMode ChannelMode_t;
   uint32 tickFreq;
   uint32 Gpt_rtiChAddr;
   uint16 channelIdx = Gpt_ChConfig_map[channel];

   /*Read the Channel Id and channel mode from configured channel*/
   ChannelMode_t = Gpt_Config_pt->ChannelConfig_pt[channelIdx].ChannelMode;
   tickFreq = Gpt_Config_pt->ChannelConfig_pt[channelIdx].GptChannelTickFrequency;
   Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(channel);

    /*Configure the register with the tick frequency and the period value*/
    /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
     * "Reason - Cast for register address " */
    /*LDRA_INSPECTED 105 D : MISRAC_2012_R2.2
      * "Reason - Code inspected LDRA tool error " */
     Gpt_RTI_StartTimer((rtiBASE_t *)Gpt_rtiChAddr, channel, tickFreq, ChannelMode_t, value);
    /*Set the notify function pointer*/
    Gpt_ChannelNotifyFunctions[channel] = Gpt_Config_pt->ChannelConfig_pt[channelIdx].Notification_pt;

}


/* Design : GPT_DesignId_009 */
/*
 * Requirements : SWS_Gpt_00285, SWS_Gpt_00013, SWS_Gpt_00343, SWS_Gpt_00099
 *                SWS_Gpt_00344, SWS_Gpt_00116, SWS_Gpt_00213, SWS_Gpt_00225
 */
/*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
FUNC(void, GPT_CODE) Gpt_StopTimer( Gpt_ChannelType channel )
{
   /* Lower 2 bits determine the compare block - (0, 1, 2, 3) */
   uint32 Gpt_rtiChAddr;
   uint32 exitCondition = FALSE; /*Used to solve METRICS.E.HIS_Metrics___Max_nesting_level_LEVEL issue*/
   /* Check if the driver has been successfully initialized. If the driver
    * has not been initialized, report an error and return immediately.
    */
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
   if (NULL_PTR == Gpt_Config_pt)
   {
      (void)Gpt_reportDetError(GPT_SID_STOP_TIMER, GPT_E_UNINIT);
      exitCondition = TRUE;
   }
   /* Check if parameter channel is in valid range. If its value is out
    * of range report an error and return immediately.
    */
   if ((exitCondition == FALSE) && (channel > GPT_RTI_CH_MAX))
   {
      (void)Gpt_reportDetError( GPT_SID_STOP_TIMER, GPT_E_PARAM_CHANNEL );
      exitCondition = TRUE;
   }
   if (exitCondition == FALSE)
#endif
   {
      /*Check for Channel State, if channel is not in "Running" state
       * there will be no state change  */
      if ( Gpt_ChannelState[channel] == GPT_RUNNING )
      {
         Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(channel);
         /* Critical section, block the interrupts */
         SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_0();

         /* SWS_Gpt_00343: Set the channel state to "Stopped" */
         Gpt_ChannelState[channel] = GPT_STOPPED;

         /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
         * "Reason - Cast for register address " */
         /*LDRA_INSPECTED 105 D : MISRAC_2012_R2.2
         * "Reason - Code inspected LDRA tool error " */
         Gpt_RTI_StopTimer((rtiBASE_t*)Gpt_rtiChAddr, channel);

         /* Critical section, restore the interrupts */
         SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_0();
      }/*if (Channel_State == GPT_RUNNING)*/
   }
} /* Gpt_StopTimer */

/* Design : GPT_DesignId_010 */

#if (STD_ON == GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API)
/*
 * Requirements : SWS_Gpt_00286, SWS_Gpt_00014, SWS_Gpt_00117, SWS_Gpt_00199
 *                SWS_Gpt_00226, SWS_Gpt_00214, SWS_Gpt_00377
 */
 /*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
FUNC(void, GPT_CODE) Gpt_EnableNotification( Gpt_ChannelType channel )
{
   uint32 Gpt_rtiChAddr;
   uint16 channelIdx = 0U ;
   if(channel <= GPT_RTI_CH_MAX){
      channelIdx = Gpt_ChConfig_map[channel];
   }
   /* Check if the driver has been successfully initialized. If the driver
    * has not been initialized, report an error and return immediately.
    */
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
   if ( NULL_PTR == Gpt_Config_pt )
   {
      (void)Gpt_reportDetError(GPT_SID_ENABLE_NOTIFY, GPT_E_UNINIT);
   }
   /* Check if parameter channel is in valid range. If its value is out
    * of range report an error and return immediately.
    */
   else if (( channel > GPT_RTI_CH_MAX) ||
            /* Requirements: SWS_Gpt_00377 */
            (NULL_PTR == Gpt_Config_pt->ChannelConfig_pt[channelIdx].Notification_pt))
   {
      (void)Gpt_reportDetError(GPT_SID_ENABLE_NOTIFY, GPT_E_PARAM_CHANNEL);
   }
   else
#endif
   {
      Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(channel);
      /* Critical section, block the interrupts */
      SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_0();

      /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
       * "Reason - Cast for register address " */
      /*LDRA_INSPECTED 105 D : MISRAC_2012_R2.2
       * "Reason - Code inspected LDRA tool error " */
      Gpt_RTI_EnableNotification((rtiBASE_t*)Gpt_rtiChAddr, channel);

      /* Mark the notification for this channel */
      SET(uint16, Gpt_ActiveNotifyChannels, channel);

      /* Critical section, restore the interrupts */
      SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_0();
   }

} /* Gpt_EnableNotification */
#endif /* GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API */


/* Design : GPT_DesignId_011 */
#if (STD_ON == GPT_CFG_ENABLE_DISABLE_NOTIFICATION_API)
/*
 * Requirements : SWS_Gpt_00287, SWS_Gpt_00015, SWS_Gpt_00118, SWS_Gpt_00200
 *                SWS_Gpt_00227, SWS_Gpt_00217, SWS_Gpt_00379, SWS_Gpt_00093
 */
 /*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
FUNC(void, GPT_CODE) Gpt_DisableNotification( Gpt_ChannelType channel )
{
   uint32 Gpt_rtiChAddr;
   uint16 channelIdx = 0U ;
   if(channel <= GPT_RTI_CH_MAX){
      channelIdx = Gpt_ChConfig_map[channel];
   }
   /* Check if the driver has been successfully initialized. If the driver
    * has not been initialized, report an error and return immediately.
    */
#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
   if ( NULL_PTR == Gpt_Config_pt )
   {
      (void)Gpt_reportDetError(GPT_SID_DISABLE_NOTIFY, GPT_E_UNINIT);
   }
   /* Check if parameter channel is in valid range. If its value is out
    * of range report an error and return immediately.
    */
   else if (( channel > GPT_RTI_CH_MAX) ||
            (NULL_PTR == Gpt_Config_pt->ChannelConfig_pt[channelIdx].Notification_pt))
   {
      (void)Gpt_reportDetError( GPT_SID_DISABLE_NOTIFY, GPT_E_PARAM_CHANNEL );
   }
   else
#endif
   {
        Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(channel);
        /* Critical section, block the interrupts */
        SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_0();
        /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
        * "Reason - Cast for register address " */
        /*LDRA_INSPECTED 105 D : MISRAC_2012_R2.2
        * "Reason - Code inspected LDRA tool error " */
        Gpt_RTI_DisableNotification((rtiBASE_t*)Gpt_rtiChAddr, channel);
        /* Mark the notification for this channel */
        CLEAR(uint16, Gpt_ActiveNotifyChannels, channel);
        /* Critical section, restore the interrupts */
        SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_0();
    }
}
#endif /* GPT_ENABLE_DISABLE_NOTIFICATION_API */



/***************************************************************************************************************
    Function name:  Gpt_NotifContIsr
 ***************************************************************************************************************/
/*  \Description: This Interrupt notification call function is called when timer channel is configured in
 *                Continuous mode and interrupt notification should be enabled for the channel.
 *                Gpt_StartTimer is called with the referenced channel. Once the timer channel is expired,
 *                interrupt is triggered which calls the Gpt_NotifContIsr call back function inside the timer Isr.
 *  \param[in]:  ChannelID
 *  \return:     None
 *  \context:    Called by ISR.
 *****************************************************************************************************************/
/*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is called from ISR  " */
/*LDRA_INSPECTED 8 D : MISRAC_2012_R2.2
 * "Reason - Code inspected LDRA tool error " */
FUNC(void, GPT_CODE) Gpt_NotifContIsr( Gpt_ChannelType Channel )
{
   uint32 Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(Channel);
   /* Critical section, block the interrupts */
   SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_0();

    /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
     * "Reason - Cast for register address " */
    /*LDRA_INSPECTED 105 D : MISRAC_2012_R2.2
     * "Reason - Code inspected LDRA tool error " */
    Gpt_RTINotifyContIsr((rtiBASE_t *)Gpt_rtiChAddr, Channel);

   if ( NULL_PTR != ( Gpt_ChannelNotifyFunctions[Channel] ))
   {
      /* Call notification callback */
      /* Requirements : SWS_Gpt_00233, SWS_Gpt_00086 */
      Gpt_ChannelNotifyFunctions[Channel]();
   }
   /* Critical section, restore the interrupts */
   SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_0();
} /* Gpt_NotifContIsr */


/*****************************************************************************************************************
    Function name:  Gpt_NotifSingleIsr
 *****************************************************************************************************************/
/*  \Description: This Interrupt notification callback function is called when timer channel is configured in
 *                Single mode and interrupt notification should be enabled for the channel.
 *                Gpt_StartTimer should be called with the referenced channel. Once the timer channel is expired,
 *                interrupt is triggered and Gpt_NotifSingleIsr call back function is called inside the subroutine.
 *                This call back function will stop the timer channel in One shot mode.
  *  \param[in]:  ChannelID
 *  \return:      None
 *  \context:     Called by ISR.
  *****************************************************************************************************************/
/* Requirements : SWS_Gpt_00206, SWS_Gpt_00209*/
/*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is called from ISR " */
/*LDRA_INSPECTED 8 D : MISRAC_2012_R2.2
 * "Reason - Code inspected LDRA tool error " */
FUNC(void, GPT_CODE) Gpt_NotifSingleIsr( Gpt_ChannelType Channel )
{
   uint32 Gpt_rtiChAddr = Gpt_GetRTIChannelAddr(Channel);
   /* Critical section, block the interrupts */
   SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_0();

   /* Mark the channel as inactive */

   /* Requirements: SWS_Gpt_00185 */
   Gpt_ChannelState[Channel] = GPT_EXPIRED;

   /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
    * "Reason - Cast for register address " */
    /*LDRA_INSPECTED 105 D : MISRAC_2012_R2.2
        * "Reason - Code inspected LDRA tool error " */
   Gpt_RTINotifySingleIsr((rtiBASE_t *)Gpt_rtiChAddr, Channel);

   if ( NULL_PTR != ( Gpt_ChannelNotifyFunctions[Channel] ))
   {
      /* Call notification callback */
      /* Requirements: SWS_Gpt_00331 */
      Gpt_ChannelNotifyFunctions[Channel]();
   }
   /* Critical section, restore the interrupts */
   SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_0();

} /* Gpt_NotifSingleIsr */



#if (STD_ON == GPT_CFG_DEV_ERROR_DETECT)
void Gpt_reportDetError(uint8 apiId, uint8 errorId)
{
    (void) Det_ReportError(GPT_MODULE_ID, GPT_INSTANCE_ID, apiId, errorId);
}

#endif  /* #if (STD_ON == GPT_CFG_DEV_ERROR_DETECT) */

void Gpt_reportRuntimeError(uint8 apiId, uint8 errorId)
{
    (void) Det_ReportRuntimeError(GPT_MODULE_ID, GPT_INSTANCE_ID, apiId, errorId);
}


#if (STD_ON == GPT_CFG_REGISTER_READBACK_API)
/*   Design :GPT_DesignId_013
  * Requirements : AUTORADAR_MCAL-53
  */
  /*LDRA_INSPECTED 76 D : MISRAC_2012_R.8.7
* "Reason - This is external APIs " */
/*LDRA_INSPECTED 8 D : MISRAC_2012_R2.2
 * "Reason - Code inspected LDRA tool error " */
FUNC(Std_ReturnType, GPT_CODE) Gpt_ConfigRegReadBack( GptConfigReg* GptConfigReg_pt)
{
    VAR(Std_ReturnType, AUTOMATIC)  Gpt_RetTmp;
    Gpt_ChannelType Gpt_Channel;
    Gpt_RetTmp  = (Std_ReturnType)E_NOT_OK;
    if ((NULL_PTR != GptConfigReg_pt ) && (NULL_PTR != Gpt_Config_pt))
    {
        Gpt_Channel = Gpt_Config_pt->ChannelConfig_pt[channel].ChannelId;
        /*LDRA_INSPECTED 440 S : MISRAC_2012_R11.1
        * "Reason - Cast for register address " */
        Gpt_RegReadBack((rtiBASE_t *)Gpt_GetRTIChannelAddr(Gpt_Channel), GptConfigReg_pt);

        Gpt_RetTmp = (Std_ReturnType)E_OK;
    }
   return Gpt_RetTmp;
}
#endif

#define GPT_STOP_SEC_CODE
/*LDRA_INSPECTED 338 S : MISRAC_2012_R.20.1
 * "Reason - Required to comply with AUTOSAR memmap spec " */
#include "Gpt_MemMap.h"
/* eof */


