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