/*!
* @file     Mcal.h
*
* @version  1.0.0
*
* @brief    This file contains the MCAL specific macros for compiler abstraction
*
* @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.
*/

/*
* MISRA-C:2012 compliance checks
*
*     Mcal_h_MISRA_REF1
*         Breaks the required Dir-1.1-C90 of MISRA 2012 guidelines,
*         Any implementation-defined behaviour on which the output of the program depends shall be documented and understood.
*/

#ifndef MCAL_H
#define MCAL_H

#ifdef __cplusplus
extern "C"{
#endif

#include "Compiler.h"
#include "Std_Types.h"
#include <stdint.h>

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup PLATFORM_Driver
  * @brief PLATFORM driver modules
  @{
*/

/** @defgroup PLATFORM_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define MCAL_H_VENDOR_ID                     0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define MCAL_H_AR_RELEASE_MAJOR_VERSION      0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define MCAL_H_AR_RELEASE_MINOR_VERSION      0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define MCAL_H_AR_RELEASE_REVISION_VERSION   0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define MCAL_H_SW_MAJOR_VERSION              0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define MCAL_H_SW_MINOR_VERSION              0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define MCAL_H_SW_PATCH_VERSION              0x00U

/**@} end of group PLATFORM_Macros */

/**************************************************************************
                    VERSION INFOMATION VERIFICATION
**************************************************************************/
#ifdef ENABLE_INTERMODULE_MCAL_CHECK
    /* Make sure the AUTOSAR major version number is the same between Mcal.h and Std_Types.h */
    #if (MCAL_H_AR_RELEASE_MAJOR_VERSION != STD_TYPES_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR Major Version Number mismatch between Mcal.h and Std_Types.h"
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Mcal.h and Std_Types.h */
    #if (MCAL_H_AR_RELEASE_MINOR_VERSION != STD_TYPES_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR Minor Version Number mismatch between Mcal.h and Std_Types.h"
    #endif

    /* Make sure the AUTOSAR major version number is the same between Mcal.h and Compiler.h */
    #if (MCAL_H_AR_RELEASE_MAJOR_VERSION != COMPILER_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR Major Version Number mismatch between Mcal.h and Compiler.h"
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Mcal.h and Compiler.h */
    #if (MCAL_H_AR_RELEASE_MINOR_VERSION != COMPILER_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR Minor Version Number mismatch between Mcal.h and Compiler.h"
    #endif
#endif

/*******************************************************************************
                            DEFINES AND MACROS
*******************************************************************************/
/** @defgroup PLATFORM_Macros
  @{
*/

/** ARM M0PLUS Thumb */
#define MCAL_ARM_MARCH      (16)
/** ARM ARCH32 */
#define MCAL_ARM_AARCH32    (32)
/** ARM ARCH64 */
#define MCAL_ARM_AARCH64    (64)

/** Used to specify the ARM architecture */
#define MCAL_PLATFORM_ARM  MCAL_ARM_MARCH

/** Pointer to pointer to variable */
#define P2P2VAR(ptrtype, memclass, ptrclass) ptrtype **

/** Pointer to pointer to constant */
#define P2P2CONST(ptrtype, memclass, ptrclass) const ptrtype **

/** Data Synchronization Barrier (DSB) completes when all instructions before this instruction complete. */
#define MCAL_DATA_SYNC_BARRIER() ASM_KEYWORD(" DSB")

/**
* Flush the pipeline in the processor so that all instructions following the
* ISB are fetched from cache or memory after the ISB has been completed.
*/
#define MCAL_INSTRUCTION_SYNC_BARRIER() ASM_KEYWORD(" ISB")

/**@} end of group PLATFORM_Macros */

/** @defgroup PLATFORM_Structure
  @{
*/

/**
 *  @brief Used for DEM error management implemented by MCAL drivers
 */
typedef struct
{
    uint32 state;   //!< Enable or disable the DEM error: Active=STD_ON Inactive=STD_OFF
    uint32 id;      //!< ID of DEM error (0 if STD_OFF)
} Mcal_DemErrorType;

/**@} end of group PLATFORM_Structure */

#ifdef MCAL_ENABLE_USER_MODE_SUPPORT
#ifdef AUTOSAR_OS_NOT_USED

/** @defgroup PLATFORM_Fuctions
  @{
*/

extern uint8  Sys_GoToSupervisor(void);
extern uint32 Sys_GoToUser(void);
extern uint32 Sys_GoToUser_Return(uint8 SwitchToSupervisor, uint32 ReturnValue);

/**@} end of group PLATFORM_Fuctions */

/** @defgroup PLATFORM_Macros
  @{
*/
    #define Mcal_goToSupervisor() ASM_KEYWORD("svc 0x0");
    #define Mcal_goToUser()       ASM_KEYWORD("svc 0x1");

    #define Mcal_Trusted_Call(name) \
        ((1UL == Sys_GoToSupervisor()) ? \
            (name(), (void)Sys_GoToUser()) : \
            (name(),(void)0U))

    #define Mcal_Trusted_Call1param(name, param) \
        ((1UL == Sys_GoToSupervisor()) ? \
            (name(param), (void)Sys_GoToUser()) : \
            (name(param),(void)0U))

    #define Mcal_Trusted_Call2params(name, param1, param2) \
        ((1UL == Sys_GoToSupervisor()) ? \
            (name(param1, param2), (void)Sys_GoToUser()) : \
            (name(param1, param2),(void)0U))

    #define Mcal_Trusted_Call3params(name, param1, param2, param3) \
        ((1UL == Sys_GoToSupervisor()) ? \
            (name(param1, param2, param3), (void)Sys_GoToUser()) : \
            (name(param1, param2, param3),(void)0U))

    #define Mcal_Trusted_Call4params(name, param1, param2, param3, param4) \
        ((1UL == Sys_GoToSupervisor()) ? \
            (name(param1, param2, param3, param4), (void)Sys_GoToUser()) : \
            (name(param1, param2, param3, param4), (void)0U))

    #define Mcal_Trusted_Call_Return(name) \
        ((1UL == Sys_GoToSupervisor()) ? \
            Sys_GoToUser_Return(1U, name()) : \
            Sys_GoToUser_Return(0U, name()))

    #define Mcal_Trusted_Call_Return1param(name, param) \
        ((1UL == Sys_GoToSupervisor()) ? \
            Sys_GoToUser_Return(1U, name(param)) : \
            Sys_GoToUser_Return(0U, name(param)))

    #define Mcal_Trusted_Call_Return2param(name, param1, param2) \
        ((1UL == Sys_GoToSupervisor()) ? \
            Sys_GoToUser_Return(1U, name(param1, param2)) : \
            Sys_GoToUser_Return(0U, name(param1, param2)))

    #define Mcal_Trusted_Call_Return3param(name, param1, param2, param3) \
        ((1UL == Sys_GoToSupervisor()) ? \
            Sys_GoToUser_Return(1U, name(param1, param2, param3)) : \
            Sys_GoToUser_Return(0U, name(param1, param2, param3)))

    #define Mcal_Trusted_Call_Return4param(name, param1, param2, param3, param4) \
        ((1UL == Sys_GoToSupervisor()) ? \
            Sys_GoToUser_Return(1U, name(param1, param2, param3, param4)) : \
            Sys_GoToUser_Return(0U, name(param1, param2, param3, param4)))
#else
    #define Mcal_Trusted_Call(name) \
                Call_##name##_TRUSTED()
    #define Mcal_Trusted_Call1param(name, param) \
                Call_##name##_TRUSTED(param)
    #define Mcal_Trusted_Call2params(name, param1, param2) \
                Call_##name##_TRUSTED(param1, param2)
    #define Mcal_Trusted_Call3params(name, param1, param2, param3) \
                Call_##name##_TRUSTED(param1, param2, param3)
    #define Mcal_Trusted_Call4params(name, param1, param2, param3, param4) \
                Call_##name##_TRUSTED(param1, param2, param3, param4)
    #define Mcal_Trusted_Call_Return(name) \
                Call_##name##_TRUSTED()
    #define Mcal_Trusted_Call_Return1param(name, param1) \
                Call_##name##_TRUSTED(param1)
    #define Mcal_Trusted_Call_Return2param(name, param1, param2) \
                Call_##name##_TRUSTED(param1, param2)
    #define Mcal_Trusted_Call_Return3param(name, param1, param2, param3) \
                Call_##name##_TRUSTED(param1, param2, param3)
    #define Mcal_Trusted_Call_Return4param(name, param1, param2, param3, param4) \
                Call_##name##_TRUSTED(param1, param2, param3, param4)

/**@} end of group PLATFORM_Macros */

#endif
#endif

/** @defgroup PLATFORM_Macros
  @{
*/

#ifdef AUTOSAR_OS_NOT_USED
    /** Compiler abstraction for creating an interrupt handler if OS is not used. */
    #ifdef USE_SW_VECTOR_MODE
        #define ISR(IsrName)    void IsrName(void)
    #else
        #define ISR(IsrName)    INTERRUPT_FUNC void IsrName(void)
    #endif

    /** Compiler abstraction for returning from an ISR if OS is not used. */
    #define EXIT_INTERRUPT()

    /** Compiler abstraction for disabling/enabling all interrupts if OS is not used. */
    #if (MCAL_ARM_AARCH64 == MCAL_PLATFORM_ARM)
        #define SuspendAllInterrupts()  ASM_KEYWORD(" msr DAIFSet,#0xf")
        #define ResumeAllInterrupts()   ASM_KEYWORD(" msr DAIFClr,#0xf")
    #else
    /*** @warning Mcal_h_MISRA_REF1 [L] More than 8 levels of nested conditional inclusion - program does not conform strictly to ISO:C90. */
        #ifdef MCAL_ENABLE_USER_MODE_SUPPORT
    /*** @warning Mcal_h_MISRA_REF1 [L] More than 8 levels of nested conditional inclusion - program does not conform strictly to ISO:C90. */
            #ifdef MCAL_M0PLUS_CORE_SUPPORT
                #define SuspendAllInterrupts()
                #define ResumeAllInterrupts()
            #else
                #define SuspendAllInterrupts()  ASM_KEYWORD("svc 0x3")
                #define ResumeAllInterrupts()   ASM_KEYWORD("svc 0x2")
            #endif
        #else
            #define SuspendAllInterrupts()  ASM_KEYWORD(" cpsid i")
            #define ResumeAllInterrupts()   ASM_KEYWORD(" cpsie i")
        #endif
    #endif
#else
    #include "Os.h"
    /** Compiler abstraction for returning from an ISR if OS is used. */
    #define EXIT_INTERRUPT()
#endif

/*******************************************************************************
                            COMPILER CHECK
*******************************************************************************/
/** Check if the compiler is supported */
#if !defined(G32A_C_IAR) && \
    !defined(G32A_C_DS5) && \
    !defined(G32A_C_GREENHILLS) && \
    !defined(G32A_C_LINARO) && \
    !defined(G32A_C_DIAB) && \
    !defined(_G32A_C_HITECH_) && \
    !defined(G32A_C_CODEWARRIOR) && \
    !defined(G32A_C_COSMIC)
  #error "Unsupported compiler"
#endif

/*******************************************************************************
                            IAR COMPILER
*******************************************************************************/
#ifdef G32A_C_IAR
    /** Compiler abstraction for the PACKED qualifier */
    #define PACKED __packed

    /** Compiler abstraction for the ASM keyword */
    #define ASM_KEYWORD __asm

    /** Compiler abstraction for the intrinsic wait instruction */
    #define EXECUTE_WAIT() ASM_KEYWORD("  wfi")

    /** Compiler abstraction for "put in quotes" */
    #define MCAL_PUT_IN_QUOTES(x) #x

    /** Compiler abstraction for "double put in quotes" */
    #define MCAL_PUT_IN_QUOTES1(x) MCAL_PUT_IN_QUOTES(x)

    /** Compiler abstraction for data alignment */
    #define VAR_ALIGN(v, size) _Pragma(MCAL_PUT_IN_QUOTES1(data_alignment=size)) v;
    #define ALIGNED_VARS_START(sec_name, align)
    #define ALIGNED_VARS_STOP()

    /** Compiler abstraction for the fault injection tests */
    #ifdef MCAL_ENABLE_FAULT_INJECTION
        #define MCAL_FAULT_INJECTION_POINT(label) ASM_KEYWORD(MCAL_PUT_IN_QUOTES(label:))
    #else
        #define MCAL_FAULT_INJECTION_POINT(label)
    #endif
#endif

/*******************************************************************************
                            DS5 COMPILER
*******************************************************************************/
#ifdef G32A_C_DS5
    /** Compiler abstraction for the PACKED qualifier */
    #define PACKED __packed

    /** Compiler abstraction for the ASM keyword */
    #define ASM_KEYWORD __asm

    /** Compiler abstraction for the intrinsic wait instruction */
    #define EXECUTE_WAIT() ASM_KEYWORD("  wfi")

    /** Compiler abstraction for data alignment */
    #define VAR_ALIGN(v, size) __align(size) v;
    #define ALIGNED_VARS_START(sec_name, align)
    #define ALIGNED_VARS_STOP()

    /** Compiler abstraction for the fault injection tests */
    #ifdef MCAL_ENABLE_FAULT_INJECTION
        #define MCAL_PUT_IN_QUOTES(x) #x
        #define MCAL_FAULT_INJECTION_POINT(label) ASM_KEYWORD(MCAL_PUT_IN_QUOTES(label:))
    #else
        #define MCAL_FAULT_INJECTION_POINT(label)
    #endif
#endif

/*******************************************************************************
                            GREENHILLS COMPILER
*******************************************************************************/
#ifdef G32A_C_GREENHILLS
    /** Compiler abstraction for the PACKED qualifier */
    #define PACKED __packed

    /** Compiler abstraction for the ASM keyword */
    #define ASM_KEYWORD __asm

    /** Compiler abstraction for the intrinsic wait instruction */
    #define EXECUTE_WAIT() ASM_KEYWORD("  wfi")

    /** Compiler abstraction for data alignment */
    #define VAR_ALIGN(v, size) __attribute__(( aligned(size) )) v;
    #define ALIGNED_VARS_START(sec_name, align)
    #define ALIGNED_VARS_STOP()

    /** Compiler abstraction for the fault injection tests */
    #ifdef MCAL_ENABLE_FAULT_INJECTION
        #define MCAL_PUT_IN_QUOTES(x) #x
        #define MCAL_FAULT_INJECTION_POINT(label) ASM_KEYWORD(MCAL_PUT_IN_QUOTES(label::))
    #else
        #define MCAL_FAULT_INJECTION_POINT(label)
    #endif
#endif

/*******************************************************************************
                            LINARO COMPILER
*******************************************************************************/
#ifdef G32A_C_LINARO
    /** Compiler abstraction for the PACKED qualifier */
    #define PACKED __attribute__((__packed__))

    /** Compiler abstraction for the ASM keyword */
    #define ASM_KEYWORD __asm

    /** Compiler abstraction for the intrinsic wait instruction */
    #define EXECUTE_WAIT() ASM_KEYWORD("  wfi")

    /** Compiler abstraction for data alignment */
    #define VAR_ALIGN(v, size) __attribute__(( aligned(size) )) v;
    #define ALIGNED_VARS_START(sec_name, align)
    #define ALIGNED_VARS_STOP()

    /** Compiler abstraction for the fault injection tests */
    #ifdef MCAL_ENABLE_FAULT_INJECTION
        #define MCAL_PUT_IN_QUOTES(x) #x
        #define MCAL_FAULT_INJECTION_POINT(label) ASM_KEYWORD(MCAL_PUT_IN_QUOTES(label:))
    #else
        #define MCAL_FAULT_INJECTION_POINT(label)
    #endif
#endif

/*******************************************************************************
                            DIAB COMPILER
*******************************************************************************/
#ifdef G32A_C_DIAB
    /** Compiler abstraction for the PACKED qualifier */
    #define PACKED __packed__

    /** Compiler abstraction for the ASM keyword */
    #define ASM_KEYWORD asm volatile

    /** Compiler abstraction for the intrinsic wait instruction */
    #define EXECUTE_WAIT() ASM_KEYWORD("  .word 0x7C00007C")

    /** Compiler abstraction for data alignment */
    #define VAR_ALIGN(v, size) __attribute__(( aligned(size) )) v;
    #define ALIGNED_VARS_START(sec_name, align)
    #define ALIGNED_VARS_STOP()

    /** Compiler abstraction for the fault injection tests */
    #ifdef MCAL_ENABLE_FAULT_INJECTION
        #define MCAL_PUT_IN_QUOTES(x) #x
        #define MCAL_FAULT_INJECTION_POINT(label) ASM_KEYWORD(MCAL_PUT_IN_QUOTES(label:))
    #else
        #define MCAL_FAULT_INJECTION_POINT(label)
    #endif
#endif

/*******************************************************************************
                            HITECH COMPILER
*******************************************************************************/
#ifdef _G32A_C_HITECH_
    /** Compiler abstraction for the ASM keyword */
    #define ASM_KEYWORD __asm

    /** Compiler abstraction for the intrinsic wait instruction */
    #define EXECUTE_WAIT() ASM_KEYWORD("  wait")

    /** Compiler abstraction for data alignment */
    #define VAR_ALIGN(v, size) __attribute__(( aligned(size) )) v;
    #define ALIGNED_VARS_START(sec_name, align)
    #define ALIGNED_VARS_STOP()
#endif

/*******************************************************************************
                            CODEWARRIOR COMPILER
*******************************************************************************/
#ifdef G32A_C_CODEWARRIOR
    /** Compiler abstraction for the PACKED qualifier */
    #define PACKED __packed

    /** Compiler abstraction for the ASM keyword */
    #define ASM_KEYWORD asm

    /** Compiler abstraction for the intrinsic wait instruction */
    #define EXECUTE_WAIT() ASM_KEYWORD (" opword 0x7C00007C")

    /** Compiler abstraction for data alignment */
    #define VAR_ALIGN(v, size) v __attribute__(( aligned(size) ));
    #define ALIGNED_VARS_START(sec_name, align)
    #define ALIGNED_VARS_STOP()
#endif

/*******************************************************************************
                            COSMIC COMPILER
*******************************************************************************/
#ifdef G32A_C_COSMIC
    /** Compiler abstraction for the ASM keyword */
    #define ASM_KEYWORD _asm
    #define ASM_PUBLIC_LABEL(label) _asm("\txdef\t" #label "\n" #label ":")

    /** Compiler abstraction for the intrinsic wait instruction */
    #define EXECUTE_WAIT() ASM_KEYWORD (" dc.l 0x7C00007C")

    /** Compiler abstraction for data alignment */
    #define VAR_ALIGN(v, size) v;
    #define ALIGNED_VARS_START(sec_name, align) \#pragma section [sec_name ## align]
    #define ALIGNED_VARS_STOP() \#pragma section []
#endif

/**@} end of group PLATFORM_Macros */

#ifdef __cplusplus
}
#endif

#endif

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