Skip to content

Adds HardwareSerial to Peripheral Manager - Arduino 3.0.0 #8328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 7 additions & 22 deletions cores/esp32/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,6 @@ _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){
Expand Down Expand Up @@ -420,9 +416,6 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
_rxFIFOFull = fifoFull;
}

_rxPin = rxPin;
_txPin = txPin;

HSERIAL_MUTEX_UNLOCK();
}

Expand All @@ -441,15 +434,12 @@ void HardwareSerial::end(bool fullyTerminate)
if (uartGetDebug() == _uart_nr) {
uartSetDebug(0);
}

_rxFIFOFull = 0;

uartDetachPins(_uart, _rxPin, _txPin, _ctsPin, _rtsPin);
_rxPin = _txPin = _ctsPin = _rtsPin = -1;

uartEnd(_uart); // fully detach all pins and delete the UART driver
} else {
// do not invalidate callbacks, detach pins, invalidate DBG output
uart_driver_delete(_uart_nr);
}
delay(10);
uartEnd(_uart);
_uart = 0;
_destroyEventTask();
}
Expand Down Expand Up @@ -555,16 +545,11 @@ bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t r
}

// uartSetPins() checks if pins are valid for each function and for the SoC
bool retCode = uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin);
if (retCode) {
_txPin = _txPin >= 0 ? txPin : _txPin;
_rxPin = _rxPin >= 0 ? rxPin : _rxPin;
_rtsPin = _rtsPin >= 0 ? rtsPin : _rtsPin;
_ctsPin = _ctsPin >= 0 ? ctsPin : _ctsPin;
if (uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin)) {
return true;
} else {
log_e("Error when setting Serial port Pins. Invalid Pin.\n");
return false;
}
return retCode;
}

// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
Expand Down
1 change: 0 additions & 1 deletion cores/esp32/HardwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ class HardwareSerial: public Stream
#if !CONFIG_DISABLE_HAL_LOCKS
SemaphoreHandle_t _lock;
#endif
int8_t _rxPin, _txPin, _ctsPin, _rtsPin;

void _createEventTask(void *args);
void _destroyEventTask(void);
Expand Down
137 changes: 114 additions & 23 deletions cores/esp32/esp32-hal-uart.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
// Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -14,6 +14,7 @@

#include "esp32-hal-uart.h"
#include "esp32-hal.h"
#include "esp32-hal-periman.h"

#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
Expand Down Expand Up @@ -42,6 +43,7 @@ struct uart_struct_t {
bool has_peek;
uint8_t peek_byte;
QueueHandle_t uart_event_queue; // export it by some uartGetEventQueue() function
int8_t _rxPin, _txPin, _ctsPin, _rtsPin; // UART GPIOs
};

#if CONFIG_DISABLE_HAL_LOCKS
Expand All @@ -50,12 +52,12 @@ struct uart_struct_t {
#define UART_MUTEX_UNLOCK()

static uart_t _uart_bus_array[] = {
{0, false, 0, NULL},
{0, false, 0, NULL, -1, -1, -1, -1},
#if SOC_UART_NUM > 1
{1, false, 0, NULL},
{1, false, 0, NULL, -1, -1, -1, -1},
#endif
#if SOC_UART_NUM > 2
{2, false, 0, NULL},
{2, false, 0, NULL, -1, -1, -1, -1},
#endif
};

Expand All @@ -65,12 +67,12 @@ static uart_t _uart_bus_array[] = {
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock)

static uart_t _uart_bus_array[] = {
{NULL, 0, false, 0, NULL},
{NULL, 0, false, 0, NULL, -1, -1, -1, -1},
#if SOC_UART_NUM > 1
{NULL, 1, false, 0, NULL},
{NULL, 1, false, 0, NULL, -1, -1, -1, -1},
#endif
#if SOC_UART_NUM > 2
{NULL, 2, false, 0, NULL},
{NULL, 2, false, 0, NULL, -1, -1, -1, -1},
#endif
};

Expand All @@ -81,13 +83,11 @@ static uart_t _uart_bus_array[] = {
// 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)
static 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);
Expand All @@ -107,7 +107,6 @@ void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int
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();
}

// Routines that take care of UART events will be in the HardwareSerial Class code
Expand All @@ -134,17 +133,99 @@ bool uartIsDriverInstalled(uart_t* uart)
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
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{
if(uart == NULL) {
return false;
}

bool retCode = true;
UART_MUTEX_LOCK();
if (rxPin > 0) {
// detachs previous UART pin
if (uart->_rxPin > 0 && rxPin != uart->_rxPin) _uartDetachPins(uart, uart->_rxPin, -1, -1, -1);
//assign the new one
retCode &= perimanSetPinBus(rxPin, ESP32_BUS_TYPE_UART, (void *)uart);
if (retCode) {
uart->_rxPin = rxPin;
}
}
if (retCode && txPin > 0) {
// detachs previous UART pin
if (uart->_txPin > 0 && txPin != uart->_txPin) _uartDetachPins(uart, -1, uart->_txPin, -1, -1);
//assign the new one
retCode &= perimanSetPinBus(txPin, ESP32_BUS_TYPE_UART, (void *)uart);
if (retCode) {
uart->_txPin = txPin;
}
}
if (retCode && ctsPin > 0) {
// detachs previous UART pin
if (uart->_ctsPin > 0 && ctsPin != uart->_ctsPin) _uartDetachPins(uart, -1, -1, uart->_ctsPin, -1);
//assign the new one
retCode &= perimanSetPinBus(ctsPin, ESP32_BUS_TYPE_UART, (void *)uart);
if (retCode) {
uart->_ctsPin = ctsPin;
}
}
if (retCode && rtsPin > 0) {
// detachs previous UART pin
if (uart->_rtsPin > 0 && rtsPin != uart->_rtsPin) _uartDetachPins(uart, -1, -1, -1, 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.
bool retCode = uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin) == ESP_OK;
if (retCode) retCode &= ESP_OK == uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin);

UART_MUTEX_UNLOCK();

// if it fails at any point ... detachs UART
if (!retCode) _uartDetachBus((void *) uart);
return retCode;
}

Expand All @@ -161,28 +242,29 @@ bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold) {
return retCode;
}


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)
{
if(uart_nr >= SOC_UART_NUM) {
return NULL;
}

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)) {
uartEnd(uart);
_uartDetachBus((void *) uart);
}

#if !CONFIG_DISABLE_HAL_LOCKS
if(uart->lock == NULL) {
uart->lock = xSemaphoreCreateMutex();
if(uart->lock == NULL) {
log_e("HAL LOCK error.");
return NULL;
}
}
#endif

UART_MUTEX_LOCK();

uart_config_t uart_config;
Expand All @@ -193,19 +275,27 @@ 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.baud_rate = baudrate;
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_param_config(uart_nr, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(uart_nr, txPin, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
bool retCode = ESP_OK == uart_driver_install(uart_nr, rx_buffer_size, tx_buffer_size, 20, &(uart->uart_event_queue), 0);
if (retCode) retCode &= ESP_OK == uart_param_config(uart_nr, &uart_config);

// Is it right or the idea is to swap rx and tx pins?
if (inverted) {
if (retCode && inverted) {
// invert signal for both Rx and Tx
ESP_ERROR_CHECK(uart_set_line_inverse(uart_nr, UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV));
retCode &= ESP_OK == uart_set_line_inverse(uart_nr, UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV);
}

UART_MUTEX_UNLOCK();

uartFlush(uart);
if (retCode) retCode &= uartSetPins(uart, rxPin, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

if (retCode) uartFlush(uart);
else {
_uartDetachBus((void *) uart);
uart = NULL;
log_e("UART%d initialization error.", uart->num);
}

log_v("UART%d baud(%ld) Mode(%x) rxPin(%d) txPin(%d)", uart_nr, baudrate, config, rxPin, txPin);
return uart;
}

Expand Down Expand Up @@ -254,14 +344,15 @@ bool uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull)
return retCode;
}


void uartEnd(uart_t* uart)
{
if(uart == NULL) {
return;
}

UART_MUTEX_LOCK();
uart_driver_delete(uart->num);
_uartDetachBus((void *) uart);
UART_MUTEX_UNLOCK();
}

Expand Down
3 changes: 1 addition & 2 deletions cores/esp32/esp32-hal-uart.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
// Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -132,7 +132,6 @@ bool uartIsDriverInstalled(uart_t* uart);

// 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
bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);
Expand Down