/* * cmd_system.c * * Copyright (c) 2025 Umber Networks & Robert McMahon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "esp_log.h" #include "esp_console.h" #include "argtable3/argtable3.h" #include "esp_system.h" #include "esp_chip_info.h" #include "esp_mac.h" #include "esp_heap_caps.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "app_console.h" static const char *TAG = "CMD_SYS"; // ============================================================================ // COMMAND: system (Reboot, Info, Heap) // ============================================================================ static struct { struct arg_lit *reboot; struct arg_lit *info; struct arg_lit *heap; struct arg_lit *help; struct arg_end *end; } sys_args; static const char* get_chip_model_string(esp_chip_model_t model) { switch (model) { case CHIP_ESP32: return "ESP32"; case CHIP_ESP32S2: return "ESP32-S2"; case CHIP_ESP32S3: return "ESP32-S3"; case CHIP_ESP32C3: return "ESP32-C3"; case CHIP_ESP32C2: return "ESP32-C2"; case CHIP_ESP32C6: return "ESP32-C6"; case CHIP_ESP32H2: return "ESP32-H2"; #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)) case CHIP_ESP32C5: return "ESP32-C5"; // Requires recent IDF case CHIP_ESP32P4: return "ESP32-P4"; #endif default: return "Unknown"; } } static int cmd_system(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&sys_args); if (nerrors > 0) { arg_print_errors(stderr, sys_args.end, argv[0]); return 1; } if (sys_args.help->count > 0) { printf("Usage: system [--reboot|--info|--heap]\n"); printf(" --reboot Restart the device immediately\n"); printf(" --info Show chip model, revision, and MAC\n"); printf(" --heap Show current memory statistics\n"); return 0; } // --- HEAP STATS --- if (sys_args.heap->count > 0) { uint32_t free_heap = esp_get_free_heap_size(); uint32_t min_heap = esp_get_minimum_free_heap_size(); printf("Heap Summary:\n"); printf(" Free Heap: %" PRIu32 " bytes\n", free_heap); printf(" Min Free Ever: %" PRIu32 " bytes\n", min_heap); uint32_t internal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); uint32_t dma = heap_caps_get_free_size(MALLOC_CAP_DMA); printf(" Internal (SRAM): %" PRIu32 " bytes\n", internal); printf(" DMA Capable: %" PRIu32 " bytes\n", dma); } // --- CHIP INFO --- if (sys_args.info->count > 0) { esp_chip_info_t chip_info; esp_chip_info(&chip_info); printf("Hardware Info:\n"); printf(" Model: %s\n", get_chip_model_string(chip_info.model)); printf(" Cores: %d\n", chip_info.cores); // Revision format is typically MXX (Major, Minor) printf(" Revision: v%d.%02d\n", chip_info.revision / 100, chip_info.revision % 100); printf(" Features: "); if (chip_info.features & CHIP_FEATURE_WIFI_BGN) printf("WiFi-BGN "); if (chip_info.features & CHIP_FEATURE_BLE) printf("BLE "); if (chip_info.features & CHIP_FEATURE_BT) printf("BT "); if (chip_info.features & CHIP_FEATURE_EMB_FLASH) printf("Emb-Flash "); if (chip_info.features & CHIP_FEATURE_IEEE802154) printf("802.15.4 (Zigbee/Thread) "); printf("\n"); uint8_t mac[6]; if (esp_read_mac(mac, ESP_MAC_WIFI_STA) == ESP_OK) { printf(" MAC (STA): %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } if (esp_read_mac(mac, ESP_MAC_WIFI_SOFTAP) == ESP_OK) { printf(" MAC (AP): %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } } // --- REBOOT --- if (sys_args.reboot->count > 0) { ESP_LOGW(TAG, "Reboot requested by user."); printf("Rebooting system in 1 second...\n"); vTaskDelay(pdMS_TO_TICKS(1000)); esp_restart(); } return 0; } void register_system_cmd(void) { sys_args.reboot = arg_lit0(NULL, "reboot", "Reboot device"); sys_args.info = arg_lit0(NULL, "info", "Chip Info"); sys_args.heap = arg_lit0(NULL, "heap", "Memory Info"); sys_args.help = arg_lit0("h", "help", "Help"); sys_args.end = arg_end(1); const esp_console_cmd_t cmd = { .command = "system", .help = "System Management (Reboot, Info, Heap)", .func = &cmd_system, .argtable = &sys_args }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); }