samples: boards: mec15xxevb: Power management tests
Sample code that demonstrates power management features on MEC15xx-based boards. It showcases how an app can enter into light and deep sleep. Signed-off-by: Jose Alberto Meza <jose.a.meza.arellano@intel.com>
This commit is contained in:
parent
2215d21104
commit
8b14807e55
10
samples/boards/mec15xxevb_assy6853/mec15xxevb_assy6853.rst
Normal file
10
samples/boards/mec15xxevb_assy6853/mec15xxevb_assy6853.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
.. mec15xxevb_assy6853-samples:
|
||||
|
||||
MEC15xxEVB Reference Board Samples
|
||||
##################################
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
**/*
|
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(mec15_brd_test)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
|
@ -0,0 +1,32 @@
|
|||
.. mec15xxevb-sample:
|
||||
|
||||
MEC15xx sample board test application
|
||||
#####################################
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This sample demonstrates power management features on MEC15xx-based boards.
|
||||
It showcase simple app that allows to enter into light and deep sleep.
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
The sample can be built and executed on boards using west.
|
||||
No pins configurations, except GPIO014 is used as indicator for entry/exit.
|
||||
|
||||
|
||||
Sample output
|
||||
=============
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
Wake from Light Sleep
|
||||
Wake from Deep Sleep
|
||||
ResumeBBBAA
|
||||
Wake from Light Sleep
|
||||
Suspend...
|
||||
Wake from Deep Sleep
|
||||
ResumeBBBAA
|
||||
|
||||
note:: The values shown above might differ.
|
11
samples/boards/mec15xxevb_assy6853/power_management/prj.conf
Normal file
11
samples/boards/mec15xxevb_assy6853/power_management/prj.conf
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Enable config log
|
||||
CONFIG_LOG=y
|
||||
|
||||
# Logging thread frequency higher than CONFIG_SYS_PM_MIN_RESIDENCY_DEEP_SLEEP_1
|
||||
CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=2100
|
||||
|
||||
# Enable kernel debug
|
||||
CONFIG_KERNEL_DEBUG=y
|
||||
CONFIG_THREAD_NAME=y
|
||||
# Enable PM debug in MEC1501 this will give indication in MCHP_060
|
||||
CONFIG_SYS_PM_DEBUG=y
|
|
@ -0,0 +1,6 @@
|
|||
sample:
|
||||
name: MEC150x board sample power management tests
|
||||
tests:
|
||||
sample.board.mec15xxevb_assy6853:
|
||||
platform_whitelist: mec15xxevb_assy6853
|
||||
tags: board
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_LEVEL LOG_LEVEL_INF
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(mec15_brd_test);
|
||||
#include "power_mgmt.h"
|
||||
|
||||
|
||||
void main(void)
|
||||
{
|
||||
test_pwr_mgmt_singlethread(false, 10);
|
||||
|
||||
test_pwr_mgmt_singlethread(true, 10);
|
||||
|
||||
test_pwr_mgmt_multithread(false, 10);
|
||||
|
||||
test_pwr_mgmt_multithread(true, 10);
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <soc.h>
|
||||
#include <power/power.h>
|
||||
#include <logging/log.h>
|
||||
#define LOG_LEVEL LOG_LEVEL_DBG
|
||||
LOG_MODULE_REGISTER(pwrmgmt_test);
|
||||
|
||||
|
||||
#define SLP_STATES_SUPPORTED 2
|
||||
|
||||
/* Thread properties */
|
||||
#define TASK_STACK_SIZE 1024
|
||||
#define PRIORITY K_PRIO_COOP(5)
|
||||
/* Thread sleep should be lower than CONFIG_SYS_PM_MIN_RESIDENCY_SLEEP_1 */
|
||||
#define THREAD_A_SLEEP_TIME 100
|
||||
#define THREAD_B_SLEEP_TIME 1000
|
||||
|
||||
K_THREAD_STACK_DEFINE(stackA, TASK_STACK_SIZE);
|
||||
K_THREAD_STACK_DEFINE(stackB, TASK_STACK_SIZE);
|
||||
|
||||
static struct k_thread threadA_id;
|
||||
static struct k_thread threadB_id;
|
||||
|
||||
struct pm_counter {
|
||||
u8_t entry_cnt;
|
||||
u8_t exit_cnt;
|
||||
};
|
||||
|
||||
struct pm_counter pm_counters[SLP_STATES_SUPPORTED];
|
||||
|
||||
/* Hooks to count entry/exit */
|
||||
void sys_pm_notify_power_state_entry(enum power_states state)
|
||||
{
|
||||
switch (state) {
|
||||
case SYS_POWER_STATE_SLEEP_1:
|
||||
pm_counters[0].entry_cnt++;
|
||||
break;
|
||||
case SYS_POWER_STATE_DEEP_SLEEP_1:
|
||||
pm_counters[1].entry_cnt++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sys_pm_notify_power_state_exit(enum power_states state)
|
||||
{
|
||||
switch (state) {
|
||||
case SYS_POWER_STATE_SLEEP_1:
|
||||
pm_counters[0].exit_cnt++;
|
||||
break;
|
||||
case SYS_POWER_STATE_DEEP_SLEEP_1:
|
||||
pm_counters[1].exit_cnt++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pm_reset_counters(void)
|
||||
{
|
||||
for (int i = 0; i < SLP_STATES_SUPPORTED; i++) {
|
||||
printk("[%d] PM entry %d\n", i, pm_counters[i].entry_cnt);
|
||||
printk("[%d] PM exit %d\n", i, pm_counters[i].exit_cnt);
|
||||
pm_counters[i].entry_cnt = 0;
|
||||
pm_counters[i].exit_cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void pm_entry_marker(void)
|
||||
{
|
||||
/* Directly access a pin */
|
||||
GPIO_CTRL_REGS->CTRL_0014 = 0x00240UL;
|
||||
printk("PM >\n");
|
||||
}
|
||||
|
||||
static void pm_exit_marker(void)
|
||||
{
|
||||
/* Directly access a pin */
|
||||
GPIO_CTRL_REGS->CTRL_0014 = 0x10240UL;
|
||||
printk("PM <\n");
|
||||
}
|
||||
|
||||
static int taskA_init(void)
|
||||
{
|
||||
LOG_INF("Thread task A init");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int taskB_init(void)
|
||||
{
|
||||
printk("Thread task B init");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void taskA_thread(void *p1, void *p2, void *p3)
|
||||
{
|
||||
while (true) {
|
||||
k_sleep(THREAD_A_SLEEP_TIME);
|
||||
printk("A");
|
||||
}
|
||||
}
|
||||
|
||||
static void taskB_thread(void *p1, void *p2, void *p3)
|
||||
{
|
||||
while (true) {
|
||||
k_sleep(THREAD_B_SLEEP_TIME);
|
||||
printk("B");
|
||||
}
|
||||
}
|
||||
|
||||
static void create_tasks(void)
|
||||
{
|
||||
taskA_init();
|
||||
taskB_init();
|
||||
|
||||
k_thread_create(&threadA_id, stackA, TASK_STACK_SIZE, taskA_thread,
|
||||
NULL, NULL, NULL, PRIORITY, K_INHERIT_PERMS, K_FOREVER);
|
||||
k_thread_create(&threadB_id, stackB, TASK_STACK_SIZE, taskB_thread,
|
||||
NULL, NULL, NULL, PRIORITY, K_INHERIT_PERMS, K_FOREVER);
|
||||
|
||||
k_thread_start(&threadA_id);
|
||||
k_thread_start(&threadB_id);
|
||||
|
||||
}
|
||||
|
||||
static void suspend_all_tasks(void)
|
||||
{
|
||||
k_thread_suspend(&threadA_id);
|
||||
k_thread_suspend(&threadB_id);
|
||||
}
|
||||
|
||||
static void resume_all_tasks(void)
|
||||
{
|
||||
k_thread_resume(&threadA_id);
|
||||
k_thread_resume(&threadB_id);
|
||||
}
|
||||
|
||||
int test_pwr_mgmt_multithread(bool use_logging, u8_t cycles)
|
||||
{
|
||||
|
||||
/* Ensure we can enter deep sleep when stopping threads
|
||||
* No UART output should occurr when threads are suspended
|
||||
* Test to verify Zephyr RTOS issue #20033
|
||||
* https://github.com/zephyrproject-rtos/zephyr/issues/20033
|
||||
*/
|
||||
|
||||
create_tasks();
|
||||
|
||||
pm_exit_marker();
|
||||
|
||||
while (cycles-- > 0) {
|
||||
k_sleep(CONFIG_SYS_PM_MIN_RESIDENCY_SLEEP_1 + 500);
|
||||
|
||||
if (use_logging) {
|
||||
LOG_INF("Wake from Light Sleep\n");
|
||||
} else {
|
||||
printk("Wake from Light Sleep\n");
|
||||
}
|
||||
|
||||
k_busy_wait(100);
|
||||
|
||||
LOG_INF("Suspend...");
|
||||
suspend_all_tasks();
|
||||
|
||||
/* GPIO toggle to measure latency */
|
||||
pm_entry_marker();
|
||||
|
||||
k_sleep(CONFIG_SYS_PM_MIN_RESIDENCY_DEEP_SLEEP_1 + 500);
|
||||
|
||||
k_busy_wait(3000);
|
||||
|
||||
if (use_logging) {
|
||||
LOG_INF("Wake from Deep Sleep\n");
|
||||
} else {
|
||||
printk("Wake from Deep Sleep\n");
|
||||
}
|
||||
|
||||
pm_exit_marker();
|
||||
LOG_INF("Resume");
|
||||
resume_all_tasks();
|
||||
}
|
||||
|
||||
pm_reset_counters();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_pwr_mgmt_singlethread(bool use_logging, u8_t cycles)
|
||||
{
|
||||
pm_exit_marker();
|
||||
|
||||
while (cycles-- > 0) {
|
||||
|
||||
/* Trigger Light Sleep 1 state. 48MHz PLL stays on */
|
||||
k_sleep(CONFIG_SYS_PM_MIN_RESIDENCY_SLEEP_1 + 500);
|
||||
|
||||
if (use_logging) {
|
||||
LOG_INF("Wake from Light Sleep\n");
|
||||
} else {
|
||||
printk("Wake from Light Sleep\n");
|
||||
}
|
||||
|
||||
k_busy_wait(100);
|
||||
|
||||
/* Trigger Deep Sleep 1 state. 48MHz PLL off */
|
||||
|
||||
LOG_INF("About to sleep for enough time for Deep Sleep\n");
|
||||
|
||||
/* GPIO toggle to measure latency */
|
||||
pm_entry_marker();
|
||||
|
||||
k_sleep(CONFIG_SYS_PM_MIN_RESIDENCY_DEEP_SLEEP_1 + 1000);
|
||||
|
||||
k_busy_wait(3000);
|
||||
|
||||
if (use_logging) {
|
||||
LOG_INF("Wake from Deep Sleep\n");
|
||||
} else {
|
||||
printk("Wake from Deep Sleep\n");
|
||||
}
|
||||
|
||||
pm_exit_marker();
|
||||
}
|
||||
|
||||
pm_reset_counters();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __TEST_PWRMGMT_H__
|
||||
#define __TEST_PWRMGMT_H__
|
||||
|
||||
|
||||
/** @brief Alternates between light and deep sleep cycles.
|
||||
*
|
||||
* For light sleep, the test sleeps in main thread for 500 ms longer than
|
||||
* CONFIG_SYS_PM_MIN_RESIDENCY_SLEEP_1.
|
||||
*
|
||||
* Similarly for deep sleep, the test sleeps in the main thread for 500 ms
|
||||
* longer than CONFIG_SYS_PM_MIN_RESIDENCY_DEEP_SLEEP_1.
|
||||
*
|
||||
* @param use_logging test progress will be reported using logging,
|
||||
* otherwise printk.
|
||||
* @param cycles to repeat the cycle described above.
|
||||
* @retval 0 if successful, errno otherwise.
|
||||
*/
|
||||
int test_pwr_mgmt_singlethread(bool use_logging, u8_t cycles);
|
||||
|
||||
/** @brief Alternates between light and deep sleep cycles.
|
||||
*
|
||||
* Performs same approach to achieve light and deep sleep, but additional
|
||||
* it suspend all threads within the app.
|
||||
*
|
||||
* @param use_logging test progress will be reported using logging,
|
||||
* otherwise printk.
|
||||
* @param cycles to repeat the cycle described above.
|
||||
* @retval 0 if successful, errno otherwise.
|
||||
*/
|
||||
int test_pwr_mgmt_multithread(bool use_logging, u8_t cycles);
|
||||
|
||||
#endif /* __TEST_PWRMGMT_H__ */
|
Loading…
Reference in a new issue