Skip to content

Commit f1ff9e1

Browse files
committed
refactor(examples/storage): add nvs_console example
1 parent 24065c6 commit f1ff9e1

File tree

9 files changed

+480
-0
lines changed

9 files changed

+480
-0
lines changed

examples/storage/nvs/.build-test-rules.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ examples/storage/nvs/nvs_bootloader:
99
- if: CONFIG_NAME == "nvs_enc_hmac" and (SOC_HMAC_SUPPORTED != 1 or (SOC_HMAC_SUPPORTED == 1 and (SOC_AES_SUPPORTED != 1 and ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB != 1)))
1010
reason: As of now in such cases, we do not have any way to perform AES operations in the bootloader build
1111

12+
examples/storage/nvs/nvs_console:
13+
depends_components:
14+
- nvs_flash
15+
- console
16+
- vfs
17+
disable_test:
18+
- if: IDF_TARGET not in ["esp32", "esp32c3"]
19+
reason: only one target per arch needed
1220
examples/storage/nvs/nvs_rw_blob:
1321
depends_components:
1422
- nvs_flash
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# The following lines of boilerplate have to be in your project's CMakeLists
2+
# in this exact order for cmake to work correctly
3+
cmake_minimum_required(VERSION 3.16)
4+
5+
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/system/console/advanced/components")
6+
7+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
8+
project(nvs_console_example)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
2+
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- |
3+
4+
# NVS Console Example
5+
6+
This example demonstrates how to use Non-Volatile Storage (NVS) through an interactive console interface. It provides a set of commands to read, write, and manage data in NVS.
7+
8+
## Overview
9+
10+
The example implements a command-line interface with the following features:
11+
- Interactive console with command history
12+
- Command auto-completion
13+
- Command hints
14+
- Persistent command history (optional)
15+
- Color-coded output (on supported terminals)
16+
17+
## Hardware Required
18+
19+
This example can run on any ESP32 family development board.
20+
21+
## Configuration
22+
23+
The example can be configured through `menuconfig`:
24+
1. Enable/disable command history storage (`CONFIG_CONSOLE_STORE_HISTORY`)
25+
2. Configure UART parameters
26+
3. Configure console prompt color settings
27+
28+
## How to Use
29+
30+
### Build and Flash
31+
32+
Build the project and flash it to the board, then run monitor tool to view serial output:
33+
34+
```bash
35+
idf.py -p PORT flash monitor
36+
```
37+
38+
(Replace PORT with the name of the serial port to use.)
39+
40+
### Console Commands
41+
42+
The following commands are available:
43+
44+
1. NVS Operations:
45+
- `nvs_namespace <namespace>` - Set current namespace
46+
- Example: `nvs_namespace storage`
47+
48+
- `nvs_set <key> <type> -v <value>` - Set a value in NVS
49+
- type can be: i8, u8, i16, u16 i32, u32 i64, u64, str, blob
50+
- Example: `nvs_set counter i32 -v 42`
51+
- Example: `nvs_set name str -v "esp"`
52+
53+
- `nvs_get <key>` - Get a value from NVS
54+
- Example: `nvs_get counter`
55+
56+
- `nvs_erase <key>` - Erase a key from NVS
57+
- Example: `nvs_erase counter`
58+
59+
- `nvs_list <partition> [-n <namespace>] [-t <type>]` - List stored key-value pairs stored in NVS.
60+
- Example: `nvs_list nvs -n storage -t i8`
61+
62+
- `nvs_erase_namespace <namespace>` - Erases specified namespace
63+
- Example: `nvs_erase_namespace storage`
64+
65+
2. System Commands:
66+
- `help` - List all commands
67+
- `free` - Get the current size of free heap memory
68+
- `restart` - Software reset of the chip
69+
- `version` - Get version of chip and SDK
70+
- `heap` - Get minimum size of free heap memory that was available during program execution
71+
72+
### Example Output
73+
74+
``` bash
75+
...
76+
NVS Console Example
77+
-------------------
78+
Type 'help' to get the list of commands.
79+
Use UP/DOWN arrows to navigate through command history.
80+
Press TAB when typing command name to auto-complete.
81+
Press Ctrl+C to exit the console.
82+
83+
nvs> version
84+
IDF Version:v5.5-dev-2627-g2cbfce97768-dirt
85+
Chip info:
86+
model:ESP32
87+
cores:2
88+
feature:/802.11bgn/BLE/BT/External-Flash:2 MB
89+
revision number:0
90+
nvs> free
91+
298172
92+
nvs> heap
93+
min heap size: 298156
94+
nvs> nvs_list nvs
95+
namespace 'storage_1', key 'u8_key', type 'u8'
96+
namespace 'storage_1', key 'i8_key', type 'i8'
97+
namespace 'storage_1', key 'u16_key', type 'u16'
98+
namespace 'storage_2', key 'u32_key', type 'u32'
99+
namespace 'storage_2', key 'i32_key', type 'i32'
100+
namespace 'storage_2', key 'str_key', type 'str'
101+
nvs> nvs_namespace storage_1
102+
I (85497) cmd_nvs: Namespace set to 'storage_1'
103+
nvs> nvs_get i8_key i8
104+
-128
105+
nvs> nvs_set i8_key i8 -v -50
106+
I (233297) cmd_nvs: Value stored under key 'i8_key'
107+
nvs> nvs_get i8_key i8
108+
-50
109+
nvs>
110+
...
111+
```
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
idf_component_register(SRCS "nvs_console_main.c"
2+
"console_settings.c"
3+
REQUIRES cmd_nvs cmd_system esp_driver_uart fatfs
4+
INCLUDE_DIRS ".")
5+
6+
# Create a NVS image from the contents of the `nvs_data` CSV file
7+
# that fits the partition named 'nvs'. FLASH_IN_PROJECT indicates that
8+
# the generated image should be flashed when the entire project is flashed to
9+
# the target with 'idf.py -p PORT flash'.
10+
nvs_create_partition_image(nvs ../nvs_data.csv FLASH_IN_PROJECT)
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Unlicense OR CC0-1.0
5+
*/
6+
#include <stdio.h>
7+
#include <string.h>
8+
#include <unistd.h>
9+
#include <fcntl.h>
10+
#include "esp_system.h"
11+
#include "esp_log.h"
12+
#include "esp_console.h"
13+
#include "esp_vfs_dev.h"
14+
#include "driver/uart.h"
15+
#include "driver/uart_vfs.h"
16+
#include "linenoise/linenoise.h"
17+
#include "argtable3/argtable3.h"
18+
#include "console_settings.h"
19+
20+
#define CONSOLE_MAX_CMDLINE_ARGS 8
21+
#define CONSOLE_MAX_CMDLINE_LENGTH 256
22+
#define CONSOLE_PROMPT_MAX_LEN (32)
23+
24+
static const char *TAG = "console_settings";
25+
static char prompt[CONSOLE_PROMPT_MAX_LEN];
26+
27+
void initialize_console_peripheral(void)
28+
{
29+
/* Drain stdout before reconfiguring it */
30+
fflush(stdout);
31+
fsync(fileno(stdout));
32+
33+
/* Disable buffering on stdin */
34+
setvbuf(stdin, NULL, _IONBF, 0);
35+
36+
/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
37+
uart_vfs_dev_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
38+
/* Move the caret to the beginning of the next line on '\n' */
39+
uart_vfs_dev_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
40+
41+
/* Configure UART */
42+
const uart_config_t uart_config = {
43+
.baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE,
44+
.data_bits = UART_DATA_8_BITS,
45+
.parity = UART_PARITY_DISABLE,
46+
.stop_bits = UART_STOP_BITS_1,
47+
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
48+
.source_clk = UART_SCLK_REF_TICK,
49+
#else
50+
.source_clk = UART_SCLK_XTAL,
51+
#endif
52+
};
53+
54+
/* Install UART driver for interrupt-driven reads and writes */
55+
ESP_ERROR_CHECK(uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM,
56+
256, 0, 0, NULL, 0));
57+
ESP_ERROR_CHECK(uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config));
58+
59+
/* Tell VFS to use UART driver */
60+
uart_vfs_dev_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
61+
}
62+
63+
void initialize_console_library(const char *history_path)
64+
{
65+
/* Initialize the console */
66+
esp_console_config_t console_config = {
67+
.max_cmdline_args = CONSOLE_MAX_CMDLINE_ARGS,
68+
.max_cmdline_length = CONSOLE_MAX_CMDLINE_LENGTH,
69+
#if CONFIG_LOG_COLORS
70+
.hint_color = atoi(LOG_COLOR_CYAN)
71+
#endif
72+
};
73+
ESP_ERROR_CHECK(esp_console_init(&console_config));
74+
75+
/* Configure linenoise line completion library */
76+
linenoiseSetMultiLine(1);
77+
78+
/* Tell linenoise where to get command completions and hints */
79+
linenoiseSetCompletionCallback(&esp_console_get_completion);
80+
linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint);
81+
82+
/* Set command history size */
83+
linenoiseHistorySetMaxLen(100);
84+
85+
/* Set command maximum length */
86+
linenoiseSetMaxLineLen(console_config.max_cmdline_length);
87+
88+
/* Don't return empty lines */
89+
linenoiseAllowEmpty(false);
90+
91+
#if CONFIG_CONSOLE_STORE_HISTORY
92+
/* Load command history from filesystem */
93+
if (history_path) {
94+
linenoiseHistoryLoad(history_path);
95+
}
96+
#endif
97+
98+
/* Figure out if the terminal supports escape sequences */
99+
int probe_status = linenoiseProbe();
100+
if (probe_status) { /* zero indicates success */
101+
ESP_LOGW(TAG, "Your terminal application does not support escape sequences.\n"
102+
"Line editing and history features are disabled.\n"
103+
"On Windows, try using Windows Terminal or Putty instead.");
104+
linenoiseSetDumbMode(1);
105+
}
106+
}
107+
108+
char *setup_prompt(const char *prompt_str)
109+
{
110+
const char *prompt_temp = "esp>";
111+
if (prompt_str) {
112+
prompt_temp = prompt_str;
113+
}
114+
115+
/* Set command line prompt */
116+
if (linenoiseIsDumbMode()) {
117+
/* Since the terminal doesn't support escape sequences,
118+
* don't use color codes in the prompt */
119+
snprintf(prompt, CONSOLE_PROMPT_MAX_LEN - 1, "%s ", prompt_temp);
120+
} else {
121+
snprintf(prompt, CONSOLE_PROMPT_MAX_LEN - 1, LOG_COLOR_I "%s " LOG_RESET_COLOR, prompt_temp);
122+
}
123+
124+
return prompt;
125+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
/**
14+
* @brief Initialize console peripheral type
15+
*
16+
* Console peripheral is based on sdkconfig settings
17+
*
18+
* UART CONFIG_ESP_CONSOLE_UART_DEFAULT
19+
* USB_OTG CONFIG_ESP_CONSOLE_USB_CDC
20+
* USB_SERIAL_JTAG CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
21+
*/
22+
void initialize_console_peripheral(void);
23+
24+
/**
25+
* @brief Initialize linenoise and esp console
26+
*
27+
* This function initialize linenoise library and esp_console component,
28+
* also checks if the terminal supports escape sequences
29+
*
30+
* @param history_path Path to store command history
31+
*/
32+
void initialize_console_library(const char *history_path);
33+
34+
/**
35+
* @brief Initialize console prompt
36+
*
37+
* This function adds color code to the prompt (if the console supports escape sequences)
38+
*
39+
* @param prompt_str Prompt in form of string eg esp32s3>
40+
*
41+
* @return
42+
* - pointer to initialized prompt
43+
*/
44+
char *setup_prompt(const char *prompt_str);
45+
46+
#ifdef __cplusplus
47+
}
48+
#endif

0 commit comments

Comments
 (0)