1
- // Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
1
+ // Copyright 2015-2024 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.
33
33
#include "hal/gpio_hal.h"
34
34
#include "esp_rom_gpio.h"
35
35
36
- static int s_uart_debug_nr = 0 ;
36
+ static int s_uart_debug_nr = 0 ; // UART number for debug output
37
37
38
38
struct uart_struct_t {
39
39
40
40
#if !CONFIG_DISABLE_HAL_LOCKS
41
- SemaphoreHandle_t lock ;
41
+ SemaphoreHandle_t lock ; // UART lock
42
42
#endif
43
43
44
- uint8_t num ;
45
- bool has_peek ;
46
- uint8_t peek_byte ;
47
- QueueHandle_t uart_event_queue ; // export it by some uartGetEventQueue() function
48
- int8_t _rxPin , _txPin , _ctsPin , _rtsPin ; // UART GPIOs
44
+ uint8_t num ; // UART number for IDF driver API
45
+ bool has_peek ; // flag to indicate that there is a peek byte pending to be read
46
+ uint8_t peek_byte ; // peek byte that has been read but not consumed
47
+ QueueHandle_t uart_event_queue ; // export it by some uartGetEventQueue() function
48
+ // configuration data:: Arduino API tipical data
49
+ int8_t _rxPin , _txPin , _ctsPin , _rtsPin ; // UART GPIOs
50
+ uint32_t _baudrate , _config ; // UART baudrate and config
51
+ // UART ESP32 specific data
52
+ uint16_t _rx_buffer_size , _tx_buffer_size ; // UART RX and TX buffer sizes
53
+ bool _inverted ; // UART inverted signal
54
+ uint8_t _rxfifo_full_thrhd ; // UART RX FIFO full threshold
49
55
};
50
56
51
57
#if CONFIG_DISABLE_HAL_LOCKS
@@ -54,12 +60,12 @@ struct uart_struct_t {
54
60
#define UART_MUTEX_UNLOCK ()
55
61
56
62
static uart_t _uart_bus_array [] = {
57
- {0 , false, 0 , NULL , -1 , -1 , -1 , -1 },
63
+ {0 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
58
64
#if SOC_UART_NUM > 1
59
- {1 , false, 0 , NULL , -1 , -1 , -1 , -1 },
65
+ {1 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
60
66
#endif
61
67
#if SOC_UART_NUM > 2
62
- {2 , false, 0 , NULL , -1 , -1 , -1 , -1 },
68
+ {2 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
63
69
#endif
64
70
};
65
71
@@ -69,12 +75,12 @@ static uart_t _uart_bus_array[] = {
69
75
#define UART_MUTEX_UNLOCK () if(uart->lock != NULL) xSemaphoreGive(uart->lock)
70
76
71
77
static uart_t _uart_bus_array [] = {
72
- {NULL , 0 , false, 0 , NULL , -1 , -1 , -1 , -1 },
78
+ {NULL , 0 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
73
79
#if SOC_UART_NUM > 1
74
- {NULL , 1 , false, 0 , NULL , -1 , -1 , -1 , -1 },
80
+ {NULL , 1 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
75
81
#endif
76
82
#if SOC_UART_NUM > 2
77
- {NULL , 2 , false, 0 , NULL , -1 , -1 , -1 , -1 },
83
+ {NULL , 2 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
78
84
#endif
79
85
};
80
86
@@ -97,7 +103,12 @@ static bool _uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
97
103
// detaches pins and sets Peripheral Manager and UART information
98
104
if (rxPin >= 0 && uart -> _rxPin == rxPin && perimanGetPinBusType (rxPin ) == ESP32_BUS_TYPE_UART_RX ) {
99
105
gpio_hal_iomux_func_sel (GPIO_PIN_MUX_REG [rxPin ], PIN_FUNC_GPIO );
100
- esp_rom_gpio_connect_in_signal (GPIO_FUNC_IN_LOW , UART_PERIPH_SIGNAL (uart_num , SOC_UART_RX_PIN_IDX ), false);
106
+ // avoids causing BREAK in the UART line
107
+ if (uart -> _inverted ) {
108
+ esp_rom_gpio_connect_in_signal (GPIO_FUNC_IN_LOW , UART_PERIPH_SIGNAL (uart_num , SOC_UART_RX_PIN_IDX ), false);
109
+ } else {
110
+ esp_rom_gpio_connect_in_signal (GPIO_FUNC_IN_HIGH , UART_PERIPH_SIGNAL (uart_num , SOC_UART_RX_PIN_IDX ), false);
111
+ }
101
112
uart -> _rxPin = -1 ; // -1 means unassigned/detached
102
113
if (!perimanClearPinBus (rxPin )) {
103
114
retCode = false;
@@ -355,28 +366,121 @@ bool uartSetHwFlowCtrlMode(uart_t *uart, uart_hw_flowcontrol_t mode, uint8_t thr
355
366
return retCode ;
356
367
}
357
368
358
- 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 )
369
+ // This helper function will return true if a new IDF UART driver needs to be restarted and false if the current one can continue its execution
370
+ bool _testUartBegin (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 )
359
371
{
360
372
if (uart_nr >= SOC_UART_NUM ) {
361
- return NULL ;
373
+ return false; // no new driver has to be installed
362
374
}
363
375
uart_t * uart = & _uart_bus_array [uart_nr ];
364
-
376
+ // verify if is necessary to restart the UART driver
365
377
if (uart_is_driver_installed (uart_nr )) {
366
- uartEnd (uart_nr );
378
+ // some parameters can't be changed unless we end the UART driver
379
+ if ( uart -> _rx_buffer_size != rx_buffer_size || uart -> _tx_buffer_size != tx_buffer_size || uart -> _inverted != inverted || uart -> _rxfifo_full_thrhd != rxfifo_full_thrhd ) {
380
+ return true; // the current IDF UART driver must be terminated and a new driver shall be installed
381
+ } else {
382
+ return false; // The current IDF UART driver can continue its execution
383
+ }
384
+ } else {
385
+ return true; // no IDF UART driver is running and a new driver shall be installed
367
386
}
387
+ }
388
+
389
+ 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 )
390
+ {
391
+ if (uart_nr >= SOC_UART_NUM ) {
392
+ log_e ("UART number is invalid, please use number from 0 to %u" , SOC_UART_NUM - 1 );
393
+ return NULL ; // no new driver was installed
394
+ }
395
+ uart_t * uart = & _uart_bus_array [uart_nr ];
396
+ log_v ("UART%d baud(%ld) Mode(%x) rxPin(%d) txPin(%d)" , uart_nr , baudrate , config , rxPin , txPin );
368
397
369
398
#if !CONFIG_DISABLE_HAL_LOCKS
370
399
if (uart -> lock == NULL ) {
371
400
uart -> lock = xSemaphoreCreateMutex ();
372
401
if (uart -> lock == NULL ) {
373
402
log_e ("HAL LOCK error." );
374
- return NULL ;
403
+ return NULL ; // no new driver was installed
375
404
}
376
405
}
377
406
#endif
378
- UART_MUTEX_LOCK ();
379
407
408
+ if (uart_is_driver_installed (uart_nr )) {
409
+ log_v ("UART%d Driver already installed." , uart_nr );
410
+ // some parameters can't be changed unless we end the UART driver
411
+ if ( uart -> _rx_buffer_size != rx_buffer_size || uart -> _tx_buffer_size != tx_buffer_size || uart -> _inverted != inverted || uart -> _rxfifo_full_thrhd != rxfifo_full_thrhd ) {
412
+ log_v ("UART%d changing buffer sizes or inverted signal or rxfifo_full_thrhd. IDF driver will be restarted" , uart_nr );
413
+ uartEnd (uart_nr );
414
+ } else {
415
+ bool retCode = true;
416
+ UART_MUTEX_LOCK ();
417
+ //User may just want to change some parameters, such as baudrate, data length, parity, stop bits or pins
418
+ if (uart -> _baudrate != baudrate ) {
419
+ if (ESP_OK != uart_set_baudrate (uart_nr , baudrate )) {
420
+ log_e ("UART%d changing baudrate failed." , uart_nr );
421
+ retCode = false;
422
+ } else {
423
+ log_v ("UART%d changed baudrate to %d" , uart_nr , baudrate );
424
+ uart -> _baudrate = baudrate ;
425
+ }
426
+ }
427
+ uart_word_length_t data_bits = (config & 0xc ) >> 2 ;
428
+ uart_parity_t parity = config & 0x3 ;
429
+ uart_stop_bits_t stop_bits = (config & 0x30 ) >> 4 ;
430
+ if (retCode && (uart -> _config & 0xc ) >> 2 != data_bits ) {
431
+ if (ESP_OK != uart_set_word_length (uart_nr , data_bits )) {
432
+ log_e ("UART%d changing data length failed." , uart_nr );
433
+ retCode = false;
434
+ } else {
435
+ log_v ("UART%d changed data length to %d" , uart_nr , data_bits + 5 );
436
+ }
437
+ }
438
+ if (retCode && (uart -> _config & 0x3 ) != parity ) {
439
+ if (ESP_OK != uart_set_parity (uart_nr , parity )) {
440
+ log_e ("UART%d changing parity failed." , uart_nr );
441
+ retCode = false;
442
+ } else {
443
+ log_v ("UART%d changed parity to %s" , uart_nr , parity == 0 ? "NONE" : parity == 2 ? "EVEN" : "ODD" );
444
+ }
445
+ }
446
+ if (retCode && (uart -> _config & 0xc30 ) >> 4 != stop_bits ) {
447
+ if (ESP_OK != uart_set_stop_bits (uart_nr , stop_bits )) {
448
+ log_e ("UART%d changing stop bits failed." , uart_nr );
449
+ retCode = false;
450
+ } else {
451
+ log_v ("UART%d changed stop bits to %d" , uart_nr , stop_bits == 3 ? 2 : 1 );
452
+ }
453
+ }
454
+ if (retCode ) uart -> _config = config ;
455
+ if (retCode && rxPin > 0 && uart -> _rxPin != rxPin ) {
456
+ retCode &= _uartDetachPins (uart_nr , uart -> _rxPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
457
+ retCode &= _uartAttachPins (uart_nr , rxPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
458
+ if (!retCode ) {
459
+ log_e ("UART%d changing RX pin failed." , uart_nr );
460
+ } else {
461
+ log_v ("UART%d changed RX pin to %d" , uart_nr , rxPin );
462
+ }
463
+ }
464
+ if (retCode && txPin > 0 && uart -> _txPin != txPin ) {
465
+ retCode &= _uartDetachPins (uart_nr , UART_PIN_NO_CHANGE , uart -> _txPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
466
+ retCode &= _uartAttachPins (uart_nr , UART_PIN_NO_CHANGE , txPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
467
+ if (!retCode ) {
468
+ log_e ("UART%d changing TX pin failed." , uart_nr );
469
+ } else {
470
+ log_v ("UART%d changed TX pin to %d" , uart_nr , txPin );
471
+ }
472
+ }
473
+ UART_MUTEX_UNLOCK ();
474
+ if (retCode ) {
475
+ // UART driver was already working, just return the uart_t structure, syaing that no new driver was installed
476
+ return uart ;
477
+ }
478
+ // if we reach this point, it means that we need to restart the UART driver
479
+ uartEnd (uart_nr );
480
+ }
481
+ } else {
482
+ log_v ("UART%d not installed. Starting installation" , uart_nr );
483
+ }
380
484
uart_config_t uart_config ;
381
485
uart_config .data_bits = (config & 0xc ) >> 2 ;
382
486
uart_config .parity = (config & 0x3 );
@@ -386,7 +490,10 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
386
490
uart_config .baud_rate = baudrate ;
387
491
// CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F40M for C2 -- CLK_PLL_F48M for H2 -- CLK_PLL_F80M for C6
388
492
uart_config .source_clk = UART_SCLK_DEFAULT ;
493
+
494
+ UART_MUTEX_LOCK ();
389
495
bool retCode = ESP_OK == uart_driver_install (uart_nr , rx_buffer_size , tx_buffer_size , 20 , & (uart -> uart_event_queue ), 0 );
496
+
390
497
if (retCode ) retCode &= ESP_OK == uart_param_config (uart_nr , & uart_config );
391
498
392
499
// Is it right or the idea is to swap rx and tx pins?
@@ -395,19 +502,31 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
395
502
retCode &= ESP_OK == uart_set_line_inverse (uart_nr , UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV );
396
503
}
397
504
505
+ if (retCode ) {
506
+ uart -> _baudrate = baudrate ;
507
+ uart -> _config = config ;
508
+ uart -> _inverted = inverted ;
509
+ uart -> _rxfifo_full_thrhd = rxfifo_full_thrhd ;
510
+ uart -> _rx_buffer_size = rx_buffer_size ;
511
+ uart -> _tx_buffer_size = tx_buffer_size ;
512
+ uart -> _ctsPin = -1 ;
513
+ uart -> _rtsPin = -1 ;
514
+ uart -> has_peek = false;
515
+ uart -> peek_byte = 0 ;
516
+ }
398
517
UART_MUTEX_UNLOCK ();
518
+
399
519
// uartSetPins detaches previous pins if new ones are used over a previous begin()
400
520
if (retCode ) retCode &= uartSetPins (uart_nr , rxPin , txPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
401
-
402
- if (retCode ) uartFlush (uart );
403
- else {
521
+ if (!retCode ) {
404
522
uartEnd (uart_nr );
405
523
uart = NULL ;
406
524
log_e ("UART%d initialization error." , uart -> num );
525
+ } else {
526
+ uartFlush (uart );
527
+ log_v ("UART%d initialization done." , uart -> num );
407
528
}
408
-
409
- log_v ("UART%d baud(%ld) Mode(%x) rxPin(%d) txPin(%d)" , uart_nr , baudrate , config , rxPin , txPin );
410
- return uart ;
529
+ return uart ; // a new driver was installed
411
530
}
412
531
413
532
// This function code is under testing - for now just keep it here
@@ -658,6 +777,7 @@ void uartSetBaudRate(uart_t* uart, uint32_t baud_rate)
658
777
if (uart_get_sclk_freq (UART_SCLK_DEFAULT , & sclk_freq ) == ESP_OK ){
659
778
uart_ll_set_baudrate (UART_LL_GET_HW (uart -> num ), baud_rate , sclk_freq );
660
779
}
780
+ uart -> _baudrate = baud_rate ;
661
781
UART_MUTEX_UNLOCK ();
662
782
}
663
783
@@ -1025,3 +1145,4 @@ int uart_send_msg_with_break(uint8_t uartNum, uint8_t *msg, size_t msgSize)
1025
1145
}
1026
1146
1027
1147
#endif /* SOC_UART_SUPPORTED */
1148
+
0 commit comments