未验证 提交 c26e3f42 编写于 作者: G Gonzalo Brusco 提交者: GitHub

Adds HardwareSerial::setRxTimeout() (#6397)

* Adds HardwareSerial::onReceiveTimeout()

* Fixed typo

* Changes requested

* Fix eventQueueReset

* Changed _onReceiveTimeout to _rxTimeout for consistency

* Uniform uart_set_rx_timeout condition

* test _uart not NULL in eventQueueReset()

check if _uart is not NULL before using it.

* revert last commit - no need for it

reverting last change made - it is not necessary.

* adds onReceive() parameter 

In order to allow the user to choose if onReceive() call back will be called only when UART Rx timeout happens or also when UART FIFO gets 120 bytes, 
a new parameter has been added to onReceive() with the default behavior based on timeout.

    void onReceive(OnReceiveCb function, bool onlyOnTimeout = true);

   onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
   UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF)
   UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbos by default in IDF)
   onlyOnTimeout parameter will define how onReceive will behave:
   Default: true -- The callback will only be called when RX Timeout happens. 
                           Whole stream of bytes will be ready for being read on the callback function at once.
                           This option may lead to Rx Overflow depending on the Rx Buffer Size and number of bytes received in the streaming
            false --    The callback will be called when FIFO reaches 120 bytes and also on RX Timeout.
                           The stream of incommig bytes will be "split" into blocks of 120 bytes on each callback.
                           This option avoid any sort of Rx Overflow, but leaves the UART packet reassembling work to the Application.

* Adds onReceive() parameter for timeout only

* Adds back setRxTimeout()

* Adds setRxTimeout()

* CI Syntax error - "," missing
Co-authored-by: NRodrigo Garcia <rodrigo.garcia@espressif.com>
上级 ab34321a
...@@ -122,11 +122,13 @@ void serialEventRun(void) ...@@ -122,11 +122,13 @@ void serialEventRun(void)
HardwareSerial::HardwareSerial(int uart_nr) : HardwareSerial::HardwareSerial(int uart_nr) :
_uart_nr(uart_nr), _uart_nr(uart_nr),
_uart(NULL), _uart(NULL),
_rxBufferSize(256), _rxBufferSize(256),
_txBufferSize(0), _txBufferSize(0),
_onReceiveCB(NULL), _onReceiveCB(NULL),
_onReceiveErrorCB(NULL), _onReceiveErrorCB(NULL),
_onReceiveTimeout(true),
_rxTimeout(10),
_eventTask(NULL) _eventTask(NULL)
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
,_lock(NULL) ,_lock(NULL)
...@@ -183,18 +185,49 @@ void HardwareSerial::onReceiveError(OnReceiveErrorCb function) ...@@ -183,18 +185,49 @@ void HardwareSerial::onReceiveError(OnReceiveErrorCb function)
HSERIAL_MUTEX_UNLOCK(); HSERIAL_MUTEX_UNLOCK();
} }
void HardwareSerial::onReceive(OnReceiveCb function) void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout)
{ {
HSERIAL_MUTEX_LOCK(); HSERIAL_MUTEX_LOCK();
// function may be NULL to cancel onReceive() from its respective task // function may be NULL to cancel onReceive() from its respective task
_onReceiveCB = function; _onReceiveCB = function;
// When Rx timeout is Zero (disabled), there is only one possible option that is callback when FIFO reaches 120 bytes
_onReceiveTimeout = _rxTimeout > 0 ? onlyOnTimeout : false;
// this can be called after Serial.begin(), therefore it shall create the event task // this can be called after Serial.begin(), therefore it shall create the event task
if (function != NULL && _uart != NULL && _eventTask == NULL) { if (function != NULL && _uart != NULL && _eventTask == NULL) {
_createEventTask(this); _createEventTask(this); // Create event task
} }
HSERIAL_MUTEX_UNLOCK(); HSERIAL_MUTEX_UNLOCK();
} }
// timout is calculates in time to receive UART symbols at the UART baudrate.
// the estimation is about 11 bits per symbol (SERIAL_8N1)
void HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
{
HSERIAL_MUTEX_LOCK();
// Zero disables timeout, thus, onReceive callback will only be called when RX FIFO reaches 120 bytes
// Any non-zero value will activate onReceive callback based on UART baudrate with about 11 bits per symbol
_rxTimeout = symbols_timeout;
if (!symbols_timeout) _onReceiveTimeout = false; // only when RX timeout is disabled, we also must disable this flag
if(_uart != NULL) uart_set_rx_timeout(_uart_nr, _rxTimeout); // Set new timeout
HSERIAL_MUTEX_UNLOCK();
}
void HardwareSerial::eventQueueReset()
{
QueueHandle_t uartEventQueue = NULL;
if (_uart == NULL) {
return;
}
uartGetEventQueue(_uart, &uartEventQueue);
if (uartEventQueue != NULL) {
xQueueReset(uartEventQueue);
}
}
void HardwareSerial::_uartEventTask(void *args) void HardwareSerial::_uartEventTask(void *args)
{ {
HardwareSerial *uart = (HardwareSerial *)args; HardwareSerial *uart = (HardwareSerial *)args;
...@@ -207,14 +240,16 @@ void HardwareSerial::_uartEventTask(void *args) ...@@ -207,14 +240,16 @@ void HardwareSerial::_uartEventTask(void *args)
if(xQueueReceive(uartEventQueue, (void * )&event, (portTickType)portMAX_DELAY)) { if(xQueueReceive(uartEventQueue, (void * )&event, (portTickType)portMAX_DELAY)) {
switch(event.type) { switch(event.type) {
case UART_DATA: case UART_DATA:
if(uart->_onReceiveCB && uart->available() > 0) uart->_onReceiveCB(); if(uart->_onReceiveCB && uart->available() > 0 &&
((uart->_onReceiveTimeout && event.timeout_flag) || !uart->_onReceiveTimeout) )
uart->_onReceiveCB();
break; break;
case UART_FIFO_OVF: case UART_FIFO_OVF:
log_w("UART%d FIFO Overflow. Consider adding Hardware Flow Control to your Application.", uart->_uart_nr); log_w("UART%d FIFO Overflow. Consider adding Hardware Flow Control to your Application.", uart->_uart_nr);
if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(UART_FIFO_OVF_ERROR); if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(UART_FIFO_OVF_ERROR);
break; break;
case UART_BUFFER_FULL: case UART_BUFFER_FULL:
log_w("UART%d Buffer Full. Consider encreasing your buffer size of your Application.", uart->_uart_nr); log_w("UART%d Buffer Full. Consider increasing your buffer size of your Application.", uart->_uart_nr);
if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(UART_BUFFER_FULL_ERROR); if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(UART_BUFFER_FULL_ERROR);
break; break;
case UART_BREAK: case UART_BREAK:
...@@ -317,6 +352,12 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in ...@@ -317,6 +352,12 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
if (_uart != NULL && (_onReceiveCB != NULL || _onReceiveErrorCB != NULL) && _eventTask == NULL) { if (_uart != NULL && (_onReceiveCB != NULL || _onReceiveErrorCB != NULL) && _eventTask == NULL) {
_createEventTask(this); _createEventTask(this);
} }
// Set UART RX timeout
if (_uart != NULL) {
uart_set_rx_timeout(_uart_nr, _rxTimeout);
}
HSERIAL_MUTEX_UNLOCK(); HSERIAL_MUTEX_UNLOCK();
} }
......
...@@ -73,10 +73,31 @@ public: ...@@ -73,10 +73,31 @@ public:
HardwareSerial(int uart_nr); HardwareSerial(int uart_nr);
~HardwareSerial(); ~HardwareSerial();
// onReceive will setup a callback for whenever UART data is received // setRxTimeout sets the timeout after which onReceive callback will be called (after receiving data, it waits for this time of UART rx inactivity to call the callback fnc)
// it will work as UART Rx interrupt -- Using C++ 11 std::fuction // param symbols_timeout defines a timeout threshold in uart symbol periods. Setting 0 symbol timeout disables the callback call by timeout.
void onReceive(OnReceiveCb function); // Maximum timeout setting is calculacted automatically by IDF. If set above the maximum, it is ignored and an error is printed on Serial0 (check console).
// Examples: Maximum for 11 bits symbol is 92 (SERIAL_8N2, SERIAL_8E1, SERIAL_8O1, etc), Maximum for 10 bits symbol is 101 (SERIAL_8N1).
// For example symbols_timeout=1 defines a timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
// For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms
void setRxTimeout(uint8_t symbols_timeout);
// onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
// UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF)
// UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbos by default in IDF)
// onlyOnTimeout parameter will define how onReceive will behave:
// Default: true -- The callback will only be called when RX Timeout happens.
// Whole stream of bytes will be ready for being read on the callback function at once.
// This option may lead to Rx Overflow depending on the Rx Buffer Size and number of bytes received in the streaming
// false -- The callback will be called when FIFO reaches 120 bytes and also on RX Timeout.
// The stream of incommig bytes will be "split" into blocks of 120 bytes on each callback.
// This option avoid any sort of Rx Overflow, but leaves the UART packet reassembling work to the Application.
void onReceive(OnReceiveCb function, bool onlyOnTimeout = true);
// onReceive will be called on error events (see hardwareSerial_error_t)
void onReceiveError(OnReceiveErrorCb function); void onReceiveError(OnReceiveErrorCb function);
// eventQueueReset clears all events in the queue (the events that trigger onReceive and onReceiveError) - maybe usefull in some use cases
void eventQueueReset();
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112); void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112);
void end(bool fullyTerminate = true); void end(bool fullyTerminate = true);
...@@ -140,6 +161,9 @@ protected: ...@@ -140,6 +161,9 @@ protected:
size_t _rxBufferSize; size_t _rxBufferSize;
size_t _txBufferSize; size_t _txBufferSize;
OnReceiveCb _onReceiveCB; OnReceiveCb _onReceiveCB;
// _onReceive and _rxTimeout have be consistent when timeout is disabled
bool _onReceiveTimeout;
uint8_t _rxTimeout;
OnReceiveErrorCb _onReceiveErrorCB; OnReceiveErrorCb _onReceiveErrorCB;
TaskHandle_t _eventTask; TaskHandle_t _eventTask;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册