diff --git a/components/bootloader_support/src/bootloader_console.c b/components/bootloader_support/src/bootloader_console.c index 0e8f2697bb..0de00bb51c 100644 --- a/components/bootloader_support/src/bootloader_console.c +++ b/components/bootloader_support/src/bootloader_console.c @@ -126,5 +126,12 @@ void bootloader_console_init(void) void bootloader_console_init(void) { esp_rom_output_switch_buffer(ESP_ROM_USB_SERIAL_DEVICE_NUM); + + /* Switch console channel to avoid output on UART and allow */ + esp_rom_output_set_as_console(ESP_ROM_USB_SERIAL_DEVICE_NUM); + + /* ROM printf by default also prints to USB-Serial-JTAG on channel 2 + need to disable to not print twice */ + esp_rom_install_channel_putc(2, NULL); } #endif //CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG diff --git a/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/pytest_usb_serial_jtag.py b/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/pytest_usb_serial_jtag.py index d76ee7fdba..6b10e901f9 100644 --- a/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/pytest_usb_serial_jtag.py +++ b/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/pytest_usb_serial_jtag.py @@ -1,6 +1,5 @@ # SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut @@ -13,7 +12,7 @@ from pytest_embedded import Dut @pytest.mark.parametrize( 'port, config', [ - ('/dev/ttyACM0', 'release'), + pytest.param('/dev/serial_ports/ttyACM-esp32', 'release'), ], indirect=True, ) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index bfcd94ca20..e20f2f7d3e 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -542,7 +542,9 @@ FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t pd_flags, int64_t sleep } else { /* Only flush the uart_num configured to console, the transmission integrity of other uarts is guaranteed by the UART driver */ - esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + if (CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + } } } else { suspend_uarts(); diff --git a/components/esp_system/port/soc/esp32c2/clk.c b/components/esp_system/port/soc/esp32c2/clk.c index a964f75b13..25d79e2199 100644 --- a/components/esp_system/port/soc/esp32c2/clk.c +++ b/components/esp_system/port/soc/esp32c2/clk.c @@ -116,7 +116,9 @@ __attribute__((weak)) void esp_clk_init(void) // Wait for UART TX to finish, otherwise some UART output will be lost // when switching APB frequency - esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + if (CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + } if (res) { rtc_clk_cpu_freq_set_config(&new_config); diff --git a/components/esp_system/port/soc/esp32c3/clk.c b/components/esp_system/port/soc/esp32c3/clk.c index e9914ae17b..fe35c4e60a 100644 --- a/components/esp_system/port/soc/esp32c3/clk.c +++ b/components/esp_system/port/soc/esp32c3/clk.c @@ -122,7 +122,9 @@ __attribute__((weak)) void esp_clk_init(void) // Wait for UART TX to finish, otherwise some UART output will be lost // when switching APB frequency - esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + if (CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + } if (res) { rtc_clk_cpu_freq_set_config(&new_config); diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index f7ceba2fa6..9ed553e6b5 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -122,7 +122,9 @@ __attribute__((weak)) void esp_clk_init(void) // Wait for UART TX to finish, otherwise some UART output will be lost // when switching APB frequency - esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + if (CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + } if (res) { rtc_clk_cpu_freq_set_config(&new_config); diff --git a/components/esp_system/port/soc/esp32c6/clk.c b/components/esp_system/port/soc/esp32c6/clk.c index 81ca7becae..66f86cd18e 100644 --- a/components/esp_system/port/soc/esp32c6/clk.c +++ b/components/esp_system/port/soc/esp32c6/clk.c @@ -118,7 +118,9 @@ __attribute__((weak)) void esp_clk_init(void) // Wait for UART TX to finish, otherwise some UART output will be lost // when switching APB frequency - esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + if (CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + } if (res) { rtc_clk_cpu_freq_set_config(&new_config); diff --git a/components/esp_system/port/soc/esp32h2/clk.c b/components/esp_system/port/soc/esp32h2/clk.c index 20c4df2f5a..4cd35b577b 100644 --- a/components/esp_system/port/soc/esp32h2/clk.c +++ b/components/esp_system/port/soc/esp32h2/clk.c @@ -117,7 +117,9 @@ __attribute__((weak)) void esp_clk_init(void) // Wait for UART TX to finish, otherwise some UART output will be lost // when switching APB frequency - esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + if (CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + } if (res) { rtc_clk_cpu_freq_set_config(&new_config); diff --git a/components/esp_system/port/soc/esp32p4/clk.c b/components/esp_system/port/soc/esp32p4/clk.c index a2e0c1f0cd..fc03e0d300 100644 --- a/components/esp_system/port/soc/esp32p4/clk.c +++ b/components/esp_system/port/soc/esp32p4/clk.c @@ -93,7 +93,9 @@ __attribute__((weak)) void esp_clk_init(void) // Wait for UART TX to finish, otherwise some UART output will be lost // when switching APB frequency - esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + if (CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + } if (res) { rtc_clk_cpu_freq_set_config(&new_config); diff --git a/components/esp_system/test_apps/.build-test-rules.yml b/components/esp_system/test_apps/.build-test-rules.yml index 1eebf6ca17..867c056945 100644 --- a/components/esp_system/test_apps/.build-test-rules.yml +++ b/components/esp_system/test_apps/.build-test-rules.yml @@ -1,5 +1,9 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps +components/esp_system/test_apps/console: + disable: + - if: CONFIG_NAME == "serial_jtag_only" and SOC_USB_SERIAL_JTAG_SUPPORTED != 1 + components/esp_system/test_apps/esp_system_unity_tests: disable: - if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1 diff --git a/components/esp_system/test_apps/console/CMakeLists.txt b/components/esp_system/test_apps/console/CMakeLists.txt new file mode 100644 index 0000000000..0e1dd698b2 --- /dev/null +++ b/components/esp_system/test_apps/console/CMakeLists.txt @@ -0,0 +1,12 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +list(PREPEND SDKCONFIG_DEFAULTS "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers") + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +project(test_esp_system_console_tests) diff --git a/components/esp_system/test_apps/console/README.md b/components/esp_system/test_apps/console/README.md new file mode 100644 index 0000000000..bf47d80ec6 --- /dev/null +++ b/components/esp_system/test_apps/console/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_system/test_apps/console/main/CMakeLists.txt b/components/esp_system/test_apps/console/main/CMakeLists.txt new file mode 100644 index 0000000000..443ab77c2c --- /dev/null +++ b/components/esp_system/test_apps/console/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "test_app_main.c" + REQUIRES vfs esp_driver_uart + WHOLE_ARCHIVE) diff --git a/components/esp_system/test_apps/console/main/test_app_main.c b/components/esp_system/test_apps/console/main/test_app_main.c new file mode 100644 index 0000000000..0740cdfc50 --- /dev/null +++ b/components/esp_system/test_apps/console/main/test_app_main.c @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "sdkconfig.h" + +#include "esp_rom_uart.h" +#include "esp_rom_sys.h" + +#include "hal/uart_ll.h" +#include "esp_private/uart_share_hw_ctrl.h" + +#include "driver/uart.h" +#include "soc/uart_channel.h" + +#if CONFIG_ESP_CONSOLE_NONE +/* Set up UART on UART_0 (console) to be able to + notify pytest test case that app booted successfully +*/ +#define CONSOLE_UART_NUM 0 + +static void console_none_print(void) +{ + /* Configure parameters of an UART driver, + * communication pins and install the driver */ + uart_config_t uart_config = { + .baud_rate = CONFIG_ESPTOOLPY_MONITOR_BAUD, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_DEFAULT, + }; + + ESP_ERROR_CHECK(uart_driver_install(CONSOLE_UART_NUM, 256, 0, 0, NULL, 0)); + ESP_ERROR_CHECK(uart_param_config(CONSOLE_UART_NUM, &uart_config)); + ESP_ERROR_CHECK(uart_set_pin(CONSOLE_UART_NUM, UART_NUM_0_TXD_DIRECT_GPIO_NUM, UART_NUM_0_RXD_DIRECT_GPIO_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); + + // Configure a temporary buffer for the incoming data + uint8_t data[] = "This message will be printed even with CONFIG_ESP_CONSOLE_NONE\r\n"; + + uart_write_bytes(CONSOLE_UART_NUM, data, sizeof(data)); +} +#endif + +void app_main(void) +{ + printf("Hello World\n"); + +#if CONFIG_ESP_CONSOLE_NONE + console_none_print(); +#endif // CONFIG_ESP_CONSOLE_NONE +} diff --git a/components/esp_system/test_apps/console/pytest_esp_system_console_tests.py b/components/esp_system/test_apps/console/pytest_esp_system_console_tests.py new file mode 100644 index 0000000000..730a390a47 --- /dev/null +++ b/components/esp_system/test_apps/console/pytest_esp_system_console_tests.py @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import pexpect +import pytest +from pytest_embedded import Dut + + +def not_expect(dut: Dut, output_regex: str) -> None: + try: + dut.expect(output_regex, timeout=5) + except pexpect.TIMEOUT: + pass + else: + raise RuntimeError(f'Found not_expect output {output_regex}') + + +JTAG_SERIAL_MARKS = [ + pytest.mark.esp32s3, + pytest.mark.esp32c2, + pytest.mark.esp32c3, + pytest.mark.esp32c6, + pytest.mark.esp32h2, + pytest.mark.esp32p4, +] + + +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + pytest.param('console_none', marks=pytest.mark.supported_targets), + ], + indirect=True +) +def test_esp_system_console_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') + + +@pytest.mark.usb_serial_jtag +@pytest.mark.parametrize( + 'port, config', + [ + pytest.param('/dev/serial_ports/ttyACM-esp32', 'serial_jtag_only', marks=JTAG_SERIAL_MARKS), + ], + indirect=True, +) +def test_esp_system_console_only_serial_jtag(dut: Dut) -> None: + dut.expect('2nd stage bootloader') + dut.expect('Hello World') diff --git a/components/esp_system/test_apps/console/sdkconfig.ci.console_none b/components/esp_system/test_apps/console/sdkconfig.ci.console_none new file mode 100644 index 0000000000..85ac33c784 --- /dev/null +++ b/components/esp_system/test_apps/console/sdkconfig.ci.console_none @@ -0,0 +1 @@ +CONFIG_ESP_CONSOLE_NONE=y diff --git a/components/esp_system/test_apps/console/sdkconfig.ci.serial_jtag_only b/components/esp_system/test_apps/console/sdkconfig.ci.serial_jtag_only new file mode 100644 index 0000000000..0ed159f5c9 --- /dev/null +++ b/components/esp_system/test_apps/console/sdkconfig.ci.serial_jtag_only @@ -0,0 +1,3 @@ +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y +# Disabled due to semihosting issue IDF-9574 +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=n diff --git a/components/unity/unity_port_esp32.c b/components/unity/unity_port_esp32.c index 2be18855d0..dc812f61ff 100644 --- a/components/unity/unity_port_esp32.c +++ b/components/unity/unity_port_esp32.c @@ -26,7 +26,9 @@ void unity_putc(int c) void unity_flush(void) { - esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + if(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); + } } #define iscontrol(c) ((c) <= '\x1f' || (c) == '\x7f')