1- // Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
1+ // Copyright 2015-2024 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.
3333#include "hal/gpio_hal.h"
3434#include "esp_rom_gpio.h"
3535
36- static int s_uart_debug_nr = 0 ;
36+ static int s_uart_debug_nr = 0 ; // UART number for debug output
3737
3838struct uart_struct_t {
3939
4040#if !CONFIG_DISABLE_HAL_LOCKS
41- SemaphoreHandle_t lock ;
41+ SemaphoreHandle_t lock ; // UART lock
4242#endif
4343
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
4955};
5056
5157#if CONFIG_DISABLE_HAL_LOCKS
@@ -54,12 +60,12 @@ struct uart_struct_t {
5460#define UART_MUTEX_UNLOCK ()
5561
5662static 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 },
5864#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 },
6066#endif
6167#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 },
6369#endif
6470};
6571
@@ -69,12 +75,12 @@ static uart_t _uart_bus_array[] = {
6975#define UART_MUTEX_UNLOCK () if(uart->lock != NULL) xSemaphoreGive(uart->lock)
7076
7177static 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 },
7379#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 },
7581#endif
7682#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 },
7884#endif
7985};
8086
@@ -97,7 +103,12 @@ static bool _uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
97103 // detaches pins and sets Peripheral Manager and UART information
98104 if (rxPin >= 0 && uart -> _rxPin == rxPin && perimanGetPinBusType (rxPin ) == ESP32_BUS_TYPE_UART_RX ) {
99105 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+ }
101112 uart -> _rxPin = -1 ; // -1 means unassigned/detached
102113 if (!perimanClearPinBus (rxPin )) {
103114 retCode = false;
@@ -355,28 +366,121 @@ bool uartSetHwFlowCtrlMode(uart_t *uart, uart_hw_flowcontrol_t mode, uint8_t thr
355366 return retCode ;
356367}
357368
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 )
359371{
360372 if (uart_nr >= SOC_UART_NUM ) {
361- return NULL ;
373+ return false; // no new driver has to be installed
362374 }
363375 uart_t * uart = & _uart_bus_array [uart_nr ];
364-
376+ // verify if is necessary to restart the UART driver
365377 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
367386 }
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 );
368397
369398#if !CONFIG_DISABLE_HAL_LOCKS
370399 if (uart -> lock == NULL ) {
371400 uart -> lock = xSemaphoreCreateMutex ();
372401 if (uart -> lock == NULL ) {
373402 log_e ("HAL LOCK error." );
374- return NULL ;
403+ return NULL ; // no new driver was installed
375404 }
376405 }
377406#endif
378- UART_MUTEX_LOCK ();
379407
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+ }
380484 uart_config_t uart_config ;
381485 uart_config .data_bits = (config & 0xc ) >> 2 ;
382486 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
386490 uart_config .baud_rate = baudrate ;
387491 // CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F40M for C2 -- CLK_PLL_F48M for H2 -- CLK_PLL_F80M for C6
388492 uart_config .source_clk = UART_SCLK_DEFAULT ;
493+
494+ UART_MUTEX_LOCK ();
389495 bool retCode = ESP_OK == uart_driver_install (uart_nr , rx_buffer_size , tx_buffer_size , 20 , & (uart -> uart_event_queue ), 0 );
496+
390497 if (retCode ) retCode &= ESP_OK == uart_param_config (uart_nr , & uart_config );
391498
392499 // 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
395502 retCode &= ESP_OK == uart_set_line_inverse (uart_nr , UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV );
396503 }
397504
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+ }
398517 UART_MUTEX_UNLOCK ();
518+
399519 // uartSetPins detaches previous pins if new ones are used over a previous begin()
400520 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 ) {
404522 uartEnd (uart_nr );
405523 uart = NULL ;
406524 log_e ("UART%d initialization error." , uart -> num );
525+ } else {
526+ uartFlush (uart );
527+ log_v ("UART%d initialization done." , uart -> num );
407528 }
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
411530}
412531
413532// 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)
658777 if (uart_get_sclk_freq (UART_SCLK_DEFAULT , & sclk_freq ) == ESP_OK ){
659778 uart_ll_set_baudrate (UART_LL_GET_HW (uart -> num ), baud_rate , sclk_freq );
660779 }
780+ uart -> _baudrate = baud_rate ;
661781 UART_MUTEX_UNLOCK ();
662782}
663783
@@ -1025,3 +1145,4 @@ int uart_send_msg_with_break(uint8_t uartNum, uint8_t *msg, size_t msgSize)
10251145}
10261146
10271147#endif /* SOC_UART_SUPPORTED */
1148+
0 commit comments