diff --git a/components/power/los_pm.c b/components/power/los_pm.c index a9c1c1e7..46f5cd92 100644 --- a/components/power/los_pm.c +++ b/components/power/los_pm.c @@ -34,20 +34,23 @@ #include "los_sched.h" #include "los_timer.h" #include "los_memory.h" +#include "los_swtmr.h" #if (LOSCFG_KERNEL_PM == 1) #define OS_PM_NODE_FREE 0x80000000U #define OS_PM_LOCK_MAX 0xFFFFU +#define OS_PM_SYS_EARLY 1 +#define OS_PM_SYS_DEVICE_EARLY 2 -typedef UINT32 (*Suspend)(VOID); +typedef UINT32 (*SysSuspend)(VOID); +typedef UINT32 (*Suspend)(UINT32 mode); -#if (LOSCFG_KERNEL_PM_DEBUG == 1) typedef struct { CHAR *name; UINT32 count; + UINT32 swtmrID; LOS_DL_LIST list; } OsPmLockCB; -#endif typedef struct { LOS_SysSleepEnum pmMode; @@ -60,11 +63,12 @@ typedef struct { #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0) UINT64 enterSleepTime; #endif -#if (LOSCFG_KERNEL_PM_DEBUG == 1) LOS_DL_LIST lockList; -#endif } LosPmCB; +#define PM_EVENT_LOCK_MASK 0xF +#define PM_EVENT_LOCK_RELEASE 0x1 +STATIC EVENT_CB_S g_pmEvent; STATIC LosPmCB g_pmCB; STATIC LosPmSysctrl *g_sysctrl = NULL; STATIC UINT64 g_pmSleepTime; @@ -99,7 +103,7 @@ STATIC VOID OsPmTickTimerStart(LosPmCB *pm) return; } -STATIC VOID OsPmTickTimerStop(LosPmCB *pm) +STATIC BOOL OsPmTickTimerStop(LosPmCB *pm) { #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0) UINT64 sleepCycle; @@ -108,13 +112,13 @@ STATIC VOID OsPmTickTimerStop(LosPmCB *pm) LosPmTickTimer *tickTimer = pm->tickTimer; if ((tickTimer == NULL) || (tickTimer->tickLock == NULL)) { - return; + return FALSE; } #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0) if (tickTimer->timerStart != NULL) { if (realSleepTime == 0) { - return; + return FALSE; } sleepCycle = OS_SYS_CYCLE_TO_NS(realSleepTime, OS_SYS_CLOCK); @@ -124,12 +128,12 @@ STATIC VOID OsPmTickTimerStop(LosPmCB *pm) pm->enterSleepTime = OsGetCurrSysTimeCycle(); tickTimer->tickLock(); tickTimer->timerStart(sleepCycle); - return; + return TRUE; } #endif tickTimer->tickLock(); - return; + return TRUE; } STATIC VOID OsPmCpuResume(LosPmCB *pm) @@ -143,9 +147,9 @@ STATIC VOID OsPmCpuResume(LosPmCB *pm) } } -STATIC Suspend OsPmCpuSuspend(LosPmCB *pm) +STATIC SysSuspend OsPmCpuSuspend(LosPmCB *pm) { - Suspend sysSuspend = NULL; + SysSuspend sysSuspend = NULL; /* cpu enter low power mode */ LOS_ASSERT(pm->sysctrl != NULL); @@ -165,36 +169,94 @@ STATIC Suspend OsPmCpuSuspend(LosPmCB *pm) return sysSuspend; } -STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm) +STATIC VOID OsPmResumePrepare(LosPmCB *pm, UINT32 mode, UINT32 prepare) +{ + if ((prepare == 0) && (pm->device->resume != NULL)) { + pm->device->resume(mode); + } + + if (((prepare == 0) || (prepare == OS_PM_SYS_DEVICE_EARLY)) && (pm->sysctrl->late != NULL)) { + pm->sysctrl->late(mode); + } +} + +STATIC UINT32 OsPmSuspendPrepare(Suspend sysSuspendEarly, Suspend deviceSuspend, UINT32 mode, UINT32 *prepare) +{ + UINT32 ret; + + if (sysSuspendEarly != NULL) { + ret = sysSuspendEarly(mode); + if (ret != LOS_OK) { + *prepare = OS_PM_SYS_EARLY; + return ret; + } + } + + if (deviceSuspend != NULL) { + ret = deviceSuspend(mode); + if (ret != LOS_OK) { + *prepare = OS_PM_SYS_DEVICE_EARLY; + return ret; + } + } + + return LOS_OK; +} + +STATIC UINT32 OsPmSuspendCheck(LosPmCB *pm, Suspend *sysSuspendEarly, Suspend *deviceSuspend, LOS_SysSleepEnum *mode) { - UINT32 ret = LOS_OK; UINT32 intSave; - LOS_SysSleepEnum mode; - Suspend sysSuspend = NULL; intSave = LOS_IntLock(); pm->sysMode = pm->pmMode; - if ((pm->pmMode != LOS_SYS_NORMAL_SLEEP) && (pm->lock > 0)) { + if (pm->lock > 0) { pm->sysMode = LOS_SYS_NORMAL_SLEEP; - } - - if (pm->sysMode == LOS_SYS_NORMAL_SLEEP) { LOS_IntRestore(intSave); return LOS_NOK; } pm->isWake = FALSE; - LOS_TaskLock(); + *mode = pm->sysMode; + *sysSuspendEarly = pm->sysctrl->early; + *deviceSuspend = pm->device->suspend; + LOS_IntRestore(intSave); + return LOS_OK; +} - mode = pm->sysMode; - if (pm->device->suspend != NULL) { - ret = pm->device->suspend(mode); - if (ret != LOS_OK) { - goto DEVICE_EXIT; - } +STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm) +{ + UINT32 ret, intSave; + Suspend sysSuspendEarly, deviceSuspend; + LOS_SysSleepEnum mode; + UINT32 prepare = 0; + BOOL tickTimerStop = FALSE; + SysSuspend sysSuspend; + UINT64 currTime; + + ret = OsPmSuspendCheck(pm, &sysSuspendEarly, &deviceSuspend, &mode); + if (ret != LOS_OK) { + return ret; } - OsPmTickTimerStop(pm); + ret = OsPmSuspendPrepare(sysSuspendEarly, deviceSuspend, (UINT32)mode, &prepare); + if (ret != LOS_OK) { + intSave = LOS_IntLock(); + LOS_TaskLock(); + goto EXIT; + } + + intSave = LOS_IntLock(); + LOS_TaskLock(); + if (pm->isWake || (pm->lock > 0)) { + goto EXIT; + } + + tickTimerStop = OsPmTickTimerStop(pm); + if (!tickTimerStop) { + currTime = OsGetCurrSchedTimeCycle(); + OsSchedResetSchedResponseTime(0); + OsSchedSetNextExpireTime(currTime, OS_INVALID, OS_SCHED_MAX_RESPONSE_TIME, TRUE); + } sysSuspend = OsPmCpuSuspend(pm); LOS_IntRestore(intSave); @@ -209,22 +271,20 @@ STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm) OsPmTickTimerStart(pm); - if (pm->device->resume != NULL) { - pm->device->resume(mode); - } - -DEVICE_EXIT: +EXIT: pm->sysMode = LOS_SYS_NORMAL_SLEEP; + OsPmResumePrepare(pm, (UINT32)mode, prepare); LOS_IntRestore(intSave); LOS_TaskUnlock(); return ret; } -STATIC VOID OsPmNormalSleep(LosPmCB *pm) +STATIC VOID OsPmNormalSleep(VOID) { UINT32 intSave; - Suspend sysSuspend = NULL; + LosPmCB *pm = &g_pmCB; + SysSuspend sysSuspend = NULL; intSave = LOS_IntLock(); sysSuspend = OsPmCpuSuspend(pm); @@ -237,24 +297,6 @@ STATIC VOID OsPmNormalSleep(LosPmCB *pm) LOS_IntRestore(intSave); } -STATIC VOID OsPmEnter(VOID) -{ - UINT32 ret; - LosPmCB *pm = &g_pmCB; - - ret = OsPmSuspendSleep(pm); - if (ret != LOS_OK) { - OsPmNormalSleep(pm); - } - - return; -} - -STATIC VOID OsPmTask(VOID) -{ - OsPmEnter(); -} - STATIC UINT32 OsPmDeviceRegister(LosPmCB *pm, LosPmDevice *device) { UINT32 intSave; @@ -438,11 +480,8 @@ LOS_SysSleepEnum LOS_PmModeGet(VOID) UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode) { UINT32 intSave; - UINT32 taskID; - UINT32 ret; LosPmCB *pm = &g_pmCB; INT32 sleepMode = (INT32)mode; - TSK_INIT_PARAM_S taskInitParam = { 0 }; if ((sleepMode < 0) || (sleepMode > LOS_SYS_SHUTDOWN)) { return LOS_ERRNO_PM_INVALID_MODE; @@ -472,17 +511,6 @@ UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode) pm->pmMode = mode; LOS_IntRestore(intSave); - if ((mode == LOS_SYS_DEEP_SLEEP) || (mode == LOS_SYS_SHUTDOWN)) { - taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsPmTask; - taskInitParam.uwStackSize = LOSCFG_KERNEL_PM_TASK_STACKSIZE; - taskInitParam.pcName = "pm"; - taskInitParam.usTaskPrio = LOSCFG_KERNEL_PM_TASK_PTIORITY; - ret = LOS_TaskCreate(&taskID, &taskInitParam); - if (ret != LOS_OK) { - return ret; - } - } - return LOS_OK; } @@ -509,24 +537,17 @@ VOID LOS_PmLockInfoShow(VOID) } #endif -UINT32 LOS_PmLockRequest(const CHAR *name) +UINT32 OsPmLockRequest(const CHAR *name, UINT32 swtmrID) { UINT32 intSave; UINT32 ret = LOS_ERRNO_PM_NOT_LOCK; LosPmCB *pm = &g_pmCB; -#if (LOSCFG_KERNEL_PM_DEBUG == 1) OsPmLockCB *listNode = NULL; OsPmLockCB *lock = NULL; LOS_DL_LIST *head = &pm->lockList; LOS_DL_LIST *list = head->pstNext; - if (name == NULL) { - return LOS_ERRNO_PM_INVALID_PARAM; - } -#endif - intSave = LOS_IntLock(); -#if (LOSCFG_KERNEL_PM_DEBUG == 1) while (list != head) { listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list); if (strcmp(name, listNode->name) == 0) { @@ -545,11 +566,17 @@ UINT32 LOS_PmLockRequest(const CHAR *name) } lock->name = (CHAR *)name; lock->count = 1; + lock->swtmrID = swtmrID; LOS_ListTailInsert(head, &lock->list); } else if (lock->count < OS_PM_LOCK_MAX) { lock->count++; } -#endif + + if ((lock->swtmrID != OS_INVALID) && (lock->count > 1)) { + lock->count--; + LOS_IntRestore(intSave); + return LOS_ERRNO_PM_ALREADY_LOCK; + } if (pm->lock < OS_PM_LOCK_MAX) { pm->lock++; @@ -560,25 +587,34 @@ UINT32 LOS_PmLockRequest(const CHAR *name) return ret; } +UINT32 LOS_PmLockRequest(const CHAR *name) +{ + if (name == NULL) { + return LOS_ERRNO_PM_INVALID_PARAM; + } + + return OsPmLockRequest(name, OS_INVALID); +} + UINT32 LOS_PmLockRelease(const CHAR *name) { UINT32 intSave; UINT32 ret = LOS_ERRNO_PM_NOT_LOCK; LosPmCB *pm = &g_pmCB; -#if (LOSCFG_KERNEL_PM_DEBUG == 1) OsPmLockCB *lock = NULL; OsPmLockCB *listNode = NULL; LOS_DL_LIST *head = &pm->lockList; LOS_DL_LIST *list = head->pstNext; - VOID *lockFree = NULL; + OsPmLockCB *lockFree = NULL; + BOOL isRelease = FALSE; + UINT32 mode; if (name == NULL) { return LOS_ERRNO_PM_INVALID_PARAM; } -#endif intSave = LOS_IntLock(); -#if (LOSCFG_KERNEL_PM_DEBUG == 1) + mode = (UINT32)pm->pmMode; while (list != head) { listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list); if (strcmp(name, listNode->name) == 0) { @@ -599,25 +635,139 @@ UINT32 LOS_PmLockRelease(const CHAR *name) lockFree = lock; } } -#endif if (pm->lock > 0) { pm->lock--; + if (pm->lock == 0) { + isRelease = TRUE; + } ret = LOS_OK; } - LOS_IntRestore(intSave); -#if (LOSCFG_KERNEL_PM_DEBUG == 1) - (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree); -#endif + + if (lockFree != NULL) { + (VOID)LOS_SwtmrDelete(lockFree->swtmrID); + (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree); + } + + if (isRelease && (mode > LOS_SYS_NORMAL_SLEEP)) { + (VOID)LOS_EventWrite(&g_pmEvent, PM_EVENT_LOCK_RELEASE); + } + return ret; } +VOID OsPmFreezeTaskUnsafe(UINT32 taskID) +{ + UINT64 responseTime; + LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); + + responseTime = GET_SORTLIST_VALUE(&taskCB->sortList); + OsDeleteSortLink(&taskCB->sortList, OS_SORT_LINK_TASK); + SET_SORTLIST_VALUE(&taskCB->sortList, responseTime); + taskCB->taskStatus |= OS_TASK_FALG_FREEZE; + return; +} + +VOID OsPmUnfreezeTaskUnsafe(UINT32 taskID) +{ + LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); + UINT64 currTime, responseTime; + UINT32 remainTick; + + taskCB->taskStatus &= ~OS_TASK_FALG_FREEZE; + currTime = OsGetCurrSchedTimeCycle(); + responseTime = GET_SORTLIST_VALUE(&taskCB->sortList); + if (responseTime > currTime) { + remainTick = ((responseTime - currTime) + OS_CYCLE_PER_TICK - 1) / OS_CYCLE_PER_TICK; + OsAdd2SortLink(&taskCB->sortList, currTime, remainTick, OS_SORT_LINK_TASK); + return; + } + + SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME); + LOS_ListDelete(&taskCB->pendList); + taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME); + return; +} + +STATIC VOID OsPmSwtmrHandler(UINT32 arg) +{ + const CHAR *name = (const CHAR *)arg; + UINT32 ret = LOS_PmLockRelease(name); + if (ret != LOS_OK) { + PRINT_ERR("Pm delay lock %s release faled! : 0x%x\n", name, ret); + } +} + +UINT32 LOS_PmTimeLockRequest(const CHAR *name, UINT64 millisecond) +{ + UINT32 ticks; + UINT32 swtmrID; + UINT32 ret; + + if ((name == NULL) || !millisecond) { + return LOS_ERRNO_PM_INVALID_PARAM; + } + + ticks = (UINT32)((millisecond + OS_MS_PER_TICK - 1) / OS_MS_PER_TICK); +#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1) + ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name, + OS_SWTMR_ROUSES_ALLOW, OS_SWTMR_ALIGN_INSENSITIVE); +#else + ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name); +#endif + if (ret != LOS_OK) { + return ret; + } + + ret = OsPmLockRequest(name, swtmrID); + if (ret != LOS_OK) { + (VOID)LOS_SwtmrDelete(swtmrID); + return ret; + } + + ret = LOS_SwtmrStart(swtmrID); + if (ret != LOS_OK) { + (VOID)LOS_PmLockRelease(name); + } + + return ret; +} + +UINT32 LOS_PmReadLock(VOID) +{ + UINT32 ret = LOS_EventRead(&g_pmEvent, PM_EVENT_LOCK_MASK, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); + if (ret > PM_EVENT_LOCK_MASK) { + PRINT_ERR("%s event read failed! ERROR: 0x%x\n", ret); + } + + return LOS_OK; +} + +UINT32 LOS_PmSuspend(UINT32 wakeCount) +{ + (VOID)wakeCount; + return OsPmSuspendSleep(&g_pmCB); +} + STATIC VOID OsPmSleepTimeSet(UINT64 sleepTime) { g_pmSleepTime = sleepTime; } +BOOL OsIsPmMode(VOID) +{ + LosPmCB *pm = &g_pmCB; + + UINT32 intSave = LOS_IntLock(); + if ((pm->sysMode != LOS_SYS_NORMAL_SLEEP) && (pm->lock == 0)) { + LOS_IntRestore(intSave); + return TRUE; + } + LOS_IntRestore(intSave); + return FALSE; +} + UINT32 OsPmInit(VOID) { UINT32 ret; @@ -626,16 +776,15 @@ UINT32 OsPmInit(VOID) (VOID)memset_s(pm, sizeof(LosPmCB), 0, sizeof(LosPmCB)); pm->pmMode = LOS_SYS_NORMAL_SLEEP; -#if (LOSCFG_KERNEL_PM_DEBUG == 1) LOS_ListInit(&pm->lockList); -#endif + (VOID)LOS_EventInit(&g_pmEvent); ret = OsSchedRealSleepTimeSet(OsPmSleepTimeSet); if (ret != LOS_OK) { return ret; } - ret = OsPmEnterHandlerSet(OsPmEnter); + ret = OsPmEnterHandlerSet(OsPmNormalSleep); if (ret != LOS_OK) { return ret; } diff --git a/components/power/los_pm.h b/components/power/los_pm.h index 5564de6d..a3e7e3f9 100644 --- a/components/power/los_pm.h +++ b/components/power/los_pm.h @@ -118,6 +118,15 @@ */ #define LOS_ERRNO_PM_DEVICE_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x09) +/** + * @ingroup los_pm + * Pm error code: The delay lock has already been activated. + * + * Value: 0x0200200a + * + */ +#define LOS_ERRNO_PM_ALREADY_LOCK LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x0a) + typedef enum { LOS_SYS_NORMAL_SLEEP = 0, LOS_SYS_LIGHT_SLEEP, @@ -132,8 +141,8 @@ typedef enum { } LOS_PmNodeType; typedef struct { - UINT32 (*suspend)(UINT32 mode); - VOID (*resume)(UINT32 mode); + UINT32 (*suspend)(UINT32 mode); /* The device enters low power consumption, Unlocked task scheduling. */ + VOID (*resume)(UINT32 mode); /* The device exits from low power consumption, Unlocked task scheduling. */ } LosPmDevice; typedef struct { @@ -146,13 +155,47 @@ typedef struct { } LosPmTickTimer; typedef struct { + /* Preparations before the CPU enters low power consumption. + * All modes except normal mode are invoked. + * Unlocked task scheduling. + */ + UINT32 (*early)(UINT32 mode); + /* The system performs low-power recovery. + * All modes except normal mode are invoked. + * Unlocked task scheduling. + */ + VOID (*late)(UINT32 mode); + /* The system enters the Normal sleep mode. + * In normal mode, the value cannot be NULL. + */ UINT32 (*normalSuspend)(VOID); + /* The system recovers from normal sleep. + * The value can be NULL. + */ VOID (*normalResume)(VOID); + /* The system enters the light sleep mode. + * In light sleep mode, the value cannot be NULL. + */ UINT32 (*lightSuspend)(VOID); + /* The system recovers from light sleep. + * The value can be NULL. + */ VOID (*lightResume)(VOID); + /* The system enters the deep sleep mode. + * In deep sleep mode, the value cannot be NULL. + */ UINT32 (*deepSuspend)(VOID); + /* The system recovers from deep sleep. + * The value can be NULL. + */ VOID (*deepResume)(VOID); + /* The system enters the shutdown mode. + * In shutdown mode, the value cannot be NULL. + */ UINT32 (*shutdownSuspend)(VOID); + /* The system recovers from shutdown. + * In shutdown mode, the value cannot be NULL. + */ VOID (*shutdownResume)(VOID); } LosPmSysctrl; @@ -174,6 +217,60 @@ typedef struct { */ UINT32 OsPmInit(VOID); +/** + * @ingroup los_pm + * @brief Whether the low power consumption condition is met. + * + * @par Description: + * This API is used to check whether low power consumption is met. + * + * @attention None. + * + * @param None. + * + * @retval TRUE or FALSE. + * @par Dependency: + * + * @see + */ +BOOL OsIsPmMode(VOID); + +/** + * @ingroup los_pm + * @brief Freeze delay tasks, internal interfaces between modules. + * + * @par Description: + * This API is used to freeze delay tasks. + * + * @attention None. + * + * @param taskID [IN] task ID. + * + * @retval None. + * @par Dependency: + * + * @see OsPmUnfreezeTaskUnsafe + */ +VOID OsPmFreezeTaskUnsafe(UINT32 taskID); + +/** + * @ingroup los_pm + * @brief Unfreeze delayed tasks, internal interface between modules. + * + * @par Description: + * This API is used to unfreeze delayed tasks. + * + * @attention None. + * + * @param taskID [IN] task ID. + * + * @retval None. + * @par Dependency: + * + * @see OsPmFreezeTaskUnsafe + */ +VOID OsPmUnfreezeTaskUnsafe(UINT32 taskID); + /** * @ingroup los_pm * @brief Register a power management node. @@ -285,6 +382,27 @@ UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode); */ UINT32 LOS_PmLockRequest(const CHAR *name); +/** + * @ingroup los_pm + * @brief Request to obtain the lock in current mode, so that the system will not enter + * this mode when it enters the idle task next time. After the specified interval, the + * lock is automatically released. + * + * @par Description: + * This API is used to obtain the delay lock in current mode. + * + * @attention None. + * + * @param name [IN] Who requests the lock. + * @param millisecond [IN] Specifies the time to automatically release the lock. + * + * @retval error code, LOS_OK means success. + * @par Dependency: + * + * @see LOS_PmLockRelease + */ +UINT32 LOS_PmTimeLockRequest(const CHAR *name, UINT64 millisecond); + /** * @ingroup los_pm * @brief Release the lock in current mode so that the next time the system enters @@ -304,6 +422,42 @@ UINT32 LOS_PmLockRequest(const CHAR *name); */ UINT32 LOS_PmLockRelease(const CHAR *name); +/** + * @ingroup los_pm + * @brief Gets the current PM lock status. + * + * @par Description: + * This API is used to Get the current PM lock status. + * + * @attention None. + * + * @param NA. + * + * @retval Number of awakening sources of the device. + * @par Dependency: + * + * @see + */ +UINT32 LOS_PmReadLock(VOID); + +/** + * @ingroup los_pm + * @brief The system enters the low-power flow. + * + * @par Description: + * This API is used to enter the system into a low-power process. + * + * @attention None. + * + * @param wakeCount [IN] Number of wake sources. + * + * @retval error code, LOS_OK means success. + * @par Dependency: + * + * @see + */ +UINT32 LOS_PmSuspend(UINT32 wakeCount); + #if (LOSCFG_KERNEL_PM_DEBUG == 1) /** * @ingroup los_pm diff --git a/kernel/include/los_sched.h b/kernel/include/los_sched.h index df26da61..87b8189b 100644 --- a/kernel/include/los_sched.h +++ b/kernel/include/los_sched.h @@ -61,6 +61,8 @@ VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask); UINT32 OsSchedSwtmrScanRegister(SchedScan func); +VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, BOOL timeUpdate); + VOID OsSchedUpdateExpireTime(UINT64 startTime, BOOL timeUpdate); VOID OsSchedTaskDeQueue(LosTaskCB *taskCB); diff --git a/kernel/include/los_task.h b/kernel/include/los_task.h index 1df6c111..0e587535 100644 --- a/kernel/include/los_task.h +++ b/kernel/include/los_task.h @@ -1175,6 +1175,14 @@ extern VOID LOS_UDelay(UINT64 microseconds); */ #define OS_TASK_STATUS_PEND_TIME 0x0080 +/** + * @ingroup los_task + * Flag that indicates the task or task control block status. + * + * The delayed operation of this task is frozen. + */ +#define OS_TASK_FALG_FREEZE 0x4000 + /** * @ingroup los_task * Flag that indicates the task is in userspace. diff --git a/kernel/src/los_sched.c b/kernel/src/los_sched.c index a0b2c221..b0d72d6d 100644 --- a/kernel/src/los_sched.c +++ b/kernel/src/los_sched.c @@ -179,7 +179,7 @@ STATIC INLINE VOID OsSchedTickReload(UINT64 nextResponseTime, UINT32 responseID, HalSysTickReload(nextResponseTime); } -STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, BOOL timeUpdate) +VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, BOOL timeUpdate) { UINT64 nextExpireTime; UINT64 nextResponseTime = 0; @@ -415,7 +415,7 @@ BOOL OsSchedModifyTaskSchedParam(LosTaskCB *taskCB, UINT16 priority) } taskCB->priority = priority; - OsHookCall(LOS_HOOK_TYPE_TASK_PRIMODIFY, taskCB, taskCB->priority); + OsHookCall(LOS_HOOK_TYPE_TASK_PRIMODIFY, taskCB, taskCB->priority); if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) { return TRUE; } diff --git a/kernel/src/los_task.c b/kernel/src/los_task.c index a4f5afbc..33437640 100644 --- a/kernel/src/los_task.c +++ b/kernel/src/los_task.c @@ -44,6 +44,9 @@ #if (LOSCFG_BASE_CORE_CPUP == 1) #include "los_cpup.h" #endif +#if (LOSCFG_KERNEL_PM == 1) +#include "los_pm.h" +#endif /** * @ingroup los_task @@ -403,7 +406,6 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID) taskInitParam.pcName = "IdleCore000"; taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST; retVal = LOS_TaskCreateOnly(&g_idleTaskID, &taskInitParam); - if (retVal != LOS_OK) { return retVal; } @@ -803,6 +805,12 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID) OS_GOTO_ERREND(); } +#if (LOSCFG_KERNEL_PM == 1) + if (tempStatus & OS_TASK_FALG_FREEZE) { + OsPmUnfreezeTaskUnsafe(taskID); + } +#endif + taskCB->taskStatus &= (~OS_TASK_STATUS_SUSPEND); if (!(taskCB->taskStatus & OS_CHECK_TASK_BLOCK)) { OsSchedTaskEnQueue(taskCB); @@ -862,6 +870,12 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID) OsSchedTaskDeQueue(taskCB); } +#if (LOSCFG_KERNEL_PM == 1) + if ((tempStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) && OsIsPmMode()) { + OsPmFreezeTaskUnsafe(taskID); + } +#endif + taskCB->taskStatus |= OS_TASK_STATUS_SUSPEND; OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB); if (taskID == g_losTask.runTask->taskID) { diff --git a/testsuits/sample/kernel/power/BUILD.gn b/testsuits/sample/kernel/power/BUILD.gn index 1f8177cd..9fefaa7d 100644 --- a/testsuits/sample/kernel/power/BUILD.gn +++ b/testsuits/sample/kernel/power/BUILD.gn @@ -31,6 +31,7 @@ static_library("test_pm") { "It_los_pm.c", "It_los_pm_001.c", "It_los_pm_002.c", + "It_los_pm_003.c", ] include_dirs = [ "//kernel/liteos_m/components/power" ] diff --git a/testsuits/sample/kernel/power/It_los_pm.c b/testsuits/sample/kernel/power/It_los_pm.c index fa61be39..dd731e72 100644 --- a/testsuits/sample/kernel/power/It_los_pm.c +++ b/testsuits/sample/kernel/power/It_los_pm.c @@ -31,9 +31,10 @@ #include "osTest.h" #include "It_los_pm.h" -VOID ItSuiteLosPm() +VOID ItSuiteLosPm(VOID) { ItLosPm001(); ItLosPm002(); + ItLosPm003(); } diff --git a/testsuits/sample/kernel/power/It_los_pm.h b/testsuits/sample/kernel/power/It_los_pm.h index 82809c35..6190979c 100644 --- a/testsuits/sample/kernel/power/It_los_pm.h +++ b/testsuits/sample/kernel/power/It_los_pm.h @@ -55,6 +55,7 @@ extern "C" { extern VOID ItLosPm001(VOID); extern VOID ItLosPm002(VOID); +extern VOID ItLosPm003(VOID); #ifdef __cplusplus #if __cplusplus diff --git a/testsuits/sample/kernel/power/It_los_pm_001.c b/testsuits/sample/kernel/power/It_los_pm_001.c index ac3f8571..81ff4667 100644 --- a/testsuits/sample/kernel/power/It_los_pm_001.c +++ b/testsuits/sample/kernel/power/It_los_pm_001.c @@ -50,16 +50,21 @@ static VOID SysResume(VOID) { } -static UINT32 SysSuspend(VOID) -{ - return HalEnterSleep(); -} - static LosPmSysctrl g_sysctrl = { .normalSuspend = NULL, .normalResume = SysResume, }; +static VOID TimerStart(UINT64 timer) +{ + +} + +static UINT64 GetTimerCycle(VOID) +{ + return 0; +} + static VOID TickLock(VOID) { return; @@ -128,7 +133,7 @@ static UINT32 TestCase(VOID) g_tickTimer.tickLock = TickLock; g_tickTimer.tickUnlock = TickUnlock; - g_tickTimer.timerStart = TickLock; + g_tickTimer.timerStart = TimerStart; ret = LOS_PmRegister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer); ICUNIT_ASSERT_EQUAL(ret, LOS_ERRNO_PM_INVALID_PARAM, ret); @@ -136,7 +141,7 @@ static UINT32 TestCase(VOID) ret = LOS_PmRegister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer); ICUNIT_ASSERT_EQUAL(ret, LOS_ERRNO_PM_INVALID_PARAM, ret); - g_tickTimer.timerCycleGet = TickLock; + g_tickTimer.timerCycleGet = GetTimerCycle; ret = LOS_PmRegister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer); ICUNIT_ASSERT_EQUAL(ret, LOS_ERRNO_PM_INVALID_PARAM, ret); @@ -159,4 +164,3 @@ VOID ItLosPm001(VOID) // IT_Layer_ModuleORFeature_No { TEST_ADD_CASE("ItLosPm001", TestCase, TEST_LOS, TEST_TASK, TEST_LEVEL0, TEST_FUNCTION); } - diff --git a/testsuits/sample/kernel/power/It_los_pm_002.c b/testsuits/sample/kernel/power/It_los_pm_002.c index 762e8edd..a64964f5 100644 --- a/testsuits/sample/kernel/power/It_los_pm_002.c +++ b/testsuits/sample/kernel/power/It_los_pm_002.c @@ -32,9 +32,14 @@ #include "It_los_pm.h" #include "los_timer.h" +#define myprintf // printf +#define TEST_LOOP 5 +static EVENT_CB_S g_pmTestEvent; +static UINT32 g_taskID1, g_taskID2; static UINT32 g_deviceCount = 0; static UINT32 g_sysCount = 0; -static UINT32 g_sysTickTimerCount = 0; +static volatile UINT32 g_pmTestCount = 0; + static UINT32 DeviceSuspend(UINT32 mode) { g_deviceCount++; @@ -53,26 +58,6 @@ static LosPmDevice g_device = { .resume = DeviceResume, }; -static VOID TickLock(VOID) -{ - g_testCount++; - g_sysTickTimerCount++; -} - -static VOID TickUnlock(VOID) -{ - g_sysTickTimerCount--; -} - -static LosPmTickTimer g_tickTimer = { - .tickLock = TickLock, - .tickUnlock = TickUnlock, - .timerStart = NULL, - .timerStop = NULL, - .timerCycleGet = NULL, - .freq = 0, -}; - static VOID SysResume(VOID) { if (g_sysCount != (UINT32)-1) { @@ -85,29 +70,154 @@ static UINT32 SysSuspend(VOID) g_testCount++; g_sysCount++; - if ((g_sysTickTimerCount != 1) || (g_deviceCount != 1) || (g_sysCount != 1)) { + if ((g_deviceCount != 1) || (g_sysCount != 1)) { /* 1: sys count */ g_sysCount = (UINT32)-1; } + UINT64 timeout = LOS_SchedTickTimeoutNsGet(); + printf("pm timeout : %u ns -> %u ticks\n", (UINT32)timeout, (UINT32)(timeout / OS_NS_PER_TICK)); return HalEnterSleep(); } +static UINT32 SystemPmEarly(UINT32 mode) +{ + UINT32 ret; + + ret = LOS_TaskSuspend(g_taskID2); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + ret = LOS_TaskSuspend(g_taskID1); + if (ret != LOS_OK) { + (VOID)LOS_TaskResume(g_taskID2); + } + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + return LOS_OK; +} + +static VOID SystemPmLate(UINT32 mode) +{ + UINT32 ret; + LosTaskCB *taskCB = NULL; + + ICUNIT_ASSERT_EQUAL_VOID(mode, LOS_SYS_LIGHT_SLEEP, mode); + + ret = LOS_TaskResume(g_taskID2); + ICUNIT_ASSERT_EQUAL_VOID(ret, LOS_OK, ret); + + ret = LOS_TaskResume(g_taskID1); + ICUNIT_ASSERT_EQUAL_VOID(ret, LOS_OK, ret); +} + static LosPmSysctrl g_sysctrl = { + .early = SystemPmEarly, + .late = SystemPmLate, .normalSuspend = HalEnterSleep, .normalResume = NULL, .lightSuspend = SysSuspend, .lightResume = SysResume, }; +#define TEST_FLAGS 100 +static VOID PmTestTask(VOID) +{ + UINT32 ret; + UINT32 wakeCount; + + while (1) { + wakeCount = LOS_PmReadLock(); + + ret = LOS_PmSuspend(wakeCount); + ICUNIT_GOTO_EQUAL(ret, LOS_OK, ret, EXIT); + ICUNIT_GOTO_NOT_EQUAL(g_testCount, 0, g_sysCount, EXIT); + ICUNIT_GOTO_EQUAL(g_sysCount, 0, g_sysCount, EXIT); + + g_pmTestCount++; + if (g_pmTestCount > TEST_LOOP) { + break; + } + printf("PmTestTask loop: %u\n", g_pmTestCount); + } + +EXIT: + g_pmTestCount = TEST_FLAGS; + (VOID)LOS_EventWrite(&g_pmTestEvent, 0x1); /* 0x1: test exit evnet */ + return; +} + +#define TEST_TASK1_LOOP 10 +static volatile UINT32 g_testSample1Count, g_testSample2Count; +static void TaskSampleEntry2(void) +{ + UINT32 g_testSample2Count = TEST_FLAGS; + + while (1) { + if (g_testSample2Count == TEST_FLAGS) { + g_testSample2Count = 0; + LOS_PmLockRequest("TaskSampleEntry2"); + myprintf("%s request pm lock\n", __FUNCTION__); + } + + myprintf("TaskSampleEntry2 running...count: %u\n\r", g_testSample2Count); + LOS_TaskDelay(20); /* sleep 20 ticks */ + + if (g_testSample2Count <= TEST_TASK1_LOOP) { /* */ + g_testSample2Count++; + } + if (g_testSample2Count == TEST_TASK1_LOOP) { + LOS_PmLockRelease("TaskSampleEntry2"); + myprintf("%s release pm lock\n", __FUNCTION__); + } + + if (g_pmTestCount > TEST_LOOP) { + break; + } + } + + LOS_PmLockRelease("TaskSampleEntry2"); + myprintf("TaskSampleEntry2 exit\n"); +} + +static void TaskSampleEntry1(void) +{ + UINT32 g_testSample1Count = 0; + + while (1) { + if (g_testSample1Count == 0) { + LOS_PmLockRequest("TaskSampleEntry1"); + myprintf("%s request pm lock\n", __FUNCTION__); + } + + myprintf("TaskSampleEntry1 running...%u\n\r", g_testSample1Count); + LOS_TaskDelay(50); /* sleep 50 ticks */ + + g_testSample1Count++; + if (g_testSample1Count == TEST_TASK1_LOOP) { + LOS_PmLockRelease("TaskSampleEntry1"); + myprintf("%s release pm lock\n", __FUNCTION__); + } else if (g_testSample1Count == (TEST_TASK1_LOOP + 1)) { /* 1: incremental */ + g_testSample1Count = 0; + g_testSample2Count = TEST_FLAGS; + } + + if (g_pmTestCount > TEST_LOOP) { + break; + } + } + + LOS_PmLockRelease("TaskSampleEntry1"); + myprintf("TaskSampleEntry1 exit\n"); +} + static UINT32 TestCase(VOID) { UINT32 ret; + TSK_INIT_PARAM_S task1 = { 0 }; g_sysCount = 0; g_deviceCount = 0; - g_sysTickTimerCount = 0; g_testCount = 0; - ret = LOS_PmRegister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer); + ret = LOS_EventInit(&g_pmTestEvent); ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); ret = LOS_PmRegister(LOS_PM_TYPE_DEVICE, &g_device); @@ -119,34 +229,42 @@ static UINT32 TestCase(VOID) ret = LOS_PmModeSet(LOS_SYS_LIGHT_SLEEP); ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); - LOS_PmLockRequest("testlock"); - LOS_TaskDelay(100); /* delay 100 ticks */ - LOS_PmLockRelease("testlock"); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)PmTestTask; + task1.uwStackSize = 0x2000; /* 0x2000 pm task stack size */ + task1.pcName = "pmTask"; + task1.usTaskPrio = 5; /* 5: pm task prio */ + ret = LOS_TaskCreate(&g_testTaskID01, &task1); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); - ICUNIT_GOTO_EQUAL(g_testCount, 0, g_testCount, EXIT); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry1; + task1.uwStackSize = 0x1000; /* 0x1000 task stack size */ + task1.pcName = "TaskSampleEntry1"; + task1.usTaskPrio = 10; /* 10: task prio */ + ret = LOS_TaskCreate(&g_taskID1, &task1); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); - LOS_TaskDelay(100); /* delay 100 ticks */ + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry2; + task1.uwStackSize = 0x1000; /* 0x1000 task stack size */ + task1.pcName = "TaskSampleEntry2"; + task1.usTaskPrio = 12; /* 12: task prio */ + ret = LOS_TaskCreate(&g_taskID2, &task1); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); - ICUNIT_GOTO_NOT_EQUAL(g_testCount, 0, g_sysCount, EXIT); - ICUNIT_GOTO_EQUAL(g_sysCount, 0, g_sysCount, EXIT); + (VOID)LOS_EventRead(&g_pmTestEvent, 0xff, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); ret = LOS_PmUnregister(LOS_PM_TYPE_DEVICE, &g_device); ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); - ret = LOS_PmUnregister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer); + ret = LOS_PmModeSet(LOS_SYS_NORMAL_SLEEP); ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + (VOID)LOS_TaskDelete(g_taskID1); + (VOID)LOS_TaskDelete(g_taskID2); + (VOID)LOS_TaskDelete(g_testTaskID01); return LOS_OK; - -EXIT: - LOS_PmUnregister(LOS_PM_TYPE_DEVICE, &g_device); - - LOS_PmUnregister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer); - return LOS_NOK; } VOID ItLosPm002(VOID) // IT_Layer_ModuleORFeature_No { TEST_ADD_CASE("ItLosPm002", TestCase, TEST_LOS, TEST_TASK, TEST_LEVEL0, TEST_FUNCTION); } - diff --git a/testsuits/sample/kernel/power/It_los_pm_003.c b/testsuits/sample/kernel/power/It_los_pm_003.c new file mode 100644 index 00000000..55092096 --- /dev/null +++ b/testsuits/sample/kernel/power/It_los_pm_003.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "osTest.h" +#include "It_los_pm.h" +#include "los_timer.h" + +#define TEST_LOOP 5 +static EVENT_CB_S g_pmTestEvent; +static UINT32 g_taskID1, g_taskID2; +static UINT32 g_deviceCount = 0; +static UINT32 g_sysCount = 0; +static volatile UINT32 g_pmTestCount = 0; +static UINT32 g_pmTimeLock = 0; + +static UINT32 DeviceSuspend(UINT32 mode) +{ + g_deviceCount++; + g_testCount++; + return LOS_OK; +} + +static VOID DeviceResume(UINT32 mode) +{ + g_deviceCount--; + return; +} + +static LosPmDevice g_device = { + .suspend = DeviceSuspend, + .resume = DeviceResume, +}; + +static VOID SysResume(VOID) +{ + if (g_sysCount != (UINT32)-1) { + g_sysCount--; + } +} + +static UINT32 SysSuspend(VOID) +{ + g_testCount++; + g_sysCount++; + + if ((g_deviceCount != 1) || (g_sysCount != 1)) { /* 2: device count 1: sys count */ + g_sysCount = (UINT32)-1; + } + + UINT64 timeout = LOS_SchedTickTimeoutNsGet(); + printf("pm timeout : %u ns -> %u ticks\n", (UINT32)timeout, (UINT32)(timeout / OS_NS_PER_TICK)); + return HalEnterSleep(); +} + +static UINT32 SystemPmEarly(UINT32 mode) +{ + UINT32 ret; + + ICUNIT_ASSERT_EQUAL(mode, LOS_SYS_LIGHT_SLEEP, mode); + + ret = LOS_TaskSuspend(g_taskID2); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + ret = LOS_TaskSuspend(g_taskID1); + if (ret != LOS_OK) { + (VOID)LOS_TaskResume(g_taskID2); + } + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + return LOS_OK; +} + +static VOID SystemPmLate(UINT32 mode) +{ + UINT32 ret; + + ICUNIT_ASSERT_EQUAL_VOID(mode, LOS_SYS_LIGHT_SLEEP, mode); + + ret = LOS_TaskResume(g_taskID2); + ICUNIT_ASSERT_EQUAL_VOID(ret, LOS_OK, ret); + + ret = LOS_TaskResume(g_taskID1); + ICUNIT_ASSERT_EQUAL_VOID(ret, LOS_OK, ret); +} + +static LosPmSysctrl g_sysctrl = { + .early = SystemPmEarly, + .late = SystemPmLate, + .normalSuspend = HalEnterSleep, + .normalResume = NULL, + .lightSuspend = SysSuspend, + .lightResume = SysResume, +}; + +#define TEST_FLAGS 100 +static VOID PmTestTask(VOID) +{ + UINT32 ret; + UINT32 wakeCount; + + while (1) { + wakeCount = LOS_PmReadLock(); + + ret = LOS_PmSuspend(wakeCount); + ICUNIT_GOTO_EQUAL(ret, LOS_OK, ret, EXIT); + ICUNIT_GOTO_NOT_EQUAL(g_testCount, 0, g_sysCount, EXIT); + ICUNIT_GOTO_EQUAL(g_sysCount, 0, g_sysCount, EXIT); + + g_pmTimeLock = 0; + g_pmTestCount++; + if (g_pmTestCount > TEST_LOOP) { + break; + } + printf("PmTestTask loop: %u\n", g_pmTestCount); + } + +EXIT: + g_pmTestCount = TEST_FLAGS; + (VOID)LOS_EventWrite(&g_pmTestEvent, 0x1); /* 0x1: test exit evnet */ + return; +} + +static void TaskSampleEntry2(void) +{ + while (1) { + LOS_TaskDelay(20); /* sleep 20 ticks */ + if (g_pmTestCount > TEST_LOOP) { + break; + } + } +} + +static void TaskSampleEntry1(void) +{ + UINT32 ret; + + while (1) { + if (g_pmTimeLock == 0) { + g_pmTimeLock = TEST_FLAGS; + ret = LOS_PmTimeLockRequest("TaskSampleEntry1", 1000); /* delay 1000 ms */ + ICUNIT_ASSERT_EQUAL_VOID(ret, LOS_OK, ret); + + ret = LOS_PmTimeLockRequest("TaskSampleEntry1", 1000); /* delay 1000 ms */ + ICUNIT_ASSERT_EQUAL_VOID(ret, LOS_ERRNO_PM_ALREADY_LOCK, ret); + } + + LOS_TaskDelay(50); /* sleep 50 ticks */ + + if (g_pmTestCount > TEST_LOOP) { + break; + } + } + + return; +} + +static UINT32 TestCase(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1 = { 0 }; + g_sysCount = 0; + g_deviceCount = 0; + g_testCount = 0; + + ret = LOS_EventInit(&g_pmTestEvent); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + ret = LOS_PmRegister(LOS_PM_TYPE_DEVICE, &g_device); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + ret = LOS_PmRegister(LOS_PM_TYPE_SYSCTRL, &g_sysctrl); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + ret = LOS_PmModeSet(LOS_SYS_LIGHT_SLEEP); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)PmTestTask; + task1.uwStackSize = 0x2000; /* 0x2000 pm task stack size */ + task1.pcName = "pmTask"; + task1.usTaskPrio = 5; /* 5: pm task prio */ + ret = LOS_TaskCreate(&g_testTaskID01, &task1); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry1; + task1.uwStackSize = 0x1000; /* 0x1000 task stack size */ + task1.pcName = "TaskSampleEntry1"; + task1.usTaskPrio = 10; /* 10: task prio */ + ret = LOS_TaskCreate(&g_taskID1, &task1); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry2; + task1.uwStackSize = 0x1000; /* 0x1000 task stack size */ + task1.pcName = "TaskSampleEntry2"; + task1.usTaskPrio = 12; /* 12: task prio */ + ret = LOS_TaskCreate(&g_taskID2, &task1); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + (VOID)LOS_EventRead(&g_pmTestEvent, 0xff, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); + + ret = LOS_PmUnregister(LOS_PM_TYPE_DEVICE, &g_device); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + ret = LOS_PmModeSet(LOS_SYS_NORMAL_SLEEP); + ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret); + + (VOID)LOS_TaskDelete(g_taskID1); + (VOID)LOS_TaskDelete(g_taskID2); + (VOID)LOS_TaskDelete(g_testTaskID01); + return LOS_OK; +} + +VOID ItLosPm003(VOID) // IT_Layer_ModuleORFeature_No +{ + TEST_ADD_CASE("ItLosPm003", TestCase, TEST_LOS, TEST_TASK, TEST_LEVEL0, TEST_FUNCTION); +}