47
47
#include "user_interface.h"
48
48
#include "uart_register.h"
49
49
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";
51
51
static int s_uart_debug_nr = UART0 ;
52
52
53
53
54
- struct uart_rx_buffer_
54
+ struct uart_rx_buffer_
55
55
{
56
56
size_t size ;
57
57
size_t rpos ;
@@ -65,7 +65,8 @@ struct uart_
65
65
int baud_rate ;
66
66
bool rx_enabled ;
67
67
bool tx_enabled ;
68
- bool overrun ;
68
+ bool rx_overrun ;
69
+ bool rx_error ;
69
70
uint8_t rx_pin ;
70
71
uint8_t tx_pin ;
71
72
struct uart_rx_buffer_ * rx_buffer ;
@@ -85,7 +86,8 @@ struct uart_
85
86
86
87
87
88
88
- inline size_t
89
+ // called by ISR
90
+ inline size_t ICACHE_RAM_ATTR
89
91
uart_rx_fifo_available (const int uart_nr )
90
92
{
91
93
return (USS (uart_nr ) >> USRXC ) & 0xFF ;
@@ -110,11 +112,11 @@ uart_rx_available_unsafe(uart_t* uart)
110
112
return uart_rx_buffer_available_unsafe (uart -> rx_buffer ) + uart_rx_fifo_available (uart -> uart_nr );
111
113
}
112
114
113
-
114
115
//#define UART_DISCARD_NEWEST
115
116
116
117
// 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
118
120
uart_rx_copy_fifo_to_buffer_unsafe (uart_t * uart )
119
121
{
120
122
struct uart_rx_buffer_ * rx_buffer = uart -> rx_buffer ;
@@ -124,11 +126,10 @@ uart_rx_copy_fifo_to_buffer_unsafe(uart_t* uart)
124
126
size_t nextPos = (rx_buffer -> wpos + 1 ) % rx_buffer -> size ;
125
127
if (nextPos == rx_buffer -> rpos )
126
128
{
127
-
128
- if (!uart -> overrun )
129
+ if (!uart -> rx_overrun )
129
130
{
130
- uart -> overrun = true;
131
- os_printf_plus (overrun_str );
131
+ uart -> rx_overrun = true;
132
+ // os_printf_plus(overrun_str);
132
133
}
133
134
134
135
// a choice has to be made here,
@@ -158,25 +159,27 @@ uart_peek_char_unsafe(uart_t* uart)
158
159
159
160
//without the following if statement and body, there is a good chance of a fifo overrun
160
161
if (uart_rx_buffer_available_unsafe (uart -> rx_buffer ) == 0 )
162
+ // hw fifo can't be peeked, data need to be copied to sw
161
163
uart_rx_copy_fifo_to_buffer_unsafe (uart );
162
164
163
165
return uart -> rx_buffer -> buffer [uart -> rx_buffer -> rpos ];
164
166
}
165
167
166
- inline int
168
+ // taking data straight from hw fifo: loopback-test BW jumps by 19%
169
+ inline int
167
170
uart_read_char_unsafe (uart_t * uart )
168
171
{
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 ];
171
176
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 ;
173
181
}
174
182
175
-
176
- /**********************************************************/
177
-
178
-
179
-
180
183
size_t
181
184
uart_rx_available (uart_t * uart )
182
185
{
@@ -204,14 +207,47 @@ uart_peek_char(uart_t* uart)
204
207
205
208
int
206
209
uart_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 )
207
218
{
208
219
if (uart == NULL || !uart -> rx_enabled )
209
- return -1 ;
210
-
220
+ return 0 ;
221
+
222
+ size_t ret = 0 ;
211
223
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
+
213
249
ETS_UART_INTR_ENABLE ();
214
- return data ;
250
+ return ret ;
215
251
}
216
252
217
253
size_t
@@ -231,6 +267,8 @@ uart_resize_rx_buffer(uart_t* uart, size_t new_size)
231
267
ETS_UART_INTR_DISABLE ();
232
268
while (uart_rx_available_unsafe (uart ) && new_wpos < new_size )
233
269
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 ;
234
272
235
273
uint8_t * old_buf = uart -> rx_buffer -> buffer ;
236
274
uart -> rx_buffer -> rpos = 0 ;
@@ -242,22 +280,39 @@ uart_resize_rx_buffer(uart_t* uart, size_t new_size)
242
280
return uart -> rx_buffer -> size ;
243
281
}
244
282
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
+ }
245
288
246
289
247
290
void ICACHE_RAM_ATTR
248
291
uart_isr (void * arg )
249
292
{
250
293
uart_t * uart = (uart_t * )arg ;
294
+ uint32_t usis = USIS (uart -> uart_nr );
295
+
251
296
if (uart == NULL || !uart -> rx_enabled )
252
297
{
253
- USIC (uart -> uart_nr ) = USIS ( uart -> uart_nr ) ;
298
+ USIC (uart -> uart_nr ) = usis ;
254
299
ETS_UART_INTR_DISABLE ();
255
300
return ;
256
301
}
257
- if (USIS (uart -> uart_nr ) & ((1 << UIFF ) | (1 << UITO )))
302
+
303
+ if (usis & (1 << UIFF ))
258
304
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
+ }
259
311
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 ;
261
316
}
262
317
263
318
static void
@@ -270,9 +325,22 @@ uart_start_isr(uart_t* uart)
270
325
// triggers the IRS very often. A value of 127 would not leave much time
271
326
// for ISR to clear fifo before the next byte is dropped. So pick a value
272
327
// 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 );
274
336
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 );
276
344
ETS_UART_INTR_ATTACH (uart_isr , (void * )uart );
277
345
ETS_UART_INTR_ENABLE ();
278
346
}
@@ -415,7 +483,8 @@ uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx
415
483
return NULL ;
416
484
417
485
uart -> uart_nr = uart_nr ;
418
- uart -> overrun = false;
486
+ uart -> rx_overrun = false;
487
+ uart -> rx_error = false;
419
488
420
489
switch (uart -> uart_nr )
421
490
{
@@ -678,11 +747,22 @@ uart_rx_enabled(uart_t* uart)
678
747
bool
679
748
uart_has_overrun (uart_t * uart )
680
749
{
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 )
682
762
return false;
683
763
684
764
// clear flag
685
- uart -> overrun = false;
765
+ uart -> rx_error = false;
686
766
return true;
687
767
}
688
768
0 commit comments