#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/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); #if WITH_TASKS_INFO static void register_tasks(void); #endif static void register_log_level(void); void register_system(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) { const 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 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) { const 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; const 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) ); }