]> granicus.if.org Git - esp-idf/commitdiff
support for console redirection to other UART
authorIvan Grokhotkov <ivan@espressif.com>
Thu, 27 Oct 2016 08:17:28 +0000 (16:17 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Wed, 7 Dec 2016 17:42:37 +0000 (01:42 +0800)
This change adds a set of menuconfig options to set custom UART#, baud rate, and pins, for console output.
Setting happens in bootloader startup code for PRO CPU, and in application startup code for APP CPU.
Ref. TW8146

components/bootloader/src/main/bootloader_start.c
components/esp32/Kconfig
components/esp32/cpu_freq.c
components/esp32/cpu_start.c

index 8dd163fe3391b48950988e130bebb025c3f710b6..c3ddf0e10a3d89cc001b9e810482f36b01f3554e 100644 (file)
@@ -23,6 +23,8 @@
 #include "rom/spi_flash.h"
 #include "rom/crc.h"
 #include "rom/rtc.h"
+#include "rom/uart.h"
+#include "rom/gpio.h"
 
 #include "soc/soc.h"
 #include "soc/cpu.h"
@@ -31,6 +33,8 @@
 #include "soc/efuse_reg.h"
 #include "soc/rtc_cntl_reg.h"
 #include "soc/timer_group_reg.h"
+#include "soc/gpio_reg.h"
+#include "soc/gpio_sig_map.h"
 
 #include "sdkconfig.h"
 #include "esp_image_format.h"
@@ -62,7 +66,7 @@ void set_cache_and_start_app(uint32_t drom_addr,
     uint32_t irom_size,
     uint32_t entry_addr);
 static void update_flash_config(const esp_image_header_t* pfhdr);
-
+static void uart_console_configure(void);
 
 void IRAM_ATTR call_start_cpu0()
 {
@@ -224,6 +228,7 @@ static bool ota_select_valid(const esp_ota_select_entry_t *s)
 
 void bootloader_main()
 {
+    uart_console_configure();
     ESP_LOGI(TAG, "Espressif ESP32 2nd stage bootloader v. %s", BOOT_VERSION);
 
     esp_image_header_t fhdr;
@@ -616,3 +621,63 @@ void print_flash_info(const esp_image_header_t* phdr)
     ESP_LOGI(TAG, "SPI Flash Size : %s", str );
 #endif
 }
+
+static uint32_t get_apb_freq(void)
+{
+    // Get the value of APB clock from RTC memory.
+    // The value is initialized in ROM code, and updated by librtc.a
+    // when APB clock is changed.
+    // This value is stored in RTC_CNTL_STORE5_REG as follows:
+    // RTC_CNTL_STORE5_REG = (freq >> 12) | ((freq >> 12) << 16)
+    uint32_t apb_freq_reg = REG_READ(RTC_CNTL_STORE5_REG);
+    uint32_t apb_freq_l = apb_freq_reg & 0xffff;
+    uint32_t apb_freq_h = apb_freq_reg >> 16;
+    if (apb_freq_l == apb_freq_h && apb_freq_l != 0) {
+        return apb_freq_l << 12;
+    } else {
+        // fallback value
+        return APB_CLK_FREQ_ROM;
+    }
+}
+
+static void uart_console_configure(void)
+{
+#if CONFIG_CONSOLE_UART_NONE
+    ets_install_putc1(NULL);
+    ets_install_putc2(NULL);
+#else // CONFIG_CONSOLE_UART_NONE
+    uartAttach();
+    ets_install_uart_printf();
+
+#if CONFIG_CONSOLE_UART_CUSTOM
+    // Some constants to make the following code less upper-case
+    const int uart_num = CONFIG_CONSOLE_UART_NUM;
+    const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE;
+    const int uart_tx_gpio = CONFIG_CONSOLE_UART_TX_GPIO;
+    const int uart_rx_gpio = CONFIG_CONSOLE_UART_RX_GPIO;
+    // ROM bootloader may have put a lot of text into UART0 FIFO.
+    // Wait for it to be printed.
+    uart_tx_wait_idle(0);
+    // Switch to the new UART (this just changes UART number used for
+    // ets_printf in ROM code).
+    uart_tx_switch(uart_num);
+    // Set new baud rate
+    uart_div_modify(uart_num, (((uint64_t) get_apb_freq()) << 4) / uart_baud);
+    // 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 tx_idx = tx_idx_list[uart_num];
+        const uint32_t rx_idx = rx_idx_list[uart_num];
+        gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
+        gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
+    }
+#endif // CONFIG_CONSOLE_UART_CUSTOM
+#endif // CONFIG_CONSOLE_UART_NONE
+}
index 8300b444c59ea3e1028849f5249b742c70498365..79e0b374132b056360755d1104e4d7d0b574f3fb 100644 (file)
@@ -138,6 +138,64 @@ config NEWLIB_STDOUT_ADDCR
         is usually done by an added CR character. Enabling this will make the
         standard output code automatically add a CR character before a LF.
 
+choice CONSOLE_UART
+    prompt "UART for console output"
+    default CONSOLE_UART_DEFAULT
+    help
+        Select whether to use UART for console output (through stdout and stderr).
+        - Default is to use UART0 on pins GPIO1(TX) and GPIO3(RX).
+        - 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.
+
+config CONSOLE_UART_DEFAULT
+    bool "Default: UART0, TX=GPIO1, RX=GPIO3"
+config CONSOLE_UART_CUSTOM
+    bool "Custom"
+config CONSOLE_UART_NONE
+    bool "None"
+endchoice
+
+choice CONSOLE_UART_NUM
+       prompt "UART peripheral to use for console output (0-1)"
+       depends on CONSOLE_UART_CUSTOM
+    default CONSOLE_UART_CUSTOM_NUM_0
+    help
+       Due of a ROM bug, UART2 is not supported for console output
+       via ets_printf.
+
+config CONSOLE_UART_CUSTOM_NUM_0
+       bool "UART0"
+config CONSOLE_UART_CUSTOM_NUM_1
+       bool "UART1"
+endchoice
+
+config CONSOLE_UART_NUM
+       int
+       default 0 if CONSOLE_UART_DEFAULT || CONSOLE_UART_NONE
+       default 0 if CONSOLE_UART_CUSTOM_NUM_0
+       default 1 if CONSOLE_UART_CUSTOM_NUM_1
+
+config CONSOLE_UART_TX_GPIO
+       int "UART TX on GPIO#"
+       depends on CONSOLE_UART_CUSTOM
+       range 0 33
+       default 19
+
+config CONSOLE_UART_RX_GPIO
+       int "UART RX on GPIO#"
+       depends on CONSOLE_UART_CUSTOM
+       range 0 39
+       default 21
+
+config CONSOLE_UART_BAUDRATE
+       int "UART console baud rate"
+       depends on !CONSOLE_UART_NONE
+       default 115200
+       range 1200 4000000
+
 config ULP_COPROC_ENABLED
     bool "Enable Ultra Low Power (ULP) Coprocessor"
     default "n"
index c68dd4f078f6fd6be536203a2bbaefefb3ce7c6b..0e9dc23044f450605b3a9f502ddbc18c03dcfd1d 100644 (file)
@@ -33,7 +33,7 @@ void esp_set_cpu_freq(void)
 
     // freq will be changed to 40MHz in rtc_init_lite,
     // wait uart tx finish, otherwise some uart output will be lost
-    uart_tx_wait_idle(0);
+    uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
 
     rtc_init_lite(XTAL_AUTO);
     cpu_freq_t freq = CPU_80M;
@@ -54,7 +54,7 @@ void esp_set_cpu_freq(void)
 
     // freq will be changed to freq in rtc_set_cpu_freq,
     // wait uart tx finish, otherwise some uart output will be lost
-    uart_tx_wait_idle(0);
+    uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
 
     rtc_set_cpu_freq(freq);
     ets_update_cpu_frequency(freq_mhz);
index 1641ab3f0a3e0975d5df18b3183482e9fc3f4ef8..81c748c11f23ed97f2ed1a9ea0a796409d508d36 100644 (file)
@@ -54,6 +54,9 @@
 #include "esp_coexist.h"
 #include "trax.h"
 
+#define STRINGIFY(s) STRINGIFY2(s)
+#define STRINGIFY2(s) #s
+
 void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default")));
 void start_cpu0_default(void) IRAM_ATTR;
 #if !CONFIG_FREERTOS_UNICORE
@@ -97,9 +100,6 @@ void IRAM_ATTR call_start_cpu0()
                   "wsr    %0, vecbase\n" \
                   ::"r"(&_init_start));
 
-    uartAttach();
-    ets_install_uart_printf();
-
     memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
 
     /* Unless waking from deep sleep (implying RTC memory is intact), clear RTC bss */
@@ -145,6 +145,15 @@ void IRAM_ATTR call_start_cpu1()
 
     cpu_configure_region_protection();
 
+#if CONFIG_CONSOLE_UART_NONE
+    ets_install_putc1(NULL);
+    ets_install_putc2(NULL);
+#else // CONFIG_CONSOLE_UART_NONE
+    uartAttach();
+    ets_install_uart_printf();
+    uart_tx_switch(CONFIG_CONSOLE_UART_NUM);
+#endif
+
     ESP_EARLY_LOGI(TAG, "App cpu up.");
     app_cpu_started = 1;
     start_cpu1();
@@ -164,7 +173,7 @@ void start_cpu0_default(void)
     trax_start_trace(TRAX_DOWNCOUNT_WORDS);
 #endif
     esp_set_cpu_freq();     // set CPU frequency configured in menuconfig
-    uart_div_modify(0, (APB_CLK_FREQ << 4) / 115200);
+       uart_div_modify(CONFIG_CONSOLE_UART_NUM, (APB_CLK_FREQ << 4) / CONFIG_CONSOLE_UART_BAUDRATE);
 #if CONFIG_BROWNOUT_DET
     esp_brownout_init();
 #endif
@@ -177,10 +186,16 @@ void start_cpu0_default(void)
     esp_setup_time_syscalls();
     esp_vfs_dev_uart_register();
     esp_reent_init(_GLOBAL_REENT);
-    const char* default_uart_dev = "/dev/uart/0";
+#ifndef CONFIG_CONSOLE_UART_NONE
+    const char* default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_CONSOLE_UART_NUM);
     _GLOBAL_REENT->_stdin  = fopen(default_uart_dev, "r");
     _GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
     _GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
+#else
+    _GLOBAL_REENT->_stdin  = (FILE*) &__sf_fake_stdin;
+    _GLOBAL_REENT->_stdout = (FILE*) &__sf_fake_stdout;
+    _GLOBAL_REENT->_stderr = (FILE*) &__sf_fake_stderr;
+#endif
     do_global_ctors();
 #if !CONFIG_FREERTOS_UNICORE
     esp_crosscore_int_init();