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.
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
5254static 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
6769static 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
139178bool 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-
165245uart_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+
257348void 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
0 commit comments