feat: 低功耗支持冻结线程等需求
1.支持低功耗时冻结线程 2.支持延时锁 3.低功耗与idle分离 4.支持对接电源管组件的低功耗接口 LOS_PmReadLock --- 常阻塞,低功耗线程阻塞于该接口,当系统无任何模块持锁时会唤醒低功耗线程, 触发低功耗流程 LOS_PmSuspend --- 进入低功耗流程 Close #I49FJF Signed-off-by: zhushengle <zhushengle@huawei.com> Change-Id: I009255cfa1852b109dd8bfaf9c779e976660d621
This commit is contained in:
parent
c77c178ec1
commit
9b5739ab11
|
@ -34,20 +34,23 @@
|
||||||
#include "los_sched.h"
|
#include "los_sched.h"
|
||||||
#include "los_timer.h"
|
#include "los_timer.h"
|
||||||
#include "los_memory.h"
|
#include "los_memory.h"
|
||||||
|
#include "los_swtmr.h"
|
||||||
|
|
||||||
#if (LOSCFG_KERNEL_PM == 1)
|
#if (LOSCFG_KERNEL_PM == 1)
|
||||||
#define OS_PM_NODE_FREE 0x80000000U
|
#define OS_PM_NODE_FREE 0x80000000U
|
||||||
#define OS_PM_LOCK_MAX 0xFFFFU
|
#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 {
|
typedef struct {
|
||||||
CHAR *name;
|
CHAR *name;
|
||||||
UINT32 count;
|
UINT32 count;
|
||||||
|
UINT32 swtmrID;
|
||||||
LOS_DL_LIST list;
|
LOS_DL_LIST list;
|
||||||
} OsPmLockCB;
|
} OsPmLockCB;
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LOS_SysSleepEnum pmMode;
|
LOS_SysSleepEnum pmMode;
|
||||||
|
@ -60,11 +63,12 @@ typedef struct {
|
||||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||||
UINT64 enterSleepTime;
|
UINT64 enterSleepTime;
|
||||||
#endif
|
#endif
|
||||||
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
|
||||||
LOS_DL_LIST lockList;
|
LOS_DL_LIST lockList;
|
||||||
#endif
|
|
||||||
} LosPmCB;
|
} LosPmCB;
|
||||||
|
|
||||||
|
#define PM_EVENT_LOCK_MASK 0xF
|
||||||
|
#define PM_EVENT_LOCK_RELEASE 0x1
|
||||||
|
STATIC EVENT_CB_S g_pmEvent;
|
||||||
STATIC LosPmCB g_pmCB;
|
STATIC LosPmCB g_pmCB;
|
||||||
STATIC LosPmSysctrl *g_sysctrl = NULL;
|
STATIC LosPmSysctrl *g_sysctrl = NULL;
|
||||||
STATIC UINT64 g_pmSleepTime;
|
STATIC UINT64 g_pmSleepTime;
|
||||||
|
@ -99,7 +103,7 @@ STATIC VOID OsPmTickTimerStart(LosPmCB *pm)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC VOID OsPmTickTimerStop(LosPmCB *pm)
|
STATIC BOOL OsPmTickTimerStop(LosPmCB *pm)
|
||||||
{
|
{
|
||||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||||
UINT64 sleepCycle;
|
UINT64 sleepCycle;
|
||||||
|
@ -108,13 +112,13 @@ STATIC VOID OsPmTickTimerStop(LosPmCB *pm)
|
||||||
LosPmTickTimer *tickTimer = pm->tickTimer;
|
LosPmTickTimer *tickTimer = pm->tickTimer;
|
||||||
|
|
||||||
if ((tickTimer == NULL) || (tickTimer->tickLock == NULL)) {
|
if ((tickTimer == NULL) || (tickTimer->tickLock == NULL)) {
|
||||||
return;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||||
if (tickTimer->timerStart != NULL) {
|
if (tickTimer->timerStart != NULL) {
|
||||||
if (realSleepTime == 0) {
|
if (realSleepTime == 0) {
|
||||||
return;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sleepCycle = OS_SYS_CYCLE_TO_NS(realSleepTime, OS_SYS_CLOCK);
|
sleepCycle = OS_SYS_CYCLE_TO_NS(realSleepTime, OS_SYS_CLOCK);
|
||||||
|
@ -124,12 +128,12 @@ STATIC VOID OsPmTickTimerStop(LosPmCB *pm)
|
||||||
pm->enterSleepTime = OsGetCurrSysTimeCycle();
|
pm->enterSleepTime = OsGetCurrSysTimeCycle();
|
||||||
tickTimer->tickLock();
|
tickTimer->tickLock();
|
||||||
tickTimer->timerStart(sleepCycle);
|
tickTimer->timerStart(sleepCycle);
|
||||||
return;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tickTimer->tickLock();
|
tickTimer->tickLock();
|
||||||
return;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC VOID OsPmCpuResume(LosPmCB *pm)
|
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 */
|
/* cpu enter low power mode */
|
||||||
LOS_ASSERT(pm->sysctrl != NULL);
|
LOS_ASSERT(pm->sysctrl != NULL);
|
||||||
|
@ -165,36 +169,94 @@ STATIC Suspend OsPmCpuSuspend(LosPmCB *pm)
|
||||||
return sysSuspend;
|
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;
|
UINT32 intSave;
|
||||||
LOS_SysSleepEnum mode;
|
|
||||||
Suspend sysSuspend = NULL;
|
|
||||||
|
|
||||||
intSave = LOS_IntLock();
|
intSave = LOS_IntLock();
|
||||||
pm->sysMode = pm->pmMode;
|
pm->sysMode = pm->pmMode;
|
||||||
if ((pm->pmMode != LOS_SYS_NORMAL_SLEEP) && (pm->lock > 0)) {
|
if (pm->lock > 0) {
|
||||||
pm->sysMode = LOS_SYS_NORMAL_SLEEP;
|
pm->sysMode = LOS_SYS_NORMAL_SLEEP;
|
||||||
}
|
|
||||||
|
|
||||||
if (pm->sysMode == LOS_SYS_NORMAL_SLEEP) {
|
|
||||||
LOS_IntRestore(intSave);
|
LOS_IntRestore(intSave);
|
||||||
return LOS_NOK;
|
return LOS_NOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm->isWake = FALSE;
|
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;
|
STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm)
|
||||||
if (pm->device->suspend != NULL) {
|
{
|
||||||
ret = pm->device->suspend(mode);
|
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) {
|
if (ret != LOS_OK) {
|
||||||
goto DEVICE_EXIT;
|
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);
|
sysSuspend = OsPmCpuSuspend(pm);
|
||||||
LOS_IntRestore(intSave);
|
LOS_IntRestore(intSave);
|
||||||
|
@ -209,22 +271,20 @@ STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm)
|
||||||
|
|
||||||
OsPmTickTimerStart(pm);
|
OsPmTickTimerStart(pm);
|
||||||
|
|
||||||
if (pm->device->resume != NULL) {
|
EXIT:
|
||||||
pm->device->resume(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEVICE_EXIT:
|
|
||||||
pm->sysMode = LOS_SYS_NORMAL_SLEEP;
|
pm->sysMode = LOS_SYS_NORMAL_SLEEP;
|
||||||
|
OsPmResumePrepare(pm, (UINT32)mode, prepare);
|
||||||
LOS_IntRestore(intSave);
|
LOS_IntRestore(intSave);
|
||||||
|
|
||||||
LOS_TaskUnlock();
|
LOS_TaskUnlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC VOID OsPmNormalSleep(LosPmCB *pm)
|
STATIC VOID OsPmNormalSleep(VOID)
|
||||||
{
|
{
|
||||||
UINT32 intSave;
|
UINT32 intSave;
|
||||||
Suspend sysSuspend = NULL;
|
LosPmCB *pm = &g_pmCB;
|
||||||
|
SysSuspend sysSuspend = NULL;
|
||||||
|
|
||||||
intSave = LOS_IntLock();
|
intSave = LOS_IntLock();
|
||||||
sysSuspend = OsPmCpuSuspend(pm);
|
sysSuspend = OsPmCpuSuspend(pm);
|
||||||
|
@ -237,24 +297,6 @@ STATIC VOID OsPmNormalSleep(LosPmCB *pm)
|
||||||
LOS_IntRestore(intSave);
|
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)
|
STATIC UINT32 OsPmDeviceRegister(LosPmCB *pm, LosPmDevice *device)
|
||||||
{
|
{
|
||||||
UINT32 intSave;
|
UINT32 intSave;
|
||||||
|
@ -438,11 +480,8 @@ LOS_SysSleepEnum LOS_PmModeGet(VOID)
|
||||||
UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode)
|
UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode)
|
||||||
{
|
{
|
||||||
UINT32 intSave;
|
UINT32 intSave;
|
||||||
UINT32 taskID;
|
|
||||||
UINT32 ret;
|
|
||||||
LosPmCB *pm = &g_pmCB;
|
LosPmCB *pm = &g_pmCB;
|
||||||
INT32 sleepMode = (INT32)mode;
|
INT32 sleepMode = (INT32)mode;
|
||||||
TSK_INIT_PARAM_S taskInitParam = { 0 };
|
|
||||||
|
|
||||||
if ((sleepMode < 0) || (sleepMode > LOS_SYS_SHUTDOWN)) {
|
if ((sleepMode < 0) || (sleepMode > LOS_SYS_SHUTDOWN)) {
|
||||||
return LOS_ERRNO_PM_INVALID_MODE;
|
return LOS_ERRNO_PM_INVALID_MODE;
|
||||||
|
@ -472,17 +511,6 @@ UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode)
|
||||||
pm->pmMode = mode;
|
pm->pmMode = mode;
|
||||||
LOS_IntRestore(intSave);
|
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;
|
return LOS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,24 +537,17 @@ VOID LOS_PmLockInfoShow(VOID)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UINT32 LOS_PmLockRequest(const CHAR *name)
|
UINT32 OsPmLockRequest(const CHAR *name, UINT32 swtmrID)
|
||||||
{
|
{
|
||||||
UINT32 intSave;
|
UINT32 intSave;
|
||||||
UINT32 ret = LOS_ERRNO_PM_NOT_LOCK;
|
UINT32 ret = LOS_ERRNO_PM_NOT_LOCK;
|
||||||
LosPmCB *pm = &g_pmCB;
|
LosPmCB *pm = &g_pmCB;
|
||||||
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
|
||||||
OsPmLockCB *listNode = NULL;
|
OsPmLockCB *listNode = NULL;
|
||||||
OsPmLockCB *lock = NULL;
|
OsPmLockCB *lock = NULL;
|
||||||
LOS_DL_LIST *head = &pm->lockList;
|
LOS_DL_LIST *head = &pm->lockList;
|
||||||
LOS_DL_LIST *list = head->pstNext;
|
LOS_DL_LIST *list = head->pstNext;
|
||||||
|
|
||||||
if (name == NULL) {
|
|
||||||
return LOS_ERRNO_PM_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
intSave = LOS_IntLock();
|
intSave = LOS_IntLock();
|
||||||
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
|
||||||
while (list != head) {
|
while (list != head) {
|
||||||
listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
|
listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
|
||||||
if (strcmp(name, listNode->name) == 0) {
|
if (strcmp(name, listNode->name) == 0) {
|
||||||
|
@ -545,11 +566,17 @@ UINT32 LOS_PmLockRequest(const CHAR *name)
|
||||||
}
|
}
|
||||||
lock->name = (CHAR *)name;
|
lock->name = (CHAR *)name;
|
||||||
lock->count = 1;
|
lock->count = 1;
|
||||||
|
lock->swtmrID = swtmrID;
|
||||||
LOS_ListTailInsert(head, &lock->list);
|
LOS_ListTailInsert(head, &lock->list);
|
||||||
} else if (lock->count < OS_PM_LOCK_MAX) {
|
} else if (lock->count < OS_PM_LOCK_MAX) {
|
||||||
lock->count++;
|
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) {
|
if (pm->lock < OS_PM_LOCK_MAX) {
|
||||||
pm->lock++;
|
pm->lock++;
|
||||||
|
@ -560,25 +587,34 @@ UINT32 LOS_PmLockRequest(const CHAR *name)
|
||||||
return ret;
|
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 LOS_PmLockRelease(const CHAR *name)
|
||||||
{
|
{
|
||||||
UINT32 intSave;
|
UINT32 intSave;
|
||||||
UINT32 ret = LOS_ERRNO_PM_NOT_LOCK;
|
UINT32 ret = LOS_ERRNO_PM_NOT_LOCK;
|
||||||
LosPmCB *pm = &g_pmCB;
|
LosPmCB *pm = &g_pmCB;
|
||||||
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
|
||||||
OsPmLockCB *lock = NULL;
|
OsPmLockCB *lock = NULL;
|
||||||
OsPmLockCB *listNode = NULL;
|
OsPmLockCB *listNode = NULL;
|
||||||
LOS_DL_LIST *head = &pm->lockList;
|
LOS_DL_LIST *head = &pm->lockList;
|
||||||
LOS_DL_LIST *list = head->pstNext;
|
LOS_DL_LIST *list = head->pstNext;
|
||||||
VOID *lockFree = NULL;
|
OsPmLockCB *lockFree = NULL;
|
||||||
|
BOOL isRelease = FALSE;
|
||||||
|
UINT32 mode;
|
||||||
|
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
return LOS_ERRNO_PM_INVALID_PARAM;
|
return LOS_ERRNO_PM_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
intSave = LOS_IntLock();
|
intSave = LOS_IntLock();
|
||||||
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
mode = (UINT32)pm->pmMode;
|
||||||
while (list != head) {
|
while (list != head) {
|
||||||
listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
|
listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
|
||||||
if (strcmp(name, listNode->name) == 0) {
|
if (strcmp(name, listNode->name) == 0) {
|
||||||
|
@ -599,25 +635,139 @@ UINT32 LOS_PmLockRelease(const CHAR *name)
|
||||||
lockFree = lock;
|
lockFree = lock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (pm->lock > 0) {
|
if (pm->lock > 0) {
|
||||||
pm->lock--;
|
pm->lock--;
|
||||||
|
if (pm->lock == 0) {
|
||||||
|
isRelease = TRUE;
|
||||||
|
}
|
||||||
ret = LOS_OK;
|
ret = LOS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOS_IntRestore(intSave);
|
LOS_IntRestore(intSave);
|
||||||
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
|
||||||
|
if (lockFree != NULL) {
|
||||||
|
(VOID)LOS_SwtmrDelete(lockFree->swtmrID);
|
||||||
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree);
|
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
if (isRelease && (mode > LOS_SYS_NORMAL_SLEEP)) {
|
||||||
|
(VOID)LOS_EventWrite(&g_pmEvent, PM_EVENT_LOCK_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
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)
|
STATIC VOID OsPmSleepTimeSet(UINT64 sleepTime)
|
||||||
{
|
{
|
||||||
g_pmSleepTime = 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 OsPmInit(VOID)
|
||||||
{
|
{
|
||||||
UINT32 ret;
|
UINT32 ret;
|
||||||
|
@ -626,16 +776,15 @@ UINT32 OsPmInit(VOID)
|
||||||
(VOID)memset_s(pm, sizeof(LosPmCB), 0, sizeof(LosPmCB));
|
(VOID)memset_s(pm, sizeof(LosPmCB), 0, sizeof(LosPmCB));
|
||||||
|
|
||||||
pm->pmMode = LOS_SYS_NORMAL_SLEEP;
|
pm->pmMode = LOS_SYS_NORMAL_SLEEP;
|
||||||
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
|
||||||
LOS_ListInit(&pm->lockList);
|
LOS_ListInit(&pm->lockList);
|
||||||
#endif
|
(VOID)LOS_EventInit(&g_pmEvent);
|
||||||
|
|
||||||
ret = OsSchedRealSleepTimeSet(OsPmSleepTimeSet);
|
ret = OsSchedRealSleepTimeSet(OsPmSleepTimeSet);
|
||||||
if (ret != LOS_OK) {
|
if (ret != LOS_OK) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = OsPmEnterHandlerSet(OsPmEnter);
|
ret = OsPmEnterHandlerSet(OsPmNormalSleep);
|
||||||
if (ret != LOS_OK) {
|
if (ret != LOS_OK) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,15 @@
|
||||||
*/
|
*/
|
||||||
#define LOS_ERRNO_PM_DEVICE_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x09)
|
#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 {
|
typedef enum {
|
||||||
LOS_SYS_NORMAL_SLEEP = 0,
|
LOS_SYS_NORMAL_SLEEP = 0,
|
||||||
LOS_SYS_LIGHT_SLEEP,
|
LOS_SYS_LIGHT_SLEEP,
|
||||||
|
@ -132,8 +141,8 @@ typedef enum {
|
||||||
} LOS_PmNodeType;
|
} LOS_PmNodeType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT32 (*suspend)(UINT32 mode);
|
UINT32 (*suspend)(UINT32 mode); /* The device enters low power consumption, Unlocked task scheduling. */
|
||||||
VOID (*resume)(UINT32 mode);
|
VOID (*resume)(UINT32 mode); /* The device exits from low power consumption, Unlocked task scheduling. */
|
||||||
} LosPmDevice;
|
} LosPmDevice;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -146,13 +155,47 @@ typedef struct {
|
||||||
} LosPmTickTimer;
|
} LosPmTickTimer;
|
||||||
|
|
||||||
typedef struct {
|
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);
|
UINT32 (*normalSuspend)(VOID);
|
||||||
|
/* The system recovers from normal sleep.
|
||||||
|
* The value can be NULL.
|
||||||
|
*/
|
||||||
VOID (*normalResume)(VOID);
|
VOID (*normalResume)(VOID);
|
||||||
|
/* The system enters the light sleep mode.
|
||||||
|
* In light sleep mode, the value cannot be NULL.
|
||||||
|
*/
|
||||||
UINT32 (*lightSuspend)(VOID);
|
UINT32 (*lightSuspend)(VOID);
|
||||||
|
/* The system recovers from light sleep.
|
||||||
|
* The value can be NULL.
|
||||||
|
*/
|
||||||
VOID (*lightResume)(VOID);
|
VOID (*lightResume)(VOID);
|
||||||
|
/* The system enters the deep sleep mode.
|
||||||
|
* In deep sleep mode, the value cannot be NULL.
|
||||||
|
*/
|
||||||
UINT32 (*deepSuspend)(VOID);
|
UINT32 (*deepSuspend)(VOID);
|
||||||
|
/* The system recovers from deep sleep.
|
||||||
|
* The value can be NULL.
|
||||||
|
*/
|
||||||
VOID (*deepResume)(VOID);
|
VOID (*deepResume)(VOID);
|
||||||
|
/* The system enters the shutdown mode.
|
||||||
|
* In shutdown mode, the value cannot be NULL.
|
||||||
|
*/
|
||||||
UINT32 (*shutdownSuspend)(VOID);
|
UINT32 (*shutdownSuspend)(VOID);
|
||||||
|
/* The system recovers from shutdown.
|
||||||
|
* In shutdown mode, the value cannot be NULL.
|
||||||
|
*/
|
||||||
VOID (*shutdownResume)(VOID);
|
VOID (*shutdownResume)(VOID);
|
||||||
} LosPmSysctrl;
|
} LosPmSysctrl;
|
||||||
|
|
||||||
|
@ -174,6 +217,60 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
UINT32 OsPmInit(VOID);
|
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:
|
||||||
|
* <ul><li>los_pm.h: the header file that contains the API declaration.</li></ul>
|
||||||
|
* @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:
|
||||||
|
* <ul><li>los_pm.h: the header file that contains the API declaration.</li></ul>
|
||||||
|
* @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:
|
||||||
|
* <ul><li>los_pm.h: the header file that contains the API declaration.</li></ul>
|
||||||
|
* @see OsPmFreezeTaskUnsafe
|
||||||
|
*/
|
||||||
|
VOID OsPmUnfreezeTaskUnsafe(UINT32 taskID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup los_pm
|
* @ingroup los_pm
|
||||||
* @brief Register a power management node.
|
* @brief Register a power management node.
|
||||||
|
@ -285,6 +382,27 @@ UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode);
|
||||||
*/
|
*/
|
||||||
UINT32 LOS_PmLockRequest(const CHAR *name);
|
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:
|
||||||
|
* <ul><li>los_pm.h: the header file that contains the API declaration.</li></ul>
|
||||||
|
* @see LOS_PmLockRelease
|
||||||
|
*/
|
||||||
|
UINT32 LOS_PmTimeLockRequest(const CHAR *name, UINT64 millisecond);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup los_pm
|
* @ingroup los_pm
|
||||||
* @brief Release the lock in current mode so that the next time the system enters
|
* @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);
|
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:
|
||||||
|
* <ul><li>los_pm.h: the header file that contains the API declaration.</li></ul>
|
||||||
|
* @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:
|
||||||
|
* <ul><li>los_pm.h: the header file that contains the API declaration.</li></ul>
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
UINT32 LOS_PmSuspend(UINT32 wakeCount);
|
||||||
|
|
||||||
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
|
||||||
/**
|
/**
|
||||||
* @ingroup los_pm
|
* @ingroup los_pm
|
||||||
|
|
|
@ -61,6 +61,8 @@ VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask);
|
||||||
|
|
||||||
UINT32 OsSchedSwtmrScanRegister(SchedScan func);
|
UINT32 OsSchedSwtmrScanRegister(SchedScan func);
|
||||||
|
|
||||||
|
VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, BOOL timeUpdate);
|
||||||
|
|
||||||
VOID OsSchedUpdateExpireTime(UINT64 startTime, BOOL timeUpdate);
|
VOID OsSchedUpdateExpireTime(UINT64 startTime, BOOL timeUpdate);
|
||||||
|
|
||||||
VOID OsSchedTaskDeQueue(LosTaskCB *taskCB);
|
VOID OsSchedTaskDeQueue(LosTaskCB *taskCB);
|
||||||
|
|
|
@ -1175,6 +1175,14 @@ extern VOID LOS_UDelay(UINT64 microseconds);
|
||||||
*/
|
*/
|
||||||
#define OS_TASK_STATUS_PEND_TIME 0x0080
|
#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
|
* @ingroup los_task
|
||||||
* Flag that indicates the task is in userspace.
|
* Flag that indicates the task is in userspace.
|
||||||
|
|
|
@ -179,7 +179,7 @@ STATIC INLINE VOID OsSchedTickReload(UINT64 nextResponseTime, UINT32 responseID,
|
||||||
HalSysTickReload(nextResponseTime);
|
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 nextExpireTime;
|
||||||
UINT64 nextResponseTime = 0;
|
UINT64 nextResponseTime = 0;
|
||||||
|
|
|
@ -44,6 +44,9 @@
|
||||||
#if (LOSCFG_BASE_CORE_CPUP == 1)
|
#if (LOSCFG_BASE_CORE_CPUP == 1)
|
||||||
#include "los_cpup.h"
|
#include "los_cpup.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if (LOSCFG_KERNEL_PM == 1)
|
||||||
|
#include "los_pm.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup los_task
|
* @ingroup los_task
|
||||||
|
@ -403,7 +406,6 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
|
||||||
taskInitParam.pcName = "IdleCore000";
|
taskInitParam.pcName = "IdleCore000";
|
||||||
taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;
|
taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;
|
||||||
retVal = LOS_TaskCreateOnly(&g_idleTaskID, &taskInitParam);
|
retVal = LOS_TaskCreateOnly(&g_idleTaskID, &taskInitParam);
|
||||||
|
|
||||||
if (retVal != LOS_OK) {
|
if (retVal != LOS_OK) {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -803,6 +805,12 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
|
||||||
OS_GOTO_ERREND();
|
OS_GOTO_ERREND();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (LOSCFG_KERNEL_PM == 1)
|
||||||
|
if (tempStatus & OS_TASK_FALG_FREEZE) {
|
||||||
|
OsPmUnfreezeTaskUnsafe(taskID);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
taskCB->taskStatus &= (~OS_TASK_STATUS_SUSPEND);
|
taskCB->taskStatus &= (~OS_TASK_STATUS_SUSPEND);
|
||||||
if (!(taskCB->taskStatus & OS_CHECK_TASK_BLOCK)) {
|
if (!(taskCB->taskStatus & OS_CHECK_TASK_BLOCK)) {
|
||||||
OsSchedTaskEnQueue(taskCB);
|
OsSchedTaskEnQueue(taskCB);
|
||||||
|
@ -862,6 +870,12 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID)
|
||||||
OsSchedTaskDeQueue(taskCB);
|
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;
|
taskCB->taskStatus |= OS_TASK_STATUS_SUSPEND;
|
||||||
OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB);
|
OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB);
|
||||||
if (taskID == g_losTask.runTask->taskID) {
|
if (taskID == g_losTask.runTask->taskID) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ static_library("test_pm") {
|
||||||
"It_los_pm.c",
|
"It_los_pm.c",
|
||||||
"It_los_pm_001.c",
|
"It_los_pm_001.c",
|
||||||
"It_los_pm_002.c",
|
"It_los_pm_002.c",
|
||||||
|
"It_los_pm_003.c",
|
||||||
]
|
]
|
||||||
|
|
||||||
include_dirs = [ "//kernel/liteos_m/components/power" ]
|
include_dirs = [ "//kernel/liteos_m/components/power" ]
|
||||||
|
|
|
@ -31,9 +31,10 @@
|
||||||
#include "osTest.h"
|
#include "osTest.h"
|
||||||
#include "It_los_pm.h"
|
#include "It_los_pm.h"
|
||||||
|
|
||||||
VOID ItSuiteLosPm()
|
VOID ItSuiteLosPm(VOID)
|
||||||
{
|
{
|
||||||
ItLosPm001();
|
ItLosPm001();
|
||||||
ItLosPm002();
|
ItLosPm002();
|
||||||
|
ItLosPm003();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ extern "C" {
|
||||||
|
|
||||||
extern VOID ItLosPm001(VOID);
|
extern VOID ItLosPm001(VOID);
|
||||||
extern VOID ItLosPm002(VOID);
|
extern VOID ItLosPm002(VOID);
|
||||||
|
extern VOID ItLosPm003(VOID);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
|
|
@ -50,16 +50,21 @@ static VOID SysResume(VOID)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT32 SysSuspend(VOID)
|
|
||||||
{
|
|
||||||
return HalEnterSleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
static LosPmSysctrl g_sysctrl = {
|
static LosPmSysctrl g_sysctrl = {
|
||||||
.normalSuspend = NULL,
|
.normalSuspend = NULL,
|
||||||
.normalResume = SysResume,
|
.normalResume = SysResume,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static VOID TimerStart(UINT64 timer)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT64 GetTimerCycle(VOID)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static VOID TickLock(VOID)
|
static VOID TickLock(VOID)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -128,7 +133,7 @@ static UINT32 TestCase(VOID)
|
||||||
|
|
||||||
g_tickTimer.tickLock = TickLock;
|
g_tickTimer.tickLock = TickLock;
|
||||||
g_tickTimer.tickUnlock = TickUnlock;
|
g_tickTimer.tickUnlock = TickUnlock;
|
||||||
g_tickTimer.timerStart = TickLock;
|
g_tickTimer.timerStart = TimerStart;
|
||||||
ret = LOS_PmRegister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer);
|
ret = LOS_PmRegister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer);
|
||||||
ICUNIT_ASSERT_EQUAL(ret, LOS_ERRNO_PM_INVALID_PARAM, ret);
|
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);
|
ret = LOS_PmRegister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer);
|
||||||
ICUNIT_ASSERT_EQUAL(ret, LOS_ERRNO_PM_INVALID_PARAM, ret);
|
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);
|
ret = LOS_PmRegister(LOS_PM_TYPE_TICK_TIMER, &g_tickTimer);
|
||||||
ICUNIT_ASSERT_EQUAL(ret, LOS_ERRNO_PM_INVALID_PARAM, ret);
|
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);
|
TEST_ADD_CASE("ItLosPm001", TestCase, TEST_LOS, TEST_TASK, TEST_LEVEL0, TEST_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,14 @@
|
||||||
#include "It_los_pm.h"
|
#include "It_los_pm.h"
|
||||||
#include "los_timer.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_deviceCount = 0;
|
||||||
static UINT32 g_sysCount = 0;
|
static UINT32 g_sysCount = 0;
|
||||||
static UINT32 g_sysTickTimerCount = 0;
|
static volatile UINT32 g_pmTestCount = 0;
|
||||||
|
|
||||||
static UINT32 DeviceSuspend(UINT32 mode)
|
static UINT32 DeviceSuspend(UINT32 mode)
|
||||||
{
|
{
|
||||||
g_deviceCount++;
|
g_deviceCount++;
|
||||||
|
@ -53,26 +58,6 @@ static LosPmDevice g_device = {
|
||||||
.resume = DeviceResume,
|
.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)
|
static VOID SysResume(VOID)
|
||||||
{
|
{
|
||||||
if (g_sysCount != (UINT32)-1) {
|
if (g_sysCount != (UINT32)-1) {
|
||||||
|
@ -85,29 +70,154 @@ static UINT32 SysSuspend(VOID)
|
||||||
g_testCount++;
|
g_testCount++;
|
||||||
g_sysCount++;
|
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;
|
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();
|
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 = {
|
static LosPmSysctrl g_sysctrl = {
|
||||||
|
.early = SystemPmEarly,
|
||||||
|
.late = SystemPmLate,
|
||||||
.normalSuspend = HalEnterSleep,
|
.normalSuspend = HalEnterSleep,
|
||||||
.normalResume = NULL,
|
.normalResume = NULL,
|
||||||
.lightSuspend = SysSuspend,
|
.lightSuspend = SysSuspend,
|
||||||
.lightResume = SysResume,
|
.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)
|
static UINT32 TestCase(VOID)
|
||||||
{
|
{
|
||||||
UINT32 ret;
|
UINT32 ret;
|
||||||
|
TSK_INIT_PARAM_S task1 = { 0 };
|
||||||
g_sysCount = 0;
|
g_sysCount = 0;
|
||||||
g_deviceCount = 0;
|
g_deviceCount = 0;
|
||||||
g_sysTickTimerCount = 0;
|
|
||||||
g_testCount = 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);
|
ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret);
|
||||||
|
|
||||||
ret = LOS_PmRegister(LOS_PM_TYPE_DEVICE, &g_device);
|
ret = LOS_PmRegister(LOS_PM_TYPE_DEVICE, &g_device);
|
||||||
|
@ -119,34 +229,42 @@ static UINT32 TestCase(VOID)
|
||||||
ret = LOS_PmModeSet(LOS_SYS_LIGHT_SLEEP);
|
ret = LOS_PmModeSet(LOS_SYS_LIGHT_SLEEP);
|
||||||
ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret);
|
ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret);
|
||||||
|
|
||||||
LOS_PmLockRequest("testlock");
|
task1.pfnTaskEntry = (TSK_ENTRY_FUNC)PmTestTask;
|
||||||
LOS_TaskDelay(100); /* delay 100 ticks */
|
task1.uwStackSize = 0x2000; /* 0x2000 pm task stack size */
|
||||||
LOS_PmLockRelease("testlock");
|
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);
|
(VOID)LOS_EventRead(&g_pmTestEvent, 0xff, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
|
||||||
ICUNIT_GOTO_EQUAL(g_sysCount, 0, g_sysCount, EXIT);
|
|
||||||
|
|
||||||
ret = LOS_PmUnregister(LOS_PM_TYPE_DEVICE, &g_device);
|
ret = LOS_PmUnregister(LOS_PM_TYPE_DEVICE, &g_device);
|
||||||
ICUNIT_ASSERT_EQUAL(ret, LOS_OK, ret);
|
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);
|
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;
|
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
|
VOID ItLosPm002(VOID) // IT_Layer_ModuleORFeature_No
|
||||||
{
|
{
|
||||||
TEST_ADD_CASE("ItLosPm002", TestCase, TEST_LOS, TEST_TASK, TEST_LEVEL0, TEST_FUNCTION);
|
TEST_ADD_CASE("ItLosPm002", TestCase, TEST_LOS, TEST_TASK, TEST_LEVEL0, TEST_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue