Unverified Commit 6b1933b3 authored by Rodrigo Garcia's avatar Rodrigo Garcia Committed by GitHub

3.0.0 - UART Peripheral Manager + Detach UART pins on begin()/setPins() (#8719)

* detach UART pins

* fixes uartEnd() call
parent 9e526477
...@@ -149,7 +149,7 @@ void serialEventRun(void) ...@@ -149,7 +149,7 @@ void serialEventRun(void)
#define HSERIAL_MUTEX_UNLOCK() #define HSERIAL_MUTEX_UNLOCK()
#endif #endif
HardwareSerial::HardwareSerial(int uart_nr) : HardwareSerial::HardwareSerial(uint8_t uart_nr) :
_uart_nr(uart_nr), _uart_nr(uart_nr),
_uart(NULL), _uart(NULL),
_rxBufferSize(256), _rxBufferSize(256),
...@@ -173,6 +173,12 @@ _eventTask(NULL) ...@@ -173,6 +173,12 @@ _eventTask(NULL)
} }
} }
#endif #endif
// sets UART0 (default console) RX/TX pins as already configured in boot
if (uart_nr == 0) {
setPins(SOC_RX0, SOC_TX0);
}
// set deinit function in the Peripheral Manager
uart_init_PeriMan();
} }
HardwareSerial::~HardwareSerial() HardwareSerial::~HardwareSerial()
...@@ -342,8 +348,8 @@ void HardwareSerial::_uartEventTask(void *args) ...@@ -342,8 +348,8 @@ void HardwareSerial::_uartEventTask(void *args)
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) 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)
{ {
if(0 > _uart_nr || _uart_nr >= SOC_UART_NUM) { if(_uart_nr >= SOC_UART_NUM) {
log_e("Serial number is invalid, please use numers from 0 to %u", SOC_UART_NUM - 1); log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_NUM - 1);
return; return;
} }
...@@ -357,26 +363,32 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in ...@@ -357,26 +363,32 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
HSERIAL_MUTEX_LOCK(); HSERIAL_MUTEX_LOCK();
// First Time or after end() --> set default Pins // First Time or after end() --> set default Pins
if (!uartIsDriverInstalled(_uart)) { if (!uartIsDriverInstalled(_uart)) {
// get previously used RX/TX pins, if any.
int8_t _rxPin = uart_get_RxPin(_uart_nr);
int8_t _txPin = uart_get_TxPin(_uart_nr);
switch (_uart_nr) { switch (_uart_nr) {
case UART_NUM_0: case UART_NUM_0:
if (rxPin < 0 && txPin < 0) { if (rxPin < 0 && txPin < 0) {
rxPin = SOC_RX0; // do not change RX0/TX0 if it has already been set before
txPin = SOC_TX0; rxPin = _rxPin < 0 ? SOC_RX0 : _rxPin;
txPin = _txPin < 0 ? SOC_TX0 : _txPin;
} }
break; break;
#if SOC_UART_NUM > 1 // may save some flash bytes... #if SOC_UART_NUM > 1 // may save some flash bytes...
case UART_NUM_1: case UART_NUM_1:
if (rxPin < 0 && txPin < 0) { if (rxPin < 0 && txPin < 0) {
rxPin = RX1; // do not change RX1/TX1 if it has already been set before
txPin = TX1; rxPin = _rxPin < 0 ? RX1 : _rxPin;
txPin = _txPin < 0 ? TX1 : _txPin;
} }
break; break;
#endif #endif
#if SOC_UART_NUM > 2 // may save some flash bytes... #if SOC_UART_NUM > 2 // may save some flash bytes...
case UART_NUM_2: case UART_NUM_2:
if (rxPin < 0 && txPin < 0) { if (rxPin < 0 && txPin < 0) {
rxPin = RX2; // do not change RX2/TX2 if it has already been set before
txPin = TX2; rxPin = _rxPin < 0 ? RX2 : _rxPin;
txPin = _txPin < 0 ? TX2 : _txPin;
} }
break; break;
#endif #endif
...@@ -390,6 +402,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in ...@@ -390,6 +402,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
} }
// IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified. // IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified.
// it will detach previous UART attached pins
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, _rxBufferSize, _txBufferSize, invert, rxfifo_full_thrhd); _uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, _rxBufferSize, _txBufferSize, invert, rxfifo_full_thrhd);
if (!baud) { if (!baud) {
// using baud rate as zero, forces it to try to detect the current baud rate in place // using baud rate as zero, forces it to try to detect the current baud rate in place
...@@ -452,13 +465,13 @@ void HardwareSerial::end(bool fullyTerminate) ...@@ -452,13 +465,13 @@ void HardwareSerial::end(bool fullyTerminate)
uartSetDebug(0); uartSetDebug(0);
} }
_rxFIFOFull = 0; _rxFIFOFull = 0;
uartEnd(_uart); // fully detach all pins and delete the UART driver uartEnd(_uart_nr); // fully detach all pins and delete the UART driver
} else { } else {
// do not invalidate callbacks, detach pins, invalidate DBG output // do not invalidate callbacks, detach pins, invalidate DBG output
uart_driver_delete(_uart_nr); uart_driver_delete(_uart_nr);
} }
uartEnd(_uart); uartEnd(_uart_nr);
_uart = 0; _uart = 0;
_destroyEventTask(); _destroyEventTask();
} }
...@@ -540,8 +553,8 @@ size_t HardwareSerial::write(const uint8_t *buffer, size_t size) ...@@ -540,8 +553,8 @@ size_t HardwareSerial::write(const uint8_t *buffer, size_t size)
uartWriteBuf(_uart, buffer, size); uartWriteBuf(_uart, buffer, size);
return size; return size;
} }
uint32_t HardwareSerial::baudRate()
uint32_t HardwareSerial::baudRate()
{ {
return uartGetBaudRate(_uart); return uartGetBaudRate(_uart);
} }
...@@ -556,19 +569,11 @@ void HardwareSerial::setRxInvert(bool invert) ...@@ -556,19 +569,11 @@ void HardwareSerial::setRxInvert(bool invert)
} }
// negative Pin value will keep it unmodified // negative Pin value will keep it unmodified
// can be called after or before begin()
bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{ {
if(_uart == NULL) { // uartSetPins() checks if pins are valid and, if necessary, detaches the previous ones
log_e("setPins() shall be called after begin() - nothing done\n"); return uartSetPins(_uart_nr, rxPin, txPin, ctsPin, rtsPin);
return false;
}
// uartSetPins() checks if pins are valid for each function and for the SoC
if (uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin)) {
return true;
} else {
return false;
}
} }
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before) // Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
......
...@@ -71,7 +71,7 @@ typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb; ...@@ -71,7 +71,7 @@ typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;
class HardwareSerial: public Stream class HardwareSerial: public Stream
{ {
public: public:
HardwareSerial(int uart_nr); HardwareSerial(uint8_t uart_nr);
~HardwareSerial(); ~HardwareSerial();
// 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) // 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)
...@@ -106,6 +106,11 @@ public: ...@@ -106,6 +106,11 @@ public:
// eventQueueReset clears all events in the queue (the events that trigger onReceive and onReceiveError) - maybe usefull in some use cases // eventQueueReset clears all events in the queue (the events that trigger onReceive and onReceiveError) - maybe usefull in some use cases
void eventQueueReset(); void eventQueueReset();
// When pins are changed, it will detach the previous ones
// if pin is negative, it won't be set/changed and will be kept as is
// timeout_ms is used in baudrate detection (ESP32, ESP32S2 only)
// invert will invert RX/TX polarity
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
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);
void updateBaudRate(unsigned long baud); void updateBaudRate(unsigned long baud);
...@@ -160,7 +165,8 @@ public: ...@@ -160,7 +165,8 @@ public:
void setRxInvert(bool); void setRxInvert(bool);
// Negative Pin Number will keep it unmodified, thus this function can set individual pins // Negative Pin Number will keep it unmodified, thus this function can set individual pins
// SetPins shall be called after Serial begin() // setPins() can be called after or before begin()
// When pins are changed, it will detach the previous ones
bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1); bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before) // Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
bool setHwFlowCtrlMode(uint8_t mode = HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length bool setHwFlowCtrlMode(uint8_t mode = HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
...@@ -170,7 +176,7 @@ public: ...@@ -170,7 +176,7 @@ public:
size_t setTxBufferSize(size_t new_size); size_t setTxBufferSize(size_t new_size);
protected: protected:
int _uart_nr; uint8_t _uart_nr;
uart_t* _uart; uart_t* _uart;
size_t _rxBufferSize; size_t _rxBufferSize;
size_t _txBufferSize; size_t _txBufferSize;
......
...@@ -253,7 +253,10 @@ static void printPerimanInfo(void){ ...@@ -253,7 +253,10 @@ static void printPerimanInfo(void){
chip_report_printf(" %17u : ", i); chip_report_printf(" %17u : ", i);
switch(type){ switch(type){
case ESP32_BUS_TYPE_GPIO: chip_report_printf("GPIO\n"); break; case ESP32_BUS_TYPE_GPIO: chip_report_printf("GPIO\n"); break;
case ESP32_BUS_TYPE_UART: chip_report_printf("UART\n"); break; case ESP32_BUS_TYPE_UART_RX: chip_report_printf("UART_RX\n"); break;
case ESP32_BUS_TYPE_UART_TX: chip_report_printf("UART_TX\n"); break;
case ESP32_BUS_TYPE_UART_CTS: chip_report_printf("UART_CTS\n"); break;
case ESP32_BUS_TYPE_UART_RTS: chip_report_printf("UART_RTS\n"); break;
#if SOC_SDM_SUPPORTED #if SOC_SDM_SUPPORTED
case ESP32_BUS_TYPE_SIGMADELTA: chip_report_printf("SIGMADELTA\n"); break; case ESP32_BUS_TYPE_SIGMADELTA: chip_report_printf("SIGMADELTA\n"); break;
#endif #endif
......
...@@ -17,7 +17,10 @@ extern "C" ...@@ -17,7 +17,10 @@ extern "C"
typedef enum { typedef enum {
ESP32_BUS_TYPE_INIT, // IO has not been attached to a bus yet ESP32_BUS_TYPE_INIT, // IO has not been attached to a bus yet
ESP32_BUS_TYPE_GPIO, // IO is used as GPIO ESP32_BUS_TYPE_GPIO, // IO is used as GPIO
ESP32_BUS_TYPE_UART, // IO is used as UART pin ESP32_BUS_TYPE_UART_RX, // IO is used as UART RX pin
ESP32_BUS_TYPE_UART_TX, // IO is used as UART TX pin
ESP32_BUS_TYPE_UART_CTS, // IO is used as UART CTS pin
ESP32_BUS_TYPE_UART_RTS, // IO is used as UART RTS pin
#if SOC_SDM_SUPPORTED #if SOC_SDM_SUPPORTED
ESP32_BUS_TYPE_SIGMADELTA, // IO is used as SigmeDelta output ESP32_BUS_TYPE_SIGMADELTA, // IO is used as SigmeDelta output
#endif #endif
......
...@@ -65,8 +65,8 @@ static uart_t _uart_bus_array[] = { ...@@ -65,8 +65,8 @@ static uart_t _uart_bus_array[] = {
#else #else
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS) #define UART_MUTEX_LOCK() if(uart->lock != NULL) do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock) #define UART_MUTEX_UNLOCK() if(uart->lock != NULL) xSemaphoreGive(uart->lock)
static uart_t _uart_bus_array[] = { static uart_t _uart_bus_array[] = {
{NULL, 0, false, 0, NULL, -1, -1, -1, -1}, {NULL, 0, false, 0, NULL, -1, -1, -1, -1},
...@@ -80,35 +80,178 @@ static uart_t _uart_bus_array[] = { ...@@ -80,35 +80,178 @@ static uart_t _uart_bus_array[] = {
#endif #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 // Negative Pin Number will keep it unmodified, thus this function can detach individual pins
static void _uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) // This function will also unset the pins in the Peripheral Manager and set the pin to -1 after detaching
static bool _uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{ {
if(uart == NULL) { if(uart_num >= SOC_UART_NUM) {
return; log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1);
return false;
} }
if (txPin >= 0) { // get UART information
uart_t* uart = &_uart_bus_array[uart_num];
bool retCode = true;
//log_v("detaching UART%d pins: prev,pin RX(%d,%d) TX(%d,%d) CTS(%d,%d) RTS(%d,%d)", uart_num,
// uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10);
// detaches pins and sets Peripheral Manager and UART information
if (rxPin >= 0 && uart->_rxPin == rxPin && perimanGetPinBusType(rxPin) == ESP32_BUS_TYPE_UART_RX) {
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);
uart->_rxPin = -1; // -1 means unassigned/detached
if (!perimanSetPinBus(rxPin, ESP32_BUS_TYPE_INIT, NULL)) {
retCode = false;
log_e("UART%d failed to detach RX pin %d", uart_num, rxPin);
}
}
if (txPin >= 0 && uart->_txPin == txPin && perimanGetPinBusType(txPin) == ESP32_BUS_TYPE_UART_TX) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[txPin], PIN_FUNC_GPIO); 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); esp_rom_gpio_connect_out_signal(txPin, SIG_GPIO_OUT_IDX, false, false);
uart->_txPin = -1; // -1 means unassigned/detached
if (!perimanSetPinBus(txPin, ESP32_BUS_TYPE_INIT, NULL)) {
retCode = false;
log_e("UART%d failed to detach TX pin %d", uart_num, txPin);
}
} }
if (ctsPin >= 0 && uart->_ctsPin == ctsPin && perimanGetPinBusType(ctsPin) == ESP32_BUS_TYPE_UART_CTS) {
if (rxPin >= 0) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctsPin], PIN_FUNC_GPIO);
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_CTS_PIN_IDX), false);
esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_RX_PIN_IDX), false); uart->_ctsPin = -1; // -1 means unassigned/detached
if (!perimanSetPinBus(ctsPin, ESP32_BUS_TYPE_INIT, NULL)) {
retCode = false;
log_e("UART%d failed to detach CTS pin %d", uart_num, ctsPin);
}
} }
if (rtsPin >= 0 && uart->_rtsPin == rtsPin && perimanGetPinBusType(rtsPin) == ESP32_BUS_TYPE_UART_RTS) {
if (rtsPin >= 0) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rtsPin], PIN_FUNC_GPIO); 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); esp_rom_gpio_connect_out_signal(rtsPin, SIG_GPIO_OUT_IDX, false, false);
uart->_rtsPin = -1; // -1 means unassigned/detached
if (!perimanSetPinBus(rtsPin, ESP32_BUS_TYPE_INIT, NULL)) {
retCode = false;
log_e("UART%d failed to detach RTS pin %d", uart_num, rtsPin);
}
} }
return retCode;
}
// Peripheral Manager detach callback for each specific UART PIN
static bool _uartDetachBus_RX(void *busptr)
{
// sanity check - it should never happen
assert(busptr && "_uartDetachBus_RX bus NULL pointer.");
uart_t* bus = (uart_t*) busptr;
return _uartDetachPins(bus->num, bus->_rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
static bool _uartDetachBus_TX(void *busptr)
{
// sanity check - it should never happen
assert(busptr && "_uartDetachBus_TX bus NULL pointer.");
uart_t* bus = (uart_t*) busptr;
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, bus->_txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
static bool _uartDetachBus_CTS(void *busptr)
{
// sanity check - it should never happen
assert(busptr && "_uartDetachBus_CTS bus NULL pointer.");
uart_t* bus = (uart_t*) busptr;
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, bus->_ctsPin, UART_PIN_NO_CHANGE);
}
static bool _uartDetachBus_RTS(void *busptr)
{
// sanity check - it should never happen
assert(busptr && "_uartDetachBus_RTS bus NULL pointer.");
uart_t* bus = (uart_t*) busptr;
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, bus->_rtsPin);
}
// Attach function for UART
// connects the IO Pad, set Paripheral Manager and internal UART structure data
static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{
if(uart_num >= SOC_UART_NUM) {
log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1);
return false;
}
// get UART information
uart_t* uart = &_uart_bus_array[uart_num];
//log_v("attaching UART%d pins: prev,new RX(%d,%d) TX(%d,%d) CTS(%d,%d) RTS(%d,%d)", uart_num,
// uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10);
bool retCode = true;
if (rxPin >= 0) {
// connect RX Pad
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
if (ret) {
ret &= perimanSetPinBus(rxPin, ESP32_BUS_TYPE_UART_RX, (void *)uart);
if (ret) uart->_rxPin = rxPin;
}
if (!ret) {
log_e("UART%d failed to attach RX pin %d", uart_num, rxPin);
}
retCode &= ret;
}
if (txPin >= 0) {
// connect TX Pad
bool ret = ESP_OK == uart_set_pin(uart->num, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
if (ret) {
ret &= perimanSetPinBus(txPin, ESP32_BUS_TYPE_UART_TX, (void *)uart);
if (ret) uart->_txPin = txPin;
}
if (!ret) {
log_e("UART%d failed to attach TX pin %d", uart_num, txPin);
}
retCode &= ret;
}
if (ctsPin >= 0) { if (ctsPin >= 0) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctsPin], PIN_FUNC_GPIO); // connect CTS Pad
esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_CTS_PIN_IDX), false); bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, ctsPin);
if (ret) {
ret &= perimanSetPinBus(ctsPin, ESP32_BUS_TYPE_UART_CTS, (void *)uart);
if (ret) uart->_ctsPin = ctsPin;
}
if (!ret) {
log_e("UART%d failed to attach CTS pin %d", uart_num, ctsPin);
}
retCode &= ret;
} }
if (rtsPin >= 0) {
// connect RTS Pad
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin, UART_PIN_NO_CHANGE);
if (ret) {
ret &= perimanSetPinBus(rtsPin, ESP32_BUS_TYPE_UART_RTS, (void *)uart);
if (ret) uart->_rtsPin = rtsPin;
}
if (!ret) {
log_e("UART%d failed to attach RTS pin %d", uart_num, rtsPin);
}
retCode &= ret;
}
return retCode;
}
// just helper functions
int8_t uart_get_RxPin(uint8_t uart_num)
{
return _uart_bus_array[uart_num]._rxPin;
}
int8_t uart_get_TxPin(uint8_t uart_num)
{
return _uart_bus_array[uart_num]._txPin;
}
void uart_init_PeriMan(void)
{
// set Peripheral Manager deInit Callback for each UART pin
perimanSetBusDeinit(ESP32_BUS_TYPE_UART_RX, _uartDetachBus_RX);
perimanSetBusDeinit(ESP32_BUS_TYPE_UART_TX, _uartDetachBus_TX);
perimanSetBusDeinit(ESP32_BUS_TYPE_UART_CTS, _uartDetachBus_CTS);
perimanSetBusDeinit(ESP32_BUS_TYPE_UART_RTS, _uartDetachBus_RTS);
} }
// Routines that take care of UART events will be in the HardwareSerial Class code // Routines that take care of UART events will be in the HardwareSerial Class code
...@@ -135,99 +278,59 @@ bool uartIsDriverInstalled(uart_t* uart) ...@@ -135,99 +278,59 @@ bool uartIsDriverInstalled(uart_t* uart)
return false; return false;
} }
// Peripheral Manager detach callback
static bool _uartDetachBus(void *busptr)
{
// sanity check - it should never happen
assert(busptr && "_uartDetachBus bus NULL pointer.");
bool retCode = true;
uart_t* bus = (uart_t*) busptr;
if (bus->_rxPin > 0 && perimanGetPinBusType(bus->_rxPin) == ESP32_BUS_TYPE_UART) {
int8_t oldPinNum = bus->_rxPin;
_uartDetachPins(bus, bus->_rxPin, -1, -1, -1);
bus->_rxPin = -1;
retCode &= perimanSetPinBus(oldPinNum, ESP32_BUS_TYPE_INIT, NULL);
}
if (retCode && bus->_txPin > 0 && perimanGetPinBusType(bus->_txPin) == ESP32_BUS_TYPE_UART) {
int8_t oldPinNum = bus->_txPin;
_uartDetachPins(bus, -1, bus->_txPin, -1, -1);
bus->_txPin = -1;
retCode &= perimanSetPinBus(oldPinNum, ESP32_BUS_TYPE_INIT, NULL);
}
if (retCode && bus->_ctsPin > 0 && perimanGetPinBusType(bus->_ctsPin) == ESP32_BUS_TYPE_UART) {
int8_t oldPinNum = bus->_ctsPin;
_uartDetachPins(bus, -1, -1, bus->_ctsPin, -1);
bus->_ctsPin = -1;
retCode &= perimanSetPinBus(oldPinNum, ESP32_BUS_TYPE_INIT, NULL);
}
if (retCode && bus->_rtsPin > 0 && perimanGetPinBusType(bus->_rtsPin) == ESP32_BUS_TYPE_UART) {
int8_t oldPinNum = bus->_rtsPin;
_uartDetachPins(bus, -1, -1, -1, bus->_rtsPin);
bus->_rtsPin = -1;
retCode &= perimanSetPinBus(oldPinNum, ESP32_BUS_TYPE_INIT, NULL);
}
if(retCode && uart_is_driver_installed(bus->num)) {
retCode &= ESP_OK == uart_driver_delete(bus->num);
}
return retCode;
}
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
// Negative Pin Number will keep it unmodified, thus this function can set individual pins // Negative Pin Number will keep it unmodified, thus this function can set individual pins
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) // When pins are changed, it will detach the previous one
bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{ {
if(uart == NULL) { if(uart_num >= SOC_UART_NUM) {
log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1);
return false; return false;
} }
// get UART information
uart_t* uart = &_uart_bus_array[uart_num];
bool retCode = true; bool retCode = true;
UART_MUTEX_LOCK(); UART_MUTEX_LOCK();
if (rxPin > 0) {
// detachs previous UART pin //log_v("setting UART%d pins: prev->new RX(%d->%d) TX(%d->%d) CTS(%d->%d) RTS(%d->%d)", uart_num,
if (uart->_rxPin > 0 && rxPin != uart->_rxPin) _uartDetachPins(uart, uart->_rxPin, -1, -1, -1); // uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10);
//assign the new one
retCode &= perimanSetPinBus(rxPin, ESP32_BUS_TYPE_UART, (void *)uart); // First step: detachs all previous UART pins
if (retCode) { bool rxPinChanged = rxPin >= 0 && rxPin != uart->_rxPin;
uart->_rxPin = rxPin; if (rxPinChanged) {
} retCode &= _uartDetachPins(uart_num, uart->_rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
} }
if (retCode && txPin > 0) { bool txPinChanged = txPin >= 0 && txPin != uart->_txPin;
// detachs previous UART pin if (txPinChanged) {
if (uart->_txPin > 0 && txPin != uart->_txPin) _uartDetachPins(uart, -1, uart->_txPin, -1, -1); retCode &= _uartDetachPins(uart_num, UART_PIN_NO_CHANGE, uart->_txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
//assign the new one
retCode &= perimanSetPinBus(txPin, ESP32_BUS_TYPE_UART, (void *)uart);
if (retCode) {
uart->_txPin = txPin;
}
} }
if (retCode && ctsPin > 0) { bool ctsPinChanged = ctsPin >= 0 && ctsPin != uart->_ctsPin;
// detachs previous UART pin if (ctsPinChanged) {
if (uart->_ctsPin > 0 && ctsPin != uart->_ctsPin) _uartDetachPins(uart, -1, -1, uart->_ctsPin, -1); retCode &= _uartDetachPins(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, uart->_ctsPin, UART_PIN_NO_CHANGE);
//assign the new one
retCode &= perimanSetPinBus(ctsPin, ESP32_BUS_TYPE_UART, (void *)uart);
if (retCode) {
uart->_ctsPin = ctsPin;
}
} }
if (retCode && rtsPin > 0) { bool rtsPinChanged = rtsPin >= 0 && rtsPin != uart->_rtsPin;
// detachs previous UART pin if (rtsPinChanged) {
if (uart->_rtsPin > 0 && rtsPin != uart->_rtsPin) _uartDetachPins(uart, -1, -1, -1, uart->_rtsPin); retCode &= _uartDetachPins(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, uart->_rtsPin);
//assign the new one
retCode &= perimanSetPinBus(rtsPin, ESP32_BUS_TYPE_UART, (void *)uart);
if (retCode) {
uart->_rtsPin = rtsPin;
}
} }
// IDF uart_set_pin() will issue necessary Error Message and take care of all GPIO Number validation.
if (retCode) retCode &= ESP_OK == uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin);
// Second step: attach all UART new pins
if (rxPinChanged) {
retCode &= _uartAttachPins(uart_num, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
if (txPinChanged) {
retCode &= _uartAttachPins(uart_num, UART_PIN_NO_CHANGE, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
if (ctsPinChanged) {
retCode &= _uartAttachPins(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, ctsPin, UART_PIN_NO_CHANGE);
}
if (rtsPinChanged) {
retCode &= _uartAttachPins(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin);
}
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
// if it fails at any point ... detachs UART if (!retCode) {
if (!retCode) _uartDetachBus((void *) uart); log_e("UART%d set pins failed.");
}
return retCode; return retCode;
} }
...@@ -251,11 +354,8 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx ...@@ -251,11 +354,8 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
} }
uart_t* uart = &_uart_bus_array[uart_nr]; uart_t* uart = &_uart_bus_array[uart_nr];
// set Peripheral Manager deInit Callback
perimanSetBusDeinit(ESP32_BUS_TYPE_UART, _uartDetachBus);
if (uart_is_driver_installed(uart_nr)) { if (uart_is_driver_installed(uart_nr)) {
_uartDetachBus((void *) uart); uartEnd(uart_nr);
} }
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
...@@ -288,12 +388,12 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx ...@@ -288,12 +388,12 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
} }
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
// uartSetPins detaches previous pins if new ones are used over a previous begin()
if (retCode) retCode &= uartSetPins(uart, rxPin, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); if (retCode) retCode &= uartSetPins(uart_nr, rxPin, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
if (retCode) uartFlush(uart); if (retCode) uartFlush(uart);
else { else {
_uartDetachBus((void *) uart); uartEnd(uart_nr);
uart = NULL; uart = NULL;
log_e("UART%d initialization error.", uart->num); log_e("UART%d initialization error.", uart->num);
} }
...@@ -348,14 +448,20 @@ bool uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull) ...@@ -348,14 +448,20 @@ bool uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull)
} }
void uartEnd(uart_t* uart) void uartEnd(uint8_t uart_num)
{ {
if(uart == NULL) { if(uart_num >= SOC_UART_NUM) {
log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1);
return; return;
} }
// get UART information
uart_t* uart = &_uart_bus_array[uart_num];
UART_MUTEX_LOCK(); UART_MUTEX_LOCK();
_uartDetachBus((void *) uart); _uartDetachPins(uart_num, uart->_rxPin, uart->_txPin, uart->_ctsPin, uart->_rtsPin);
if(uart_is_driver_installed(uart_num)) {
uart_driver_delete(uart_num);
}
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
} }
......
...@@ -103,7 +103,7 @@ struct uart_struct_t; ...@@ -103,7 +103,7 @@ struct uart_struct_t;
typedef struct uart_struct_t uart_t; typedef struct uart_struct_t uart_t;
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t rx_buffer_size, uint16_t tx_buffer_size, bool inverted, uint8_t rxfifo_full_thrhd); uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t rx_buffer_size, uint16_t tx_buffer_size, bool inverted, uint8_t rxfifo_full_thrhd);
void uartEnd(uart_t* uart); void uartEnd(uint8_t uart_num);
// This is used to retrieve the Event Queue pointer from a UART IDF Driver in order to allow user to deal with its events // This is used to retrieve the Event Queue pointer from a UART IDF Driver in order to allow user to deal with its events
void uartGetEventQueue(uart_t* uart, QueueHandle_t *q); void uartGetEventQueue(uart_t* uart, QueueHandle_t *q);
...@@ -133,8 +133,16 @@ int uartGetDebug(); ...@@ -133,8 +133,16 @@ int uartGetDebug();
bool uartIsDriverInstalled(uart_t* uart); bool uartIsDriverInstalled(uart_t* uart);
// Negative Pin Number will keep it unmodified, thus this function can set/reset individual pins // Negative Pin Number will keep it unmodified, thus this function can set individual pins
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin); // When pins are changed, it will detach the previous ones
// Can be called before or after begin()
bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
// helper functions
int8_t uart_get_RxPin(uint8_t uart_num);
int8_t uart_get_TxPin(uint8_t uart_num);
void uart_init_PeriMan(void);
// Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins // Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins
bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold); bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment