From 8b14807e5540ee9d50ef2ffd867946f526fb9fa9 Mon Sep 17 00:00:00 2001 From: Jose Alberto Meza Date: Mon, 2 Mar 2020 17:18:12 -0800 Subject: [PATCH] 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 --- .../mec15xxevb_assy6853.rst | 10 + .../power_management/CMakeLists.txt | 8 + .../power_management/README.rst | 32 +++ .../power_management/prj.conf | 11 + .../power_management/sample.yaml | 6 + .../power_management/src/main.c | 22 ++ .../power_management/src/power_mgmt.c | 239 ++++++++++++++++++ .../power_management/src/power_mgmt.h | 38 +++ 8 files changed, 366 insertions(+) create mode 100644 samples/boards/mec15xxevb_assy6853/mec15xxevb_assy6853.rst create mode 100644 samples/boards/mec15xxevb_assy6853/power_management/CMakeLists.txt create mode 100644 samples/boards/mec15xxevb_assy6853/power_management/README.rst create mode 100644 samples/boards/mec15xxevb_assy6853/power_management/prj.conf create mode 100644 samples/boards/mec15xxevb_assy6853/power_management/sample.yaml create mode 100644 samples/boards/mec15xxevb_assy6853/power_management/src/main.c create mode 100644 samples/boards/mec15xxevb_assy6853/power_management/src/power_mgmt.c create mode 100644 samples/boards/mec15xxevb_assy6853/power_management/src/power_mgmt.h diff --git a/samples/boards/mec15xxevb_assy6853/mec15xxevb_assy6853.rst b/samples/boards/mec15xxevb_assy6853/mec15xxevb_assy6853.rst new file mode 100644 index 00000000000..d74a8544276 --- /dev/null +++ b/samples/boards/mec15xxevb_assy6853/mec15xxevb_assy6853.rst @@ -0,0 +1,10 @@ +.. mec15xxevb_assy6853-samples: + +MEC15xxEVB Reference Board Samples +################################## + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/boards/mec15xxevb_assy6853/power_management/CMakeLists.txt b/samples/boards/mec15xxevb_assy6853/power_management/CMakeLists.txt new file mode 100644 index 00000000000..bc7e57584d3 --- /dev/null +++ b/samples/boards/mec15xxevb_assy6853/power_management/CMakeLists.txt @@ -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}) diff --git a/samples/boards/mec15xxevb_assy6853/power_management/README.rst b/samples/boards/mec15xxevb_assy6853/power_management/README.rst new file mode 100644 index 00000000000..5b15f60fc6d --- /dev/null +++ b/samples/boards/mec15xxevb_assy6853/power_management/README.rst @@ -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. diff --git a/samples/boards/mec15xxevb_assy6853/power_management/prj.conf b/samples/boards/mec15xxevb_assy6853/power_management/prj.conf new file mode 100644 index 00000000000..328bcabbec2 --- /dev/null +++ b/samples/boards/mec15xxevb_assy6853/power_management/prj.conf @@ -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 diff --git a/samples/boards/mec15xxevb_assy6853/power_management/sample.yaml b/samples/boards/mec15xxevb_assy6853/power_management/sample.yaml new file mode 100644 index 00000000000..8e97690b8b4 --- /dev/null +++ b/samples/boards/mec15xxevb_assy6853/power_management/sample.yaml @@ -0,0 +1,6 @@ +sample: + name: MEC150x board sample power management tests +tests: + sample.board.mec15xxevb_assy6853: + platform_whitelist: mec15xxevb_assy6853 + tags: board diff --git a/samples/boards/mec15xxevb_assy6853/power_management/src/main.c b/samples/boards/mec15xxevb_assy6853/power_management/src/main.c new file mode 100644 index 00000000000..16d8393f75f --- /dev/null +++ b/samples/boards/mec15xxevb_assy6853/power_management/src/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_LEVEL LOG_LEVEL_INF +#include +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); +} diff --git a/samples/boards/mec15xxevb_assy6853/power_management/src/power_mgmt.c b/samples/boards/mec15xxevb_assy6853/power_management/src/power_mgmt.c new file mode 100644 index 00000000000..8a794a855ef --- /dev/null +++ b/samples/boards/mec15xxevb_assy6853/power_management/src/power_mgmt.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/samples/boards/mec15xxevb_assy6853/power_management/src/power_mgmt.h b/samples/boards/mec15xxevb_assy6853/power_management/src/power_mgmt.h new file mode 100644 index 00000000000..585726dafe7 --- /dev/null +++ b/samples/boards/mec15xxevb_assy6853/power_management/src/power_mgmt.h @@ -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__ */