Skip to content

Commit 667dcac

Browse files
authored
feat(uart): set clock source as necessary
1 parent d860572 commit 667dcac

File tree

1 file changed

+57
-18
lines changed

1 file changed

+57
-18
lines changed

cores/esp32/esp32-hal-uart.c

+57-18
Original file line numberDiff line numberDiff line change
@@ -668,20 +668,22 @@ uart_t *uartBegin(
668668
if (uart_nr >= SOC_UART_HP_NUM) { // it is a LP UART NUM
669669
if (uart->_uart_clock_source > 0) {
670670
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);
671672
} else {
672673
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);
673675
}
674-
log_v("Setting UART%d to use LP clock (%d) ", uart_nr, uart_config.lp_source_clk);
675676
} else
676-
#endif
677+
#endif // SOC_UART_LP_NUM >= 1
677678
{
678679
#if CONFIG_ARDUINO_SERIAL_FORCE_IDF_DEFAULT_CLOCK_SOURCE
679680
// 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
680681
uart_config.source_clk = UART_SCLK_DEFAULT; // baudrate may change with the APB Frequency!
681682
log_v("Setting UART%d to use DEFAULT clock", uart_nr);
682683
#else
683-
if (uart->_uart_clock_source > 0) {
684+
if (uart->_uart_clock_source >= 0) {
684685
uart_config.source_clk = (soc_module_clk_t) uart->_uart_clock_source; // use user defined HP UART clock
686+
log_v("Setting UART%d to user defined HP clock source (%d) ", uart_nr, uart->_uart_clock_source);
685687
} else {
686688
// there is an issue when returning from light sleep with the C6 and H2: the uart baud rate is not restored
687689
// therefore, uart clock source will set to XTAL for all SoC that support it. This fix solves the C6|H2 issue.
@@ -700,9 +702,9 @@ uart_t *uartBegin(
700702
// 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
701703
uart_config.source_clk = UART_SCLK_DEFAULT; // baudrate may change with the APB Frequency!
702704
log_v("Setting UART%d to use DEFAULT clock", uart_nr);
703-
#endif
704-
#endif
705+
#endif // SOC_UART_SUPPORT_XTAL_CLK
705706
}
707+
#endif // CONFIG_ARDUINO_SERIAL_FORCE_IDF_DEFAULT_CLOCK_SOURCE
706708
}
707709

708710
UART_MUTEX_LOCK();
@@ -731,6 +733,7 @@ uart_t *uartBegin(
731733
uart->_tx_buffer_size = tx_buffer_size;
732734
uart->has_peek = false;
733735
uart->peek_byte = 0;
736+
uart->_uart_clock_source = uart_config.source_clk;
734737
}
735738
UART_MUTEX_UNLOCK();
736739

@@ -990,22 +993,58 @@ bool uartSetBaudRate(uart_t *uart, uint32_t baud_rate) {
990993
return false;
991994
}
992995
bool retCode = true;
993-
UART_MUTEX_LOCK();
994-
#if SOC_UART_SUPPORT_XTAL_CLK // ESP32-S3, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-H2 and ESP32-P4
995-
soc_module_clk_t newClkSrc = UART_SCLK_XTAL;
996+
soc_module_clk_t newClkSrc = UART_SCLK_DEFAULT;
997+
uint8_t previousClkSrc = uart->_uart_clock_source;
996998
#if SOC_UART_LP_NUM >= 1
997-
if (uart->num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
998-
newClkSrc = LP_UART_SCLK_DEFAULT; // use default LP clock
999+
if (uart_nr >= SOC_UART_HP_NUM) { // it is a LP UART NUM
1000+
if (uart->_uart_clock_source > 0) {
1001+
newClkSrc = (soc_periph_lp_uart_clk_src_t) uart->_uart_clock_source; // use user defined LP UART clock
1002+
log_v("Setting UART%d to user defined LP clock source (%d) ", uart->num, newClkSrc);
1003+
} else {
1004+
newClkSrc = LP_UART_SCLK_DEFAULT; // use default LP clock
1005+
log_v("Setting UART%d to Default LP clock source", uart->num);
1006+
}
1007+
} else
1008+
#endif // SOC_UART_LP_NUM >= 1
1009+
{
1010+
#if CONFIG_ARDUINO_SERIAL_FORCE_IDF_DEFAULT_CLOCK_SOURCE
1011+
// 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
1012+
// newClkSrc already set in the variable declaration
1013+
log_v("Setting UART%d to use DEFAULT clock", uart->num);
1014+
#else
1015+
if (uart->_uart_clock_source >= 0) {
1016+
newClkSrc = (soc_module_clk_t) uart->_uart_clock_source; // use user defined HP UART clock
1017+
log_v("Setting UART%d to use HP clock source (%d) ", uart->num, newClkSrc);
1018+
} else {
1019+
// there is an issue when returning from light sleep with the C6 and H2: the uart baud rate is not restored
1020+
// therefore, uart clock source will set to XTAL for all SoC that support it. This fix solves the C6|H2 issue.
1021+
#if SOC_UART_SUPPORT_XTAL_CLK
1022+
newClkSrc = UART_SCLK_XTAL; // valid for C2, S3, C3, C6, H2 and P4
1023+
log_v("Setting UART%d to use XTAL clock", uart->num);
1024+
#elif SOC_UART_SUPPORT_REF_TICK
1025+
if (baudrate <= REF_TICK_BAUDRATE_LIMIT) {
1026+
newClkSrc = UART_SCLK_REF_TICK; // valid for ESP32, S2 - MAX supported baud rate is 250 Kbps
1027+
log_v("Setting UART%d to use REF_TICK clock", uart->num);
1028+
} else {
1029+
newClkSrc = UART_SCLK_APB; // baudrate may change with the APB Frequency!
1030+
log_v("Setting UART%d to use APB clock", uart->num);
1031+
}
1032+
#else
1033+
// 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
1034+
// using newClkSrc = UART_SCLK_DEFAULT as defined in the variable declaration
1035+
log_v("Setting UART%d to use DEFAULT clock", uart->num);
1036+
#endif // SOC_UART_SUPPORT_XTAL_CLK
1037+
}
1038+
#endif // CONFIG_ARDUINO_SERIAL_FORCE_IDF_DEFAULT_CLOCK_SOURCE
9991039
}
1000-
#endif
1001-
// ESP32-P4 demands an atomic operation for setting the clock source
1002-
HP_UART_SRC_CLK_ATOMIC() {
1003-
uart_ll_set_sclk(UART_LL_GET_HW(uart->num), newClkSrc);
1040+
UART_MUTEX_LOCK();
1041+
// if necessary, set the correct UART Clock Source before changing the baudrate
1042+
if (previousClkSrc != newClkSrc) {
1043+
HP_UART_SRC_CLK_ATOMIC() {
1044+
uart_ll_set_sclk(UART_LL_GET_HW(uart->num), newClkSrc);
1045+
}
1046+
uart->_uart_clock_source = newClkSrc;
10041047
}
1005-
#else // ESP32, ESP32-S2
1006-
soc_module_clk_t newClkSrc = baud_rate <= REF_TICK_BAUDRATE_LIMIT ? SOC_MOD_CLK_REF_TICK : SOC_MOD_CLK_APB;
1007-
uart_ll_set_sclk(UART_LL_GET_HW(uart->num), newClkSrc);
1008-
#endif
10091048
if (uart_set_baudrate(uart->num, baud_rate) == ESP_OK) {
10101049
log_v("Setting UART%d baud rate to %ld.", uart->num, baud_rate);
10111050
uart->_baudrate = baud_rate;

0 commit comments

Comments
 (0)