1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

Merge pull request #11731 from benemorius/tests-periph_pm-ux

tests/periph_pm: make usage more intuitive and move shell commands to sys/
This commit is contained in:
Alexandre Abadie 2020-04-28 18:52:09 +02:00 committed by GitHub
commit f22529ec71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 243 additions and 121 deletions

View File

@ -49,6 +49,14 @@ extern "C" {
#define PROVIDES_PM_SET_LOWEST #define PROVIDES_PM_SET_LOWEST
#endif #endif
/**
* @brief Power Management mode blocker typedef
*/
typedef union {
uint32_t val_u32; /**< power mode blockers u32 */
uint8_t val_u8[PM_NUM_MODES]; /**< power mode blockers u8 */
} pm_blocker_t;
/** /**
* @brief Block a power mode * @brief Block a power mode
* *

View File

@ -33,14 +33,6 @@
#define PM_BLOCKER_INITIAL 0x01010101 /* block all by default */ #define PM_BLOCKER_INITIAL 0x01010101 /* block all by default */
#endif #endif
/**
* @brief Power Management mode typedef
*/
typedef union {
uint32_t val_u32;
uint8_t val_u8[PM_NUM_MODES];
} pm_blocker_t;
/** /**
* @brief Global variable for keeping track of blocked modes * @brief Global variable for keeping track of blocked modes
*/ */

View File

@ -8,6 +8,9 @@ endif
ifneq (,$(filter mci,$(USEMODULE))) ifneq (,$(filter mci,$(USEMODULE)))
SRC += sc_disk.c SRC += sc_disk.c
endif endif
ifneq (,$(filter periph_pm,$(USEMODULE)))
SRC += sc_pm.c
endif
ifneq (,$(filter ps,$(USEMODULE))) ifneq (,$(filter ps,$(USEMODULE)))
SRC += sc_ps.c SRC += sc_ps.c
endif endif

194
sys/shell/commands/sc_pm.c Normal file
View File

@ -0,0 +1,194 @@
/*
* Copyright (C) 2019 Thomas Stilwell <stilwellt@openlabs.co>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_shell_commands
* @{
*
* @file
* @brief Shell command to interact with the PM subsystem
*
* @author Bas Stottelaar <basstottelaar@gmail.com>
* @author Vincent Dupont <vincent@otakeys.com>
* @author Thomas Stilwell <stilwellt@openlabs.co>
*
* @}
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "periph/pm.h"
#ifdef MODULE_PM_LAYERED
#include "pm_layered.h"
extern volatile pm_blocker_t pm_blocker; /* sys/pm_layered/pm.c */
#endif /* MODULE_PM_LAYERED */
static void _print_usage(void) {
puts("Usage:");
#ifdef MODULE_PM_LAYERED
puts("\tpm show: display current blockers for each power mode");
puts("\tpm set <mode>: manually set power mode (lasts until WFI returns)");
puts("\tpm block <mode>: manually block power mode");
puts("\tpm unblock <mode>: manually unblock power mode");
#endif /* MODULE_PM_LAYERED */
puts("\tpm off: call pm_off()");
}
#ifdef MODULE_PM_LAYERED
static int check_mode(int argc, char **argv)
{
if (argc != 3) {
printf("Usage: %s %s <power mode>\n", argv[0], argv[1]);
return -1;
}
return 0;
}
static int parse_mode(char *argv)
{
uint8_t mode = atoi(argv);
if (mode >= PM_NUM_MODES) {
printf("Error: power mode not in range 0 - %d.\n", PM_NUM_MODES - 1);
return -1;
}
return mode;
}
static int cmd_block(char *arg)
{
int mode = parse_mode(arg);
if (mode < 0) {
return 1;
}
printf("Blocking power mode %d.\n", mode);
fflush(stdout);
pm_block(mode);
return 0;
}
static int cmd_set(char *arg)
{
int mode = parse_mode(arg);
if (mode < 0) {
return 1;
}
printf("CPU is entering power mode %d.\n", mode);
puts("Now waiting for a wakeup event...");
fflush(stdout);
pm_set(mode);
/* execution stops here until anything (like shell input) wakes the CPU */
printf("CPU has returned from power mode %d.\n", mode);
return 0;
}
static int cmd_unblock(char *arg)
{
int mode = parse_mode(arg);
if (mode < 0) {
return 1;
}
if (pm_blocker.val_u8[mode] == 0) {
printf("Mode %d is already unblocked.\n", mode);
return 1;
}
printf("Unblocking power mode %d.\n", mode);
fflush(stdout);
pm_unblock(mode);
return 0;
}
static int cmd_show(char *arg)
{
(void)arg;
uint8_t lowest_allowed_mode = 0;
for (unsigned i = 0; i < PM_NUM_MODES; i++) {
printf("mode %u blockers: %u \n", i, pm_blocker.val_u8[i]);
if (pm_blocker.val_u8[i]) {
lowest_allowed_mode = i + 1;
}
}
printf("Lowest allowed mode: %u\n", lowest_allowed_mode);
return 0;
}
#endif /* MODULE_PM_LAYERED */
static int cmd_off(char *arg)
{
(void)arg;
pm_off();
return 0;
}
int _pm_handler(int argc, char **argv)
{
#ifdef MODULE_PM_LAYERED
if (!strcmp(argv[1], "show")) {
if (argc != 2) {
puts("usage: pm show: display current blockers for each power mode");
return 1;
}
return cmd_show(argv[1]);
}
if (!strcmp(argv[1], "block")) {
if (check_mode(argc, argv) != 0) {
return 1;
}
return cmd_block(argv[2]);
}
if (!strcmp(argv[1], "unblock")) {
if (check_mode(argc, argv) != 0) {
return 1;
}
return cmd_unblock(argv[2]);
}
if (!strcmp(argv[1], "set")) {
if (check_mode(argc, argv) != 0) {
return 1;
}
return cmd_set(argv[2]);
}
#else
(void)argc;
#endif /* MODULE_PM_LAYERED */
if (!strcmp(argv[1], "off")) {
return cmd_off(NULL);
}
_print_usage();
return 1;
}

View File

@ -34,6 +34,10 @@ extern int _id_handler(int argc, char **argv);
extern int _heap_handler(int argc, char **argv); extern int _heap_handler(int argc, char **argv);
#endif #endif
#ifdef MODULE_PERIPH_PM
extern int _pm_handler(int argc, char **argv);
#endif
#ifdef MODULE_PS #ifdef MODULE_PS
extern int _ps_handler(int argc, char **argv); extern int _ps_handler(int argc, char **argv);
#endif #endif
@ -180,6 +184,9 @@ const shell_command_t _shell_command_list[] = {
#ifdef MODULE_HEAP_CMD #ifdef MODULE_HEAP_CMD
{"heap", "Prints heap statistics.", _heap_handler}, {"heap", "Prints heap statistics.", _heap_handler},
#endif #endif
#ifdef MODULE_PERIPH_PM
{ "pm", "interact with layered PM subsystem", _pm_handler },
#endif
#ifdef MODULE_PS #ifdef MODULE_PS
{"ps", "Prints information about running threads.", _ps_handler}, {"ps", "Prints information about running threads.", _ps_handler},
#endif #endif

View File

@ -5,5 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-uno \ arduino-uno \
atmega328p \ atmega328p \
nucleo-f031k6 \ nucleo-f031k6 \
nucleo-f042k6 \
nucleo-l031k6 \
stm32f030f4-demo \ stm32f030f4-demo \
# #

View File

@ -7,6 +7,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-uno \ arduino-uno \
atmega1284p \ atmega1284p \
atmega328p \ atmega328p \
blackpill \
bluepill \
calliope-mini \ calliope-mini \
chronos \ chronos \
derfmega128 \ derfmega128 \

View File

@ -11,6 +11,8 @@ BOARD_INSUFFICIENT_MEMORY := \
nucleo-f334r8 \ nucleo-f334r8 \
nucleo-l031k6 \ nucleo-l031k6 \
nucleo-l053r8 \ nucleo-l053r8 \
saml10-xpro \
saml11-xpro \
stm32f030f4-demo \ stm32f030f4-demo \
stm32f0discovery \ stm32f0discovery \
stm32l0538-disco \ stm32l0538-disco \

View File

@ -8,5 +8,6 @@ FEATURES_OPTIONAL += periph_rtc
FEATURES_OPTIONAL += periph_gpio_irq FEATURES_OPTIONAL += periph_gpio_irq
USEMODULE += shell USEMODULE += shell
USEMODULE += shell_commands
include $(RIOTBASE)/Makefile.include include $(RIOTBASE)/Makefile.include

View File

@ -33,6 +33,9 @@
#endif #endif
#include "pm_layered.h" #include "pm_layered.h"
#endif #endif
extern int _pm_handler(int argc, char **argv);
#include "shell.h" #include "shell.h"
#ifndef BTN0_INT_FLANK #ifndef BTN0_INT_FLANK
@ -40,10 +43,14 @@
#endif #endif
#ifdef MODULE_PM_LAYERED #ifdef MODULE_PM_LAYERED
static int check_mode(int argc, char **argv)
extern volatile pm_blocker_t pm_blocker; /* sys/pm_layered/pm.c */
#ifdef MODULE_PERIPH_RTC
static int check_mode_duration(int argc, char **argv)
{ {
if (argc < 2) { if (argc != 3) {
printf("Usage: %s <power mode>\n", argv[0]); printf("Usage: %s <power mode> <duration (s)>\n", argv[0]);
return -1; return -1;
} }
@ -62,17 +69,6 @@ static int parse_mode(char *argv)
return mode; return mode;
} }
#ifdef MODULE_PERIPH_RTC
static int check_mode_duration(int argc, char **argv)
{
if (argc != 3) {
printf("Usage: %s <power mode> <duration (s)>\n", argv[0]);
return -1;
}
return 0;
}
static int parse_duration(char *argv) static int parse_duration(char *argv)
{ {
int duration = atoi(argv); int duration = atoi(argv);
@ -91,97 +87,7 @@ static void cb_rtc(void *arg)
pm_block(level); pm_block(level);
} }
#endif /* MODULE_PERIPH_RTC */
#endif /* MODULE_PM_LAYERED */
static int cmd_off(int argc, char **argv)
{
(void) argc;
(void) argv;
puts("CPU will turn off.");
fflush(stdout);
pm_off();
return 0;
}
static int cmd_reboot(int argc, char **argv)
{
(void) argc;
(void) argv;
puts("CPU will reboot.");
fflush(stdout);
pm_reboot();
return 0;
}
#ifdef MODULE_PM_LAYERED
static int cmd_block(int argc, char **argv)
{
if (check_mode(argc, argv) != 0) {
return 1;
}
int mode = parse_mode(argv[1]);
if (mode < 0) {
return 1;
}
printf("Blocking power mode %d.\n", mode);
fflush(stdout);
pm_block(mode);
return 0;
}
static int cmd_set(int argc, char **argv)
{
if (check_mode(argc, argv) != 0) {
return 1;
}
int mode = parse_mode(argv[1]);
if (mode < 0) {
return 1;
}
printf("CPU will enter power mode %d.\n", mode);
fflush(stdout);
pm_set(mode);
return 0;
}
static int cmd_unblock(int argc, char **argv)
{
if (check_mode(argc, argv) != 0) {
return 1;
}
int mode = parse_mode(argv[1]);
if (mode < 0) {
return 1;
}
printf("Unblocking power mode %d.\n", mode);
fflush(stdout);
pm_unblock(mode);
return 0;
}
#ifdef MODULE_PERIPH_RTC
static int cmd_unblock_rtc(int argc, char **argv) static int cmd_unblock_rtc(int argc, char **argv)
{ {
if (check_mode_duration(argc, argv) != 0) { if (check_mode_duration(argc, argv) != 0) {
@ -195,6 +101,11 @@ static int cmd_unblock_rtc(int argc, char **argv)
return 1; return 1;
} }
if (pm_blocker.val_u8[mode] == 0) {
printf("Mode %d is already unblocked.\n", mode);
return 1;
}
printf("Unblocking power mode %d for %d seconds.\n", mode, duration); printf("Unblocking power mode %d for %d seconds.\n", mode, duration);
fflush(stdout); fflush(stdout);
@ -224,15 +135,8 @@ static void btn_cb(void *ctx)
* @brief List of shell commands for this example. * @brief List of shell commands for this example.
*/ */
static const shell_command_t shell_commands[] = { static const shell_command_t shell_commands[] = {
{ "off", "turn off", cmd_off }, #if defined MODULE_PM_LAYERED && defined MODULE_PERIPH_RTC
{ "reboot", "reboot", cmd_reboot }, { "unblock_rtc", "temporarily unblock power mode", cmd_unblock_rtc },
#ifdef MODULE_PM_LAYERED
{ "block", "block power mode", cmd_block },
{ "set", "set power mode", cmd_set },
{ "unblock", "unblock power mode", cmd_unblock },
#ifdef MODULE_PERIPH_RTC
{ "unblock_rtc", "temporary unblock power mode", cmd_unblock_rtc },
#endif
#endif #endif
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
@ -251,6 +155,13 @@ int main(void)
"save more power, but may require an event/interrupt to wake up\n" "save more power, but may require an event/interrupt to wake up\n"
"the CPU. Reset the CPU if needed.\n", "the CPU. Reset the CPU if needed.\n",
PM_NUM_MODES - 1); PM_NUM_MODES - 1);
/* In case the system boots into an unresponsive shell, at least display
* the state of PM blockers so that the user will know which power mode has
* been entered and is presumably responsible for the unresponsive shell.
*/
_pm_handler(2, (char *[]){"pm", "show"});
#else #else
puts("This application allows you to test the CPU power management.\n" puts("This application allows you to test the CPU power management.\n"
"Layered support is not unavailable for this CPU. Reset the CPU if\n" "Layered support is not unavailable for this CPU. Reset the CPU if\n"