2025-04-10 17:31:33 +08:00

808 lines
26 KiB
C

/******************************************************************************
*(C) Copyright 2018 EIGENCOMM International Ltd.
* All Rights Reserved
******************************************************************************
* Filename:
*
* Description:
*
* History: initiated by xuwang
*
* Notes:
*
******************************************************************************/
/*----------------------------------------------------------------------------*
* INCLUDES *
*----------------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include "cmsis_os2.h"
#include "osaulfcmem.h"
#include "exception_process.h"
#if defined CHIP_EC718 || defined CHIP_EC716
#include "system_ec7xx.h"
#elif defined CHIP_EC618
#include "system_ec618.h"
#endif
#include "sctdef.h"
#include DEBUG_LOG_HEADER_FILE
/*----------------------------------------------------------------------------*
* MACROS *
*----------------------------------------------------------------------------*/
#define OSA_ULFC_MEM_UNSET_TIMER_PERIOD (2 * 1000) /* 2sec, unit: ms */
/* lan max chanNo is 16(4bits) */
#define OSA_ULFC_MEM_NODE_MAXNUM 16
/* max task cnt is supported! */
#define OSA_ULFC_MEM_MSGQ_MAXNUM 4
#define OSA_ULFC_MEM_ALLOC_MAGIC 0xBFCA
#define OSA_ULFC_MEM_FREED_MAGIC 0xBFCF
#define OSA_ULFC_BLOCKING_EVT_FLAGS 0xF
/* MCB: memory control block */
#define OSA_ULFC_MCB_TOTAL_SIZE(hasPbuf, hasUlpdu) (sizeof(OsaUlfcMemHdr_t) + \
((hasPbuf) ? LWIP_PBUF_STRUCT_LEN : 0) + \
((hasUlpdu) ? sizeof(UlPduBlock) : 0))
#define OSA_ULFC_ALIGN_UP(x,sz) (((x) + ((sz) - 1)) & (~((sz) - 1)))
#define OSA_ULFC_ALIGN_DOWN(x,sz) ((x) & (~((sz) - 1)))
#define OSA_ULFC_MEM_TFCM_SET(tfcm, fid) ((tfcm) |= (1 << (fid)))
#define OSA_ULFC_MEM_TFCM_CLR(tfcm, fid) ((tfcm) &= ~(1 << (fid)))
#define OSA_ULFC_MEM_BUILD_HDR(hdr, len, xtras) \
do\
{\
((OsaUlfcMemHdr_t*)(hdr))->magicNum = OSA_ULFC_MEM_ALLOC_MAGIC;\
((OsaUlfcMemHdr_t*)(hdr))->extras = (xtras);\
((OsaUlfcMemHdr_t*)(hdr))->memSize = (len);\
}while(0)
#define OSA_ULFC_MEM_BUILD_ULPDU(ulpdu, chno, buf, len, bpbuf) UL_PDU_BLOCK_SET_BASICS(ulpdu, chno, UL_AFC_MEM, 1, buf, len, bpbuf, 0, NULL)
/*----------------------------------------------------------------------------*
* DATA TYPE DEFINITION *
*----------------------------------------------------------------------------*/
typedef uint32_t OsaUlfcMemFactorId_bm;
typedef struct
{
uint8_t isInit :1;
uint8_t hasAlert :1; /* 0/1: has reached/been above alert line or not? */
uint8_t hasNotif :1; /* 0/1: has notified the memory event(low water)? */
uint8_t isUnset :1; /* 0/1: ulfc conf will be unset? */
uint8_t rsvdBits :4;
uint8_t refNum;
uint8_t rsvd[2];
/* memory state machine:
* ___________________
* | |
* V |
* FREE --> FROZEN --> USED
*/
uint32_t memFrozen;
uint32_t memUsed;
uint32_t memUsedPeak;
uint32_t memThres;
uint32_t memThresAlert;
uint32_t memThresAlertPct;
uint32_t memAllocCnt;
uint32_t memFreeCnt;
osTimerId_t ustTimer;
osEventFlagsId_t handle;
OsaUlfcSrcTaskId_bm bmTaskId;
OsaUlfcMemFactorId_bm memTfcm; /* TFCM: Trigggerd-Factor-Control-Map */
}OsaUlfcMemNode_t;
typedef struct
{
uint8_t taskId; /* OsaUlfcSrcTaskId_e */
uint8_t chanNo;
uint8_t rsvd[2];
OsaUlfcMemNode_t *memNode;
}OsaUlfcTimerCtx_t;
typedef struct
{
OsaUlfcMemNode_t memNode[OSA_ULFC_MEM_NODE_MAXNUM];
OsaUlfcTimerCtx_t timerCtx[OSA_ULFC_MEM_NODE_MAXNUM];
}OsaUlfcMemMan_t;
/*----------------------------------------------------------------------------*
* PRIVATE FUNCTION DECLEARATION *
*----------------------------------------------------------------------------*/
extern void ccioReportUlfcMemEvent(OsaUlfcMemEvtFlags_e flags, OsaUlfcMemEvtArgs_t *args);
/*----------------------------------------------------------------------------*
* GLOBAL VARIABLES *
*----------------------------------------------------------------------------*/
/* ULFC memory is supported or not? */
AP_PLAT_COMMON_DATA static uint16_t gOsaUlfcMemSuppFlag = 1;
AP_PLAT_COMMON_BSS static OsaUlfcMemMan_t gOsaUlfcMemMan;
/*----------------------------------------------------------------------------*
* PRIVATE FUNCTIONS *
*----------------------------------------------------------------------------*/
static void OsaUlfcUnsetTimerExpr(OsaUlfcTimerCtx_t *timerCtx)
{
uint8_t isUnset = 0;
if(timerCtx->chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_TIMER_EXPR_1, P_WARNING, "invalid chanNo(%d) err!", timerCtx->chanNo);
return;
}
ECPLAT_PRINTF(UNILOG_OSA, ULFC_TIMER_EXPR_2, P_SIG, "UlfcMem(%d): task(%d/0x%x) unset(%d) timer event!",
timerCtx->chanNo,
timerCtx->taskId,
timerCtx->memNode->bmTaskId,
timerCtx->memNode->isUnset);
uint32_t mask = SaveAndSetIRQMask();
EC_ASSERT(timerCtx->memNode->isInit, timerCtx->memNode, timerCtx->chanNo, timerCtx->taskId);
isUnset = timerCtx->memNode->isUnset;
RestoreIRQMask(mask);
if(isUnset)
{
OsaUlfcDisable(timerCtx->chanNo, timerCtx->taskId);
}
}
/*----------------------------------------------------------------------------*
* GLOBAL FUNCTIONS *
*----------------------------------------------------------------------------*/
/******************************************************************************
* @brief : OsaUlfcSetMemSuppFlag
* @author: Xu.Wang
* @note : support Ulfc Policy or Not?
******************************************************************************/
void OsaUlfcSetMemSuppFlag(uint16_t isSupp)
{
gOsaUlfcMemSuppFlag = isSupp;
}
/******************************************************************************
* @brief : OsaUlfcGetMemUsedThresAlertPct
* @author: Xu.Wang
* @note :
******************************************************************************/
uint32_t OsaUlfcGetMemUsedThresAlertPct(uint8_t chanNo)
{
OsaUlfcMemNode_t *memNode = NULL;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_GET_USED_THRES_ALERT_PCT, P_WARNING, "invalid chanNo(%d) err!", chanNo);
return 0;
}
memNode = &gOsaUlfcMemMan.memNode[chanNo];
if(!memNode->isInit) return OSA_ULFC_MEM_USED_THRES_ALERT_PCT_ANY;
return memNode->memThresAlertPct;
}
/******************************************************************************
* @brief : OsaUlfcSetMemUsedThresAlertPct
* @author: Xu.Wang
* @note :
******************************************************************************/
void OsaUlfcSetMemUsedThresAlertPct(uint8_t chanNo, uint8_t alertPct)
{
OsaUlfcMemNode_t *memNode = NULL;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM || alertPct > 100)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_SET_USED_THRES_ALERT_PCT, P_WARNING, "invalid chanNo(%d) or alertPct(%d) err!", chanNo, alertPct);
return;
}
memNode = &gOsaUlfcMemMan.memNode[chanNo];
if(!memNode->isInit) return;
memNode->memThresAlert = ((memNode->memThres * alertPct) / 100);
memNode->memThresAlertPct = alertPct;
}
/******************************************************************************
* @brief : OsaUlfcGetMemUsedSizeThres
* @author: Xu.Wang
* @note :
******************************************************************************/
uint32_t OsaUlfcGetMemUsedSizeThres(uint8_t chanNo)
{
OsaUlfcMemNode_t *memNode = NULL;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_GET_USED_THRES, P_WARNING, "invalid chanNo(%d) err!", chanNo);
return 0;
}
memNode = &gOsaUlfcMemMan.memNode[chanNo];
if(!memNode->isInit) return OSA_ULFC_MEM_USED_THRES_ANY;
return memNode->memThres;
}
/******************************************************************************
* @brief : OsaUlfcSetMemUsedSizeThres
* @author: Xu.Wang
* @note :
******************************************************************************/
void OsaUlfcSetMemUsedSizeThres(uint8_t chanNo, uint32_t usedSize)
{
OsaUlfcMemNode_t *memNode = NULL;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_SET_USED_THRES, P_WARNING, "invalid chanNo(%d) err!", chanNo);
return;
}
memNode = &gOsaUlfcMemMan.memNode[chanNo];
if(!memNode->isInit) return;
memNode->memThres = OSA_ULFC_ALIGN_UP(usedSize, 4);
memNode->memThresAlert = ((memNode->memThres * memNode->memThresAlertPct) / 100);
}
/******************************************************************************
* @brief : OsaUlfcQueryEnableState
* @author: Xu.Wang
* @note :
******************************************************************************/
PPP_FM_RAMCODE uint8_t OsaUlfcQueryEnableState(uint8_t chanNo)
{
uint8_t isEnabled = 0;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_QUERY_ENABLE_STATE, P_WARNING, "invalid chanNo(%d) err!", chanNo);
return 0;
}
uint32_t mask = SaveAndSetIRQMask();
isEnabled = gOsaUlfcMemMan.memNode[chanNo].isInit;
RestoreIRQMask(mask);
return isEnabled;
}
/******************************************************************************
* @brief : OsaUlfcQueryMemAvlbSize
* @author: Xu.Wang
* @note :
******************************************************************************/
PPP_FM_RAMCODE uint32_t OsaUlfcQueryMemAvlbSize(uint8_t chanNo)
{
uint32_t avlbSize = 0;
uint32_t totalSize = 0;
OsaUlfcMemNode_t *memNode = NULL;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_QUERY_AVLB_SIZE, P_WARNING, "invalid chanNo(%d) err!", chanNo);
return 0;
}
memNode = &gOsaUlfcMemMan.memNode[chanNo];
if(!memNode->isInit) return 0;
uint32_t mask = SaveAndSetIRQMask();
/* MCB size will be double if the imcoming data is stored in the tail and the head of the rbuf! */
totalSize = memNode->memFrozen + memNode->memUsed + (OSA_ULFC_MCB_TOTAL_SIZE(1, 1) << 1);
avlbSize = memNode->memThres > totalSize ? (memNode->memThres - totalSize) : 0;
RestoreIRQMask(mask);
return avlbSize;
}
/******************************************************************************
* @brief : OsaUlfcGetMemStat
* @author: Xu.Wang
* @note :
******************************************************************************/
void OsaUlfcGetMemStat(uint8_t *buf, uint16_t bufLen)
{
uint8_t *ptr = buf;
uint16_t tempSize = 0;
uint16_t remnSize = bufLen;
OsaUlfcMemNode_t *memNode = &gOsaUlfcMemMan.memNode[0];
if(!gOsaUlfcMemSuppFlag) return;
if(!buf) return;
for(uint16_t loop = 0; loop < OSA_ULFC_MEM_NODE_MAXNUM; loop++)
{
if(!memNode[loop].isInit) continue;
tempSize = snprintf((char*)ptr, tempSize, "UlfcMem(%d/%d): tfcm(0x%x), frozen(%d), usedPeak(%d), used(%d), usedThres(%d/%d%%), alertThres(%d)\r\n",
loop, gOsaUlfcMemSuppFlag, memNode[loop].memTfcm, memNode[loop].memFrozen, memNode[loop].memUsedPeak, memNode[loop].memUsed,
memNode[loop].memThres, memNode[loop].memThresAlertPct, memNode[loop].memThresAlert);
ptr += tempSize;
remnSize -= tempSize;
}
}
/******************************************************************************
* @brief : OsaUlfcFreezeMem
* @author: Xu.Wang
* @note :
******************************************************************************/
PPP_FM_RAMCODE void OsaUlfcFreezeMem(uint8_t chanNo, uint32_t wantedSize)
{
#if 0
uint32_t mask = 0;
uint32_t frozenSize = OSA_ULFC_ALIGN_UP(wantedSize, 4) + OSA_ULFC_MCB_TOTAL_SIZE(1, 1);
OsaUlfcMemNode_t *memNode = NULL;
EC_ASSERT(chanNo < OSA_ULFC_MEM_NODE_MAXNUM && gOsaUlfcMemMan.memNode[chanNo].isInit, chanNo, gOsaUlfcMemMan.memNode[chanNo].isInit, wantedSize);
memNode = &gOsaUlfcMemMan.memNode[chanNo];
if(gOsaUlfcMemSuppFlag)
{
mask = SaveAndSetIRQMask();
memNode->memFrozen += frozenSize;
RestoreIRQMask(mask);
}
#endif
return;
}
/******************************************************************************
* @brief : OsaUlfcAllocMem
* @author: Xu.Wang
* @note :
******************************************************************************/
PPP_FM_RAMCODE void* OsaUlfcAllocMem(uint32_t wantedSize, uint8_t hasPbuf, uint8_t hasUlpdu, uint8_t isBlocking, uint16_t extras)
{
uint8_t *buffer = NULL;
uint8_t *ptr = NULL;
uint32_t mask = 0;
uint32_t memUsed = 0;
//uint32_t allocSize = OSA_ULFC_ALIGN_UP(wantedSize, 4) + OSA_ULFC_MCB_TOTAL_SIZE(hasPbuf, hasUlpdu);
uint32_t allocSize = OSA_ULFC_ALIGN_UP(wantedSize, 4) + OSA_ULFC_MCB_TOTAL_SIZE(1, 1);
osEventFlagsId_t handle = NULL;
OsaUlfcMemNode_t *memNode = NULL;
OsaUlfcMemFactorId_bm memTfcm = 0;
OsaUlfcMemEvtArgs_t evtArgs;
EC_ASSERT(wantedSize || __get_IPSR() == 0, wantedSize, __get_IPSR(), extras);
EC_ASSERT(extras < OSA_ULFC_MEM_NODE_MAXNUM && gOsaUlfcMemMan.memNode[extras].isInit, extras, gOsaUlfcMemMan.memNode[extras].isInit, wantedSize);
memNode = &gOsaUlfcMemMan.memNode[extras];
while(gOsaUlfcMemSuppFlag)
{
mask = SaveAndSetIRQMask();
if(memNode->memUsed /*+ allocSize*/ >= memNode->memThres)
{
OSA_ULFC_MEM_TFCM_SET(memNode->memTfcm, OSA_ULFC_MFI_MEM_THRES);
}
else
{
OSA_ULFC_MEM_TFCM_CLR(memNode->memTfcm, OSA_ULFC_MFI_MEM_THRES);
}
memTfcm = memNode->memTfcm;
memUsed = memNode->memUsed;
handle = memNode->handle;
RestoreIRQMask(mask);
if(isBlocking && !handle)
{
handle = osEventFlagsNew(NULL);
EC_ASSERT(handle, wantedSize, 0, 0);
mask = SaveAndSetIRQMask();
memNode->handle = handle;
RestoreIRQMask(mask);
}
if(!memTfcm) break;
/* callback by user! */
evtArgs.extras = extras;
evtArgs.memUsed = memUsed;
OsaUlfcNotifyMemEvent(OSA_ULFC_MEF_HIGH_WATER, &evtArgs);
if(!isBlocking) return NULL;
osEventFlagsWait(memNode->handle, OSA_ULFC_BLOCKING_EVT_FLAGS, osFlagsWaitAny, osWaitForever);
}
buffer = (uint8_t*)mallocEc(allocSize);
if(buffer == NULL)
{
return NULL;
}
mask = SaveAndSetIRQMask();
memNode->memAllocCnt ++;
memNode->memFrozen -= (memNode->memFrozen <= allocSize ? memNode->memFrozen : allocSize);
memNode->memUsed += allocSize;
if(memNode->memUsed > memNode->memUsedPeak)
{
memNode->memUsedPeak = memNode->memUsed;
}
/* reach or above the alert line */
if(!memNode->hasAlert && memNode->memUsed >= memNode->memThresAlert)
{
memNode->hasAlert = 1;
ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_ALLOC_1, P_SIG, "UlfcMem(%d): alerting water! usedSize(%d), alertThres(%d/%d%%)",
extras, memNode->memUsed, memNode->memThresAlert, memNode->memThresAlertPct);
}
RestoreIRQMask(mask);
OSA_ULFC_MEM_BUILD_HDR(buffer, allocSize - sizeof(OsaUlfcMemHdr_t), extras);
/* skip the ulfc hdr */
buffer += sizeof(OsaUlfcMemHdr_t);
if(hasPbuf)
{
ptr = buffer + LWIP_PBUF_STRUCT_LEN;
}
else
{
ptr = buffer;
}
if(hasUlpdu)
{
memset(ptr, 0, sizeof(UlPduBlock));
OSA_ULFC_MEM_BUILD_ULPDU(ptr, extras, ptr + sizeof(UlPduBlock), wantedSize, hasPbuf);
}
//ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_ALLOC_2, P_INFO, "UlfcMem(%d): alloc addr(0x%x), size(%d)", extras, buffer, allocSize);
return (void*)buffer;
}
/******************************************************************************
* @brief : OsaUlfcFreeMem
* @author: Xu.Wang
* @note :
******************************************************************************/
PPP_FM_RAMCODE void OsaUlfcFreeMem(void *ptr)
{
uint8_t hasAlert = 0;
uint8_t hasNotif = 0;
uint16_t extras = 0;
uint32_t freeSize = 0;
uint32_t memUsed = 0;
OsaUlfcMemNode_t *memNode = NULL;
OsaUlfcMemHdr_t *ulfcHdr = NULL;
OsaUlfcMemEvtArgs_t evtArgs;
EC_ASSERT(ptr || __get_IPSR() == 0, __get_IPSR(), ptr, 0);
ulfcHdr = (OsaUlfcMemHdr_t*)((uint8_t*)ptr - sizeof(OsaUlfcMemHdr_t));
EC_ASSERT(ulfcHdr->magicNum == OSA_ULFC_MEM_ALLOC_MAGIC, ulfcHdr->magicNum, OSA_ULFC_MEM_ALLOC_MAGIC, ulfcHdr);
extras = ulfcHdr->extras;
/* set it freed magic */
ulfcHdr->magicNum = OSA_ULFC_MEM_FREED_MAGIC;
freeSize = OSA_ULFC_ALIGN_UP(ulfcHdr->memSize, 4) + sizeof(OsaUlfcMemHdr_t);
freeEc(ulfcHdr);
EC_ASSERT(extras < OSA_ULFC_MEM_NODE_MAXNUM && gOsaUlfcMemMan.memNode[extras].isInit,
extras, OSA_ULFC_MEM_NODE_MAXNUM, gOsaUlfcMemMan.memNode[extras].isInit);
memNode = &gOsaUlfcMemMan.memNode[extras];
uint32_t mask = SaveAndSetIRQMask();
EC_ASSERT(memNode->memUsed >= freeSize, memNode->memUsed, freeSize, extras);
memNode->memFreeCnt ++;
memNode->memUsed -= freeSize;
hasAlert = memNode->hasAlert;
hasNotif = memNode->hasNotif;
memUsed = memNode->memUsed;
RestoreIRQMask(mask);
/* always trigger it! */
if(gOsaUlfcMemSuppFlag)
{
/* set it 85% of alerting water level to reduce the event of low water! */
if(hasAlert && (memUsed < (memNode->memThresAlert * 70) / 100))
{
/* no matter to notify twice or more... */
if(!hasNotif)
{
uint32_t mask = SaveAndSetIRQMask();
memNode->hasNotif = 1;
memNode->hasAlert = 0;
RestoreIRQMask(mask);
/* callback by user! */
evtArgs.extras = extras;
evtArgs.memUsed = memUsed;
OsaUlfcNotifyMemEvent(OSA_ULFC_MEF_LOW_WATER, &evtArgs);
}
}
if(memNode->handle)
{
osEventFlagsSet(memNode->handle, OSA_ULFC_BLOCKING_EVT_FLAGS);
}
}
//ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_FREE_2, P_INFO, "UlfcMem(%d): free addr(0x%x), size(%d)", extras, ptr, freeSize);
return;
}
/******************************************************************************
* @brief : OsaUlfcReallocMem
* @author: Xu.Wang
* @note :
******************************************************************************/
void OsaUlfcReallocMem(void *ptr, uint32_t wantedSize)
{
/* TBD */
}
/******************************************************************************
* @brief : OsaUlfcEnable
* @author: Xu.Wang
* @note :
******************************************************************************/
void OsaUlfcEnable(uint8_t chanNo, uint8_t isBlocking, OsaUlfcSrcTaskId_e taskId)
{
osEventFlagsId_t handle = NULL;
OsaUlfcMemNode_t *memNode = NULL;
if(!gOsaUlfcMemSuppFlag) return;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_ENABLE_1, P_WARNING, "invalid chanNo(%d) err!", chanNo);
return;
}
memNode = &gOsaUlfcMemMan.memNode[chanNo];
uint32_t mask = SaveAndSetIRQMask();
if(!memNode->isInit)
{
memset(memNode, 0, sizeof(OsaUlfcMemNode_t));
memNode->isInit = 1;
memNode->refNum = 1;
memNode->memThres = OSA_ULFC_ALIGN_UP(OSA_ULFC_MEM_USED_THRES_DFT, 4);
memNode->memThresAlert = ((memNode->memThres * OSA_ULFC_MEM_USED_THRES_ALERT_PCT_DFT) / 100);
memNode->memThresAlertPct = OSA_ULFC_MEM_USED_THRES_ALERT_PCT_DFT;
memNode->bmTaskId = (1 << taskId);
}
else
{
if(!(memNode->bmTaskId & (1 << taskId)))
{
memNode->refNum ++;
memNode->isUnset = 0; /* clr */
memNode->bmTaskId |= (1 << taskId);
}
}
handle = memNode->handle;
RestoreIRQMask(mask);
if(isBlocking && !handle)
{
handle = osEventFlagsNew(NULL);
EC_ASSERT(handle, chanNo, memNode->handle, memNode->bmTaskId);
mask = SaveAndSetIRQMask();
memNode->handle = handle;
RestoreIRQMask(mask);
}
ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_ENABLE_2, P_SIG, "UlfcMem(%d): set task(%d/0x%x) to %s mode(%d), latest ref(%d)!",
chanNo, taskId, memNode->bmTaskId,
isBlocking ? "blocking" : "nonblocking",
isBlocking, memNode->refNum);
return;
}
/******************************************************************************
* @brief : OsaUlfcDisable
* @author: Xu.Wang
* @note :
******************************************************************************/
void OsaUlfcDisable(uint8_t chanNo, OsaUlfcSrcTaskId_e taskId)
{
uint32_t opFlags = 0;
osTimerId_t ustTimer = NULL;
osEventFlagsId_t handle = NULL;
OsaUlfcMemNode_t *memNode = NULL;
OsaUlfcTimerCtx_t *timerCtx = NULL;
if(!gOsaUlfcMemSuppFlag) return;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_DISABLE_1, P_WARNING, "invalid chanNo(%d) err!", chanNo);
return;
}
memNode = &gOsaUlfcMemMan.memNode[chanNo];
timerCtx = &gOsaUlfcMemMan.timerCtx[chanNo];
EC_ASSERT(memNode->isInit, memNode, chanNo, taskId);
ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_DISABLE_2, P_SIG, "UlfcMem(%d): unset task(%d/0x%x), latest ref(%d)!",
chanNo, taskId, memNode->bmTaskId, memNode->refNum);
uint32_t mask = SaveAndSetIRQMask();
if(memNode->bmTaskId & (1 << taskId))
{
memNode->refNum --;
memNode->bmTaskId &= ~(1 << taskId);
}
if(!memNode->refNum)
{
EC_ASSERT(!memNode->bmTaskId, memNode->bmTaskId, chanNo, memNode);
if(memNode->memUsed)
{
/* unsetting is delayed! */
ustTimer = memNode->ustTimer;
if(!ustTimer)
{
opFlags |= 0x1;
memNode->isUnset = 1;
}
else
{
opFlags |= 0x2;
}
}
else
{
opFlags |= 0x4;
handle = memNode->handle;
ustTimer = memNode->ustTimer;
memset(memNode, 0, sizeof(OsaUlfcMemNode_t));
}
}
RestoreIRQMask(mask);
if(opFlags & 0x1)
{
ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_DISABLE_3, P_SIG, "UlfcMem(%d): create unset timer!", chanNo);
timerCtx->taskId = taskId;
timerCtx->chanNo = chanNo;
timerCtx->memNode = memNode;
ustTimer = osTimerNew((osTimerFunc_t)OsaUlfcUnsetTimerExpr, osTimerOnce, (void*)timerCtx, NULL);
EC_ASSERT(ustTimer && osOK == osTimerStart(ustTimer, OSA_ULFC_MEM_UNSET_TIMER_PERIOD), ustTimer, memNode, chanNo);
mask = SaveAndSetIRQMask();
memNode->ustTimer = ustTimer;
RestoreIRQMask(mask);
}
else if(opFlags & 0x2)
{
/* reset timer period! */
EC_ASSERT(osOK == osTimerStart(ustTimer, OSA_ULFC_MEM_UNSET_TIMER_PERIOD), memNode, taskId, chanNo);
}
else if(opFlags & 0x4)
{
if(handle)
{
osEventFlagsDelete(handle);
}
if(ustTimer)
{
if(osTimerIsRunning(ustTimer))
{
osTimerStop(ustTimer);
}
osTimerDelete(ustTimer);
}
}
}
/******************************************************************************
* @brief : OsaUlfcNotifyMemEvent
* @author: Xu.Wang
* @note :
******************************************************************************/
PPP_FM_RAMCODE void OsaUlfcNotifyMemEvent(OsaUlfcMemEvtFlags_e flags, OsaUlfcMemEvtArgs_t *args)
{
OsaUlfcMemNode_t *memNode = NULL;
if(args->extras >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_NOTIFY_MEM_EVT, P_WARNING, "invalid chanNo(%d) err!", args->extras);
return;
}
memNode = &gOsaUlfcMemMan.memNode[args->extras];
if(memNode->isInit)
{
ECPLAT_PRINTF(UNILOG_OSA, OSA_ULFC_EVT_NOTIF, P_SIG, "UlfcMem(%d): %s water(%d), usedSize(%d), @bmTaskId(0x%x)!",
args->extras, flags ? "high" : "low", flags, args->memUsed, memNode->bmTaskId);
#ifdef FEATURE_CCIO_ENABLE
if(memNode->bmTaskId & (1 << OSA_ULFC_STI_CCIO_RX))
{
/* for now, only low water event is the interest of ccio rx task! */
if(flags == OSA_ULFC_MEF_LOW_WATER) ccioReportUlfcMemEvent(flags, args);
}
#endif
}
}
/******************************************************************************
* @brief : OsaUlfcConfmMemEvent
* @author: Xu.Wang
* @note :
******************************************************************************/
PPP_FM_RAMCODE void OsaUlfcConfmMemEvent(uint8_t chanNo)
{
OsaUlfcMemNode_t *memNode = NULL;
if(chanNo >= OSA_ULFC_MEM_NODE_MAXNUM)
{
ECPLAT_PRINTF(UNILOG_OSA, ULFC_CONFM_MEM_EVT, P_WARNING, "invalid chanNo(%d) err!", chanNo);
return;
}
memNode = &gOsaUlfcMemMan.memNode[chanNo];
uint32_t mask = SaveAndSetIRQMask();
if(memNode->isInit)
{
memNode->hasNotif = 0;
}
RestoreIRQMask(mask);
}