Skip to content

Commit c5a355e

Browse files
authored
Adds HardwareSerial to Peripheral Manager Arduino 3.0.0 (#8328)
1 parent aca449f commit c5a355e

File tree

4 files changed

+122
-48
lines changed

4 files changed

+122
-48
lines changed

cores/esp32/HardwareSerial.cpp

+7-22
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,6 @@ _eventTask(NULL)
146146
#if !CONFIG_DISABLE_HAL_LOCKS
147147
,_lock(NULL)
148148
#endif
149-
,_rxPin(-1)
150-
,_txPin(-1)
151-
,_ctsPin(-1)
152-
,_rtsPin(-1)
153149
{
154150
#if !CONFIG_DISABLE_HAL_LOCKS
155151
if(_lock == NULL){
@@ -420,9 +416,6 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
420416
_rxFIFOFull = fifoFull;
421417
}
422418

423-
_rxPin = rxPin;
424-
_txPin = txPin;
425-
426419
HSERIAL_MUTEX_UNLOCK();
427420
}
428421

@@ -441,15 +434,12 @@ void HardwareSerial::end(bool fullyTerminate)
441434
if (uartGetDebug() == _uart_nr) {
442435
uartSetDebug(0);
443436
}
444-
445437
_rxFIFOFull = 0;
446-
447-
uartDetachPins(_uart, _rxPin, _txPin, _ctsPin, _rtsPin);
448-
_rxPin = _txPin = _ctsPin = _rtsPin = -1;
449-
438+
uartEnd(_uart); // fully detach all pins and delete the UART driver
439+
} else {
440+
// do not invalidate callbacks, detach pins, invalidate DBG output
441+
uart_driver_delete(_uart_nr);
450442
}
451-
delay(10);
452-
uartEnd(_uart);
453443
_uart = 0;
454444
_destroyEventTask();
455445
}
@@ -555,16 +545,11 @@ bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t r
555545
}
556546

557547
// uartSetPins() checks if pins are valid for each function and for the SoC
558-
bool retCode = uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin);
559-
if (retCode) {
560-
_txPin = _txPin >= 0 ? txPin : _txPin;
561-
_rxPin = _rxPin >= 0 ? rxPin : _rxPin;
562-
_rtsPin = _rtsPin >= 0 ? rtsPin : _rtsPin;
563-
_ctsPin = _ctsPin >= 0 ? ctsPin : _ctsPin;
548+
if (uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin)) {
549+
return true;
564550
} else {
565-
log_e("Error when setting Serial port Pins. Invalid Pin.\n");
551+
return false;
566552
}
567-
return retCode;
568553
}
569554

570555
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)

cores/esp32/HardwareSerial.h

-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ class HardwareSerial: public Stream
183183
#if !CONFIG_DISABLE_HAL_LOCKS
184184
SemaphoreHandle_t _lock;
185185
#endif
186-
int8_t _rxPin, _txPin, _ctsPin, _rtsPin;
187186

188187
void _createEventTask(void *args);
189188
void _destroyEventTask(void);

cores/esp32/esp32-hal-uart.c

+114-23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
1+
// Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
1414

1515
#include "esp32-hal-uart.h"
1616
#include "esp32-hal.h"
17+
#include "esp32-hal-periman.h"
1718

1819
#include "freertos/FreeRTOS.h"
1920
#include "freertos/semphr.h"
@@ -42,6 +43,7 @@ struct uart_struct_t {
4243
bool has_peek;
4344
uint8_t peek_byte;
4445
QueueHandle_t uart_event_queue; // export it by some uartGetEventQueue() function
46+
int8_t _rxPin, _txPin, _ctsPin, _rtsPin; // UART GPIOs
4547
};
4648

4749
#if CONFIG_DISABLE_HAL_LOCKS
@@ -50,12 +52,12 @@ struct uart_struct_t {
5052
#define UART_MUTEX_UNLOCK()
5153

5254
static uart_t _uart_bus_array[] = {
53-
{0, false, 0, NULL},
55+
{0, false, 0, NULL, -1, -1, -1, -1},
5456
#if SOC_UART_NUM > 1
55-
{1, false, 0, NULL},
57+
{1, false, 0, NULL, -1, -1, -1, -1},
5658
#endif
5759
#if SOC_UART_NUM > 2
58-
{2, false, 0, NULL},
60+
{2, false, 0, NULL, -1, -1, -1, -1},
5961
#endif
6062
};
6163

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

6769
static uart_t _uart_bus_array[] = {
68-
{NULL, 0, false, 0, NULL},
70+
{NULL, 0, false, 0, NULL, -1, -1, -1, -1},
6971
#if SOC_UART_NUM > 1
70-
{NULL, 1, false, 0, NULL},
72+
{NULL, 1, false, 0, NULL, -1, -1, -1, -1},
7173
#endif
7274
#if SOC_UART_NUM > 2
73-
{NULL, 2, false, 0, NULL},
75+
{NULL, 2, false, 0, NULL, -1, -1, -1, -1},
7476
#endif
7577
};
7678

@@ -81,13 +83,11 @@ static uart_t _uart_bus_array[] = {
8183
// be seen in the previous pins and new pins as well.
8284
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
8385
// Negative Pin Number will keep it unmodified, thus this function can detach individual pins
84-
void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
86+
static void _uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
8587
{
8688
if(uart == NULL) {
8789
return;
8890
}
89-
90-
UART_MUTEX_LOCK();
9191
if (txPin >= 0) {
9292
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[txPin], PIN_FUNC_GPIO);
9393
esp_rom_gpio_connect_out_signal(txPin, SIG_GPIO_OUT_IDX, false, false);
@@ -107,7 +107,6 @@ void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int
107107
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctsPin], PIN_FUNC_GPIO);
108108
esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_CTS_PIN_IDX), false);
109109
}
110-
UART_MUTEX_UNLOCK();
111110
}
112111

113112
// Routines that take care of UART events will be in the HardwareSerial Class code
@@ -134,17 +133,99 @@ bool uartIsDriverInstalled(uart_t* uart)
134133
return false;
135134
}
136135

136+
// Peripheral Manager detach callback
137+
static bool _uartDetachBus(void *busptr)
138+
{
139+
// sanity check - it should never happen
140+
assert(busptr && "_uartDetachBus bus NULL pointer.");
141+
142+
bool retCode = true;
143+
uart_t* bus = (uart_t*) busptr;
144+
145+
if (bus->_rxPin > 0 && perimanGetPinBusType(bus->_rxPin) == ESP32_BUS_TYPE_UART) {
146+
int8_t oldPinNum = bus->_rxPin;
147+
_uartDetachPins(bus, bus->_rxPin, -1, -1, -1);
148+
bus->_rxPin = -1;
149+
retCode &= perimanSetPinBus(oldPinNum, ESP32_BUS_TYPE_INIT, NULL);
150+
}
151+
if (retCode && bus->_txPin > 0 && perimanGetPinBusType(bus->_txPin) == ESP32_BUS_TYPE_UART) {
152+
int8_t oldPinNum = bus->_txPin;
153+
_uartDetachPins(bus, -1, bus->_txPin, -1, -1);
154+
bus->_txPin = -1;
155+
retCode &= perimanSetPinBus(oldPinNum, ESP32_BUS_TYPE_INIT, NULL);
156+
}
157+
if (retCode && bus->_ctsPin > 0 && perimanGetPinBusType(bus->_ctsPin) == ESP32_BUS_TYPE_UART) {
158+
int8_t oldPinNum = bus->_ctsPin;
159+
_uartDetachPins(bus, -1, -1, bus->_ctsPin, -1);
160+
bus->_ctsPin = -1;
161+
retCode &= perimanSetPinBus(oldPinNum, ESP32_BUS_TYPE_INIT, NULL);
162+
}
163+
if (retCode && bus->_rtsPin > 0 && perimanGetPinBusType(bus->_rtsPin) == ESP32_BUS_TYPE_UART) {
164+
int8_t oldPinNum = bus->_rtsPin;
165+
_uartDetachPins(bus, -1, -1, -1, bus->_rtsPin);
166+
bus->_rtsPin = -1;
167+
retCode &= perimanSetPinBus(oldPinNum, ESP32_BUS_TYPE_INIT, NULL);
168+
}
169+
if(retCode && uart_is_driver_installed(bus->num)) {
170+
retCode &= ESP_OK == uart_driver_delete(bus->num);
171+
}
172+
173+
return retCode;
174+
}
175+
137176
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
138177
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
139178
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
140179
{
141180
if(uart == NULL) {
142181
return false;
143182
}
183+
184+
bool retCode = true;
144185
UART_MUTEX_LOCK();
186+
if (rxPin > 0) {
187+
// detachs previous UART pin
188+
if (uart->_rxPin > 0 && rxPin != uart->_rxPin) _uartDetachPins(uart, uart->_rxPin, -1, -1, -1);
189+
//assign the new one
190+
retCode &= perimanSetPinBus(rxPin, ESP32_BUS_TYPE_UART, (void *)uart);
191+
if (retCode) {
192+
uart->_rxPin = rxPin;
193+
}
194+
}
195+
if (retCode && txPin > 0) {
196+
// detachs previous UART pin
197+
if (uart->_txPin > 0 && txPin != uart->_txPin) _uartDetachPins(uart, -1, uart->_txPin, -1, -1);
198+
//assign the new one
199+
retCode &= perimanSetPinBus(txPin, ESP32_BUS_TYPE_UART, (void *)uart);
200+
if (retCode) {
201+
uart->_txPin = txPin;
202+
}
203+
}
204+
if (retCode && ctsPin > 0) {
205+
// detachs previous UART pin
206+
if (uart->_ctsPin > 0 && ctsPin != uart->_ctsPin) _uartDetachPins(uart, -1, -1, uart->_ctsPin, -1);
207+
//assign the new one
208+
retCode &= perimanSetPinBus(ctsPin, ESP32_BUS_TYPE_UART, (void *)uart);
209+
if (retCode) {
210+
uart->_ctsPin = ctsPin;
211+
}
212+
}
213+
if (retCode && rtsPin > 0) {
214+
// detachs previous UART pin
215+
if (uart->_rtsPin > 0 && rtsPin != uart->_rtsPin) _uartDetachPins(uart, -1, -1, -1, uart->_rtsPin);
216+
//assign the new one
217+
retCode &= perimanSetPinBus(rtsPin, ESP32_BUS_TYPE_UART, (void *)uart);
218+
if (retCode) {
219+
uart->_rtsPin = rtsPin;
220+
}
221+
}
145222
// IDF uart_set_pin() will issue necessary Error Message and take care of all GPIO Number validation.
146-
bool retCode = uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin) == ESP_OK;
223+
if (retCode) retCode &= ESP_OK == uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin);
224+
147225
UART_MUTEX_UNLOCK();
226+
227+
// if it fails at any point ... detachs UART
228+
if (!retCode) _uartDetachBus((void *) uart);
148229
return retCode;
149230
}
150231

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

164-
165245
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)
166246
{
167247
if(uart_nr >= SOC_UART_NUM) {
168248
return NULL;
169249
}
170-
171250
uart_t* uart = &_uart_bus_array[uart_nr];
172251

252+
// set Peripheral Manager deInit Callback
253+
perimanSetBusDeinit(ESP32_BUS_TYPE_UART, _uartDetachBus);
254+
173255
if (uart_is_driver_installed(uart_nr)) {
174-
uartEnd(uart);
256+
_uartDetachBus((void *) uart);
175257
}
176258

177259
#if !CONFIG_DISABLE_HAL_LOCKS
178260
if(uart->lock == NULL) {
179261
uart->lock = xSemaphoreCreateMutex();
180262
if(uart->lock == NULL) {
263+
log_e("HAL LOCK error.");
181264
return NULL;
182265
}
183266
}
184267
#endif
185-
186268
UART_MUTEX_LOCK();
187269

188270
uart_config_t uart_config;
@@ -193,19 +275,27 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
193275
uart_config.rx_flow_ctrl_thresh = rxfifo_full_thrhd;
194276
uart_config.baud_rate = baudrate;
195277
uart_config.source_clk = UART_SCLK_APB;
196-
ESP_ERROR_CHECK(uart_driver_install(uart_nr, rx_buffer_size, tx_buffer_size, 20, &(uart->uart_event_queue), 0));
197-
ESP_ERROR_CHECK(uart_param_config(uart_nr, &uart_config));
198-
ESP_ERROR_CHECK(uart_set_pin(uart_nr, txPin, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
278+
bool retCode = ESP_OK == uart_driver_install(uart_nr, rx_buffer_size, tx_buffer_size, 20, &(uart->uart_event_queue), 0);
279+
if (retCode) retCode &= ESP_OK == uart_param_config(uart_nr, &uart_config);
199280

200281
// Is it right or the idea is to swap rx and tx pins?
201-
if (inverted) {
282+
if (retCode && inverted) {
202283
// invert signal for both Rx and Tx
203-
ESP_ERROR_CHECK(uart_set_line_inverse(uart_nr, UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV));
284+
retCode &= ESP_OK == uart_set_line_inverse(uart_nr, UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV);
204285
}
205286

206287
UART_MUTEX_UNLOCK();
207288

208-
uartFlush(uart);
289+
if (retCode) retCode &= uartSetPins(uart, rxPin, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
290+
291+
if (retCode) uartFlush(uart);
292+
else {
293+
_uartDetachBus((void *) uart);
294+
uart = NULL;
295+
log_e("UART%d initialization error.", uart->num);
296+
}
297+
298+
log_v("UART%d baud(%ld) Mode(%x) rxPin(%d) txPin(%d)", uart_nr, baudrate, config, rxPin, txPin);
209299
return uart;
210300
}
211301

@@ -254,14 +344,15 @@ bool uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull)
254344
return retCode;
255345
}
256346

347+
257348
void uartEnd(uart_t* uart)
258349
{
259350
if(uart == NULL) {
260351
return;
261352
}
262353

263354
UART_MUTEX_LOCK();
264-
uart_driver_delete(uart->num);
355+
_uartDetachBus((void *) uart);
265356
UART_MUTEX_UNLOCK();
266357
}
267358

cores/esp32/esp32-hal-uart.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
1+
// Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -132,7 +132,6 @@ bool uartIsDriverInstalled(uart_t* uart);
132132

133133
// Negative Pin Number will keep it unmodified, thus this function can set/reset individual pins
134134
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
135-
void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
136135

137136
// Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins
138137
bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);

0 commit comments

Comments
 (0)