PeripheralDriver_Flagchip_F.../Src/module_driver_mam.c

365 lines
12 KiB
C

/**
* @file module_driver_mam.c
* @author Flagchip
* @brief MAM driver source code
* @version 2.0.0
* @date 2024-08-20
*
* SDK Version: 2.6.0
*
* @copyright Copyright (c) 2020-2024 Flagchip Semiconductors Co., Ltd.
*
*/
/* ********************************************************************************
* Revision History:
*
* Version Date Initials CR# Descriptions
* --------- ---------- ------------ ---------- ---------------
* 0.1.0 2023-02-08 Flagchip054 N/A First version for FC7300
* 2.5.0 2025-08-20 Flagchip0100 N/A Add FC7300F4MDDxxxT1C support
******************************************************************************** */
#include "module_driver_mam.h"
#if MAM_INSTANCE_COUNT > 0U
/**
* @struct MAM_Inf_Type
* @brief Matrix Access Monitor Information Structure
*/
typedef struct
{
uint16_t error;
uint16_t mam_num;
uint32_t block_num;
} MAM_Inf_Type;
/**
* @struct MAM_Block_Region_Type
* @brief Matrix Access Monitor Block Region Configuration Structure
*/
typedef struct
{
uint32_t start_addr;
uint32_t end_addr;
uint32_t block_size;
uint16_t block_base;
uint16_t mam_idx;
} MAM_Block_Region_Type;
static MAM_Type *const s_apMamBase[MAM_INSTANCE_COUNT] = MAM_BASE_PTRS;
static const uint32_t s_u32MamAcr[MAM_INSTANCE_COUNT] = MAM_ACR_OFFSET;
static const MAM_Block_Region_Type block_region[MAM_BLOCK_REGION_MAX] = {MAM_BLOCK_REGION};
/**
* @brief Get MAM information for a given memory address
*
* This function searches through all configured memory regions to determine
* which MAM instance and block number corresponds to the specified address.
*
* @param u32Addr Memory address to lookup (32-bit physical address)
*
* @return MAM_Inf_Type Structure containing:
* - error: 0 if address found in valid region, 1 if not found
* - mam_num: MAM instance index responsible for the address
* - block_num: Calculated block number within the MAM instance
*/
static MAM_Inf_Type MAM_GetMamInf(uint32_t u32Addr);
/*************** Local Functions ***************/
/**
* @brief Get MAM information for a given memory address
*
* This function searches through all configured memory regions to determine
* which MAM instance and block number corresponds to the specified address.
*
* @param u32Addr Memory address to lookup (32-bit physical address)
*
* @return MAM_Inf_Type Structure containing:
* - error: 0 if address found in valid region, 1 if not found
* - mam_num: MAM instance index responsible for the address
* - block_num: Calculated block number within the MAM instance
*/
static MAM_Inf_Type MAM_GetMamInf(uint32_t u32Addr)
{
uint32_t u32AddrOffset;
uint32_t u32LoopI;
MAM_Inf_Type inf = { .error = 1 };
for (u32LoopI = 0u; u32LoopI < MAM_BLOCK_REGION_MAX; ++u32LoopI)
{
if ((block_region[u32LoopI].start_addr <= u32Addr) &&
(u32Addr <= block_region[u32LoopI].end_addr))
{
u32AddrOffset = u32Addr - block_region[u32LoopI].start_addr;
inf.error = 0;
inf.mam_num = block_region[u32LoopI].mam_idx;
inf.block_num = (u32AddrOffset >> block_region[u32LoopI].block_size) + block_region[u32LoopI].block_base;
break;
}
}
return inf;
}
#ifdef MAM_SOFT_RESET_SUPPORT
/***************** Global Functions *******************/
/**
* @brief Perform software reset of the specified Matrix Access Monitor instance
*
* This function resets the Matrix Access Monitor (MAM) hardware to its default
* state by toggling the matrix configuration bit. The reset clears all MAM
* configuration registers and monitoring states.
*
* @param eMam MAM instance index to reset (MAM_INDEX_0, MAM_INDEX_1, etc.)
*/
void MAM_Reset(MAM_Index_Type eMam)
{
MAM_Type *const pMam = s_apMamBase[(uint32_t)eMam];
Mam_HWA_SetMatrixCfg(pMam, 0x01U);
DSB();
Mam_HWA_SetMatrixCfg(pMam, 0x00U);
DSB();
}
#endif
/**
* @brief Enable watchdog for a specific master on the Matrix Access Monitor
*
* This function configures and enables the watchdog timer for a specified master
* interface on the MAM. The watchdog monitors access violations and can generate
* interrupts or system resets on timeout.
*
* @param eMam MAM instance index (MAM_INDEX_0, MAM_INDEX_1, etc.)
* @param eMaster Master interface to monitor (MAM_MASTER_0, MAM_MASTER_1, etc.)
* @param eWdgTo Watchdog timeout value selection
* @param eWdgDiv Watchdog clock divider ratio
*/
void MAM_WdogEnable(MAM_Index_Type eMam, MAM_Master_Type eMaster, MAM_Wdog_Timeout_Type eWdgTo, MAM_Wdog_Div_Type eWdgDiv)
{
uint32_t regval = 0U;
uint32_t bit_idx = 0U;
MAM_Type *const pMam = s_apMamBase[(uint32_t)eMam];
#ifdef MAM_WDOG_DIV_SUPPORT
bit_idx = (uint32_t)eMaster << 2;
regval = Mam_HWA_GetWdgDiv(pMam);
regval = (regval & ~(0xFUL << bit_idx)) | ((uint32_t)eWdgDiv << bit_idx);
Mam_HWA_SetWdgDiv(pMam, regval);
#else
regval = ((uint32_t)eWdgDiv << bit_idx);
#endif
bit_idx = (uint32_t)eMaster << 1;
regval = Mam_HWA_GetWdgToCr(pMam);
regval = (regval & ~(0x3UL << bit_idx)) | ((uint32_t)eWdgTo << bit_idx);
Mam_HWA_SetWdgToCr(pMam, regval);
bit_idx = (uint32_t)eMaster;
regval = Mam_HWA_GetWdgCr(pMam);
regval |= 1UL << bit_idx;
Mam_HWA_SetWdgCr(pMam, regval);
}
/**
* @brief Disable watchdog for a specific master on the Matrix Access Monitor
*
* This function disables the watchdog timer for a specified master interface
* on the MAM, preventing further access violation monitoring for that master.
*
* @param eMam MAM instance index (MAM_INDEX_0, MAM_INDEX_1, etc.)
* @param eMaster Master interface to disable watchdog for (MAM_MASTER_0, MAM_MASTER_1, etc.)
*/
void MAM_WdogDisable(MAM_Index_Type eMam, MAM_Master_Type eMaster)
{
uint32_t regval = 0U;
uint32_t bit_idx = 0U;
MAM_Type *const pMam = s_apMamBase[(uint32_t)eMam];
bit_idx = (uint32_t)eMaster;
regval = Mam_HWA_GetWdgCr(pMam);
regval &= ~(1UL << bit_idx);
Mam_HWA_SetWdgCr(pMam, regval);
}
/**
* @brief Configure access control for a specific memory address and master
*
* This function sets the access control permissions for a memory block
* corresponding to the specified address for a particular master interface.
* The configuration determines what type of access (read/write) is allowed.
*
* @param eMaster Master interface to configure (MAM_MASTER_0, MAM_MASTER_1, etc.)
* @param u32Addr Memory address within the block to configure
* @param u32Val Access control value (4-bit field) to set
* Typically defines read/write permissions for the master
*
* @return uint8_t Status code:
* - 0: Configuration successful
* - 1: Error - address not found in any configured MAM region
*/
uint8_t MAM_Config(MAM_Master_Type eMaster, uint32_t u32Addr, uint32_t u32Val)
{
MAM_Inf_Type inf = MAM_GetMamInf(u32Addr);
MAM_Type *pMam;
uint32_t reg_idx = 0U;
uint32_t bit_idx = 0U;
uint32_t regval = 0U;
uint8_t status = 0U;
if (inf.error == 1U)
{
status = 1U;
}
else
{
pMam = s_apMamBase[inf.mam_num];
reg_idx = (inf.block_num >> 3U) + s_u32MamAcr[inf.mam_num] * (uint32_t)eMaster;
bit_idx = (inf.block_num & 0x7U) << 2;
regval = Mam_HWA_Get_ACR(pMam, reg_idx);
regval = (regval & ~(0xFUL << bit_idx)) | (u32Val << bit_idx);
Mam_HWA_Set_ACR(pMam, reg_idx, regval);
}
return status;
}
/**
* @brief Lock access control configuration for a specific memory block
*
* This function sets the lock bit for the memory block containing the specified
* address, preventing further modifications to its access control configuration.
* Once locked, the access permissions cannot be changed until system reset.
*
* @param u32Addr Memory address within the block to lock
*
* @return uint8_t Status code:
* - 0: Lock operation successful
* - 1: Error - address not found in any configured MAM region
*/
uint8_t MAM_ConfigLock(uint32_t u32Addr)
{
MAM_Inf_Type inf = MAM_GetMamInf(u32Addr);
MAM_Type *pMam;
uint32_t reg_idx = 0U;
uint32_t bit_idx = 0U;
uint32_t regval = 0U;
uint8_t status = 0U;
if (inf.error == 1U)
{
status = 1U;
}
else
{
pMam = s_apMamBase[inf.mam_num];
reg_idx = (inf.block_num >> 5U);
bit_idx = inf.block_num & 0x1FU;
regval = Mam_HWA_Get_ACLR(pMam, reg_idx);
regval |= 1UL << bit_idx;
Mam_HWA_Set_ACLR(pMam, reg_idx, regval);
}
return status;
}
#ifdef MAM_PORT_MONITOR_SUPPORT
/**
* @brief Enable monitoring for a specific port on the Matrix Access Monitor
*
* This function enables access monitoring for a specified port interface
* on the MAM. When enabled, the MAM will track and report access events
* through the specified monitor port.
*
* @param eMam MAM instance index (MAM_INDEX_0, MAM_INDEX_1, etc.)
* @param eMonitor Monitor port to enable (MAM_MONITOR_0, MAM_MONITOR_1, etc.)
*/
void MAM_MonitorEnable(MAM_Index_Type eMam, MAM_Monitor_Type eMonitor)
{
uint32_t regVal;
MAM_Type *const pMam = s_apMamBase[(uint32_t)eMam];
regVal = Mam_HWA_Get_CCLR(pMam);
regVal |= (1UL << (uint32_t)eMonitor);
Mam_HWA_Set_CCLR(pMam, regVal);
}
/**
* @brief Disable monitoring for a specific port on the Matrix Access Monitor
*
* This function disables access monitoring for a specified port interface
* on the MAM. When disabled, the MAM will no longer track or report
* access events through the specified monitor port.
*
* @param eMam MAM instance index (MAM_INDEX_0, MAM_INDEX_1, etc.)
* @param eMonitor Monitor port to disable (MAM_MONITOR_0, MAM_MONITOR_1, etc.)
*/
void MAM_MonitorDisable(MAM_Index_Type eMam, MAM_Monitor_Type eMonitor)
{
uint32_t regVal;
MAM_Type *const pMam = s_apMamBase[(uint32_t)eMam];
regVal = Mam_HWA_Get_CCLR(pMam);
regVal &= ~(1UL << (uint32_t)eMonitor);
Mam_HWA_Set_CCLR(pMam, regVal);
}
#endif
#ifdef MAM_SLAVE_PRIORITY_SUPPORT
/**
* @brief Enable priority arbitration for a specific slave interface
*
* This function configures and enables priority-based arbitration for a
* specified slave interface on the MAM. It assigns a priority master that
* will be granted access when multiple masters attempt to access the same slave.
*
* @param eMam MAM instance index (MAM_INDEX_0, MAM_INDEX_1, etc.)
* @param eSlave Slave interface to configure priority for (MAM_SLAVE_0 to MAM_SLAVE_15)
* @param eMaster Master interface to assign as priority master for the slave
*/
void MAM_SlavePriorityEnable(MAM_Index_Type eMam, MAM_Slave_Type eSlave, MAM_Master_Type eMaster)
{
uint32_t regVal;
MAM_Type *const pMam = s_apMamBase[(uint32_t)eMam];
if ((uint32_t)eSlave < MAM_SLAVE_8)
{
regVal = Mam_HWA_Get_PRI_ID_SLVGRP0(pMam);
regVal = (regVal & ~(0xF << ((uint32_t)eSlave << 2))) | ((uint32_t)eMaster << ((uint32_t)eSlave << 2));
Mam_HWA_Set_PRI_ID_SLVGRP0(pMam, regVal);
}
else
{
regVal = (uint32_t)eMaster;
Mam_HWA_Set_PRI_ID_SLVGRP1(pMam, regVal);
}
regVal = Mam_HWA_Get_PRI_EN(pMam);
regVal |= (1UL << (uint32_t)eSlave);
Mam_HWA_Set_PRI_EN(pMam, regVal);
}
/**
* @brief Disable priority arbitration for a specific slave interface
*
* This function disables priority-based arbitration for a specified slave
* interface on the MAM, returning it to default round-robin arbitration.
*
* @param eMam MAM instance index (MAM_INDEX_0, MAM_INDEX_1, etc.)
* @param eSlave Slave interface to disable priority for (MAM_SLAVE_0 to MAM_SLAVE_15)
*/
void MAM_SlavePriorityDisable(MAM_Index_Type eMam, MAM_Slave_Type eSlave)
{
uint32_t regVal;
MAM_Type *const pMam = s_apMamBase[(uint32_t)eMam];
regVal = Mam_HWA_Get_PRI_EN(pMam);
regVal &= ~(1UL << (uint32_t)eSlave);
Mam_HWA_Set_PRI_EN(pMam, regVal);
}
#endif
#endif /* #if MAM_INSTANCE_COUNT > 0U */