1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Update UART selection for Boot ROM ets_putc, when debug port is selected. (#6489)

* Add code to select the UART for Boot ROM ets_putc which is used by
::printf, ets_printf_P in core_esp_postmortem.cpp and others.

ets_putc is a wrapper for uart_tx_one_char. uart_tx_one_char uses
the element buff_uart_no in UartDev (A structure in data area of the
Boot ROM) to select UART0 or UART1. uart_buff_switch is used to set
that entry.

The structure for UartDev can be found in uart.h from the
ESP8266_NONOS_SDK. As best I can tell the Boot ROM always
defaults to UART0.

* Fixes debug UART selection for ets_putc

This addresses an issue of UART selection for ROM function ets_putc,
which is used by ::printf, ets_printf_P in core_esp_postmortem.cpp
and others. Currently ets_putc stays on UART0 after
Serial1.setDebugOutput(true) is called.

ets_putc() is not affected by calls to ets_install_putc1.
Its UART selection is controlled by the ROM function uart_buff_switch.

Updated uart_set_debug() to call uart_buff_switch whenever debug is
enabled on an UART. For the case of disabling, a call to select UART0
is made, because there is no disable option for this print method.

* Removed fp_putc_t typedef, save for a later PR
This commit is contained in:
M Hightower 2019-09-23 14:05:27 -07:00 committed by Earle F. Philhower, III
parent 308e131dee
commit f3ca09006d
2 changed files with 106 additions and 77 deletions

View File

@ -11,6 +11,27 @@ extern int rom_i2c_readReg_Mask(int, int, int, int, int);
extern int uart_baudrate_detect(int, int);
/*
ROM function, uart_buff_switch(), is used to switch printing between UART0 and
UART1. It updates a structure that only controls a select group of print
functions. ets_putc() and ets_uart_printf() are examples and are not affected by
calls to ets_install_putc1().
Use:
0 for UART0, also clears RX FIFO
1 for UART1
*/
extern void uart_buff_switch(uint8_t);
/*
ROM function, ets_uart_printf(), prints on the UART selected by
uart_buff_switch(). Supported format options are the same as vprintf(). Also
has cooked newline behavior. No flash format/string support; however, ISR safe.
Also, uses a static function in ROM to print characters which is only
controlled by uart_buff_switch().
*/
extern int ets_uart_printf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
extern void ets_delay_us(uint32_t us);
#ifdef __cplusplus

View File

@ -83,7 +83,7 @@ struct uart_rx_buffer_
uint8_t * buffer;
};
struct uart_
struct uart_
{
int uart_nr;
int baud_rate;
@ -112,7 +112,7 @@ struct uart_
// called by ISR
inline size_t ICACHE_RAM_ATTR
uart_rx_fifo_available(const int uart_nr)
uart_rx_fifo_available(const int uart_nr)
{
return (USS(uart_nr) >> USRXC) & 0xFF;
}
@ -121,12 +121,12 @@ uart_rx_fifo_available(const int uart_nr)
/**********************************************************/
/************ UNSAFE FUNCTIONS ****************************/
/**********************************************************/
inline size_t
uart_rx_buffer_available_unsafe(const struct uart_rx_buffer_ * rx_buffer)
inline size_t
uart_rx_buffer_available_unsafe(const struct uart_rx_buffer_ * rx_buffer)
{
if(rx_buffer->wpos < rx_buffer->rpos)
if(rx_buffer->wpos < rx_buffer->rpos)
return (rx_buffer->wpos + rx_buffer->size) - rx_buffer->rpos;
return rx_buffer->wpos - rx_buffer->rpos;
}
@ -141,14 +141,14 @@ uart_rx_available_unsafe(uart_t* uart)
// Copy all the rx fifo bytes that fit into the rx buffer
// called by ISR
inline void ICACHE_RAM_ATTR
uart_rx_copy_fifo_to_buffer_unsafe(uart_t* uart)
uart_rx_copy_fifo_to_buffer_unsafe(uart_t* uart)
{
struct uart_rx_buffer_ *rx_buffer = uart->rx_buffer;
while(uart_rx_fifo_available(uart->uart_nr))
{
size_t nextPos = (rx_buffer->wpos + 1) % rx_buffer->size;
if(nextPos == rx_buffer->rpos)
if(nextPos == rx_buffer->rpos)
{
if (!uart->rx_overrun)
{
@ -175,17 +175,17 @@ uart_rx_copy_fifo_to_buffer_unsafe(uart_t* uart)
}
}
inline int
inline int
uart_peek_char_unsafe(uart_t* uart)
{
if (!uart_rx_available_unsafe(uart))
return -1;
//without the following if statement and body, there is a good chance of a fifo overrun
if (uart_rx_buffer_available_unsafe(uart->rx_buffer) == 0)
// hw fifo can't be peeked, data need to be copied to sw
uart_rx_copy_fifo_to_buffer_unsafe(uart);
return uart->rx_buffer->buffer[uart->rx_buffer->rpos];
}
@ -204,12 +204,12 @@ uart_read_char_unsafe(uart_t* uart)
return -1;
}
size_t
size_t
uart_rx_available(uart_t* uart)
{
if(uart == NULL || !uart->rx_enabled)
return 0;
ETS_UART_INTR_DISABLE();
int uartrxbufferavailable = uart_rx_buffer_available_unsafe(uart->rx_buffer);
ETS_UART_INTR_ENABLE();
@ -217,19 +217,19 @@ uart_rx_available(uart_t* uart)
return uartrxbufferavailable + uart_rx_fifo_available(uart->uart_nr);
}
int
int
uart_peek_char(uart_t* uart)
{
if(uart == NULL || !uart->rx_enabled)
return -1;
ETS_UART_INTR_DISABLE(); //access to rx_buffer can be interrupted by the isr (similar to a critical section), so disable interrupts here
int ret = uart_peek_char_unsafe(uart);
ETS_UART_INTR_ENABLE();
return ret;
}
int
int
uart_read_char(uart_t* uart)
{
uint8_t ret;
@ -322,26 +322,26 @@ static void ICACHE_RAM_ATTR uart_isr_handle_data(void* arg, uint8_t data)
USIC(uart->uart_nr) = usis;
}
size_t
size_t
uart_resize_rx_buffer(uart_t* uart, size_t new_size)
{
if(uart == NULL || !uart->rx_enabled)
if(uart == NULL || !uart->rx_enabled)
return 0;
if(uart->rx_buffer->size == new_size)
if(uart->rx_buffer->size == new_size)
return uart->rx_buffer->size;
uint8_t * new_buf = (uint8_t*)malloc(new_size);
if(!new_buf)
return uart->rx_buffer->size;
size_t new_wpos = 0;
ETS_UART_INTR_DISABLE();
while(uart_rx_available_unsafe(uart) && new_wpos < new_size)
new_buf[new_wpos++] = uart_read_char_unsafe(uart); //if uart_rx_available_unsafe() returns non-0, uart_read_char_unsafe() can't return -1
if (new_wpos == new_size)
new_wpos = 0;
uint8_t * old_buf = uart->rx_buffer->buffer;
uart->rx_buffer->rpos = 0;
uart->rx_buffer->wpos = new_wpos;
@ -359,13 +359,13 @@ uart_get_rx_buffer_size(uart_t* uart)
}
// The default ISR handler called when GDB is not enabled
void ICACHE_RAM_ATTR
void ICACHE_RAM_ATTR
uart_isr(void * arg)
{
uart_t* uart = (uart_t*)arg;
uint32_t usis = USIS(uart->uart_nr);
if(uart == NULL || !uart->rx_enabled)
if(uart == NULL || !uart->rx_enabled)
{
USIC(uart->uart_nr) = usis;
ETS_UART_INTR_DISABLE();
@ -380,14 +380,14 @@ uart_isr(void * arg)
uart->rx_overrun = true;
//os_printf_plus(overrun_str);
}
if (usis & ((1 << UIFR) | (1 << UIPE) | (1 << UITO)))
uart->rx_error = true;
USIC(uart->uart_nr) = usis;
}
static void
static void
uart_start_isr(uart_t* uart)
{
if(uart == NULL || !uart->rx_enabled)
@ -422,7 +422,7 @@ uart_start_isr(uart_t* uart)
ETS_UART_INTR_ENABLE();
}
static void
static void
uart_stop_isr(uart_t* uart)
{
if(uart == NULL || !uart->rx_enabled)
@ -459,7 +459,7 @@ uart_tx_fifo_full(const int uart_nr)
}
static void
static void
uart_do_write_char(const int uart_nr, char c)
{
while(uart_tx_fifo_full(uart_nr));
@ -467,7 +467,7 @@ uart_do_write_char(const int uart_nr, char c)
USF(uart_nr) = c;
}
size_t
size_t
uart_write_char(uart_t* uart, char c)
{
if(uart == NULL || !uart->tx_enabled)
@ -481,7 +481,7 @@ uart_write_char(uart_t* uart, char c)
return 1;
}
size_t
size_t
uart_write(uart_t* uart, const char* buf, size_t size)
{
if(uart == NULL || !uart->tx_enabled)
@ -501,7 +501,7 @@ uart_write(uart_t* uart, const char* buf, size_t size)
}
size_t
size_t
uart_tx_free(uart_t* uart)
{
if(uart == NULL || !uart->tx_enabled)
@ -510,7 +510,7 @@ uart_tx_free(uart_t* uart)
return UART_TX_FIFO_SIZE - uart_tx_fifo_available(uart->uart_nr);
}
void
void
uart_wait_tx_empty(uart_t* uart)
{
if(uart == NULL || !uart->tx_enabled)
@ -521,14 +521,14 @@ uart_wait_tx_empty(uart_t* uart)
}
void
void
uart_flush(uart_t* uart)
{
if(uart == NULL)
return;
uint32_t tmp = 0x00000000;
if(uart->rx_enabled)
if(uart->rx_enabled)
{
tmp |= (1 << UCRXRST);
ETS_UART_INTR_DISABLE();
@ -546,7 +546,7 @@ uart_flush(uart_t* uart)
}
}
void
void
uart_set_baudrate(uart_t* uart, int baud_rate)
{
if(uart == NULL)
@ -556,7 +556,7 @@ uart_set_baudrate(uart_t* uart, int baud_rate)
USD(uart->uart_nr) = (ESP8266_CLOCK / uart->baud_rate);
}
int
int
uart_get_baudrate(uart_t* uart)
{
if(uart == NULL)
@ -565,7 +565,7 @@ uart_get_baudrate(uart_t* uart)
return uart->baud_rate;
}
uart_t*
uart_t*
uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size)
{
uart_t* uart = (uart_t*) malloc(sizeof(uart_t));
@ -576,7 +576,7 @@ uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx
uart->rx_overrun = false;
uart->rx_error = false;
switch(uart->uart_nr)
switch(uart->uart_nr)
{
case UART0:
ETS_UART_INTR_DISABLE();
@ -586,10 +586,10 @@ uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx
uart->rx_enabled = (mode != UART_TX_ONLY);
uart->tx_enabled = (mode != UART_RX_ONLY);
uart->rx_pin = (uart->rx_enabled)?3:255;
if(uart->rx_enabled)
if(uart->rx_enabled)
{
struct uart_rx_buffer_ * rx_buffer = (struct uart_rx_buffer_ *)malloc(sizeof(struct uart_rx_buffer_));
if(rx_buffer == NULL)
if(rx_buffer == NULL)
{
free(uart);
return NULL;
@ -598,7 +598,7 @@ uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx
rx_buffer->rpos = 0;
rx_buffer->wpos = 0;
rx_buffer->buffer = (uint8_t *)malloc(rx_buffer->size);
if(rx_buffer->buffer == NULL)
if(rx_buffer->buffer == NULL)
{
free(rx_buffer);
free(uart);
@ -607,20 +607,20 @@ uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx
uart->rx_buffer = rx_buffer;
pinMode(uart->rx_pin, SPECIAL);
}
if(uart->tx_enabled)
if(uart->tx_enabled)
{
if (tx_pin == 2)
if (tx_pin == 2)
{
uart->tx_pin = 2;
pinMode(uart->tx_pin, FUNCTION_4);
}
else
}
else
{
uart->tx_pin = 1;
pinMode(uart->tx_pin, FUNCTION_0);
}
}
else
}
else
{
uart->tx_pin = 255;
}
@ -666,7 +666,7 @@ uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx
return uart;
}
void
void
uart_uninit(uart_t* uart)
{
if(uart == NULL)
@ -675,7 +675,7 @@ uart_uninit(uart_t* uart)
uart_stop_isr(uart);
if(uart->tx_enabled && (!gdbstub_has_uart_isr_control() || uart->uart_nr != UART0)) {
switch(uart->tx_pin)
switch(uart->tx_pin)
{
case 1:
pinMode(1, INPUT);
@ -693,7 +693,7 @@ uart_uninit(uart_t* uart)
free(uart->rx_buffer->buffer);
free(uart->rx_buffer);
if(!gdbstub_has_uart_isr_control()) {
switch(uart->rx_pin)
switch(uart->rx_pin)
{
case 3:
pinMode(3, INPUT);
@ -707,16 +707,16 @@ uart_uninit(uart_t* uart)
free(uart);
}
void
void
uart_swap(uart_t* uart, int tx_pin)
{
if(uart == NULL)
return;
switch(uart->uart_nr)
switch(uart->uart_nr)
{
case UART0:
if(((uart->tx_pin == 1 || uart->tx_pin == 2) && uart->tx_enabled) || (uart->rx_pin == 3 && uart->rx_enabled))
if(((uart->tx_pin == 1 || uart->tx_pin == 2) && uart->tx_enabled) || (uart->rx_pin == 3 && uart->rx_enabled))
{
if(uart->tx_enabled) //TX
{
@ -728,15 +728,15 @@ uart_swap(uart_t* uart, int tx_pin)
pinMode(uart->rx_pin, INPUT);
uart->rx_pin = 13;
}
if(uart->tx_enabled)
if(uart->tx_enabled)
pinMode(uart->tx_pin, FUNCTION_4); //TX
if(uart->rx_enabled)
pinMode(uart->rx_pin, FUNCTION_4); //RX
IOSWAP |= (1 << IOSWAPU0);
}
else
}
else
{
if(uart->tx_enabled) //TX
{
@ -751,7 +751,7 @@ uart_swap(uart_t* uart, int tx_pin)
if(uart->tx_enabled)
pinMode(uart->tx_pin, (tx_pin == 2)?FUNCTION_4:SPECIAL); //TX
if(uart->rx_enabled)
if(uart->rx_enabled)
pinMode(3, SPECIAL); //RX
IOSWAP &= ~(1 << IOSWAPU0);
@ -765,24 +765,24 @@ uart_swap(uart_t* uart, int tx_pin)
}
}
void
void
uart_set_tx(uart_t* uart, int tx_pin)
{
if(uart == NULL)
return;
switch(uart->uart_nr)
switch(uart->uart_nr)
{
case UART0:
if(uart->tx_enabled)
if(uart->tx_enabled)
{
if (uart->tx_pin == 1 && tx_pin == 2)
if (uart->tx_pin == 1 && tx_pin == 2)
{
pinMode(uart->tx_pin, INPUT);
uart->tx_pin = 2;
pinMode(uart->tx_pin, FUNCTION_4);
}
else if (uart->tx_pin == 2 && tx_pin != 2)
}
else if (uart->tx_pin == 2 && tx_pin != 2)
{
pinMode(uart->tx_pin, INPUT);
uart->tx_pin = 1;
@ -799,7 +799,7 @@ uart_set_tx(uart_t* uart, int tx_pin)
}
}
void
void
uart_set_pins(uart_t* uart, int tx, int rx)
{
if(uart == NULL)
@ -807,13 +807,13 @@ uart_set_pins(uart_t* uart, int tx, int rx)
if(uart->uart_nr == UART0) // Only UART0 allows pin changes
{
if(uart->tx_enabled && uart->tx_pin != tx)
if(uart->tx_enabled && uart->tx_pin != tx)
{
if( rx == 13 && tx == 15)
if( rx == 13 && tx == 15)
{
uart_swap(uart, 15);
}
else if (rx == 3 && (tx == 1 || tx == 2))
}
else if (rx == 3 && (tx == 1 || tx == 2))
{
if (uart->rx_pin != rx)
uart_swap(uart, tx);
@ -827,7 +827,7 @@ uart_set_pins(uart_t* uart, int tx, int rx)
}
bool
bool
uart_tx_enabled(uart_t* uart)
{
if(uart == NULL)
@ -836,7 +836,7 @@ uart_tx_enabled(uart_t* uart)
return uart->tx_enabled;
}
bool
bool
uart_rx_enabled(uart_t* uart)
{
if(uart == NULL)
@ -845,7 +845,7 @@ uart_rx_enabled(uart_t* uart)
return uart->rx_enabled;
}
bool
bool
uart_has_overrun (uart_t* uart)
{
if (uart == NULL || !uart->rx_overrun)
@ -867,7 +867,7 @@ uart_has_rx_error (uart_t* uart)
return true;
}
static void
static void
uart_ignore_char(char c)
{
(void) c;
@ -883,34 +883,42 @@ uart_write_char_delay(const int uart_nr, char c)
}
static void
static void
uart0_write_char(char c)
{
uart_write_char_delay(0, c);
}
static void
static void
uart1_write_char(char c)
{
uart_write_char_delay(1, c);
}
void
void
uart_set_debug(int uart_nr)
{
s_uart_debug_nr = uart_nr;
void (*func)(char) = NULL;
switch(s_uart_debug_nr)
switch(s_uart_debug_nr)
{
case UART0:
func = &uart0_write_char;
// This selects the UART for ROM ets_putc which is used by
// ::printf, ets_printf_P in core_esp_postmortem.cpp and others.
// Has a side effect of clearing RX FIFO for UART0
uart_buff_switch(0);
break;
case UART1:
func = &uart1_write_char;
uart_buff_switch(1);
break;
case UART_NO:
default:
func = &uart_ignore_char;
// There is no disable option for ets_putc,
// we switch to UART0 for disable case.
uart_buff_switch(0);
break;
}
if(gdbstub_has_putc1_control()) {
@ -925,7 +933,7 @@ uart_set_debug(int uart_nr)
}
}
int
int
uart_get_debug()
{
return s_uart_debug_nr;