77#include " HardwareSerial.h"
88#include " soc/soc_caps.h"
99#include " driver/uart.h"
10+ #include " freertos/queue.h"
1011
1112#ifndef SOC_RX0
1213#if CONFIG_IDF_TARGET_ESP32
@@ -115,7 +116,131 @@ void serialEventRun(void)
115116}
116117#endif
117118
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+ }
119244
120245void 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)
121246{
@@ -124,6 +249,14 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
124249 return ;
125250 }
126251
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 ();
127260 // First Time or after end() --> set default Pins
128261 if (!uartIsDriverInstalled (_uart)) {
129262 switch (_uart_nr) {
@@ -176,26 +309,34 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
176309 _uart = NULL ;
177310 }
178311 }
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 ();
184318}
185319
186320void HardwareSerial::updateBaudRate (unsigned long baud)
187321{
188322 uartSetBaudRate (_uart, baud);
189323}
190324
191- void HardwareSerial::end (bool turnOffDebug )
325+ void HardwareSerial::end (bool fullyTerminate )
192326{
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+ }
195335 }
196336 delay (10 );
197337 uartEnd (_uart);
198338 _uart = 0 ;
339+ _destroyEventTask ();
199340}
200341
201342void HardwareSerial::setDebugOutput (bool en)
0 commit comments