@@ -58,6 +58,7 @@ struct uart_struct_t {
58
58
uint16_t _rx_buffer_size , _tx_buffer_size ; // UART RX and TX buffer sizes
59
59
bool _inverted ; // UART inverted signal
60
60
uint8_t _rxfifo_full_thrhd ; // UART RX FIFO full threshold
61
+ int8_t _uart_clock_source ; // UART Clock Source used when it is started using uartBegin()
61
62
};
62
63
63
64
#if CONFIG_DISABLE_HAL_LOCKS
@@ -66,21 +67,21 @@ struct uart_struct_t {
66
67
#define UART_MUTEX_UNLOCK ()
67
68
68
69
static uart_t _uart_bus_array [] = {
69
- {0 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
70
+ {0 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
70
71
#if SOC_UART_NUM > 1
71
- {1 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
72
+ {1 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
72
73
#endif
73
74
#if SOC_UART_NUM > 2
74
- {2 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
75
+ {2 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
75
76
#endif
76
77
#if SOC_UART_NUM > 3
77
- {3 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
78
+ {3 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
78
79
#endif
79
80
#if SOC_UART_NUM > 4
80
- {4 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
81
+ {4 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
81
82
#endif
82
83
#if SOC_UART_NUM > 5
83
- {5 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
84
+ {5 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
84
85
#endif
85
86
};
86
87
@@ -95,21 +96,21 @@ static uart_t _uart_bus_array[] = {
95
96
xSemaphoreGive(uart->lock)
96
97
97
98
static uart_t _uart_bus_array [] = {
98
- {NULL , 0 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
99
+ {NULL , 0 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
99
100
#if SOC_UART_NUM > 1
100
- {NULL , 1 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
101
+ {NULL , 1 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
101
102
#endif
102
103
#if SOC_UART_NUM > 2
103
- {NULL , 2 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
104
+ {NULL , 2 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
104
105
#endif
105
106
#if SOC_UART_NUM > 3
106
- {NULL , 3 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
107
+ {NULL , 3 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
107
108
#endif
108
109
#if SOC_UART_NUM > 4
109
- {NULL , 4 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
110
+ {NULL , 4 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
110
111
#endif
111
112
#if SOC_UART_NUM > 5
112
- {NULL , 5 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 },
113
+ {NULL , 5 , false, 0 , NULL , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , false, 0 , -1 },
113
114
#endif
114
115
};
115
116
@@ -664,30 +665,40 @@ uart_t *uartBegin(
664
665
rxfifo_full_thrhd = uart_config .rx_flow_ctrl_thresh ; // makes sure that it will be set correctly in the struct
665
666
uart_config .baud_rate = baudrate ;
666
667
#if SOC_UART_LP_NUM >= 1
667
- if (uart_nr >= SOC_UART_HP_NUM ) { // it is a LP UART NUM
668
- uart_config .lp_source_clk = LP_UART_SCLK_DEFAULT ; // use default LP clock
669
- log_v ("Setting UART%d to use LP clock" , uart_nr );
668
+ if (uart_nr >= SOC_UART_HP_NUM ) { // it is a LP UART NUM
669
+ if (uart -> _uart_clock_source > 0 ) {
670
+ uart_config .lp_source_clk = (soc_periph_lp_uart_clk_src_t )uart -> _uart_clock_source ; // use user defined LP UART clock
671
+ log_v ("Setting UART%d to user defined LP clock source (%d) " , uart_nr , uart -> _uart_clock_source );
672
+ } else {
673
+ uart_config .lp_source_clk = LP_UART_SCLK_DEFAULT ; // use default LP clock
674
+ log_v ("Setting UART%d to Default LP clock source" , uart_nr );
675
+ }
670
676
} else
671
- #endif
677
+ #endif // SOC_UART_LP_NUM >= 1
672
678
{
673
- // there is an issue when returning from light sleep with the C6 and H2: the uart baud rate is not restored
674
- // therefore, uart clock source will set to XTAL for all SoC that support it. This fix solves the C6|H2 issue.
679
+ if (uart -> _uart_clock_source >= 0 ) {
680
+ uart_config .source_clk = (soc_module_clk_t )uart -> _uart_clock_source ; // use user defined HP UART clock
681
+ log_v ("Setting UART%d to user defined HP clock source (%d) " , uart_nr , uart -> _uart_clock_source );
682
+ } else {
683
+ // there is an issue when returning from light sleep with the C6 and H2: the uart baud rate is not restored
684
+ // therefore, uart clock source will set to XTAL for all SoC that support it. This fix solves the C6|H2 issue.
675
685
#if SOC_UART_SUPPORT_XTAL_CLK
676
- uart_config .source_clk = UART_SCLK_XTAL ; // valid for C2, S3, C3, C6, H2 and P4
677
- log_v ("Setting UART%d to use XTAL clock" , uart_nr );
686
+ uart_config .source_clk = UART_SCLK_XTAL ; // valid for C2, S3, C3, C6, H2 and P4
687
+ log_v ("Setting UART%d to use XTAL clock" , uart_nr );
678
688
#elif SOC_UART_SUPPORT_REF_TICK
679
- if (baudrate <= REF_TICK_BAUDRATE_LIMIT ) {
680
- uart_config .source_clk = UART_SCLK_REF_TICK ; // valid for ESP32, S2 - MAX supported baud rate is 250 Kbps
681
- log_v ("Setting UART%d to use REF_TICK clock" , uart_nr );
682
- } else {
683
- uart_config .source_clk = UART_SCLK_APB ; // baudrate may change with the APB Frequency!
684
- log_v ("Setting UART%d to use APB clock" , uart_nr );
685
- }
689
+ if (baudrate <= REF_TICK_BAUDRATE_LIMIT ) {
690
+ uart_config .source_clk = UART_SCLK_REF_TICK ; // valid for ESP32, S2 - MAX supported baud rate is 250 Kbps
691
+ log_v ("Setting UART%d to use REF_TICK clock" , uart_nr );
692
+ } else {
693
+ uart_config .source_clk = UART_SCLK_APB ; // baudrate may change with the APB Frequency!
694
+ log_v ("Setting UART%d to use APB clock" , uart_nr );
695
+ }
686
696
#else
687
- // Default CLK Source: CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F40M for C2 -- CLK_PLL_F48M for H2 -- CLK_PLL_F80M for C6
688
- uart_config .source_clk = UART_SCLK_DEFAULT ; // baudrate may change with the APB Frequency!
689
- log_v ("Setting UART%d to use DEFAULT clock" , uart_nr );
690
- #endif
697
+ // Default CLK Source: CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F40M for C2 -- CLK_PLL_F48M for H2 -- CLK_PLL_F80M for C6|P4
698
+ uart_config .source_clk = UART_SCLK_DEFAULT ; // baudrate may change with the APB Frequency!
699
+ log_v ("Setting UART%d to use DEFAULT clock" , uart_nr );
700
+ #endif // SOC_UART_SUPPORT_XTAL_CLK
701
+ }
691
702
}
692
703
693
704
UART_MUTEX_LOCK ();
@@ -716,6 +727,14 @@ uart_t *uartBegin(
716
727
uart -> _tx_buffer_size = tx_buffer_size ;
717
728
uart -> has_peek = false;
718
729
uart -> peek_byte = 0 ;
730
+ #if SOC_UART_LP_NUM >= 1
731
+ if (uart_nr >= SOC_UART_HP_NUM ) {
732
+ uart -> _uart_clock_source = uart_config .lp_source_clk ;
733
+ } else
734
+ #endif
735
+ {
736
+ uart -> _uart_clock_source = uart_config .source_clk ;
737
+ }
719
738
}
720
739
UART_MUTEX_UNLOCK ();
721
740
@@ -975,22 +994,52 @@ bool uartSetBaudRate(uart_t *uart, uint32_t baud_rate) {
975
994
return false;
976
995
}
977
996
bool retCode = true;
978
- UART_MUTEX_LOCK ();
979
- #if SOC_UART_SUPPORT_XTAL_CLK // ESP32-S3, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-H2 and ESP32-P4
980
- soc_module_clk_t newClkSrc = UART_SCLK_XTAL ;
997
+ soc_module_clk_t newClkSrc = UART_SCLK_DEFAULT ;
998
+ int8_t previousClkSrc = uart -> _uart_clock_source ;
981
999
#if SOC_UART_LP_NUM >= 1
982
1000
if (uart -> num >= SOC_UART_HP_NUM ) { // it is a LP UART NUM
983
- newClkSrc = LP_UART_SCLK_DEFAULT ; // use default LP clock
1001
+ if (uart -> _uart_clock_source > 0 ) {
1002
+ newClkSrc = (soc_periph_lp_uart_clk_src_t )uart -> _uart_clock_source ; // use user defined LP UART clock
1003
+ log_v ("Setting UART%d to user defined LP clock source (%d) " , uart -> num , newClkSrc );
1004
+ } else {
1005
+ newClkSrc = LP_UART_SCLK_DEFAULT ; // use default LP clock
1006
+ log_v ("Setting UART%d to Default LP clock source" , uart -> num );
1007
+ }
1008
+ } else
1009
+ #endif // SOC_UART_LP_NUM >= 1
1010
+ {
1011
+ if (uart -> _uart_clock_source >= 0 ) {
1012
+ newClkSrc = (soc_module_clk_t )uart -> _uart_clock_source ; // use user defined HP UART clock
1013
+ log_v ("Setting UART%d to use HP clock source (%d) " , uart -> num , newClkSrc );
1014
+ } else {
1015
+ // there is an issue when returning from light sleep with the C6 and H2: the uart baud rate is not restored
1016
+ // therefore, uart clock source will set to XTAL for all SoC that support it. This fix solves the C6|H2 issue.
1017
+ #if SOC_UART_SUPPORT_XTAL_CLK
1018
+ newClkSrc = UART_SCLK_XTAL ; // valid for C2, S3, C3, C6, H2 and P4
1019
+ log_v ("Setting UART%d to use XTAL clock" , uart -> num );
1020
+ #elif SOC_UART_SUPPORT_REF_TICK
1021
+ if (baud_rate <= REF_TICK_BAUDRATE_LIMIT ) {
1022
+ newClkSrc = UART_SCLK_REF_TICK ; // valid for ESP32, S2 - MAX supported baud rate is 250 Kbps
1023
+ log_v ("Setting UART%d to use REF_TICK clock" , uart -> num );
1024
+ } else {
1025
+ newClkSrc = UART_SCLK_APB ; // baudrate may change with the APB Frequency!
1026
+ log_v ("Setting UART%d to use APB clock" , uart -> num );
1027
+ }
1028
+ #else
1029
+ // Default CLK Source: CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F40M for C2 -- CLK_PLL_F48M for H2 -- CLK_PLL_F80M for C6|P4
1030
+ // using newClkSrc = UART_SCLK_DEFAULT as defined in the variable declaration
1031
+ log_v ("Setting UART%d to use DEFAULT clock" , uart -> num );
1032
+ #endif // SOC_UART_SUPPORT_XTAL_CLK
1033
+ }
984
1034
}
985
- #endif
986
- // ESP32-P4 demands an atomic operation for setting the clock source
987
- HP_UART_SRC_CLK_ATOMIC () {
988
- uart_ll_set_sclk (UART_LL_GET_HW (uart -> num ), newClkSrc );
1035
+ UART_MUTEX_LOCK ();
1036
+ // if necessary, set the correct UART Clock Source before changing the baudrate
1037
+ if (previousClkSrc < 0 || previousClkSrc != newClkSrc ) {
1038
+ HP_UART_SRC_CLK_ATOMIC () {
1039
+ uart_ll_set_sclk (UART_LL_GET_HW (uart -> num ), newClkSrc );
1040
+ }
1041
+ uart -> _uart_clock_source = newClkSrc ;
989
1042
}
990
- #else // ESP32, ESP32-S2
991
- soc_module_clk_t newClkSrc = baud_rate <= REF_TICK_BAUDRATE_LIMIT ? SOC_MOD_CLK_REF_TICK : SOC_MOD_CLK_APB ;
992
- uart_ll_set_sclk (UART_LL_GET_HW (uart -> num ), newClkSrc );
993
- #endif
994
1043
if (uart_set_baudrate (uart -> num , baud_rate ) == ESP_OK ) {
995
1044
log_v ("Setting UART%d baud rate to %ld." , uart -> num , baud_rate );
996
1045
uart -> _baudrate = baud_rate ;
@@ -1084,6 +1133,31 @@ bool uartSetMode(uart_t *uart, uart_mode_t mode) {
1084
1133
return retCode ;
1085
1134
}
1086
1135
1136
+ // this function will set the uart clock source
1137
+ // it must be called before uartBegin(), otherwise it won't change any thing.
1138
+ bool uartSetClockSource (uint8_t uartNum , uart_sclk_t clkSrc ) {
1139
+ if (uartNum >= SOC_UART_NUM ) {
1140
+ log_e ("UART%d is invalid. This device has %d UARTs, from 0 to %d." , uartNum , SOC_UART_NUM , SOC_UART_NUM - 1 );
1141
+ return false;
1142
+ }
1143
+ uart_t * uart = & _uart_bus_array [uartNum ];
1144
+ #if SOC_UART_LP_NUM >= 1
1145
+ if (uart -> num >= SOC_UART_HP_NUM ) {
1146
+ switch (clkSrc ) {
1147
+ case UART_SCLK_XTAL : uart -> _uart_clock_source = LP_UART_SCLK_XTAL_D2 ; break ;
1148
+ case UART_SCLK_RTC : uart -> _uart_clock_source = LP_UART_SCLK_LP_FAST ; break ;
1149
+ case UART_SCLK_DEFAULT :
1150
+ default : uart -> _uart_clock_source = LP_UART_SCLK_DEFAULT ;
1151
+ }
1152
+ } else
1153
+ #endif
1154
+ {
1155
+ uart -> _uart_clock_source = clkSrc ;
1156
+ }
1157
+ //log_i("UART%d set clock source to %d", uart->num, uart->_uart_clock_source);
1158
+ return true;
1159
+ }
1160
+
1087
1161
void uartSetDebug (uart_t * uart ) {
1088
1162
// LP UART is not supported for debug
1089
1163
if (uart == NULL || uart -> num >= SOC_UART_HP_NUM ) {
0 commit comments