7
7
#include " HardwareSerial.h"
8
8
#include " soc/soc_caps.h"
9
9
#include " driver/uart.h"
10
+ #include " freertos/queue.h"
10
11
11
12
#ifndef SOC_RX0
12
13
#if CONFIG_IDF_TARGET_ESP32
@@ -115,7 +116,128 @@ void serialEventRun(void)
115
116
}
116
117
#endif
117
118
118
- HardwareSerial::HardwareSerial (int uart_nr) : _uart_nr(uart_nr), _uart(NULL ), _rxBufferSize(256 ) {}
119
+ #if !CONFIG_DISABLE_HAL_LOCKS
120
+ #define HSERIAL_MUTEX_LOCK () do {} while (xSemaphoreTake(_lock, portMAX_DELAY) != pdPASS)
121
+ #define HSERIAL_MUTEX_UNLOCK () xSemaphoreGive(_lock)
122
+ #endif
123
+
124
+ HardwareSerial::HardwareSerial (int uart_nr) :
125
+ _uart_nr(uart_nr),
126
+ _uart(NULL ),
127
+ _rxBufferSize(256 ),
128
+ _onReceiveCB(NULL ),
129
+ _onReceiveErrorCB(NULL ),
130
+ _eventTask(NULL )
131
+ #if !CONFIG_DISABLE_HAL_LOCKS
132
+ ,_lock(NULL )
133
+ #endif
134
+ {
135
+ #if !CONFIG_DISABLE_HAL_LOCKS
136
+ if (_lock == NULL ){
137
+ _lock = xSemaphoreCreateMutex ();
138
+ if (_lock == NULL ){
139
+ log_e (" xSemaphoreCreateMutex failed" );
140
+ return ;
141
+ }
142
+ }
143
+ #endif
144
+ }
145
+
146
+ HardwareSerial::~HardwareSerial ()
147
+ {
148
+ end ();
149
+ #if !CONFIG_DISABLE_HAL_LOCKS
150
+ if (_lock != NULL ){
151
+ vSemaphoreDelete (_lock);
152
+ }
153
+ #endif
154
+ }
155
+
156
+
157
+ void HardwareSerial::_createEventTask (void *args)
158
+ {
159
+ // Creating UART event Task
160
+ xTaskCreate (_uartEventTask, " uart_event_task" , 2048 , this , configMAX_PRIORITIES - 1 , &_eventTask);
161
+ if (_eventTask == NULL ) {
162
+ log_e (" -- UART%d Event Task not Created!" , _uart_nr);
163
+ }
164
+ }
165
+
166
+ void HardwareSerial::_destroyEventTask (void )
167
+ {
168
+ if (_eventTask != NULL ) {
169
+ vTaskDelete (_eventTask);
170
+ _eventTask = NULL ;
171
+ }
172
+ }
173
+
174
+ void HardwareSerial::onReceiveError (OnReceiveErrorCb function)
175
+ {
176
+ HSERIAL_MUTEX_LOCK ();
177
+ // function may be NULL to cancel onReceive() from its respective task
178
+ _onReceiveErrorCB = function;
179
+ // this can be called after Serial.begin(), therefore it shall create the event task
180
+ if (function != NULL && _uart != NULL && _eventTask == NULL ) {
181
+ _createEventTask (this );
182
+ }
183
+ HSERIAL_MUTEX_UNLOCK ();
184
+ }
185
+
186
+ void HardwareSerial::onReceive (OnReceiveCb function)
187
+ {
188
+ HSERIAL_MUTEX_LOCK ();
189
+ // function may be NULL to cancel onReceive() from its respective task
190
+ _onReceiveCB = function;
191
+ // this can be called after Serial.begin(), therefore it shall create the event task
192
+ if (function != NULL && _uart != NULL && _eventTask == NULL ) {
193
+ _createEventTask (this );
194
+ }
195
+ HSERIAL_MUTEX_UNLOCK ();
196
+ }
197
+
198
+ void HardwareSerial::_uartEventTask (void *args)
199
+ {
200
+ HardwareSerial *uart = (HardwareSerial *)args;
201
+ uart_event_t event;
202
+ QueueHandle_t uartEventQueue = NULL ;
203
+ uartGetEventQueue (uart->_uart , &uartEventQueue);
204
+ if (uartEventQueue != NULL ) {
205
+ for (;;) {
206
+ // Waiting for UART event.
207
+ if (xQueueReceive (uartEventQueue, (void * )&event, (portTickType)portMAX_DELAY)) {
208
+ switch (event.type ) {
209
+ case UART_DATA:
210
+ if (uart->_onReceiveCB && uart->available () > 0 ) uart->_onReceiveCB ();
211
+ break ;
212
+ case UART_FIFO_OVF:
213
+ log_w (" UART%d FIFO Overflow. Consider adding Hardware Flow Control to your Application." , uart->_uart_nr );
214
+ if (uart->_onReceiveErrorCB ) uart->_onReceiveErrorCB (UART_FIFO_OVF_ERROR);
215
+ break ;
216
+ case UART_BUFFER_FULL:
217
+ log_w (" UART%d Buffer Full. Consider encreasing your buffer size of your Application." , uart->_uart_nr );
218
+ if (uart->_onReceiveErrorCB ) uart->_onReceiveErrorCB (UART_BUFFER_FULL_ERROR);
219
+ break ;
220
+ case UART_BREAK:
221
+ log_w (" UART%d RX break." , uart->_uart_nr );
222
+ if (uart->_onReceiveErrorCB ) uart->_onReceiveErrorCB (UART_BREAK_ERROR);
223
+ break ;
224
+ case UART_PARITY_ERR:
225
+ log_w (" UART%d parity error." , uart->_uart_nr );
226
+ if (uart->_onReceiveErrorCB ) uart->_onReceiveErrorCB (UART_PARITY_ERROR);
227
+ break ;
228
+ case UART_FRAME_ERR:
229
+ log_w (" UART%d frame error." , uart->_uart_nr );
230
+ if (uart->_onReceiveErrorCB ) uart->_onReceiveErrorCB (UART_FRAME_ERROR);
231
+ break ;
232
+ default :
233
+ log_w (" UART%d unknown event type %d." , uart->_uart_nr , event.type );
234
+ break ;
235
+ }
236
+ }
237
+ }
238
+ }
239
+ vTaskDelete (NULL );
240
+ }
119
241
120
242
void HardwareSerial::begin (unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd)
121
243
{
@@ -124,6 +246,14 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
124
246
return ;
125
247
}
126
248
249
+ #if !CONFIG_DISABLE_HAL_LOCKS
250
+ if (_lock == NULL ){
251
+ log_e (" MUTEX Lock failed. Can't begin." );
252
+ return ;
253
+ }
254
+ #endif
255
+
256
+ HSERIAL_MUTEX_LOCK ();
127
257
// First Time or after end() --> set default Pins
128
258
if (!uartIsDriverInstalled (_uart)) {
129
259
switch (_uart_nr) {
@@ -176,26 +306,34 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
176
306
_uart = NULL ;
177
307
}
178
308
}
179
- }
180
-
181
- void HardwareSerial::onReceive (void (*function)(void ))
182
- {
183
- uartOnReceive (_uart, function);
309
+ // create a task to deal with Serial Events when, for example, calling begin() twice to change the baudrate,
310
+ // or when setting the callback before calling begin()
311
+ if (_uart != NULL && (_onReceiveCB != NULL || _onReceiveErrorCB != NULL ) && _eventTask == NULL ) {
312
+ _createEventTask (this );
313
+ }
314
+ HSERIAL_MUTEX_UNLOCK ();
184
315
}
185
316
186
317
void HardwareSerial::updateBaudRate (unsigned long baud)
187
318
{
188
319
uartSetBaudRate (_uart, baud);
189
320
}
190
321
191
- void HardwareSerial::end (bool turnOffDebug )
322
+ void HardwareSerial::end (bool fullyTerminate )
192
323
{
193
- if (turnOffDebug && uartGetDebug () == _uart_nr) {
194
- uartSetDebug (0 );
324
+ // default Serial.end() will completely disable HardwareSerial,
325
+ // including any tasks or debug message channel (log_x()) - but not for IDF log messages!
326
+ if (fullyTerminate) {
327
+ _onReceiveCB = NULL ;
328
+ _onReceiveErrorCB = NULL ;
329
+ if (uartGetDebug () == _uart_nr) {
330
+ uartSetDebug (0 );
331
+ }
195
332
}
196
333
delay (10 );
197
334
uartEnd (_uart);
198
335
_uart = 0 ;
336
+ _destroyEventTask ();
199
337
}
200
338
201
339
void HardwareSerial::setDebugOutput (bool en)
0 commit comments