提交 558ce14b 编写于 作者: Z zhushengle

feat: L0 支持低功耗框架

1.【需求描述】
 L0 支持低功耗投票框架, 使内核与应用、驱动分离开,通过注册及投票机制控制系统的低功耗模式,
  减低系统功耗,提升设备电池寿命。
2.【方案描述】
 (1).提供注册机制,使驱动与内核分离
  (2).提供投票机制,判断系统运行模式
  (3).记录持锁设备,便于回溯
  进入:系统运行进入idle任务时判断当前的功耗模式,如果上层应用未对当前功耗模式(deep和shutdown)
 持锁,则系统准备进入当前模式,首先所有设备依次进入当前模式,如果有设备进入当前模式失败,则恢复
 已进入当前模式的所有设备,并且功耗模式变为normal模式;设备依次进入当前功耗模式后cpu再进入当前
 功耗模式。
  恢复:功耗模式为deep时,需要恢复逻辑,时系统恢复运行。当有中断出发时,系统会退出低功耗模式,
  恢复顺序为:首先cpu先恢复,然后设备依次恢复。

BREAKING CHANGE:
1.原调度中基于tick timer的低功耗扩展和当前的pm模块合并,删除原对外接口LOS_SchedSleepInit,
 变为pm模块统一提供的LOS_PmRegistered接口.
2.原来在arch los_timer.h下提供的低功耗模式为枚举LOS_SysSleepEnum,其中OS_SYS_NORMAL_SLEEP
  和OS_SYS_DEEP_SLEEP不符合对外定义,统一修改为LOS_SYS_NORMAL_SLEEP和LOS_SYS_DEEP_SLEEP,
  并移至los_pm.h中.
3.VOID HalEnterSleep(LOS_SysSleepEnum sleep) 变更为UINT32 HalEnterSleep(VOID).

Close #I3UDNV
Signed-off-by: Nzhushengle <zhushengle@huawei.com>
Change-Id: Id5382c42c8055ba7850895a3f575130a73e38a65
上级 468ce69f
......@@ -35,6 +35,7 @@ declare_args() {
enable_ohos_kernel_liteos_m_fs = true
enable_ohos_kernel_liteos_m_backtrace = true
enable_ohos_kernel_liteos_m_test = false
enable_ohos_kernel_liteos_m_pm = true
}
group("kernel") {
......@@ -58,6 +59,9 @@ group("kernel") {
if (enable_ohos_kernel_liteos_m_fs == true) {
deps += [ "components/fs:fs" ]
}
if (enable_ohos_kernel_liteos_m_pm == true) {
deps += [ "components/power:pm" ]
}
if (enable_ohos_kernel_liteos_m_kal == true) {
deps += [ "kal:kal" ]
}
......
# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
# Copyright (c) 2020-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.
static_library("pm") {
sources = [ "los_pm.c" ]
include_dirs = [
"../../kernel/include",
"../../kernel/arch/include",
"../../utils",
"//third_party/bounds_checking_function/include",
]
}
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-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 "los_pm.h"
#include "securec.h"
#include "los_sched.h"
#include "los_timer.h"
#include "los_memory.h"
#if (LOSCFG_KERNEL_PM == 1)
#define OS_PM_NODE_FREE 0x80000000U
#define OS_PM_LOCK_MAX 0xFFFFU
typedef UINT32 (*Suspend)(VOID);
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
typedef struct {
CHAR *name;
UINT32 count;
LOS_DL_LIST list;
} OsPmLockCB;
#endif
typedef struct {
LOS_SysSleepEnum pmMode;
LOS_SysSleepEnum sysMode;
UINT16 lock;
BOOL isWake;
LosPmDevice *device;
LosPmSysctrl *sysctrl;
LosPmTickTimer *tickTimer;
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
UINT64 enterSleepTime;
#endif
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
LOS_DL_LIST lockList;
#endif
} LosPmCB;
STATIC LosPmCB g_pmCB;
STATIC LosPmSysctrl *g_sysctrl = NULL;
STATIC UINT64 g_pmSleepTime;
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
STATIC VOID OsPmTickTimerStart(LosPmCB *pm)
{
UINT32 intSave;
UINT64 currTime, sleepTime, realSleepTime;
LosPmTickTimer *tickTimer = pm->tickTimer;
intSave = LOS_IntLock();
/* Restore the main CPU frequency */
sleepTime = tickTimer->timerCycleGet();
tickTimer->timerStop();
realSleepTime = OS_SYS_CYCLE_TO_NS(sleepTime, tickTimer->freq);
realSleepTime = OS_SYS_NS_TO_CYCLE(realSleepTime, OS_SYS_CLOCK);
currTime = pm->enterSleepTime + realSleepTime;
pm->enterSleepTime = 0;
OsSchedTimerBaseReset(currTime);
OsSchedUpdateExpireTime(currTime, FALSE);
tickTimer->tickUnlock();
LOS_IntRestore(intSave);
return;
}
STATIC VOID OsPmTickTimerStop(LosPmCB *pm)
{
UINT64 sleepCycle;
UINT64 realSleepTime = g_pmSleepTime;
LosPmTickTimer *tickTimer = pm->tickTimer;
if (realSleepTime == 0) {
return;
}
sleepCycle = OS_SYS_CYCLE_TO_NS(realSleepTime, OS_SYS_CLOCK);
sleepCycle = OS_SYS_NS_TO_CYCLE(sleepCycle, tickTimer->freq);
/* The main CPU reduces the frequency */
pm->enterSleepTime = OsGetCurrSchedTimeCycle();
tickTimer->tickLock();
tickTimer->timerStart(sleepCycle);
return;
}
#endif
STATIC VOID OsPmTickTimerResume(LosPmCB *pm)
{
if ((pm->sysMode == LOS_SYS_DEEP_SLEEP) && (pm->tickTimer->tickUnlock != NULL)) {
pm->tickTimer->tickUnlock();
} else {
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
/* Sys tick timer is restored from low power mode */
if (pm->enterSleepTime != 0) {
OsPmTickTimerStart(pm);
}
#endif
}
}
STATIC VOID OsPmCpuResume(LosPmCB *pm)
{
if ((pm->sysMode == LOS_SYS_NORMAL_SLEEP) && (pm->sysctrl->normalResume != NULL)) {
pm->sysctrl->normalResume();
} else if ((pm->sysMode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightResume != NULL)) {
pm->sysctrl->lightResume();
} else if ((pm->sysMode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepResume != NULL)) {
pm->sysctrl->deepResume();
}
}
STATIC Suspend OsPmCpuSuspend(LosPmCB *pm)
{
Suspend sysSuspend = NULL;
/* cpu enter low power mode */
LOS_ASSERT(pm->sysctrl != NULL);
if (pm->sysMode == LOS_SYS_NORMAL_SLEEP) {
sysSuspend = pm->sysctrl->normalSuspend;
} else if (pm->sysMode == LOS_SYS_LIGHT_SLEEP) {
sysSuspend = pm->sysctrl->lightSuspend;
} else if (pm->sysMode == LOS_SYS_DEEP_SLEEP) {
sysSuspend = pm->sysctrl->deepSuspend;
} else {
sysSuspend = pm->sysctrl->shutdownSuspend;
}
LOS_ASSERT(sysSuspend != NULL);
return sysSuspend;
}
STATIC VOID OsPmTickTimerSuspend(LosPmCB *pm)
{
if (((pm->sysMode == LOS_SYS_DEEP_SLEEP) || (pm->sysMode == LOS_SYS_SHUTDOWN)) &&
(pm->tickTimer->tickLock != NULL)) {
pm->tickTimer->tickLock();
} else {
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
/* Sys tick timer enter low power mode */
if (pm->tickTimer == NULL) {
return;
}
if ((pm->tickTimer->timerStart != NULL) &&
(pm->tickTimer->timerStop != NULL) &&
(pm->tickTimer->timerCycleGet == NULL) &&
(pm->tickTimer->freq != 0)) {
OsPmTickTimerStop(pm);
}
#endif
}
}
STATIC VOID OsPmEnter(BOOL isIdle)
{
UINT32 ret;
UINT32 intSave;
Suspend sysSuspend = NULL;
LosPmCB *pm = &g_pmCB;
BOOL isTaskLock = FALSE;
intSave = LOS_IntLock();
pm->sysMode = pm->pmMode;
if (isIdle) {
if ((pm->sysMode != LOS_SYS_NORMAL_SLEEP) && (pm->sysMode != LOS_SYS_LIGHT_SLEEP)) {
pm->sysMode = LOS_SYS_NORMAL_SLEEP;
}
} else {
if ((pm->sysMode != LOS_SYS_DEEP_SLEEP) && (pm->sysMode != LOS_SYS_SHUTDOWN)) {
LOS_IntRestore(intSave);
return;
}
}
if ((pm->sysMode == LOS_SYS_NORMAL_SLEEP) || (pm->sysMode == LOS_SYS_LIGHT_SLEEP)) {
if (pm->lock > 0) {
pm->sysMode = LOS_SYS_NORMAL_SLEEP;
}
} else if (pm->lock > 0) {
LOS_IntRestore(intSave);
return;
}
if (pm->sysMode != LOS_SYS_NORMAL_SLEEP) {
pm->isWake = FALSE;
LOS_TaskLock();
isTaskLock = TRUE;
ret = pm->device->suspend((UINT32)pm->sysMode);
if (ret != LOS_OK) {
goto EXIT;
}
}
OsPmTickTimerSuspend(pm);
sysSuspend = OsPmCpuSuspend(pm);
LOS_IntRestore(intSave);
if (!isTaskLock || (isTaskLock && !pm->isWake)) {
(VOID)sysSuspend();
}
intSave = LOS_IntLock();
OsPmCpuResume(pm);
OsPmTickTimerResume(pm);
if (pm->sysMode != LOS_SYS_NORMAL_SLEEP) {
pm->device->resume((UINT32)pm->sysMode);
}
if (pm->pmMode == LOS_SYS_DEEP_SLEEP) {
pm->pmMode = LOS_SYS_NORMAL_SLEEP;
}
EXIT:
LOS_IntRestore(intSave);
if (isTaskLock) {
LOS_TaskUnlock();
}
return;
}
STATIC VOID OsPmTask(VOID)
{
OsPmEnter(FALSE);
}
STATIC UINT32 OsPmDeviceRegister(LosPmCB *pm, LosPmDevice *device)
{
UINT32 intSave;
if ((device->suspend == NULL) || (device->resume == NULL)) {
return LOS_ERRNO_PM_INVALID_PARAM;
}
intSave = LOS_IntLock();
pm->device = device;
LOS_IntRestore(intSave);
return LOS_OK;
}
STATIC UINT32 OsPmTickTimerRegister(LosPmCB *pm, LosPmTickTimer *tickTimer)
{
UINT32 intSave;
intSave = LOS_IntLock();
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
pm->enterSleepTime = 0;
#endif
pm->tickTimer = tickTimer;
LOS_IntRestore(intSave);
return LOS_OK;
}
STATIC UINT32 OsPmSysctrlRegister(LosPmCB *pm, LosPmSysctrl *sysctrl)
{
UINT32 intSave;
if (sysctrl->normalSuspend == NULL) {
return LOS_ERRNO_PM_INVALID_PARAM;
}
intSave = LOS_IntLock();
pm->sysctrl = sysctrl;
LOS_IntRestore(intSave);
return LOS_OK;
}
UINT32 LOS_PmRegister(LOS_PmNodeType type, VOID *node)
{
LosPmCB *pm = &g_pmCB;
if (node == NULL) {
return LOS_ERRNO_PM_INVALID_PARAM;
}
switch (type) {
case LOS_PM_TYPE_DEVICE:
return OsPmDeviceRegister(pm, (LosPmDevice *)node);
case LOS_PM_TYPE_TICK_TIMER:
return OsPmTickTimerRegister(pm, (LosPmTickTimer *)node);
case LOS_PM_TYPE_SYSCTRL:
return OsPmSysctrlRegister(pm, (LosPmSysctrl *)node);
default:
break;
}
return LOS_ERRNO_PM_INVALID_TYPE;
}
STATIC UINT32 OsPmDeviceUnregister(LosPmCB *pm, LosPmDevice *device)
{
UINT32 intSave;
intSave = LOS_IntLock();
if (pm->device == device) {
pm->device = NULL;
pm->pmMode = LOS_SYS_NORMAL_SLEEP;
LOS_IntRestore(intSave);
return LOS_OK;
}
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_INVALID_NODE;
}
STATIC UINT32 OsPmTickTimerUnregister(LosPmCB *pm, LosPmTickTimer *tickTimer)
{
UINT32 intSave;
intSave = LOS_IntLock();
if (pm->tickTimer == tickTimer) {
pm->tickTimer = NULL;
if ((pm->pmMode != LOS_SYS_NORMAL_SLEEP) && (pm->pmMode != LOS_SYS_LIGHT_SLEEP)) {
pm->pmMode = LOS_SYS_NORMAL_SLEEP;
}
LOS_IntRestore(intSave);
return LOS_OK;
}
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_INVALID_NODE;
}
STATIC UINT32 OsPmSysctrlUnregister(LosPmCB *pm, LosPmSysctrl *sysctrl)
{
UINT32 intSave;
VOID *freeNode = NULL;
intSave = LOS_IntLock();
if (pm->sysctrl == sysctrl) {
if (pm->sysctrl == g_sysctrl) {
freeNode = (VOID *)pm->sysctrl;
g_sysctrl = NULL;
}
pm->sysctrl = NULL;
LOS_IntRestore(intSave);
if (freeNode != NULL) {
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, freeNode);
}
return LOS_OK;
}
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_INVALID_NODE;
}
UINT32 LOS_PmUnregister(LOS_PmNodeType type, VOID *node)
{
LosPmCB *pm = &g_pmCB;
if (node == NULL) {
return LOS_ERRNO_PM_INVALID_PARAM;
}
switch (type) {
case LOS_PM_TYPE_DEVICE:
return OsPmDeviceUnregister(pm, (LosPmDevice *)node);
case LOS_PM_TYPE_TICK_TIMER:
return OsPmTickTimerUnregister(pm, (LosPmTickTimer *)node);
case LOS_PM_TYPE_SYSCTRL:
return OsPmSysctrlUnregister(pm, (LosPmSysctrl *)node);
default:
break;
}
return LOS_ERRNO_PM_INVALID_TYPE;
}
VOID LOS_PmWakeSet(VOID)
{
UINT32 intSave;
LosPmCB *pm = &g_pmCB;
intSave = LOS_IntLock();
pm->isWake = TRUE;
LOS_IntRestore(intSave);
return;
}
LOS_SysSleepEnum LOS_PmModeGet(VOID)
{
LOS_SysSleepEnum mode;
LosPmCB *pm = &g_pmCB;
UINT32 intSave = LOS_IntLock();
mode = pm->pmMode;
LOS_IntRestore(intSave);
return mode;
}
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;
}
intSave = LOS_IntLock();
if ((mode != LOS_SYS_NORMAL_SLEEP) && (pm->device == NULL)) {
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_DEVICE_NULL;
}
if ((mode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightSuspend == NULL)) {
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_HANDLER_NULL;
}
if ((mode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepSuspend == NULL)) {
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_HANDLER_NULL;
}
if ((mode == LOS_SYS_SHUTDOWN) && (pm->sysctrl->shutdownSuspend == NULL)) {
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_HANDLER_NULL;
}
if ((mode == LOS_SYS_DEEP_SLEEP) || (mode == LOS_SYS_SHUTDOWN)) {
if ((pm->tickTimer == NULL) ||
(pm->tickTimer->tickLock == NULL) ||
(pm->tickTimer->tickUnlock == NULL)) {
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_TICK_TIMER_NULL;
}
}
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;
}
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
VOID LOS_PmLockInfoShow(VOID)
{
UINT32 intSave;
LosPmCB *pm = &g_pmCB;
OsPmLockCB *lock = NULL;
LOS_DL_LIST *head = &pm->lockList;
LOS_DL_LIST *list = head->pstNext;
PRINTK("Name Count\n\r");
intSave = LOS_IntLock();
while (list != head) {
lock = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
PRINTK("%-30s%5u\n\r", lock->name, lock->count);
list = list->pstNext;
}
LOS_IntRestore(intSave);
return;
}
#endif
UINT32 LOS_PmLockRequest(const CHAR *name)
{
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) {
lock = listNode;
break;
}
list = list->pstNext;
}
if (lock == NULL) {
lock = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(OsPmLockCB));
if (lock == NULL) {
LOS_IntRestore(intSave);
return LOS_NOK;
}
lock->name = (CHAR *)name;
lock->count = 1;
LOS_ListTailInsert(head, &lock->list);
} else if (lock->count < OS_PM_LOCK_MAX) {
lock->count++;
}
#endif
if (pm->lock < OS_PM_LOCK_MAX) {
pm->lock++;
ret = LOS_OK;
}
LOS_IntRestore(intSave);
return ret;
}
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;
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) {
lock = listNode;
break;
}
list = list->pstNext;
}
if (lock == NULL) {
LOS_IntRestore(intSave);
return LOS_ERRNO_PM_NOT_LOCK;
} else if (lock->count > 0) {
lock->count--;
if (lock->count == 0) {
LOS_ListDelete(&lock->list);
lockFree = lock;
}
}
#endif
if (pm->lock > 0) {
pm->lock--;
ret = LOS_OK;
}
LOS_IntRestore(intSave);
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree);
#endif
return ret;
}
STATIC VOID OsPmSleepTimeSet(UINT64 sleepTime)
{
g_pmSleepTime = sleepTime;
}
UINT32 OsPmInit(VOID)
{
UINT32 ret;
LosPmCB *pm = &g_pmCB;
(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
ret = OsSchedRealSleepTimeSet(OsPmSleepTimeSet);
if (ret != LOS_OK) {
return ret;
}
ret = OsPmEnterHandlerSet(OsPmEnter);
if (ret != LOS_OK) {
return ret;
}
g_sysctrl = (LosPmSysctrl *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(LosPmSysctrl));
if (g_sysctrl == NULL) {
return LOS_NOK;
}
(VOID)memset_s(g_sysctrl, sizeof(LosPmSysctrl), 0, sizeof(LosPmSysctrl));
g_sysctrl->normalSuspend = HalEnterSleep;
ret = LOS_PmRegister(LOS_PM_TYPE_SYSCTRL, (VOID *)g_sysctrl);
if (ret != LOS_OK) {
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, g_sysctrl);
g_sysctrl = NULL;
}
return ret;
}
#endif
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-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.
*/
#ifndef _LOS_PM_H
#define _LOS_PM_H
#include "los_config.h"
#include "los_compiler.h"
#include "los_list.h"
#include "los_error.h"
/**
* @ingroup los_pm
* Pm error code: Invalid low power mode.
*
* Value: 0x02002001
*
*/
#define LOS_ERRNO_PM_INVALID_MODE LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x01)
/**
* @ingroup los_pm
* Pm error code: Invalid input parameter.
*
* Value: 0x02002002
*
*/
#define LOS_ERRNO_PM_INVALID_PARAM LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x02)
/**
* @ingroup los_pm
* Pm error code: The current mode is unlocked.
*
* Value: 0x02002003
*
*/
#define LOS_ERRNO_PM_NOT_LOCK LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x03)
/**
* @ingroup los_pm
* Pm error code: The lock limit has been exceeded.
*
* Value: 0x02002004
*
*/
#define LOS_ERRNO_PM_LOCK_LIMIT LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x04)
/**
* @ingroup los_pm
* Pm error code: Invalid device node.
*
* Value: 0x02002005
*
*/
#define LOS_ERRNO_PM_INVALID_NODE LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x05)
/**
* @ingroup los_pm
* Pm error code: Invalid type.
*
* Value: 0x02002006
*
*/
#define LOS_ERRNO_PM_INVALID_TYPE LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x06)
/**
* @ingroup los_pm
* Pm error code: The hook for mode is not implemented.
*
* Value: 0x02002007
*
*/
#define LOS_ERRNO_PM_HANDLER_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x07)
/**
* @ingroup los_pm
* Pm error code: Deep and shutdown must implement the Tick Timer related interface.
*
* Value: 0x02002008
*
*/
#define LOS_ERRNO_PM_TICK_TIMER_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x08)
/**
* @ingroup los_pm
* Pm error code: Device is not registered.
*
* Value: 0x02002009
*
*/
#define LOS_ERRNO_PM_DEVICE_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_PM, 0x09)
typedef enum {
LOS_SYS_NORMAL_SLEEP = 0,
LOS_SYS_LIGHT_SLEEP,
LOS_SYS_DEEP_SLEEP,
LOS_SYS_SHUTDOWN,
} LOS_SysSleepEnum;
typedef enum {
LOS_PM_TYPE_DEVICE = 0,
LOS_PM_TYPE_TICK_TIMER,
LOS_PM_TYPE_SYSCTRL,
} LOS_PmNodeType;
typedef struct {
UINT32 (*suspend)(UINT32 mode);
VOID (*resume)(UINT32 mode);
} LosPmDevice;
typedef struct {
UINT32 freq; /* The frequency of the low power timer */
VOID (*timerStart)(UINT64); /* Start the low power timer */
VOID (*timerStop)(VOID); /* Stop the low power timer */
UINT64 (*timerCycleGet)(VOID); /* Gets the running time of the low power timer in unit cycle */
VOID (*tickLock)(VOID); /* Pause the system tick timer */
VOID (*tickUnlock)(VOID); /* Restore the system tick timer */
} LosPmTickTimer;
typedef struct {
UINT32 (*normalSuspend)(VOID);
VOID (*normalResume)(VOID);
UINT32 (*lightSuspend)(VOID);
VOID (*lightResume)(VOID);
UINT32 (*deepSuspend)(VOID);
VOID (*deepResume)(VOID);
UINT32 (*shutdownSuspend)(VOID);
VOID (*shutdownResume)(VOID);
} LosPmSysctrl;
/**
* @ingroup los_pm
* @brief Initialize system low power frame.
*
* @par Description:
* This API is used to initialize the system low power frame.
*
* @attention None.
*
* @param None.
*
* @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 OsPmInit(VOID);
/**
* @ingroup los_pm
* @brief Register a power management node.
*
* @par Description:
* This API is used to register a power management node.
*
* @attention None.
*
* @param type [IN] The types supported by the PM module.
* @param node [IN] power management node.
*
* @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_PmUnregister
*/
UINT32 LOS_PmRegister(LOS_PmNodeType type, VOID *node);
/**
* @ingroup los_pm
* @brief Unregister a power management node.
*
* @par Description:
* This API is used to unregister a power management node.
*
* @attention None.
*
* @param type [IN] The types supported by the PM module.
* @param node [IN] power management node.
*
* @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_PmRegister
*/
UINT32 LOS_PmUnregister(LOS_PmNodeType type, VOID *node);
/**
* @ingroup los_pm
* @brief Set the system wake up flag.
*
* @par Description:
* This API is used to set the system wake-up flag.
*
* @attention None.
*
* @param None.
*
* @retval None.
* @par Dependency:
* <ul><li>los_pm.h: the header file that contains the API declaration.</li></ul>
* @see
*/
VOID LOS_PmWakeSet(VOID);
/**
* @ingroup los_pm
* @brief Get the low power mode of the current system.
*
* @par Description:
* This API is used to get the low power mode of the current system.
*
* @attention None.
*
* @param None.
*
* @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_PmModeSet
*/
LOS_SysSleepEnum LOS_PmModeGet(VOID);
/**
* @ingroup los_pm
* @brief Set low power mode.
*
* @par Description:
* This API is used to set low power mode.
*
* @attention None.
*
* @param mode [IN] low power mode.
*
* @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_PmModeGet
*/
UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode);
/**
* @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.
*
* @par Description:
* This API is used to obtain the lock in current mode.
*
* @attention None.
*
* @param name [IN] Who requests 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_PmLockRequest(const CHAR *name);
/**
* @ingroup los_pm
* @brief Release the lock in current mode so that the next time the system enters
* the idle task, it will enter this mode.
*
* @par Description:
* This API is used to release the lock in current mode.
*
* @attention None.
*
* @param name [IN] Who releases 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_PmLockRequest
*/
UINT32 LOS_PmLockRelease(const CHAR *name);
#if (LOSCFG_KERNEL_PM_DEBUG == 1)
/**
* @ingroup los_pm
* @brief Output the locking information of the pm lock.
*
* @par Description:
* This API is used to output the locking information of the pm lock.
*
* @attention None.
*
* @param None.
*
* @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_PmLockRequest
*/
VOID LOS_PmLockInfoShow(VOID);
#endif
#endif
......@@ -49,6 +49,7 @@ static_library("kernel") {
"../components/cpup",
"../components/exchook",
"../components/backtrace",
"../components/power",
"../utils",
"//third_party/bounds_checking_function/include",
]
......
......@@ -40,7 +40,6 @@
#include "los_memory.h"
#include "los_membox.h"
/*lint -save -e40 -e522 -e533*/
UINT32 g_intCount = 0;
......@@ -169,10 +168,6 @@ LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
g_intCount++;
LOS_IntRestore(intSave);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
OsSchedUpdateSleepTime();
#endif
hwiIndex = HalIntNumGet();
OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
......
......@@ -103,15 +103,11 @@ WEAK VOID HalTickUnlock(VOID)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__DSB();
__WFI();
__ISB();
return LOS_OK;
}
......@@ -40,7 +40,6 @@
#include "los_memory.h"
#include "los_membox.h"
/*lint -save -e40 -e522 -e533*/
UINT32 g_intCount = 0;
......@@ -159,10 +158,6 @@ LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
g_intCount++;
LOS_IntRestore(intSave);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
OsSchedUpdateSleepTime();
#endif
hwiIndex = HalIntNumGet();
OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
......
......@@ -102,15 +102,11 @@ WEAK VOID HalTickUnlock(VOID)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__DSB();
__WFI();
__ISB();
return LOS_OK;
}
......@@ -41,7 +41,6 @@
#include "los_memory.h"
#include "los_membox.h"
/*lint -save -e40 -e522 -e533*/
UINT32 g_intCount = 0;
......@@ -168,10 +167,6 @@ LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
LOS_IntRestore(intSave);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
OsSchedUpdateSleepTime();
#endif
hwiIndex = HalIntNumGet();
OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
......
......@@ -102,15 +102,10 @@ WEAK VOID HalTickUnlock(VOID)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__DSB();
__WFI();
__ISB();
return LOS_OK;
}
......@@ -41,7 +41,6 @@
#include "los_memory.h"
#include "los_membox.h"
/*lint -save -e40 -e522 -e533*/
UINT32 g_intCount = 0;
......@@ -168,10 +167,6 @@ LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
LOS_IntRestore(intSave);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
OsSchedUpdateSleepTime();
#endif
hwiIndex = HalIntNumGet();
OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
......
......@@ -102,15 +102,11 @@ WEAK VOID HalTickUnlock(VOID)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__DSB();
__WFI();
__ISB();
return LOS_OK;
}
......@@ -40,7 +40,6 @@
#include "los_memory.h"
#include "los_membox.h"
/*lint -save -e40 -e522 -e533*/
UINT32 g_intCount = 0;
......@@ -169,10 +168,6 @@ LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
g_intCount++;
LOS_IntRestore(intSave);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
OsSchedUpdateSleepTime();
#endif
hwiIndex = HalIntNumGet();
OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
......
......@@ -103,16 +103,12 @@ WEAK VOID HalTickUnlock(VOID)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__DSB();
__WFI();
__ISB();
return LOS_OK;
}
......@@ -41,7 +41,6 @@
#include "los_memory.h"
#include "los_membox.h"
/*lint -save -e40 -e522 -e533*/
UINT32 g_intCount = 0;
......@@ -172,10 +171,6 @@ LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
LOS_IntRestore(intSave);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
OsSchedUpdateSleepTime();
#endif
hwiIndex = HalIntNumGet();
OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
......
......@@ -103,16 +103,11 @@ WEAK VOID HalTickUnlock(VOID)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__DSB();
__WFI();
__ISB();
}
return LOS_OK;
}
......@@ -40,7 +40,6 @@
#include "los_memory.h"
#include "los_membox.h"
/*lint -save -e40 -e522 -e533*/
UINT32 g_intCount = 0;
......@@ -159,10 +158,6 @@ LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
g_intCount++;
LOS_IntRestore(intSave);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
OsSchedUpdateSleepTime();
#endif
hwiIndex = HalIntNumGet();
OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
......
......@@ -102,15 +102,11 @@ WEAK VOID HalTickUnlock(VOID)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__DSB();
__WFI();
__ISB();
return LOS_OK;
}
......@@ -41,7 +41,6 @@
#include "los_memory.h"
#include "los_membox.h"
/*lint -save -e40 -e522 -e533*/
UINT32 g_intCount = 0;
......@@ -168,10 +167,6 @@ LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
LOS_IntRestore(intSave);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
OsSchedUpdateSleepTime();
#endif
hwiIndex = HalIntNumGet();
OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
......
......@@ -102,15 +102,11 @@ WEAK VOID HalTickUnlock(VOID)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__DSB();
__WFI();
__ISB();
return LOS_OK;
}
......@@ -52,20 +52,11 @@ extern "C" {
#define RTC_CALIBRATE_SLEEP_TIME 8
#define MACHINE_CYCLE_DEALAY_TIMES (LOSCFG_BASE_CORE_TICK_PER_SECOND << 2)
typedef enum {
OS_SYS_NORMAL_SLEEP = 0,
OS_SYS_DEEP_SLEEP,
} LOS_SysSleepEnum;
VOID HalTickLock(VOID);
VOID HalTickUnlock(VOID);
BOOL HalGetSysSleepFlag(VOID);
VOID HalClearSysSleepFlag(VOID);
VOID HalEnterSleep(LOS_SysSleepEnum sleep);
UINT32 HalEnterSleep(VOID);
/**
* @ingroup los_timer
......
......@@ -109,16 +109,11 @@ WEAK VOID HalTickUnlock(VOID)
SysTimer_Start();
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
__WFI();
return LOS_OK;
}
#ifdef __cplusplus
......
......@@ -76,14 +76,10 @@ WEAK UINT64 HalGetTickCycle(UINT32 *period)
return OS_COMBINED_64(timerH, timerL);
}
VOID HalEnterSleep(LOS_SysSleepEnum sleep)
UINT32 HalEnterSleep(VOID)
{
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
if (sleep == OS_SYS_DEEP_SLEEP) {
OsSchedToSleep();
}
#endif
wfi();
return LOS_OK;
}
......@@ -634,10 +634,34 @@ extern UINT8 *m_aucSysMem0;
/**
* @ingroup los_config
* When the tick timer is a non-64/128-bit timer, it has ultra-low power compensation.
* Configuration item for low power frame tailoring
*/
#ifndef LOSCFG_BASE_CORE_SCHED_SLEEP
#define LOSCFG_BASE_CORE_SCHED_SLEEP 0
#ifndef LOSCFG_KERNEL_PM
#define LOSCFG_KERNEL_PM 1
#endif
/**
* @ingroup los_config
* Configuration item for priority of low-power task.
*/
#ifndef LOSCFG_KERNEL_PM_TASK_PTIORITY
#define LOSCFG_KERNEL_PM_TASK_PTIORITY 1
#endif
/**
* @ingroup los_config
* Configuration item for stack size of low-power task.
*/
#ifndef LOSCFG_KERNEL_PM_TASK_STACKSIZE
#define LOSCFG_KERNEL_PM_TASK_STACKSIZE 0x800
#endif
/**
* @ingroup los_config
* Configuration item for low power frame debug tailoring
*/
#ifndef LOSCFG_KERNEL_PM_DEBUG
#define LOSCFG_KERNEL_PM_DEBUG 0
#endif
/**
......
......@@ -53,7 +53,7 @@ VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask);
UINT32 OsSchedSwtmrScanRegister(SchedScan func);
VOID OsSchedUpdateExpireTime(UINT64 startTime);
VOID OsSchedUpdateExpireTime(UINT64 startTime, BOOL timeUpdate);
VOID OsSchedTaskDeQueue(LosTaskCB *taskCB);
......@@ -81,26 +81,63 @@ BOOL OsSchedTaskSwitch(VOID);
LosTaskCB *OsGetTopTask(VOID);
extern VOID LOS_SchedTickHandler(VOID);
extern VOID LOS_Schedule(VOID);
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
VOID OsSchedUpdateSleepTime(VOID);
VOID OsSchedToSleep(VOID);
typedef UINT32 (*SchedSleepInit)(VOID);
UINT32 OsSchedRealSleepTimeSet(VOID (*func)(UINT64));
typedef VOID (*SchedSleepStart)(UINT64);
VOID OsSchedTimerBaseReset(UINT64 currTime);
typedef VOID (*SchedSleepStop)(VOID);
/**
* @ingroup los_sched
* @brief Get the time, in nanoseconds, remaining before the next tick interrupt response.
*
* @par Description:
* This API is used to get the time, in nanoseconds, remaining before the next tick interrupt response.
*
* @attention None.
*
* @param None.
*
* @retval #time, in nanoseconds.
* @par Dependency:
* <ul><li>los_sched.h: the header file that contains the API declaration.</li></ul>
* @see
*/
extern UINT64 LOS_SchedTickTimeoutNsGet(VOID);
typedef UINT64 (*SchedSleepGetSleepTimeNs)(VOID);
/**
* @ingroup los_sched
* @brief The system-provided tick interrupt handler.
*
* @par Description:
* This API is used to wake up a task that is blocked by time.
*
* @attention None.
*
* @param None.
*
* @retval None.
* @par Dependency:
* <ul><li>los_sched.h: the header file that contains the API declaration.</li></ul>
* @see
*/
extern VOID LOS_SchedTickHandler(VOID);
extern UINT32 LOS_SchedSleepInit(SchedSleepInit init, SchedSleepStart start,
SchedSleepStop stop, SchedSleepGetSleepTimeNs getTime);
#endif
/**
* @ingroup los_sched
* @brief Trigger a system dispatch.
*
* @par Description:
* This API is used to trigger a system dispatch.
*
* @attention None.
*
* @param None.
*
* @retval None.
* @par Dependency:
* <ul><li>los_sched.h: the header file that contains the API declaration.</li></ul>
* @see
*/
extern VOID LOS_Schedule(VOID);
#ifdef __cplusplus
#if __cplusplus
......
......@@ -1636,6 +1636,8 @@ extern UINT32 OsGetAllTskInfo(VOID);
extern VOID *OsTskUserStackInit(VOID* stackPtr, VOID* userSP, UINT32 userStackSize);
extern UINT32 OsPmEnterHandlerSet(VOID (*func)(BOOL));
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -124,6 +124,12 @@ extern UINT64 LOS_SysCycleGet(VOID);
#define OS_NS_PER_TICK (OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND)
#define OS_SYS_CYCLE_TO_NS(cycle, freq) (((cycle) / (freq)) * OS_SYS_NS_PER_SECOND + \
((cycle) % OS_SYS_CLOCK) * OS_SYS_NS_PER_SECOND / (freq))
#define OS_SYS_NS_TO_CYCLE(time, freq) (((time) / OS_SYS_NS_PER_SECOND) * (freq) + \
(time % OS_SYS_NS_PER_SECOND) * (freq) / OS_SYS_NS_PER_SECOND)
/**
* @ingroup los_tick
* System time basic function error code: Null pointer.
......
......@@ -62,6 +62,9 @@
#include "los_backtrace.h"
#endif
#if (LOSCFG_KERNEL_PM == 1)
#include "los_pm.h"
#endif
/*****************************************************************************
Function : LOS_Reboot
......@@ -191,6 +194,14 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_KernelInit(VOID)
}
#endif
#if (LOSCFG_KERNEL_PM == 1)
ret = OsPmInit();
if (ret != LOS_OK) {
PRINT_ERR("Pm init failed!\n");
return ret;
}
#endif
#ifdef LOSCFG_TEST
//ret = los_TestInit();
//if (ret != LOS_OK) {
......
......@@ -59,19 +59,17 @@ STATIC UINT32 g_queueBitmap;
STATIC UINT32 g_schedResponseID = 0;
STATIC UINT64 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
typedef struct {
SchedSleepInit init;
SchedSleepStart start;
SchedSleepStop stop;
SchedSleepGetSleepTimeNs getTimeNs;
} SchedSleep;
STATIC BOOL g_schedSleepFlags = FALSE;
STATIC UINT64 g_schedSleepTime;
STATIC UINT64 g_schedEntrySleepTime;
STATIC SchedSleep g_schedSleepCB;
#endif
STATIC VOID (*SchedRealSleepTimeSet)(UINT64) = NULL;
UINT32 OsSchedRealSleepTimeSet(VOID (*func)(UINT64))
{
if (func == NULL) {
return LOS_NOK;
}
SchedRealSleepTimeSet = func;
return LOS_OK;
}
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
STATIC UINT64 g_schedTimerBase;
......@@ -83,6 +81,14 @@ VOID OsSchedUpdateSchedTimeBase(VOID)
(VOID)HalGetTickCycle(&period);
g_schedTimerBase += period;
}
VOID OsSchedTimerBaseReset(UINT64 currTime)
{
LOS_ASSERT(currTime > g_schedTimerBase);
g_schedTimerBase = currTime;
g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
}
#endif
UINT64 OsGetCurrSchedTimeCycle(VOID)
......@@ -124,7 +130,7 @@ STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime)
taskCB->startTime = currTime;
}
STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime)
STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, BOOL timeUpdate)
{
UINT64 nextExpireTime = OsGetNextExpireTime(startTime);
UINT64 nextResponseTime;
......@@ -141,15 +147,15 @@ STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID,
if ((g_schedResponseTime > nextExpireTime) && ((g_schedResponseTime - nextExpireTime) >= OS_CYCLE_PER_TICK)) {
nextResponseTime = nextExpireTime - startTime;
if (nextResponseTime > OS_TICK_RESPONSE_TIME_MAX) {
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
g_schedSleepTime = nextResponseTime - OS_CYCLE_PER_TICK;
#endif
if (SchedRealSleepTimeSet != NULL) {
SchedRealSleepTimeSet(nextResponseTime);
}
nextResponseTime = OS_TICK_RESPONSE_TIME_MAX;
nextExpireTime = startTime + nextResponseTime;
} else if (nextResponseTime < OS_CYCLE_PER_TICK) {
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
g_schedSleepTime = 0;
#endif
if (SchedRealSleepTimeSet != NULL) {
SchedRealSleepTimeSet(0);
}
nextResponseTime = OS_CYCLE_PER_TICK;
nextExpireTime = startTime + nextResponseTime;
if (nextExpireTime >= g_schedResponseTime) {
......@@ -170,12 +176,14 @@ STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID,
g_schedResponseTime = nextExpireTime;
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
g_schedTimerBase = OsGetCurrSchedTimeCycle();
if (timeUpdate) {
g_schedTimerBase = OsGetCurrSchedTimeCycle();
}
#endif
HalSysTickReload(nextResponseTime);
}
VOID OsSchedUpdateExpireTime(UINT64 startTime)
VOID OsSchedUpdateExpireTime(UINT64 startTime, BOOL timeUpdate)
{
UINT64 endTime;
LosTaskCB *runTask = g_losTask.runTask;
......@@ -186,7 +194,7 @@ VOID OsSchedUpdateExpireTime(UINT64 startTime)
} else {
endTime = OS_SCHED_MAX_RESPONSE_TIME;
}
OsSchedSetNextExpireTime(startTime, runTask->taskID, endTime);
OsSchedSetNextExpireTime(startTime, runTask->taskID, endTime, timeUpdate);
}
STATIC INLINE VOID OsSchedPriQueueEnHead(LOS_DL_LIST *priqueueItem, UINT32 priority)
......@@ -450,7 +458,7 @@ VOID OsSchedStart(VOID)
g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
g_schedResponseID = OS_INVALID;
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, newTask->startTime + newTask->timeSlice);
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, newTask->startTime + newTask->timeSlice, TRUE);
PRINTK("Entering scheduler\n");
}
......@@ -490,11 +498,31 @@ BOOL OsSchedTaskSwitch(VOID)
} else {
endTime = OS_SCHED_MAX_RESPONSE_TIME;
}
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, endTime);
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, endTime, TRUE);
return isTaskSwitch;
}
UINT64 LOS_SchedTickTimeoutNsGet(VOID)
{
UINT32 intSave;
UINT64 responseTime;
UINT64 currTime;
intSave = LOS_IntLock();
responseTime = g_schedResponseTime;
currTime = OsGetCurrSchedTimeCycle();
LOS_IntRestore(intSave);
if (responseTime > currTime) {
responseTime = responseTime - currTime;
} else {
responseTime = 0; /* Tick interrupt already timeout */
}
return OS_SYS_CYCLE_TO_NS(responseTime, OS_SYS_CLOCK);
}
VOID LOS_SchedTickHandler(VOID)
{
UINT64 currTime;
......@@ -518,7 +546,7 @@ VOID LOS_SchedTickHandler(VOID)
} else {
currTime = OsGetCurrSchedTimeCycle();
OsTimeSliceUpdate(g_losTask.runTask, currTime);
OsSchedUpdateExpireTime(currTime);
OsSchedUpdateExpireTime(currTime, TRUE);
}
LOS_IntRestore(intSave);
......@@ -531,103 +559,6 @@ VOID LOS_Schedule(VOID)
}
}
#if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
VOID OsSchedUpdateSleepTime(VOID)
{
UINT64 nextResponseTime;
UINT64 currTime, realSleepTime;
UINT32 intSave;
if ((g_schedSleepFlags == FALSE) || (g_schedSleepCB.stop == NULL)) {
return;
}
intSave = LOS_IntLock();
if (g_schedSleepCB.getTimeNs != NULL) {
realSleepTime = g_schedSleepCB.getTimeNs();
realSleepTime = (realSleepTime / OS_SYS_NS_PER_SECOND) * OS_SYS_CLOCK +
(realSleepTime % OS_SYS_NS_PER_SECOND) * OS_SYS_CLOCK / OS_SYS_NS_PER_SECOND;
if (realSleepTime < g_schedSleepTime) {
nextResponseTime = g_schedSleepTime - realSleepTime;
} else {
nextResponseTime = 0;
}
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 1)
currTime = HalGetTickCycle(NULL);
#else
g_schedTimerBase = g_schedEntrySleepTime + realSleepTime;
currTime = g_schedTimerBase;
#endif
if (nextResponseTime > OS_TICK_RESPONSE_TIME_MAX) {
nextResponseTime = OS_TICK_RESPONSE_TIME_MAX;
} else if (nextResponseTime < OS_CYCLE_PER_TICK) {
nextResponseTime = OS_CYCLE_PER_TICK;
}
g_schedResponseID = OS_INVALID;
g_schedResponseTime = currTime + nextResponseTime;
HalSysTickReload(nextResponseTime);
g_schedSleepTime = 0;
}
g_schedSleepFlags = FALSE;
g_schedSleepCB.stop();
LOS_IntRestore(intSave);
}
VOID OsSchedToSleep(VOID)
{
UINT32 intSave;
UINT64 sleepTime;
if (g_schedSleepCB.start == NULL) {
return;
}
if (g_schedSleepCB.getTimeNs != NULL) {
sleepTime = (g_schedSleepTime / OS_SYS_CLOCK) * OS_SYS_NS_PER_SECOND +
(g_schedSleepTime % OS_SYS_CLOCK) * OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK;
if (sleepTime == 0) {
return;
}
intSave = LOS_IntLock();
HalTickLock();
g_schedEntrySleepTime = OsGetCurrSchedTimeCycle();
} else {
intSave = LOS_IntLock();
}
g_schedSleepCB.start(sleepTime);
g_schedSleepFlags = TRUE;
LOS_IntRestore(intSave);
}
UINT32 LOS_SchedSleepInit(SchedSleepInit init, SchedSleepStart start,
SchedSleepStop stop, SchedSleepGetSleepTimeNs getTime)
{
UINT32 ret;
if ((init == NULL) && (start == NULL) && (stop == NULL)) {
return LOS_NOK;
}
g_schedSleepCB.init = init;
g_schedSleepCB.start = start;
g_schedSleepCB.stop = stop;
g_schedSleepCB.getTimeNs = getTime;
if (g_schedSleepCB.init != NULL) {
ret = g_schedSleepCB.init();
if (ret != LOS_OK) {
return ret;
}
}
return LOS_OK;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -217,7 +217,7 @@ LITE_OS_SEC_TEXT VOID OsSwtmrStart(SWTMR_CTRL_S *swtmr)
#endif
OsAdd2SortLink(&swtmr->stSortList, currTime, swtmr->uwCount, OS_SORT_LINK_SWTMR);
if (LOS_TaskIsRunning()) {
OsSchedUpdateExpireTime(currTime);
OsSchedUpdateExpireTime(currTime, TRUE);
}
}
......@@ -248,7 +248,7 @@ LITE_OS_SEC_TEXT VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr)
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
if (LOS_TaskIsRunning()) {
OsSchedUpdateExpireTime(OsGetCurrSchedTimeCycle());
OsSchedUpdateExpireTime(OsGetCurrSchedTimeCycle(), TRUE);
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned = 0;
#endif
......
......@@ -45,7 +45,6 @@
#include "los_cpup.h"
#endif
/**
* @ingroup los_task
* @brief Convenience macro for bitwise operation of task module
......@@ -102,6 +101,8 @@ LITE_OS_SEC_DATA_INIT LOS_DL_LIST g_losFreeTask;
LITE_OS_SEC_DATA_INIT LOS_DL_LIST g_taskRecyleList;
LITE_OS_SEC_BSS BOOL g_taskScheduled = FALSE;
STATIC VOID (*PmEnter)(BOOL isIdle) = NULL;
#if (LOSCFG_BASE_CORE_TSK_MONITOR == 1)
TSKSWITCHHOOK g_pfnUsrTskSwitchHook = NULL;
#endif /* LOSCFG_BASE_CORE_TSK_MONITOR == 1 */
......@@ -145,6 +146,16 @@ STATIC VOID OsRecyleFinishedTask(VOID)
LOS_IntRestore(intSave);
}
UINT32 OsPmEnterHandlerSet(VOID (*func)(BOOL))
{
if (func == NULL) {
return LOS_NOK;
}
PmEnter = func;
return LOS_OK;
}
/*****************************************************************************
Function : OsIdleTask
Description : Idle task.
......@@ -152,11 +163,16 @@ STATIC VOID OsRecyleFinishedTask(VOID)
Output : None
Return : None
*****************************************************************************/
LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID)
LITE_OS_SEC_TEXT VOID OsIdleTask(VOID)
{
while (1) {
OsRecyleFinishedTask();
HalEnterSleep(OS_SYS_DEEP_SLEEP);
if (PmEnter != NULL) {
PmEnter(TRUE);
} else {
(VOID)HalEnterSleep();
}
}
}
......
......@@ -52,7 +52,6 @@ extern "C" {
#define LOSCFG_BASE_CORE_TICK_PER_SECOND (1000UL)
#define LOSCFG_BASE_CORE_TICK_HW_TIME 0
#define LOSCFG_BASE_CORE_TICK_WTIMER 1
#define LOSCFG_BASE_CORE_SCHED_SLEEP 1
/*=============================================================================
Hardware interrupt module configuration
=============================================================================*/
......
......@@ -52,7 +52,6 @@ extern "C" {
#define LOSCFG_BASE_CORE_TICK_PER_SECOND (1000UL)
#define LOSCFG_BASE_CORE_TICK_HW_TIME 0
#define LOSCFG_BASE_CORE_TICK_WTIMER 1
#define LOSCFG_BASE_CORE_SCHED_SLEEP 1
/*=============================================================================
Hardware interrupt module configuration
=============================================================================*/
......
......@@ -204,6 +204,7 @@ enum LOS_MODULE_ID {
LOS_MOD_MUX = 0X1d,
LOS_MOD_CPUP = 0x1e,
LOS_MOD_HOOK = 0x1f,
LOS_MOD_PM = 0x20,
LOS_MOD_SHELL = 0x31,
LOS_MOD_BUTT
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册