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:
Song Ruo Jing
2025-01-24 19:34:49 +08:00
parent 01c9407bb6
commit b38ac5ad82
37 changed files with 492 additions and 400 deletions

View File

@ -39,5 +39,5 @@ if(NOT CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM)
endif()
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES unity driver test_utils
PRIV_REQUIRES esp_driver_i2c unity esp_driver_uart test_utils esp_pm esp_driver_gptimer
WHOLE_ARCHIVE)

View File

@ -12,16 +12,12 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "driver/i2c_slave.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"

View File

@ -12,16 +12,12 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "driver/i2c_slave.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@ -11,18 +11,15 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"
#include "driver/uart.h"
static const char TAG[] = "test-i2c";
@ -182,6 +179,52 @@ TEST_CASE("I2C peripheral allocate all", "[i2c]")
TEST_ESP_OK(i2c_del_master_bus(bus_handle_2));
}
TEST_CASE("I2C master clock frequency test", "[i2c]")
{
uint8_t data_wr[500] = { 0 };
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
.trans_queue_depth = 30,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x58,
.scl_speed_hz = 100000,
.flags.disable_ack_check = 1,
};
i2c_master_dev_handle_t dev_handle;
TEST_ESP_OK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
TEST_ESP_OK(i2c_master_transmit(dev_handle, data_wr, 500, 0));
uart_bitrate_detect_config_t conf = {
.rx_io_num = I2C_MASTER_SCL_IO,
.source_clk = UART_SCLK_DEFAULT,
};
uart_bitrate_res_t res = {};
uart_detect_bitrate_start(UART_NUM_1, &conf);
vTaskDelay(pdMS_TO_TICKS(50));
uart_detect_bitrate_stop(UART_NUM_1, true, &res);
int freq_hz = res.clk_freq_hz / res.pos_period;
printf("The tested I2C SCL frequency is %d\n", freq_hz);
TEST_ASSERT_INT_WITHIN(500, 100000, freq_hz);
TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle));
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
TEST_CASE("I2C master probe device test", "[i2c]")
{
// 0x22,33,44,55 does not exist on the I2C bus, so it's expected to return `not found` error

View File

@ -12,16 +12,12 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "driver/i2c_slave.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@ -12,26 +12,14 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "driver/i2c_slave.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"
// For clock checking
#include "hal/uart_hal.h"
#include "soc/uart_periph.h"
#include "hal/clk_tree_hal.h"
#include "esp_private/gpio.h"
#include "hal/uart_ll.h"
#include "esp_clk_tree.h"
void disp_buf(uint8_t *buf, int len)
{
@ -810,92 +798,3 @@ static void i2c_slave_read_test_more_port(void)
TEST_CASE_MULTIPLE_DEVICES("I2C master write slave test, more ports", "[i2c][test_env=generic_multi_device][timeout=150]", i2c_master_write_test_more_port, i2c_slave_read_test_more_port);
#endif
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
// For now, we tested the chip which has such problem.
// This test can be extended to all chip when how uart baud rate
// works has been figured out.
#if SOC_RCC_IS_INDEPENDENT
#define HP_UART_BUS_CLK_ATOMIC()
#else
#define HP_UART_BUS_CLK_ATOMIC() PERIPH_RCC_ATOMIC()
#endif
//Init uart baud rate detection
static void uart_aut_baud_det_init(int rxd_io_num)
{
gpio_func_sel(rxd_io_num, PIN_FUNC_GPIO);
gpio_set_direction(rxd_io_num, GPIO_MODE_INPUT);
gpio_pullup_en(rxd_io_num);
esp_rom_gpio_connect_in_signal(rxd_io_num, UART_PERIPH_SIGNAL(1, SOC_UART_RX_PIN_IDX), 0);
HP_UART_BUS_CLK_ATOMIC() {
uart_ll_enable_bus_clock(1, true);
uart_ll_reset_register(1);
}
/* Reset all the bits */
uart_ll_disable_intr_mask(&UART1, ~0);
uart_ll_clr_intsts_mask(&UART1, ~0);
uart_ll_set_autobaud_en(&UART1, true);
}
static void i2c_master_write_fsm_reset(void)
{
uint8_t data_wr[3] = { 0 };
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x58,
.scl_speed_hz = 10000, // Not a typical value for I2C
};
i2c_master_dev_handle_t dev_handle;
TEST_ESP_OK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
// Nack will reset the bus
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_master_transmit(dev_handle, data_wr, 3, -1));
unity_send_signal("i2c transmit fail--connect uart");
unity_wait_for_signal("uart connected");
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_master_transmit(dev_handle, data_wr, 3, -1));
unity_send_signal("i2c transmit after fsm reset");
TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle));
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
static void uart_test_i2c_master_freq(void)
{
unity_wait_for_signal("i2c transmit fail--connect uart");
uart_aut_baud_det_init(I2C_MASTER_SCL_IO);
unity_send_signal("uart connected");
unity_wait_for_signal("i2c transmit after fsm reset");
int pospulse_cnt = uart_ll_get_pos_pulse_cnt(&UART1);
int negpulse_cnt = uart_ll_get_neg_pulse_cnt(&UART1);
// Uart uses XTAL as default clock source
int freq_hz = (clk_hal_xtal_get_freq_mhz() * 1 * 1000 * 1000) / (pospulse_cnt + negpulse_cnt);
printf("The tested I2C SCL frequency is %d\n", freq_hz);
TEST_ASSERT_INT_WITHIN(500, 10000, freq_hz);
uart_ll_set_autobaud_en(&UART1, false);
HP_UART_BUS_CLK_ATOMIC() {
uart_ll_enable_bus_clock(1, false);
}
}
TEST_CASE_MULTIPLE_DEVICES("I2C master clock frequency test", "[i2c][test_env=generic_multi_device][timeout=150]", uart_test_i2c_master_freq, i2c_master_write_fsm_reset);
#endif // CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3

View File

@ -12,16 +12,12 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "driver/i2c_slave.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"

View File

@ -12,16 +12,12 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "driver/i2c_slave.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"

View File

@ -10,6 +10,6 @@ endif()
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(
SRCS ${srcs}
PRIV_REQUIRES unity esp_driver_pcnt esp_driver_ledc esp_driver_gpio esp_timer esp_psram
PRIV_REQUIRES unity esp_driver_ledc esp_driver_gpio esp_timer esp_psram esp_driver_uart
WHOLE_ARCHIVE
)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -425,15 +425,14 @@ TEST_CASE("LEDC multi fade test", "[ledc]")
}
#endif // SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
#if SOC_PCNT_SUPPORTED // Note. C61, C3, C2 do not have PCNT peripheral, the following test cases cannot be tested
// the PCNT will count the frequency of it
// use UART auto baud rate detection feature to count the frequency
static void frequency_set_get(ledc_mode_t speed_mode, ledc_timer_t timer, uint32_t desired_freq, int16_t theoretical_freq, int16_t error)
{
int real_freq;
TEST_ESP_OK(ledc_set_freq(speed_mode, timer, desired_freq));
vTaskDelay(10 / portTICK_PERIOD_MS);
real_freq = wave_count(1000);
uint32_t cnt_duration_ms = (theoretical_freq > 5000) ? 50 : ((theoretical_freq > 2000) ? 100 : 200);
int pulse_cnt = wave_count(cnt_duration_ms);
int real_freq = pulse_cnt * 1000 / cnt_duration_ms;
TEST_ASSERT_INT16_WITHIN(error, theoretical_freq, real_freq);
TEST_ASSERT_EQUAL_INT32(theoretical_freq, ledc_get_freq(speed_mode, timer));
}
@ -463,7 +462,9 @@ static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_
if (clk_src_freq == 80 * 1000 * 1000) {
theoretical_freq = 8993;
} else if (clk_src_freq == 96 * 1000 * 1000) {
theoretical_freq = 9009;
theoretical_freq = 8996;
} else if (clk_src_freq == 60 * 1000 * 1000) {
theoretical_freq = 8993;
}
frequency_set_get(speed_mode, timer, 9000, theoretical_freq, 50);
#endif
@ -476,8 +477,6 @@ static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_
TEST_CASE("LEDC set and get frequency", "[ledc][timeout=60]")
{
setup_testbench();
ledc_channel_config_t ledc_ch_config = initialize_channel_config();
#if SOC_LEDC_SUPPORT_HS_MODE
ledc_ch_config.speed_mode = LEDC_HIGH_SPEED_MODE;
@ -489,12 +488,10 @@ TEST_CASE("LEDC set and get frequency", "[ledc][timeout=60]")
#endif // SOC_LEDC_SUPPORT_HS_MODE
ledc_ch_config.speed_mode = LEDC_LOW_SPEED_MODE;
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_0, LEDC_LOW_SPEED_MODE);
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_1, LEDC_LOW_SPEED_MODE);
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_2, LEDC_LOW_SPEED_MODE);
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_3, LEDC_LOW_SPEED_MODE);
tear_testbench();
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_12_BIT, LEDC_TIMER_0, LEDC_LOW_SPEED_MODE);
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_12_BIT, LEDC_TIMER_1, LEDC_LOW_SPEED_MODE);
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_12_BIT, LEDC_TIMER_2, LEDC_LOW_SPEED_MODE);
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_12_BIT, LEDC_TIMER_3, LEDC_LOW_SPEED_MODE);
}
#if SOC_CLK_TREE_SUPPORTED
@ -517,13 +514,12 @@ static void timer_set_clk_src_and_freq_test(ledc_mode_t speed_mode, ledc_clk_cfg
} else {
TEST_ASSERT_EQUAL_INT32(freq_hz, ledc_get_freq(speed_mode, LEDC_TIMER_0));
}
int count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(10, freq_hz, count);
int count = wave_count(200);
TEST_ASSERT_UINT32_WITHIN(10, freq_hz * 200 / 1000, count);
}
TEST_CASE("LEDC timer select specific clock source", "[ledc]")
{
setup_testbench();
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
ledc_channel_config_t ledc_ch_config = {
.gpio_num = PULSE_IO,
@ -563,14 +559,11 @@ TEST_CASE("LEDC timer select specific clock source", "[ledc]")
TEST_ESP_OK(ledc_bind_channel_timer(test_speed_mode, LEDC_CHANNEL_0, LEDC_TIMER_0));
vTaskDelay(1000 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(ledc_get_freq(test_speed_mode, LEDC_TIMER_0), 500);
tear_testbench();
}
#endif //SOC_CLK_TREE_SUPPORTED
TEST_CASE("LEDC timer pause and resume", "[ledc]")
{
setup_testbench();
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
int count;
@ -595,30 +588,29 @@ TEST_CASE("LEDC timer pause and resume", "[ledc]")
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
vTaskDelay(10 / portTICK_PERIOD_MS);
count = wave_count(1000);
TEST_ASSERT_INT16_WITHIN(5, TEST_PWM_FREQ, count);
count = wave_count(200);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ * 200 / 1000, count);
//pause ledc timer, when pause it, will get no waveform count
printf("Pause ledc timer\n");
TEST_ESP_OK(ledc_timer_pause(test_speed_mode, LEDC_TIMER_0));
vTaskDelay(10 / portTICK_PERIOD_MS);
count = wave_count(1000);
TEST_ASSERT_INT16_WITHIN(5, 0, count);
count = wave_count(200);
TEST_ASSERT_UINT32_WITHIN(5, 0, count);
//resume ledc timer
printf("Resume ledc timer\n");
TEST_ESP_OK(ledc_timer_resume(test_speed_mode, LEDC_TIMER_0));
vTaskDelay(10 / portTICK_PERIOD_MS);
count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, count);
count = wave_count(200);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ * 200 / 1000, count);
//reset ledc timer
printf("reset ledc timer\n");
TEST_ESP_OK(ledc_timer_rst(test_speed_mode, LEDC_TIMER_0));
vTaskDelay(100 / portTICK_PERIOD_MS);
count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, count);
tear_testbench();
count = wave_count(200);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ * 200 / 1000, count);
}
static void ledc_cpu_reset_test_first_stage(void)
@ -637,14 +629,10 @@ static void ledc_cpu_reset_test_second_stage(void)
{
int count;
TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason());
setup_testbench();
count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, count);
tear_testbench();
count = wave_count(200);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ * 200 / 1000, count);
}
TEST_CASE_MULTIPLE_STAGES("LEDC continue work after software reset", "[ledc]",
ledc_cpu_reset_test_first_stage,
ledc_cpu_reset_test_second_stage);
#endif // SOC_PCNT_SUPPORTED

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -38,12 +38,8 @@ static void test_ledc_sleep_retention(bool allow_pd)
vTaskDelay(50 / portTICK_PERIOD_MS);
#if SOC_PCNT_SUPPORTED
setup_testbench();
pulse_count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, pulse_count);
tear_testbench(); // tear down so that PCNT won't affect TOP PD
#endif
pulse_count = wave_count(200);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ * 200 / 1000, pulse_count);
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
@ -74,12 +70,8 @@ static void test_ledc_sleep_retention(bool allow_pd)
TEST_ASSERT_EQUAL(4000, ledc_get_duty(TEST_SPEED_MODE, LEDC_CHANNEL_0));
}
#if SOC_PCNT_SUPPORTED
setup_testbench();
pulse_count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, pulse_count);
tear_testbench();
#endif
pulse_count = wave_count(200);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ * 200 / 1000, pulse_count);
}
TEST_CASE("ledc can output after light sleep (LEDC power domain xpd)", "[ledc]")
@ -100,7 +92,6 @@ TEST_CASE("ledc can output after light sleep (LEDC power domain pd)", "[ledc]")
}
#endif
#if SOC_PCNT_SUPPORTED
static const ledc_clk_src_t test_ledc_clk_in_slp[] = {
LEDC_USE_RC_FAST_CLK,
#if SOC_LEDC_SUPPORT_XTAL_CLOCK
@ -112,18 +103,14 @@ static const int test_clks_num = sizeof(test_ledc_clk_in_slp) / sizeof(test_ledc
static void ledc_output_monitor(void)
{
setup_testbench();
for (int i = 0; i < test_clks_num; i++) {
unity_wait_for_signal("Go to light sleep for 3 seconds");
vTaskDelay(500 / portTICK_PERIOD_MS);
int pulse_count = wave_count(1000);
int pulse_count = wave_count(200);
uint32_t acceptable_delta = (test_ledc_clk_in_slp[i] == (ledc_clk_src_t)LEDC_USE_RC_FAST_CLK) ? 20 : 5; // RC_FAST as the clk src has a bigger error range is reasonable
TEST_ASSERT_UINT32_WITHIN(acceptable_delta, TEST_PWM_LOW_FREQ, pulse_count);
TEST_ASSERT_UINT32_WITHIN(acceptable_delta, TEST_PWM_LOW_FREQ * 200 / 1000, pulse_count);
unity_wait_for_signal("Waked up!");
}
tear_testbench();
}
static void ledc_output_in_sleep(void)
@ -156,4 +143,3 @@ static void ledc_output_in_sleep(void)
}
TEST_CASE_MULTIPLE_DEVICES("ledc can output during light sleep", "[ledc][test_env=generic_multi_device]", ledc_output_in_sleep, ledc_output_monitor);
#endif // SOC_PCNT_SUPPORTED

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -9,7 +9,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "test_ledc_utils.h"
#include "soc/soc_caps.h"
#include "driver/uart.h"
ledc_channel_config_t initialize_channel_config(void)
{
@ -37,48 +37,16 @@ ledc_timer_config_t create_default_timer_config(void)
return ledc_time_config;
}
// use PCNT to test the waveform of LEDC
#if SOC_PCNT_SUPPORTED
#include "driver/pulse_cnt.h"
#define HIGHEST_LIMIT 10000
#define LOWEST_LIMIT -10000
static pcnt_unit_handle_t pcnt_unit;
static pcnt_channel_handle_t pcnt_chan;
void setup_testbench(void)
{
pcnt_unit_config_t unit_config = {
.high_limit = HIGHEST_LIMIT,
.low_limit = LOWEST_LIMIT,
};
TEST_ESP_OK(pcnt_new_unit(&unit_config, &pcnt_unit));
pcnt_chan_config_t chan_config = {
.edge_gpio_num = PULSE_IO,
.level_gpio_num = -1,
};
TEST_ESP_OK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit));
}
void tear_testbench(void)
{
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit));
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
TEST_ESP_OK(pcnt_del_unit(pcnt_unit));
}
// use UART auto baud rate detection feature to test the waveform of LEDC
int wave_count(int last_time)
{
int test_counter = 0;
TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit));
TEST_ESP_OK(pcnt_unit_start(pcnt_unit));
uart_bitrate_detect_config_t conf = {
.rx_io_num = PULSE_IO,
.source_clk = UART_SCLK_DEFAULT,
};
uart_bitrate_res_t res = {};
uart_detect_bitrate_start(UART_NUM_1, &conf);
vTaskDelay(pdMS_TO_TICKS(last_time));
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &test_counter));
return test_counter;
uart_detect_bitrate_stop(UART_NUM_1, true, &res);
return (res.edge_cnt + 1) / 2; // edge count -> pulse count, round up
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@ -40,22 +40,10 @@ ledc_channel_config_t initialize_channel_config(void);
*/
ledc_timer_config_t create_default_timer_config(void);
#if SOC_PCNT_SUPPORTED
/**
* Setup PCNT test bench
*/
void setup_testbench(void);
/**
* Tear down PCNT test bench
*/
void tear_testbench(void);
/**
* Use PCNT to count pulse
* Use UART auto baud rate detection feature to count pulse
*
* @param last_time Duration time in ms
* @return Pulse count
*/
int wave_count(int last_time);
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -865,6 +865,68 @@ esp_err_t uart_set_loop_back(uart_port_t uart_num, bool loop_back_en);
*/
void uart_set_always_rx_timeout(uart_port_t uart_num, bool always_rx_timeout_en);
/**************************** AUTO BAUD RATE DETECTION *****************************/
/**
* @brief UART bitrate detection configuration parameters for `uart_detect_bitrate_start` function to acquire a new uart handle
*/
typedef struct {
int rx_io_num; /*!< GPIO pin number for the incoming signal */
uart_sclk_t source_clk; /*!< The higher the frequency of the clock source, the more accurate the detected bitrate value;
The slower the frequency of the clock source, the slower the bitrate can be measured */
} uart_bitrate_detect_config_t;
/**
* @brief Structure to store the measurement results for UART bitrate detection within the measurement period
*
* Formula to calculate the bitrate:
* If the signal is ideal,
* bitrate = clk_freq_hz * 2 / (low_period + high_period)
* If the signal is weak along falling edges, then you may use
* bitrate = clk_freq_hz * 2 / pos_period
* If the signal is weak along rising edges, then you may use
* bitrate = clk_freq_hz * 2 / neg_period
*/
typedef struct {
uint32_t low_period; /*!< Stores the minimum tick count of a low-level pulse */
uint32_t high_period; /*!< Stores the minimum tick count of a high-level pulse */
uint32_t pos_period; /*!< Stores the minimum tick count between two positive edges */
uint32_t neg_period; /*!< Stores the minimum tick count between two negative edges */
uint32_t edge_cnt; /*!< Stores the count of RX edge changes (10-bit counter, be careful, it could overflow) */
uint32_t clk_freq_hz; /*!< The frequency of the tick being used to count the measurement results, in Hz */
} uart_bitrate_res_t;
/**
* @brief Start to do a bitrate detection for an incoming data signal (auto baud rate detection)
*
* This function can act as a standalone API. No need to install UART driver before calling this function.
*
* It is recommended that the incoming data line contains alternating bit sequence, data bytes such as `0x55` or `0xAA`. Characters `NULL', `0xCC` are not good for the measurement.
*
* @param uart_num The ID of the UART port to be used to do the measurement. Note that only HP UART ports have the capability.
* @param config Pointer to the configuration structure for the UART port. If the port has already been acquired, this parameter is ignored.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL No free uart port or source_clk invalid
*/
esp_err_t uart_detect_bitrate_start(uart_port_t uart_num, const uart_bitrate_detect_config_t *config);
/**
* @brief Stop the bitrate detection
*
* The measurement period should last for at least one-byte long if detecting UART baud rate, then call this function to stop and get the measurement result.
*
* @param uart_num The ID of the UART port
* @param deinit Whether to release the UART port after finishing the measurement
* @param[out] ret_res Structure to store the measurement results
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Unknown tick frequency
*/
esp_err_t uart_detect_bitrate_stop(uart_port_t uart_num, bool deinit, uart_bitrate_res_t *ret_res);
#ifdef __cplusplus
}
#endif

View File

@ -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;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -586,3 +586,62 @@ TEST_CASE("uart in one-wire mode", "[uart]")
TEST_ESP_OK(uart_driver_delete(uart_num));
}
static void uart_console_write_task(void *arg)
{
while (1) {
printf("This is a sentence used to detect uart baud rate...\nThis is a sentence used to detect uart baud rate...\nThis is a sentence used to detect uart baud rate...\nThis is a sentence used to detect uart baud rate...\nThis is a sentence used to detect uart baud rate...\n");
vTaskDelay(pdMS_TO_TICKS(100));
}
}
TEST_CASE("uart auto baud rate detection", "[uart]")
{
uart_port_param_t port_param = {};
TEST_ASSERT(port_select(&port_param));
// This is indeed a standalone feature, no need to specify the uart port, call port_select() to be compatible with pytest
// And this test case no need to be tested twice on HP/LP uart ports both exist targets (also, LP UART does not support auto baud rate detection functionality)
if (port_param.port_num < SOC_UART_HP_NUM) {
TaskHandle_t console_write_task = NULL;
xTaskCreate(uart_console_write_task, "uart_console_write_task", 2048, NULL, 5, &console_write_task);
vTaskDelay(20);
// Measure console uart baudrate
uint32_t actual_baudrate = 0;
uint32_t detected_baudrate = 0;
uart_bitrate_detect_config_t conf = {
.rx_io_num = uart_periph_signal[CONFIG_CONSOLE_UART_NUM].pins[SOC_UART_TX_PIN_IDX].default_gpio,
.source_clk = UART_SCLK_DEFAULT,
};
uart_bitrate_res_t res = {};
uart_get_baudrate(CONFIG_CONSOLE_UART_NUM, &actual_baudrate);
TEST_ESP_OK(uart_detect_bitrate_start(UART_NUM_1, &conf)); // acquire a new uart port
vTaskDelay(pdMS_TO_TICKS(500));
TEST_ESP_OK(uart_detect_bitrate_stop(UART_NUM_1, false, &res)); // no releasing
detected_baudrate = res.clk_freq_hz * 2 / res.pos_period; // assume the wave has a slow falling slew rate
TEST_ASSERT_INT32_WITHIN(actual_baudrate * 0.03, actual_baudrate, detected_baudrate); // allow 3% error
// Temporarily change console baudrate
uart_set_baudrate(CONFIG_CONSOLE_UART_NUM, 38400);
uart_get_baudrate(CONFIG_CONSOLE_UART_NUM, &actual_baudrate);
TEST_ESP_OK(uart_detect_bitrate_start(UART_NUM_1, NULL)); // use the previously acquired uart port
vTaskDelay(pdMS_TO_TICKS(500));
TEST_ESP_OK(uart_detect_bitrate_stop(UART_NUM_1, true, &res)); // release the uart port
detected_baudrate = res.clk_freq_hz * 2 / res.pos_period;
TEST_ASSERT_INT32_WITHIN(actual_baudrate * 0.03, actual_baudrate, detected_baudrate);
// Set back to original console baudrate, test again
uart_set_baudrate(CONFIG_CONSOLE_UART_NUM, CONFIG_CONSOLE_UART_BAUDRATE);
uart_get_baudrate(CONFIG_CONSOLE_UART_NUM, &actual_baudrate);
TEST_ESP_OK(uart_detect_bitrate_start(UART_NUM_1, &conf)); // acquire a new uart port again
vTaskDelay(pdMS_TO_TICKS(500));
TEST_ESP_OK(uart_detect_bitrate_stop(UART_NUM_1, true, &res)); // release it
detected_baudrate = res.clk_freq_hz * 2 / res.pos_period;
TEST_ASSERT_INT32_WITHIN(actual_baudrate * 0.03, actual_baudrate, detected_baudrate);
vTaskDelete(console_write_task);
}
}

View File

@ -4,4 +4,3 @@ CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_COMPILER_OPTIMIZATION_NONE=y

View File

@ -30,9 +30,12 @@ extern "C" {
// The timeout calibration factor when using ref_tick
#define UART_LL_TOUT_REF_FACTOR_DEFAULT (8)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
// Define UART interrupts

View File

@ -29,9 +29,12 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_FSM_IDLE (0x0)
#define UART_LL_FSM_TX_WAIT_SEND (0xf)
@ -994,6 +997,67 @@ FORCE_INLINE_ATTR uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
return UART_RX_TOUT_THRHD_V;
}
/**
* @brief Configure the auto baudrate.
*
* @param hw Beginning address of the peripheral registers.
* @param enable Boolean marking whether the auto baudrate should be enabled or not.
*/
FORCE_INLINE_ATTR void uart_ll_set_autobaud_en(uart_dev_t *hw, bool enable)
{
hw->conf0.autobaud_en = enable ? 1 : 0;
}
/**
* @brief Get the RXD edge count.
*
* @param hw Beginning address of the peripheral registers.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_rxd_edge_cnt(uart_dev_t *hw)
{
return hw->rxd_cnt.edge_cnt;
}
/**
* @brief Get the positive pulse minimum count.
*
* @param hw Beginning address of the peripheral registers.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_pos_pulse_cnt(uart_dev_t *hw)
{
return hw->pospulse.min_cnt;
}
/**
* @brief Get the negative pulse minimum count.
*
* @param hw Beginning address of the peripheral registers.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_neg_pulse_cnt(uart_dev_t *hw)
{
return hw->negpulse.min_cnt;
}
/**
* @brief Get the high pulse minimum count.
*
* @param hw Beginning address of the peripheral registers.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_high_pulse_cnt(uart_dev_t *hw)
{
return hw->highpulse.min_cnt;
}
/**
* @brief Get the low pulse minimum count.
*
* @param hw Beginning address of the peripheral registers.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_low_pulse_cnt(uart_dev_t *hw)
{
return hw->lowpulse.min_cnt;
}
/**
* @brief Force UART xoff.
*

View File

@ -29,9 +29,12 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_FSM_IDLE (0x0)
#define UART_LL_FSM_TX_WAIT_SEND (0xf)

View File

@ -31,11 +31,14 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&LP_UART)))
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)

View File

@ -31,11 +31,14 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&LP_UART)))
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)

View File

@ -30,7 +30,12 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&UART2)))
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -64,9 +69,6 @@ extern "C" {
((hw) == &UART1) ? PCR.uart1_##reg_suffix.uart1_##field_suffix : \
PCR.uart2_##reg_suffix.uart2_##field_suffix)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),

View File

@ -29,7 +29,12 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -57,10 +62,6 @@ extern "C" {
#define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \
(((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),

View File

@ -29,7 +29,12 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -58,9 +63,6 @@ extern "C" {
(((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),

View File

@ -29,7 +29,12 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_WAKEUP_EDGE_THRED_MIN (2)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -57,9 +62,6 @@ extern "C" {
#define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \
(((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),

View File

@ -38,11 +38,14 @@ extern "C" {
(num) == 3 ? (&UART3) : \
(num) == 4 ? (&UART4) : (&LP_UART))
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)

View File

@ -28,9 +28,12 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
// Define UART interrupts
typedef enum {

View File

@ -29,9 +29,12 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&UART2)))
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_PULSE_TICK_CNT_MAX UART_LOWPULSE_MIN_CNT_V
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_FSM_IDLE (0x0)
#define UART_LL_FSM_TX_WAIT_SEND (0xf)

View File

@ -479,6 +479,49 @@ uint16_t uart_hal_get_max_rx_timeout_thrd(uart_hal_context_t *hal);
*/
#define uart_hal_get_rxfifo_len(hal) uart_ll_get_rxfifo_len((hal)->dev)
/**
* @brief Enable or disable the auto baudrate detection
*
* @param hal Context of the HAL layer
* @param enable Boolean marking whether the auto baudrate should be enabled or not
*/
#define uart_hal_set_autobaud_en(hal, enable) uart_ll_set_autobaud_en((hal)->dev, enable)
/**
* @brief Get the positive pulse minimum count
*
* @param hal Context of the HAL layer
*/
#define uart_hal_get_pos_pulse_cnt(hal) uart_ll_get_pos_pulse_cnt((hal)->dev)
/**
* @brief Get the negative pulse minimum count
*
* @param hal Context of the HAL layer
*/
#define uart_hal_get_neg_pulse_cnt(hal) uart_ll_get_neg_pulse_cnt((hal)->dev)
/**
* @brief Get the high pulse minimum count
*
* @param hal Context of the HAL layer
*/
#define uart_hal_get_high_pulse_cnt(hal) uart_ll_get_high_pulse_cnt((hal)->dev)
/**
* @brief Get the low pulse minimum count
*
* @param hal Context of the HAL layer
*/
#define uart_hal_get_low_pulse_cnt(hal) uart_ll_get_low_pulse_cnt((hal)->dev)
/**
* @brief Get the RXD edge count
*
* @param hal Context of the HAL layer
*/
#define uart_hal_get_rxd_edge_cnt(hal) uart_ll_get_rxd_edge_cnt((hal)->dev)
#ifdef __cplusplus
}
#endif

View File

@ -140,8 +140,6 @@ typedef struct {
uint8_t xoff_thrd; /*!< If the software flow control is enabled and the data amount in rxfifo is more than xoff_thrd, an xoff_char will be sent*/
} uart_sw_flowctrl_t;
/**
* @brief Enumeration of UART wake-up modes.
*/

View File

@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -1287,27 +1287,6 @@ extern "C" {
* LP UART core clock configuration
*/
#define LP_UART_CLK_CONF_REG (DR_REG_LP_UART_BASE + 0x88)
/** LP_UART_SCLK_DIV_B : R/W; bitpos: [5:0]; default: 0;
* The denominator of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_B 0x0000003FU
#define LP_UART_SCLK_DIV_B_M (LP_UART_SCLK_DIV_B_V << LP_UART_SCLK_DIV_B_S)
#define LP_UART_SCLK_DIV_B_V 0x0000003FU
#define LP_UART_SCLK_DIV_B_S 0
/** LP_UART_SCLK_DIV_A : R/W; bitpos: [11:6]; default: 0;
* The numerator of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_A 0x0000003FU
#define LP_UART_SCLK_DIV_A_M (LP_UART_SCLK_DIV_A_V << LP_UART_SCLK_DIV_A_S)
#define LP_UART_SCLK_DIV_A_V 0x0000003FU
#define LP_UART_SCLK_DIV_A_S 6
/** LP_UART_SCLK_DIV_NUM : R/W; bitpos: [19:12]; default: 1;
* The integral part of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_NUM 0x000000FFU
#define LP_UART_SCLK_DIV_NUM_M (LP_UART_SCLK_DIV_NUM_V << LP_UART_SCLK_DIV_NUM_S)
#define LP_UART_SCLK_DIV_NUM_V 0x000000FFU
#define LP_UART_SCLK_DIV_NUM_S 12
/** LP_UART_TX_SCLK_EN : R/W; bitpos: [24]; default: 1;
* Configures whether or not to enable LP UART TX clock.\\
* 0: Disable\\

View File

@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -844,22 +844,7 @@ typedef union {
*/
typedef union {
struct {
/** sclk_div_b : R/W; bitpos: [5:0]; default: 0;
* The denominator of the frequency divider factor.
* Only available to LP UART instance
*/
uint32_t sclk_div_b:6;
/** sclk_div_a : R/W; bitpos: [11:6]; default: 0;
* The numerator of the frequency divider factor.
* Only available to LP UART instance
*/
uint32_t sclk_div_a:6;
/** sclk_div_num : R/W; bitpos: [19:12]; default: 1;
* The integral part of the frequency divider factor.
* Only available to LP UART instance
*/
uint32_t sclk_div_num:8;
uint32_t reserved_20:4;
uint32_t reserved_0:24;
/** tx_sclk_en : R/W; bitpos: [24]; default: 1;
* Configures whether or not to enable LP UART TX clock.\\
* 0: Disable\\

View File

@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -1235,27 +1235,6 @@ extern "C" {
* UART core clock configuration
*/
#define LP_UART_CLK_CONF_REG (DR_REG_LP_UART_BASE + 0x88)
/** LP_UART_SCLK_DIV_B : R/W; bitpos: [5:0]; default: 0;
* The denominator of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_B 0x0000003FU
#define LP_UART_SCLK_DIV_B_M (LP_UART_SCLK_DIV_B_V << LP_UART_SCLK_DIV_B_S)
#define LP_UART_SCLK_DIV_B_V 0x0000003FU
#define LP_UART_SCLK_DIV_B_S 0
/** LP_UART_SCLK_DIV_A : R/W; bitpos: [11:6]; default: 0;
* The numerator of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_A 0x0000003FU
#define LP_UART_SCLK_DIV_A_M (LP_UART_SCLK_DIV_A_V << LP_UART_SCLK_DIV_A_S)
#define LP_UART_SCLK_DIV_A_V 0x0000003FU
#define LP_UART_SCLK_DIV_A_S 6
/** LP_UART_SCLK_DIV_NUM : R/W; bitpos: [19:12]; default: 1;
* The integral part of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_NUM 0x000000FFU
#define LP_UART_SCLK_DIV_NUM_M (LP_UART_SCLK_DIV_NUM_V << LP_UART_SCLK_DIV_NUM_S)
#define LP_UART_SCLK_DIV_NUM_V 0x000000FFU
#define LP_UART_SCLK_DIV_NUM_S 12
/** LP_UART_TX_SCLK_EN : R/W; bitpos: [24]; default: 1;
* Set this bit to enable UART Tx clock.
*/

View File

@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -791,30 +791,7 @@ typedef union {
*/
typedef union {
struct {
/** sclk_div_b : R/W; bitpos: [5:0]; default: 0;
* The denominator of the frequency divider factor.
*/
uint32_t sclk_div_b:6;
/** sclk_div_a : R/W; bitpos: [11:6]; default: 0;
* The numerator of the frequency divider factor.
*/
uint32_t sclk_div_a:6;
/** sclk_div_num : R/W; bitpos: [19:12]; default: 1;
* The integral part of the frequency divider factor.
*/
uint32_t sclk_div_num:8;
/** sclk_sel : R/W; bitpos: [21:20]; default: 3;
* UART clock source select. 1: 80Mhz. 2: 8Mhz. 3: XTAL.
*/
uint32_t sclk_sel:2;
/** sclk_en : R/W; bitpos: [22]; default: 1;
* Set this bit to enable UART Tx/Rx clock.
*/
uint32_t sclk_en:1;
/** rst_core : R/W; bitpos: [23]; default: 0;
* Write 1 then write 0 to this bit to reset UART Tx/Rx.
*/
uint32_t rst_core:1;
uint32_t reserved_0:24;
/** tx_sclk_en : R/W; bitpos: [24]; default: 1;
* Set this bit to enable UART Tx clock.
*/

View File

@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -1235,27 +1235,6 @@ extern "C" {
* UART core clock configuration
*/
#define LP_UART_CLK_CONF_REG (DR_REG_LP_UART_BASE + 0x88)
/** LP_UART_SCLK_DIV_B : R/W; bitpos: [5:0]; default: 0;
* The denominator of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_B 0x0000003FU
#define LP_UART_SCLK_DIV_B_M (LP_UART_SCLK_DIV_B_V << LP_UART_SCLK_DIV_B_S)
#define LP_UART_SCLK_DIV_B_V 0x0000003FU
#define LP_UART_SCLK_DIV_B_S 0
/** LP_UART_SCLK_DIV_A : R/W; bitpos: [11:6]; default: 0;
* The numerator of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_A 0x0000003FU
#define LP_UART_SCLK_DIV_A_M (LP_UART_SCLK_DIV_A_V << LP_UART_SCLK_DIV_A_S)
#define LP_UART_SCLK_DIV_A_V 0x0000003FU
#define LP_UART_SCLK_DIV_A_S 6
/** LP_UART_SCLK_DIV_NUM : R/W; bitpos: [19:12]; default: 1;
* The integral part of the frequency divider factor.
*/
#define LP_UART_SCLK_DIV_NUM 0x000000FFU
#define LP_UART_SCLK_DIV_NUM_M (LP_UART_SCLK_DIV_NUM_V << LP_UART_SCLK_DIV_NUM_S)
#define LP_UART_SCLK_DIV_NUM_V 0x000000FFU
#define LP_UART_SCLK_DIV_NUM_S 12
/** LP_UART_TX_SCLK_EN : R/W; bitpos: [24]; default: 1;
* Set this bit to enable UART Tx clock.
*/

View File

@ -4,5 +4,5 @@ set(srcs "test_app_main.c"
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES unity test_utils spi_flash driver esp_partition esp_driver_i2c
PRIV_REQUIRES unity test_utils spi_flash driver esp_partition esp_driver_i2c esp_driver_gptimer
WHOLE_ARCHIVE)