@@ -72,65 +72,90 @@ SerialUART::SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx) {
7272 mutex_init (&_mutex);
7373}
7474
75+ static void _uart0IRQ ();
76+ static void _uart1IRQ ();
77+
7578void SerialUART::begin (unsigned long baud, uint16_t config) {
7679 _baud = baud;
7780 uart_init (_uart, baud);
7881 int bits, stop;
7982 uart_parity_t parity;
8083 switch (config & SERIAL_PARITY_MASK) {
81- case SERIAL_PARITY_EVEN: parity = UART_PARITY_EVEN; break ;
82- case SERIAL_PARITY_ODD: parity = UART_PARITY_ODD; break ;
83- default : parity = UART_PARITY_NONE; break ;
84+ case SERIAL_PARITY_EVEN:
85+ parity = UART_PARITY_EVEN;
86+ break ;
87+ case SERIAL_PARITY_ODD:
88+ parity = UART_PARITY_ODD;
89+ break ;
90+ default :
91+ parity = UART_PARITY_NONE;
92+ break ;
8493 }
8594 switch (config & SERIAL_STOP_BIT_MASK) {
86- case SERIAL_STOP_BIT_1: stop = 1 ; break ;
87- default : stop = 2 ; break ;
95+ case SERIAL_STOP_BIT_1:
96+ stop = 1 ;
97+ break ;
98+ default :
99+ stop = 2 ;
100+ break ;
88101 }
89102 switch (config & SERIAL_DATA_MASK) {
90- case SERIAL_DATA_5: bits = 5 ; break ;
91- case SERIAL_DATA_6: bits = 6 ; break ;
92- case SERIAL_DATA_7: bits = 7 ; break ;
93- default : bits = 8 ; break ;
103+ case SERIAL_DATA_5:
104+ bits = 5 ;
105+ break ;
106+ case SERIAL_DATA_6:
107+ bits = 6 ;
108+ break ;
109+ case SERIAL_DATA_7:
110+ bits = 7 ;
111+ break ;
112+ default :
113+ bits = 8 ;
114+ break ;
94115 }
95116 uart_set_format (_uart, bits, stop, parity);
96117 gpio_set_function (_tx, GPIO_FUNC_UART);
97118 gpio_set_function (_rx, GPIO_FUNC_UART);
98- _running = true ;
99- while (!_swFIFO.empty ()) {
100- (void )_swFIFO.pop (); // Just throw out anything in our old FIFO
119+ _writer = 0 ;
120+ _reader = 0 ;
121+
122+ if (_uart == uart0) {
123+ irq_set_exclusive_handler (UART0_IRQ, _uart0IRQ);
124+ irq_set_enabled (UART0_IRQ, true );
125+ } else {
126+ irq_set_exclusive_handler (UART1_IRQ, _uart1IRQ);
127+ irq_set_enabled (UART1_IRQ, true );
101128 }
129+ uart_get_hw (_uart)->imsc |= UART_UARTIMSC_RXIM_BITS | UART_UARTIMSC_RTIM_BITS;
130+ _running = true ;
102131}
103132
104133void SerialUART::end () {
105134 if (!_running) {
106135 return ;
107136 }
137+ if (_uart == uart0) {
138+ irq_set_enabled (UART0_IRQ, false );
139+ } else {
140+ irq_set_enabled (UART1_IRQ, false );
141+ }
108142 uart_deinit (_uart);
109143 _running = false ;
110144}
111145
112- // Transfers any data in the HW FIFO into our SW one, up to 32 bytes
113- void SerialUART::_pumpFIFO () {
114- while ((_swFIFO.size () < 32 ) && (uart_is_readable (_uart))) {
115- _swFIFO.push (uart_getc (_uart));
116- }
117- }
118-
119146int SerialUART::peek () {
120147 CoreMutex m (&_mutex);
121148 if (!_running || !m) {
122149 return -1 ;
123150 }
124- _pumpFIFO ();
125- // If there's something in the FIFO now, just peek at it
126- if (_swFIFO.size ()) {
127- return _swFIFO.front ();
128- }
129- // The SW FIFO is empty, read the HW one until the timeout
130- if (uart_is_readable_within_us (_uart, _timeout * 1000 )) {
131- // We got one char, put it in the FIFO (which will now have exactly 1 byte) and return it
132- _swFIFO.push (uart_getc (_uart));
133- return _swFIFO.front ();
151+ uint32_t start = millis ();
152+ uint32_t now = millis ();
153+ while ((now - start) < _timeout) {
154+ if (_writer != _reader) {
155+ return _queue[_reader];
156+ }
157+ delay (1 );
158+ now = millis ();
134159 }
135160 return -1 ; // Nothing available before timeout
136161}
@@ -140,16 +165,16 @@ int SerialUART::read() {
140165 if (!_running || !m) {
141166 return -1 ;
142167 }
143- _pumpFIFO ();
144- if (_swFIFO. size ()) {
145- auto ret = _swFIFO. front ();
146- _swFIFO. pop ();
147- return ret;
148- }
149- // The SW FIFO is empty, read the HW one until the timeout
150- if ( uart_is_readable_within_us (_uart, _timeout * 1000 )) {
151- // We got one char, return it (FIFO will still be empty
152- return uart_getc (_uart );
168+ uint32_t start = millis ();
169+ uint32_t now = millis ();
170+ while ((now - start) < _timeout) {
171+ if (_writer != _reader) {
172+ auto ret = _queue[_reader] ;
173+ _reader = (_reader + 1 ) % sizeof (_queue);
174+ return ret;
175+ }
176+ delay ( 1 );
177+ now = millis ( );
153178 }
154179 return -1 ; // Timeout
155180}
@@ -159,16 +184,14 @@ int SerialUART::available() {
159184 if (!_running || !m) {
160185 return 0 ;
161186 }
162- _pumpFIFO ();
163- return _swFIFO.size ();
187+ return (_writer - _reader) % sizeof (_queue);
164188}
165189
166190int SerialUART::availableForWrite () {
167191 CoreMutex m (&_mutex);
168192 if (!_running || !m) {
169193 return 0 ;
170194 }
171- _pumpFIFO ();
172195 return (uart_is_writable (_uart)) ? 1 : 0 ;
173196}
174197
@@ -177,7 +200,6 @@ void SerialUART::flush() {
177200 if (!_running || !m) {
178201 return ;
179202 }
180- _pumpFIFO ();
181203 uart_tx_wait_blocking (_uart);
182204}
183205
@@ -186,7 +208,6 @@ size_t SerialUART::write(uint8_t c) {
186208 if (!_running || !m) {
187209 return 0 ;
188210 }
189- _pumpFIFO ();
190211 uart_putc_raw (_uart, c);
191212 return 1 ;
192213}
@@ -196,7 +217,6 @@ size_t SerialUART::write(const uint8_t *p, size_t len) {
196217 if (!_running || !m) {
197218 return 0 ;
198219 }
199- _pumpFIFO ();
200220 size_t cnt = len;
201221 while (cnt) {
202222 uart_putc_raw (_uart, *p);
@@ -224,3 +244,21 @@ void arduino::serialEvent2Run(void) {
224244 serialEvent2 ();
225245 }
226246}
247+
248+ // IRQ handler, called when FIFO > 1/4 full or when it had held unread data for >32 bit times
249+ void __not_in_flash_func (SerialUART::_handleIRQ)() {
250+ uart_get_hw (_uart)->icr |= UART_UARTICR_RTIC_BITS | UART_UARTICR_RXIC_BITS;
251+ while ((uart_is_readable (_uart)) && ((_writer + 1 ) % sizeof (_queue) != _reader)) {
252+ _queue[_writer] = uart_getc (_uart);
253+ asm volatile (" " ::: " memory" ); // Ensure the queue is written before the written count advances
254+ _writer = (_writer + 1 ) % sizeof (_queue);
255+ }
256+ }
257+
258+ static void __not_in_flash_func (_uart0IRQ)() {
259+ Serial1._handleIRQ ();
260+ }
261+
262+ static void __not_in_flash_func (_uart1IRQ)() {
263+ Serial2._handleIRQ ();
264+ }
0 commit comments