@@ -101,7 +101,8 @@ void uart_disarm_tx_interrupt(uart_t* uart);
101
101
void uart_set_baudrate (uart_t * uart, int baud_rate);
102
102
int uart_get_baudrate (uart_t * uart);
103
103
104
- uart_t * uart_init (int uart_nr, int baudrate, byte config);
104
+ uart_t * uart_start_init (int uart_nr, int baudrate, byte config);
105
+ void uart_finish_init (uart_t * uart);
105
106
void uart_uninit (uart_t * uart);
106
107
void uart_swap (uart_t * uart);
107
108
@@ -116,6 +117,13 @@ int uart_get_debug();
116
117
// ####################################################################################################
117
118
// ####################################################################################################
118
119
120
+ // These function internals can be used from interrupt handlers to ensure they
121
+ // are in instruction RAM, or anywhere that the uart_nr has been validated.
122
+ #define UART_GET_TX_FIFO_ROOM (uart_nr ) (UART_TX_FIFO_SIZE - ((USS(uart_nr) >> USTXC) & 0xff ))
123
+ #define UART_TRANSMIT_CHAR (uart_nr, c ) do { USF (uart_nr) = (c); } while (0 )
124
+ #define UART_ARM_TX_INTERRUPT (uart_nr ) do { USIE (uart_nr) |= (1 << UIFE); } while (0 )
125
+ #define UART_DISARM_TX_INTERRUPT (uart_nr ) do { USIE (uart_nr) &= ~(1 << UIFE); } while (0 )
126
+
119
127
void ICACHE_RAM_ATTR uart_interrupt_handler (uart_t * uart) {
120
128
121
129
// -------------- UART 0 --------------
@@ -133,13 +141,7 @@ void ICACHE_RAM_ATTR uart_interrupt_handler(uart_t* uart) {
133
141
}
134
142
135
143
// -------------- UART 1 --------------
136
-
137
- if (Serial1.isRxEnabled ()) {
138
- while (U1IS & (1 << UIFF)) {
139
- Serial1._rx_complete_irq ((char ) (U1F & 0xff ));
140
- U1IC = (1 << UIFF);
141
- }
142
- }
144
+ // Note: only TX is supported on UART 1.
143
145
if (Serial1.isTxEnabled ()) {
144
146
if (U1IS & (1 << UIFE)) {
145
147
U1IC = (1 << UIFE);
@@ -166,7 +168,7 @@ size_t uart_get_tx_fifo_room(uart_t* uart) {
166
168
if (uart == 0 )
167
169
return 0 ;
168
170
if (uart->txEnabled ) {
169
- return UART_TX_FIFO_SIZE - (( USS ( uart->uart_nr ) >> USTXC) & 0xff );
171
+ return UART_GET_TX_FIFO_ROOM ( uart->uart_nr );
170
172
}
171
173
return 0 ;
172
174
}
@@ -183,7 +185,7 @@ void uart_transmit_char(uart_t* uart, char c) {
183
185
if (uart == 0 )
184
186
return ;
185
187
if (uart->txEnabled ) {
186
- USF (uart->uart_nr ) = c ;
188
+ UART_TRANSMIT_CHAR (uart->uart_nr , c) ;
187
189
}
188
190
}
189
191
@@ -247,15 +249,15 @@ void uart_arm_tx_interrupt(uart_t* uart) {
247
249
if (uart == 0 )
248
250
return ;
249
251
if (uart->txEnabled ) {
250
- USIE (uart->uart_nr ) |= ( 1 << UIFE );
252
+ UART_ARM_TX_INTERRUPT (uart->uart_nr );
251
253
}
252
254
}
253
255
254
256
void uart_disarm_tx_interrupt (uart_t * uart) {
255
257
if (uart == 0 )
256
258
return ;
257
259
if (uart->txEnabled ) {
258
- USIE (uart->uart_nr ) &= ~( 1 << UIFE );
260
+ UART_DISARM_TX_INTERRUPT (uart->uart_nr );
259
261
}
260
262
}
261
263
@@ -272,9 +274,8 @@ int uart_get_baudrate(uart_t* uart) {
272
274
return uart->baud_rate ;
273
275
}
274
276
275
- uart_t * uart_init (int uart_nr, int baudrate, byte config, byte mode) {
277
+ uart_t * uart_start_init (int uart_nr, int baudrate, byte config, byte mode) {
276
278
277
- uint32_t conf1 = 0x00000000 ;
278
279
uart_t * uart = (uart_t *) os_malloc (sizeof (uart_t ));
279
280
280
281
if (uart == 0 ) {
@@ -294,6 +295,7 @@ uart_t* uart_init(int uart_nr, int baudrate, byte config, byte mode) {
294
295
IOSWAP &= ~(1 << IOSWAPU0);
295
296
break ;
296
297
case UART1:
298
+ // Note: uart_interrupt_handler does not support RX on UART 1.
297
299
uart->rxEnabled = false ;
298
300
uart->txEnabled = (mode != SERIAL_RX_ONLY);
299
301
uart->rxPin = 255 ;
@@ -309,6 +311,12 @@ uart_t* uart_init(int uart_nr, int baudrate, byte config, byte mode) {
309
311
uart_set_baudrate (uart, baudrate);
310
312
USC0 (uart->uart_nr ) = config;
311
313
314
+ return uart;
315
+ }
316
+
317
+ void uart_finish_init (uart_t * uart) {
318
+ uint32_t conf1 = 0x00000000 ;
319
+
312
320
uart_flush (uart);
313
321
uart_interrupt_enable (uart);
314
322
@@ -321,8 +329,6 @@ uart_t* uart_init(int uart_nr, int baudrate, byte config, byte mode) {
321
329
}
322
330
323
331
USC1 (uart->uart_nr ) = conf1;
324
-
325
- return uart;
326
332
}
327
333
328
334
void uart_uninit (uart_t * uart) {
@@ -479,35 +485,48 @@ int uart_get_debug() {
479
485
// ####################################################################################################
480
486
481
487
HardwareSerial::HardwareSerial (int uart_nr) :
482
- _uart_nr(uart_nr), _uart(0 ), _tx_buffer(0 ), _rx_buffer(0 ), _written( false ) {
488
+ _uart_nr(uart_nr), _uart(0 ), _tx_buffer(0 ), _rx_buffer(0 ) {
483
489
}
484
490
485
491
void HardwareSerial::begin (unsigned long baud, byte config, byte mode) {
492
+ InterruptLock il;
486
493
487
494
// disable debug for this interface
488
495
if (uart_get_debug () == _uart_nr) {
489
496
uart_set_debug (UART_NO);
490
497
}
491
498
492
- _uart = uart_init (_uart_nr, baud, config, mode);
499
+ if (_uart) {
500
+ os_free (_uart);
501
+ }
502
+ _uart = uart_start_init (_uart_nr, baud, config, mode);
493
503
494
504
if (_uart == 0 ) {
495
505
return ;
496
506
}
497
507
498
- if (_uart->rxEnabled ) {
499
- if (!_rx_buffer)
500
- _rx_buffer = new cbuf (SERIAL_RX_BUFFER_SIZE);
508
+ // Disable the RX and/or TX functions if we fail to allocate circular buffers.
509
+ // The user can confirm they are enabled with isRxEnabled() and isTxEnabled().
510
+ if (_uart->rxEnabled && !_rx_buffer) {
511
+ _rx_buffer = new cbuf (SERIAL_RX_BUFFER_SIZE);
512
+ if (!_rx_buffer) {
513
+ _uart->rxEnabled = false ;
514
+ }
501
515
}
502
- if (_uart->txEnabled ) {
503
- if (!_tx_buffer)
504
- _tx_buffer = new cbuf (SERIAL_TX_BUFFER_SIZE);
516
+ if (_uart->txEnabled && !_tx_buffer) {
517
+ _tx_buffer = new cbuf (SERIAL_TX_BUFFER_SIZE);
518
+ if (!_tx_buffer) {
519
+ _uart->txEnabled = false ;
520
+ }
505
521
}
506
- _written = false ;
507
522
delay (1 );
523
+
524
+ uart_finish_init (_uart);
508
525
}
509
526
510
527
void HardwareSerial::end () {
528
+ InterruptLock il;
529
+
511
530
if (uart_get_debug () == _uart_nr) {
512
531
uart_set_debug (UART_NO);
513
532
}
@@ -541,13 +560,13 @@ void HardwareSerial::setDebugOutput(bool en) {
541
560
}
542
561
}
543
562
544
- bool HardwareSerial::isTxEnabled (void ) {
563
+ bool ICACHE_RAM_ATTR HardwareSerial::isTxEnabled (void ) {
545
564
if (_uart == 0 )
546
565
return false ;
547
566
return _uart->txEnabled ;
548
567
}
549
568
550
- bool HardwareSerial::isRxEnabled (void ) {
569
+ bool ICACHE_RAM_ATTR HardwareSerial::isRxEnabled (void ) {
551
570
if (_uart == 0 )
552
571
return false ;
553
572
return _uart->rxEnabled ;
@@ -606,71 +625,74 @@ void HardwareSerial::flush() {
606
625
return ;
607
626
if (!_uart->txEnabled )
608
627
return ;
609
- if (!_written)
610
- return ;
611
628
629
+ const int uart_nr = _uart->uart_nr ;
612
630
while (true ) {
613
631
{
614
632
InterruptLock il;
615
633
if (_tx_buffer->getSize () == 0 &&
616
- uart_get_tx_fifo_room (_uart ) >= UART_TX_FIFO_SIZE) {
634
+ UART_GET_TX_FIFO_ROOM (uart_nr ) >= UART_TX_FIFO_SIZE) {
617
635
break ;
636
+ } else if (il.savedInterruptLevel () > 0 ) {
637
+ _tx_empty_irq ();
638
+ continue ;
618
639
}
619
640
}
620
641
yield ();
621
642
}
622
- _written = false ;
623
643
}
624
644
625
645
size_t HardwareSerial::write (uint8_t c) {
626
646
if (_uart == 0 || !_uart->txEnabled )
627
647
return 0 ;
628
- _written = true ;
629
648
649
+ bool tx_now = false ;
650
+ const int uart_nr = _uart->uart_nr ;
630
651
while (true ) {
631
652
{
632
653
InterruptLock il;
633
654
if (_tx_buffer->empty ()) {
634
- if (uart_get_tx_fifo_room (_uart ) > 0 ) {
635
- uart_transmit_char (_uart, c) ;
655
+ if (UART_GET_TX_FIFO_ROOM (uart_nr ) > 0 ) {
656
+ tx_now = true ;
636
657
} else {
637
658
_tx_buffer->write (c);
638
- uart_arm_tx_interrupt (_uart );
659
+ UART_ARM_TX_INTERRUPT (uart_nr );
639
660
}
640
661
break ;
641
662
} else if (_tx_buffer->write (c)) {
642
663
break ;
664
+ } else if (il.savedInterruptLevel () > 0 ) {
665
+ _tx_empty_irq ();
666
+ continue ;
643
667
}
644
668
}
645
669
yield ();
646
670
}
671
+ if (tx_now) {
672
+ UART_TRANSMIT_CHAR (uart_nr, c);
673
+ }
647
674
return 1 ;
648
675
}
649
676
650
677
HardwareSerial::operator bool () const {
651
678
return _uart != 0 ;
652
679
}
653
680
654
- void HardwareSerial::_rx_complete_irq (char c) {
655
- if (_rx_buffer) {
656
- _rx_buffer->write (c);
657
- }
681
+ void ICACHE_RAM_ATTR HardwareSerial::_rx_complete_irq (char c) {
682
+ _rx_buffer->write (c);
658
683
}
659
684
660
- void HardwareSerial::_tx_empty_irq (void ) {
661
- if (_uart == 0 )
662
- return ;
663
- if (_tx_buffer == 0 )
664
- return ;
685
+ void ICACHE_RAM_ATTR HardwareSerial::_tx_empty_irq (void ) {
686
+ const int uart_nr = _uart->uart_nr ;
665
687
size_t queued = _tx_buffer->getSize ();
666
688
if (!queued) {
667
- uart_disarm_tx_interrupt (_uart );
689
+ UART_DISARM_TX_INTERRUPT (uart_nr );
668
690
return ;
669
691
}
670
692
671
- size_t room = uart_get_tx_fifo_room (_uart );
693
+ size_t room = UART_GET_TX_FIFO_ROOM (uart_nr );
672
694
int n = static_cast <int >((queued < room) ? queued : room);
673
695
while (n--) {
674
- uart_transmit_char (_uart , _tx_buffer->read ());
696
+ UART_TRANSMIT_CHAR (uart_nr , _tx_buffer->read ());
675
697
}
676
698
}
0 commit comments