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