Skip to content

Commit f8a8a2a

Browse files
me-no-devigrr
authored andcommitted
Implement Serial RX Buffer (#2239)
In connection with: #2237 #2037 #1683
1 parent edba2d2 commit f8a8a2a

File tree

4 files changed

+188
-56
lines changed

4 files changed

+188
-56
lines changed

cores/esp8266/HardwareSerial.cpp

+17-33
Original file line numberDiff line numberDiff line change
@@ -32,31 +32,34 @@
3232

3333

3434
HardwareSerial::HardwareSerial(int uart_nr)
35-
: _uart_nr(uart_nr)
35+
: _uart_nr(uart_nr), _rx_size(256)
3636
{}
3737

3838
void HardwareSerial::begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin)
39+
{
40+
end();
41+
_uart = uart_init(_uart_nr, baud, (int) config, (int) mode, tx_pin, _rx_size);
42+
}
43+
44+
void HardwareSerial::end()
3945
{
4046
if(uart_get_debug() == _uart_nr) {
4147
uart_set_debug(UART_NO);
4248
}
4349

4450
if (_uart) {
45-
free(_uart);
51+
uart_uninit(_uart);
52+
_uart = NULL;
4653
}
47-
48-
_uart = uart_init(_uart_nr, baud, (int) config, (int) mode, tx_pin);
49-
_peek_char = -1;
5054
}
5155

52-
void HardwareSerial::end()
53-
{
54-
if(uart_get_debug() == _uart_nr) {
55-
uart_set_debug(UART_NO);
56+
size_t HardwareSerial::setRxBufferSize(size_t size){
57+
if(_uart) {
58+
_rx_size = uart_resize_rx_buffer(_uart, size);
59+
} else {
60+
_rx_size = size;
5661
}
57-
58-
uart_uninit(_uart);
59-
_uart = NULL;
62+
return _rx_size;
6063
}
6164

6265
void HardwareSerial::swap(uint8_t tx_pin)
@@ -114,14 +117,7 @@ bool HardwareSerial::isRxEnabled(void)
114117

115118
int HardwareSerial::available(void)
116119
{
117-
if(!_uart || !uart_rx_enabled(_uart)) {
118-
return 0;
119-
}
120-
121120
int result = static_cast<int>(uart_rx_available(_uart));
122-
if (_peek_char != -1) {
123-
result += 1;
124-
}
125121
if (!result) {
126122
optimistic_yield(10000);
127123
}
@@ -130,25 +126,13 @@ int HardwareSerial::available(void)
130126

131127
int HardwareSerial::peek(void)
132128
{
133-
if (_peek_char != -1) {
134-
return _peek_char;
135-
}
136129
// this may return -1, but that's okay
137-
_peek_char = uart_read_char(_uart);
138-
return _peek_char;
130+
return uart_peek_char(_uart);
139131
}
140132

141133
int HardwareSerial::read(void)
142134
{
143-
if(!_uart || !uart_rx_enabled(_uart)) {
144-
return -1;
145-
}
146-
147-
if (_peek_char != -1) {
148-
auto tmp = _peek_char;
149-
_peek_char = -1;
150-
return tmp;
151-
}
135+
// this may return -1, but that's okay
152136
return uart_read_char(_uart);
153137
}
154138

cores/esp8266/HardwareSerial.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ class HardwareSerial: public Stream
8787

8888
void end();
8989

90+
size_t setRxBufferSize(size_t size);
91+
9092
void swap()
9193
{
9294
swap(1);
@@ -138,7 +140,7 @@ class HardwareSerial: public Stream
138140
protected:
139141
int _uart_nr;
140142
uart_t* _uart = nullptr;
141-
int _peek_char = -1;
143+
size_t _rx_size;
142144
};
143145

144146
extern HardwareSerial Serial;

cores/esp8266/uart.c

+164-21
Original file line numberDiff line numberDiff line change
@@ -47,51 +47,163 @@
4747

4848
static int s_uart_debug_nr = UART0;
4949

50+
struct uart_rx_buffer_ {
51+
size_t size;
52+
size_t rpos;
53+
size_t wpos;
54+
uint8_t * buffer;
55+
};
56+
5057
struct uart_ {
5158
int uart_nr;
5259
int baud_rate;
5360
bool rx_enabled;
5461
bool tx_enabled;
5562
uint8_t rx_pin;
5663
uint8_t tx_pin;
64+
struct uart_rx_buffer_ * rx_buffer;
5765
};
5866

59-
void uart_write_char(uart_t* uart, char c)
67+
size_t uart_resize_rx_buffer(uart_t* uart, size_t new_size)
6068
{
61-
if(uart == NULL || !uart->tx_enabled) {
62-
return;
69+
if(uart == NULL || !uart->rx_enabled) {
70+
return 0;
6371
}
64-
while((USS(uart->uart_nr) >> USTXC) >= 0x7f);
65-
USF(uart->uart_nr) = c;
66-
}
67-
68-
void uart_write(uart_t* uart, const char* buf, size_t size)
69-
{
70-
if(uart == NULL || !uart->tx_enabled) {
71-
return;
72+
if(uart->rx_buffer->size == new_size) {
73+
return uart->rx_buffer->size;
7274
}
73-
while(size--) {
74-
uart_write_char(uart, *buf++);
75+
uint8_t * new_buf = (uint8_t*)malloc(new_size);
76+
if(!new_buf) {
77+
return uart->rx_buffer->size;
7578
}
79+
size_t new_wpos = 0;
80+
ETS_UART_INTR_DISABLE();
81+
while(uart_rx_available(uart) && new_wpos < new_size) {
82+
new_buf[new_wpos++] = uart_read_char(uart);
83+
}
84+
uint8_t * old_buf = uart->rx_buffer->buffer;
85+
uart->rx_buffer->rpos = 0;
86+
uart->rx_buffer->wpos = new_wpos;
87+
uart->rx_buffer->size = new_size;
88+
uart->rx_buffer->buffer = new_buf;
89+
free(old_buf);
90+
ETS_UART_INTR_ENABLE();
91+
return uart->rx_buffer->size;
7692
}
7793

78-
int uart_read_char(uart_t* uart)
94+
int uart_peek_char(uart_t* uart)
7995
{
8096
if(uart == NULL || !uart->rx_enabled) {
8197
return -1;
8298
}
8399
if (!uart_rx_available(uart)) {
84100
return -1;
85101
}
86-
return USF(uart->uart_nr) & 0xff;
102+
return uart->rx_buffer->buffer[uart->rx_buffer->rpos];
103+
}
104+
105+
int uart_read_char(uart_t* uart)
106+
{
107+
int data = uart_peek_char(uart);
108+
if(data != -1) {
109+
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + 1) % uart->rx_buffer->size;
110+
}
111+
return data;
87112
}
88113

89114
size_t uart_rx_available(uart_t* uart)
90115
{
91116
if(uart == NULL || !uart->rx_enabled) {
92-
return -1;
117+
return 0;
118+
}
119+
if(uart->rx_buffer->wpos < uart->rx_buffer->rpos) {
120+
return (uart->rx_buffer->wpos + uart->rx_buffer->size) - uart->rx_buffer->rpos;
121+
}
122+
return uart->rx_buffer->wpos - uart->rx_buffer->rpos;
123+
}
124+
125+
126+
void ICACHE_RAM_ATTR uart_isr(void * arg)
127+
{
128+
uart_t* uart = (uart_t*)arg;
129+
if(uart == NULL || !uart->rx_enabled) {
130+
USIC(uart->uart_nr) = 0xffff;
131+
ETS_UART_INTR_DISABLE();
132+
return;
133+
}
134+
135+
uint32_t int_status = USIS(uart->uart_nr);
136+
137+
if(int_status & (1 << UIFR)) {
138+
USIC(uart->uart_nr) = (1 << UIFR);//clear any frame error
139+
}
140+
141+
if(int_status & (1 << UIFF) || int_status & (1 << UITO)){
142+
ETS_UART_INTR_DISABLE();
143+
while(((USS(uart->uart_nr) >> USRXC) & 0x7F) != 0){
144+
uint8_t data = USF(uart->uart_nr);
145+
size_t nextPos = (uart->rx_buffer->wpos + 1) % uart->rx_buffer->size;
146+
if(nextPos != uart->rx_buffer->rpos) {
147+
uart->rx_buffer->buffer[uart->rx_buffer->wpos] = data;
148+
uart->rx_buffer->wpos = nextPos;
149+
} else {
150+
//rx buffer OverFlow
151+
//maybe stop the loop and try later?
152+
}
153+
}
154+
int_status = USIS(uart->uart_nr);
155+
if(int_status & (1 << UIFF)) {
156+
USIC(uart->uart_nr) = (1 << UIFF);//clear any FIFO FULL error
157+
}
158+
if(int_status & (1 << UITO)) {
159+
USIC(uart->uart_nr) = (1 << UITO);//clear any TimeOut error
160+
}
161+
ETS_UART_INTR_ENABLE();
162+
}
163+
}
164+
165+
void uart_start_isr(uart_t* uart)
166+
{
167+
if(uart == NULL || !uart->rx_enabled) {
168+
return;
169+
}
170+
USC1(uart->uart_nr) = (127 << UCFFT) | (0x02 << UCTOT) | (1 <<UCTOE );
171+
USIC(uart->uart_nr) = 0xffff;
172+
USIE(uart->uart_nr) = (1 << UIFF) | (1 << UIFR) | (1 << UITO);
173+
ETS_UART_INTR_ATTACH(uart_isr, (void *)uart);
174+
ETS_UART_INTR_ENABLE();
175+
}
176+
177+
void uart_stop_isr(uart_t* uart)
178+
{
179+
if(uart == NULL || !uart->rx_enabled) {
180+
return;
181+
}
182+
ETS_UART_INTR_DISABLE();
183+
USC1(uart->uart_nr) = 0;
184+
USIC(uart->uart_nr) = 0xffff;
185+
USIE(uart->uart_nr) = 0;
186+
ETS_UART_INTR_ATTACH(NULL, NULL);
187+
}
188+
189+
190+
void uart_write_char(uart_t* uart, char c)
191+
{
192+
if(uart == NULL || !uart->tx_enabled) {
193+
return;
194+
}
195+
while((USS(uart->uart_nr) >> USTXC) >= 0x7f);
196+
USF(uart->uart_nr) = c;
197+
}
198+
199+
void uart_write(uart_t* uart, const char* buf, size_t size)
200+
{
201+
if(uart == NULL || !uart->tx_enabled) {
202+
return;
203+
}
204+
while(size--) {
205+
uart_write_char(uart, *buf++);
93206
}
94-
return (USS(uart->uart_nr) >> USRXC) & 0xff;
95207
}
96208

97209
size_t uart_tx_free(uart_t* uart)
@@ -121,6 +233,10 @@ void uart_flush(uart_t* uart)
121233
uint32_t tmp = 0x00000000;
122234
if(uart->rx_enabled) {
123235
tmp |= (1 << UCRXRST);
236+
ETS_UART_INTR_DISABLE();
237+
uart->rx_buffer->rpos = 0;
238+
uart->rx_buffer->wpos = 0;
239+
ETS_UART_INTR_ENABLE();
124240
}
125241

126242
if(uart->tx_enabled) {
@@ -148,7 +264,7 @@ int uart_get_baudrate(uart_t* uart)
148264
return uart->baud_rate;
149265
}
150266

151-
uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin)
267+
uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size)
152268
{
153269
uart_t* uart = (uart_t*) malloc(sizeof(uart_t));
154270
if(uart == NULL) {
@@ -159,9 +275,29 @@ uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin)
159275

160276
switch(uart->uart_nr) {
161277
case UART0:
278+
ETS_UART_INTR_DISABLE();
279+
ETS_UART_INTR_ATTACH(NULL, NULL);
162280
uart->rx_enabled = (mode != UART_TX_ONLY);
163281
uart->tx_enabled = (mode != UART_RX_ONLY);
164282
uart->rx_pin = (uart->rx_enabled)?3:255;
283+
if(uart->rx_enabled) {
284+
struct uart_rx_buffer_ * rx_buffer = (struct uart_rx_buffer_ *)malloc(sizeof(struct uart_rx_buffer_));
285+
if(rx_buffer == NULL) {
286+
free(uart);
287+
return NULL;
288+
}
289+
rx_buffer->size = rx_size;//var this
290+
rx_buffer->rpos = 0;
291+
rx_buffer->wpos = 0;
292+
rx_buffer->buffer = (uint8_t *)malloc(rx_buffer->size);
293+
if(rx_buffer->buffer == NULL) {
294+
free(rx_buffer);
295+
free(uart);
296+
return NULL;
297+
}
298+
uart->rx_buffer = rx_buffer;
299+
pinMode(uart->rx_pin, SPECIAL);
300+
}
165301
if(uart->tx_enabled) {
166302
if (tx_pin == 2) {
167303
uart->tx_pin = 2;
@@ -173,9 +309,6 @@ uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin)
173309
} else {
174310
uart->tx_pin = 255;
175311
}
176-
if(uart->rx_enabled) {
177-
pinMode(uart->rx_pin, SPECIAL);
178-
}
179312
IOSWAP &= ~(1 << IOSWAPU0);
180313
break;
181314
case UART1:
@@ -199,6 +332,11 @@ uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin)
199332
USC0(uart->uart_nr) = config;
200333
uart_flush(uart);
201334
USC1(uart->uart_nr) = 0;
335+
USIC(uart->uart_nr) = 0xffff;
336+
USIE(uart->uart_nr) = 0;
337+
if(uart->uart_nr == UART0 && uart->rx_enabled) {
338+
uart_start_isr(uart);
339+
}
202340

203341
return uart;
204342
}
@@ -230,6 +368,11 @@ void uart_uninit(uart_t* uart)
230368
break;
231369
}
232370

371+
if(uart->rx_enabled){
372+
free(uart->rx_buffer->buffer);
373+
free(uart->rx_buffer);
374+
//uart_stop_isr(uart);
375+
}
233376
free(uart);
234377
}
235378

cores/esp8266/uart.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ extern "C" {
113113
struct uart_;
114114
typedef struct uart_ uart_t;
115115

116-
uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin);
116+
uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size);
117117
void uart_uninit(uart_t* uart);
118118

119119
void uart_swap(uart_t* uart, int tx_pin);
@@ -125,9 +125,12 @@ bool uart_rx_enabled(uart_t* uart);
125125
void uart_set_baudrate(uart_t* uart, int baud_rate);
126126
int uart_get_baudrate(uart_t* uart);
127127

128+
size_t uart_resize_rx_buffer(uart_t* uart, size_t new_size);
129+
128130
void uart_write_char(uart_t* uart, char c);
129131
void uart_write(uart_t* uart, const char* buf, size_t size);
130132
int uart_read_char(uart_t* uart);
133+
int uart_peek_char(uart_t* uart);
131134
size_t uart_rx_available(uart_t* uart);
132135
size_t uart_tx_free(uart_t* uart);
133136
void uart_wait_tx_empty(uart_t* uart);

0 commit comments

Comments
 (0)