feat(stdio): added esp_stdio component

esp_stdio contains everything the old esp_vfs_console contained (the vfs stdio glue layer)
as well as other functionality related to stdio (previously referred to as console)
This commit is contained in:
Marius Vikhammer
2025-07-24 14:38:03 +08:00
parent 7ce5732049
commit a257812e14
41 changed files with 371 additions and 341 deletions
+1 -2
View File
@@ -117,13 +117,12 @@
/components/esp_ringbuf/ @esp-idf-codeowners/system
/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
/components/esp_security/ @esp-idf-codeowners/security
/components/esp_stdio/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
/components/esp_system/ @esp-idf-codeowners/system
/components/esp_tee/ @esp-idf-codeowners/security
/components/esp_timer/ @esp-idf-codeowners/system
/components/esp-tls/ @esp-idf-codeowners/app-utilities
/components/esp_usb_cdc_rom_console/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals/usb
/components/esp_vfs_*/ @esp-idf-codeowners/storage
/components/esp_vfs_console/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
/components/esp_wifi/ @esp-idf-codeowners/wifi
/components/espcoredump/ @esp-idf-codeowners/debugging
/components/esptool_py/ @esp-idf-codeowners/tools
@@ -32,7 +32,8 @@ set(COMPONENTS
main
efuse
esp_libc
esp_tee)
esp_tee
esp_stdio)
# EXTRA_COMPONENT_DIRS can be populated with directories containing one or several components.
# Make sure this variable contains `bootloader_components` directory of the project being compiled.
+1 -1
View File
@@ -12,7 +12,7 @@ if(${target} STREQUAL "linux")
list(APPEND srcs "esp_console_repl_linux.c")
else()
list(APPEND srcs "esp_console_repl_chip.c")
list(APPEND requires esp_vfs_console)
list(APPEND requires esp_stdio)
endif()
set(argtable_srcs argtable3/arg_cmd.c
-81
View File
@@ -15,8 +15,6 @@
#include <sys/fcntl.h>
#include <sys/stat.h>
#include "sdkconfig.h"
#include "esp_rom_serial_output.h"
#include "esp_system_console.h"
static int syscall_not_implemented(struct _reent *r, ...)
{
@@ -29,85 +27,6 @@ static int syscall_not_implemented_aborts(void)
abort();
}
ssize_t _write_r_console(struct _reent *r, int fd, const void * data, size_t size)
{
#if !CONFIG_ESP_CONSOLE_NONE
const char* cdata = (const char*) data;
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
for (size_t i = 0; i < size; ++i) {
if (cdata[i] == '\n') {
esp_system_console_put_char('\r');
}
esp_system_console_put_char(cdata[i]);
}
return size;
}
#endif //!CONFIG_ESP_CONSOLE_NONE
__errno_r(r) = EBADF;
return -1;
}
ssize_t _read_r_console(struct _reent *r, int fd, void * data, size_t size)
{
#if !CONFIG_ESP_CONSOLE_NONE
char* cdata = (char*) data;
if (fd == STDIN_FILENO) {
size_t received;
for (received = 0; received < size; ++received) {
int status = esp_rom_output_rx_one_char((uint8_t*) &cdata[received]);
if (status != 0) {
break;
}
if (cdata[received] == '\r') {
cdata[received] = '\n';
}
}
if (received == 0) {
__errno_r(r) = EWOULDBLOCK;
return -1;
}
return received;
}
#endif //!CONFIG_ESP_CONSOLE_NONE
__errno_r(r) = EBADF;
return -1;
}
static ssize_t _fstat_r_console(struct _reent *r, int fd, struct stat * st)
{
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
memset(st, 0, sizeof(*st));
/* This needs to be set so that stdout and stderr are line buffered. */
st->st_mode = S_IFCHR;
return 0;
}
__errno_r(r) = EBADF;
return -1;
}
static int _fsync_console(int fd)
{
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
esp_rom_output_flush_tx(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM);
return 0;
}
errno = EBADF;
return -1;
}
/* The following weak definitions of syscalls will be used unless
* another definition is provided. That definition may come from
* VFS, LWIP, or the application.
*/
ssize_t _read_r(struct _reent *r, int fd, void *dst, size_t size)
__attribute__((weak, alias("_read_r_console")));
ssize_t _write_r(struct _reent *r, int fd, const void *data, size_t size)
__attribute__((weak, alias("_write_r_console")));
int _fstat_r(struct _reent *r, int fd, struct stat *st)
__attribute__((weak, alias("_fstat_r_console")));
int fsync(int fd)
__attribute__((weak, alias("_fsync_console")));
/* The aliases below are to "syscall_not_implemented", which
* doesn't have the same signature as the original function.
* Disable type mismatch warnings for this reason.
+29
View File
@@ -0,0 +1,29 @@
idf_build_get_property(target IDF_TARGET)
# Bootloader builds only needs it for config, not for anything else
idf_build_get_property(non_os_build NON_OS_BUILD)
if(non_os_build OR ${target} STREQUAL "linux")
idf_component_register()
return()
endif()
set(srcs "stdio_vfs.c"
"stdio_simple.c"
"stdio_syscalls_simple.c")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS include)
if(CONFIG_VFS_SUPPORT_IO)
# These drivers will be pulled in from the vfs driver
# This maintains the old behavior of just having to add vfs as a REQUIRES to enable
# the desired output driver. When we have requires that depend on kconfig values
# this can be refactored to conditionally pull drivers into the build instead
# TODO: IDF-13984 - Refactor to conditionally include stdio drivers based on Kconfig values
idf_component_optional_requires(PRIVATE vfs esp_driver_uart esp_driver_usb_serial_jtag esp_usb_cdc_rom_console)
target_link_libraries(${COMPONENT_LIB} PRIVATE idf::vfs)
# Make sure esp_stdio_register gets called at startup stage
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_vfs_include_console_register")
endif()
+188
View File
@@ -0,0 +1,188 @@
menu "ESP-STDIO"
choice ESP_CONSOLE_UART
prompt "Channel for console output"
default ESP_CONSOLE_UART_DEFAULT
help
Select where to send console output (through stdout and stderr).
- Default is to use UART0 on pre-defined GPIOs.
- If "Custom" is selected, UART0 or UART1 can be chosen,
and any pins can be selected.
- If "None" is selected, there will be no console output on any UART, except
for initial output from ROM bootloader. This ROM output can be suppressed by
GPIO strapping or EFUSE, refer to chip datasheet for details.
- On chips with USB OTG peripheral, "USB CDC" option redirects output to the
CDC port. This option uses the CDC driver in the chip ROM.
This option is incompatible with TinyUSB stack.
- On chips with an USB serial/JTAG debug controller, selecting the option
for that redirects output to the CDC/ACM (serial port emulation) component
of that device.
config ESP_CONSOLE_UART_DEFAULT
bool "Default: UART0"
config ESP_CONSOLE_USB_CDC
bool "USB CDC"
# && !TINY_USB is because the ROM CDC driver is currently incompatible with TinyUSB.
depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) && !TINY_USB
config ESP_CONSOLE_USB_SERIAL_JTAG
bool "USB Serial/JTAG Controller"
depends on SOC_USB_SERIAL_JTAG_SUPPORTED
config ESP_CONSOLE_UART_CUSTOM
bool "Custom UART"
config ESP_CONSOLE_NONE
bool "None"
endchoice
choice ESP_CONSOLE_SECONDARY
depends on SOC_USB_SERIAL_JTAG_SUPPORTED
prompt "Channel for console secondary output"
default ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
help
This secondary option supports output through other specific port like USB_SERIAL_JTAG
when UART0 port as a primary is selected but not connected. This secondary output currently only supports
non-blocking mode without using REPL. If you want to output in blocking mode with REPL or
input through this secondary port, please change the primary config to this port
in `Channel for console output` menu.
config ESP_CONSOLE_SECONDARY_NONE
bool "No secondary console"
config ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
bool "USB_SERIAL_JTAG PORT"
depends on !ESP_CONSOLE_USB_SERIAL_JTAG
help
This option supports output through USB_SERIAL_JTAG port when the UART0 port is not connected.
The output currently only supports non-blocking mode without using the console.
If you want to output in blocking mode with REPL or input through USB_SERIAL_JTAG port,
please change the primary config to ESP_CONSOLE_USB_SERIAL_JTAG above.
endchoice
config ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED
# Internal option, indicates that console USB SERIAL JTAG is used
bool
default y if ESP_CONSOLE_USB_SERIAL_JTAG || ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
select USJ_ENABLE_USB_SERIAL_JTAG
config ESP_CONSOLE_UART
# Internal option, indicates that console UART is used (and not USB, for example)
bool
default y if ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_CUSTOM
choice ESP_CONSOLE_UART_NUM
prompt "UART peripheral to use for console output (0-1)"
depends on ESP_CONSOLE_UART_CUSTOM
default ESP_CONSOLE_UART_CUSTOM_NUM_0
help
This UART peripheral is used for console output from the ESP-IDF Bootloader and the app.
If the configuration is different in the Bootloader binary compared to the app binary, UART
is reconfigured after the bootloader exits and the app starts.
Due to an ESP32 ROM bug, UART2 is not supported for console output
via esp_rom_printf.
config ESP_CONSOLE_UART_CUSTOM_NUM_0
bool "UART0"
config ESP_CONSOLE_UART_CUSTOM_NUM_1
bool "UART1"
endchoice
config ESP_CONSOLE_UART_NUM
int
default 0 if ESP_CONSOLE_UART_DEFAULT
default 0 if ESP_CONSOLE_UART_CUSTOM_NUM_0
default 1 if ESP_CONSOLE_UART_CUSTOM_NUM_1
default -1 if !ESP_CONSOLE_UART
config ESP_CONSOLE_ROM_SERIAL_PORT_NUM
# This config is used for the correct serial number used in ROM uart function.
int
default 0 if ESP_CONSOLE_UART_DEFAULT
default 0 if ESP_CONSOLE_UART_CUSTOM_NUM_0
default 1 if ESP_CONSOLE_UART_CUSTOM_NUM_1
# Can be extended if we have more uarts.
default ESP_ROM_USB_SERIAL_DEVICE_NUM if ESP_CONSOLE_USB_SERIAL_JTAG
default ESP_ROM_USB_OTG_NUM if ESP_CONSOLE_USB_CDC
default -1 if ESP_CONSOLE_NONE
config ESP_CONSOLE_UART_TX_GPIO
int "UART TX on GPIO<num>"
depends on ESP_CONSOLE_UART_CUSTOM
range -1 SOC_GPIO_OUT_RANGE_MAX
# Specific value for old targets for compatibility. No need to add for new targets.
default 1 if IDF_TARGET_ESP32
default 43 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 20 if IDF_TARGET_ESP32C2
default 21 if IDF_TARGET_ESP32C3
default 16 if IDF_TARGET_ESP32C6
default 37 if IDF_TARGET_ESP32P4
default 24 if IDF_TARGET_ESP32H2
default -1
help
This GPIO is used for console UART TX output in the ESP-IDF Bootloader and the app (including
boot log output and default standard output and standard error of the app). Value -1 means to
continue using the default console UART TX pin.
If the configuration is different in the Bootloader binary compared to the app binary, UART
is reconfigured after the bootloader exits and the app starts.
config ESP_CONSOLE_UART_RX_GPIO
int "UART RX on GPIO<num>"
depends on ESP_CONSOLE_UART_CUSTOM
range -1 SOC_GPIO_IN_RANGE_MAX
# Specific value for old targets for compatibility. No need to add for new targets.
default 3 if IDF_TARGET_ESP32
default 44 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 19 if IDF_TARGET_ESP32C2
default 20 if IDF_TARGET_ESP32C3
default 17 if IDF_TARGET_ESP32C6
default 38 if IDF_TARGET_ESP32P4
default 23 if IDF_TARGET_ESP32H2
default -1
help
This GPIO is used for console UART RX input in the ESP-IDF Bootloader and the app (including
default standard input of the app). Value -1 means to continue using the default console UART
RX pin.
Note: The default ESP-IDF Bootloader configures this pin but doesn't read anything from the UART.
If the configuration is different in the Bootloader binary compared to the app binary, UART
is reconfigured after the bootloader exits and the app starts.
config ESP_CONSOLE_UART_BAUDRATE
int
prompt "UART console baud rate" if ESP_CONSOLE_UART_CUSTOM
depends on ESP_CONSOLE_UART
default 74880 if (IDF_TARGET_ESP32C2 && XTAL_FREQ_26)
default 115200
range 1200 4000000 if !PM_ENABLE
range 1200 1000000 if PM_ENABLE
help
This baud rate is used by both the ESP-IDF Bootloader and the app (including
boot log output and default standard input/output/error of the app).
The app's maximum baud rate depends on the UART clock source. If Power Management is disabled,
the UART clock source is the APB clock and all baud rates in the available range will be sufficiently
accurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided
from 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be
accurate.
If the configuration is different in the Bootloader binary compared to the app binary, UART
is reconfigured after the bootloader exits and the app starts.
config ESP_CONSOLE_USB_CDC_RX_BUF_SIZE
int "Size of USB CDC RX buffer"
depends on ESP_CONSOLE_USB_CDC
default 64
range 4 16384
help
Set the size of USB CDC RX buffer. Increase the buffer size if your application
is often receiving data over USB CDC.
config ESP_CONSOLE_USB_CDC_SUPPORT_ETS_PRINTF
bool "Enable esp_rom_printf / ESP_EARLY_LOG via USB CDC"
depends on ESP_CONSOLE_USB_CDC
default n
help
If enabled, esp_rom_printf and ESP_EARLY_LOG output will also be sent over USB CDC.
Disabling this option saves about 1kB or RAM.
endmenu
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -19,7 +19,7 @@ extern "C" {
*
* This function is called from startup code to enable serial output
*/
esp_err_t esp_vfs_console_register(void);
esp_err_t esp_stdio_register(void);
#ifdef __cplusplus
}
@@ -0,0 +1,97 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <reent.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include "sdkconfig.h"
#include "esp_rom_serial_output.h"
#include "esp_system_console.h"
ssize_t _write_r_console(struct _reent *r, int fd, const void * data, size_t size)
{
#if !CONFIG_ESP_CONSOLE_NONE
const char* cdata = (const char*) data;
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
for (size_t i = 0; i < size; ++i) {
if (cdata[i] == '\n') {
esp_system_console_put_char('\r');
}
esp_system_console_put_char(cdata[i]);
}
return size;
}
#endif //!CONFIG_ESP_CONSOLE_NONE
__errno_r(r) = EBADF;
return -1;
}
ssize_t _read_r_console(struct _reent *r, int fd, void * data, size_t size)
{
#if !CONFIG_ESP_CONSOLE_NONE
char* cdata = (char*) data;
if (fd == STDIN_FILENO) {
size_t received;
for (received = 0; received < size; ++received) {
int status = esp_rom_output_rx_one_char((uint8_t*) &cdata[received]);
if (status != 0) {
break;
}
if (cdata[received] == '\r') {
cdata[received] = '\n';
}
}
if (received == 0) {
__errno_r(r) = EWOULDBLOCK;
return -1;
}
return received;
}
#endif //!CONFIG_ESP_CONSOLE_NONE
__errno_r(r) = EBADF;
return -1;
}
static ssize_t _fstat_r_console(struct _reent *r, int fd, struct stat * st)
{
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
memset(st, 0, sizeof(*st));
/* This needs to be set so that stdout and stderr are line buffered. */
st->st_mode = S_IFCHR;
return 0;
}
__errno_r(r) = EBADF;
return -1;
}
static int _fsync_console(int fd)
{
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
esp_rom_output_flush_tx(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM);
return 0;
}
errno = EBADF;
return -1;
}
/* The following weak definitions of syscalls will be used unless
* another definition is provided. That definition may come from
* VFS, LWIP, or the application.
*/
ssize_t _read_r(struct _reent *r, int fd, void *dst, size_t size)
__attribute__((weak, alias("_read_r_console")));
ssize_t _write_r(struct _reent *r, int fd, const void *data, size_t size)
__attribute__((weak, alias("_write_r_console")));
int _fstat_r(struct _reent *r, int fd, struct stat *st)
__attribute__((weak, alias("_fstat_r_console")));
int fsync(int fd)
__attribute__((weak, alias("_fsync_console")));
@@ -1,22 +1,24 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include <fcntl.h>
#include "esp_err.h"
#include "esp_rom_sys.h"
#include "esp_stdio.h"
#include <sys/errno.h>
#if CONFIG_VFS_SUPPORT_IO
#include "esp_vfs_cdcacm.h"
#include "esp_private/esp_vfs_cdcacm.h"
#include "driver/esp_private/usb_serial_jtag_vfs.h"
#include "driver/esp_private/uart_vfs.h"
#include "esp_private/usb_console.h"
#include "esp_vfs_console.h"
#include "sdkconfig.h"
#include "esp_private/startup_internal.h"
#include "esp_private/nullfs.h"
#include <sys/errno.h>
#endif
#define STRINGIFY(s) STRINGIFY2(s)
#define STRINGIFY2(s) #s
@@ -79,7 +81,6 @@ int console_open(const char * path, int flags, int mode)
ssize_t console_write(int fd, const void *data, size_t size)
{
// All function calls are to primary, except from write and close, which will be forwarded to both primary and secondary.
write(vfs_console.fd_primary, data, size);
#if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
write(vfs_console.fd_secondary, data, size);
@@ -237,7 +238,7 @@ static esp_err_t esp_vfs_dev_console_register(void)
return esp_vfs_register_fs(ESP_VFS_DEV_CONSOLE, &s_vfs_console, ESP_VFS_FLAG_STATIC, NULL);
}
esp_err_t esp_vfs_console_register(void)
esp_err_t esp_stdio_register(void)
{
esp_err_t err = ESP_OK;
// Primary vfs part.
@@ -261,7 +262,7 @@ esp_err_t esp_vfs_console_register(void)
ESP_SYSTEM_INIT_FN(init_vfs_console, CORE, BIT(0), 119)
{
return esp_vfs_console_register();
return esp_stdio_register();
}
#endif // CONFIG_VFS_SUPPORT_IO
@@ -0,0 +1,8 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/esp_stdio/test_apps/stdio:
disable:
- if: CONFIG_NAME == "serial_jtag_only" and SOC_USB_SERIAL_JTAG_SUPPORTED != 1
- if: CONFIG_NAME == "serial_jtag_only_no_vfs" and SOC_USB_SERIAL_JTAG_SUPPORTED != 1
- if: CONFIG_NAME == "stdio_no_vfs" and SOC_USB_SERIAL_JTAG_SUPPORTED != 1
disable_test:
- if: CONFIG_NAME == "simple" and IDF_TARGET != "esp32"
@@ -9,4 +9,4 @@ list(PREPEND SDKCONFIG_DEFAULTS "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfi
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
set(COMPONENTS main)
project(test_esp_system_console_tests)
project(test_esp_stdio_tests)
@@ -17,9 +17,9 @@ def not_expect(dut: Dut, output_regex: str) -> None:
@pytest.mark.generic
@idf_parametrize('config', ['console_none'], indirect=['config'])
@idf_parametrize('config', ['stdio_none'], indirect=['config'])
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_esp_system_console_no_output_uart(dut: Dut) -> None:
def test_esp_system_stdio_no_output_uart(dut: Dut) -> None:
not_expect(dut, r'2nd stage bootloader|Hello World')
dut.expect('This message will be printed even with CONFIG_ESP_CONSOLE_NONE')
@@ -29,7 +29,7 @@ def test_esp_system_console_no_output_uart(dut: Dut) -> None:
@idf_parametrize('flash_port', ['/dev/serial_ports/ttyUSB-esp32'], indirect=['flash_port'])
@idf_parametrize('port', ['/dev/serial_ports/ttyACM-esp32'], indirect=['port'])
@idf_parametrize('target', soc_filtered_targets('SOC_USB_SERIAL_JTAG_SUPPORTED == 1'), indirect=['target'])
def test_esp_system_console_only_serial_jtag(dut: Dut) -> None:
def test_esp_system_stdio_only_serial_jtag(dut: Dut) -> None:
dut.expect('2nd stage bootloader')
dut.expect('Hello World')
dut.expect('Opening /dev/console')
@@ -43,17 +43,17 @@ def test_esp_system_console_only_serial_jtag(dut: Dut) -> None:
@idf_parametrize('flash_port', ['/dev/serial_ports/ttyUSB-esp32'], indirect=['flash_port'])
@idf_parametrize('port', ['/dev/serial_ports/ttyACM-esp32'], indirect=['port'])
@idf_parametrize('target', soc_filtered_targets('SOC_USB_SERIAL_JTAG_SUPPORTED == 1'), indirect=['target'])
def test_esp_system_console_only_serial_jtag_no_vfs(dut: Dut) -> None:
def test_esp_system_stdio_only_serial_jtag_no_vfs(dut: Dut) -> None:
dut.expect('2nd stage bootloader')
dut.expect('Hello World')
@pytest.mark.usb_serial_jtag
@idf_parametrize('config', ['console_no_vfs'], indirect=['config'])
@idf_parametrize('config', ['stdio_no_vfs'], indirect=['config'])
@idf_parametrize('flash_port', ['/dev/serial_ports/ttyUSB-esp32'], indirect=['flash_port'])
@idf_parametrize('port', ['/dev/serial_ports/ttyACM-esp32'], indirect=['port'])
@idf_parametrize('target', soc_filtered_targets('SOC_USB_SERIAL_JTAG_SUPPORTED == 1'), indirect=['target'])
def test_esp_system_console_secondary_serial_jtag(dut: Dut) -> None:
def test_esp_system_stdio_secondary_serial_jtag(dut: Dut) -> None:
dut.expect('2nd stage bootloader')
dut.expect('Hello World')
@@ -61,7 +61,7 @@ def test_esp_system_console_secondary_serial_jtag(dut: Dut) -> None:
@pytest.mark.generic
@idf_parametrize('config', ['simple'], indirect=['config'])
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_esp_system_console_correct_open_and_close(dut: Dut) -> None:
def test_esp_system_stdio_correct_open_and_close(dut: Dut) -> None:
dut.expect('2nd stage bootloader')
dut.expect('Hello World')
dut.expect('Opening /dev/console')
-1
View File
@@ -32,7 +32,6 @@ else()
list(APPEND srcs "crosscore_int.c"
"esp_ipc.c"
"esp_err.c"
"esp_system_console.c"
"freertos_hooks.c"
"int_wdt.c"
"panic.c"
-186
View File
@@ -267,192 +267,6 @@ menu "ESP System Settings"
Minimal value of size, in bytes, accepted to execute a expression
with shared stack.
choice ESP_CONSOLE_UART
prompt "Channel for console output"
default ESP_CONSOLE_UART_DEFAULT
help
Select where to send console output (through stdout and stderr).
- Default is to use UART0 on pre-defined GPIOs.
- If "Custom" is selected, UART0 or UART1 can be chosen,
and any pins can be selected.
- If "None" is selected, there will be no console output on any UART, except
for initial output from ROM bootloader. This ROM output can be suppressed by
GPIO strapping or EFUSE, refer to chip datasheet for details.
- On chips with USB OTG peripheral, "USB CDC" option redirects output to the
CDC port. This option uses the CDC driver in the chip ROM.
This option is incompatible with TinyUSB stack.
- On chips with an USB serial/JTAG debug controller, selecting the option
for that redirects output to the CDC/ACM (serial port emulation) component
of that device.
config ESP_CONSOLE_UART_DEFAULT
bool "Default: UART0"
config ESP_CONSOLE_USB_CDC
bool "USB CDC"
# && !TINY_USB is because the ROM CDC driver is currently incompatible with TinyUSB.
depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) && !TINY_USB
config ESP_CONSOLE_USB_SERIAL_JTAG
bool "USB Serial/JTAG Controller"
depends on SOC_USB_SERIAL_JTAG_SUPPORTED
config ESP_CONSOLE_UART_CUSTOM
bool "Custom UART"
config ESP_CONSOLE_NONE
bool "None"
endchoice
choice ESP_CONSOLE_SECONDARY
depends on SOC_USB_SERIAL_JTAG_SUPPORTED
prompt "Channel for console secondary output"
default ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
help
This secondary option supports output through other specific port like USB_SERIAL_JTAG
when UART0 port as a primary is selected but not connected. This secondary output currently only supports
non-blocking mode without using REPL. If you want to output in blocking mode with REPL or
input through this secondary port, please change the primary config to this port
in `Channel for console output` menu.
config ESP_CONSOLE_SECONDARY_NONE
bool "No secondary console"
config ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
bool "USB_SERIAL_JTAG PORT"
depends on !ESP_CONSOLE_USB_SERIAL_JTAG
help
This option supports output through USB_SERIAL_JTAG port when the UART0 port is not connected.
The output currently only supports non-blocking mode without using the console.
If you want to output in blocking mode with REPL or input through USB_SERIAL_JTAG port,
please change the primary config to ESP_CONSOLE_USB_SERIAL_JTAG above.
endchoice
config ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED
# Internal option, indicates that console USB SERIAL JTAG is used
bool
default y if ESP_CONSOLE_USB_SERIAL_JTAG || ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
select USJ_ENABLE_USB_SERIAL_JTAG
config ESP_CONSOLE_UART
# Internal option, indicates that console UART is used (and not USB, for example)
bool
default y if ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_CUSTOM
choice ESP_CONSOLE_UART_NUM
prompt "UART peripheral to use for console output (0-1)"
depends on ESP_CONSOLE_UART_CUSTOM
default ESP_CONSOLE_UART_CUSTOM_NUM_0
help
This UART peripheral is used for console output from the ESP-IDF Bootloader and the app.
If the configuration is different in the Bootloader binary compared to the app binary, UART
is reconfigured after the bootloader exits and the app starts.
Due to an ESP32 ROM bug, UART2 is not supported for console output
via esp_rom_printf.
config ESP_CONSOLE_UART_CUSTOM_NUM_0
bool "UART0"
config ESP_CONSOLE_UART_CUSTOM_NUM_1
bool "UART1"
endchoice
config ESP_CONSOLE_UART_NUM
int
default 0 if ESP_CONSOLE_UART_DEFAULT
default 0 if ESP_CONSOLE_UART_CUSTOM_NUM_0
default 1 if ESP_CONSOLE_UART_CUSTOM_NUM_1
default -1 if !ESP_CONSOLE_UART
config ESP_CONSOLE_ROM_SERIAL_PORT_NUM
# This config is used for the correct serial number used in ROM uart function.
int
default 0 if ESP_CONSOLE_UART_DEFAULT
default 0 if ESP_CONSOLE_UART_CUSTOM_NUM_0
default 1 if ESP_CONSOLE_UART_CUSTOM_NUM_1
# Can be extended if we have more uarts.
default ESP_ROM_USB_SERIAL_DEVICE_NUM if ESP_CONSOLE_USB_SERIAL_JTAG
default ESP_ROM_USB_OTG_NUM if ESP_CONSOLE_USB_CDC
default -1 if ESP_CONSOLE_NONE
config ESP_CONSOLE_UART_TX_GPIO
int "UART TX on GPIO<num>"
depends on ESP_CONSOLE_UART_CUSTOM
range -1 SOC_GPIO_OUT_RANGE_MAX
# Specific value for old targets for compatibility. No need to add for new targets.
default 1 if IDF_TARGET_ESP32
default 43 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 20 if IDF_TARGET_ESP32C2
default 21 if IDF_TARGET_ESP32C3
default 16 if IDF_TARGET_ESP32C6
default 37 if IDF_TARGET_ESP32P4
default 24 if IDF_TARGET_ESP32H2
default -1
help
This GPIO is used for console UART TX output in the ESP-IDF Bootloader and the app (including
boot log output and default standard output and standard error of the app). Value -1 means to
continue using the default console UART TX pin.
If the configuration is different in the Bootloader binary compared to the app binary, UART
is reconfigured after the bootloader exits and the app starts.
config ESP_CONSOLE_UART_RX_GPIO
int "UART RX on GPIO<num>"
depends on ESP_CONSOLE_UART_CUSTOM
range -1 SOC_GPIO_IN_RANGE_MAX
# Specific value for old targets for compatibility. No need to add for new targets.
default 3 if IDF_TARGET_ESP32
default 44 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 19 if IDF_TARGET_ESP32C2
default 20 if IDF_TARGET_ESP32C3
default 17 if IDF_TARGET_ESP32C6
default 38 if IDF_TARGET_ESP32P4
default 23 if IDF_TARGET_ESP32H2
default -1
help
This GPIO is used for console UART RX input in the ESP-IDF Bootloader and the app (including
default standard input of the app). Value -1 means to continue using the default console UART
RX pin.
Note: The default ESP-IDF Bootloader configures this pin but doesn't read anything from the UART.
If the configuration is different in the Bootloader binary compared to the app binary, UART
is reconfigured after the bootloader exits and the app starts.
config ESP_CONSOLE_UART_BAUDRATE
int
prompt "UART console baud rate" if ESP_CONSOLE_UART_CUSTOM
depends on ESP_CONSOLE_UART
default 74880 if (IDF_TARGET_ESP32C2 && XTAL_FREQ_26)
default 115200
range 1200 4000000 if !PM_ENABLE
range 1200 1000000 if PM_ENABLE
help
This baud rate is used by both the ESP-IDF Bootloader and the app (including
boot log output and default standard input/output/error of the app).
The app's maximum baud rate depends on the UART clock source. If Power Management is disabled,
the UART clock source is the APB clock and all baud rates in the available range will be sufficiently
accurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided
from 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be
accurate.
If the configuration is different in the Bootloader binary compared to the app binary, UART
is reconfigured after the bootloader exits and the app starts.
config ESP_CONSOLE_USB_CDC_RX_BUF_SIZE
int "Size of USB CDC RX buffer"
depends on ESP_CONSOLE_USB_CDC
default 64
range 4 16384
help
Set the size of USB CDC RX buffer. Increase the buffer size if your application
is often receiving data over USB CDC.
config ESP_CONSOLE_USB_CDC_SUPPORT_ETS_PRINTF
bool "Enable esp_rom_printf / ESP_EARLY_LOG via USB CDC"
depends on ESP_CONSOLE_USB_CDC
default n
help
If enabled, esp_rom_printf and ESP_EARLY_LOG output will also be sent over USB CDC.
Disabling this option saves about 1kB or RAM.
config ESP_INT_WDT
bool "Interrupt watchdog"
default y
+1 -1
View File
@@ -57,7 +57,7 @@ CORE: 111: init_vfs_usj in components/esp_driver_usb_serial_jtag/src/usb_serial_
CORE: 112: init_vfs_usj_sec in components/esp_driver_usb_serial_jtag/src/usb_serial_jtag_vfs.c on BIT(0)
CORE: 113: init_vfs_usb_cdc_rom_console in components/esp_usb_cdc_rom_console/vfs_cdcacm.c on BIT(0)
CORE: 118: init_vfs_nullfs in components/vfs/nullfs.c on BIT(0)
CORE: 119: init_vfs_console in components/esp_vfs_console/vfs_console.c on BIT(0)
CORE: 119: init_vfs_console in components/esp_stdio/stdio_vfs.c on BIT(0)
CORE: 120: init_libc_stdio in components/esp_libc/src/init.c on BIT(0)
CORE: 130: init_flash in components/esp_system/startup_funcs.c on BIT(0)
@@ -4,14 +4,6 @@ components/esp_system/test_apps/cache_panic:
depends_components:
- spi_flash # esp_system is included by default
components/esp_system/test_apps/console:
disable:
- if: CONFIG_NAME == "serial_jtag_only" and SOC_USB_SERIAL_JTAG_SUPPORTED != 1
- if: CONFIG_NAME == "serial_jtag_only_no_vfs" and SOC_USB_SERIAL_JTAG_SUPPORTED != 1
- if: CONFIG_NAME == "console_no_vfs" and SOC_USB_SERIAL_JTAG_SUPPORTED != 1
disable_test:
- if: CONFIG_NAME == "simple" and IDF_TARGET != "esp32"
components/esp_system/test_apps/esp_system_unity_tests:
disable:
- if: (CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1)
+1 -1
View File
@@ -76,7 +76,7 @@ else()
idf_component_register(INCLUDE_DIRS include
SRCS ${srcs}
PRIV_REQUIRES efuse esp_security esp_system spi_flash esptool_py esp_hal_wdt)
PRIV_REQUIRES efuse esp_security esp_system esp_stdio spi_flash esptool_py esp_hal_wdt)
if(CONFIG_SECURE_ENABLE_TEE)
set(EXTRA_LINK_FLAGS)
+1 -1
View File
@@ -25,7 +25,7 @@ set(ESP_TEE_BUILD 1)
set(NON_OS_BUILD 1)
# Additional components
list(APPEND COMPONENTS bootloader_support efuse esp_security mbedtls)
list(APPEND COMPONENTS bootloader_support efuse esp_security mbedtls esp_stdio)
# TEE-specific components
list(APPEND COMPONENTS tee_flash_mgr tee_ota_ops tee_sec_storage tee_attestation)
@@ -7,7 +7,6 @@
#pragma once
#include "esp_err.h"
#include "esp_vfs.h"
#include "esp_vfs_common.h"
#ifdef __cplusplus
@@ -2,6 +2,6 @@ set(src "test_app_main.c")
idf_component_register(SRCS ${src}
PRIV_INCLUDE_DIRS .
PRIV_REQUIRES esp_system esp_vfs_console unity esp_usb_cdc_rom_console
PRIV_REQUIRES esp_system esp_stdio unity esp_usb_cdc_rom_console vfs
WHOLE_ARCHIVE
)
@@ -12,6 +12,7 @@
#include "esp_private/usb_console.h"
#include "esp_vfs_cdcacm.h"
#include "esp_rom_sys.h"
#include "esp_vfs.h"
static void flush_write(void)
{
-18
View File
@@ -1,18 +0,0 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(srcs "vfs_console.c")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS include
PRIV_REQUIRES vfs esp_driver_uart esp_driver_usb_serial_jtag esp_usb_cdc_rom_console
)
if(CONFIG_VFS_SUPPORT_IO)
target_link_libraries(${COMPONENT_LIB} PUBLIC idf::vfs)
# Make sure esp_vfs_console_register gets called at startup stage
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_vfs_include_console_register")
endif()
+1 -1
View File
@@ -23,7 +23,7 @@
_Static_assert(MAX_FDS >= CONFIG_LWIP_MAX_SOCKETS, "MAX_FDS < CONFIG_LWIP_MAX_SOCKETS");
_Static_assert(FD_SETSIZE >= CONFIG_LWIP_MAX_SOCKETS, "FD_SETSIZE < CONFIG_LWIP_MAX_SOCKETS");
_Static_assert(LWIP_SOCKET_OFFSET >= 6, "Not enough room for esp_vfs_console (LWIP_SOCKET_OFFSET < 6)");
_Static_assert(LWIP_SOCKET_OFFSET >= 6, "Not enough room for esp_stdio (LWIP_SOCKET_OFFSET < 6)");
#ifdef CONFIG_VFS_SUPPORT_SELECT
+7 -2
View File
@@ -9,14 +9,19 @@ endif()
set(sources "")
# These are here to pull the misc stdio drivers into the build when using VFS
# This maintains the old behavior of just having to add vfs as a REQUIRES to enable
# the desired output driver. When we have requires that depend on kconfig values
# this can be refactored to conditionally pull drivers into the build instead
# TODO: IDF-13984 - Refactor to conditionally include stdio drivers based on Kconfig values
list(APPEND pr esp_driver_uart esp_driver_usb_serial_jtag esp_usb_cdc_rom_console)
list(APPEND sources "vfs.c"
"vfs_eventfd.c"
"vfs_semihost.c"
"nullfs.c"
)
list(APPEND pr esp_vfs_console)
idf_component_register(SRCS ${sources}
LDFRAGMENTS "linker.lf"
INCLUDE_DIRS include
+6 -13
View File
@@ -1,16 +1,8 @@
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
@@ -27,6 +19,7 @@ typedef enum {
ESP_LINE_ENDINGS_LF, //!< LF
} esp_line_endings_t;
#ifdef __cplusplus
}
#endif
@@ -6,7 +6,6 @@
#include "sdkconfig.h"
#include "esp_vfs.h"
#include "esp_vfs_common.h"
#include <stddef.h>
#ifdef __cplusplus
@@ -11,3 +11,7 @@ VFS
- Deleted deprecated UART-VFS functions (```esp_vfs_dev_uart_*``) located in the ``vfs`` component. Please use API from UART driver instead: ``uart_vfs_dev_*``.
- Deleted deprecated USB-Serial-JTAG-VFS functions (```esp_vfs_dev_usb_serial_jtag_*``) located in the ``vfs`` component. Please use API from USB-Serial-JTAG driver instead: ``usb_serial_jtag_vfs_*``.
``esp_vfs_console``
--------------------
The ``esp_vfs_console`` component has been renamed to ``esp_stdio``. This component did not have any public functions, so in normal circumstances there is no need to update your code. If you for any reason had declared a dependency on this component it can be deleted, as the new ``esp_stdio`` is a common component that is added to all components by default.
-1
View File
@@ -504,7 +504,6 @@ components/spi_flash/include/spi_flash_chip_generic.h
components/spi_flash/spi_flash_chip_boya.c
components/spi_flash/spi_flash_chip_issi.c
components/tcp_transport/include/esp_transport_ws.h
components/vfs/include/esp_vfs_common.h
components/wpa_supplicant/esp_supplicant/src/esp_wpa_err.h
components/wpa_supplicant/include/utils/wpa_debug.h
components/wpa_supplicant/include/utils/wpabuf.h
+3 -2
View File
@@ -316,13 +316,14 @@ function(__build_init idf_path)
endforeach()
if("${target}" STREQUAL "linux")
set(requires_common freertos esp_hw_support heap log soc hal esp_rom esp_common esp_system linux)
set(requires_common freertos esp_hw_support heap log soc hal esp_rom esp_common esp_system linux esp_stdio)
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}")
else()
# Set components required by all other components in the build
#
# - esp_hw_support is here for backward compatibility
set(requires_common cxx esp_libc freertos esp_hw_support heap log soc hal esp_rom esp_common esp_system)
set(requires_common cxx esp_libc freertos esp_hw_support heap log soc hal
esp_rom esp_common esp_system esp_stdio)
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}")
endif()
@@ -5,7 +5,7 @@
cmake_minimum_required(VERSION 3.22)
set(g0_components soc hal esp_common esp_rom) # also <arch>, i.e. xtensa or riscv, will be added below
set(g1_components spi_flash freertos log heap esp_libc esp_system esp_hw_support esp_mm)
set(g1_components spi_flash freertos log heap esp_libc esp_system esp_hw_support esp_mm esp_stdio)
set(COMPONENTS ${g0_components} ${g1_components} main)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)