@@ -72,65 +72,90 @@ SerialUART::SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx) {
72
72
mutex_init (&_mutex);
73
73
}
74
74
75
+ static void _uart0IRQ ();
76
+ static void _uart1IRQ ();
77
+
75
78
void SerialUART::begin (unsigned long baud, uint16_t config) {
76
79
_baud = baud;
77
80
uart_init (_uart, baud);
78
81
int bits, stop;
79
82
uart_parity_t parity;
80
83
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 ;
84
93
}
85
94
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 ;
88
101
}
89
102
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 ;
94
115
}
95
116
uart_set_format (_uart, bits, stop, parity);
96
117
gpio_set_function (_tx, GPIO_FUNC_UART);
97
118
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 );
101
128
}
129
+ uart_get_hw (_uart)->imsc |= UART_UARTIMSC_RXIM_BITS | UART_UARTIMSC_RTIM_BITS;
130
+ _running = true ;
102
131
}
103
132
104
133
void SerialUART::end () {
105
134
if (!_running) {
106
135
return ;
107
136
}
137
+ if (_uart == uart0) {
138
+ irq_set_enabled (UART0_IRQ, false );
139
+ } else {
140
+ irq_set_enabled (UART1_IRQ, false );
141
+ }
108
142
uart_deinit (_uart);
109
143
_running = false ;
110
144
}
111
145
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
-
119
146
int SerialUART::peek () {
120
147
CoreMutex m (&_mutex);
121
148
if (!_running || !m) {
122
149
return -1 ;
123
150
}
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 ();
134
159
}
135
160
return -1 ; // Nothing available before timeout
136
161
}
@@ -140,16 +165,16 @@ int SerialUART::read() {
140
165
if (!_running || !m) {
141
166
return -1 ;
142
167
}
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 ( );
153
178
}
154
179
return -1 ; // Timeout
155
180
}
@@ -159,16 +184,14 @@ int SerialUART::available() {
159
184
if (!_running || !m) {
160
185
return 0 ;
161
186
}
162
- _pumpFIFO ();
163
- return _swFIFO.size ();
187
+ return (_writer - _reader) % sizeof (_queue);
164
188
}
165
189
166
190
int SerialUART::availableForWrite () {
167
191
CoreMutex m (&_mutex);
168
192
if (!_running || !m) {
169
193
return 0 ;
170
194
}
171
- _pumpFIFO ();
172
195
return (uart_is_writable (_uart)) ? 1 : 0 ;
173
196
}
174
197
@@ -177,7 +200,6 @@ void SerialUART::flush() {
177
200
if (!_running || !m) {
178
201
return ;
179
202
}
180
- _pumpFIFO ();
181
203
uart_tx_wait_blocking (_uart);
182
204
}
183
205
@@ -186,7 +208,6 @@ size_t SerialUART::write(uint8_t c) {
186
208
if (!_running || !m) {
187
209
return 0 ;
188
210
}
189
- _pumpFIFO ();
190
211
uart_putc_raw (_uart, c);
191
212
return 1 ;
192
213
}
@@ -196,7 +217,6 @@ size_t SerialUART::write(const uint8_t *p, size_t len) {
196
217
if (!_running || !m) {
197
218
return 0 ;
198
219
}
199
- _pumpFIFO ();
200
220
size_t cnt = len;
201
221
while (cnt) {
202
222
uart_putc_raw (_uart, *p);
@@ -224,3 +244,21 @@ void arduino::serialEvent2Run(void) {
224
244
serialEvent2 ();
225
245
}
226
246
}
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