4747#include "user_interface.h"
4848#include "uart_register.h"
4949
50- const char overrun_str [] PROGMEM STORE_ATTR = "uart input full!\r\n" ;
50+ // const char overrun_str [] PROGMEM STORE_ATTR = "uart input full!\r\n";
5151static int s_uart_debug_nr = UART0 ;
5252
5353
54- struct uart_rx_buffer_
54+ struct uart_rx_buffer_
5555{
5656 size_t size ;
5757 size_t rpos ;
@@ -65,7 +65,8 @@ struct uart_
6565 int baud_rate ;
6666 bool rx_enabled ;
6767 bool tx_enabled ;
68- bool overrun ;
68+ bool rx_overrun ;
69+ bool rx_error ;
6970 uint8_t rx_pin ;
7071 uint8_t tx_pin ;
7172 struct uart_rx_buffer_ * rx_buffer ;
@@ -85,7 +86,8 @@ struct uart_
8586
8687
8788
88- inline size_t
89+ // called by ISR
90+ inline size_t ICACHE_RAM_ATTR
8991uart_rx_fifo_available (const int uart_nr )
9092{
9193 return (USS (uart_nr ) >> USRXC ) & 0xFF ;
@@ -110,11 +112,11 @@ uart_rx_available_unsafe(uart_t* uart)
110112 return uart_rx_buffer_available_unsafe (uart -> rx_buffer ) + uart_rx_fifo_available (uart -> uart_nr );
111113}
112114
113-
114115//#define UART_DISCARD_NEWEST
115116
116117// Copy all the rx fifo bytes that fit into the rx buffer
117- inline void
118+ // called by ISR
119+ inline void ICACHE_RAM_ATTR
118120uart_rx_copy_fifo_to_buffer_unsafe (uart_t * uart )
119121{
120122 struct uart_rx_buffer_ * rx_buffer = uart -> rx_buffer ;
@@ -124,11 +126,10 @@ uart_rx_copy_fifo_to_buffer_unsafe(uart_t* uart)
124126 size_t nextPos = (rx_buffer -> wpos + 1 ) % rx_buffer -> size ;
125127 if (nextPos == rx_buffer -> rpos )
126128 {
127-
128- if (!uart -> overrun )
129+ if (!uart -> rx_overrun )
129130 {
130- uart -> overrun = true;
131- os_printf_plus (overrun_str );
131+ uart -> rx_overrun = true;
132+ // os_printf_plus(overrun_str);
132133 }
133134
134135 // a choice has to be made here,
@@ -158,25 +159,27 @@ uart_peek_char_unsafe(uart_t* uart)
158159
159160 //without the following if statement and body, there is a good chance of a fifo overrun
160161 if (uart_rx_buffer_available_unsafe (uart -> rx_buffer ) == 0 )
162+ // hw fifo can't be peeked, data need to be copied to sw
161163 uart_rx_copy_fifo_to_buffer_unsafe (uart );
162164
163165 return uart -> rx_buffer -> buffer [uart -> rx_buffer -> rpos ];
164166}
165167
166- inline int
168+ // taking data straight from hw fifo: loopback-test BW jumps by 19%
169+ inline int
167170uart_read_char_unsafe (uart_t * uart )
168171{
169- int data = uart_peek_char_unsafe (uart );
170- if (data != -1 )
172+ if (uart_rx_buffer_available_unsafe (uart -> rx_buffer ))
173+ {
174+ // take oldest sw data
175+ int ret = uart -> rx_buffer -> buffer [uart -> rx_buffer -> rpos ];
171176 uart -> rx_buffer -> rpos = (uart -> rx_buffer -> rpos + 1 ) % uart -> rx_buffer -> size ;
172- return data ;
177+ return ret ;
178+ }
179+ // unavailable
180+ return -1 ;
173181}
174182
175-
176- /**********************************************************/
177-
178-
179-
180183size_t
181184uart_rx_available (uart_t * uart )
182185{
@@ -204,14 +207,47 @@ uart_peek_char(uart_t* uart)
204207
205208int
206209uart_read_char (uart_t * uart )
210+ {
211+ uint8_t ret ;
212+ return uart_read (uart , (char * )& ret , 1 )? ret : -1 ;
213+ }
214+
215+ // loopback-test BW jumps by 190%
216+ size_t
217+ uart_read (uart_t * uart , char * userbuffer , size_t usersize )
207218{
208219 if (uart == NULL || !uart -> rx_enabled )
209- return -1 ;
210-
220+ return 0 ;
221+
222+ size_t ret = 0 ;
211223 ETS_UART_INTR_DISABLE ();
212- int data = uart_read_char_unsafe (uart );
224+
225+ while (ret < usersize && uart_rx_available_unsafe (uart ))
226+ {
227+ if (!uart_rx_buffer_available_unsafe (uart -> rx_buffer ))
228+ {
229+ // no more data in sw buffer, take them from hw fifo
230+ while (ret < usersize && uart_rx_fifo_available (uart -> uart_nr ))
231+ userbuffer [ret ++ ] = USF (uart -> uart_nr );
232+
233+ // no more sw/hw data available
234+ break ;
235+ }
236+
237+ // pour sw buffer to user's buffer
238+ // get largest linear length from sw buffer
239+ size_t chunk = uart -> rx_buffer -> rpos < uart -> rx_buffer -> wpos ?
240+ uart -> rx_buffer -> wpos - uart -> rx_buffer -> rpos :
241+ uart -> rx_buffer -> size - uart -> rx_buffer -> rpos ;
242+ if (ret + chunk > usersize )
243+ chunk = usersize - ret ;
244+ memcpy (userbuffer + ret , uart -> rx_buffer -> buffer + uart -> rx_buffer -> rpos , chunk );
245+ uart -> rx_buffer -> rpos = (uart -> rx_buffer -> rpos + chunk ) % uart -> rx_buffer -> size ;
246+ ret += chunk ;
247+ }
248+
213249 ETS_UART_INTR_ENABLE ();
214- return data ;
250+ return ret ;
215251}
216252
217253size_t
@@ -231,6 +267,8 @@ uart_resize_rx_buffer(uart_t* uart, size_t new_size)
231267 ETS_UART_INTR_DISABLE ();
232268 while (uart_rx_available_unsafe (uart ) && new_wpos < new_size )
233269 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
270+ if (new_wpos == new_size )
271+ new_wpos = 0 ;
234272
235273 uint8_t * old_buf = uart -> rx_buffer -> buffer ;
236274 uart -> rx_buffer -> rpos = 0 ;
@@ -242,22 +280,39 @@ uart_resize_rx_buffer(uart_t* uart, size_t new_size)
242280 return uart -> rx_buffer -> size ;
243281}
244282
283+ size_t
284+ uart_get_rx_buffer_size (uart_t * uart )
285+ {
286+ return uart && uart -> rx_enabled ? uart -> rx_buffer -> size : 0 ;
287+ }
245288
246289
247290void ICACHE_RAM_ATTR
248291uart_isr (void * arg )
249292{
250293 uart_t * uart = (uart_t * )arg ;
294+ uint32_t usis = USIS (uart -> uart_nr );
295+
251296 if (uart == NULL || !uart -> rx_enabled )
252297 {
253- USIC (uart -> uart_nr ) = USIS ( uart -> uart_nr ) ;
298+ USIC (uart -> uart_nr ) = usis ;
254299 ETS_UART_INTR_DISABLE ();
255300 return ;
256301 }
257- if (USIS (uart -> uart_nr ) & ((1 << UIFF ) | (1 << UITO )))
302+
303+ if (usis & (1 << UIFF ))
258304 uart_rx_copy_fifo_to_buffer_unsafe (uart );
305+
306+ if ((usis & (1 << UIOF )) && !uart -> rx_overrun )
307+ {
308+ uart -> rx_overrun = true;
309+ //os_printf_plus(overrun_str);
310+ }
259311
260- USIC (uart -> uart_nr ) = USIS (uart -> uart_nr );
312+ if (usis & ((1 << UIFR ) | (1 << UIPE ) | (1 << UITO )))
313+ uart -> rx_error = true;
314+
315+ USIC (uart -> uart_nr ) = usis ;
261316}
262317
263318static void
@@ -270,9 +325,22 @@ uart_start_isr(uart_t* uart)
270325 // triggers the IRS very often. A value of 127 would not leave much time
271326 // for ISR to clear fifo before the next byte is dropped. So pick a value
272327 // in the middle.
273- USC1 (uart -> uart_nr ) = (100 << UCFFT ) | (0x02 << UCTOT ) | (1 <<UCTOE );
328+ // update: loopback test @ 3Mbauds/8n1 (=2343Kibits/s):
329+ // - 4..120 give > 2300Kibits/s
330+ // - 1, 2, 3 are below
331+ // was 100, use 16 to stay away from overrun
332+ #define INTRIGG 16
333+
334+ //was:USC1(uart->uart_nr) = (INTRIGG << UCFFT) | (0x02 << UCTOT) | (1 <<UCTOE);
335+ USC1 (uart -> uart_nr ) = (INTRIGG << UCFFT );
274336 USIC (uart -> uart_nr ) = 0xffff ;
275- USIE (uart -> uart_nr ) = (1 << UIFF ) | (1 << UIFR ) | (1 << UITO );
337+ //was: USIE(uart->uart_nr) = (1 << UIFF) | (1 << UIFR) | (1 << UITO);
338+ // UIFF: rx fifo full
339+ // UIOF: rx fifo overflow (=overrun)
340+ // UIFR: frame error
341+ // UIPE: parity error
342+ // UITO: rx fifo timeout
343+ USIE (uart -> uart_nr ) = (1 << UIFF ) | (1 << UIOF ) | (1 << UIFR ) | (1 << UIPE ) | (1 << UITO );
276344 ETS_UART_INTR_ATTACH (uart_isr , (void * )uart );
277345 ETS_UART_INTR_ENABLE ();
278346}
@@ -415,7 +483,8 @@ uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx
415483 return NULL ;
416484
417485 uart -> uart_nr = uart_nr ;
418- uart -> overrun = false;
486+ uart -> rx_overrun = false;
487+ uart -> rx_error = false;
419488
420489 switch (uart -> uart_nr )
421490 {
@@ -678,11 +747,22 @@ uart_rx_enabled(uart_t* uart)
678747bool
679748uart_has_overrun (uart_t * uart )
680749{
681- if (uart == NULL || !uart -> overrun )
750+ if (uart == NULL || !uart -> rx_overrun )
751+ return false;
752+
753+ // clear flag
754+ uart -> rx_overrun = false;
755+ return true;
756+ }
757+
758+ bool
759+ uart_has_rx_error (uart_t * uart )
760+ {
761+ if (uart == NULL || !uart -> rx_error )
682762 return false;
683763
684764 // clear flag
685- uart -> overrun = false;
765+ uart -> rx_error = false;
686766 return true;
687767}
688768
0 commit comments