From 5ee75165f256fe20fe55a66d14aae3aab310acac Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 30 Apr 2020 15:29:23 +0200 Subject: [PATCH] esp_common: add "USB CDC" option for console output --- .../src/bootloader_console.c | 104 ++++++++++++++++++ .../src/esp32/bootloader_esp32.c | 56 +--------- .../src/esp32s2/bootloader_esp32s2.c | 60 +--------- components/esp_common/Kconfig | 56 ++++++++-- components/esp_common/sdkconfig.rename | 3 +- 5 files changed, 156 insertions(+), 123 deletions(-) create mode 100644 components/bootloader_support/src/bootloader_console.c diff --git a/components/bootloader_support/src/bootloader_console.c b/components/bootloader_support/src/bootloader_console.c new file mode 100644 index 0000000000..31e3041acb --- /dev/null +++ b/components/bootloader_support/src/bootloader_console.c @@ -0,0 +1,104 @@ +// Copyright 2020 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. + +#include "sdkconfig.h" +#include "bootloader_console.h" +#include "soc/uart_periph.h" +#include "soc/uart_channel.h" +#include "soc/io_mux_reg.h" +#include "soc/gpio_periph.h" +#include "soc/gpio_sig_map.h" +#include "soc/rtc.h" +#include "hal/clk_gate_ll.h" +#ifdef CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/ets_sys.h" +#include "esp32/rom/uart.h" +#include "esp32/rom/gpio.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/ets_sys.h" +#include "esp32s2/rom/uart.h" +#include "esp32s2/rom/gpio.h" +#include "esp32s2/rom/usb/cdc_acm.h" +#include "esp32s2/rom/usb/usb_common.h" +#endif + +#ifdef CONFIG_ESP_CONSOLE_UART_NONE +void bootloader_console_init(void) +{ + ets_install_putc1(NULL); + ets_install_putc2(NULL); +} +#endif // CONFIG_ESP_CONSOLE_UART_NONE + +#ifdef CONFIG_ESP_CONSOLE_UART +void bootloader_console_init(void) +{ + const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM; + + ets_install_uart_printf(); + + // Wait for UART FIFO to be empty. + uart_tx_wait_idle(0); + +#if CONFIG_ESP_CONSOLE_UART_CUSTOM + // Some constants to make the following code less upper-case + const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO; + const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO; + // Switch to the new UART (this just changes UART number used for + // ets_printf in ROM code). + uart_tx_switch(uart_num); + // If console is attached to UART1 or if non-default pins are used, + // need to reconfigure pins using GPIO matrix + if (uart_num != 0 || + uart_tx_gpio != UART_NUM_0_TXD_DIRECT_GPIO_NUM || + uart_rx_gpio != UART_NUM_0_RXD_DIRECT_GPIO_NUM) { + // Change default UART pins back to GPIOs + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, PIN_FUNC_GPIO); + // Route GPIO signals to/from pins + const uint32_t tx_idx = uart_periph_signal[uart_num].tx_sig; + const uint32_t rx_idx = uart_periph_signal[uart_num].rx_sig; + PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]); + gpio_pad_pullup(uart_rx_gpio); + gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0); + gpio_matrix_in(uart_rx_gpio, rx_idx, 0); + // Enable the peripheral + periph_ll_enable_clk_clear_rst(PERIPH_UART0_MODULE + uart_num); + } +#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM + + // Set configured UART console baud rate + const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE; + uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud); +} +#endif // CONFIG_ESP_CONSOLE_UART + +#ifdef CONFIG_ESP_CONSOLE_USB_CDC +/* Buffer for CDC data structures. No RX buffer allocated. */ +static char s_usb_cdc_buf[CDC_ACM_WORK_BUF_MIN]; + +void bootloader_console_init(void) +{ +#ifdef CONFIG_IDF_TARGET_ESP32S2 + /* ESP32-S2 specific patch to set the correct serial number in the descriptor. + * Later chips don't need this. + */ + rom_usb_cdc_set_descriptor_patch(); +#endif + + Uart_Init_USB(s_usb_cdc_buf, sizeof(s_usb_cdc_buf)); + uart_tx_switch(ROM_UART_USB); + ets_install_putc1(bootloader_console_write_char_usb); +} +#endif //CONFIG_ESP_CONSOLE_USB_CDC diff --git a/components/bootloader_support/src/esp32/bootloader_esp32.c b/components/bootloader_support/src/esp32/bootloader_esp32.c index c1e8a618e0..d50350dfb8 100644 --- a/components/bootloader_support/src/esp32/bootloader_esp32.c +++ b/components/bootloader_support/src/esp32/bootloader_esp32.c @@ -23,6 +23,7 @@ #include "bootloader_common.h" #include "bootloader_flash_config.h" #include "bootloader_mem.h" +#include "bootloader_console.h" #include "soc/cpu.h" #include "soc/dport_reg.h" @@ -277,59 +278,6 @@ static esp_err_t bootloader_init_spi_flash(void) return ESP_OK; } -static void bootloader_init_uart_console(void) -{ -#if CONFIG_ESP_CONSOLE_UART_NONE - ets_install_putc1(NULL); - ets_install_putc2(NULL); -#else // CONFIG_ESP_CONSOLE_UART_NONE - const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM; - - uartAttach(); - ets_install_uart_printf(); - - // Wait for UART FIFO to be empty. - uart_tx_wait_idle(0); - -#if CONFIG_ESP_CONSOLE_UART_CUSTOM - // Some constants to make the following code less upper-case - const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO; - const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO; - // Switch to the new UART (this just changes UART number used for - // ets_printf in ROM code). - uart_tx_switch(uart_num); - // If console is attached to UART1 or if non-default pins are used, - // need to reconfigure pins using GPIO matrix - if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) { - // Change pin mode for GPIO1/3 from UART to GPIO - PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1); - // Route GPIO signals to/from pins - // (arrays should be optimized away by the compiler) - const uint32_t tx_idx_list[3] = {U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX}; - const uint32_t rx_idx_list[3] = {U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX}; - const uint32_t uart_reset[3] = {DPORT_UART_RST, DPORT_UART1_RST, DPORT_UART2_RST}; - const uint32_t tx_idx = tx_idx_list[uart_num]; - const uint32_t rx_idx = rx_idx_list[uart_num]; - - PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]); - gpio_pad_pullup(uart_rx_gpio); - - gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0); - gpio_matrix_in(uart_rx_gpio, rx_idx, 0); - - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]); - } -#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM - - // Set configured UART console baud rate - const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE; - uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud); - -#endif // CONFIG_ESP_CONSOLE_UART_NONE -} - static void wdt_reset_cpu0_info_enable(void) { //We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1. @@ -452,7 +400,7 @@ esp_err_t bootloader_init(void) // config clock bootloader_clock_configure(); // initialize uart console, from now on, we can use esp_log - bootloader_init_uart_console(); + bootloader_console_init(); /* print 2nd bootloader banner */ bootloader_print_banner(); // update flash ID diff --git a/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c b/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c index 972c9bfd24..ca73e2d2c4 100644 --- a/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c +++ b/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c @@ -26,12 +26,13 @@ #include "bootloader_clock.h" #include "bootloader_flash_config.h" #include "bootloader_mem.h" +#include "bootloader_console.h" #include "esp32s2/rom/cache.h" #include "esp32s2/rom/ets_sys.h" #include "esp32s2/rom/spi_flash.h" #include "esp32s2/rom/rtc.h" -#include "esp32s2/rom/uart.h" + #include "esp_attr.h" #include "esp_log.h" #include "esp_image_format.h" @@ -216,59 +217,6 @@ static esp_err_t bootloader_init_spi_flash(void) return ESP_OK; } -static void bootloader_init_uart_console(void) -{ -#if CONFIG_ESP_CONSOLE_UART_NONE - ets_install_putc1(NULL); - ets_install_putc2(NULL); -#else // CONFIG_ESP_CONSOLE_UART_NONE - const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM; - - uartAttach(NULL); - ets_install_uart_printf(); - - // Wait for UART FIFO to be empty. - uart_tx_wait_idle(0); - -#if CONFIG_ESP_CONSOLE_UART_CUSTOM - // Some constants to make the following code less upper-case - const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO; - const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO; - // Switch to the new UART (this just changes UART number used for - // ets_printf in ROM code). - uart_tx_switch(uart_num); - // If console is attached to UART1 or if non-default pins are used, - // need to reconfigure pins using GPIO matrix - if (uart_num != 0 || uart_tx_gpio != 43 || uart_rx_gpio != 44) { - // Change pin mode UART to GPIO - PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO44); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO43); - // Route GPIO signals to/from pins - // (arrays should be optimized away by the compiler) - const uint32_t tx_idx_list[2] = {U0TXD_OUT_IDX, U1TXD_OUT_IDX}; - const uint32_t rx_idx_list[2] = {U0RXD_IN_IDX, U1RXD_IN_IDX}; - const uint32_t uart_reset[2] = {DPORT_UART_RST, DPORT_UART1_RST}; - const uint32_t tx_idx = tx_idx_list[uart_num]; - const uint32_t rx_idx = rx_idx_list[uart_num]; - - PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]); - gpio_pad_pullup(uart_rx_gpio); - - gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0); - gpio_matrix_in(uart_rx_gpio, rx_idx, 0); - - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]); - } -#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM - - // Set configured UART console baud rate - const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE; - uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud); - -#endif // CONFIG_ESP_CONSOLE_UART_NONE -} - static void wdt_reset_cpu0_info_enable(void) { DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG); @@ -366,8 +314,8 @@ esp_err_t bootloader_init(void) bootloader_reset_mmu(); // config clock bootloader_clock_configure(); - // initialize uart console, from now on, we can use esp_log - bootloader_init_uart_console(); + // initialize console, from now on, we can use esp_log + bootloader_console_init(); /* print 2nd bootloader banner */ bootloader_print_banner(); // update flash ID diff --git a/components/esp_common/Kconfig b/components/esp_common/Kconfig index 919a95d6d6..671d02c4bb 100644 --- a/components/esp_common/Kconfig +++ b/components/esp_common/Kconfig @@ -62,33 +62,45 @@ menu "Common ESP-related" with shared stack. choice ESP_CONSOLE_UART - prompt "UART for console output" + prompt "Channel for console output" default ESP_CONSOLE_UART_DEFAULT help - Select whether to use UART for console output (through stdout and stderr). + 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 output can be further suppressed by - bootstrapping GPIO13 pin to low logic level. - + 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 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. config ESP_CONSOLE_UART_DEFAULT bool "Default: UART0" + config ESP_CONSOLE_USB_CDC + bool "USB CDC" + # The naming is confusing: USB_ENABLED means that TinyUSB driver is enabled, not USB in general. + # && !USB_ENABLED is because the ROM CDC driver is currently incompatible with TinyUSB. + depends on IDF_TARGET_ESP32S2 && !USB_ENABLED config ESP_CONSOLE_UART_CUSTOM - bool "Custom" - config ESP_CONSOLE_UART_NONE + bool "Custom UART" + config ESP_CONSOLE_NONE bool "None" endchoice + # Internal option, indicates that console UART is used (and not USB, for example) + config ESP_CONSOLE_UART + 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 - Due of a ROM bug, UART2 is not supported for console output - via ets_printf. + Select which UART peripheral to use for console output. + On ESP32, UART2 is not supported for console output via ets_printf. config ESP_CONSOLE_UART_CUSTOM_NUM_0 bool "UART0" @@ -98,28 +110,48 @@ menu "Common ESP-related" config ESP_CONSOLE_UART_NUM int - default 0 if ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_NONE + 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_UART_TX_GPIO int "UART TX on GPIO#" + depends on ESP_CONSOLE_UART_CUSTOM range 0 46 default 1 if IDF_TARGET_ESP32 default 43 if IDF_TARGET_ESP32S2 config ESP_CONSOLE_UART_RX_GPIO int "UART RX on GPIO#" + depends on ESP_CONSOLE_UART_CUSTOM range 0 46 default 3 if IDF_TARGET_ESP32 default 44 if IDF_TARGET_ESP32S2 config ESP_CONSOLE_UART_BAUDRATE - int "UART console baud rate" - depends on !ESP_CONSOLE_UART_NONE + int + prompt "UART console baud rate" if ESP_CONSOLE_UART_CUSTOM + depends on ESP_CONSOLE_UART default 115200 range 1200 4000000 + 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 ets_printf / ESP_EARLY_LOG via USB CDC" + depends on ESP_CONSOLE_USB_CDC + default n + help + If enabled, ets_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" diff --git a/components/esp_common/sdkconfig.rename b/components/esp_common/sdkconfig.rename index be65c9dcde..169f49a057 100644 --- a/components/esp_common/sdkconfig.rename +++ b/components/esp_common/sdkconfig.rename @@ -8,7 +8,8 @@ CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STAC CONFIG_CONSOLE_UART CONFIG_ESP_CONSOLE_UART CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT CONFIG_CONSOLE_UART_CUSTOM CONFIG_ESP_CONSOLE_UART_CUSTOM -CONFIG_CONSOLE_UART_NONE CONFIG_ESP_CONSOLE_UART_NONE +CONFIG_CONSOLE_UART_NONE CONFIG_ESP_CONSOLE_NONE +CONFIG_ESP_CONSOLE_UART_NONE CONFIG_ESP_CONSOLE_NONE CONFIG_CONSOLE_UART_NUM CONFIG_ESP_CONSOLE_UART_NUM CONFIG_CONSOLE_UART_CUSTOM_NUM_0 CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0 CONFIG_CONSOLE_UART_CUSTOM_NUM_1 CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_1