fixes UART pin detach on end() (#7402)

This commit is contained in:
Rodrigo Garcia 2022-11-02 07:30:02 -03:00 committed by GitHub
parent d3ccd2a961
commit 2cebee4a40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 8 deletions

View file

@ -145,6 +145,10 @@ _eventTask(NULL)
#if !CONFIG_DISABLE_HAL_LOCKS
,_lock(NULL)
#endif
,_rxPin(-1)
,_txPin(-1)
,_ctsPin(-1)
,_rtsPin(-1)
{
#if !CONFIG_DISABLE_HAL_LOCKS
if(_lock == NULL){
@ -384,7 +388,8 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
// Set UART RX timeout
uartSetRxTimeout(_uart, _rxTimeout);
_rxPin = rxPin;
_txPin = txPin;
HSERIAL_MUTEX_UNLOCK();
}
@ -403,6 +408,8 @@ void HardwareSerial::end(bool fullyTerminate)
if (uartGetDebug() == _uart_nr) {
uartSetDebug(0);
}
uartDetachPins(_uart, _rxPin, _txPin, _ctsPin, _rtsPin);
_rxPin = _txPin = _ctsPin = _rtsPin = -1;
}
delay(10);
uartEnd(_uart);
@ -507,10 +514,19 @@ void HardwareSerial::setRxInvert(bool invert)
void HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{
if(_uart == NULL) {
log_e("setPins() shall be called after begin() - nothing done");
log_e("setPins() shall be called after begin() - nothing done\n");
return;
}
uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin);
// uartSetPins() checks if pins are valid for each function and for the SoC
if (uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin)) {
_txPin = _txPin >= 0 ? txPin : _txPin;
_rxPin = _rxPin >= 0 ? rxPin : _rxPin;
_rtsPin = _rtsPin >= 0 ? rtsPin : _rtsPin;
_ctsPin = _ctsPin >= 0 ? ctsPin : _ctsPin;
} else {
log_e("Error when setting Serial port Pins. Invalid Pin.\n");
}
}
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)

View file

@ -176,6 +176,7 @@ protected:
#if !CONFIG_DISABLE_HAL_LOCKS
SemaphoreHandle_t _lock;
#endif
int8_t _rxPin, _txPin, _ctsPin, _rtsPin;
void _createEventTask(void *args);
void _destroyEventTask(void);

View file

@ -23,6 +23,9 @@
#include "soc/soc_caps.h"
#include "soc/uart_struct.h"
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
static int s_uart_debug_nr = 0;
struct uart_struct_t {
@ -69,6 +72,40 @@ static uart_t _uart_bus_array[] = {
#endif
// IDF UART has no detach function. As consequence, after ending a UART, the previous pins continue
// to work as RX/TX. It can be verified by changing the UART pins and writing to the UART. Output can
// be seen in the previous pins and new pins as well.
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
// Negative Pin Number will keep it unmodified, thus this function can detach individual pins
void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{
if(uart == NULL) {
return;
}
UART_MUTEX_LOCK();
if (txPin >= 0) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[txPin], PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(txPin, SIG_GPIO_OUT_IDX, false, false);
}
if (rxPin >= 0) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rxPin], PIN_FUNC_GPIO);
esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_RX_PIN_IDX), false);
}
if (rtsPin >= 0) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rtsPin], PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(rtsPin, SIG_GPIO_OUT_IDX, false, false);
}
if (ctsPin >= 0) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctsPin], PIN_FUNC_GPIO);
esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_CTS_PIN_IDX), false);
}
UART_MUTEX_UNLOCK();
}
// solves issue https://github.com/espressif/arduino-esp32/issues/6032
// baudrate must be multiplied when CPU Frequency is lower than APB 80MHz
uint32_t _get_effective_baudrate(uint32_t baudrate)
@ -108,15 +145,16 @@ bool uartIsDriverInstalled(uart_t* uart)
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
void uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{
if(uart == NULL) {
return;
return false;
}
UART_MUTEX_LOCK();
// IDF uart_set_pin() will issue necessary Error Message and take care of all GPIO Number validation.
uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin);
bool retCode = uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin) == ESP_OK;
UART_MUTEX_UNLOCK();
return retCode;
}
//

View file

@ -91,8 +91,9 @@ int uartGetDebug();
bool uartIsDriverInstalled(uart_t* uart);
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
void uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
// Negative Pin Number will keep it unmodified, thus this function can set/reset individual pins
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
// Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins
void uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);