support for console redirection to other UART

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
This commit is contained in:
Ivan Grokhotkov 2016-10-27 16:17:28 +08:00
parent 6dc77bc55c
commit b3f6cd08db
4 changed files with 146 additions and 8 deletions

View 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
}

View 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"

View 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);

View 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();