From b52607af71c5552462c77628cc39a98f5d0c7d8c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 24 Mar 2023 13:50:48 +0100 Subject: [PATCH] examples: re-enable console examples for C2, C6, H2 - Split the sleep-related system commands into a separate file - Don't compile that file and don't register sleep commands for H2 yet - Exclude Wi-Fi commands if the chip doesn't have Wi-Fi --- examples/system/.build-test-rules.yml | 18 +- examples/system/console/advanced/README.md | 4 +- .../components/cmd_system/CMakeLists.txt | 2 +- .../components/cmd_system/cmd_system.c | 451 +----------------- .../components/cmd_system/cmd_system_common.c | 274 +++++++++++ .../components/cmd_system/cmd_system_sleep.c | 221 +++++++++ .../advanced/main/console_example_main.c | 6 +- examples/system/console/basic/README.md | 4 +- .../console/basic/main/console_example_main.c | 5 +- 9 files changed, 514 insertions(+), 471 deletions(-) create mode 100644 examples/system/console/advanced/components/cmd_system/cmd_system_common.c create mode 100644 examples/system/console/advanced/components/cmd_system/cmd_system_sleep.c diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index dd8e63da37..edf1c84618 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -7,28 +7,18 @@ examples/system/app_trace_basic: reason: target esp32c6, esp32h2 is not supported yet examples/system/console/advanced: - disable: - - if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"] - temporary: true - reason: target(s) not supported yet disable_test: - - if: IDF_TARGET in ["esp32s2", "esp32s3"] - temporary: true - reason: lack of runners + - if: IDF_TARGET not in ["esp32", "esp32c3"] + reason: Sufficient to run this app on one chip with each architecture examples/system/console/advanced_usb_cdc: disable: - if: SOC_USB_PERIPH_NUM == 0 examples/system/console/basic: - disable: - - if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"] - temporary: true - reason: target(s) not supported yet disable_test: - - if: IDF_TARGET in ["esp32s2", "esp32s3"] - temporary: true - reason: lack of runners + - if: IDF_TARGET not in ["esp32", "esp32c3"] + reason: Sufficient to run this app on one chip with each architecture examples/system/deep_sleep_wake_stub: disable: diff --git a/examples/system/console/advanced/README.md b/examples/system/console/advanced/README.md index 5c3061627c..d1727552df 100644 --- a/examples/system/console/advanced/README.md +++ b/examples/system/console/advanced/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # Console Example diff --git a/examples/system/console/advanced/components/cmd_system/CMakeLists.txt b/examples/system/console/advanced/components/cmd_system/CMakeLists.txt index f54289c18c..5b2b6daca4 100644 --- a/examples/system/console/advanced/components/cmd_system/CMakeLists.txt +++ b/examples/system/console/advanced/components/cmd_system/CMakeLists.txt @@ -1,3 +1,3 @@ -idf_component_register(SRCS "cmd_system.c" +idf_component_register(SRCS "cmd_system.c" "cmd_system_common.c" "cmd_system_sleep.c" INCLUDE_DIRS . REQUIRES console spi_flash driver) diff --git a/examples/system/console/advanced/components/cmd_system/cmd_system.c b/examples/system/console/advanced/components/cmd_system/cmd_system.c index 58b94a5970..01b3cf9180 100644 --- a/examples/system/console/advanced/components/cmd_system/cmd_system.c +++ b/examples/system/console/advanced/components/cmd_system/cmd_system.c @@ -7,461 +7,12 @@ CONDITIONS OF ANY KIND, either express or implied. */ -#include -#include -#include -#include -#include -#include "esp_log.h" -#include "esp_console.h" -#include "esp_chip_info.h" -#include "esp_sleep.h" -#include "esp_flash.h" -#include "driver/rtc_io.h" -#include "driver/uart.h" -#include "argtable3/argtable3.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" + #include "cmd_system.h" #include "sdkconfig.h" -#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS -#define WITH_TASKS_INFO 1 -#endif - -static const char *TAG = "cmd_system"; - -static void register_free(void); -static void register_heap(void); -static void register_version(void); -static void register_restart(void); -static void register_deep_sleep(void); -static void register_light_sleep(void); -#if WITH_TASKS_INFO -static void register_tasks(void); -#endif -static void register_log_level(void); - -void register_system_common(void) -{ - register_free(); - register_heap(); - register_version(); - register_restart(); -#if WITH_TASKS_INFO - register_tasks(); -#endif - register_log_level(); -} - -void register_system_sleep(void) -{ - register_deep_sleep(); - register_light_sleep(); -} - void register_system(void) { register_system_common(); register_system_sleep(); } - -/* 'version' command */ -static int get_version(int argc, char **argv) -{ - const char *model; - esp_chip_info_t info; - uint32_t flash_size; - esp_chip_info(&info); - - switch(info.model) { - case CHIP_ESP32: - model = "ESP32"; - break; - case CHIP_ESP32S2: - model = "ESP32-S2"; - break; - case CHIP_ESP32S3: - model = "ESP32-S3"; - break; - case CHIP_ESP32C3: - model = "ESP32-C3"; - break; - case CHIP_ESP32H2: - model = "ESP32-H2"; - break; - case CHIP_ESP32C2: - model = "ESP32-C2"; - break; - default: - model = "Unknown"; - break; - } - - if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) { - printf("Get flash size failed"); - return 1; - } - printf("IDF Version:%s\r\n", esp_get_idf_version()); - printf("Chip info:\r\n"); - printf("\tmodel:%s\r\n", model); - printf("\tcores:%d\r\n", info.cores); - printf("\tfeature:%s%s%s%s%"PRIu32"%s\r\n", - info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "", - info.features & CHIP_FEATURE_BLE ? "/BLE" : "", - info.features & CHIP_FEATURE_BT ? "/BT" : "", - info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:", - flash_size / (1024 * 1024), " MB"); - printf("\trevision number:%d\r\n", info.revision); - return 0; -} - -static void register_version(void) -{ - const esp_console_cmd_t cmd = { - .command = "version", - .help = "Get version of chip and SDK", - .hint = NULL, - .func = &get_version, - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); -} - -/** 'restart' command restarts the program */ - -static int restart(int argc, char **argv) -{ - ESP_LOGI(TAG, "Restarting"); - esp_restart(); -} - -static void register_restart(void) -{ - const esp_console_cmd_t cmd = { - .command = "restart", - .help = "Software reset of the chip", - .hint = NULL, - .func = &restart, - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); -} - -/** 'free' command prints available heap memory */ - -static int free_mem(int argc, char **argv) -{ - printf("%"PRIu32"\n", esp_get_free_heap_size()); - return 0; -} - -static void register_free(void) -{ - const esp_console_cmd_t cmd = { - .command = "free", - .help = "Get the current size of free heap memory", - .hint = NULL, - .func = &free_mem, - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); -} - -/* 'heap' command prints minumum heap size */ -static int heap_size(int argc, char **argv) -{ - uint32_t heap_size = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT); - printf("min heap size: %"PRIu32"\n", heap_size); - return 0; -} - -static void register_heap(void) -{ - const esp_console_cmd_t heap_cmd = { - .command = "heap", - .help = "Get minimum size of free heap memory that was available during program execution", - .hint = NULL, - .func = &heap_size, - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) ); - -} - -/** 'tasks' command prints the list of tasks and related information */ -#if WITH_TASKS_INFO - -static int tasks_info(int argc, char **argv) -{ - const size_t bytes_per_task = 40; /* see vTaskList description */ - char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task); - if (task_list_buffer == NULL) { - ESP_LOGE(TAG, "failed to allocate buffer for vTaskList output"); - return 1; - } - fputs("Task Name\tStatus\tPrio\tHWM\tTask#", stdout); -#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID - fputs("\tAffinity", stdout); -#endif - fputs("\n", stdout); - vTaskList(task_list_buffer); - fputs(task_list_buffer, stdout); - free(task_list_buffer); - return 0; -} - -static void register_tasks(void) -{ - const esp_console_cmd_t cmd = { - .command = "tasks", - .help = "Get information about running tasks", - .hint = NULL, - .func = &tasks_info, - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); -} - -#endif // WITH_TASKS_INFO - -/** 'deep_sleep' command puts the chip into deep sleep mode */ - -static struct { - struct arg_int *wakeup_time; -#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP - struct arg_int *wakeup_gpio_num; - struct arg_int *wakeup_gpio_level; -#endif - struct arg_end *end; -} deep_sleep_args; - - -static int deep_sleep(int argc, char **argv) -{ - int nerrors = arg_parse(argc, argv, (void **) &deep_sleep_args); - if (nerrors != 0) { - arg_print_errors(stderr, deep_sleep_args.end, argv[0]); - return 1; - } - if (deep_sleep_args.wakeup_time->count) { - uint64_t timeout = 1000ULL * deep_sleep_args.wakeup_time->ival[0]; - ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout); - ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) ); - } - -#if SOC_PM_SUPPORT_EXT1_WAKEUP - if (deep_sleep_args.wakeup_gpio_num->count) { - int io_num = deep_sleep_args.wakeup_gpio_num->ival[0]; - if (!esp_sleep_is_valid_wakeup_gpio(io_num)) { - ESP_LOGE(TAG, "GPIO %d is not an RTC IO", io_num); - return 1; - } - int level = 0; - if (deep_sleep_args.wakeup_gpio_level->count) { - level = deep_sleep_args.wakeup_gpio_level->ival[0]; - if (level != 0 && level != 1) { - ESP_LOGE(TAG, "Invalid wakeup level: %d", level); - return 1; - } - } - ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level", - io_num, level ? "HIGH" : "LOW"); - - ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) ); - ESP_LOGE(TAG, "GPIO wakeup from deep sleep currently unsupported on ESP32-C3"); - } -#endif // SOC_PM_SUPPORT_EXT1_WAKEUP - -#if CONFIG_IDF_TARGET_ESP32 - rtc_gpio_isolate(GPIO_NUM_12); -#endif //CONFIG_IDF_TARGET_ESP32 - - esp_deep_sleep_start(); -} - -static void register_deep_sleep(void) -{ - int num_args = 1; - deep_sleep_args.wakeup_time = - arg_int0("t", "time", "", "Wake up time, ms"); -#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP - deep_sleep_args.wakeup_gpio_num = - arg_int0(NULL, "io", "", - "If specified, wakeup using GPIO with given number"); - deep_sleep_args.wakeup_gpio_level = - arg_int0(NULL, "io_level", "<0|1>", "GPIO level to trigger wakeup"); - num_args += 2; -#endif - deep_sleep_args.end = arg_end(num_args); - - const esp_console_cmd_t cmd = { - .command = "deep_sleep", - .help = "Enter deep sleep mode. " -#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP - "Two wakeup modes are supported: timer and GPIO. " -#else - "Timer wakeup mode is supported. " -#endif - "If no wakeup option is specified, will sleep indefinitely.", - .hint = NULL, - .func = &deep_sleep, - .argtable = &deep_sleep_args - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); -} - -/** 'light_sleep' command puts the chip into light sleep mode */ - -static struct { - struct arg_int *wakeup_time; - struct arg_int *wakeup_gpio_num; - struct arg_int *wakeup_gpio_level; - struct arg_end *end; -} light_sleep_args; - -static int light_sleep(int argc, char **argv) -{ - int nerrors = arg_parse(argc, argv, (void **) &light_sleep_args); - if (nerrors != 0) { - arg_print_errors(stderr, light_sleep_args.end, argv[0]); - return 1; - } - esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); - if (light_sleep_args.wakeup_time->count) { - uint64_t timeout = 1000ULL * light_sleep_args.wakeup_time->ival[0]; - ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout); - ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) ); - } - int io_count = light_sleep_args.wakeup_gpio_num->count; - if (io_count != light_sleep_args.wakeup_gpio_level->count) { - ESP_LOGE(TAG, "Should have same number of 'io' and 'io_level' arguments"); - return 1; - } - for (int i = 0; i < io_count; ++i) { - int io_num = light_sleep_args.wakeup_gpio_num->ival[i]; - int level = light_sleep_args.wakeup_gpio_level->ival[i]; - if (level != 0 && level != 1) { - ESP_LOGE(TAG, "Invalid wakeup level: %d", level); - return 1; - } - ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level", - io_num, level ? "HIGH" : "LOW"); - - ESP_ERROR_CHECK( gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL) ); - } - if (io_count > 0) { - ESP_ERROR_CHECK( esp_sleep_enable_gpio_wakeup() ); - } - if (CONFIG_ESP_CONSOLE_UART_NUM >= 0 && CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) { - ESP_LOGI(TAG, "Enabling UART wakeup (press ENTER to exit light sleep)"); - ESP_ERROR_CHECK( uart_set_wakeup_threshold(CONFIG_ESP_CONSOLE_UART_NUM, 3) ); - ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM) ); - } - fflush(stdout); - fsync(fileno(stdout)); - esp_light_sleep_start(); - esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); - const char *cause_str; - switch (cause) { - case ESP_SLEEP_WAKEUP_GPIO: - cause_str = "GPIO"; - break; - case ESP_SLEEP_WAKEUP_UART: - cause_str = "UART"; - break; - case ESP_SLEEP_WAKEUP_TIMER: - cause_str = "timer"; - break; - default: - cause_str = "unknown"; - printf("%d\n", cause); - } - ESP_LOGI(TAG, "Woke up from: %s", cause_str); - return 0; -} - -static void register_light_sleep(void) -{ - light_sleep_args.wakeup_time = - arg_int0("t", "time", "", "Wake up time, ms"); - light_sleep_args.wakeup_gpio_num = - arg_intn(NULL, "io", "", 0, 8, - "If specified, wakeup using GPIO with given number"); - light_sleep_args.wakeup_gpio_level = - arg_intn(NULL, "io_level", "<0|1>", 0, 8, "GPIO level to trigger wakeup"); - light_sleep_args.end = arg_end(3); - - const esp_console_cmd_t cmd = { - .command = "light_sleep", - .help = "Enter light sleep mode. " - "Two wakeup modes are supported: timer and GPIO. " - "Multiple GPIO pins can be specified using pairs of " - "'io' and 'io_level' arguments. " - "Will also wake up on UART input.", - .hint = NULL, - .func = &light_sleep, - .argtable = &light_sleep_args - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); -} - -/** log_level command changes log level via esp_log_level_set */ - -static struct { - struct arg_str *tag; - struct arg_str *level; - struct arg_end *end; -} log_level_args; - -static const char* s_log_level_names[] = { - "none", - "error", - "warn", - "info", - "debug", - "verbose" -}; - -static int log_level(int argc, char **argv) -{ - int nerrors = arg_parse(argc, argv, (void **) &log_level_args); - if (nerrors != 0) { - arg_print_errors(stderr, log_level_args.end, argv[0]); - return 1; - } - assert(log_level_args.tag->count == 1); - assert(log_level_args.level->count == 1); - const char* tag = log_level_args.tag->sval[0]; - const char* level_str = log_level_args.level->sval[0]; - esp_log_level_t level; - size_t level_len = strlen(level_str); - for (level = ESP_LOG_NONE; level <= ESP_LOG_VERBOSE; level++) { - if (memcmp(level_str, s_log_level_names[level], level_len) == 0) { - break; - } - } - if (level > ESP_LOG_VERBOSE) { - printf("Invalid log level '%s', choose from none|error|warn|info|debug|verbose\n", level_str); - return 1; - } - if (level > CONFIG_LOG_MAXIMUM_LEVEL) { - printf("Can't set log level to %s, max level limited in menuconfig to %s. " - "Please increase CONFIG_LOG_MAXIMUM_LEVEL in menuconfig.\n", - s_log_level_names[level], s_log_level_names[CONFIG_LOG_MAXIMUM_LEVEL]); - return 1; - } - esp_log_level_set(tag, level); - return 0; -} - -static void register_log_level(void) -{ - log_level_args.tag = arg_str1(NULL, NULL, "", "Log tag to set the level for, or * to set for all tags"); - log_level_args.level = arg_str1(NULL, NULL, "", "Log level to set. Abbreviated words are accepted."); - log_level_args.end = arg_end(2); - - const esp_console_cmd_t cmd = { - .command = "log_level", - .help = "Set log level for all tags or a specific tag.", - .hint = NULL, - .func = &log_level, - .argtable = &log_level_args - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); -} diff --git a/examples/system/console/advanced/components/cmd_system/cmd_system_common.c b/examples/system/console/advanced/components/cmd_system/cmd_system_common.c new file mode 100644 index 0000000000..d027ecc405 --- /dev/null +++ b/examples/system/console/advanced/components/cmd_system/cmd_system_common.c @@ -0,0 +1,274 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* Console example — various system commands + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include +#include "esp_log.h" +#include "esp_console.h" +#include "esp_chip_info.h" +#include "esp_flash.h" +#include "argtable3/argtable3.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "cmd_system.h" +#include "sdkconfig.h" + +#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS +#define WITH_TASKS_INFO 1 +#endif + +static const char *TAG = "cmd_system_common"; + +static void register_free(void); +static void register_heap(void); +static void register_version(void); +static void register_restart(void); +#if WITH_TASKS_INFO +static void register_tasks(void); +#endif +static void register_log_level(void); + +void register_system_common(void) +{ + register_free(); + register_heap(); + register_version(); + register_restart(); +#if WITH_TASKS_INFO + register_tasks(); +#endif + register_log_level(); +} + + +/* 'version' command */ +static int get_version(int argc, char **argv) +{ + const char *model; + esp_chip_info_t info; + uint32_t flash_size; + esp_chip_info(&info); + + switch(info.model) { + case CHIP_ESP32: + model = "ESP32"; + break; + case CHIP_ESP32S2: + model = "ESP32-S2"; + break; + case CHIP_ESP32S3: + model = "ESP32-S3"; + break; + case CHIP_ESP32C3: + model = "ESP32-C3"; + break; + case CHIP_ESP32H2: + model = "ESP32-H2"; + break; + case CHIP_ESP32C2: + model = "ESP32-C2"; + break; + default: + model = "Unknown"; + break; + } + + if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) { + printf("Get flash size failed"); + return 1; + } + printf("IDF Version:%s\r\n", esp_get_idf_version()); + printf("Chip info:\r\n"); + printf("\tmodel:%s\r\n", model); + printf("\tcores:%d\r\n", info.cores); + printf("\tfeature:%s%s%s%s%"PRIu32"%s\r\n", + info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "", + info.features & CHIP_FEATURE_BLE ? "/BLE" : "", + info.features & CHIP_FEATURE_BT ? "/BT" : "", + info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:", + flash_size / (1024 * 1024), " MB"); + printf("\trevision number:%d\r\n", info.revision); + return 0; +} + +static void register_version(void) +{ + const esp_console_cmd_t cmd = { + .command = "version", + .help = "Get version of chip and SDK", + .hint = NULL, + .func = &get_version, + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); +} + +/** 'restart' command restarts the program */ + +static int restart(int argc, char **argv) +{ + ESP_LOGI(TAG, "Restarting"); + esp_restart(); +} + +static void register_restart(void) +{ + const esp_console_cmd_t cmd = { + .command = "restart", + .help = "Software reset of the chip", + .hint = NULL, + .func = &restart, + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); +} + +/** 'free' command prints available heap memory */ + +static int free_mem(int argc, char **argv) +{ + printf("%"PRIu32"\n", esp_get_free_heap_size()); + return 0; +} + +static void register_free(void) +{ + const esp_console_cmd_t cmd = { + .command = "free", + .help = "Get the current size of free heap memory", + .hint = NULL, + .func = &free_mem, + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); +} + +/* 'heap' command prints minumum heap size */ +static int heap_size(int argc, char **argv) +{ + uint32_t heap_size = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT); + printf("min heap size: %"PRIu32"\n", heap_size); + return 0; +} + +static void register_heap(void) +{ + const esp_console_cmd_t heap_cmd = { + .command = "heap", + .help = "Get minimum size of free heap memory that was available during program execution", + .hint = NULL, + .func = &heap_size, + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) ); + +} + +/** 'tasks' command prints the list of tasks and related information */ +#if WITH_TASKS_INFO + +static int tasks_info(int argc, char **argv) +{ + const size_t bytes_per_task = 40; /* see vTaskList description */ + char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task); + if (task_list_buffer == NULL) { + ESP_LOGE(TAG, "failed to allocate buffer for vTaskList output"); + return 1; + } + fputs("Task Name\tStatus\tPrio\tHWM\tTask#", stdout); +#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID + fputs("\tAffinity", stdout); +#endif + fputs("\n", stdout); + vTaskList(task_list_buffer); + fputs(task_list_buffer, stdout); + free(task_list_buffer); + return 0; +} + +static void register_tasks(void) +{ + const esp_console_cmd_t cmd = { + .command = "tasks", + .help = "Get information about running tasks", + .hint = NULL, + .func = &tasks_info, + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); +} + +#endif // WITH_TASKS_INFO + +/** log_level command changes log level via esp_log_level_set */ + +static struct { + struct arg_str *tag; + struct arg_str *level; + struct arg_end *end; +} log_level_args; + +static const char* s_log_level_names[] = { + "none", + "error", + "warn", + "info", + "debug", + "verbose" +}; + +static int log_level(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &log_level_args); + if (nerrors != 0) { + arg_print_errors(stderr, log_level_args.end, argv[0]); + return 1; + } + assert(log_level_args.tag->count == 1); + assert(log_level_args.level->count == 1); + const char* tag = log_level_args.tag->sval[0]; + const char* level_str = log_level_args.level->sval[0]; + esp_log_level_t level; + size_t level_len = strlen(level_str); + for (level = ESP_LOG_NONE; level <= ESP_LOG_VERBOSE; level++) { + if (memcmp(level_str, s_log_level_names[level], level_len) == 0) { + break; + } + } + if (level > ESP_LOG_VERBOSE) { + printf("Invalid log level '%s', choose from none|error|warn|info|debug|verbose\n", level_str); + return 1; + } + if (level > CONFIG_LOG_MAXIMUM_LEVEL) { + printf("Can't set log level to %s, max level limited in menuconfig to %s. " + "Please increase CONFIG_LOG_MAXIMUM_LEVEL in menuconfig.\n", + s_log_level_names[level], s_log_level_names[CONFIG_LOG_MAXIMUM_LEVEL]); + return 1; + } + esp_log_level_set(tag, level); + return 0; +} + +static void register_log_level(void) +{ + log_level_args.tag = arg_str1(NULL, NULL, "", "Log tag to set the level for, or * to set for all tags"); + log_level_args.level = arg_str1(NULL, NULL, "", "Log level to set. Abbreviated words are accepted."); + log_level_args.end = arg_end(2); + + const esp_console_cmd_t cmd = { + .command = "log_level", + .help = "Set log level for all tags or a specific tag.", + .hint = NULL, + .func = &log_level, + .argtable = &log_level_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); +} diff --git a/examples/system/console/advanced/components/cmd_system/cmd_system_sleep.c b/examples/system/console/advanced/components/cmd_system/cmd_system_sleep.c new file mode 100644 index 0000000000..71834e2de2 --- /dev/null +++ b/examples/system/console/advanced/components/cmd_system/cmd_system_sleep.c @@ -0,0 +1,221 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* Console example — various sleep-related commands + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include +#include +#include "esp_log.h" +#include "esp_console.h" +#include "esp_chip_info.h" +#include "esp_sleep.h" +#include "driver/rtc_io.h" +#include "driver/uart.h" +#include "argtable3/argtable3.h" +#include "cmd_system.h" +#include "sdkconfig.h" + +static const char *TAG = "cmd_system_sleep"; + +static void register_deep_sleep(void); +static void register_light_sleep(void); + +void register_system_sleep(void) +{ + register_deep_sleep(); + register_light_sleep(); +} + + +/** 'deep_sleep' command puts the chip into deep sleep mode */ + +static struct { + struct arg_int *wakeup_time; +#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP + struct arg_int *wakeup_gpio_num; + struct arg_int *wakeup_gpio_level; +#endif + struct arg_end *end; +} deep_sleep_args; + + +static int deep_sleep(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &deep_sleep_args); + if (nerrors != 0) { + arg_print_errors(stderr, deep_sleep_args.end, argv[0]); + return 1; + } + if (deep_sleep_args.wakeup_time->count) { + uint64_t timeout = 1000ULL * deep_sleep_args.wakeup_time->ival[0]; + ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout); + ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) ); + } + +#if SOC_PM_SUPPORT_EXT1_WAKEUP + if (deep_sleep_args.wakeup_gpio_num->count) { + int io_num = deep_sleep_args.wakeup_gpio_num->ival[0]; + if (!esp_sleep_is_valid_wakeup_gpio(io_num)) { + ESP_LOGE(TAG, "GPIO %d is not an RTC IO", io_num); + return 1; + } + int level = 0; + if (deep_sleep_args.wakeup_gpio_level->count) { + level = deep_sleep_args.wakeup_gpio_level->ival[0]; + if (level != 0 && level != 1) { + ESP_LOGE(TAG, "Invalid wakeup level: %d", level); + return 1; + } + } + ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level", + io_num, level ? "HIGH" : "LOW"); + + ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) ); + ESP_LOGE(TAG, "GPIO wakeup from deep sleep currently unsupported on ESP32-C3"); + } +#endif // SOC_PM_SUPPORT_EXT1_WAKEUP + +#if CONFIG_IDF_TARGET_ESP32 + rtc_gpio_isolate(GPIO_NUM_12); +#endif //CONFIG_IDF_TARGET_ESP32 + + esp_deep_sleep_start(); +} + +static void register_deep_sleep(void) +{ + int num_args = 1; + deep_sleep_args.wakeup_time = + arg_int0("t", "time", "", "Wake up time, ms"); +#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP + deep_sleep_args.wakeup_gpio_num = + arg_int0(NULL, "io", "", + "If specified, wakeup using GPIO with given number"); + deep_sleep_args.wakeup_gpio_level = + arg_int0(NULL, "io_level", "<0|1>", "GPIO level to trigger wakeup"); + num_args += 2; +#endif + deep_sleep_args.end = arg_end(num_args); + + const esp_console_cmd_t cmd = { + .command = "deep_sleep", + .help = "Enter deep sleep mode. " +#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP + "Two wakeup modes are supported: timer and GPIO. " +#else + "Timer wakeup mode is supported. " +#endif + "If no wakeup option is specified, will sleep indefinitely.", + .hint = NULL, + .func = &deep_sleep, + .argtable = &deep_sleep_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); +} + +/** 'light_sleep' command puts the chip into light sleep mode */ + +static struct { + struct arg_int *wakeup_time; + struct arg_int *wakeup_gpio_num; + struct arg_int *wakeup_gpio_level; + struct arg_end *end; +} light_sleep_args; + +static int light_sleep(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &light_sleep_args); + if (nerrors != 0) { + arg_print_errors(stderr, light_sleep_args.end, argv[0]); + return 1; + } + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); + if (light_sleep_args.wakeup_time->count) { + uint64_t timeout = 1000ULL * light_sleep_args.wakeup_time->ival[0]; + ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout); + ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) ); + } + int io_count = light_sleep_args.wakeup_gpio_num->count; + if (io_count != light_sleep_args.wakeup_gpio_level->count) { + ESP_LOGE(TAG, "Should have same number of 'io' and 'io_level' arguments"); + return 1; + } + for (int i = 0; i < io_count; ++i) { + int io_num = light_sleep_args.wakeup_gpio_num->ival[i]; + int level = light_sleep_args.wakeup_gpio_level->ival[i]; + if (level != 0 && level != 1) { + ESP_LOGE(TAG, "Invalid wakeup level: %d", level); + return 1; + } + ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level", + io_num, level ? "HIGH" : "LOW"); + + ESP_ERROR_CHECK( gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL) ); + } + if (io_count > 0) { + ESP_ERROR_CHECK( esp_sleep_enable_gpio_wakeup() ); + } + if (CONFIG_ESP_CONSOLE_UART_NUM >= 0 && CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) { + ESP_LOGI(TAG, "Enabling UART wakeup (press ENTER to exit light sleep)"); + ESP_ERROR_CHECK( uart_set_wakeup_threshold(CONFIG_ESP_CONSOLE_UART_NUM, 3) ); + ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM) ); + } + fflush(stdout); + fsync(fileno(stdout)); + esp_light_sleep_start(); + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + const char *cause_str; + switch (cause) { + case ESP_SLEEP_WAKEUP_GPIO: + cause_str = "GPIO"; + break; + case ESP_SLEEP_WAKEUP_UART: + cause_str = "UART"; + break; + case ESP_SLEEP_WAKEUP_TIMER: + cause_str = "timer"; + break; + default: + cause_str = "unknown"; + printf("%d\n", cause); + } + ESP_LOGI(TAG, "Woke up from: %s", cause_str); + return 0; +} + +static void register_light_sleep(void) +{ + light_sleep_args.wakeup_time = + arg_int0("t", "time", "", "Wake up time, ms"); + light_sleep_args.wakeup_gpio_num = + arg_intn(NULL, "io", "", 0, 8, + "If specified, wakeup using GPIO with given number"); + light_sleep_args.wakeup_gpio_level = + arg_intn(NULL, "io_level", "<0|1>", 0, 8, "GPIO level to trigger wakeup"); + light_sleep_args.end = arg_end(3); + + const esp_console_cmd_t cmd = { + .command = "light_sleep", + .help = "Enter light sleep mode. " + "Two wakeup modes are supported: timer and GPIO. " + "Multiple GPIO pins can be specified using pairs of " + "'io' and 'io_level' arguments. " + "Will also wake up on UART input.", + .hint = NULL, + .func = &light_sleep, + .argtable = &light_sleep_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); +} diff --git a/examples/system/console/advanced/main/console_example_main.c b/examples/system/console/advanced/main/console_example_main.c index c7a5a3241b..4f7d7cd893 100644 --- a/examples/system/console/advanced/main/console_example_main.c +++ b/examples/system/console/advanced/main/console_example_main.c @@ -19,6 +19,7 @@ #include "esp_vfs_fat.h" #include "nvs.h" #include "nvs_flash.h" +#include "soc/soc_caps.h" #include "cmd_system.h" #include "cmd_wifi.h" #include "cmd_nvs.h" @@ -154,8 +155,11 @@ void app_main(void) /* Register commands */ esp_console_register_help_command(); - register_system(); + register_system_common(); + register_system_sleep(); +#if SOC_WIFI_SUPPORTED register_wifi(); +#endif register_nvs(); /* Prompt to be printed before each line. diff --git a/examples/system/console/basic/README.md b/examples/system/console/basic/README.md index 64897a7d8a..f1ac0d4ba0 100644 --- a/examples/system/console/basic/README.md +++ b/examples/system/console/basic/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # Basic Console Example (`esp_console_repl`) diff --git a/examples/system/console/basic/main/console_example_main.c b/examples/system/console/basic/main/console_example_main.c index 26fc3d4d5b..34fd94d131 100644 --- a/examples/system/console/basic/main/console_example_main.c +++ b/examples/system/console/basic/main/console_example_main.c @@ -79,8 +79,11 @@ void app_main(void) /* Register commands */ esp_console_register_help_command(); - register_system(); + register_system_common(); + register_system_sleep(); +#if SOC_WIFI_SUPPORTED register_wifi(); +#endif register_nvs(); #if defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) || defined(CONFIG_ESP_CONSOLE_UART_CUSTOM)