power_mgmt:sample:Power Manager application

Sample implementation of a power manager app that uses the zephyr
power management infrastructure. This app demonstrates use of the
hooks to implement Low Power State and Tickless idle power saving
policies.

Tested on quark_se.

Origin: Original
Change-Id: I10207014f2a844374b4c7a1c0ed50f2fb5c3c440
Signed-off-by: Ramesh Thomas <ramesh.thomas@intel.com>
Signed-off-by: Sergio Rodriguez <sergio.sf.rodriguez@intel.com>
This commit is contained in:
Ramesh Thomas 2016-02-16 17:53:22 -08:00 committed by Gerrit Code Review
commit 58d71d4efb
7 changed files with 243 additions and 0 deletions

View file

@ -0,0 +1,6 @@
MDEF_FILE = prj.mdef
KERNEL_TYPE = micro
BOARD ?= quark_se_devboard
CONF_FILE = prj.conf
include ${ZEPHYR_BASE}/Makefile.inc

View file

@ -0,0 +1,56 @@
Title: Power management demo
Description:
A sample implementation of a power manager app that uses the zephyr
power management infrastructure.
This app will cycle through the various power schemes at every call
to _sys_soc_suspend() hook function.
It will cycle through following states
1. Low Power State (LPS) - puts the CPU in C2 state
2. Tickless Idle - demonstrates hooks into tickless idle entry and exit
3. No-op - no operation and letting kernel do its idle
--------------------------------------------------------------------------------
Building and Running Project:
This application is architecture and SoC specific. It is written for x86
architecture and uses features specific to quark_se platforms.
This is a microkernel only project since the zephyr power management
infrastructure currently is only microkernel idle based. In future, when
nanokernel idle is supported, a separate nanokernel app would be created.
make BOARD=<quark_se board>
--------------------------------------------------------------------------------
Troubleshooting:
Problems caused by out-dated project information can be addressed by
issuing one of the following commands then rebuilding the project:
make clean # discard results of previous builds
# but keep existing configuration info
or
make pristine # discard results of previous builds
# and restore pre-defined configuration info
--------------------------------------------------------------------------------
Sample Output:
Power Management Demo
Going to low power state!
Resume from low power state
Total Elapsed From Suspend To Resume = 163838 RTC Cycles
Tickless idle power saving!
Exit from tickless idle
Total Elapsed From Suspend To Tickless Resume = 163838 RTC Cycles
...

View file

@ -0,0 +1,5 @@
CONFIG_ADVANCED_POWER_MANAGEMENT=y
CONFIG_ADVANCED_IDLE=y
CONFIG_TICKLESS_IDLE=y
CONFIG_RTC=y
CONFIG_STDOUT_CONSOLE=y

View file

@ -0,0 +1,5 @@
% Application : Power Management demo
% TASK NAME PRIO ENTRY STACK GROUPS
% ==================================
TASK TASKA 7 main 2048 [EXE]

View file

@ -0,0 +1 @@
obj-y = main.o

View file

@ -0,0 +1,165 @@
/*
* Copyright (c) 2016 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zephyr.h>
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT printf
#else
#include <misc/printk.h>
#define PRINT printk
#endif
#include <rtc.h>
#define SLEEPTICKS SECONDS(5)
#define P_LVL2 0xb0800504
static int pm_state; /* 1 = LPS; 2 = Tickless Idle */
static void quark_low_power(void);
static struct device *rtc_dev;
static uint32_t start_time, end_time;
void main(void)
{
struct rtc_config config;
PRINT("Power Management Demo\n");
config.init_val = 0;
config.alarm_enable = 0;
config.alarm_val = RTC_ALARM_SECOND;
config.cb_fn = NULL;
rtc_dev = device_get_binding(CONFIG_RTC_DRV_NAME);
rtc_enable(rtc_dev);
rtc_set_config(rtc_dev, &config);
while (1) {
task_sleep(SLEEPTICKS);
}
}
static int check_pm_policy(int32_t ticks)
{
static int policy;
/*
* Compare time available with wake latencies and select
* appropriate power saving policy
*
* For the demo we will alternate between following states
*
* 0 = no power saving operation
* 1 = low power state
* 2 = tickless idle power saving
*
*/
policy = (policy > 2 ? 0 : policy);
return policy++;
}
static int do_low_power(int32_t ticks)
{
PRINT("\n\nGoing to low power state!\n");
/* Turn off peripherals/clocks here */
quark_low_power();
return 1; /* non-zero so kernel does not do idle wait */
}
static int do_tickless_idle(int32_t ticks)
{
PRINT("Tickless idle power saving!\n");
/* Turn off peripherals/clocks here */
return 0; /* zero to let kernel do idle wait */
}
int _sys_soc_suspend(int32_t ticks)
{
int ret = 0;
pm_state = check_pm_policy(ticks);
switch (pm_state) {
case 1:
start_time = rtc_read(rtc_dev);
ret = do_low_power(ticks);
break;
case 2:
start_time = rtc_read(rtc_dev);
ret = do_tickless_idle(ticks);
break;
default:
/* No PM operations */
ret = 0;
break;
}
return ret;
}
static void low_power_resume(void)
{
end_time = rtc_read(rtc_dev);
PRINT("\nResume from low power state\n");
PRINT("Total Elapsed From Suspend To Resume = %d RTC Cycles\n",
end_time - start_time);
}
static void tickless_idle_resume(void)
{
end_time = rtc_read(rtc_dev);
PRINT("\nExit from tickless idle\n");
PRINT("Total Elapsed From Suspend To Tickless Resume = %d RTC Cycles\n",
end_time - start_time);
}
void _sys_soc_resume(void)
{
switch (pm_state) {
case 1:
low_power_resume();
break;
case 2:
tickless_idle_resume();
break;
default:
break;
}
pm_state = 0;
}
static void quark_low_power(void)
{
__asm__ volatile (
"sti\n\t"
/*
* Atomically enable interrupts and enter LPS.
*
* Reading P_LVL2 causes C2 transition.
*/
"movl (%%eax), %%eax\n\t"
::"a"(P_LVL2));
}

View file

@ -0,0 +1,5 @@
[test]
build_only = true
tags = apps
arch_whitelist = x86
platform_whitelist = quark_se_devboard arduino_101