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

#ifdef __cplusplus
extern "C"{
#endif

#include "StdRegMacros.h"
#include "Irme_SmsReg.h"
#include "CDD_Irme_Cfg.h"
#include "Irme_Sms.h"

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup IRME_Driver
  * @brief IRME driver modules
  @{
*/

/** @defgroup IRME_Macros
  @{
*/
/**********************************************************************************************************************
                                    VENDOR ID & AUTOSAR VERSION INFO
***********************************************************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define IRME_SMS_VENDOR_ID                                0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define IRME_SMS_AR_RELEASE_MAJOR_VERSION                 0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define IRME_SMS_AR_RELEASE_MINOR_VERSION                 0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define IRME_SMS_AR_RELEASE_REVISION_VERSION              0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define IRME_SMS_SW_MAJOR_VERSION                         0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define IRME_SMS_SW_MINOR_VERSION                         0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define IRME_SMS_SW_PATCH_VERSION                         0x00U

/**@} end of group IRME_Macros */

/**********************************************************************************************************************           
                                      VERSION INFOMATION VERIFICATION
***********************************************************************************************************************/
/* Make sure the vendor ids are the same between Irme_Sms.c and Irme_Sms.h */
#if (IRME_SMS_VENDOR_ID != IRME_SMS_H_VENDOR_ID)
    #error "Vendor ids mismatch between Irme_Sms.c and Irme_Sms.h"
#endif
/* Make sure the AUTOSAR major version number is the same between Irme_Sms.c and Irme_Sms.h */
#if (IRME_SMS_AR_RELEASE_MAJOR_VERSION    != IRME_SMS_H_AR_RELEASE_MAJOR_VERSION)
    #error "AUTOSAR Major Version Number mismatch between Irme_Sms.c and Irme_Sms.h"
#endif
/* Make sure the AUTOSAR minor version number is the same between Irme_Sms.c and Irme_Sms.h */
#if (IRME_SMS_AR_RELEASE_MINOR_VERSION    != IRME_SMS_H_AR_RELEASE_MINOR_VERSION)
    #error "AUTOSAR Minor Version Number mismatch between Irme_Sms.c and Irme_Sms.h"
#endif
/* Make sure the AUTOSAR revision version number is the same between Irme_Sms.c and Irme_Sms.h */
#if (IRME_SMS_AR_RELEASE_REVISION_VERSION != IRME_SMS_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR Revision Version Number mismatch between Irme_Sms.c and Irme_Sms.h"
#endif
/* Make sure the software major version number is the same between Irme_Sms.c and Irme_Sms.h */
#if (IRME_SMS_SW_MAJOR_VERSION != IRME_SMS_H_SW_MAJOR_VERSION)
    #error "Software Major Version Number mismatch between Irme_Sms.c and Irme_Sms.h"
#endif
/* Make sure the software minor version number is the same between Irme_Sms.c and Irme_Sms.h */
#if (IRME_SMS_SW_MINOR_VERSION != IRME_SMS_H_SW_MINOR_VERSION)
    #error "Software Minor Version Number mismatch between Irme_Sms.c and Irme_Sms.h"
#endif
/* Make sure the software patch version number is the same between Irme_Sms.c and Irme_Sms.h */
#if (IRME_SMS_SW_PATCH_VERSION != IRME_SMS_H_SW_PATCH_VERSION)
    #error "Software Patch Version Number mismatch between Irme_Sms.c and Irme_Sms.h"
#endif

/* Make sure the vendor ids are the same between Irme_Sms.c and CDD_Irme_Cfg.h */
#if (IRME_SMS_VENDOR_ID != CDD_IRME_CFG_H_VENDOR_ID)
    #error "Vendor ids mismatch between Irme_Sms.c and CDD_Irme_Cfg.h"
#endif
/* Make sure the AUTOSAR major version number is the same between Irme_Sms.c and CDD_Irme_Cfg.h */
#if (IRME_SMS_AR_RELEASE_MAJOR_VERSION != CDD_IRME_CFG_H_AR_RELEASE_MAJOR_VERSION)
    #error "AUTOSAR Major Version Number mismatch between Irme_Sms.c and CDD_Irme_Cfg.h"
#endif
/* Make sure the AUTOSAR minor version number is the same between Irme_Sms.c and CDD_Irme_Cfg.h */
#if (IRME_SMS_AR_RELEASE_MINOR_VERSION != CDD_IRME_CFG_H_AR_RELEASE_MINOR_VERSION)
    #error "AUTOSAR Minor Version Number mismatch between Irme_Sms.c and CDD_Irme_Cfg.h"
#endif
/* Make sure the AUTOSAR revision version number is the same between Irme_Sms.c and CDD_Irme_Cfg.h */
#if (IRME_SMS_AR_RELEASE_REVISION_VERSION != CDD_IRME_CFG_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR Revision Version Number mismatch between Irme_Sms.c and CDD_Irme_Cfg.h"
#endif
/* Make sure the software major version number is the same between Irme_Sms.c and CDD_Irme_Cfg.h */
#if (IRME_SMS_SW_MAJOR_VERSION != CDD_IRME_CFG_H_SW_MAJOR_VERSION)
    #error "Software Major Version Number mismatch between Irme_Sms.c and CDD_Irme_Cfg.h"
#endif
/* Make sure the software minor version number is the same between Irme_Sms.c and CDD_Irme_Cfg.h */
#if (IRME_SMS_SW_MINOR_VERSION != CDD_IRME_CFG_H_SW_MINOR_VERSION)
    #error "Software Minor Version Number mismatch between Irme_Sms.c and CDD_Irme_Cfg.h"
#endif
/* Make sure the software patch version number is the same between Irme_Sms.c and CDD_Irme_Cfg.h */
#if (IRME_SMS_SW_PATCH_VERSION != CDD_IRME_CFG_H_SW_PATCH_VERSION)
    #error "Software Patch Version Number mismatch between Irme_Sms.c and CDD_Irme_Cfg.h"
#endif

/* Make sure the vendor ids are the same between Irme_Sms.c and Irme_SmsReg.h */
#if (IRME_SMS_VENDOR_ID != IRME_SMS_REG_H_VENDOR_ID)
    #error "Vendor ids mismatch between Irme_Sms.c and Irme_SmsReg.h"
#endif
/* Make sure the AUTOSAR major version number is the same between Irme_Sms.c and Irme_SmsReg.h */ 
#if (IRME_SMS_AR_RELEASE_MAJOR_VERSION != IRME_SMS_REG_H_AR_RELEASE_MAJOR_VERSION)
    #error "AUTOSAR Major Version Number mismatch between Irme_Sms.c and Irme_SmsReg.h"
#endif
/* Make sure the AUTOSAR minor version number is the same between Irme_Sms.c and Irme_SmsReg.h */
#if (IRME_SMS_AR_RELEASE_MINOR_VERSION != IRME_SMS_REG_H_AR_RELEASE_MINOR_VERSION)
    #error "AUTOSAR Minor Version Number mismatch between Irme_Sms.c and Irme_SmsReg.h"
#endif
/* Make sure the AUTOSAR revision version number is the same between Irme_Sms.c and Irme_SmsReg.h */
#if (IRME_SMS_AR_RELEASE_REVISION_VERSION != IRME_SMS_REG_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR Revision Version Number mismatch between Irme_Sms.c and Irme_SmsReg.h"
#endif
/* Make sure the software major version number is the same between Irme_Sms.c and Irme_SmsReg.h */
#if (IRME_SMS_SW_MAJOR_VERSION != IRME_SMS_REG_H_SW_MAJOR_VERSION)
    #error "Software Major Version Number mismatch between Irme_Sms.c and Irme_SmsReg.h"
#endif
/* Make sure the software minor version number is the same between Irme_Sms.c and Irme_SmsReg.h */
#if (IRME_SMS_SW_MINOR_VERSION != IRME_SMS_REG_H_SW_MINOR_VERSION)
    #error "Software Minor Version Number mismatch between Irme_Sms.c and Irme_SmsReg.h"
#endif
/* Make sure the software patch version number is the same between Irme_Sms.c and Irme_SmsReg.h */
#if (IRME_SMS_SW_PATCH_VERSION != IRME_SMS_REG_H_SW_PATCH_VERSION)
    #error "Software Patch Version Number mismatch between Irme_Sms.c and Irme_SmsReg.h"
#endif

#ifdef ENABLE_INTERMODULE_MCAL_CHECK
    /* Make sure the AUTOSAR major version number is the same between Irme_Sms.c and StdRegMacros.h */ 
    #if (IRME_SMS_AR_RELEASE_MAJOR_VERSION != STD_REG_MACROS_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR Major Version Number mismatch between Irme_Sms.c and StdRegMacros.h"
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Irme_Sms.c and StdRegMacros.h */
    #if (IRME_SMS_AR_RELEASE_MINOR_VERSION != STD_REG_MACROS_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR Minor Version Number mismatch between Irme_Sms.c and StdRegMacros.h"
    #endif
#endif  

/**********************************************************************************************************************
                                                   GLOBAL VARIABLES
***********************************************************************************************************************/
#define IRME_START_SEC_VAR_INIT_UNSPECIFIED
#include "Irme_MemMap.h"

/** @defgroup IRME_Variable
  @{
*/

/** The configuration data of the Irme module */
P2CONST(Irme_SmsConfigType, AUTOMATIC, IRME_APPL_CONST) g_smsConfigPtr = NULL_PTR;

/**@} end of group IRME_Variable */

#define IRME_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "Irme_MemMap.h"

#define IRME_START_SEC_CONST_UNSPECIFIED
#include "Irme_MemMap.h"

/** @defgroup IRME_Variable
  @{
*/

/** The fault shift bits array */
CONST(uint32,IRME_CONST) g_irmeSmsStatBitPosition[IRME_FAULTS_TOTAL_COUNT] = {(uint32)SMS_STAT_RD_ERR_SIN_SHIFT, \
                                                                              (uint32)SMS_STAT_RD_ERR_DBL_SHIFT, \
                                                                              (uint32)SMS_STAT_RMW_ERR_SIN_SHIFT, \
                                                                              (uint32)SMS_STAT_RMW_ERR_DBL_SHIFT};

/**@} end of group IRME_Variable */

#define IRME_STOP_SEC_CONST_UNSPECIFIED
#include "Irme_MemMap.h"

/**********************************************************************************************************************
                                                    GLOBAL FUNCTION
***********************************************************************************************************************/
#define IRME_START_SEC_CODE
#include "Irme_MemMap.h"

/** @defgroup IRME_Fuctions
  @{
*/

/*!
* @brief          The function is to get errors 
*
* @param[in]      FaultPool  Error pool where the error flags shall be stored
* @param[out]     None
* @param[in,out]  None
*
* @retval         E_OK:     There is no pending fault.
*                 E_NOT_OK: There is at least one pending fault.
*/
FUNC(Std_ReturnType, IRME_CODE) Irme_Sms_GetErrors(VAR(uint32,AUTOMATIC) FaultPool[])
{
    VAR(uint8, AUTOMATIC) circleCnt = 0;
    VAR(uint32, AUTOMATIC) regVal = 0;
    VAR(Std_ReturnType,IRME_VAR) returnVal = (Std_ReturnType)E_OK;

    FaultPool[0] = 0U;

    /* Get the ECC error flags */
    regVal = REG_READ32(SMS_INTRRn_REG_ADDR) & EREPM_STS_MASK;

    if((0U != (regVal & SMS_INTRRn_RD_ERR_DET_MASK)) || (0U != (regVal & SMS_INTRRn_RMW_ERR_DET_MASK)))
    {
        while(circleCnt < IRME_FAULTS_TOTAL_COUNT)
        {
            if (0U != (regVal & ((uint32)1U << g_irmeSmsStatBitPosition[circleCnt])))
            {
                FaultPool[0] |= (uint32)1U << circleCnt;
                returnVal = (Std_ReturnType)E_NOT_OK;
            }
            else
            {
              /* do nothing */
            }

            circleCnt++;
        }
    }
    else
    {
      /* do nothing */
    }

    return (returnVal);
}

/*!
* @brief          The function is to clear the fault flags
*
* @param[in]      None
* @param[out]     None
* @param[in,out]  None
*
* @retval         E_OK: the is cleared successfully.
*                 E_NOT_OK: the fault is cleared failed.
*/
FUNC(Std_ReturnType, IRME_CODE) Irme_Sms_ClearFault(void)
{
    VAR(Std_ReturnType,IRME_VAR) returnVal = (Std_ReturnType)E_NOT_OK;
    VAR(uint32, IRME_VAR) regValTemp = 0;

    /* Clear the fault flag */ 
    REG_WRITE32(SMS_INTRRn_REG_ADDR, 0U);

    MCAL_FAULT_INJECTION_POINT(FIP_T_IRME_CLEAR_FAULTS);

    regValTemp = (uint32)REG_READ32(SMS_INTRRn_REG_ADDR);

    if (IRME_SMS_NO_ERR == regValTemp)
    {
        returnVal = (Std_ReturnType)E_OK;
    }
    else
    {
        /* do nothing */
    }

    return returnVal;
}

/*!
* @brief          The function is to check if inject type is valid.
*
* @param[in]      InjectBitErr      The type of the fault to be injected.
* @param[out]     None
* @param[in,out]  None
*
* @retval         E_OK:     the fault type is valid.
*                 E_NOT_OK: the fault type is not invalid.
*/
FUNC(boolean, IRME_CODE) Irme_Sms_CheckValidFault(VAR(Irme_InjectBitErrType, AUTOMATIC) InjectBitErr)
{
    VAR(boolean,IRME_VAR) returnVal = (boolean)FALSE;
    
    /* Check if the inject type is enabled */
    if (((uint8)InjectBitErr > 0U) && ((uint8)InjectBitErr < 4U))
    {
        returnVal = (boolean)TRUE;
    }
    else
    {
        /* do nothing */
    }

    return returnVal;
}

/*!
* @brief          The function is to init the Irme moudle.
*
* @param[in]      SmsConfigPtr       The point of configuration parameter.
* @param[out]     None
* @param[in,out]  None
*
* @retval         E_OK:Initialize successfully.
*                 E_NOT_OK:Initialize failed.
*
* @note          This function additionally clear all injected errors.
*/
FUNC(Std_ReturnType, IRME_CODE) Irme_Sms_Init(P2CONST(Irme_SmsConfigType, AUTOMATIC, IRME_APPL_CONST) SmsConfigPtr)
{
    g_smsConfigPtr = SmsConfigPtr;

    /* Reset all error status */
    REG_READ32(SMS_STAT_REG_ADDR);
    /* Clear the error intrrupt flags */
    REG_WRITE32(SMS_INTRRn_REG_ADDR, 0xFFFFFFFFU);
    /* Configure the SMS_ECC_CFG register */
    REG_WRITE32(SMS_ECC_CFG_REG_ADDR, SmsConfigPtr->smsEccCfgVal);
    
    /* Config SMS_INTRMn register */
    REG_WRITE32(SMS_INTRMn_REG_ADDR, SmsConfigPtr->smsIntRMVal);

    return ((Std_ReturnType)E_OK);
}

/*!
* @brief          The function is to inject a fault.
*
* @param[in]      InjectBitErrType       The fault id to be injected.
* @param[out]     None
* @param[in,out]  None
*/
FUNC(void, IRME_CODE) Irme_Sms_InjectFault(VAR(Irme_InjectBitErrType, AUTOMATIC) InjectBitErrType)
{
    SuspendAllInterrupts();
    /* Clear the INSERT_ERR bit region of the SMS_ECC_CFG register */
    REG_BIT_CLEAR32(SMS_ECC_CFG_REG_ADDR, SMS_ECC_CFG_INSERT_ERR_MASK);

    switch(InjectBitErrType)
    {
        case IRME_INJECT_SINGLE_BIT_ERROR:
            REG_BIT_SET32(SMS_ECC_CFG_REG_ADDR, (uint8)IRME_INJECT_SINGLE_BIT_ERROR << SMS_ECC_CFG_INSERT_ERR_SHIFT);
            break;
        case IRME_INJECT_DOUBLE_BIT_ERROR:
            REG_BIT_SET32(SMS_ECC_CFG_REG_ADDR, (uint8)IRME_INJECT_DOUBLE_BIT_ERROR << SMS_ECC_CFG_INSERT_ERR_SHIFT);
            break;
        case IRME_INJECT_TRIPLE_BIT_ERROR:
            REG_BIT_SET32(SMS_ECC_CFG_REG_ADDR, (uint8)IRME_INJECT_TRIPLE_BIT_ERROR << SMS_ECC_CFG_INSERT_ERR_SHIFT);
            break;
        default:
            /* Do nothing */
            break;
    }

    /* Write the value to the address */
    REG_WRITE32(g_smsConfigPtr->injectRamAddr, 0xFFFFFFFFU);

    /* Read the value of the address to inject an error:RD type */
    REG_READ32(g_smsConfigPtr->injectRamAddr);
    /* Byte operation to trigger RMW operation with an error: RMW type */
    REG_WRITE8(g_smsConfigPtr->injectRamAddr, 1);

    /* Disable the error injection */
    REG_BIT_CLEAR32(SMS_ECC_CFG_REG_ADDR, SMS_ECC_CFG_INSERT_ERR_MASK);

    ResumeAllInterrupts();
}

/*!
* @brief          The function is to get the error address.
*
* @param[in]      None
* @param[out]     None
* @param[in,out]  None
*
* @retval        The address where the error occurred.
*/
FUNC(uint32, IRME_CODE) Irme_Sms_GetErrorAddr(void)
{
    VAR(uint32, IRME_VAR) errorAddr = 0;

    errorAddr = REG_READ32(SMS_ECC_LOGn_REG_ADDR);
    errorAddr = (((errorAddr >> SMS_ECC_LOGn_ADDR_SHIFT) * 4U ) + SMS_RAM_START_ADDRESS);

    return (errorAddr);
}

/**@} end of group IRME_Fuctions */

#define IRME_STOP_SEC_CODE
#include "Irme_MemMap.h"

#ifdef __cplusplus
}
#endif

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