diff --git a/cores/esp8266/HardwareSerial.cpp b/cores/esp8266/HardwareSerial.cpp index b69729ae4b..979b0c0da4 100644 --- a/cores/esp8266/HardwareSerial.cpp +++ b/cores/esp8266/HardwareSerial.cpp @@ -32,31 +32,34 @@ HardwareSerial::HardwareSerial(int uart_nr) - : _uart_nr(uart_nr) + : _uart_nr(uart_nr), _rx_size(256) {} void HardwareSerial::begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin) +{ + end(); + _uart = uart_init(_uart_nr, baud, (int) config, (int) mode, tx_pin, _rx_size); +} + +void HardwareSerial::end() { if(uart_get_debug() == _uart_nr) { uart_set_debug(UART_NO); } if (_uart) { - free(_uart); + uart_uninit(_uart); + _uart = NULL; } - - _uart = uart_init(_uart_nr, baud, (int) config, (int) mode, tx_pin); - _peek_char = -1; } -void HardwareSerial::end() -{ - if(uart_get_debug() == _uart_nr) { - uart_set_debug(UART_NO); +size_t HardwareSerial::setRxBufferSize(size_t size){ + if(_uart) { + _rx_size = uart_resize_rx_buffer(_uart, size); + } else { + _rx_size = size; } - - uart_uninit(_uart); - _uart = NULL; + return _rx_size; } void HardwareSerial::swap(uint8_t tx_pin) @@ -114,14 +117,7 @@ bool HardwareSerial::isRxEnabled(void) int HardwareSerial::available(void) { - if(!_uart || !uart_rx_enabled(_uart)) { - return 0; - } - int result = static_cast(uart_rx_available(_uart)); - if (_peek_char != -1) { - result += 1; - } if (!result) { optimistic_yield(10000); } @@ -130,25 +126,13 @@ int HardwareSerial::available(void) int HardwareSerial::peek(void) { - if (_peek_char != -1) { - return _peek_char; - } // this may return -1, but that's okay - _peek_char = uart_read_char(_uart); - return _peek_char; + return uart_peek_char(_uart); } int HardwareSerial::read(void) { - if(!_uart || !uart_rx_enabled(_uart)) { - return -1; - } - - if (_peek_char != -1) { - auto tmp = _peek_char; - _peek_char = -1; - return tmp; - } + // this may return -1, but that's okay return uart_read_char(_uart); } diff --git a/cores/esp8266/HardwareSerial.h b/cores/esp8266/HardwareSerial.h index a05cb5d301..4b384fee53 100644 --- a/cores/esp8266/HardwareSerial.h +++ b/cores/esp8266/HardwareSerial.h @@ -87,6 +87,8 @@ class HardwareSerial: public Stream void end(); + size_t setRxBufferSize(size_t size); + void swap() { swap(1); @@ -138,7 +140,7 @@ class HardwareSerial: public Stream protected: int _uart_nr; uart_t* _uart = nullptr; - int _peek_char = -1; + size_t _rx_size; }; extern HardwareSerial Serial; diff --git a/cores/esp8266/uart.c b/cores/esp8266/uart.c index 123261aef8..9f0f0eb1be 100644 --- a/cores/esp8266/uart.c +++ b/cores/esp8266/uart.c @@ -47,6 +47,13 @@ static int s_uart_debug_nr = UART0; +struct uart_rx_buffer_ { + size_t size; + size_t rpos; + size_t wpos; + uint8_t * buffer; +}; + struct uart_ { int uart_nr; int baud_rate; @@ -54,28 +61,37 @@ struct uart_ { bool tx_enabled; uint8_t rx_pin; uint8_t tx_pin; + struct uart_rx_buffer_ * rx_buffer; }; -void uart_write_char(uart_t* uart, char c) +size_t uart_resize_rx_buffer(uart_t* uart, size_t new_size) { - if(uart == NULL || !uart->tx_enabled) { - return; + if(uart == NULL || !uart->rx_enabled) { + return 0; } - while((USS(uart->uart_nr) >> USTXC) >= 0x7f); - USF(uart->uart_nr) = c; -} - -void uart_write(uart_t* uart, const char* buf, size_t size) -{ - if(uart == NULL || !uart->tx_enabled) { - return; + if(uart->rx_buffer->size == new_size) { + return uart->rx_buffer->size; } - while(size--) { - uart_write_char(uart, *buf++); + 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(uart) && new_wpos < new_size) { + new_buf[new_wpos++] = uart_read_char(uart); + } + uint8_t * old_buf = uart->rx_buffer->buffer; + uart->rx_buffer->rpos = 0; + uart->rx_buffer->wpos = new_wpos; + uart->rx_buffer->size = new_size; + uart->rx_buffer->buffer = new_buf; + free(old_buf); + ETS_UART_INTR_ENABLE(); + return uart->rx_buffer->size; } -int uart_read_char(uart_t* uart) +int uart_peek_char(uart_t* uart) { if(uart == NULL || !uart->rx_enabled) { return -1; @@ -83,15 +99,111 @@ int uart_read_char(uart_t* uart) if (!uart_rx_available(uart)) { return -1; } - return USF(uart->uart_nr) & 0xff; + return uart->rx_buffer->buffer[uart->rx_buffer->rpos]; +} + +int uart_read_char(uart_t* uart) +{ + int data = uart_peek_char(uart); + if(data != -1) { + uart->rx_buffer->rpos = (uart->rx_buffer->rpos + 1) % uart->rx_buffer->size; + } + return data; } size_t uart_rx_available(uart_t* uart) { if(uart == NULL || !uart->rx_enabled) { - return -1; + return 0; + } + if(uart->rx_buffer->wpos < uart->rx_buffer->rpos) { + return (uart->rx_buffer->wpos + uart->rx_buffer->size) - uart->rx_buffer->rpos; + } + return uart->rx_buffer->wpos - uart->rx_buffer->rpos; +} + + +void ICACHE_RAM_ATTR uart_isr(void * arg) +{ + uart_t* uart = (uart_t*)arg; + if(uart == NULL || !uart->rx_enabled) { + USIC(uart->uart_nr) = 0xffff; + ETS_UART_INTR_DISABLE(); + return; + } + + uint32_t int_status = USIS(uart->uart_nr); + + if(int_status & (1 << UIFR)) { + USIC(uart->uart_nr) = (1 << UIFR);//clear any frame error + } + + if(int_status & (1 << UIFF) || int_status & (1 << UITO)){ + ETS_UART_INTR_DISABLE(); + while(((USS(uart->uart_nr) >> USRXC) & 0x7F) != 0){ + uint8_t data = USF(uart->uart_nr); + size_t nextPos = (uart->rx_buffer->wpos + 1) % uart->rx_buffer->size; + if(nextPos != uart->rx_buffer->rpos) { + uart->rx_buffer->buffer[uart->rx_buffer->wpos] = data; + uart->rx_buffer->wpos = nextPos; + } else { + //rx buffer OverFlow + //maybe stop the loop and try later? + } + } + int_status = USIS(uart->uart_nr); + if(int_status & (1 << UIFF)) { + USIC(uart->uart_nr) = (1 << UIFF);//clear any FIFO FULL error + } + if(int_status & (1 << UITO)) { + USIC(uart->uart_nr) = (1 << UITO);//clear any TimeOut error + } + ETS_UART_INTR_ENABLE(); + } +} + +void uart_start_isr(uart_t* uart) +{ + if(uart == NULL || !uart->rx_enabled) { + return; + } + USC1(uart->uart_nr) = (127 << UCFFT) | (0x02 << UCTOT) | (1 <uart_nr) = 0xffff; + USIE(uart->uart_nr) = (1 << UIFF) | (1 << UIFR) | (1 << UITO); + ETS_UART_INTR_ATTACH(uart_isr, (void *)uart); + ETS_UART_INTR_ENABLE(); +} + +void uart_stop_isr(uart_t* uart) +{ + if(uart == NULL || !uart->rx_enabled) { + return; + } + ETS_UART_INTR_DISABLE(); + USC1(uart->uart_nr) = 0; + USIC(uart->uart_nr) = 0xffff; + USIE(uart->uart_nr) = 0; + ETS_UART_INTR_ATTACH(NULL, NULL); +} + + +void uart_write_char(uart_t* uart, char c) +{ + if(uart == NULL || !uart->tx_enabled) { + return; + } + while((USS(uart->uart_nr) >> USTXC) >= 0x7f); + USF(uart->uart_nr) = c; +} + +void uart_write(uart_t* uart, const char* buf, size_t size) +{ + if(uart == NULL || !uart->tx_enabled) { + return; + } + while(size--) { + uart_write_char(uart, *buf++); } - return (USS(uart->uart_nr) >> USRXC) & 0xff; } size_t uart_tx_free(uart_t* uart) @@ -121,6 +233,10 @@ void uart_flush(uart_t* uart) uint32_t tmp = 0x00000000; if(uart->rx_enabled) { tmp |= (1 << UCRXRST); + ETS_UART_INTR_DISABLE(); + uart->rx_buffer->rpos = 0; + uart->rx_buffer->wpos = 0; + ETS_UART_INTR_ENABLE(); } if(uart->tx_enabled) { @@ -148,7 +264,7 @@ int uart_get_baudrate(uart_t* uart) return uart->baud_rate; } -uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin) +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)); if(uart == NULL) { @@ -159,9 +275,29 @@ uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin) switch(uart->uart_nr) { case UART0: + ETS_UART_INTR_DISABLE(); + ETS_UART_INTR_ATTACH(NULL, NULL); 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) { + struct uart_rx_buffer_ * rx_buffer = (struct uart_rx_buffer_ *)malloc(sizeof(struct uart_rx_buffer_)); + if(rx_buffer == NULL) { + free(uart); + return NULL; + } + rx_buffer->size = rx_size;//var this + rx_buffer->rpos = 0; + rx_buffer->wpos = 0; + rx_buffer->buffer = (uint8_t *)malloc(rx_buffer->size); + if(rx_buffer->buffer == NULL) { + free(rx_buffer); + free(uart); + return NULL; + } + uart->rx_buffer = rx_buffer; + pinMode(uart->rx_pin, SPECIAL); + } if(uart->tx_enabled) { if (tx_pin == 2) { uart->tx_pin = 2; @@ -173,9 +309,6 @@ uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin) } else { uart->tx_pin = 255; } - if(uart->rx_enabled) { - pinMode(uart->rx_pin, SPECIAL); - } IOSWAP &= ~(1 << IOSWAPU0); break; case UART1: @@ -199,6 +332,11 @@ uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin) USC0(uart->uart_nr) = config; uart_flush(uart); USC1(uart->uart_nr) = 0; + USIC(uart->uart_nr) = 0xffff; + USIE(uart->uart_nr) = 0; + if(uart->uart_nr == UART0 && uart->rx_enabled) { + uart_start_isr(uart); + } return uart; } @@ -230,6 +368,11 @@ void uart_uninit(uart_t* uart) break; } + if(uart->rx_enabled){ + free(uart->rx_buffer->buffer); + free(uart->rx_buffer); + //uart_stop_isr(uart); + } free(uart); } diff --git a/cores/esp8266/uart.h b/cores/esp8266/uart.h index e5480f2225..b79745adf5 100644 --- a/cores/esp8266/uart.h +++ b/cores/esp8266/uart.h @@ -113,7 +113,7 @@ extern "C" { struct uart_; typedef struct uart_ uart_t; -uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin); +uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size); void uart_uninit(uart_t* uart); void uart_swap(uart_t* uart, int tx_pin); @@ -125,9 +125,12 @@ bool uart_rx_enabled(uart_t* uart); void uart_set_baudrate(uart_t* uart, int baud_rate); int uart_get_baudrate(uart_t* uart); +size_t uart_resize_rx_buffer(uart_t* uart, size_t new_size); + void uart_write_char(uart_t* uart, char c); void uart_write(uart_t* uart, const char* buf, size_t size); int uart_read_char(uart_t* uart); +int uart_peek_char(uart_t* uart); size_t uart_rx_available(uart_t* uart); size_t uart_tx_free(uart_t* uart); void uart_wait_tx_empty(uart_t* uart);