PeripheralDriver_Flagchip_F.../Src/module_driver_erm.c

228 lines
8.0 KiB
C

/**
* @file module_driver_erm.c
* @author Flagchip0100
* @brief ERM Module driver type definition and API
* @version 2.0.0
* @date 2024-08-20
*
* SDK Version: 2.6.0
*
* @copyright Copyright 2020-2024 Flagchip Semiconductors Co., Ltd.
*/
/********************************************************************************
* Revision History:
*
* Version Date Initials CR# Descriptions
* --------- ---------- ------------ ---------- ---------------
* 0.2.0 2023-02-15 Flagchip052 N/A First version for FC7300
* 2.0.0 2024-08-01 Flagchip0100 N/A SDK2.0 release version
********************************************************************************/
#include "module_driver_erm.h"
#if (ERM_INSTANCE_COUNT > 0U)
/*******************************************************************************
* Definitions
******************************************************************************/
#ifndef ERM_DEV_ERROR_REPORT
#define ERM_DEV_ERROR_REPORT STD_OFF
#endif
#if ERM_DEV_ERROR_REPORT == STD_ON
#define ERM_ReportDevError(func, error) ReportDevError(ERM_MODULE_ID, func, error)
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
static ERM_Type *const s_apErmBase[ERM_INSTANCE_COUNT] = ERM_BASE_PTRS;
/*******************************************************************************
* Code
******************************************************************************/
/**
* @brief Initializes the Error Reporting Module (ERM) for the specified instance
*
* This function initializes the ERM module with the provided configuration structure.
* It performs parameter validation, sets up the control register based on the configuration,
* and clears the status. If an error occurs or the handle is invalid, an error report will
* be generated, and the function will return a failure status.
*
* @param pHandle Pointer to an ERM handle structure containing the instance information
* @param pInitCfg Pointer to an ERM configuration structure with desired settings
*
* @return Status of the initialization operation
* - ERM_STATUS_SUCCESS: Initialization successful
* - ERM_STATUS_FAIL: Initialization failed due to an error
*
* @preconditions
* - A valid ERM handle and configuration structure pointers must be provided
* - The ERM instance number should be within the supported range
*
* @postconditions
* - The ERM will be configured according to the provided settings
* - The status will be cleared
* - The error callback function pointer in the handle will be set to the one from the configuration
*
* @note Error reporting is enabled when `ERM_DEV_ERROR_REPORT` is set to `STD_ON`.
*/
ERM_StatusType ERM_Init(ERM_HandleType *const pHandle, const ERM_CfgType *const pInitCfg)
{
ERM_StatusType eStatus = ERM_STATUS_SUCCESS;
#if ERM_DEV_ERROR_REPORT == STD_ON
if (pHandle == NULL)
{
ERM_ReportDevError(ERM_INIT_ID, ERM_E_PARAM_NULLPTR);
eStatus = ERM_STATUS_FAIL;
}
else if (pInitCfg == NULL)
{
ERM_ReportDevError(ERM_INIT_ID, ERM_E_PARAM_NULLPTR);
eStatus = ERM_STATUS_FAIL;
}
else if (pHandle->eInstance >= ERM_INSTANCE_COUNT)
{
ERM_ReportDevError(ERM_INIT_ID, ERM_E_PARAM_INSTANCE);
eStatus = ERM_STATUS_FAIL;
}
else
#endif
{
ERM_Type *const pErm = s_apErmBase[pHandle->eInstance];
uint32_t u32CRnValue = 0U;
uint8_t u8CRnIdx = (pInitCfg->u8Channel >> 3U) & 0x1FU;
uint8_t u8CRnPos = (uint8_t)(30U - 4U * (pInitCfg->u8Channel & 0x7U));
ERM_HWA_SetSRn(pErm, u8CRnIdx, (uint32_t)0x03U << u8CRnPos);
u32CRnValue = ERM_HWA_GetCRn(pErm, u8CRnIdx);
/* Enable ERM Channel */
if(pInitCfg->u8ErmEnable != 0U)
{
u32CRnValue |= (uint32_t)pInitCfg->u8IntType << u8CRnPos;
}
/* Disable ERM Channel */
else
{
u32CRnValue &= ~((uint32_t)pInitCfg->u8IntType << u8CRnPos);
}
ERM_HWA_SetCRn(pErm, u8CRnIdx, u32CRnValue);
}
return eStatus;
}
/**
* @brief Deinitializes the ERM module.
*
* This function deinitializes the specified ERM module instance by clearing its control and status registers.
*
* @param pHandle Pointer to the ERM handle structure.
*
* @return ERM_StatusType Indicates the status of the operation (ERM_STATUS_SUCCESS or ERM_STATUS_FAIL).
*
* @note If the handle pointer is NULL or the instance index is out of range, a device error will be reported, and the function returns ERM_STATUS_FAIL.
*/
ERM_StatusType ERM_DeInit(ERM_HandleType *const pHandle)
{
ERM_StatusType eStatus = ERM_STATUS_SUCCESS;
#if ERM_DEV_ERROR_REPORT == STD_ON
if (pHandle == NULL)
{
ERM_ReportDevError(ERM_DEINIT_ID, ERM_E_PARAM_NULLPTR);
eStatus = ERM_STATUS_FAIL;
}
else if (pHandle->eInstance >= ERM_INSTANCE_COUNT)
{
ERM_ReportDevError(ERM_DEINIT_ID, ERM_E_PARAM_INSTANCE);
eStatus = ERM_STATUS_FAIL;
}
else
#endif
{
ERM_Type *const pErm = s_apErmBase[pHandle->eInstance];
uint8_t u8loop;
for (u8loop = 0U; u8loop < ERM_CR_SR_COUNT_MAX; u8loop++)
{
ERM_HWA_SetCRn(pErm, u8loop, 0x0U);
ERM_HWA_SetSRn(pErm, u8loop, ERM_SR0_MASK);
}
}
return eStatus;
}
/**
* @brief Handles common Error Reporting Module (ERM) interrupts and invokes error callbacks
*
* This function serves as the common interrupt handler for the ERM, checking for errors in various channels
* (CTCM, DTCM, PFLASH, optionally DFLASH, and DMA) and invoking the error callback function when an error
* is detected. It also clears the status flags after processing the interrupts.
*
* @param pHandle Pointer to an ERM handle structure containing the instance information and error callback
*
* @preconditions
* - A valid ERM handle must be provided with a potentially registered error callback
*
* @postconditions
* - If an error is detected, the corresponding error callback will be called with details
* including the channel, error type, and the address where the error occurred
* - All ERM status flags will be cleared after handling the interrupts
*
* @note This function is designed to be used within an interrupt context.
* @note Support for DFLASH depends on the compile-time configuration `ERM_DFLASH_SUPPORT`.
*/
void ERM_CommonIRQHandler(ERM_HandleType *const pHandle)
{
#if ERM_DEV_ERROR_REPORT == STD_ON
if (pHandle == NULL)
{
ERM_ReportDevError(ERM_COMMONIRQHANDLER_ID, ERM_E_PARAM_NULLPTR);
}
else if (pHandle->eInstance >= ERM_INSTANCE_COUNT)
{
ERM_ReportDevError(ERM_COMMONIRQHANDLER_ID, ERM_E_PARAM_INSTANCE);
}
else
#endif
{
ERM_Type *const pErm = s_apErmBase[pHandle->eInstance];
uint32_t u32SRnValue;
uint8_t u8LoopI, u8LoopJ, u8Channel, u8ErrorType;
for (u8LoopI = 0U; u8LoopI < ERM_CR_SR_COUNT_MAX; u8LoopI++)
{
u32SRnValue = ERM_HWA_GetSRn(pErm, u8LoopI);
if (u32SRnValue != 0U)
{
for (u8LoopJ = 0U; u8LoopJ < 8U; u8LoopJ++)
{
u8ErrorType = (u32SRnValue >> (30U - 4U * u8LoopJ)) & 0x3U;
if (u8ErrorType != 0)
{
u8Channel = (uint8_t)((u8LoopI << 3U) + u8LoopJ);
if (pHandle->tSettings.pErrorCallback[u8Channel] != NULL)
{
pHandle->tSettings.pErrorCallback[u8Channel](pHandle, u8ErrorType, ERM_HWA_GetEARn(pErm, u8Channel));
}
}
}
ERM_HWA_SetSRn(pErm, u8LoopI, u32SRnValue);
}
}
}
}
#endif /* (ERM_INSTANCE_COUNT > 0U) */