/**
*   @file    Mcl_Sema4.c
*   @version 1.0.0
*
*   @brief   AUTOSAR Mcl - Sema4 low level driver.
*   @details contains the low level driver for the Sema4 module.
*
*   @addtogroup MCL_MODULE
*   @{
*/
/*==================================================================================================
*   Project              : AUTOSAR 4.3 MCAL
*   Platform             : PA
*   Peripheral           : eDMA
*   Dependencies         : none
*
*   Autosar Version      : 4.3.1
*   Autosar Revision     : ASR_REL_4_3_REV_0001
*   Autosar Conf.Variant :
*   SW Version           : 1.0.0
*   Build Version        : MPC5777C_MCAL_1_0_0_RTM_ASR_REL_4_3_REV_0001_20190315
*
*   (c) Copyright 2006-2016 Freescale Semiconductor, Inc. 
*       Copyright 2017-2019 NXP
*   All Rights Reserved.
==================================================================================================*/
/*==================================================================================================
==================================================================================================*/

#ifdef __cplusplus
extern "C"{
#endif


/**
* @page misra_violations MISRA-C:2012 violations
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.1, External identifiers shall be distinct.
* The used compilers use more than 31 chars for identifiers.
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.2, Identifiers declared in the same scope and namespace shall be distinct.
* The used compilers use more than 31 chars for identifiers.
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.4, Macro identifiers shall be distinct.
* The used compilers use more than 31 chars for identifiers.
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.5, Identifiers shall be distinct from macro names.
* The used compilers use more than 31 chars for identifiers.
*
* @section WDG_Sema4_c_REF_1
* Violates MISRA 2012 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential 
* type category or a wider essential type.
* The cast is used to access memory mapped registers.
*
* @section WDG_Sema4_c_REF_2
* Violates MISRA 2012 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type.
* The cast is used to access memory mapped registers.
*
* @section WDG_Sema4_c_REF_3
* Violates MISRA 2012 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type.
* The cast is used to access memory mapped registers.
*
* @section WDG_Sema4_c_REF_4
* Violates MISRA 2012 Advisory Rule 20.1, #include directives should only be preceded by preprocessor directives or comments.
* <MA>_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR.
*
* @section WDG_Sema4_c_REF_5
* Violates MISRA 2012 Required Directive 4.10, Precautions shall be taken in order to prevent the contents of a header file
* being included more than once. * This violation is not fixed since the inclusion of <MA>_MemMap.h is as per AUTOSAR requirement
* [SWS_MemMap_00003].
*
*/

/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "CDD_Mcl_Cfg.h"

#ifdef MCL_SEMA4_FEATURE_API
#if (STD_ON == MCL_SEMA4_FEATURE_API)
#include "Mcl_Sema4.h"

#if (MCL_DEV_ERROR_DETECT == STD_ON)
    #include "Det.h"
#endif
#endif
#endif
/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#ifdef MCL_SEMA4_FEATURE_API
#if (STD_ON == MCL_SEMA4_FEATURE_API)

#define MCL_SEMA4_VENDOR_ID_C                    43
#define MCL_SEMA4_AR_RELEASE_MAJOR_VERSION_C     4
#define MCL_SEMA4_AR_RELEASE_MINOR_VERSION_C     3
#define MCL_SEMA4_AR_RELEASE_REVISION_VERSION_C  1
#define MCL_SEMA4_SW_MAJOR_VERSION_C             1
#define MCL_SEMA4_SW_MINOR_VERSION_C             0
#define MCL_SEMA4_SW_PATCH_VERSION_C             0

/*==================================================================================================
*                                      FILE VERSION CHECKS
==================================================================================================*/

/* Check if source file and Mcl_Sema4 header file are of the same Vendor ID */
#if (MCL_SEMA4_VENDOR_ID_C != MCL_SEMA4_VENDOR_ID)
    #error "Mcl_Sema4.c and Mcl_Sema4.h have different vendor IDs"
#endif
/* Check if source file and Mcl_Sema4 header file are of the same Autosar version */
#if ((MCL_SEMA4_AR_RELEASE_MAJOR_VERSION_C != MCL_SEMA4_AR_RELEASE_MAJOR_VERSION) || \
     (MCL_SEMA4_AR_RELEASE_MINOR_VERSION_C != MCL_SEMA4_AR_RELEASE_MINOR_VERSION) || \
     (MCL_SEMA4_AR_RELEASE_REVISION_VERSION_C != MCL_SEMA4_AR_RELEASE_REVISION_VERSION))
#error "AutoSar Version Numbers of Mcl_Sema4.c and Mcl_Sema4.h are different"
#endif
/* Check if source file and Mcl_Sema4 header file are of the same Software version */
#if ((MCL_SEMA4_SW_MAJOR_VERSION_C != MCL_SEMA4_SW_MAJOR_VERSION) || \
     (MCL_SEMA4_SW_MINOR_VERSION_C != MCL_SEMA4_SW_MINOR_VERSION) || \
     (MCL_SEMA4_SW_PATCH_VERSION_C != MCL_SEMA4_SW_PATCH_VERSION))
#error "Software Version Numbers of Mcl_Sema4.c and Mcl_Sema4.h are different"
#endif

/* Check if source file and DET header file are of the same version */
#if (MCL_DEV_ERROR_DETECT == STD_ON)
#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
#if ((MCL_SEMA4_AR_RELEASE_MAJOR_VERSION_C != DET_AR_RELEASE_MAJOR_VERSION) || \
     (MCL_SEMA4_AR_RELEASE_MINOR_VERSION_C != DET_AR_RELEASE_MINOR_VERSION))
#error "AutoSar Version Numbers of Mcl_Sema4.c and Det.h are different"
#endif
#endif
#endif /* MCL_DEV_ERROR_DETECT */

#endif
#endif
/*==================================================================================================
                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/


/*==================================================================================================
*                                       LOCAL MACROS
==================================================================================================*/


/*==================================================================================================
*                                       LOCAL CONSTANTS
==================================================================================================*/


/*==================================================================================================
*                                       LOCAL VARIABLES
==================================================================================================*/


/*==================================================================================================
*                                       GLOBAL CONSTANTS
==================================================================================================*/


/*==================================================================================================
*                                       GLOBAL VARIABLES
==================================================================================================*/
#ifdef MCL_SEMA4_FEATURE_API
#if (STD_ON == MCL_SEMA4_FEATURE_API)

#define MCL_START_SEC_VAR_INIT_UNSPECIFIED
/* @violates @ref WDG_Sema4_c_REF_4 MISRA 2012 Advisory 20.1*/
/* @violates @ref WDG_Sema4_c_REF_5 MISRA 2012 Required 4.10*/
#include "Mcl_MemMap.h"
/**
 * @brief   Stores state of all Sema4 channels (locked / unlocked)
 **/
static VAR(Mcl_Sema4BusyType, MCL_VAR) Mcl_Sema4_ChannelLocked[MCL_SEMA4_NUMBER] = {MCL_SEMA4_NOT_USED};

#define MCL_STOP_SEC_VAR_INIT_UNSPECIFIED
/* @violates @ref WDG_Sema4_c_REF_4 MISRA 2012 Advisory 20.1*/
/* @violates @ref WDG_Sema4_c_REF_5 MISRA 2012 Required 4.10*/
#include "Mcl_MemMap.h"
/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/


/*==================================================================================================
*                                       LOCAL FUNCTIONS
==================================================================================================*/


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

#define MCL_START_SEC_CODE
/* @violates @ref WDG_Sema4_c_REF_4 MISRA 2012 Advisory 20.1*/
/* @violates @ref WDG_Sema4_c_REF_5 MISRA 2012 Required 4.10*/
#include "Mcl_MemMap.h"

/**
* @details      Checks if the Semaphore channel is locked or not
*               Returns the core number if the semaphore is locked, 
*               and MCL_SEMAPHORE_FREE if it's free
*/
FUNC(uint8, MCL_CODE) Mcl_Sema4_GetGateStatus(VAR(Mcl_Sema4ChannelType, AUTOMATIC) ChannelId)
{
    VAR(uint8, AUTOMATIC) u8gateStatus;
    
    /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
    /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
    /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
    if ((uint8)0 == (uint8)(REG_READ8(SEMA4_GATE_ADDR8(ChannelId)) & SEMA4_GATE_GTFSM_MASK_U8))
    {
        u8gateStatus = (uint8)MCL_SEMAPHORE_FREE;
    }
    else
    {
        /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
        /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
        /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
        u8gateStatus = ((uint8)(REG_READ8(SEMA4_GATE_ADDR8(ChannelId)) & SEMA4_GATE_GTFSM_MASK_U8) - (uint8)1);
    }
    
    return u8gateStatus;
}

/**
* @details      Locks a semaphore with the core number from witch the lock is called
*/
FUNC(Mcl_Sema4ReturnType, MCL_CODE) Mcl_Sema4_LockGate(VAR(Mcl_Sema4ChannelType, AUTOMATIC) ChannelId)
{
    VAR(Mcl_Sema4ReturnType, AUTOMATIC) valid;
    
    /* If semaphore is not locked, lock it*/
    /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
    /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
    /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
    if ((uint8)0 == (uint8)(REG_READ8(SEMA4_GATE_ADDR8(ChannelId)) & SEMA4_GATE_GTFSM_MASK_U8))
    {
        /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
        /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
        /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
        REG_WRITE8(SEMA4_GATE_ADDR8(ChannelId), (uint8)MCL_CORE_USED + (uint8)1);
        
        /* Read to see if there weren't issues caused by concurrent access */
        /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
        /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
        /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
        if ((uint8)((uint8)MCL_CORE_USED + (uint8)1) == (uint8)(REG_READ8(SEMA4_GATE_ADDR8(ChannelId)) & SEMA4_GATE_GTFSM_MASK_U8))
        {
            Mcl_Sema4_ChannelLocked[ChannelId] = MCL_SEMA4_USED;
            
            valid = MCL_SEMA4_OK;
        }
        else
        {
            valid = MCL_SEMA4_NOT_OK;
        }
    }
    /* If the semaphore is locked return error instead of writing */
    else 
    {   
        /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
        /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
        /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
        if ((uint8)((uint8)MCL_CORE_USED + (uint8)1) != (uint8)(REG_READ8(SEMA4_GATE_ADDR8(ChannelId)) & SEMA4_GATE_GTFSM_MASK_U8))
        {
            valid = MCL_SEMA4_NOT_OK;
        }
        /* If semaphore is already locked by the same core, or
        if two Sema4_Lock calls are successive
        */
        else
        {   
            valid = MCL_SEMA4_DET;
        }
    }
    
    return valid;
}

/**
* @details      Unlocks a semaphore
*/
FUNC(Mcl_Sema4ReturnType, MCL_CODE) Mcl_Sema4_UnlockGate(VAR(Mcl_Sema4ChannelType, AUTOMATIC) ChannelId)
{
    VAR(Mcl_Sema4ReturnType, AUTOMATIC) valid;
    
    /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
    /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
    /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
    if ((uint8)MCL_CORE_USED == (Mcl_Sema4CoreNoType)((uint8)(REG_READ8(SEMA4_GATE_ADDR8(ChannelId)) & SEMA4_GATE_GTFSM_MASK_U8) - (uint8)1))
    {
        /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
        /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
        /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
        REG_WRITE8(SEMA4_GATE_ADDR8(ChannelId), (uint8)0);
        
        Mcl_Sema4_ChannelLocked[ChannelId] = MCL_SEMA4_NOT_USED;
        
        valid = MCL_SEMA4_OK;
    }
    /* If Api is called on a unlocked semaphore */
    /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
    /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
    /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
    else if ((Mcl_Sema4CoreNoType)0 == (Mcl_Sema4CoreNoType)(REG_READ8(SEMA4_GATE_ADDR8(ChannelId)) & SEMA4_GATE_GTFSM_MASK_U8))
    {
        valid = MCL_SEMA4_NOT_OK;
    }
    /* If Api is called on a semaphore locked by another core */
    else 
    {
        valid = MCL_SEMA4_DET;
    }

    return valid;
}

/**
* @details      Resets a semaphore. It must be configured in advance by the Mcl driver.
*/
FUNC(void, MCL_CODE) Mcl_Sema4_ResetSemaphore(VAR(Mcl_Sema4ChannelType, AUTOMATIC) ChannelId)
{
    /* First write in the RSTGTS register to reset the semaphore */
    /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
    /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
    /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
    REG_WRITE16(SEMA4_RESET_GATE_ADDR8, (ChannelId | SEMA4_FIRST_RSTGDP_MASK_U16));
    
    /* Second write in the RSTGTS register to reset the semaphore */
    /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
    /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
    /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
    REG_WRITE16(SEMA4_RESET_GATE_ADDR8, (ChannelId | SEMA4_SECOND_RSTGDP_MASK_U16));
}

/**
* @details      Resets all semaphores.
*/
FUNC(void, MCL_CODE) Mcl_Sema4_ResetAllSemaphores(void)
{
    VAR(uint8,   AUTOMATIC) u8semNo;
    
    /* Check all semaphores and if they were configured by the driver force reset them */
    for (u8semNo = 0U; u8semNo < MCL_SEMA4_NUMBER; u8semNo++)
    {
        if (MCL_SEMA4_USED == Mcl_Sema4_ChannelLocked[u8semNo])
        {
            /* First write in the RSTGTS register to reset the current semaphore */
            /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
            /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
            /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
            REG_WRITE16(SEMA4_RESET_GATE_ADDR8, (u8semNo | SEMA4_FIRST_RSTGDP_MASK_U16));
            
            /* Second write in the RSTGTS register to reset the current semaphore */
            /* @violates @ref WDG_Sema4_c_REF_1 Required Rule 10.8, The value of a composite expression shall no be cast to a different essential type category or a wider essential type.*/
            /* @violates @ref WDG_Sema4_c_REF_2 Advisory Rule 11.4, A conversion should not be performed between a pointer to object and an integer type. */
            /* @violates @ref WDG_Sema4_c_REF_3 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type*/
            REG_WRITE16(SEMA4_RESET_GATE_ADDR8, (u8semNo | SEMA4_SECOND_RSTGDP_MASK_U16));
        }
    }
}


#define MCL_STOP_SEC_CODE
/* @violates @ref WDG_Sema4_c_REF_4 MISRA 2012 Advisory 20.1*/
/* @violates @ref WDG_Sema4_c_REF_5 MISRA 2012 Required 4.10*/
#include "Mcl_MemMap.h"
#endif
#endif
#ifdef __cplusplus
}
#endif
/** @} */
