diff --git a/cores/esp8266/esp8266_undocumented.h b/cores/esp8266/esp8266_undocumented.h index dc84e2f57..22216d962 100644 --- a/cores/esp8266/esp8266_undocumented.h +++ b/cores/esp8266/esp8266_undocumented.h @@ -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 diff --git a/cores/esp8266/uart.cpp b/cores/esp8266/uart.cpp index 30b375cba..b464c0653 100644 --- a/cores/esp8266/uart.cpp +++ b/cores/esp8266/uart.cpp @@ -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;