1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/shell/cmds/pm.c
Marian Buschsieweke c06335b71b
sys/shell: make cmds submodules
Previously `shell_commands` was a "catch-all" module that included
shell commands for each and every used module that has a shell
companion. Instead, the new `shell_cmds` module is now used to provide
shell commands as individually selectable submodules, e.g.
`cmd_gnrc_icmpv6_echo` now provides the ICMPv6 echo command (a.k.a.
ping).

To still have a "catch all" module to pull in shell commands of modules
already used, `shell_cmds_default` was introduced. `shell_commands`
depends now on `shell_cmds_default` for backward compatibility, but
has been deprecated. New apps should use `shell_cmds_default`
instead.

For a handful of shell commands individual selection was already
possible. Those modules now depend on the corresponding `cmd_%` module
and they have been deprecated.
2022-09-16 13:15:45 +02:00

203 lines
4.1 KiB
C

/*
* 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"
#include "shell.h"
#ifdef MODULE_PM_LAYERED
#include "pm_layered.h"
#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;
}
pm_blocker_t pm_blocker = pm_get_blocker();
if (pm_blocker.blockers[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;
pm_blocker_t pm_blocker = pm_get_blocker();
for (unsigned i = 0; i < PM_NUM_MODES; i++) {
printf("mode %u blockers: %u \n", i, pm_blocker.blockers[i]);
if (pm_blocker.blockers[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;
}
static int _pm_handler(int argc, char **argv)
{
if (argc < 2) {
_print_usage();
return 1;
}
#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]);
}
#endif /* MODULE_PM_LAYERED */
if (!strcmp(argv[1], "off")) {
return cmd_off(NULL);
}
_print_usage();
return 1;
}
SHELL_COMMAND(pm, "interact with layered PM subsystem", _pm_handler);