mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-26 18:14:11 +00:00
feat(uart): add uart_detect_bitrate_bps API for data line bitrate measurement
Closes https://github.com/espressif/esp-idf/issues/14721
This commit is contained in:
@@ -163,7 +163,7 @@ typedef struct {
|
||||
#endif
|
||||
} uart_obj_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct uart_context_t {
|
||||
_lock_t mutex; /*!< Protect uart_module_enable, uart_module_disable, retention, etc. */
|
||||
uart_port_t port_id;
|
||||
uart_hal_context_t hal; /*!< UART hal context*/
|
||||
@@ -196,8 +196,9 @@ static portMUX_TYPE uart_selectlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static esp_err_t uart_create_sleep_retention_link_cb(void *arg);
|
||||
#endif
|
||||
|
||||
static void uart_module_enable(uart_port_t uart_num)
|
||||
static bool uart_module_enable(uart_port_t uart_num)
|
||||
{
|
||||
bool newly_enabled = false;
|
||||
_lock_acquire(&(uart_context[uart_num].mutex));
|
||||
if (uart_context[uart_num].hw_enabled != true) {
|
||||
if (uart_num < SOC_UART_HP_NUM) {
|
||||
@@ -243,8 +244,10 @@ static void uart_module_enable(uart_port_t uart_num)
|
||||
}
|
||||
#endif
|
||||
uart_context[uart_num].hw_enabled = true;
|
||||
newly_enabled = true;
|
||||
}
|
||||
_lock_release(&(uart_context[uart_num].mutex));
|
||||
return newly_enabled;
|
||||
}
|
||||
|
||||
static void uart_module_disable(uart_port_t uart_num)
|
||||
@@ -347,7 +350,7 @@ esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate)
|
||||
uint32_t sclk_freq;
|
||||
|
||||
uart_hal_get_sclk(&(uart_context[uart_num].hal), &src_clk);
|
||||
ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(src_clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), UART_TAG, "Invalid src_clk");
|
||||
ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(src_clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), UART_TAG, "invalid src_clk");
|
||||
|
||||
bool success = false;
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
@@ -909,7 +912,7 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
|
||||
}
|
||||
#endif
|
||||
uint32_t sclk_freq;
|
||||
ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(uart_sclk_sel, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), UART_TAG, "Invalid src_clk");
|
||||
ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(uart_sclk_sel, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), UART_TAG, "invalid src_clk");
|
||||
|
||||
bool success = false;
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
@@ -1999,3 +2002,88 @@ static esp_err_t uart_create_sleep_retention_link_cb(void *arg)
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************** AUTO BAUD RATE DETECTION *****************************/
|
||||
esp_err_t uart_detect_bitrate_start(uart_port_t uart_num, const uart_bitrate_detect_config_t *config)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(uart_num < SOC_UART_HP_NUM, ESP_ERR_INVALID_ARG, UART_TAG, "invalid arg");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
soc_module_clk_t uart_sclk_sel = 0;
|
||||
if (uart_module_enable(uart_num)) { // if a newly acquired port, do following configurations
|
||||
ESP_GOTO_ON_FALSE(config && GPIO_IS_VALID_GPIO(config->rx_io_num), ESP_ERR_INVALID_ARG, err, UART_TAG, "invalid arg");
|
||||
|
||||
uart_sclk_sel = (soc_module_clk_t)((config->source_clk) ? config->source_clk : UART_SCLK_DEFAULT); // if no specifying the clock source (soc_module_clk_t starts from 1), then just use the default clock
|
||||
uint32_t sclk_freq = 0;
|
||||
ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz(uart_sclk_sel, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), err, UART_TAG, "invalid source_clk");
|
||||
esp_clk_tree_enable_src(uart_sclk_sel, true);
|
||||
#if SOC_UART_SUPPORT_RTC_CLK
|
||||
if (uart_sclk_sel == (soc_module_clk_t)UART_SCLK_RTC) {
|
||||
periph_rtc_dig_clk8m_enable();
|
||||
}
|
||||
#endif
|
||||
HP_UART_SRC_CLK_ATOMIC() {
|
||||
uart_hal_set_sclk(&(uart_context[uart_num].hal), uart_sclk_sel);
|
||||
uart_hal_set_baudrate(&(uart_context[uart_num].hal), 57600, sclk_freq); // set to any baudrate
|
||||
}
|
||||
uart_set_pin(uart_num, UART_PIN_NO_CHANGE, config->rx_io_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
} else if (config != NULL) {
|
||||
ESP_LOGW(UART_TAG, "unable to re-configure for an acquired port, ignoring the new config");
|
||||
}
|
||||
|
||||
// start auto baud rate detection
|
||||
uart_hal_set_autobaud_en(&(uart_context[uart_num].hal), true);
|
||||
|
||||
err:
|
||||
if (ret != ESP_OK) {
|
||||
uart_module_disable(uart_num);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t uart_detect_bitrate_stop(uart_port_t uart_num, bool deinit, uart_bitrate_res_t *ret_res)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(uart_context[uart_num].hw_enabled && ret_res, ESP_ERR_INVALID_ARG, UART_TAG, "invalid arg");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
ret_res->low_period = uart_hal_get_low_pulse_cnt(&(uart_context[uart_num].hal)) + 1;
|
||||
ret_res->high_period = uart_hal_get_high_pulse_cnt(&(uart_context[uart_num].hal)) + 1;
|
||||
ret_res->pos_period = uart_hal_get_pos_pulse_cnt(&(uart_context[uart_num].hal)) + 1;
|
||||
ret_res->neg_period = uart_hal_get_neg_pulse_cnt(&(uart_context[uart_num].hal)) + 1;
|
||||
ret_res->edge_cnt = uart_hal_get_rxd_edge_cnt(&(uart_context[uart_num].hal));
|
||||
|
||||
// stop auto baud rate detection
|
||||
uart_hal_set_autobaud_en(&(uart_context[uart_num].hal), false);
|
||||
|
||||
const char *err_str = "";
|
||||
if (ret_res->low_period == 0 || ret_res->high_period == 0 || ret_res->pos_period == 0 || ret_res->neg_period == 0) {
|
||||
err_str = "fast";
|
||||
} else if (ret_res->low_period == UART_LL_PULSE_TICK_CNT_MAX || ret_res->high_period == UART_LL_PULSE_TICK_CNT_MAX || ret_res->pos_period == UART_LL_PULSE_TICK_CNT_MAX || ret_res->neg_period == UART_LL_PULSE_TICK_CNT_MAX) {
|
||||
err_str = "slow";
|
||||
}
|
||||
if (strcmp(err_str, "") != 0) {
|
||||
ESP_LOGE(UART_TAG, "bitrate too %s, unable to count ticks, please try to adjust source_clk", err_str);
|
||||
}
|
||||
|
||||
soc_module_clk_t src_clk;
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
src_clk = SOC_MOD_CLK_APB; // On such targets, ticks are counted with APB clock, regardless the UART func clock sel
|
||||
#else
|
||||
uart_hal_get_sclk(&(uart_context[uart_num].hal), &src_clk);
|
||||
#endif
|
||||
ret = esp_clk_tree_src_get_freq_hz(src_clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &ret_res->clk_freq_hz);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(UART_TAG, "unknown source_clk freq");
|
||||
}
|
||||
|
||||
if (deinit) { // release the port
|
||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
|
||||
#if SOC_UART_SUPPORT_RTC_CLK
|
||||
if (src_clk == (soc_module_clk_t)UART_SCLK_RTC) {
|
||||
periph_rtc_dig_clk8m_disable();
|
||||
}
|
||||
#endif
|
||||
uart_module_disable(uart_num);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user