Changes UART ISR to only trigger on RX FIFO Full and timeout (#6930)
* Changes UART ISR to only trigger on RX FIFO Full and timeout * changes initial RX timeout * Eliminates extra testing for _uart != NULL * reconfiguration with "uartSetFastReading()" * Adds new function "uartSetFastReading()" * changed default onReceive() behaviour * forces User callback in case of error * Error Code Order Set NO_ERROR as first error code, same as ESP_OK = 0
This commit is contained in:
parent
85aecec8d4
commit
dca1a1e6b3
4 changed files with 80 additions and 13 deletions
|
|
@ -140,7 +140,7 @@ _txBufferSize(0),
|
||||||
_onReceiveCB(NULL),
|
_onReceiveCB(NULL),
|
||||||
_onReceiveErrorCB(NULL),
|
_onReceiveErrorCB(NULL),
|
||||||
_onReceiveTimeout(true),
|
_onReceiveTimeout(true),
|
||||||
_rxTimeout(10),
|
_rxTimeout(2),
|
||||||
_eventTask(NULL)
|
_eventTask(NULL)
|
||||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
,_lock(NULL)
|
,_lock(NULL)
|
||||||
|
|
@ -212,6 +212,18 @@ void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout)
|
||||||
HSERIAL_MUTEX_UNLOCK();
|
HSERIAL_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function allow the user to define how many bytes will trigger an Interrupt that will copy RX FIFO to the internal RX Ringbuffer
|
||||||
|
// ISR will also move data from FIFO to RX Ringbuffer after a RX Timeout defined in HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
|
||||||
|
// A low value of FIFO Full bytes will consume more CPU time within the ISR
|
||||||
|
// A high value of FIFO Full bytes will make the application wait longer to have byte available for the Stkech in a streaming scenario
|
||||||
|
// Both RX FIFO Full and RX Timeout may affect when onReceive() will be called
|
||||||
|
void HardwareSerial::setRxFIFOFull(uint8_t fifoBytes)
|
||||||
|
{
|
||||||
|
HSERIAL_MUTEX_LOCK();
|
||||||
|
uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout
|
||||||
|
HSERIAL_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
// timout is calculates in time to receive UART symbols at the UART baudrate.
|
// timout is calculates in time to receive UART symbols at the UART baudrate.
|
||||||
// the estimation is about 11 bits per symbol (SERIAL_8N1)
|
// the estimation is about 11 bits per symbol (SERIAL_8N1)
|
||||||
void HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
|
void HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
|
||||||
|
|
@ -223,7 +235,7 @@ void HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
|
||||||
_rxTimeout = symbols_timeout;
|
_rxTimeout = symbols_timeout;
|
||||||
if (!symbols_timeout) _onReceiveTimeout = false; // only when RX timeout is disabled, we also must disable this flag
|
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
|
uartSetRxTimeout(_uart, _rxTimeout); // Set new timeout
|
||||||
|
|
||||||
HSERIAL_MUTEX_UNLOCK();
|
HSERIAL_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
@ -250,6 +262,7 @@ void HardwareSerial::_uartEventTask(void *args)
|
||||||
for(;;) {
|
for(;;) {
|
||||||
//Waiting for UART event.
|
//Waiting for UART event.
|
||||||
if(xQueueReceive(uartEventQueue, (void * )&event, (portTickType)portMAX_DELAY)) {
|
if(xQueueReceive(uartEventQueue, (void * )&event, (portTickType)portMAX_DELAY)) {
|
||||||
|
hardwareSerial_error_t currentErr = UART_NO_ERROR;
|
||||||
switch(event.type) {
|
switch(event.type) {
|
||||||
case UART_DATA:
|
case UART_DATA:
|
||||||
if(uart->_onReceiveCB && uart->available() > 0 &&
|
if(uart->_onReceiveCB && uart->available() > 0 &&
|
||||||
|
|
@ -258,28 +271,32 @@ void HardwareSerial::_uartEventTask(void *args)
|
||||||
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);
|
currentErr = UART_FIFO_OVF_ERROR;
|
||||||
break;
|
break;
|
||||||
case UART_BUFFER_FULL:
|
case UART_BUFFER_FULL:
|
||||||
log_w("UART%d Buffer Full. Consider increasing 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);
|
currentErr = UART_BUFFER_FULL_ERROR;
|
||||||
break;
|
break;
|
||||||
case UART_BREAK:
|
case UART_BREAK:
|
||||||
log_w("UART%d RX break.", uart->_uart_nr);
|
log_w("UART%d RX break.", uart->_uart_nr);
|
||||||
if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(UART_BREAK_ERROR);
|
currentErr = UART_BREAK_ERROR;
|
||||||
break;
|
break;
|
||||||
case UART_PARITY_ERR:
|
case UART_PARITY_ERR:
|
||||||
log_w("UART%d parity error.", uart->_uart_nr);
|
log_w("UART%d parity error.", uart->_uart_nr);
|
||||||
if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(UART_PARITY_ERROR);
|
currentErr = UART_PARITY_ERROR;
|
||||||
break;
|
break;
|
||||||
case UART_FRAME_ERR:
|
case UART_FRAME_ERR:
|
||||||
log_w("UART%d frame error.", uart->_uart_nr);
|
log_w("UART%d frame error.", uart->_uart_nr);
|
||||||
if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(UART_FRAME_ERROR);
|
currentErr = UART_FRAME_ERROR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_w("UART%d unknown event type %d.", uart->_uart_nr, event.type);
|
log_w("UART%d unknown event type %d.", uart->_uart_nr, event.type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (currentErr != UART_NO_ERROR) {
|
||||||
|
if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(currentErr);
|
||||||
|
if(uart->_onReceiveCB && uart->available() > 0) uart->_onReceiveCB(); // forces User Callback too
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -366,9 +383,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set UART RX timeout
|
// Set UART RX timeout
|
||||||
if (_uart != NULL) {
|
uartSetRxTimeout(_uart, _rxTimeout);
|
||||||
uart_set_rx_timeout(_uart_nr, _rxTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
HSERIAL_MUTEX_UNLOCK();
|
HSERIAL_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
UART_NO_ERROR,
|
||||||
UART_BREAK_ERROR,
|
UART_BREAK_ERROR,
|
||||||
UART_BUFFER_FULL_ERROR,
|
UART_BUFFER_FULL_ERROR,
|
||||||
UART_FIFO_OVF_ERROR,
|
UART_FIFO_OVF_ERROR,
|
||||||
|
|
@ -81,6 +82,12 @@ public:
|
||||||
// For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms
|
// 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);
|
void setRxTimeout(uint8_t symbols_timeout);
|
||||||
|
|
||||||
|
// setRxFIFOFull(uint8_t fifoBytes) will set the number of bytes that will trigger UART_INTR_RXFIFO_FULL interrupt and fill up RxRingBuffer
|
||||||
|
// This affects some functions such as Serial::available() and Serial.read() because, in a UART flow of receiving data, Serial internal
|
||||||
|
// RxRingBuffer will be filled only after these number of bytes arrive or a RX Timeout happens.
|
||||||
|
// This parameter can be set to 1 in order to receive byte by byte, but it will also consume more CPU time as the ISR will be activates often.
|
||||||
|
void setRxFIFOFull(uint8_t fifoBytes);
|
||||||
|
|
||||||
// onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
|
// 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_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)
|
// UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbos by default in IDF)
|
||||||
|
|
@ -91,7 +98,7 @@ public:
|
||||||
// false -- The callback will be called when FIFO reaches 120 bytes and also on RX Timeout.
|
// 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.
|
// 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.
|
// 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);
|
void onReceive(OnReceiveCb function, bool onlyOnTimeout = false);
|
||||||
|
|
||||||
// onReceive will be called on error events (see hardwareSerial_error_t)
|
// onReceive will be called on error events (see hardwareSerial_error_t)
|
||||||
void onReceiveError(OnReceiveErrorCb function);
|
void onReceiveError(OnReceiveErrorCb function);
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,6 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
|
||||||
uart_config.rx_flow_ctrl_thresh = rxfifo_full_thrhd;
|
uart_config.rx_flow_ctrl_thresh = rxfifo_full_thrhd;
|
||||||
uart_config.source_clk = UART_SCLK_APB;
|
uart_config.source_clk = UART_SCLK_APB;
|
||||||
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(uart_driver_install(uart_nr, rx_buffer_size, tx_buffer_size, 20, &(uart->uart_event_queue), 0));
|
ESP_ERROR_CHECK(uart_driver_install(uart_nr, rx_buffer_size, tx_buffer_size, 20, &(uart->uart_event_queue), 0));
|
||||||
ESP_ERROR_CHECK(uart_param_config(uart_nr, &uart_config));
|
ESP_ERROR_CHECK(uart_param_config(uart_nr, &uart_config));
|
||||||
ESP_ERROR_CHECK(uart_set_pin(uart_nr, txPin, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
ESP_ERROR_CHECK(uart_set_pin(uart_nr, txPin, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||||
|
|
@ -179,6 +178,49 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
|
||||||
return uart;
|
return uart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This code is under testing - for now just keep it here
|
||||||
|
void uartSetFastReading(uart_t* uart)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
// override default RX IDF Driver Interrupt - no BREAK, PARITY or OVERFLOW
|
||||||
|
uart_intr_config_t uart_intr = {
|
||||||
|
.intr_enable_mask = UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT, // only these IRQs - no BREAK, PARITY or OVERFLOW
|
||||||
|
.rx_timeout_thresh = 1,
|
||||||
|
.txfifo_empty_intr_thresh = 10,
|
||||||
|
.rxfifo_full_thresh = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(uart_intr_config(uart->num, &uart_intr));
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uartSetRxTimeout(uart_t* uart, uint8_t numSymbTimeout)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
uart_set_rx_timeout(uart->num, numSymbTimeout);
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
uart_set_rx_full_threshold(uart->num, numBytesFIFOFull);
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
void uartEnd(uart_t* uart)
|
void uartEnd(uart_t* uart)
|
||||||
{
|
{
|
||||||
if(uart == NULL) {
|
if(uart == NULL) {
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,9 @@ void uartSetBaudRate(uart_t* uart, uint32_t baud_rate);
|
||||||
uint32_t uartGetBaudRate(uart_t* uart);
|
uint32_t uartGetBaudRate(uart_t* uart);
|
||||||
|
|
||||||
void uartSetRxInvert(uart_t* uart, bool invert);
|
void uartSetRxInvert(uart_t* uart, bool invert);
|
||||||
|
void uartSetRxTimeout(uart_t* uart, uint8_t numSymbTimeout);
|
||||||
|
void uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull);
|
||||||
|
void uartSetFastReading(uart_t* uart);
|
||||||
|
|
||||||
void uartSetDebug(uart_t* uart);
|
void uartSetDebug(uart_t* uart);
|
||||||
int uartGetDebug();
|
int uartGetDebug();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue