📄 edma3resmgr.c
字号:
}
rmInstance->avlblQdmaChannels[0u]
= rmInstance->initParam.rmInstInitConfig->ownQdmaChannels[0u];
for (resMgrIdx = 0u; resMgrIdx < paramSetDwrds; ++resMgrIdx)
{
rmInstance->avlblPaRAMSets[resMgrIdx]
= rmInstance->initParam.rmInstInitConfig->ownPaRAMSets[resMgrIdx];
}
for (resMgrIdx = 0u; resMgrIdx < tccDwrds; ++resMgrIdx)
{
rmInstance->avlblTccs [resMgrIdx]
= rmInstance->initParam.rmInstInitConfig->ownTccs[resMgrIdx];
}
/*
* If mapping exists b/w DMA channel and PaRAM set (i.e. programmable),
* then mark those PaRAM sets which are mapped to some specific
* DMA channels as RESERVED. If NO mapping (ie ch 0 is tied to PaRAM 0,
* ch 1 is tied to PaRAM 1), mark all as RESERVED.
*/
if (rmObj->gblCfgParams.dmaChPaRAMMapExists == TRUE)
{
/* Mapping Exists */
for (resMgrIdx = 0u; resMgrIdx < rmObj->gblCfgParams.numDmaChannels; ++resMgrIdx)
{
mappedPaRAMId = rmObj->gblCfgParams.dmaChannelPaRAMMap[resMgrIdx];
if (mappedPaRAMId != EDMA3_RM_CH_NO_PARAM_MAP)
{
/* Channel is mapped to a particular PaRAM Set, mark it as Reserved. */
rmInstance->initParam.rmInstInitConfig->resvdPaRAMSets[mappedPaRAMId/32u] |= (1u<<(mappedPaRAMId%32u));
}
}
}
else
{
/* Mapping Doesnot Exist, PaRAM Sets are 1-to-1 mapped, mark all as Reserved */
for (resMgrIdx = 0u; resMgrIdx < dmaChDwrds; ++resMgrIdx)
{
rmInstance->initParam.rmInstInitConfig->resvdPaRAMSets[resMgrIdx] = 0xFFFFFFFFu;
}
}
/*
* If the EDMA RM instance is MASTER (ie. initParam->isMaster
* is TRUE), save the region ID.
* Only this shadow region will receive the
* EDMA3 interrupts, if enabled.
*/
if (TRUE == initParam->isMaster)
{
/* Store the region id to use it in the ISRs */
edma3RegionId = rmInstance->initParam.regionId;
masterExists = TRUE;
}
if (TRUE == initParam->regionInitEnable)
{
edma3ShadowRegionInit (rmInstance);
}
/**
* By default, PaRAM Sets allocated using this RM Instance
* will get cleared during their allocation.
* User can stop their clearing by calling specific IOCTL
* command.
*/
rmInstance->paramInitRequired = TRUE;
/**
* By default, during the EDMA3_RM_allocLogicalChannel (),
* global EDMA3 registers (DCHMAP/QCHMAP) and the allocated
* PaRAM Set will be programmed accordingly, for users using this
* RM Instance.
* User can stop their pre-programming by calling
* EDMA3_RM_IOCTL_SET_GBL_REG_MODIFY_OPTION
* IOCTL command.
*/
rmInstance->regModificationRequired = TRUE;
if (EDMA3_RM_SOK == result)
{
rmObj->state = EDMA3_RM_OPENED;
/* Increase the Instance count */
resMgrObj[phyCtrllerInstId].numOpens++;
retVal = rmInstance;
}
}
else
{
result = EDMA3_RM_E_INVALID_PARAM;
}
edma3OsProtectExit (EDMA3_OS_PROTECT_INTERRUPT, intState);
}
}
}
*errorCode = result;
return (EDMA3_RM_Handle)retVal;
}
/**\fn EDMA3_RM_Result EDMA3_RM_close (EDMA3_RM_Handle hEdmaResMgr,
* const void *param)
* \brief Close EDMA3 Resource Manager Instance
*
* This API is used to close a previously opened EDMA3 RM Instance.
*
* \param hEdmaResMgr [IN] Handle to the previously opened Resource
* Manager Instance.
* \param param [IN] For possible future use.
*
* \return EDMA3_RM_SOK or EDMA3_RM Error Code
*
* \note This function disables the global interrupts (by calling API
* edma3OsProtectEntry with protection level
* EDMA3_OS_PROTECT_INTERRUPT) while modifying the global RM data
* structures, to make it re-entrant.
*/
EDMA3_RM_Result EDMA3_RM_close (EDMA3_RM_Handle hEdmaResMgr,
const void *param)
{
EDMA3_RM_Result result = EDMA3_RM_SOK;
unsigned int intState = 0u;
unsigned int resMgrIdx = 0u;
EDMA3_RM_Obj *rmObj = NULL;
EDMA3_RM_Instance *rmInstance = NULL;
unsigned int dmaChDwrds;
unsigned int paramSetDwrds;
unsigned int tccDwrds;
/*to remove CCS remark: parameter "param" was never referenced */
(void)param;
if (hEdmaResMgr == NULL)
{
result = EDMA3_RM_E_INVALID_PARAM;
}
else
{
rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
rmObj = rmInstance->pResMgrObjHandle;
if (rmObj == NULL)
{
result = (EDMA3_RM_E_INVALID_PARAM);
}
else
{
/* Check state of driver, state should be opened */
if (rmObj->state != EDMA3_RM_OPENED)
{
result = (EDMA3_RM_E_OBJ_NOT_OPENED);
}
else
{
dmaChDwrds = rmObj->gblCfgParams.numDmaChannels / 32u;
paramSetDwrds = rmObj->gblCfgParams.numPaRAMSets / 32u;
tccDwrds = rmObj->gblCfgParams.numTccs / 32u;
/* Set the instance config as NULL*/
for (resMgrIdx = 0u; resMgrIdx < dmaChDwrds; ++resMgrIdx)
{
rmInstance->avlblDmaChannels[resMgrIdx] = 0x0u;
}
for (resMgrIdx = 0u; resMgrIdx < paramSetDwrds; ++resMgrIdx)
{
rmInstance->avlblPaRAMSets[resMgrIdx] = 0x0u;
}
rmInstance->avlblQdmaChannels[0u] = 0x0u;
for (resMgrIdx = 0u; resMgrIdx < tccDwrds; ++resMgrIdx)
{
rmInstance->avlblTccs[resMgrIdx] = 0x0u;
}
/**
* If this is the Master Instance, reset the static variable
* 'masterExists'.
*/
if (TRUE == rmInstance->initParam.isMaster)
{
masterExists = FALSE;
edma3RegionId = EDMA3_MAX_REGIONS;
}
/* Reset the Initparam for this RM Instance */
edma3MemSet((void *)&(rmInstance->initParam) , 0x00u,
sizeof(EDMA3_RM_Param));
/* Critical section starts */
edma3OsProtectEntry (EDMA3_OS_PROTECT_INTERRUPT, &intState);
/* Decrease the Number of Opens */
--rmObj->numOpens;
if (NULL == rmObj->numOpens)
{
edma3MemSet((void *)&(edma3RmChBoundRes[rmObj->phyCtrllerInstId]), 0x00u,
sizeof(edma3RmChBoundRes));
rmObj->state = EDMA3_RM_CLOSED;
}
/* Critical section ends */
edma3OsProtectExit (EDMA3_OS_PROTECT_INTERRUPT, intState);
rmInstance->pResMgrObjHandle = NULL;
rmInstance->shadowRegs = NULL;
rmInstance = NULL;
}
}
}
return result;
}
/**\fn EDMA3_RM_Result EDMA3_RM_allocResource (EDMA3_RM_Handle hEdmaResMgr,
* EDMA3_RM_ResDesc *resObj)
* \brief This API is used to allocate specified EDMA3 Resources like
* DMA/QDMA channel, PaRAM Set or TCC.
*
* Note: To free the resources allocated by this API, user should call
* EDMA3_RM_freeResource () ONLY to de-allocate all the allocated resources.
*
* User can either request a specific resource by passing the resource id
* in 'resObj->resId' OR request ANY available resource of the type
* 'resObj->type'.
*
* ANY types of resources are those resources when user doesn't care about the
* actual resource allocated; user just wants a resource of the type specified.
* One use-case is to perform memory-to-memory data transfer operation. This
* operation can be performed using any available DMA or QDMA channel.
* User doesn't need any specific channel for the same.
*
* To allocate a specific resource, first this API checks whether that resource
* is OWNED by the Resource Manager instance. Then it checks the current
* availability of that resource.
*
* To allocate ANY available resource, this API tries to allocate a resource
* from the pool of (owned && non_reserved && available_right_now) resources.
*
* After allocating a DMA/QDMA channel or TCC, the same resource is enabled in
* the shadow region specific register (DRAE/DRAEH/QRAE).
*
* Allocated PaRAM Set is initialized to NULL before this API returns if user
* has requested for one.
*
* \param hEdmaResMgr [IN] Handle to the previously opened Resource
* Manager Instance.
* \param resObj [IN/OUT] Handle to the resource descriptor
* object, which needs to be allocated.
* In case user passes a specific resource
* Id, resObj value is left unchanged.
* In case user requests ANY available
* resource, the allocated resource id is
* returned in resObj.
*
* \return EDMA3_RM_SOK or EDMA3_RM Error Code
*
* \note This function acquires a RM Instance specific semaphore
* to prevent simultaneous access to the global pool of resources.
* It is re-entrant, but should not be called from the user callback
* function (ISR context).
*/
EDMA3_RM_Result EDMA3_RM_allocResource(EDMA3_RM_Handle hEdmaResMgr,
EDMA3_RM_ResDesc *resObj)
{
EDMA3_RM_Instance *rmInstance = NULL;
EDMA3_RM_Obj *rmObj = NULL;
EDMA3_RM_Result result = EDMA3_RM_SOK;
EDMA3_RM_Result semResult = EDMA3_RM_SOK;
unsigned int avlblIdx = 0u;
unsigned int resIdClr = 0x0;
unsigned int resIdSet = 0x0;
unsigned int resId;
volatile EDMA3_CCRL_Regs *gblRegs = NULL;
#ifdef EDMA3_INSTRUMENTATION_ENABLED
EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -