/**********************************************************************************************************************
 *  COPYRIGHT
 *  -------------------------------------------------------------------------------------------------------------------
 *  \verbatim
 *
 *                 TEXAS INSTRUMENTS INCORPORATED PROPRIETARY INFORMATION
 *
 *                 Property of Texas Instruments, Unauthorized reproduction and/or distribution
 *                 is strictly prohibited.  This product  is  protected  under  copyright  law
 *                 and  trade  secret law as an  unpublished work.
 *                 (C) Copyright Texas Instruments.  All rights reserved.
 *
 *  \endverbatim
 *  -------------------------------------------------------------------------------------------------------------------
 *  FILE DESCRIPTION
 *  -------------------------------------------------------------------------------------------------------------------
 *         File:  Port.c
 *      Project:  Tms570_AutoSarPortDriver
 *       Module:  PortDriver
 *    Generator:  -
 *
 *  Description:  This module implements a driver in ANSI C programming language to centralize the
 *                configuration of ports and pins which are used by more than one driver module.
 *                With this driver you can:
 *                - Configure all port pins
 *                - Initialize the configuration
 *                - Refresh the configuration (EMC purposes)
 *                - Switch the port pin configuration during runtime
 *---------------------------------------------------------------------------------------------------------------------
 * Author:  Sunil Kumar T V
 *---------------------------------------------------------------------------------------------------------------------
 * Revision History
 *---------------------------------------------------------------------------------------------------------------------
 * Version        Date         Author                 Change ID       Description
 *---------------------------------------------------------------------------------------------------------------------
 * 02.10.00       11Feb2013    Sapthagiri G           0000000000000   Initial version (adapted from TMS570LS3xx v01.10.00).
 * 02.20.00       29Aug2013    Sreyas K               SDOCM00103509   Changes for Production Version Champion
 * 02.21.00       30Sep2014    Vineeth T Alex         SDOCM00113123   Changes for 2.21.00 release; Files restructured
 * 02.21.01       23Aug2016    VishwanathReddy        SDOCM00122619   Update version info. 
 * 02.30.00       01Dec2016    Sudhakar Singh         None            Update version info
 * 05.30.00       15Mar2017    Sudhakar Singh         SDOCM00122834   Version supports TMS570LSxx Family of Devices.
 *********************************************************************************************************************/

#define PORT_SOURCE

/**********************************************************************************************************************
 *  INCLUDES
 *********************************************************************************************************************/
/* SourceId : Port_SourceId_024 */
/* DesignId : Port_DesignId_04  */
/* Requirements : AR_PORT_SR1, AR_PORT_SR2, AR_PORT_SR3, AR_PORT_SR4, AR_PORT_SR5, AR_PORT_SR6, AR_PORT_SR7, */
#include "Std_Types.h"
#include "Port.h"
#if (PORT_DEV_ERROR_DETECT == STD_ON)
/* Include-File, which contains Errorhook-Function                            */
 /*<PORT_DET_INCLUDE_FILE>*/
#include "Det.h"
/*</PORT_DET_INCLUDE_FILE>*/
#endif

 /* Include list - here you must insert the Irq.h or Os.h file, dependent,
  * which function you will use to protect critical sections */
 /*<PORT_CFG_INCLUDE_IRQ>*/
#include "SchM_Port.h"
/*</PORT_CFG_INCLUDE_IRQ>*/

/**********************************************************************************************************************
 *  VERSION CHECK
 *********************************************************************************************************************/
#define  PORT_SW_C_MAJOR_VERSION               (5U)
#define  PORT_SW_C_MINOR_VERSION               (30U)
#define  PORT_SW_C_PATCH_VERSION               (0U)
 
 /* AUTOSAR version information check has to match definition in header file */
#if ((PORT_AR_RELEASE_MAJOR_VERSION != 0x04) || \
    (PORT_AR_RELEASE_MINOR_VERSION != 0x00) || \
    (PORT_AR_RELEASE_REVISION_VERSION != 0x03))
   #error "Port: AUTOSAR Version Numbers of Port Driver are different"
#endif

 /* Vendor specific version  */
#if ((PORT_SW_MAJOR_VERSION != PORT_SW_C_MAJOR_VERSION) || \
     (PORT_SW_MINOR_VERSION != PORT_SW_C_MINOR_VERSION))
   #error "Vendor specific version numbers of Port.c and Port.h are inconsistent"
#endif

/* Versions of all included header files shall be checked, configuration is just an example */
#if ((PORT_CFG_MAJOR_VERSION != PORT_SW_C_MAJOR_VERSION) || \
     (PORT_CFG_MINOR_VERSION != PORT_SW_C_MINOR_VERSION))
   #error "Version numbers of Port.c and Port_Cfg.h are inconsistent!"
#endif


/**********************************************************************************************************************
 *  MACRO DEFINITIONS
 *********************************************************************************************************************/
#define Port_GlobalSuspend() /*<PORT_GLOBAL_SUSPEND/>*/ SchM_Enter_Port_PORT_EXCLUSIVE_AREA_0()
#define Port_GlobalRestore() /*<PORT_GLOBAL_RESTORE/>*/ SchM_Exit_Port_PORT_EXCLUSIVE_AREA_0()

/**********************************************************************************************************************
 *  GLOBAL DATA
 *********************************************************************************************************************/
/* Memory mapping, done via MemMap.h: Variables that are initialised */
#define PORT_START_SEC_VAR_UNSPECIFIED
#include "MemMap.h"

/* Global buffer for the pointer to the current configuration             */
/*SAFETYMCUSW 440 S MR:10.1 <APPROVED> "Reason -  Typecasted at compiler, Platform_types.h"*/
static P2CONST(Port_ConfigType, PORT_VAR, PORT_PBCFG) Port_ConfigPtr_pt = NULL_PTR;

/* Memory mapping, done via MemMap.h: Variables that are initialised */
/*SAFETYMCUSW 580 S MR:1.1 <APPROVED> "Reason - This is the format for specifying memory sections" */
#define PORT_STOP_SEC_VAR_UNSPECIFIED
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format for specifying memory sections" */
#include "MemMap.h"

/* Memory mapping, done via MemMap.h: Code */
/*SAFETYMCUSW 580 S MR:1.1 <APPROVED> "Reason -  This is the format for specifying memory sections" */
#define PORT_START_SEC_CODE
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format for specifying memory sections" */
#include "MemMap.h"

/**********************************************************************************************************************
 *  LOCAL FUNCTIONS
 *********************************************************************************************************************/
#if (STD_ON == PORT_SET_PIN_DIRECTION_API )
   static FUNC(void, PORT_CODE) _Port_SetDirectionReg(Port_PinType Pin, Port_PinDirectionType Direction);
#endif

/**********************************************************************************************************************
 *  GLOBAL FUNCTIONS
 *********************************************************************************************************************/

/**********************************************************************************************************************
 *  Port_Init
 *********************************************************************************************************************/
/*! \brief      Initialization of whole port registers, ports and pins and selection of port functionality
 *  \param[in]  ConfigPtr        pointer to the port configuration struct.
 *  \pre        Input parameter must not be NULL_PTR.
 *  \context    Function should be called from user context
  ********************************************************************************************************************/
/* SourceId : Port_SourceId_012 */
/* DesignId : Port_DesignId_10  */
/* Requirements : AR_PORT_SR39, AR_PORT_SR40, AR_PORT_SR43 */
FUNC(void, PORT_CODE) Port_Init(P2CONST( Port_ConfigType, AUTOMATIC, PORT_PBCFG) ConfigPtr)
{
#if (STD_ON == PORT_DEV_ERROR_DETECT)
   /* Call of Errorhook if parameter refers to NULL */
   /* SourceId : Port_SourceId_007 */
	/* DesignId : Port_DesignId_10  */
   /* Requirements : AR_PORT_SR28, AR_PORT_SR56, AR_PORT_SR32, AR_PORT_SR33 */
   /*SAFETYMCUSW 440 S MR:10.1 <APPROVED> "Reason -  Typecasted at compiler, Platform_types.h"*/
   if(NULL_PTR == ConfigPtr)
   {
	   /*SAFETYMCUSW 93 S MR:6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "Type is appropriate"*/
      (void)Port_Errorhook(PORT_SID_INIT, PORT_E_PARAM_CONFIG);
   }
   else
#endif /*(STD_ON == PORT_DEV_ERROR_DETECT)*/
   /* SourceId : Port_SourceId_008 */
   /* DesignId : Port_DesignId_10  */
   /* Requirements : AR_PORT_SR34 */
   {
      /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason - ConfigPtr is checked for NULL_PTR" */
      Port_ConfigPtr_pt = ConfigPtr;
      /* Set all registers to configured values */
	  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason - ConfigPtr is checked for NULL_PTR" */
      Port_ConfigPtr_pt->Port_InitPortPins_t();
   }
}   /* Port_Init() */

/* SourceId : Port_SourceId_013 */
/* DesignId : Port_DesignId_11  */
/* Requirements : AR_PORT_SR61 */
#if (STD_ON == PORT_SET_PIN_DIRECTION_API)
/**********************************************************************************************************************
 *  Port_SetPinDirection
 *********************************************************************************************************************/
/*! \brief      This function sets the direction of each configured pin
 *              if allowed.
 *
 *  \param[In]  Pin               Configured handle of a port pin.
 *  \param[In]  Direction         Required pin direction
 *  \pre        Module have to be initialized.
 *  \context    Function could be called from interrupt level or from task level
  ********************************************************************************************************************/
/* SourceId : Port_SourceId_002 */
/* DesignId : Port_DesignId_11  */
/* Requirements : AR_PORT_SR13, AR_PORT_SR60 */
FUNC(void, PORT_CODE) Port_SetPinDirection(Port_PinType Pin, Port_PinDirectionType Direction)
{
#if (STD_ON == PORT_DEV_ERROR_DETECT)

	/* Check if module has been initialzied. */
	/*SAFETYMCUSW 440 S MR:10.1 <APPROVED> "Reason -  Typecasted at compiler, Platform_types.h"*/
	if (NULL_PTR == Port_ConfigPtr_pt)
	{
      /* Report error to an Errorhook function. */
		/*SAFETYMCUSW 93 S MR:6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "Type is appropriate"*/
      (void)Port_Errorhook(PORT_SID_SET_PIN_DIR, PORT_E_UNINIT);
	}
	/* Check of the parameter "pin" enabled ? */
	/*  Is the parameter "pin" a part of the list */
	else if(Pin >= (Port_ConfigPtr_pt->NumberOfPinChannels_u8) )
	{
	  /* Parameter was not ok  */
	  /* Report error to an Errorhook function  */
		/*SAFETYMCUSW 93 S MR:6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "Type is appropriate"*/
	  (void)Port_Errorhook( PORT_SID_SET_PIN_DIR, PORT_E_PARAM_PIN);
	  /*SAFETYMCUSW 331 S MR:10.1 <APPROVED> "Reason -  Comes from compiler"*/
	}  /* else: Parameter was not ok */
	/* SourceId : Port_SourceId_009 */
	/* DesignId : Port_DesignId_11  */
	/* Requirements : AR_PORT_SR34 */
	/*SAFETYMCUSW 331 S MR:10.1 <APPROVED> "Reason -  Comes from compiler"*/
	/*SAFETYMCUSW 139 S MR:13.7 <APPROVED> "Reason - Inspected, comparing TRUE or FALSE"*/
	else
	{
#endif
	/* Call the internal function to set direction register */
	_Port_SetDirectionReg(Pin, Direction);
#if (STD_ON == PORT_DEV_ERROR_DETECT)
	}/*if(FALSE == Port_Dev_Error_Flag)*/
#endif
	/* Normal Return */
}  /* Port_SetPinDirection */

/**********************************************************************************************************************
 *  _Port_SetDirectionReg
 *********************************************************************************************************************/
/*! \brief      This function configures the direction register of required pin
 *              appropriately.
 *
 *  \param[In]  Pin               Configured handle of a port pin.
 *  \param[In]  Direction         Required pin direction
 *  \pre        Module have to be initialized.
 *  \context    Function should be called from Port_SetPinDirection API
  ********************************************************************************************************************/
static FUNC(void, PORT_CODE) _Port_SetDirectionReg(Port_PinType Pin, Port_PinDirectionType Direction)
{
   /* Check, which direction shall be set */
   if(PORT_PIN_OUT == Direction)
   {
      /* Suspend all interrupts */
      Port_GlobalSuspend();
      /*  Set the configured pin (only for changeable pins) */
      /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - To access port register structure" */
      (((Port_RegisterPtrType)((Port_ConfigPtr_pt->PinChlConfig_pt[Pin] >> (uint32)(8U))
         | (uint32)(0xFF000000U)))->Reg.Direction_u32 )
         |= (((uint32)(0x1U) << (Port_ConfigPtr_pt->PinChlConfig_pt[Pin] & (uint32)(0xFFU))));

      /* Restore all interrupts */
      Port_GlobalRestore();
   }
   else /* Direction is set to Input */
   {
      /* Suspend all interrupts */
      Port_GlobalSuspend();

      /* Clear the pin (only for changeable pins) */
      /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - To access port register structure" */
      (((Port_RegisterPtrType)((Port_ConfigPtr_pt->PinChlConfig_pt[Pin] >> (uint32)(8U))
         | (uint32)(0xFF000000U)))->Reg.Direction_u32 )
         &= (~((uint32)(0x1U) << (Port_ConfigPtr_pt->PinChlConfig_pt[Pin] & (uint32)(0xFFU))));

      /* Restore all interrupts */
      Port_GlobalRestore();
   }
} /* _Port_SetDirectionReg */
#endif  /* (STD_ON == PORT_SET_PIN_DIRECTION_API) */

#if (STD_ON == PORT_REFRESH_PORT_DIRECTION_API)
/**********************************************************************************************************************
 *  Port_RefreshPortDirection
 *********************************************************************************************************************/
/*! \brief      This function refresh the pin direction.
 *
 *  \pre        Module have to be initialized.
 *  \context    Function could be called from interrupt level or from task level.
 *********************************************************************************************************************/
/* SourceId : Port_SourceId_003 */
/* DesignId : Port_DesignId_12  */
 /* Requirements : AR_PORT_SR15, AR_PORT_SR62, AR_PORT_SR63 */
FUNC(void, PORT_CODE) Port_RefreshPortDirection(void)
{
   /* Function local variables */
   uint32 LoopCount_u32;       /* Counter variable */
   uint32 MaxCount_u32;        /* Boundary for loop-counter */
#if (STD_ON == PORT_DEV_ERROR_DETECT)
   /* Check if module has been initialized. */
   /*SAFETYMCUSW 440 S MR:10.1 <APPROVED> "Reason -  Typecasted at compiler, Platform_types.h"*/
   if (NULL_PTR == Port_ConfigPtr_pt)
   {
      /* Report error to an Errorhook function. */
	   /*SAFETYMCUSW 93 S MR:6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "Type is appropriate"*/
      (void)Port_Errorhook(PORT_SID_REFRESH_PORT_DIR, PORT_E_UNINIT);
   }
   /* SourceId : Port_SourceId_010 */
   /* DesignId : Port_DesignId_12  */
   /* Requirements : AR_PORT_SR34 */
   /*SAFETYMCUSW 331 S MR:10.1 <APPROVED> "Reason -  Comes from compiler"*/
   /*SAFETYMCUSW 139 S MR:13.7 <APPROVED> "Reason - Inspected, comparing TRUE or FALSE"*/
   else
   {
#endif
      /* Store the loop counter boundary for the next loop */
      MaxCount_u32 = Port_ConfigPtr_pt->NumberOfRefreshPorts_u8;

      /* Suspend all interrupts */
      Port_GlobalSuspend();

      /* Refresh the direction registers with taking account of direction changeable pins (these are not refreshable)*/
      for ( LoopCount_u32 = (uint32)0U; MaxCount_u32 > LoopCount_u32; LoopCount_u32++ )
      {
         (((Port_ConfigPtr_pt->RefreshConfig_pt[LoopCount_u32]).RegisterBaseAddr_pt)->Reg.Direction_u32 )=
            /* Read back the current register content to get the
             * current valid direction settings (also the settings of pins
             * which are direction-changeable) */
             (((Port_ConfigPtr_pt->RefreshConfig_pt[LoopCount_u32].InitialDirection_u32) &
             (Port_ConfigPtr_pt->RefreshConfig_pt[LoopCount_u32].RefreshMask_u32)) |
             ((~Port_ConfigPtr_pt->RefreshConfig_pt[LoopCount_u32].RefreshMask_u32) &
             ((Port_ConfigPtr_pt->RefreshConfig_pt[LoopCount_u32].RegisterBaseAddr_pt)->Reg.Direction_u32 )));
      }   /* End for loop to refresh all configured register settings */

      /* Restore all interrupts */
      Port_GlobalRestore();

#if (STD_ON == PORT_DEV_ERROR_DETECT)
    }
#endif
}  /* Port_RefreshPortDirection() */

#endif  /*(STD_ON == PORT_REFRESH_PORT_DIRECTION_API)*/

#if (STD_ON == PORT_SET_PIN_MODE_API)
/**********************************************************************************************************************
 *  Port_SetPinMode
 *********************************************************************************************************************/
/*! \brief      This function allows to change the Pin Mode during runtime;
 *              At present this feature is not supported.
 *
 *  \param[In]  Pin               Configured handle of a port pin.
 *  \param[In]  Mode              The Mode the port pin should setted
 *  \pre        Module have to be initialized.
 *  \context    Function could be called from interrupt level or from task level
  ********************************************************************************************************************/
/* SourceId : Port_SourceId_016 */
/* DesignId : Port_DesignId_03  */
/* Requirements : AR_PORT_SR70, AR_PORT_SR71, AR_PORT_SR73 */
FUNC(void, PORT_CODE) Port_SetPinMode(Port_PinType Pin, Port_PinModeType Mode)
{
#if (STD_ON == PORT_DEV_ERROR_DETECT)
	/*SAFETYMCUSW 93 S MR:6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "Type is appropriate"*/
   (void)Port_Errorhook(PORT_SID_SET_PIN_MODE, PORT_E_PARAM_INVALID_MODE);
#endif /*(STD_ON == PORT_DEV_ERROR_DETECT)*/
}
#endif /*(STD_ON == PORT_SET_PIN_MODE_API)*/

/* SourceId : Port_SourceId_015 */
/* DesignId : Port_DesignId_13  */
/* Requirements : AR_PORT_SR67 */
#if (STD_ON == PORT_VERSION_INFO_API)
/**********************************************************************************************************************
 *  Port_GetVersionInfo
 *********************************************************************************************************************/
/*! \brief      This service returns the version information of this module.
 *              The version information includes:
 *                 - Module Id
 *                 - Vendor Id
 *                 - Vendor specific version numbers
 *
 *  \param[out] versioninfo        pointer to struct of type Std_VersionInfoType
 *  \pre        Output parameter must not be NULL_PTR.
 *  \context    Function could be called from interrupt level or from task level
  ********************************************************************************************************************/
/* SourceId : Port_SourceId_014 */
/* DesignId : Port_DesignId_13  */
/* Requirements : AR_PORT_SR65 */
FUNC(void, PORT_CODE) Port_GetVersionInfo(P2VAR(Std_VersionInfoType, AUTOMATIC, PORT_APPL_DATA) versioninfo )
{
#if (STD_ON == PORT_DEV_ERROR_DETECT)
	/*  Check parameter for NULL_PTR.  */
	/*SAFETYMCUSW 440 S MR:10.1 <APPROVED> "Reason -  Typecasted at compiler, Platform_types.h"*/
	if (NULL_PTR == versioninfo)
	{
		/*SAFETYMCUSW 93 S MR:6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "Type is appropriate"*/
      (void)Port_Errorhook(PORT_SID_GET_VERSION_INFO, PORT_E_PARAM_POINTER);
	}
	/* SourceId : Port_SourceId_011 */
	/* DesignId : Port_DesignId_13  */
	/* Requirements : AR_PORT_SR34 */
	else
	{
#endif
      /* Fill the version info */
      versioninfo->vendorID         = PORT_VENDOR_ID;
      versioninfo->moduleID         = PORT_MODULE_ID;
      versioninfo->sw_major_version = (uint8)PORT_SW_MAJOR_VERSION;
      versioninfo->sw_minor_version = (uint8)PORT_SW_MINOR_VERSION;
      versioninfo->sw_patch_version = (uint8)PORT_SW_PATCH_VERSION;
#if (STD_ON == PORT_DEV_ERROR_DETECT)
    }
#endif
}   /*  Port_GetVersionInfo()  */
#endif  /*(STD_ON == PORT_VERSION_INFO_API)*/

/* SourceId : Port_SourceId_023 */
/* DesignId : Port_DesignId_15  */
/* Requirements : AR_PORT_SR96 */
#if (STD_ON == PORT_SAFETI_API)
/**********************************************************************************************************************
 *  Port_GetConfigRegValues
 *********************************************************************************************************************/
 /*! \brief      This service returns current/initial configuration items as from the GUI.
 *               The version information includes:
 *
 *
 *  \param[out] ConfigRegPtr        pointer to struct of type PortConfigRegsType
 *  \param[in]  initial        		a boolean, if TRUE will return initial values, FALSE will return current values
 *  \pre        Output parameter must not be NULL_PTR, TRUE/FALSE should be passed as initial parameter.
 *  \context    Function could be called from interrupt level or from task level
  ********************************************************************************************************************/
FUNC(void, PORT_PBCODE) Port_GetConfigRegValues( uint8 initial,
									 P2VAR(PortConfigRegsType, AUTOMATIC, PORT_PBCFG) ConfigRegPtr )
{

#if (STD_ON == PORT_DEV_ERROR_DETECT)
	/*SAFETYMCUSW 440 S MR:10.1 <APPROVED> "Reason -  Typecasted at compiler, Platform_types.h"*/
	if (NULL_PTR == ConfigRegPtr){
		/*SAFETYMCUSW 93 S MR:6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "Type is appropriate"*/
		 (void)Port_Errorhook(PORT_SID_SET_CONFIGREG, PORT_E_PARAM_POINTER);
	}
	/*SAFETYMCUSW 331 S MR:10.1 <APPROVED> "Reason -  Comes from compiler"*/
	/*SAFETYMCUSW 434 S MR:10.1 <APPROVED> "Reason - Inspected, comparing TRUE or FALSE"*/
	else if(!((TRUE == initial) || (FALSE == initial))){
		/*SAFETYMCUSW 93 S MR:6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "Type is appropriate"*/
		(void)Port_Errorhook(PORT_SID_SET_CONFIGREG, PORT_E_PARAM_INVALID_MODE);
	}
	else
#endif
	{
		/*SAFETYMCUSW 95 S MR:11.1 <APPROVED> "Reason - New type needed as this type needs to be exposed to the user"*/
		/*SAFETYMCUSW 94 S MR:11.1 <APPROVED> "Reason - New type needed as this type needs to be exposed to the user"*/
		/*SAFETYMCUSW 94 S MR:11.1, 11.2, 11.4 <APPROVED> "Reason - Casting is required here "*/
		/*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/
		Port_GetConfigRegValues_Config(initial, (_PortConfigRegsType*)ConfigRegPtr);
	}
}
#endif
/* Memory mapping, done via MemMap.h: Code */
/*SAFETYMCUSW 580 S MR:1.1 <APPROVED> "Reason -  This is the format for specifying memory sections" */
#define PORT_STOP_SEC_CODE
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format for specifying memory sections" */
#include "MemMap.h"

/*********************************************************************************************************************
 *  END OF FILE: Port.c
 *********************************************************************************************************************/

