1
- // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
1
+ // Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
2
2
//
3
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
4
// you may not use this file except in compliance with the License.
14
14
15
15
#include "esp32-hal-uart.h"
16
16
#include "esp32-hal.h"
17
+ #include "esp32-hal-periman.h"
17
18
18
19
#include "freertos/FreeRTOS.h"
19
20
#include "freertos/semphr.h"
@@ -42,6 +43,7 @@ struct uart_struct_t {
42
43
bool has_peek ;
43
44
uint8_t peek_byte ;
44
45
QueueHandle_t uart_event_queue ; // export it by some uartGetEventQueue() function
46
+ int8_t _rxPin , _txPin , _ctsPin , _rtsPin ; // UART GPIOs
45
47
};
46
48
47
49
#if CONFIG_DISABLE_HAL_LOCKS
@@ -50,12 +52,12 @@ struct uart_struct_t {
50
52
#define UART_MUTEX_UNLOCK ()
51
53
52
54
static uart_t _uart_bus_array [] = {
53
- {0 , false, 0 , NULL },
55
+ {0 , false, 0 , NULL , -1 , -1 , -1 , -1 },
54
56
#if SOC_UART_NUM > 1
55
- {1 , false, 0 , NULL },
57
+ {1 , false, 0 , NULL , -1 , -1 , -1 , -1 },
56
58
#endif
57
59
#if SOC_UART_NUM > 2
58
- {2 , false, 0 , NULL },
60
+ {2 , false, 0 , NULL , -1 , -1 , -1 , -1 },
59
61
#endif
60
62
};
61
63
@@ -65,12 +67,12 @@ static uart_t _uart_bus_array[] = {
65
67
#define UART_MUTEX_UNLOCK () xSemaphoreGive(uart->lock)
66
68
67
69
static uart_t _uart_bus_array [] = {
68
- {NULL , 0 , false, 0 , NULL },
70
+ {NULL , 0 , false, 0 , NULL , -1 , -1 , -1 , -1 },
69
71
#if SOC_UART_NUM > 1
70
- {NULL , 1 , false, 0 , NULL },
72
+ {NULL , 1 , false, 0 , NULL , -1 , -1 , -1 , -1 },
71
73
#endif
72
74
#if SOC_UART_NUM > 2
73
- {NULL , 2 , false, 0 , NULL },
75
+ {NULL , 2 , false, 0 , NULL , -1 , -1 , -1 , -1 },
74
76
#endif
75
77
};
76
78
@@ -81,13 +83,11 @@ static uart_t _uart_bus_array[] = {
81
83
// be seen in the previous pins and new pins as well.
82
84
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
83
85
// 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 )
85
87
{
86
88
if (uart == NULL ) {
87
89
return ;
88
90
}
89
-
90
- UART_MUTEX_LOCK ();
91
91
if (txPin >= 0 ) {
92
92
gpio_hal_iomux_func_sel (GPIO_PIN_MUX_REG [txPin ], PIN_FUNC_GPIO );
93
93
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
107
107
gpio_hal_iomux_func_sel (GPIO_PIN_MUX_REG [ctsPin ], PIN_FUNC_GPIO );
108
108
esp_rom_gpio_connect_in_signal (GPIO_FUNC_IN_LOW , UART_PERIPH_SIGNAL (uart -> num , SOC_UART_CTS_PIN_IDX ), false);
109
109
}
110
- UART_MUTEX_UNLOCK ();
111
110
}
112
111
113
112
// Routines that take care of UART events will be in the HardwareSerial Class code
@@ -134,17 +133,99 @@ bool uartIsDriverInstalled(uart_t* uart)
134
133
return false;
135
134
}
136
135
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
+
137
176
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
138
177
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
139
178
bool uartSetPins (uart_t * uart , int8_t rxPin , int8_t txPin , int8_t ctsPin , int8_t rtsPin )
140
179
{
141
180
if (uart == NULL ) {
142
181
return false;
143
182
}
183
+
184
+ bool retCode = true;
144
185
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
+ }
145
222
// 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
+
147
225
UART_MUTEX_UNLOCK ();
226
+
227
+ // if it fails at any point ... detachs UART
228
+ if (!retCode ) _uartDetachBus ((void * ) uart );
148
229
return retCode ;
149
230
}
150
231
@@ -161,28 +242,29 @@ bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold) {
161
242
return retCode ;
162
243
}
163
244
164
-
165
245
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 )
166
246
{
167
247
if (uart_nr >= SOC_UART_NUM ) {
168
248
return NULL ;
169
249
}
170
-
171
250
uart_t * uart = & _uart_bus_array [uart_nr ];
172
251
252
+ // set Peripheral Manager deInit Callback
253
+ perimanSetBusDeinit (ESP32_BUS_TYPE_UART , _uartDetachBus );
254
+
173
255
if (uart_is_driver_installed (uart_nr )) {
174
- uartEnd ( uart );
256
+ _uartDetachBus (( void * ) uart );
175
257
}
176
258
177
259
#if !CONFIG_DISABLE_HAL_LOCKS
178
260
if (uart -> lock == NULL ) {
179
261
uart -> lock = xSemaphoreCreateMutex ();
180
262
if (uart -> lock == NULL ) {
263
+ log_e ("HAL LOCK error." );
181
264
return NULL ;
182
265
}
183
266
}
184
267
#endif
185
-
186
268
UART_MUTEX_LOCK ();
187
269
188
270
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
193
275
uart_config .rx_flow_ctrl_thresh = rxfifo_full_thrhd ;
194
276
uart_config .baud_rate = baudrate ;
195
277
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 );
199
280
200
281
// Is it right or the idea is to swap rx and tx pins?
201
- if (inverted ) {
282
+ if (retCode && inverted ) {
202
283
// 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 );
204
285
}
205
286
206
287
UART_MUTEX_UNLOCK ();
207
288
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 );
209
299
return uart ;
210
300
}
211
301
@@ -254,14 +344,15 @@ bool uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull)
254
344
return retCode ;
255
345
}
256
346
347
+
257
348
void uartEnd (uart_t * uart )
258
349
{
259
350
if (uart == NULL ) {
260
351
return ;
261
352
}
262
353
263
354
UART_MUTEX_LOCK ();
264
- uart_driver_delete ( uart -> num );
355
+ _uartDetachBus (( void * ) uart );
265
356
UART_MUTEX_UNLOCK ();
266
357
}
267
358
0 commit comments