From 27a9cf861ee45924608d856a30bc7fbe4f6611b2 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Dec 2020 20:03:48 +1100 Subject: [PATCH 1/9] driver: Add esp32c3 drivers (except ADC/DAC) and update tests Some ESP32-C3 drivers are still pending. Based on internal commit 3ef01301fffa552d4be6d81bc9d199c223224305 --- components/driver/CMakeLists.txt | 37 +- components/driver/include/driver/spi_master.h | 9 - components/driver/ledc.c | 32 +- components/driver/spi_bus_lock.c | 1 + .../test/include/test/test_common_spi.h | 35 ++ components/driver/test/test_gpio.c | 142 ++--- components/driver/test/test_i2c.c | 38 +- components/driver/test/test_i2s.c | 2 +- components/driver/test/test_ledc.c | 535 ++++++++---------- components/driver/test/test_pwm.c | 10 +- components/driver/test/test_rmt.c | 42 +- components/driver/test/test_rs485.c | 8 +- components/driver/test/test_rtcio.c | 2 +- components/driver/test/test_sigmadelta.c | 2 +- components/driver/test/test_spi_bus_lock.c | 6 +- components/driver/test/test_spi_master.c | 53 +- components/driver/test/test_spi_param.c | 17 +- components/driver/test/test_spi_sio.c | 8 +- components/driver/test/test_spi_slave.c | 9 +- components/driver/test/test_spi_slave_hd.c | 10 +- components/driver/test/test_timer.c | 29 +- .../test/touch_sensor_test/test_esp32.c | 9 +- .../test/touch_sensor_test/test_esp32s2.c | 9 +- components/driver/touch_sensor_common.c | 14 +- components/hal/esp32/include/hal/spi_ll.h | 2 +- components/hal/esp32c3/brownout_hal.c | 4 +- .../hal/esp32c3/include/hal/clk_gate_ll.h | 4 + components/hal/esp32c3/include/hal/gpio_ll.h | 39 +- components/hal/esp32c3/include/hal/sha_ll.h | 7 +- components/hal/esp32c3/include/hal/timer_ll.h | 19 +- components/hal/include/hal/gpio_types.h | 151 ++++- components/hal/sha_hal.c | 8 + components/hal/test/test_mpu.c | 7 + .../soc/esp32c3/include/soc/clkout_channel.h | 26 + .../soc/esp32c3/include/soc/gpio_caps.h | 8 +- .../soc/esp32c3/include/soc/gpio_struct.h | 1 + .../soc/esp32s3/include/soc/gpio_caps.h | 8 +- components/soc/esp32s3/include/soc/i2s_caps.h | 2 - tools/ci/config/target-test.yml | 4 +- 39 files changed, 770 insertions(+), 579 deletions(-) create mode 100644 components/soc/esp32c3/include/soc/clkout_channel.h diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 8dd466030a..afd71f345e 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -1,9 +1,6 @@ idf_build_get_property(target IDF_TARGET) set(srcs - "adc_common.c" - "dac_common.c" - "dedic_gpio.c" "gpio.c" "i2c.c" "i2s.c" @@ -22,44 +19,62 @@ set(srcs "spi_slave.c" "spi_bus_lock.c" "timer.c" - "touch_sensor_common.c" - "twai.c" "uart.c") set(includes "include" "${target}/include") if(${target} STREQUAL "esp32") # SDMMC and MCPWM are in ESP32 only. - list(APPEND srcs "mcpwm.c" + list(APPEND srcs "adc_common.c" + "dac_common.c" + "dedic_gpio.c" + "mcpwm.c" "sdio_slave.c" "sdmmc_host.c" "sdmmc_transaction.c" + "touch_sensor_common.c" + "twai.c" "esp32/touch_sensor.c" "esp32/adc.c" "esp32/dac.c") list(APPEND includes "esp32/include") endif() -if(${target} STREQUAL "esp32s2") - list(APPEND srcs "esp32s2/rtc_tempsensor.c" +if(IDF_TARGET STREQUAL "esp32s2") + list(APPEND srcs "adc_common.c" + "dac_common.c" + "dedic_gpio.c" + "spi_slave_hd.c" + "touch_sensor_common.c" + "twai.c" + "esp32s2/rtc_tempsensor.c" "esp32s2/touch_sensor.c" "esp32s2/adc.c" "esp32s2/adc2_init_cal.c" - "spi_slave_hd.c" "esp32s2/dac.c") list(APPEND includes "esp32s2/include") endif() if(${target} STREQUAL "esp32s3") - list(APPEND srcs "spi_slave_hd.c" + list(APPEND srcs "adc_common.c" + "dac_common.c" + "dedic_gpio.c" + "spi_slave_hd.c" + "touch_sensor_common.c" + "twai.c" ) endif() +if(IDF_TARGET STREQUAL "esp32c3") + list(APPEND srcs "spi_slave_hd.c" + "esp32c3/rtc_tempsensor.c") +endif() + idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${includes} PRIV_INCLUDE_DIRS "include/driver" PRIV_REQUIRES efuse esp_pm esp_timer esp_ipc - REQUIRES esp_ringbuf freertos soc hal) + REQUIRES esp_ringbuf freertos soc hal esp_hw_support) # (REQUIRES cannot hide soc headers, since many arguments in the driver headers are chip-dependent) # uses C11 atomic feature diff --git a/components/driver/include/driver/spi_master.h b/components/driver/include/driver/spi_master.h index 06060c37af..717287a62d 100644 --- a/components/driver/include/driver/spi_master.h +++ b/components/driver/include/driver/spi_master.h @@ -22,7 +22,6 @@ /** SPI master clock is divided by 80MHz apb clock. Below defines are example frequencies, and are accurate. Be free to specify a random frequency, it will be rounded to closest frequency (to macros below if above 8MHz). * 8MHz */ -#if APB_CLK_FREQ==80*1000*1000 #define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/10) #define SPI_MASTER_FREQ_9M (APB_CLK_FREQ/9) ///< 8.89MHz #define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/8) ///< 10MHz @@ -33,14 +32,6 @@ #define SPI_MASTER_FREQ_26M (APB_CLK_FREQ/3) ///< 26.67MHz #define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/2) ///< 40MHz #define SPI_MASTER_FREQ_80M (APB_CLK_FREQ/1) ///< 80MHz -#elif APB_CLK_FREQ==40*1000*1000 -#define SPI_MASTER_FREQ_7M (APB_CLK_FREQ/6) ///< 13.33MHz -#define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/5) ///< 16MHz -#define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/4) ///< 20MHz -#define SPI_MASTER_FREQ_13M (APB_CLK_FREQ/3) ///< 26.67MHz -#define SPI_MASTER_FREQ_20M (APB_CLK_FREQ/2) ///< 40MHz -#define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/1) ///< 80MHz -#endif #ifdef __cplusplus extern "C" { diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 69eae2c1ea..b5a6bcde0c 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -19,10 +19,12 @@ #include "soc/gpio_periph.h" #include "soc/ledc_periph.h" #include "soc/rtc.h" +#include "soc/soc_caps.h" #include "hal/ledc_hal.h" #include "driver/ledc.h" #include "esp_rom_gpio.h" #include "esp_rom_sys.h" +#include "soc/clk_ctrl_os.h" static const char* LEDC_TAG = "ledc"; @@ -93,23 +95,13 @@ static IRAM_ATTR void ledc_ls_channel_update(ledc_mode_t speed_mode, ledc_channe //We know that CLK8M is about 8M, but don't know the actual value. So we need to do a calibration. static bool ledc_slow_clk_calibrate(void) { -#ifdef CONFIG_IDF_TARGET_ESP32 - //Enable CLK8M for LEDC - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - //Waiting for CLK8M to turn on - esp_rom_delay_us(DELAY_CLK8M_CLK_SWITCH); - uint32_t cal_val = rtc_clk_cal(RTC_CAL_8MD256, SLOW_CLK_CYC_CALIBRATE); - if(cal_val == 0) { - ESP_LOGE(LEDC_TAG, "CLK8M_CLK calibration failed"); - return false; + if (periph_rtc_dig_clk8m_enable()) { + s_ledc_slow_clk_8M = periph_rtc_dig_clk8m_get_freq(); + ESP_LOGD(LEDC_TAG, "Calibrate CLK8M_CLK : %d Hz", s_ledc_slow_clk_8M); + return true; } - s_ledc_slow_clk_8M = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / cal_val; - ESP_LOGD(LEDC_TAG, "Calibrate CLK8M_CLK : %d Hz", s_ledc_slow_clk_8M); - return true; -#else - ESP_LOGE(LEDC_TAG, "CLK8M source currently only supported on ESP32"); + ESP_LOGE(LEDC_TAG, "Calibrate CLK8M_CLK failed"); return false; -#endif } static uint32_t ledc_get_src_clk_freq(ledc_clk_cfg_t clk_cfg) @@ -121,7 +113,7 @@ static uint32_t ledc_get_src_clk_freq(ledc_clk_cfg_t clk_cfg) src_clk_freq = LEDC_REF_CLK_HZ; } else if (clk_cfg == LEDC_USE_RTC8M_CLK) { src_clk_freq = s_ledc_slow_clk_8M; -#ifdef CONFIG_IDF_TARGET_ESP32S2 +#if SOC_LEDC_SUPPORT_XTAL_CLOCK } else if (clk_cfg == LEDC_USE_XTAL_CLK) { src_clk_freq = rtc_clk_xtal_freq_get() * 1000000; #endif @@ -349,6 +341,9 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf) if(p_ledc_obj[speed_mode] == NULL) { p_ledc_obj[speed_mode] = (ledc_obj_t *) heap_caps_calloc(1, sizeof(ledc_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (p_ledc_obj[speed_mode] == NULL) { + return ESP_ERR_NO_MEM; + } ledc_hal_init(&(p_ledc_obj[speed_mode]->ledc_hal), speed_mode); } @@ -380,11 +375,16 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf) LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num"); LEDC_ARG_CHECK(timer_select < LEDC_TIMER_MAX, "timer_select"); + LEDC_ARG_CHECK(intr_type < LEDC_INTR_MAX, "intr_type"); + periph_module_enable(PERIPH_LEDC_MODULE); esp_err_t ret = ESP_OK; if(p_ledc_obj[speed_mode] == NULL) { p_ledc_obj[speed_mode] = (ledc_obj_t *) heap_caps_calloc(1, sizeof(ledc_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (p_ledc_obj[speed_mode] == NULL) { + return ESP_ERR_NO_MEM; + } ledc_hal_init(&(p_ledc_obj[speed_mode]->ledc_hal), speed_mode); } diff --git a/components/driver/spi_bus_lock.c b/components/driver/spi_bus_lock.c index bb4f18444c..a32f27bb5b 100644 --- a/components/driver/spi_bus_lock.c +++ b/components/driver/spi_bus_lock.c @@ -22,6 +22,7 @@ #include "stdatomic.h" #include "esp_log.h" #include +#include "esp_heap_caps.h" /* diff --git a/components/driver/test/include/test/test_common_spi.h b/components/driver/test/include/test/test_common_spi.h index f2cf965265..6b46d304a2 100644 --- a/components/driver/test/include/test/test_common_spi.h +++ b/components/driver/test/include/test/test_common_spi.h @@ -85,6 +85,41 @@ #define ESP_SPI_SLAVE_TV 0 #define WIRE_DELAY 12.5 +#elif CONFIG_IDF_TARGET_ESP32C3 + +#define TEST_SPI_HOST FSPI_HOST +#define TEST_SLAVE_HOST FSPI_HOST + +#define PIN_NUM_MISO FSPI_IOMUX_PIN_NUM_MISO +#define PIN_NUM_MOSI FSPI_IOMUX_PIN_NUM_MOSI +#define PIN_NUM_CLK FSPI_IOMUX_PIN_NUM_CLK +#define PIN_NUM_CS FSPI_IOMUX_PIN_NUM_CS + +#define PIN_NUM_WP FSPI_IOMUX_PIN_NUM_WP +#define PIN_NUM_HD FSPI_IOMUX_PIN_NUM_HD + +#define SLAVE_PIN_NUM_MISO -1 +#define SLAVE_PIN_NUM_MOSI -1 +#define SLAVE_PIN_NUM_CLK -1 +#define SLAVE_PIN_NUM_CS -1 +#define SLAVE_PIN_NUM_WP -1 +#define SLAVE_PIN_NUM_HD -1 + +//NOTE: On esp32c3, there is only 1 GPSPI controller, so master-slave test on single board should be disabled +#define SLAVE_IOMUX_PIN_MISO FSPI_IOMUX_PIN_NUM_MISO +#define SLAVE_IOMUX_PIN_MOSI FSPI_IOMUX_PIN_NUM_MOSI +#define SLAVE_IOMUX_PIN_SCLK FSPI_IOMUX_PIN_NUM_CLK +#define SLAVE_IOMUX_PIN_CS FSPI_IOMUX_PIN_NUM_CS + +#define MASTER_IOMUX_PIN_MISO FSPI_IOMUX_PIN_NUM_MISO +#define MASTER_IOMUX_PIN_MOSI FSPI_IOMUX_PIN_NUM_MOSI +#define MASTER_IOMUX_PIN_SCLK FSPI_IOMUX_PIN_NUM_CLK +#define MASTER_IOMUX_PIN_CS FSPI_IOMUX_PIN_NUM_CS + +#define GPIO_DELAY 0 +#define ESP_SPI_SLAVE_TV 0 +#define WIRE_DELAY 12.5 + #endif #define GET_DMA_CHAN(HOST) (HOST) diff --git a/components/driver/test/test_gpio.c b/components/driver/test/test_gpio.c index b8bf98934a..792421838b 100644 --- a/components/driver/test/test_gpio.c +++ b/components/driver/test/test_gpio.c @@ -16,7 +16,6 @@ #include "esp_rom_uart.h" #include "esp_rom_sys.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) #define WAKE_UP_IGNORE 1 // gpio_wakeup function development is not completed yet, set it deprecated. @@ -35,8 +34,23 @@ #define TEST_GPIO_OUTPUT_PIN 12 #define TEST_GPIO_INPUT_ONLY_PIN 46 #define TEST_GPIO_OUTPUT_MAX GPIO_NUM_46 +#elif CONFIG_IDF_TARGET_ESP32S3 +#define TEST_GPIO_EXT_OUT_IO 19 // default output GPIO +#define TEST_GPIO_EXT_IN_IO 20 // default input GPIO +#define TEST_GPIO_OUTPUT_PIN 12 +#define TEST_GPIO_INPUT_ONLY_PIN 46 +#define TEST_GPIO_OUTPUT_MAX GPIO_NUM_47 +#elif CONFIG_IDF_TARGET_ESP32C3 +#define TEST_GPIO_EXT_OUT_IO 2 // default output GPIO +#define TEST_GPIO_EXT_IN_IO 3 // default input GPIO +#define TEST_GPIO_OUTPUT_PIN 1 +#define TEST_GPIO_OUTPUT_MAX GPIO_NUM_21 #endif +// define public test io on all boards(esp32, esp32s2, esp32s3, esp32c3) +#define TEST_IO_9 GPIO_NUM_9 +#define TEST_IO_10 GPIO_NUM_10 + static volatile int disable_intr_times = 0; // use this to calculate how many times it go into interrupt static volatile int level_intr_times = 0; // use this to get how many times the level interrupt happened static volatile int edge_intr_times = 0; // use this to get how many times the edge interrupt happened @@ -62,7 +76,7 @@ static gpio_config_t init_io(gpio_num_t num) return io_conf; } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) //No runners // edge interrupt event static void gpio_isr_edge_handler(void* arg) @@ -95,7 +109,7 @@ static void gpio_isr_level_handler2(void* arg) esp_rom_printf("GPIO[%d] intr, val: %d, level_intr_times = %d\n", TEST_GPIO_EXT_OUT_IO, gpio_get_level(TEST_GPIO_EXT_OUT_IO), level_intr_times); esp_rom_printf("GPIO[%d] intr, val: %d, level_intr_times = %d\n", gpio_num, gpio_get_level(gpio_num), level_intr_times); } -#endif +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) #if !WAKE_UP_IGNORE // get result of waking up or not @@ -120,7 +134,7 @@ static void trigger_wake_up(void *arg) gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1); vTaskDelay(100 / portTICK_RATE_MS); } -#endif +#endif //!WAKE_UP_IGNORE static void prompt_to_continue(const char* str) { @@ -169,16 +183,18 @@ TEST_CASE("GPIO config parameters test", "[gpio]") io_config.pin_bit_mask = ((uint64_t)1< 1 + &I2C1, +#endif +}; + + static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, size_t size) { @@ -248,7 +266,7 @@ TEST_CASE("I2C driver memory leaking check", "[i2c]") TEST_ASSERT_INT_WITHIN(100, size, esp_get_free_heap_size()); } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) // print the reading buffer static void disp_buf(uint8_t *buf, int len) @@ -378,7 +396,7 @@ static void slave_write_buffer_test(void) TEST_CASE_MULTIPLE_DEVICES("I2C master read slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", master_read_slave_test, slave_write_buffer_test); -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32, ESP32C3) static void i2c_master_write_read_test(void) { uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH); @@ -519,8 +537,8 @@ static void i2c_slave_repeat_read(void) TEST_CASE_MULTIPLE_DEVICES("I2C repeat write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_repeat_write, i2c_slave_repeat_read); -#endif //DISABLED_FOR_TARGET(ESP32S2, ESP32) -#endif //DISABLED_FOR_TARGET(ESP32S2) +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) static volatile bool exit_flag; static bool test_read_func; @@ -629,7 +647,7 @@ TEST_CASE("I2C general API test", "[i2c]") } } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) //Init uart baud rate detection static void uart_aut_baud_det_init(int rxd_io_num) { @@ -693,4 +711,4 @@ TEST_CASE("I2C SCL freq test (local test)", "[i2c][ignore]") TEST_ESP_OK(i2c_driver_delete(i2c_num)); } -#endif +#endif // TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) diff --git a/components/driver/test/test_i2s.c b/components/driver/test/test_i2s.c index e008166591..1a0291b122 100644 --- a/components/driver/test/test_i2s.c +++ b/components/driver/test/test_i2s.c @@ -15,7 +15,7 @@ #include "math.h" #include "esp_rom_gpio.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) #define SAMPLE_RATE (36000) #define SAMPLE_BITS (16) diff --git a/components/driver/test/test_ledc.c b/components/driver/test/test_ledc.c index 9bb55e62ea..d17f1d475c 100644 --- a/components/driver/test/test_ledc.c +++ b/components/driver/test/test_ledc.c @@ -17,23 +17,88 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "unity.h" #include "soc/ledc_periph.h" #include "esp_system.h" -#include "driver/pcnt.h" #include "driver/ledc.h" #include "driver/gpio.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) - #define PULSE_IO 18 #define PCNT_INPUT_IO 4 #define PCNT_CTRL_FLOATING_IO 5 #define HIGHEST_LIMIT 10000 #define LOWEST_LIMIT -10000 -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) +#if SOC_LEDC_SUPPORT_HS_MODE +#define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE +#define SPEED_MODE_LIST {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE} +#else +#define TEST_SPEED_MODE LEDC_LOW_SPEED_MODE +#define SPEED_MODE_LIST {LEDC_LOW_SPEED_MODE} +#endif + +static ledc_channel_config_t initialize_channel_config(void) +{ + ledc_channel_config_t config; + memset(&config, 0, sizeof(ledc_channel_config_t)); + config.gpio_num = PULSE_IO; + config.speed_mode = TEST_SPEED_MODE; + config.channel = LEDC_CHANNEL_0; + config.intr_type = LEDC_INTR_DISABLE; + config.timer_sel = LEDC_TIMER_0; + config.duty = 4000; + config.hpoint = 0; + return config; +} + +static ledc_timer_config_t create_default_timer_config(void) +{ + ledc_timer_config_t ledc_time_config; + memset(&ledc_time_config, 0, sizeof(ledc_timer_config_t)); + ledc_time_config.speed_mode = TEST_SPEED_MODE; + ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT; + ledc_time_config.timer_num = LEDC_TIMER_0; + ledc_time_config.freq_hz = 2000; + ledc_time_config.clk_cfg = LEDC_USE_APB_CLK; + return ledc_time_config; +} + +static void timer_duty_set_get(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) +{ + TEST_ESP_OK(ledc_set_duty(speed_mode, channel, duty)); + TEST_ESP_OK(ledc_update_duty(speed_mode, channel)); + vTaskDelay(1000 / portTICK_RATE_MS); + TEST_ASSERT_EQUAL_INT32(ledc_get_duty(speed_mode, channel), duty); +} + +// use logic analyzer to view +static void timer_duty_test(ledc_channel_t channel, ledc_timer_bit_t timer_bit, ledc_timer_t timer, ledc_mode_t speed_mode) +{ + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); + ledc_ch_config.speed_mode = speed_mode; + ledc_ch_config.channel = channel; + ledc_ch_config.timer_sel = timer; + + ledc_timer_config_t ledc_time_config = create_default_timer_config(); + ledc_time_config.speed_mode = speed_mode; + ledc_time_config.duty_resolution = timer_bit; + ledc_time_config.timer_num = timer; + + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + + // duty ratio: (2^duty)/(2^timer_bit) + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 0); + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 1); + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 1 << 12); // 50% duty + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, (1 << 13) - 1); + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, (1 << 13) - 2); +} + +#if SOC_PCNT_SUPPORTED +#include "driver/pcnt.h" // TODO: C3 doesn't have PCNT peripheral + +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) //no runners // use PCNT to test the waveform of LEDC @@ -101,182 +166,135 @@ static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_ frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 9000, 9025, 5); } -static void timer_duty_set_get(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) +#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) + +#endif // SOC_PCNT_SUPPORTED + +TEST_CASE("LEDC channel config wrong gpio", "[ledc]") { - TEST_ESP_OK(ledc_set_duty(speed_mode, channel, duty)); - TEST_ESP_OK(ledc_update_duty(speed_mode, channel)); - vTaskDelay(1000 / portTICK_RATE_MS); - TEST_ASSERT_EQUAL_INT32(ledc_get_duty(speed_mode, channel), duty); -} - -// use logic analyzer to view -static void timer_duty_test(ledc_channel_t channel, ledc_timer_bit_t timer_bit, ledc_timer_t timer, ledc_mode_t speed_mode) -{ - ledc_channel_config_t ledc_ch_config = { - .gpio_num = PULSE_IO, - .speed_mode = speed_mode, - .channel = channel, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = timer, - .duty = 4000, - .hpoint = 0, - }; - ledc_timer_config_t ledc_time_config = { - .speed_mode = speed_mode, - .duty_resolution = timer_bit, - .timer_num = timer, - .freq_hz = 5000, - .clk_cfg = LEDC_USE_APB_CLK, - }; - TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); - TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); - - // duty ratio: (2^duty)/(2^timer_bit) - timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 0); - timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 1); - timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 1 << 12); // 50% duty - timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, (1 << 13) - 1); - timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, (1 << 13) - 2); -} - -TEST_CASE("LEDC error log channel and timer config", "[ledc][test_env=UT_T1_LEDC]") -{ -#ifdef CONFIG_IDF_TARGET_ESP32 - const ledc_mode_t test_speed_mode = LEDC_HIGH_SPEED_MODE; -#elif defined CONFIG_IDF_TARGET_ESP32S2 - const ledc_mode_t test_speed_mode = LEDC_LOW_SPEED_MODE; -#endif - //channel configuration test - ledc_channel_config_t ledc_ch_config = { - .gpio_num = PULSE_IO, - .speed_mode = test_speed_mode, - .channel = LEDC_CHANNEL_0, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = LEDC_TIMER_0, - .duty = 4000, - .hpoint = 0, - }; - - // basic right parameter test - ledc_channel_config_t temp_ch_config = ledc_ch_config; - TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); - - // with wrong GPIO using + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); ledc_ch_config.gpio_num = GPIO_NUM_MAX; TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG); - // with wrong speed - ledc_ch_config = temp_ch_config; +} + +TEST_CASE("LEDC channel config wrong speed", "[ledc]") +{ + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); ledc_ch_config.speed_mode = LEDC_SPEED_MODE_MAX; TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG); +} - // with wrong channel - ledc_ch_config = temp_ch_config; +TEST_CASE("LEDC channel config wrong channel", "[ledc]") +{ + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); ledc_ch_config.channel = LEDC_CHANNEL_MAX; TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG); +} - // with wrong interruption type - ledc_ch_config = temp_ch_config; +TEST_CASE("LEDC channel config wrong interrupt type", "[ledc]") +{ + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); ledc_ch_config.intr_type = 2; - TEST_ASSERT_FALSE((void *)ledc_channel_config(&ledc_ch_config)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_channel_config(&ledc_ch_config)); +} - // with wrong timer - ledc_ch_config = temp_ch_config; - ledc_ch_config.timer_sel = 4; - TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG); +TEST_CASE("LEDC wrong timer", "[ledc]") +{ + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); + ledc_ch_config.timer_sel = LEDC_TIMER_MAX; + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_channel_config(&ledc_ch_config)); +} - ledc_ch_config = temp_ch_config; - ledc_ch_config.duty = 12000; - TEST_ASSERT_FALSE((void *)ledc_channel_config(&ledc_ch_config)); +TEST_CASE("LEDC channel config basic parameter test", "[ledc]") +{ + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); + TEST_ASSERT_EQUAL(ESP_OK, ledc_channel_config(&ledc_ch_config)); +} - // timer configuration test - ledc_timer_config_t ledc_time_config; - ledc_time_config.speed_mode = test_speed_mode; - ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT; - ledc_time_config.timer_num = LEDC_TIMER_0; - ledc_time_config.freq_hz = 5000; - ledc_time_config.clk_cfg = LEDC_USE_APB_CLK; - - ledc_timer_config_t temp_timer_config = ledc_time_config; - TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); - - ledc_time_config.speed_mode = LEDC_SPEED_MODE_MAX; - TEST_ASSERT(ledc_timer_config(&ledc_time_config) == ESP_ERR_INVALID_ARG); - - // wrong duty_resolution - ledc_time_config = temp_timer_config; +TEST_CASE("LEDC wrong duty resolution", "[ledc]") +{ + ledc_timer_config_t ledc_time_config = create_default_timer_config(); ledc_time_config.duty_resolution = LEDC_TIMER_BIT_MAX; - TEST_ASSERT(ledc_timer_config(&ledc_time_config) == ESP_ERR_INVALID_ARG); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_timer_config(&ledc_time_config)); +} - // wrong timer - ledc_time_config = temp_timer_config; - ledc_time_config.timer_num = 4; - TEST_ASSERT(ledc_timer_config(&ledc_time_config) == ESP_ERR_INVALID_ARG); +TEST_CASE("LEDC timer config wrong timer", "[ledc]") +{ + ledc_timer_config_t ledc_time_config = create_default_timer_config(); + ledc_time_config.timer_num = LEDC_TIMER_MAX; + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_timer_config(&ledc_time_config)); +} + +TEST_CASE("LEDC timer config wrong speed mode", "[ledc]") +{ + ledc_timer_config_t ledc_time_config = create_default_timer_config(); + ledc_time_config.speed_mode = LEDC_SPEED_MODE_MAX; + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_timer_config(&ledc_time_config)); +} + +TEST_CASE("LEDC timer config basic parameter test", "[ledc]") +{ + ledc_timer_config_t ledc_time_config = create_default_timer_config(); + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); +} + +TEST_CASE("LEDC error log channel and timer config", "[ledc]") +{ + const ledc_mode_t test_speed_mode = TEST_SPEED_MODE; + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); + ledc_timer_config_t ledc_time_config = create_default_timer_config(); + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); uint32_t current_level = LEDC.channel_group[test_speed_mode].channel[LEDC_CHANNEL_0].conf0.idle_lv; TEST_ESP_OK(ledc_stop(test_speed_mode, LEDC_CHANNEL_0, !current_level)); vTaskDelay(1000 / portTICK_RATE_MS); - TEST_ASSERT_EQUAL_INT32( LEDC.channel_group[test_speed_mode].channel[LEDC_CHANNEL_0].conf0.idle_lv, !current_level); + TEST_ASSERT_EQUAL_INT32(LEDC.channel_group[test_speed_mode].channel[LEDC_CHANNEL_0].conf0.idle_lv, !current_level); } -TEST_CASE("LEDC normal channel and timer config", "[ledc][test_env=UT_T1_LEDC]") +TEST_CASE("LEDC iterate over all channel and timer configs", "[ledc]") { - ledc_channel_config_t ledc_ch_config = { - .gpio_num = PULSE_IO, - .channel = LEDC_CHANNEL_0, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = LEDC_TIMER_0, - .duty = 4000, - .hpoint = 0, - }; - ledc_channel_config_t temp_ch_config = ledc_ch_config; - - ledc_timer_config_t ledc_time_config = { - .duty_resolution = LEDC_TIMER_13_BIT, - .timer_num = LEDC_TIMER_0, - .freq_hz = 5000, - .clk_cfg = LEDC_USE_APB_CLK, - }; - ledc_timer_config_t temp_time_config = ledc_time_config; + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); + ledc_timer_config_t ledc_time_config = create_default_timer_config(); // use all kinds of speed mode, channel, timer combination to test all of possible configuration -#ifdef CONFIG_IDF_TARGET_ESP32 - ledc_mode_t speed_mode[LEDC_SPEED_MODE_MAX] = {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}; -#elif defined CONFIG_IDF_TARGET_ESP32S2 - ledc_mode_t speed_mode[LEDC_SPEED_MODE_MAX] = {LEDC_LOW_SPEED_MODE}; -#endif - ledc_channel_t channel_type[8] = {LEDC_CHANNEL_0, LEDC_CHANNEL_1, LEDC_CHANNEL_2, LEDC_CHANNEL_3, LEDC_CHANNEL_4, LEDC_CHANNEL_5, LEDC_CHANNEL_6, LEDC_CHANNEL_7}; + ledc_mode_t speed_mode[LEDC_SPEED_MODE_MAX] = SPEED_MODE_LIST; + ledc_channel_t channels[8] = {LEDC_CHANNEL_0, LEDC_CHANNEL_1, LEDC_CHANNEL_2, LEDC_CHANNEL_3, LEDC_CHANNEL_4, LEDC_CHANNEL_5}; ledc_timer_t timer_select[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3}; for (int i = 0; i < LEDC_SPEED_MODE_MAX; i++) { ledc_ch_config.speed_mode = speed_mode[i]; ledc_time_config.speed_mode = speed_mode[i]; for (int j = 0; j < 8; j++) { - ledc_ch_config.channel = channel_type[j]; + ledc_ch_config.channel = channels[j]; for (int k = 0; k < 4; k++) { ledc_ch_config.timer_sel = timer_select[k]; ledc_time_config.timer_num = timer_select[k]; TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); - ledc_ch_config = temp_ch_config; - ledc_time_config = temp_time_config; } } } } -// set it ignore: need to debug -TEST_CASE("LEDC set and get frequency", "[ledc][test_env=UT_T1_LEDC][timeout=60][ignore]") +TEST_CASE("LEDC memory leak test", "[ledc]") { -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) - timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_0, LEDC_HIGH_SPEED_MODE); - timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_1, LEDC_HIGH_SPEED_MODE); - timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_2, LEDC_HIGH_SPEED_MODE); - timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_3, LEDC_HIGH_SPEED_MODE); -#endif - 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); + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); + + ledc_timer_config_t ledc_time_config = create_default_timer_config(); + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + + uint32_t size = esp_get_free_heap_size(); + uint32_t i; + + // install and uninstall for 1000 times to test whether memory leaking exists + for (i = 0; i <= 1000; i++) { + TEST_ESP_OK(ledc_fade_func_install(0)); + ledc_fade_func_uninstall(); + } + TEST_ASSERT_INT32_WITHIN(100, size, esp_get_free_heap_size()); + TEST_ESP_OK(ledc_stop(ledc_time_config.speed_mode, LEDC_CHANNEL_0, 0)); } // the duty need to be detected by waveform given by the logic analyzer @@ -284,11 +302,7 @@ TEST_CASE("LEDC set and get frequency", "[ledc][test_env=UT_T1_LEDC][timeout=60] TEST_CASE("LEDC set and get dut(with logic analyzer)", "[ledc][ignore]") { ledc_timer_t timer_list[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3}; -#ifdef CONFIG_IDF_TARGET_ESP32 - ledc_mode_t speed_mode_list[LEDC_SPEED_MODE_MAX] = {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}; -#elif defined CONFIG_IDF_TARGET_ESP32S2 - ledc_mode_t speed_mode_list[LEDC_SPEED_MODE_MAX] = {LEDC_LOW_SPEED_MODE}; -#endif + ledc_mode_t speed_mode_list[LEDC_SPEED_MODE_MAX] = SPEED_MODE_LIST; for(int i=0; i #include "esp_system.h" -#include "driver/pcnt.h" #include "unity.h" #include "test_utils.h" #include "freertos/FreeRTOS.h" @@ -25,10 +24,10 @@ #include "soc/rtc.h" #include "soc/soc_caps.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) - #if SOC_MCPWM_SUPPORTED +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) #include "soc/mcpwm_periph.h" +#include "driver/pcnt.h" #include "driver/mcpwm.h" @@ -788,6 +787,5 @@ TEST_CASE("MCPWM unit1, timer2 capture test", "[mcpwm][test_env=UT_T1_MCPWM][tim capture_test(MCPWM_UNIT_1, MCPWM_TIMER_2, MCPWM_POS_EDGE); } -#endif - -#endif +#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) +#endif // SOC_MCPWM_SUPPORTED diff --git a/components/driver/test/test_rmt.c b/components/driver/test/test_rmt.c index 1cc4600ef4..a9fad4dfb8 100644 --- a/components/driver/test/test_rmt.c +++ b/components/driver/test/test_rmt.c @@ -1,5 +1,4 @@ // RMT driver unit test is based on extended NEC protocol -// Please don't use channel number: SOC_RMT_CHANNELS_NUM - 1 #include #include #include "sdkconfig.h" @@ -16,7 +15,7 @@ #define RMT_TX_CHANNEL_ENCODING_END (SOC_RMT_TX_CHANNELS_NUM-1) // CI ONLY: Don't connect any other signals to this GPIO -#define RMT_DATA_IO (12) // bind signal RMT_SIG_OUT0_IDX and RMT_SIG_IN0_IDX on the same GPIO +#define RMT_DATA_IO (4) // bind signal RMT_SIG_OUT0_IDX and RMT_SIG_IN0_IDX on the same GPIO #define RMT_TESTBENCH_FLAGS_ALWAYS_ON (1<<0) #define RMT_TESTBENCH_FLAGS_CARRIER_ON (1<<1) @@ -103,7 +102,7 @@ static void rmt_clean_testbench(int tx_channel, int rx_channel) } } -TEST_CASE("RMT wrong configuration", "[rmt][error]") +TEST_CASE("RMT wrong configuration", "[rmt]") { rmt_config_t correct_config = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, 0); rmt_config_t wrong_config = correct_config; @@ -179,25 +178,30 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]") TEST_CASE("RMT multiple channels", "[rmt]") { - rmt_config_t tx_cfg1 = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, 0); + rmt_config_t tx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, 0); + for (int i = 0; i < SOC_RMT_TX_CHANNELS_NUM; i++) { + tx_cfg.channel = i; + TEST_ESP_OK(rmt_config(&tx_cfg)); + TEST_ESP_OK(rmt_driver_install(tx_cfg.channel, 0, 0)); + } - TEST_ESP_OK(rmt_config(&tx_cfg1)); - TEST_ESP_OK(rmt_driver_install(tx_cfg1.channel, 0, 0)); + for (int i = 0; i < SOC_RMT_TX_CHANNELS_NUM; i++) { + TEST_ESP_OK(rmt_driver_uninstall(i)); + } - rmt_config_t tx_cfg2 = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, 1); - TEST_ESP_OK(rmt_config(&tx_cfg2)); - TEST_ESP_OK(rmt_driver_install(tx_cfg2.channel, 0, 0)); + rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, RMT_RX_CHANNEL_ENCODING_START); + for (int i = RMT_RX_CHANNEL_ENCODING_START; i < SOC_RMT_CHANNELS_NUM; i++) { + rx_cfg.channel = i; + TEST_ESP_OK(rmt_config(&rx_cfg)); + TEST_ESP_OK(rmt_driver_install(rx_cfg.channel, 0, 0)); + } - rmt_config_t tx_cfg3 = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, 2); - TEST_ESP_OK(rmt_config(&tx_cfg3)); - TEST_ESP_OK(rmt_driver_install(tx_cfg3.channel, 0, 0)); - - TEST_ESP_OK(rmt_driver_uninstall(2)); - TEST_ESP_OK(rmt_driver_uninstall(1)); - TEST_ESP_OK(rmt_driver_uninstall(0)); + for (int i = RMT_RX_CHANNEL_ENCODING_START; i < SOC_RMT_CHANNELS_NUM; i++) { + TEST_ESP_OK(rmt_driver_uninstall(i)); + } } -TEST_CASE("RMT install/uninstall test", "[rmt][pressure]") +TEST_CASE("RMT install/uninstall test", "[rmt]") { rmt_config_t tx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, RMT_TX_CHANNEL_ENCODING_END); TEST_ESP_OK(rmt_config(&tx_cfg)); @@ -449,8 +453,8 @@ TEST_CASE("RMT TX simultaneously", "[rmt]") frames[i].level1 = 0; frames[i].duration1 = 0; - rmt_config_t tx_config0 = RMT_DEFAULT_CONFIG_TX(12, channel0); - rmt_config_t tx_config1 = RMT_DEFAULT_CONFIG_TX(13, channel1); + rmt_config_t tx_config0 = RMT_DEFAULT_CONFIG_TX(4, channel0); + rmt_config_t tx_config1 = RMT_DEFAULT_CONFIG_TX(5, channel1); TEST_ESP_OK(rmt_config(&tx_config0)); TEST_ESP_OK(rmt_config(&tx_config1)); diff --git a/components/driver/test/test_rs485.c b/components/driver/test/test_rs485.c index cc42fe4401..9a503309ab 100644 --- a/components/driver/test/test_rs485.c +++ b/components/driver/test/test_rs485.c @@ -9,8 +9,6 @@ #include "esp_log.h" #include "esp_system.h" // for uint32_t esp_random() -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) - #define UART_TAG "Uart" #define UART_NUM1 (UART_NUM_1) #define BUF_SIZE (100) @@ -31,7 +29,7 @@ // Wait timeout for uart driver #define PACKET_READ_TICS (1000 / portTICK_RATE_MS) -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) //No runners // The table for fast CRC16 calculation @@ -289,6 +287,4 @@ static void rs485_master(void) */ TEST_CASE_MULTIPLE_DEVICES("RS485 half duplex uart multiple devices test.", "[driver_RS485][test_env=UT_T2_RS485]", rs485_master, rs485_slave); -#endif - -#endif +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) diff --git a/components/driver/test/test_rtcio.c b/components/driver/test/test_rtcio.c index 02d02514ef..2e4fdbab3c 100644 --- a/components/driver/test/test_rtcio.c +++ b/components/driver/test/test_rtcio.c @@ -16,7 +16,7 @@ #include "esp_log.h" #include "soc/rtc_io_periph.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) #define RTCIO_CHECK(condition) TEST_ASSERT_MESSAGE((condition == ESP_OK), "ret is not ESP_OK") #define RTCIO_VERIFY(condition, msg) TEST_ASSERT_MESSAGE((condition), msg) diff --git a/components/driver/test/test_sigmadelta.c b/components/driver/test/test_sigmadelta.c index d0a1856ac3..d702511ba9 100644 --- a/components/driver/test/test_sigmadelta.c +++ b/components/driver/test/test_sigmadelta.c @@ -5,7 +5,7 @@ #include "soc/soc_caps.h" #include "driver/sigmadelta.h" -TEST_CASE("Sigma-Delta config test", "[sigma_delta]") +TEST_CASE("SigmaDelta config test", "[sigma_delta]") { sigmadelta_config_t sigmadelta_cfg = { .sigmadelta_prescale = 80, diff --git a/components/driver/test/test_spi_bus_lock.c b/components/driver/test/test_spi_bus_lock.c index 7a165682c0..469b43bce6 100644 --- a/components/driver/test/test_spi_bus_lock.c +++ b/components/driver/test/test_spi_bus_lock.c @@ -7,7 +7,7 @@ #include "test/test_common_spi.h" #include "unity.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) #if CONFIG_IDF_TARGET_ESP32 // The VSPI pins on UT_T1_ESP_FLASH are connected to a external flash @@ -345,6 +345,6 @@ TEST_CASE("spi master can be used on SPI1", "[spi]") //TODO: add a case when a non-polling transaction happened in the bus-acquiring time and then release the bus then queue a new trans -#endif +#endif //!CONFIG_ESP32_SPIRAM_SUPPORT -#endif +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) diff --git a/components/driver/test/test_spi_master.c b/components/driver/test/test_spi_master.c index 1846097676..ffca8d2522 100644 --- a/components/driver/test/test_spi_master.c +++ b/components/driver/test/test_spi_master.c @@ -264,6 +264,7 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi]") { TEST_ASSERT(success); } +#if !DISABLED_FOR_TARGETS(ESP32C3) //There is no input-only pin on esp32c3, so this test could be ignored. static esp_err_t test_master_pins(int mosi, int miso, int sclk, int cs) { esp_err_t ret; @@ -322,6 +323,9 @@ TEST_CASE("spi placed on input-only pins", "[spi]") TEST_ESP_OK(test_slave_pins(PIN_NUM_MOSI, PIN_NUM_MISO, PIN_NUM_CLK, INPUT_ONLY_PIN)); } +//There is no input-only pin on esp32c3, so this test could be ignored. +#endif //#if !DISABLED_FOR_TARGETS(ESP32C3) + TEST_CASE("spi bus setting with different pin configs", "[spi]") { spi_bus_config_t cfg; @@ -366,6 +370,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]") TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); +#if !DISABLED_FOR_TARGETS(ESP32C3) //There is no input-only pin on esp32c3, so this test could be ignored. ESP_LOGI(TAG, "test master 5 output pins and MOSI on input-only pin..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD | SPICOMMON_BUSFLAG_GPIO_PINS; cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = INPUT_ONLY_PIN, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin, @@ -394,6 +399,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]") .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); +#endif ESP_LOGI(TAG, "check native flag for 6 output pins..."); flags_expected = SPICOMMON_BUSFLAG_IOMUX_PINS; @@ -411,6 +417,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]") TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); +#if !DISABLED_FOR_TARGETS(ESP32C3) //There is no input-only pin on esp32c3, so this test could be ignored. ESP_LOGI(TAG, "check dual flag for master 5 output pins and MISO/MOSI on input-only pin..."); flags_expected = SPICOMMON_BUSFLAG_DUAL | SPICOMMON_BUSFLAG_GPIO_PINS; cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = INPUT_ONLY_PIN, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin, @@ -432,6 +439,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]") .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); +#endif ESP_LOGI(TAG, "check sclk flag..."); flags_expected = SPICOMMON_BUSFLAG_SCLK; @@ -552,20 +560,23 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]") TEST_ASSERT(esp_ptr_in_dram(data_malloc)); #endif TEST_ASSERT(data_malloc != NULL); + TEST_ASSERT(esp_ptr_in_dram(data_dram)); + TEST_ASSERT(esp_ptr_in_drom(data_drom)); + ESP_LOGI(TAG, "dram: %p", data_dram); + ESP_LOGI(TAG, "drom: %p, malloc: %p", data_drom, data_malloc); - //refer to soc_memory_layout.c +#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE uint32_t* data_iram = (uint32_t*)heap_caps_malloc(324, MALLOC_CAP_EXEC); TEST_ASSERT(data_iram != NULL); - - ESP_LOGI(TAG, "iram: %p, dram: %p", data_iram, data_dram); - ESP_LOGI(TAG, "drom: %p, malloc: %p", data_drom, data_malloc); - TEST_ASSERT(esp_ptr_in_dram(data_dram)); TEST_ASSERT(esp_ptr_executable(data_iram) || esp_ptr_in_iram(data_iram) || esp_ptr_in_diram_iram(data_iram)); - TEST_ASSERT(esp_ptr_in_drom(data_drom)); + ESP_LOGI(TAG, "iram: %p", data_iram); +#endif srand(52); for (int i = 0; i < 320/4; i++) { +#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE data_iram[i] = rand(); +#endif data_dram[i] = rand(); data_malloc[i] = rand(); } @@ -588,10 +599,9 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]") #define TEST_REGION_SIZE 5 static spi_transaction_t trans[TEST_REGION_SIZE]; int x; - - memset(trans, 0, sizeof(trans)); +#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE trans[0].length = 320*8, trans[0].tx_buffer = data_iram; trans[0].rx_buffer = data_malloc+1; @@ -601,12 +611,13 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]") trans[1].rx_buffer = data_iram; trans[2].length = 320*8, - trans[2].tx_buffer = data_malloc+2; - trans[2].rx_buffer = data_dram; + trans[2].tx_buffer = data_drom; + trans[2].rx_buffer = data_iram; +#endif trans[3].length = 320*8, - trans[3].tx_buffer = data_drom; - trans[3].rx_buffer = data_iram; + trans[3].tx_buffer = data_malloc+2; + trans[3].rx_buffer = data_dram; trans[4].length = 4*8, trans[4].flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA; @@ -616,7 +627,11 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]") *ptr = 0xbc124960; //Queue all transactions. +#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE for (x=0; x (b)? (b): (a)) @@ -613,7 +616,7 @@ TEST_CASE("Slave receive correct data", "[spi]") } } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) //These tests are ESP32 only due to lack of runners /******************************************************************************** * Test By Master & Slave (2 boards) @@ -1163,4 +1166,6 @@ spitest_param_set_t mode_conf[] = { }; TEST_SPI_MASTER_SLAVE(MODE, mode_conf, "") -#endif +#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) + +#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3) diff --git a/components/driver/test/test_spi_sio.c b/components/driver/test/test_spi_sio.c index 92aef5b4f1..cdb95a6b3c 100644 --- a/components/driver/test/test_spi_sio.c +++ b/components/driver/test/test_spi_sio.c @@ -24,7 +24,7 @@ #include "hal/spi_ll.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) /******************************************************************************** * Test SIO @@ -102,7 +102,7 @@ TEST_CASE("local test sio", "[spi]") master_free_device_bus(spi); } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3) //These tests are ESP32 only due to lack of runners /******************************************************************************** * Test SIO Master & Slave @@ -220,6 +220,6 @@ void test_sio_slave(void) } TEST_CASE_MULTIPLE_DEVICES("sio mode", "[spi][test_env=Example_SPI_Multi_device]", test_sio_master, test_sio_slave); -#endif +#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3) -#endif +#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) diff --git a/components/driver/test/test_spi_slave.c b/components/driver/test/test_spi_slave.c index eb2d0b29e4..ba1975f267 100644 --- a/components/driver/test/test_spi_slave.c +++ b/components/driver/test/test_spi_slave.c @@ -3,15 +3,18 @@ */ #include +#include "sdkconfig.h" #include "unity.h" +#include "test/test_common_spi.h" #include "driver/spi_master.h" #include "driver/spi_slave.h" #include "driver/gpio.h" #include "esp_log.h" -#include "sdkconfig.h" -#include "test/test_common_spi.h" #include "esp_rom_gpio.h" +//There is only one GPSPI controller, so single-board test is disabled. +#if !DISABLED_FOR_TARGETS(ESP32C3) + #ifndef CONFIG_SPIRAM //This test should be removed once the timing test is merged. @@ -142,3 +145,5 @@ TEST_CASE("test slave send unaligned","[spi]") } #endif // !CONFIG_SPIRAM + +#endif // !TEMPORARY_DISABLED_FOR_TARGETS diff --git a/components/driver/test/test_spi_slave_hd.c b/components/driver/test/test_spi_slave_hd.c index c7b6b07991..63941a2a92 100644 --- a/components/driver/test/test_spi_slave_hd.c +++ b/components/driver/test/test_spi_slave_hd.c @@ -6,11 +6,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" +#include "unity.h" #include "soc/spi_periph.h" #include "driver/spi_master.h" #include "esp_serial_slave_link/essl_spi.h" +#if !DISABLED_FOR_TARGETS(ESP32C3) +//There is only one GPSPI controller on ESP32C3, so single-board test is disabled. + #if SOC_SPI_SUPPORT_SLAVE_HD_VER2 #include "driver/spi_slave_hd.h" #include "esp_rom_gpio.h" @@ -490,7 +494,7 @@ TEST_SPI_HD(HD, hd_conf); * * This test checks that the previous trans will not influence the data slave prepared for the next transaction. */ -TEST_CASE("test spi slave hd continuous mode, master too long", "[spi][spi_slv_hd]") +TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]") { spi_device_handle_t spi; spitest_param_set_t *cfg = &hd_conf[0]; @@ -583,4 +587,6 @@ TEST_CASE("test spi slave hd continuous mode, master too long", "[spi][spi_slv_h master_free_device_bus(spi); } -#endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2 +#endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2 + +#endif //#if !DISABLED_FOR_TARGETS(ESP32C3) diff --git a/components/driver/test/test_timer.c b/components/driver/test/test_timer.c index 867f7bd2eb..e52569a05b 100644 --- a/components/driver/test/test_timer.c +++ b/components/driver/test/test_timer.c @@ -30,11 +30,16 @@ typedef struct { #define TIMER_INFO_INIT(TG, TID) {.timer_group = (TG), .timer_idx = (TID),} -static timer_info_t timer_info[4] = { +static timer_info_t timer_info[] = { +#if !CONFIG_IDF_TARGET_ESP32C3 TIMER_INFO_INIT(TIMER_GROUP_0, TIMER_0), TIMER_INFO_INIT(TIMER_GROUP_0, TIMER_1), TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_0), TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_1), +#else + TIMER_INFO_INIT(TIMER_GROUP_0, TIMER_0), + TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_0), +#endif }; static intr_handle_t timer_isr_handles[SOC_TIMER_GROUP_TOTAL_TIMERS]; @@ -236,6 +241,7 @@ static void timer_intr_enable_and_start(int timer_group, int timer_idx, double a TEST_ESP_OK(timer_pause(timer_group, timer_idx)); TEST_ESP_OK(timer_set_counter_value(timer_group, timer_idx, 0x0)); TEST_ESP_OK(timer_set_alarm_value(timer_group, timer_idx, alarm_time * TIMER_SCALE)); + TEST_ESP_OK(timer_set_alarm(timer_group, timer_idx, TIMER_ALARM_EN)); TEST_ESP_OK(timer_enable_intr(timer_group, timer_idx)); TEST_ESP_OK(timer_start(timer_group, timer_idx)); } @@ -507,8 +513,8 @@ TEST_CASE("Timer divider", "[hw_timer]") .intr_type = TIMER_INTR_LEVEL }; uint64_t set_timer_val = 0; - uint64_t time_val[4]; - uint64_t comp_time_val[4]; + uint64_t time_val[TIMER_GROUP_MAX * TIMER_MAX]; + uint64_t comp_time_val[TIMER_GROUP_MAX * TIMER_MAX]; all_timer_init(&config, true); all_timer_pause(); @@ -526,7 +532,7 @@ TEST_CASE("Timer divider", "[hw_timer]") all_timer_start(); vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time all_timer_get_counter_value(set_timer_val, false, comp_time_val); - for (i = 0; i < 4; i++) { + for (i = 0; i < TIMER_GROUP_MAX * TIMER_MAX; i++) { TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); TEST_ASSERT_INT_WITHIN(10000, 10000000, comp_time_val[i]); } @@ -538,7 +544,7 @@ TEST_CASE("Timer divider", "[hw_timer]") all_timer_start(); vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time all_timer_get_counter_value(set_timer_val, false, comp_time_val); - for (i = 0; i < 4; i++) { + for (i = 0; i < TIMER_GROUP_MAX * TIMER_MAX; i++) { TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); TEST_ASSERT_INT_WITHIN(3126, 312500, comp_time_val[i]); } @@ -550,7 +556,7 @@ TEST_CASE("Timer divider", "[hw_timer]") all_timer_start(); vTaskDelay(1000 / portTICK_PERIOD_MS); all_timer_get_counter_value(set_timer_val, false, comp_time_val); - for (i = 0; i < 4; i++) { + for (i = 0; i < TIMER_GROUP_MAX * TIMER_MAX; i++) { TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); TEST_ASSERT_INT_WITHIN(40000, 40000000, comp_time_val[i]); } @@ -561,7 +567,7 @@ TEST_CASE("Timer divider", "[hw_timer]") all_timer_start(); vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time all_timer_get_counter_value(set_timer_val, false, comp_time_val); - for (i = 0; i < 4; i++) { + for (i = 0; i < TIMER_GROUP_MAX * TIMER_MAX; i++) { TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); TEST_ASSERT_INT_WITHIN(2, 1220, comp_time_val[i]); } @@ -604,8 +610,8 @@ TEST_CASE("Timer enable alarm", "[hw_timer]") // disable alarm of tg0_timer1 alarm_flag = false; - TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_DIS)); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 1.2); + TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_DIS)); vTaskDelay(2000 / portTICK_PERIOD_MS); TEST_ASSERT_EQUAL(false, alarm_flag); @@ -618,8 +624,8 @@ TEST_CASE("Timer enable alarm", "[hw_timer]") // disable alarm of tg1_timer0 alarm_flag = false; - TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_DIS)); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.2); + TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_DIS)); vTaskDelay(2000 / portTICK_PERIOD_MS); TEST_ASSERT_EQUAL(false, alarm_flag); all_timer_isr_unreg(); @@ -682,8 +688,13 @@ TEST_CASE("Timer auto reload", "[hw_timer]") // test disable auto_reload timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 1.14); timer_isr_check(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_DIS, 1.14 * TIMER_SCALE); + timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.14); + timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_DIS, 1.14 * TIMER_SCALE); //test enable auto_reload + TEST_ESP_OK(timer_set_auto_reload(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_EN)); + timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 1.4); + timer_isr_check(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_EN, 0); TEST_ESP_OK(timer_set_auto_reload(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN)); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.4); timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN, 0); diff --git a/components/driver/test/touch_sensor_test/test_esp32.c b/components/driver/test/touch_sensor_test/test_esp32.c index f68b5a4966..0a1d4e2796 100644 --- a/components/driver/test/touch_sensor_test/test_esp32.c +++ b/components/driver/test/touch_sensor_test/test_esp32.c @@ -13,8 +13,11 @@ // limitations under the License. /* - Tests for the touch sensor device driver + Tests for the touch sensor device driver for ESP32 */ +#include "sdkconfig.h" +#if CONFIG_IDF_TARGET_ESP32 + #include "esp_system.h" #include "driver/touch_pad.h" #include "unity.h" @@ -34,8 +37,6 @@ #include "soc/rtc_io_struct.h" #include "esp_rom_sys.h" -#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2, ESP32S3) // This testcase for ESP32 - static const char *TAG = "test_touch"; #define TOUCH_READ_INVALID_VAL (0) @@ -374,4 +375,4 @@ TEST_CASE("Touch Sensor interrupt test", "[touch]") TEST_ESP_OK( test_touch_interrupt() ); } -#endif // !DISABLED_FOR_TARGETS(ESP8266, ESP32) +#endif // CONFIG_IDF_TARGET_ESP32 diff --git a/components/driver/test/touch_sensor_test/test_esp32s2.c b/components/driver/test/touch_sensor_test/test_esp32s2.c index ca02e5bd4f..787360bf76 100644 --- a/components/driver/test/touch_sensor_test/test_esp32s2.c +++ b/components/driver/test/touch_sensor_test/test_esp32s2.c @@ -13,8 +13,11 @@ // limitations under the License. /* - Tests for the touch sensor device driver + Tests for the touch sensor device driver for ESP32-S2 only */ +#include "sdkconfig.h" +#if CONFIG_IDF_TARGET_ESP32S2 + #include #include "esp_system.h" #include "driver/touch_pad.h" @@ -38,8 +41,6 @@ #include "driver/rtc_io.h" #include "esp_rom_sys.h" -#if !DISABLED_FOR_TARGETS(ESP8266, ESP32, ESP32S3) // This testcase for ESP32S2 - static const char *TAG = "test_touch"; #define PLATFORM_SELECT (1) //0: pxp; 1: chip @@ -2122,4 +2123,4 @@ void test_touch_slope_debug(int pad_num) TEST_ESP_OK( touch_pad_deinit() ); } -#endif // !DISABLED_FOR_TARGETS(ESP8266, ESP32) +#endif // CONFIG_IDF_TARGET_ESP32S2 diff --git a/components/driver/touch_sensor_common.c b/components/driver/touch_sensor_common.c index a59ad928c8..9504fcfd58 100644 --- a/components/driver/touch_sensor_common.c +++ b/components/driver/touch_sensor_common.c @@ -20,7 +20,6 @@ #include "sys/lock.h" #include "soc/soc_pins.h" #include "freertos/FreeRTOS.h" -#include "freertos/xtensa_api.h" #include "freertos/semphr.h" #include "freertos/timers.h" #include "esp_intr_alloc.h" @@ -28,7 +27,6 @@ #include "driver/touch_pad.h" #include "driver/rtc_cntl.h" #include "driver/gpio.h" - #include "hal/touch_sensor_types.h" #include "hal/touch_sensor_hal.h" @@ -43,12 +41,12 @@ static const char *TOUCH_TAG = "TOUCH_SENSOR"; #define TOUCH_CHANNEL_CHECK(channel) do { \ TOUCH_CHECK(channel < SOC_TOUCH_SENSOR_NUM && channel >= 0, "Touch channel error", ESP_ERR_INVALID_ARG); \ } while (0); -#elif defined CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#else // !CONFIG_IDF_TARGET_ESP32 #define TOUCH_CHANNEL_CHECK(channel) do { \ TOUCH_CHECK(channel < SOC_TOUCH_SENSOR_NUM && channel >= 0, "Touch channel error", ESP_ERR_INVALID_ARG); \ TOUCH_CHECK(channel != SOC_TOUCH_DENOISE_CHANNEL, "TOUCH0 is internal denoise channel", ESP_ERR_INVALID_ARG); \ } while (0); -#endif +#endif // CONFIG_IDF_TARGET_ESP32 #define TOUCH_GET_IO_NUM(channel) (touch_sensor_channel_io_map[channel]) @@ -195,7 +193,7 @@ esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold) TOUCH_EXIT_CRITICAL(); return ESP_OK; } -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#else // !CONFIG_IDF_TARGET_ESP32 esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold) { TOUCH_CHANNEL_CHECK(touch_num); @@ -206,7 +204,7 @@ esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold) TOUCH_EXIT_CRITICAL(); return ESP_OK; } -#endif +#endif // CONFIG_IDF_TARGET_ESP32 #ifdef CONFIG_IDF_TARGET_ESP32 esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold) @@ -215,7 +213,7 @@ esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold) touch_hal_get_threshold(touch_num, threshold); return ESP_OK; } -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#else // !CONFIG_IDF_TARGET_ESP32 esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold) { TOUCH_CHANNEL_CHECK(touch_num); @@ -224,7 +222,7 @@ esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold) touch_hal_get_threshold(touch_num, threshold); return ESP_OK; } -#endif +#endif // CONFIG_IDF_TARGET_ESP32 esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num) { diff --git a/components/hal/esp32/include/hal/spi_ll.h b/components/hal/esp32/include/hal/spi_ll.h index a0680a8b36..a2973e3f1b 100644 --- a/components/hal/esp32/include/hal/spi_ll.h +++ b/components/hal/esp32/include/hal/spi_ll.h @@ -154,7 +154,7 @@ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) } /** - * Reset SPI CPU FIFO + * Reset SPI CPU TX FIFO * * @param hw Beginning address of the peripheral registers. */ diff --git a/components/hal/esp32c3/brownout_hal.c b/components/hal/esp32c3/brownout_hal.c index 95d77a3974..1fc22420b1 100644 --- a/components/hal/esp32c3/brownout_hal.c +++ b/components/hal/esp32c3/brownout_hal.c @@ -16,8 +16,8 @@ #include "hal/brownout_hal.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" -#include "i2c_rtc_clk.h" -#include "i2c_brownout.h" +#include "regi2c_ctrl.h" +#include "regi2c_brownout.h" void brownout_hal_config(const brownout_hal_config_t *cfg) diff --git a/components/hal/esp32c3/include/hal/clk_gate_ll.h b/components/hal/esp32c3/include/hal/clk_gate_ll.h index db3ce2c4b1..9a4cace824 100644 --- a/components/hal/esp32c3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c3/include/hal/clk_gate_ll.h @@ -28,6 +28,8 @@ extern "C" { static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) { switch (periph) { + case PERIPH_SARADC_MODULE: + return SYSTEM_APB_SARADC_CLK_EN; case PERIPH_RMT_MODULE: return SYSTEM_RMT_CLK_EN; case PERIPH_LEDC_MODULE: @@ -89,6 +91,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en (void)enable; // unused switch (periph) { + case PERIPH_SARADC_MODULE: + return SYSTEM_APB_SARADC_RST; case PERIPH_RMT_MODULE: return SYSTEM_RMT_RST; case PERIPH_LEDC_MODULE: diff --git a/components/hal/esp32c3/include/hal/gpio_ll.h b/components/hal/esp32c3/include/hal/gpio_ll.h index 38c81eca1c..4fd25d7c27 100644 --- a/components/hal/esp32c3/include/hal/gpio_ll.h +++ b/components/hal/esp32c3/include/hal/gpio_ll.h @@ -18,7 +18,7 @@ * See readme.md in soc/include/hal/readme.md ******************************************************************************/ -// The LL layer for ESP32-S3 GPIO register operations +// The LL layer for ESP32-C3 GPIO register operations #pragma once @@ -34,6 +34,8 @@ extern "C" { // Get GPIO hardware instance with giving gpio num #define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL) +#define GPIO_LL_PRO_CPU_INTR_ENA (BIT(0)) +#define GPIO_LL_PRO_CPU_NMI_INTR_ENA (BIT(1)) /** * @brief Enable pull-up on GPIO. * @@ -133,7 +135,7 @@ static inline void gpio_ll_clear_intr_status(gpio_dev_t *hw, uint32_t mask) */ static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask) { - // hw->status1_w1tc.intr_st = mask; + // Not supported on C3 } /** @@ -146,7 +148,7 @@ static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask) static inline void gpio_ll_intr_enable_on_core(gpio_dev_t *hw, uint32_t core_id, gpio_num_t gpio_num) { if (core_id == 0) { - GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr + GPIO.pin[gpio_num].int_ena = GPIO_LL_PRO_CPU_INTR_ENA; //enable pro cpu intr } else { // GPIO.pin[gpio_num].int_ena = GPIO_APP_CPU_INTR_ENA; //enable pro cpu intr } @@ -193,12 +195,7 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, gpio_num_t gpio_num) */ static inline void gpio_ll_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num) { - if (gpio_num < 32) { - hw->enable_w1tc.enable_w1tc = (0x1 << gpio_num); - } else { - // hw->enable1_w1tc.data = (0x1 << (gpio_num - 32)); - } - + hw->enable_w1tc.enable_w1tc = (0x1 << gpio_num); // Ensure no other output signal is routed via GPIO matrix to this pin REG_WRITE(GPIO_FUNC0_OUT_SEL_CFG_REG + (gpio_num * 4), SIG_GPIO_OUT_IDX); @@ -212,11 +209,7 @@ static inline void gpio_ll_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num) */ static inline void gpio_ll_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num) { - if (gpio_num < 32) { - hw->enable_w1ts.enable_w1ts = (0x1 << gpio_num); - } else { - // hw->enable1_w1ts.data = (0x1 << (gpio_num - 32)); - } + hw->enable_w1ts.enable_w1ts = (0x1 << gpio_num); } /** @@ -251,17 +244,9 @@ static inline void gpio_ll_od_enable(gpio_dev_t *hw, gpio_num_t gpio_num) static inline void gpio_ll_set_level(gpio_dev_t *hw, gpio_num_t gpio_num, uint32_t level) { if (level) { - if (gpio_num < 32) { - hw->out_w1ts.out_w1ts = (1 << gpio_num); - } else { - // hw->out1_w1ts.data = (1 << (gpio_num - 32)); - } + hw->out_w1ts.out_w1ts = (1 << gpio_num); } else { - if (gpio_num < 32) { - hw->out_w1tc.out_w1tc = (1 << gpio_num); - } else { - // hw->out1_w1tc.data = (1 << (gpio_num - 32)); - } + hw->out_w1tc.out_w1tc = (1 << gpio_num); } } @@ -279,11 +264,7 @@ static inline void gpio_ll_set_level(gpio_dev_t *hw, gpio_num_t gpio_num, uint32 */ static inline int gpio_ll_get_level(gpio_dev_t *hw, gpio_num_t gpio_num) { - if (gpio_num < 32) { - return (hw->in.data >> gpio_num) & 0x1; - } else { - return 0; // Less than 32 GPIOs in ESP32-C3 - } + return (hw->in.data >> gpio_num) & 0x1; } /** diff --git a/components/hal/esp32c3/include/hal/sha_ll.h b/components/hal/esp32c3/include/hal/sha_ll.h index 4cd0ad9134..a7bc493252 100644 --- a/components/hal/esp32c3/include/hal/sha_ll.h +++ b/components/hal/esp32c3/include/hal/sha_ll.h @@ -15,7 +15,6 @@ #include #include "soc/hwcrypto_reg.h" -#include "soc/dport_access.h" #include "hal/sha_types.h" #ifdef __cplusplus @@ -127,8 +126,12 @@ static inline void sha_ll_fill_text_block(const void *input_text, size_t block_w static inline void sha_ll_read_digest(esp_sha_type sha_type, void *digest_state, size_t digest_word_len) { uint32_t *digest_state_words = (uint32_t *)digest_state; + const size_t REG_WIDTH = sizeof(uint32_t); + + for (size_t i = 0; i < digest_word_len; i++) { + digest_state_words[i] = REG_READ(SHA_H_BASE + (i * REG_WIDTH)); + } - esp_dport_access_read_buffer(digest_state_words, SHA_H_BASE, digest_word_len); } /** diff --git a/components/hal/esp32c3/include/hal/timer_ll.h b/components/hal/esp32c3/include/hal/timer_ll.h index 8b31074fa3..edadee14e3 100644 --- a/components/hal/esp32c3/include/hal/timer_ll.h +++ b/components/hal/esp32c3/include/hal/timer_ll.h @@ -325,13 +325,7 @@ FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uin */ static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool level_int_en) { - switch (timer_num) { - case 0: - hw->int_ena.t0 = level_int_en; - break; - default: - break; - } + // Only "level" interrupts are supported on this target } /** @@ -346,15 +340,8 @@ static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t tim */ static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num) { - bool enable = false; - switch (timer_num) { - case 0: - enable = hw->int_ena.t0; - break; - default: - break; - } - return enable; + // Only "level" interrupts are supported on this target + return true; } /** diff --git a/components/hal/include/hal/gpio_types.h b/components/hal/include/hal/gpio_types.h index d2cd96b724..31a5ed108f 100644 --- a/components/hal/include/hal/gpio_types.h +++ b/components/hal/include/hal/gpio_types.h @@ -26,8 +26,6 @@ typedef enum { GPIO_PORT_MAX, } gpio_port_t; -/** @cond */ //Doxy command to hide preprocessor definitions from docs */ - #define GPIO_SEL_0 (BIT(0)) /*!< Pin 0 selected */ #define GPIO_SEL_1 (BIT(1)) /*!< Pin 1 selected */ #define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected */ @@ -108,12 +106,10 @@ typedef enum { #define GPIO_PIN_REG_25 IO_MUX_GPIO25_REG #define GPIO_PIN_REG_26 IO_MUX_GPIO26_REG #define GPIO_PIN_REG_27 IO_MUX_GPIO27_REG -#if CONFIG_IDF_TARGET_ESP32S2 #define GPIO_PIN_REG_28 IO_MUX_GPIO28_REG #define GPIO_PIN_REG_29 IO_MUX_GPIO29_REG #define GPIO_PIN_REG_30 IO_MUX_GPIO30_REG #define GPIO_PIN_REG_31 IO_MUX_GPIO31_REG -#endif #define GPIO_PIN_REG_32 IO_MUX_GPIO32_REG #define GPIO_PIN_REG_33 IO_MUX_GPIO33_REG #define GPIO_PIN_REG_34 IO_MUX_GPIO34_REG @@ -122,7 +118,6 @@ typedef enum { #define GPIO_PIN_REG_37 IO_MUX_GPIO37_REG #define GPIO_PIN_REG_38 IO_MUX_GPIO38_REG #define GPIO_PIN_REG_39 IO_MUX_GPIO39_REG -#if SOC_GPIO_PIN_COUNT > 40 #define GPIO_PIN_REG_40 IO_MUX_GPIO40_REG #define GPIO_PIN_REG_41 IO_MUX_GPIO41_REG #define GPIO_PIN_REG_42 IO_MUX_GPIO42_REG @@ -130,10 +125,8 @@ typedef enum { #define GPIO_PIN_REG_44 IO_MUX_GPIO44_REG #define GPIO_PIN_REG_45 IO_MUX_GPIO45_REG #define GPIO_PIN_REG_46 IO_MUX_GPIO46_REG -#endif - -/** @endcond */ +#if CONFIG_IDF_TARGET_ESP32 typedef enum { GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */ GPIO_NUM_0 = 0, /*!< GPIO0, input and output */ @@ -158,14 +151,9 @@ typedef enum { GPIO_NUM_19 = 19, /*!< GPIO19, input and output */ GPIO_NUM_20 = 20, /*!< GPIO20, input and output */ GPIO_NUM_21 = 21, /*!< GPIO21, input and output */ -#if SOC_GPIO_PIN_COUNT > 22 -#if CONFIG_IDF_TARGET_ESP32 GPIO_NUM_22 = 22, /*!< GPIO22, input and output */ GPIO_NUM_23 = 23, /*!< GPIO23, input and output */ - GPIO_NUM_25 = 25, /*!< GPIO25, input and output */ -#endif // CONFIG_IDF_TARGET_ESP32 - /* Note: The missing IO is because it is used inside the chip. */ GPIO_NUM_26 = 26, /*!< GPIO26, input and output */ GPIO_NUM_27 = 27, /*!< GPIO27, input and output */ GPIO_NUM_28 = 28, /*!< GPIO28, input and output */ @@ -174,14 +162,54 @@ typedef enum { GPIO_NUM_31 = 31, /*!< GPIO31, input and output */ GPIO_NUM_32 = 32, /*!< GPIO32, input and output */ GPIO_NUM_33 = 33, /*!< GPIO33, input and output */ - GPIO_NUM_34 = 34, /*!< GPIO34, input mode only(ESP32) / input and output(ESP32-S2) */ - GPIO_NUM_35 = 35, /*!< GPIO35, input mode only(ESP32) / input and output(ESP32-S2) */ - GPIO_NUM_36 = 36, /*!< GPIO36, input mode only(ESP32) / input and output(ESP32-S2) */ - GPIO_NUM_37 = 37, /*!< GPIO37, input mode only(ESP32) / input and output(ESP32-S2) */ - GPIO_NUM_38 = 38, /*!< GPIO38, input mode only(ESP32) / input and output(ESP32-S2) */ - GPIO_NUM_39 = 39, /*!< GPIO39, input mode only(ESP32) / input and output(ESP32-S2) */ -#endif // SOC_GPIO_PIN_COUNT > 22 -#if SOC_GPIO_PIN_COUNT > 40 + GPIO_NUM_34 = 34, /*!< GPIO34, input mode only */ + GPIO_NUM_35 = 35, /*!< GPIO35, input mode only */ + GPIO_NUM_36 = 36, /*!< GPIO36, input mode only */ + GPIO_NUM_37 = 37, /*!< GPIO37, input mode only */ + GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */ + GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */ + GPIO_NUM_MAX, +/** @endcond */ +} gpio_num_t; +#elif CONFIG_IDF_TARGET_ESP32S2 +typedef enum { + GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */ + GPIO_NUM_0 = 0, /*!< GPIO0, input and output */ + GPIO_NUM_1 = 1, /*!< GPIO1, input and output */ + GPIO_NUM_2 = 2, /*!< GPIO2, input and output */ + GPIO_NUM_3 = 3, /*!< GPIO3, input and output */ + GPIO_NUM_4 = 4, /*!< GPIO4, input and output */ + GPIO_NUM_5 = 5, /*!< GPIO5, input and output */ + GPIO_NUM_6 = 6, /*!< GPIO6, input and output */ + GPIO_NUM_7 = 7, /*!< GPIO7, input and output */ + GPIO_NUM_8 = 8, /*!< GPIO8, input and output */ + GPIO_NUM_9 = 9, /*!< GPIO9, input and output */ + GPIO_NUM_10 = 10, /*!< GPIO10, input and output */ + GPIO_NUM_11 = 11, /*!< GPIO11, input and output */ + GPIO_NUM_12 = 12, /*!< GPIO12, input and output */ + GPIO_NUM_13 = 13, /*!< GPIO13, input and output */ + GPIO_NUM_14 = 14, /*!< GPIO14, input and output */ + GPIO_NUM_15 = 15, /*!< GPIO15, input and output */ + GPIO_NUM_16 = 16, /*!< GPIO16, input and output */ + GPIO_NUM_17 = 17, /*!< GPIO17, input and output */ + GPIO_NUM_18 = 18, /*!< GPIO18, input and output */ + GPIO_NUM_19 = 19, /*!< GPIO19, input and output */ + GPIO_NUM_20 = 20, /*!< GPIO20, input and output */ + GPIO_NUM_21 = 21, /*!< GPIO21, input and output */ + GPIO_NUM_26 = 26, /*!< GPIO26, input and output */ + GPIO_NUM_27 = 27, /*!< GPIO27, input and output */ + GPIO_NUM_28 = 28, /*!< GPIO28, input and output */ + GPIO_NUM_29 = 29, /*!< GPIO29, input and output */ + GPIO_NUM_30 = 30, /*!< GPIO30, input and output */ + GPIO_NUM_31 = 31, /*!< GPIO31, input and output */ + GPIO_NUM_32 = 32, /*!< GPIO32, input and output */ + GPIO_NUM_33 = 33, /*!< GPIO33, input and output */ + GPIO_NUM_34 = 34, /*!< GPIO34, input and output */ + GPIO_NUM_35 = 35, /*!< GPIO35, input and output */ + GPIO_NUM_36 = 36, /*!< GPIO36, input and output */ + GPIO_NUM_37 = 37, /*!< GPIO37, input and output */ + GPIO_NUM_38 = 38, /*!< GPIO38, input and output */ + GPIO_NUM_39 = 39, /*!< GPIO39, input and output */ GPIO_NUM_40 = 40, /*!< GPIO40, input and output */ GPIO_NUM_41 = 41, /*!< GPIO41, input and output */ GPIO_NUM_42 = 42, /*!< GPIO42, input and output */ @@ -189,10 +217,89 @@ typedef enum { GPIO_NUM_44 = 44, /*!< GPIO44, input and output */ GPIO_NUM_45 = 45, /*!< GPIO45, input and output */ GPIO_NUM_46 = 46, /*!< GPIO46, input mode only */ -#endif // GPIO_PIN_COUNT > 40 GPIO_NUM_MAX, /** @endcond */ } gpio_num_t; +#elif CONFIG_IDF_TARGET_ESP32S3 +typedef enum { + GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */ + GPIO_NUM_0 = 0, /*!< GPIO0, input and output */ + GPIO_NUM_1 = 1, /*!< GPIO1, input and output */ + GPIO_NUM_2 = 2, /*!< GPIO2, input and output */ + GPIO_NUM_3 = 3, /*!< GPIO3, input and output */ + GPIO_NUM_4 = 4, /*!< GPIO4, input and output */ + GPIO_NUM_5 = 5, /*!< GPIO5, input and output */ + GPIO_NUM_6 = 6, /*!< GPIO6, input and output */ + GPIO_NUM_7 = 7, /*!< GPIO7, input and output */ + GPIO_NUM_8 = 8, /*!< GPIO8, input and output */ + GPIO_NUM_9 = 9, /*!< GPIO9, input and output */ + GPIO_NUM_10 = 10, /*!< GPIO10, input and output */ + GPIO_NUM_11 = 11, /*!< GPIO11, input and output */ + GPIO_NUM_12 = 12, /*!< GPIO12, input and output */ + GPIO_NUM_13 = 13, /*!< GPIO13, input and output */ + GPIO_NUM_14 = 14, /*!< GPIO14, input and output */ + GPIO_NUM_15 = 15, /*!< GPIO15, input and output */ + GPIO_NUM_16 = 16, /*!< GPIO16, input and output */ + GPIO_NUM_17 = 17, /*!< GPIO17, input and output */ + GPIO_NUM_18 = 18, /*!< GPIO18, input and output */ + GPIO_NUM_19 = 19, /*!< GPIO19, input and output */ + GPIO_NUM_20 = 20, /*!< GPIO20, input and output */ + GPIO_NUM_21 = 21, /*!< GPIO21, input and output */ + GPIO_NUM_26 = 26, /*!< GPIO26, input and output */ + GPIO_NUM_27 = 27, /*!< GPIO27, input and output */ + GPIO_NUM_28 = 28, /*!< GPIO28, input and output */ + GPIO_NUM_29 = 29, /*!< GPIO29, input and output */ + GPIO_NUM_30 = 30, /*!< GPIO30, input and output */ + GPIO_NUM_31 = 31, /*!< GPIO31, input and output */ + GPIO_NUM_32 = 32, /*!< GPIO32, input and output */ + GPIO_NUM_33 = 33, /*!< GPIO33, input and output */ + GPIO_NUM_34 = 34, /*!< GPIO34, input and output */ + GPIO_NUM_35 = 35, /*!< GPIO35, input and output */ + GPIO_NUM_36 = 36, /*!< GPIO36, input and output */ + GPIO_NUM_37 = 37, /*!< GPIO37, input and output */ + GPIO_NUM_38 = 38, /*!< GPIO38, input and output */ + GPIO_NUM_39 = 39, /*!< GPIO39, input and output */ + GPIO_NUM_40 = 40, /*!< GPIO40, input and output */ + GPIO_NUM_41 = 41, /*!< GPIO41, input and output */ + GPIO_NUM_42 = 42, /*!< GPIO42, input and output */ + GPIO_NUM_43 = 43, /*!< GPIO43, input and output */ + GPIO_NUM_44 = 44, /*!< GPIO44, input and output */ + GPIO_NUM_45 = 45, /*!< GPIO45, input and output */ + GPIO_NUM_46 = 46, /*!< GPIO46, input mode only */ + GPIO_NUM_47 = 47, /*!< GPIO47, input and output */ + GPIO_NUM_MAX, +/** @endcond */ +} gpio_num_t; +#elif CONFIG_IDF_TARGET_ESP32C3 +typedef enum { + GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */ + GPIO_NUM_0 = 0, /*!< GPIO0, input and output */ + GPIO_NUM_1 = 1, /*!< GPIO1, input and output */ + GPIO_NUM_2 = 2, /*!< GPIO2, input and output */ + GPIO_NUM_3 = 3, /*!< GPIO3, input and output */ + GPIO_NUM_4 = 4, /*!< GPIO4, input and output */ + GPIO_NUM_5 = 5, /*!< GPIO5, input and output */ + GPIO_NUM_6 = 6, /*!< GPIO6, input and output */ + GPIO_NUM_7 = 7, /*!< GPIO7, input and output */ + GPIO_NUM_8 = 8, /*!< GPIO8, input and output */ + GPIO_NUM_9 = 9, /*!< GPIO9, input and output */ + GPIO_NUM_10 = 10, /*!< GPIO10, input and output */ + GPIO_NUM_11 = 11, /*!< GPIO11, input and output */ + GPIO_NUM_12 = 12, /*!< GPIO12, input and output */ + GPIO_NUM_13 = 13, /*!< GPIO13, input and output */ + GPIO_NUM_14 = 14, /*!< GPIO14, input and output */ + GPIO_NUM_15 = 15, /*!< GPIO15, input and output */ + GPIO_NUM_16 = 16, /*!< GPIO16, input and output */ + GPIO_NUM_17 = 17, /*!< GPIO17, input and output */ + GPIO_NUM_18 = 18, /*!< GPIO18, input and output */ + // TODO: ESP32C3 IDF-2463 + GPIO_NUM_20 = 20, /*!< GPIO20, input and output */ + GPIO_NUM_21 = 21, /*!< GPIO21, input and output */ + GPIO_NUM_22 = 22, /*!< GPIO22, input and output */ + GPIO_NUM_MAX, +/** @endcond */ +} gpio_num_t; +#endif typedef enum { GPIO_INTR_DISABLE = 0, /*!< Disable GPIO interrupt */ diff --git a/components/hal/sha_hal.c b/components/hal/sha_hal.c index ac9323be8b..d8d9189fda 100644 --- a/components/hal/sha_hal.c +++ b/components/hal/sha_hal.c @@ -60,12 +60,20 @@ inline static size_t state_length(esp_sha_type type) case SHA2_224: case SHA2_256: return SHA256_STATE_LEN_WORDS; +#if SOC_SHA_SUPPORT_SHA384 case SHA2_384: + return SHA512_STATE_LEN_WORDS; +#endif +#if SOC_SHA_SUPPORT_SHA512 case SHA2_512: + return SHA512_STATE_LEN_WORDS; +#endif +#if SOC_SHA_SUPPORT_SHA512_T case SHA2_512224: case SHA2_512256: case SHA2_512T: return SHA512_STATE_LEN_WORDS; +#endif default: return 0; } diff --git a/components/hal/test/test_mpu.c b/components/hal/test/test_mpu.c index 9f85b9963f..8dc3abdbd7 100644 --- a/components/hal/test/test_mpu.c +++ b/components/hal/test/test_mpu.c @@ -6,6 +6,11 @@ #include "hal/mpu_hal.h" +// TODO ESP32-C3 IDF-2375 +// LL still not implemented + +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3) + volatile static int RTC_NOINIT_ATTR access = 0; static void trigger_illegal_access(void) @@ -41,3 +46,5 @@ void check_access(void) TEST_CASE_MULTIPLE_STAGES("Can set illegal access regions", "[soc][mpu]", trigger_illegal_access, check_access); + +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3) diff --git a/components/soc/esp32c3/include/soc/clkout_channel.h b/components/soc/esp32c3/include/soc/clkout_channel.h new file mode 100644 index 0000000000..c9e9a0c245 --- /dev/null +++ b/components/soc/esp32c3/include/soc/clkout_channel.h @@ -0,0 +1,26 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SOC_CLKOUT_CHANNEL_H +#define _SOC_CLKOUT_CHANNEL_H + +//CLKOUT channels +#define CLKOUT_GPIO20_DIRECT_CHANNEL CLKOUT_CHANNEL_1 +#define CLKOUT_CHANNEL_1_DIRECT_GPIO_NUM 20 +#define CLKOUT_GPIO19_DIRECT_CHANNEL CLKOUT_CHANNEL_2 +#define CLKOUT_CHANNEL_2_DIRECT_GPIO_NUM 19 +#define CLKOUT_GPIO18_DIRECT_CHANNEL CLKOUT_CHANNEL_3 +#define CLKOUT_CHANNEL_3_DIRECT_GPIO_NUM 18 + +#endif diff --git a/components/soc/esp32c3/include/soc/gpio_caps.h b/components/soc/esp32c3/include/soc/gpio_caps.h index ec0ff52cca..ebbc15d885 100644 --- a/components/soc/esp32c3/include/soc/gpio_caps.h +++ b/components/soc/esp32c3/include/soc/gpio_caps.h @@ -18,23 +18,21 @@ extern "C" { #endif +// ESP32-C3 has 1 GPIO peripheral #define SOC_GPIO_PORT (1) #define SOC_GPIO_PIN_COUNT (22) // Target has no full RTC IO subsystem, so GPIO is 100% "independent" of RTC +// On ESP32-C3, Digital IOs have their own registers to control pullup/down/capability, independent with RTC registers. #define GPIO_SUPPORTS_RTC_INDEPENDENT (1) - +// Force hold is a new function of ESP32-C3 #define GPIO_SUPPORTS_FORCE_HOLD (1) -#define GPIO_PRO_CPU_INTR_ENA (BIT(0)) -#define GPIO_PRO_CPU_NMI_INTR_ENA (BIT(1)) - #define GPIO_MODE_DEF_DISABLE (0) #define GPIO_MODE_DEF_INPUT (BIT0) #define GPIO_MODE_DEF_OUTPUT (BIT1) #define GPIO_MODE_DEF_OD (BIT2) -// TODO ESP32-C3 IDF-2119 - check if any IOs are not full featured GPIO #define SOC_GPIO_VALID_GPIO_MASK ((1U< #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/gpio_caps.h b/components/soc/esp32s3/include/soc/gpio_caps.h index e3a5a10a61..e4cfb898c7 100644 --- a/components/soc/esp32s3/include/soc/gpio_caps.h +++ b/components/soc/esp32s3/include/soc/gpio_caps.h @@ -27,10 +27,10 @@ extern "C" { // Force hold is a new function of ESP32-S3 #define SOC_GPIO_SUPPORT_FORCE_HOLD (1) -// 0~47 except from 22~25, 47 are valid -#define SOC_GPIO_VALID_GPIO_MASK (0xFFFFFFFFFFFFULL & ~(0ULL | BIT22 | BIT23 | BIT24 | BIT25 | BIT47)) -// GPIO 46, 47 are input only -#define SOC_GPIO_VALID_OUTPUT_GPIO_MASK (SOC_GPIO_VALID_GPIO_MASK & ~(0ULL | BIT46 | BIT47)) +// 0~47 except from 22~25 are valid +#define SOC_GPIO_VALID_GPIO_MASK (0xFFFFFFFFFFFFULL & ~(0ULL | BIT22 | BIT23 | BIT24 | BIT25)) +// GPIO 46 is input only +#define SOC_GPIO_VALID_OUTPUT_GPIO_MASK (SOC_GPIO_VALID_GPIO_MASK & ~(0ULL | BIT46)) #ifdef __cplusplus diff --git a/components/soc/esp32s3/include/soc/i2s_caps.h b/components/soc/esp32s3/include/soc/i2s_caps.h index a0d476b1ad..cd21be8893 100644 --- a/components/soc/esp32s3/include/soc/i2s_caps.h +++ b/components/soc/esp32s3/include/soc/i2s_caps.h @@ -21,5 +21,3 @@ // ESP32-S3 have 1 I2S #define SOC_I2S_NUM (1) - -#define SOC_I2S_SUPPORT_PDM (0) // ESP32-S3 do not support PDM diff --git a/tools/ci/config/target-test.yml b/tools/ci/config/target-test.yml index dd479ae896..12df7a4822 100644 --- a/tools/ci/config/target-test.yml +++ b/tools/ci/config/target-test.yml @@ -359,7 +359,7 @@ component_ut_test_001: UT_001: extends: .unit_test_32_template - parallel: 45 + parallel: 47 tags: - ESP32_IDF - UT_T1_1 @@ -506,7 +506,7 @@ UT_034: UT_035: extends: .unit_test_s2_template - parallel: 47 + parallel: 48 tags: - ESP32S2_IDF - UT_T1_1 From f09b8ae7a4e9bc454da72d43ddeeb6154ffee1d5 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Dec 2020 20:23:19 +1100 Subject: [PATCH 2/9] driver: Add esp32c3 ADC driver Based on internal commit 3ef01301fffa552d4be6d81bc9d199c223224305 --- components/driver/CMakeLists.txt | 1 + components/driver/esp32/adc.c | 4 +- components/driver/esp32c3/adc.c | 590 +++++++++++ .../driver/esp32c3/include/driver/adc.h | 201 ++++ components/driver/esp32s2/adc.c | 6 +- .../driver/esp32s3/include/driver/adc.h | 33 - components/driver/include/driver/adc_common.h | 145 ++- components/hal/adc_hal.c | 84 ++ components/hal/esp32/adc_hal.c | 6 - components/hal/esp32c3/adc_hal.c | 97 +- components/hal/esp32c3/include/hal/adc_hal.h | 5 - components/hal/esp32c3/include/hal/adc_ll.h | 975 ++++++++++++++++++ components/hal/esp32s2/adc_hal.c | 9 +- components/hal/esp32s2/include/hal/adc_ll.h | 8 +- components/hal/esp32s3/include/hal/adc_hal.h | 5 - components/hal/esp32s3/include/hal/adc_ll.h | 8 +- components/hal/include/hal/adc_hal.h | 48 +- components/hal/include/hal/adc_types.h | 76 +- .../soc/esp32c3/include/soc/periph_defs.h | 1 + components/soc/esp32c3/include/soc/soc_caps.h | 4 + 20 files changed, 2144 insertions(+), 162 deletions(-) create mode 100644 components/driver/esp32c3/adc.c create mode 100644 components/driver/esp32c3/include/driver/adc.h create mode 100644 components/hal/esp32c3/include/hal/adc_ll.h diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index afd71f345e..c0b8b11c43 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -67,6 +67,7 @@ endif() if(IDF_TARGET STREQUAL "esp32c3") list(APPEND srcs "spi_slave_hd.c" + "esp32c3/adc.c" "esp32c3/rtc_tempsensor.c") endif() diff --git a/components/driver/esp32/adc.c b/components/driver/esp32/adc.c index 8451c05943..d9d7da0a18 100644 --- a/components/driver/esp32/adc.c +++ b/components/driver/esp32/adc.c @@ -118,7 +118,7 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) } adc_gpio_init(adc_unit, channel); ADC_ENTER_CRITICAL(); - adc_hal_digi_init(); + adc_hal_init(); adc_hal_digi_controller_config(&dig_cfg); ADC_EXIT_CRITICAL(); @@ -128,7 +128,7 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) esp_err_t adc_digi_init(void) { ADC_ENTER_CRITICAL(); - adc_hal_digi_init(); + adc_hal_init(); ADC_EXIT_CRITICAL(); return ESP_OK; } diff --git a/components/driver/esp32c3/adc.c b/components/driver/esp32c3/adc.c new file mode 100644 index 0000000000..e4b918f907 --- /dev/null +++ b/components/driver/esp32c3/adc.c @@ -0,0 +1,590 @@ +// Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include "esp_log.h" +#include "sys/lock.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/timers.h" +#include "esp_intr_alloc.h" +#include "driver/periph_ctrl.h" +#include "driver/rtc_io.h" +#include "driver/rtc_cntl.h" +#include "driver/gpio.h" +#include "driver/adc.h" +#include "sdkconfig.h" + +#include "esp32c3/rom/ets_sys.h" +#include "hal/adc_types.h" +#include "hal/adc_hal.h" + +#define ADC_CHECK_RET(fun_ret) ({ \ + if (fun_ret != ESP_OK) { \ + ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \ + return ESP_FAIL; \ + } \ +}) + +static const char *ADC_TAG = "ADC"; + +#define ADC_CHECK(a, str, ret_val) ({ \ + if (!(a)) { \ + ESP_LOGE(ADC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ + return (ret_val); \ + } \ +}) + +#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel]) + +#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG) + +extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. +#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) +#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) + +/*--------------------------------------------------------------- + Digital controller setting +---------------------------------------------------------------*/ +esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) +{ + esp_err_t ret = ESP_OK; + ADC_ENTER_CRITICAL(); + adc_hal_digi_controller_config(config); + ADC_EXIT_CRITICAL(); + return ret; +} + +esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config) +{ + if (adc_unit & ADC_UNIT_1) { + return ESP_ERR_NOT_SUPPORTED; + } + ADC_ENTER_CRITICAL(); + adc_hal_arbiter_config(config); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/** + * @brief Set ADC module controller. + * There are five SAR ADC controllers: + * Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes; + * Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep; + * the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2. + * + * @note Only ADC2 support arbiter to switch controllers automatically. Access to the ADC is based on the priority of the controller. + * @note For ADC1, Controller access is mutually exclusive. + * + * @param adc_unit ADC unit. + * @param ctrl ADC controller, Refer to `adc_ll_controller_t`. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_ll_controller_t ctrl) +{ + adc_arbiter_t config = {0}; + adc_arbiter_t cfg = ADC_ARBITER_CONFIG_DEFAULT(); + + if (adc_unit & ADC_UNIT_1) { + adc_hal_set_controller(ADC_NUM_1, ctrl); + } + if (adc_unit & ADC_UNIT_2) { + adc_hal_set_controller(ADC_NUM_2, ctrl); + switch (ctrl) { + case ADC2_CTRL_FORCE_PWDET: + config.pwdet_pri = 2; + config.mode = ADC_ARB_MODE_SHIELD; + adc_hal_arbiter_config(&config); + adc_hal_set_controller(ADC_NUM_2, ADC2_CTRL_PWDET); + break; + case ADC2_CTRL_FORCE_RTC: + config.rtc_pri = 2; + config.mode = ADC_ARB_MODE_SHIELD; + adc_hal_arbiter_config(&config); + adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC); + break; + case ADC2_CTRL_FORCE_DIG: + config.dig_pri = 2; + config.mode = ADC_ARB_MODE_SHIELD; + adc_hal_arbiter_config(&config); + adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_DIG); + break; + default: + adc_hal_arbiter_config(&cfg); + break; + } + } + return ESP_OK; +} + +/** + * @brief Reset FSM of adc digital controller. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_reset(void) +{ + ADC_ENTER_CRITICAL(); + adc_hal_digi_reset(); + adc_hal_digi_clear_pattern_table(ADC_NUM_1); + adc_hal_digi_clear_pattern_table(ADC_NUM_2); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/*************************************/ +/* Digital controller filter setting */ +/*************************************/ + +esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx) +{ + abort(); // TODO ESP32-C3 IDF-2528 +} + +esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config) +{ + abort(); // TODO ESP32-C3 IDF-2528 +} + +esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config) +{ + abort(); // TODO ESP32-C3 IDF-2528 +} + +esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable) +{ + abort(); // TODO ESP32-C3 IDF-2528 +} + +/** + * @brief Get the filtered data of adc digital controller filter. For debug. + * The data after each measurement and filtering is updated to the DMA by the digital controller. But it can also be obtained manually through this API. + * + * @note For ESP32S2, The filter will filter all the enabled channel data of the each ADC unit at the same time. + * @param idx Filter index. + * @return Filtered data. if <0, the read data invalid. + */ +int adc_digi_filter_read_data(adc_digi_filter_idx_t idx) +{ + abort(); // TODO ESP32-C3 IDF-2528 +} + +/**************************************/ +/* Digital controller monitor setting */ +/**************************************/ + +esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config) +{ + ADC_ENTER_CRITICAL(); + if (idx == ADC_DIGI_MONITOR_IDX0) { + adc_hal_digi_monitor_config(ADC_NUM_1, config); + } else if (idx == ADC_DIGI_MONITOR_IDX1) { + adc_hal_digi_monitor_config(ADC_NUM_2, config); + } + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable) +{ + ADC_ENTER_CRITICAL(); + if (idx == ADC_DIGI_MONITOR_IDX0) { + adc_hal_digi_monitor_enable(ADC_NUM_1, enable); + } else if (idx == ADC_DIGI_MONITOR_IDX1) { + adc_hal_digi_monitor_enable(ADC_NUM_2, enable); + } + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/**************************************/ +/* Digital controller intr setting */ +/**************************************/ + +esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) +{ + ADC_ENTER_CRITICAL(); + if (adc_unit & ADC_UNIT_1) { + adc_hal_digi_intr_enable(ADC_NUM_1, intr_mask); + } + if (adc_unit & ADC_UNIT_2) { + adc_hal_digi_intr_enable(ADC_NUM_2, intr_mask); + } + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) +{ + ADC_ENTER_CRITICAL(); + if (adc_unit & ADC_UNIT_1) { + adc_hal_digi_intr_disable(ADC_NUM_1, intr_mask); + } + if (adc_unit & ADC_UNIT_2) { + adc_hal_digi_intr_disable(ADC_NUM_2, intr_mask); + } + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) +{ + ADC_ENTER_CRITICAL(); + if (adc_unit & ADC_UNIT_1) { + adc_hal_digi_intr_clear(ADC_NUM_1, intr_mask); + } + if (adc_unit & ADC_UNIT_2) { + adc_hal_digi_intr_clear(ADC_NUM_2, intr_mask); + } + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit) +{ + uint32_t ret = 0; + ADC_ENTER_CRITICAL(); + if (adc_unit & ADC_UNIT_1) { + ret = adc_hal_digi_get_intr_status(ADC_NUM_1); + } + if (adc_unit & ADC_UNIT_2) { + ret = adc_hal_digi_get_intr_status(ADC_NUM_2); + } + ADC_EXIT_CRITICAL(); + return ret; +} + +static uint8_t s_isr_registered = 0; +static intr_handle_t s_adc_isr_handle = NULL; + +esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags) +{ + ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG); + ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL); + + esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle); + if (ret == ESP_OK) { + s_isr_registered = 1; + } + return ret; +} + +esp_err_t adc_digi_isr_deregister(void) +{ + esp_err_t ret = ESP_FAIL; + if (s_isr_registered) { + ret = esp_intr_free(s_adc_isr_handle); + if (ret == ESP_OK) { + s_isr_registered = 0; + } + } + return ret; +} + +/*--------------------------------------------------------------- + RTC controller setting +---------------------------------------------------------------*/ + + +//This feature is currently supported on ESP32C3, will be supported on other chips soon +/*--------------------------------------------------------------- + DMA setting +---------------------------------------------------------------*/ +#include "soc/system_reg.h" +#include "hal/dma_types.h" +#include "hal/gdma_ll.h" +#include "hal/adc_hal.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/ringbuf.h" +#include + +#define INTERNAL_BUF_NUM 5 +#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF + +typedef struct adc_digi_context_t { + intr_handle_t dma_intr_hdl; //MD interrupt handle + uint32_t bytes_between_intr; //bytes between in suc eof intr + uint8_t *rx_dma_buf; //dma buffer + adc_dma_hal_context_t hal_dma; //dma context (hal) + adc_dma_hal_config_t hal_dma_config; //dma config (hal) + RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler + bool ringbuf_overflow_flag; //1: ringbuffer overflow + bool driver_state_flag; //1: driver is started; 2: driver is stoped +} adc_digi_context_t; + + +static const char* ADC_DMA_TAG = "ADC_DMA:"; +static adc_digi_context_t *adc_digi_ctx = NULL; + +static void adc_dma_intr(void* arg); + +static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel) +{ + return adc_channel_io_map[adc_unit][adc_channel]; +} + +static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask) +{ + esp_err_t ret = ESP_OK; + uint64_t gpio_mask = 0; + uint32_t n = 0; + int8_t io = 0; + + while (channel_mask) { + if (channel_mask & 0x1) { + io = adc_digi_get_io_num(adc_unit, n); + if (io < 0) { + return ESP_ERR_INVALID_ARG; + } + gpio_mask |= BIT64(io); + } + channel_mask = channel_mask >> 1; + n++; + } + + gpio_config_t cfg = { + .pin_bit_mask = gpio_mask, + .mode = GPIO_MODE_DISABLE, + }; + gpio_config(&cfg); + + return ret; +} + +esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) +{ + esp_err_t ret = ESP_OK; + + adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t)); + if (adc_digi_ctx == NULL) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + + ret = esp_intr_alloc(SOC_GDMA_ADC_INTR_SOURCE, 0, adc_dma_intr, (void *)adc_digi_ctx, &adc_digi_ctx->dma_intr_hdl); + if (ret != ESP_OK) { + goto cleanup; + } + + //ringbuffer + adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF); + if (!adc_digi_ctx->ringbuf_hdl) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + + //malloc internal buffer + adc_digi_ctx->bytes_between_intr = init_config->conv_num_each_intr; + adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, adc_digi_ctx->bytes_between_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL); + if (!adc_digi_ctx->rx_dma_buf) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + + //malloc dma descriptor + adc_digi_ctx->hal_dma_config.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA); + if (!adc_digi_ctx->hal_dma_config.rx_desc) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + adc_digi_ctx->hal_dma_config.desc_max_num = INTERNAL_BUF_NUM; + adc_digi_ctx->hal_dma_config.dma_chan = init_config->dma_chan; + + if (init_config->adc1_chan_mask) { + ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask); + if (ret != ESP_OK) { + goto cleanup; + } + } + if (init_config->adc2_chan_mask) { + ret = adc_digi_gpio_init(ADC_NUM_2, init_config->adc2_chan_mask); + if (ret != ESP_OK) { + goto cleanup; + } + } + + periph_module_enable(PERIPH_SARADC_MODULE); + periph_module_enable(PERIPH_GDMA_MODULE); + adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); + ADC_ENTER_CRITICAL(); + adc_hal_init(); + adc_hal_arbiter_config(&config); + adc_hal_digi_init(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); + ADC_EXIT_CRITICAL(); + + return ret; + +cleanup: + adc_digi_deinitialize(); + return ret; + +} + +static IRAM_ATTR void adc_dma_intr(void *arg) +{ + portBASE_TYPE taskAwoken = 0; + BaseType_t ret; + + //clear the in suc eof interrupt + adc_hal_digi_clr_intr(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); + + while (adc_digi_ctx->hal_dma_config.cur_desc_ptr->dw0.owner == 0) { + + dma_descriptor_t *current_desc = adc_digi_ctx->hal_dma_config.cur_desc_ptr; + ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken); + if (ret == pdFALSE) { + //ringbuffer overflow + adc_digi_ctx->ringbuf_overflow_flag = 1; + } + + adc_digi_ctx->hal_dma_config.desc_cnt += 1; + //cycle the dma descriptor and buffers + adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.cur_desc_ptr->next; + if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) { + break; + } + } + + if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) { + + assert(adc_digi_ctx->hal_dma_config.desc_cnt == adc_digi_ctx->hal_dma_config.desc_max_num); + //reset the current descriptor status + adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.rx_desc; + adc_digi_ctx->hal_dma_config.desc_cnt = 0; + + //start next turns of dma operation + adc_hal_digi_rxdma_start(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); + } + + if(taskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +esp_err_t adc_digi_start(void) +{ + assert(adc_digi_ctx->driver_state_flag == 0 && "the driver is already started"); + //reset flags + adc_digi_ctx->ringbuf_overflow_flag = 0; + adc_digi_ctx->driver_state_flag = 1; + + //create dma descriptors + adc_hal_digi_dma_multi_descriptor(&adc_digi_ctx->hal_dma_config, adc_digi_ctx->rx_dma_buf, adc_digi_ctx->bytes_between_intr, adc_digi_ctx->hal_dma_config.desc_max_num); + adc_hal_digi_set_eof_num(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, (adc_digi_ctx->bytes_between_intr)/4); + //set the current descriptor pointer + adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.rx_desc; + adc_digi_ctx->hal_dma_config.desc_cnt = 0; + + //enable in suc eof intr + adc_hal_digi_ena_intr(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, GDMA_LL_EVENT_RX_SUC_EOF); + //start DMA + adc_hal_digi_rxdma_start(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); + //start ADC + adc_hal_digi_start(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); + + return ESP_OK; +} + +esp_err_t adc_digi_stop(void) +{ + assert(adc_digi_ctx->driver_state_flag == 1 && "the driver is already stoped"); + adc_digi_ctx->driver_state_flag = 0; + + //disable the in suc eof intrrupt + adc_hal_digi_dis_intr(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); + //clear the in suc eof interrupt + adc_hal_digi_clr_intr(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); + //stop DMA + adc_hal_digi_rxdma_stop(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); + //stop ADC + adc_hal_digi_stop(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); + + return ESP_OK; +} + +esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms) +{ + TickType_t ticks_to_wait; + esp_err_t ret = ESP_OK; + uint8_t *data = NULL; + size_t size = 0; + + ticks_to_wait = timeout_ms / portTICK_RATE_MS; + if (timeout_ms == ADC_MAX_DELAY) { + ticks_to_wait = portMAX_DELAY; + } + + data = xRingbufferReceiveUpTo(adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max); + if (!data) { + ESP_EARLY_LOGW(ADC_DMA_TAG, "No data, increase timeout or reduce conv_num_each_intr"); + ret = ESP_ERR_TIMEOUT; + *out_length = 0; + return ret; + } + + memcpy(buf, data, size); + vRingbufferReturnItem(adc_digi_ctx->ringbuf_hdl, data); + assert((size % 4) == 0); + *out_length = size; + + if (adc_digi_ctx->ringbuf_overflow_flag) { + ret = ESP_ERR_INVALID_STATE; + } + return ret; +} + +static esp_err_t adc_digi_deinit(void) +{ + ADC_ENTER_CRITICAL(); + adc_hal_digi_deinit(); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t adc_digi_deinitialize(void) +{ + assert(adc_digi_ctx->driver_state_flag == 0 && "the driver is not stoped"); + + if (adc_digi_ctx == NULL) { + return ESP_ERR_INVALID_STATE; + } + + if (adc_digi_ctx->dma_intr_hdl) { + esp_intr_free(adc_digi_ctx->dma_intr_hdl); + } + + if(adc_digi_ctx->ringbuf_hdl) { + vRingbufferDelete(adc_digi_ctx->ringbuf_hdl); + adc_digi_ctx->ringbuf_hdl = NULL; + } + + if (adc_digi_ctx->hal_dma_config.rx_desc) { + free(adc_digi_ctx->hal_dma_config.rx_desc); + } + + free(adc_digi_ctx); + adc_digi_ctx = NULL; + + adc_digi_deinit(); + periph_module_disable(PERIPH_SARADC_MODULE); + periph_module_disable(PERIPH_GDMA_MODULE); + + return ESP_OK; +} diff --git a/components/driver/esp32c3/include/driver/adc.h b/components/driver/esp32c3/include/driver/adc.h new file mode 100644 index 0000000000..197af316d4 --- /dev/null +++ b/components/driver/esp32c3/include/driver/adc.h @@ -0,0 +1,201 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "driver/adc_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------------------------------------------------- + Common setting +---------------------------------------------------------------*/ + +/** + * @brief Config ADC module arbiter. + * The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, + * the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data. + * + * @note Only ADC2 support arbiter. + * @note Default priority: Wi-Fi > RTC > Digital; + * @note In normal use, there is no need to call this interface to config arbiter. + * + * @param adc_unit ADC unit. + * @param config Refer to `adc_arbiter_t`. + * + * @return + * - ESP_OK Success + * - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter. + */ +esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config); + +/*************************************/ +/* Digital controller filter setting */ +/*************************************/ +/** + * @brief Reset adc digital controller filter. + * + * @param idx Filter index. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx); + +/** + * @brief Set adc digital controller filter configuration. + * + * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. + * + * @param idx Filter index. + * @param config See ``adc_digi_filter_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); + +/** + * @brief Get adc digital controller filter configuration. + * + * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. + * + * @param idx Filter index. + * @param config See ``adc_digi_filter_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); + +/** + * @brief Enable/disable adc digital controller filter. + * Filtering the ADC data to obtain smooth data at higher sampling rates. + * + * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. + * + * @param idx Filter index. + * @param enable Enable/Disable filter. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable); + +/**************************************/ +/* Digital controller monitor setting */ +/**************************************/ + +/** + * @brief Config monitor of adc digital controller. + * + * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time. + * + * @param idx Monitor index. + * @param config See ``adc_digi_monitor_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config); + +/** + * @brief Enable/disable monitor of adc digital controller. + * + * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time. + * + * @param idx Monitor index. + * @param enable True or false enable monitor. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable); + +/**************************************/ +/* Digital controller intr setting */ +/**************************************/ + +/** + * @brief Enable interrupt of adc digital controller by bitmask. + * + * @param adc_unit ADC unit. + * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask); + +/** + * @brief Disable interrupt of adc digital controller by bitmask. + * + * @param adc_unit ADC unit. + * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask); + +/** + * @brief Clear interrupt of adc digital controller by bitmask. + * + * @param adc_unit ADC unit. + * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask); + +/** + * @brief Get interrupt status mask of adc digital controller. + * + * @param adc_unit ADC unit. + * @return + * - intr Interrupt bitmask, See ``adc_digi_intr_t``. + */ +uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit); + +/** + * @brief Register ADC interrupt handler, the handler is an ISR. + * The handler will be attached to the same CPU core that this function is running on. + * + * @param fn Interrupt handler function. + * @param arg Parameter for handler function + * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) + * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. + * + * @return + * - ESP_OK Success + * - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags. + * - ESP_ERR_INVALID_ARG Function pointer error. + */ +esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags); + +/** + * @brief Deregister ADC interrupt handler, the handler is an ISR. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG hander error. + * - ESP_FAIL ISR not be registered. + */ +esp_err_t adc_digi_isr_deregister(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/esp32s2/adc.c b/components/driver/esp32s2/adc.c index 2422989fb7..d38fca916d 100644 --- a/components/driver/esp32s2/adc.c +++ b/components/driver/esp32s2/adc.c @@ -71,7 +71,7 @@ esp_err_t adc_digi_init(void) { adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); ADC_ENTER_CRITICAL(); - adc_hal_digi_init(); + adc_hal_init(); adc_hal_arbiter_config(&config); ADC_EXIT_CRITICAL(); return ESP_OK; @@ -148,12 +148,12 @@ esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config) * @note For ADC1, Controller access is mutually exclusive. * * @param adc_unit ADC unit. - * @param ctrl ADC controller, Refer to `adc_controller_t`. + * @param ctrl ADC controller, Refer to `adc_ll_controller_t`. * * @return * - ESP_OK Success */ -esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_controller_t ctrl) +esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_ll_controller_t ctrl) { adc_arbiter_t config = {0}; adc_arbiter_t cfg = ADC_ARBITER_CONFIG_DEFAULT(); diff --git a/components/driver/esp32s3/include/driver/adc.h b/components/driver/esp32s3/include/driver/adc.h index 107ab2fa68..e480570a47 100644 --- a/components/driver/esp32s3/include/driver/adc.h +++ b/components/driver/esp32s3/include/driver/adc.h @@ -239,39 +239,6 @@ esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_fl */ esp_err_t adc_digi_isr_deregister(void); -/*--------------------------------------------------------------- - RTC controller setting ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- - Deprecated API ----------------------------------------------------------------*/ -/** - * @brief Set I2S data source - * - * @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC. - * - * @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead. - * - * @return - * - ESP_OK success - */ -esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src) __attribute__((deprecated)); - -/** - * @brief Initialize I2S ADC mode - * - * @param adc_unit ADC unit index - * @param channel ADC channel index - * - * @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead. - * - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated)); - #ifdef __cplusplus } #endif diff --git a/components/driver/include/driver/adc_common.h b/components/driver/include/driver/adc_common.h index c00992edf0..3f0b49dc4c 100644 --- a/components/driver/include/driver/adc_common.h +++ b/components/driver/include/driver/adc_common.h @@ -24,25 +24,47 @@ extern "C" { #endif +#if CONFIG_IDF_TARGET_ESP32 /**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ typedef enum { - ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 (ESP32), GPIO1 (ESP32-S2) */ - ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 (ESP32), GPIO2 (ESP32-S2) */ - ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 (ESP32), GPIO3 (ESP32-S2) */ - ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 (ESP32), GPIO4 (ESP32-S2) */ - ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 (ESP32), GPIO5 (ESP32-S2) */ - ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 (ESP32), GPIO6 (ESP32-S2) */ - ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 (ESP32), GPIO7 (ESP32-S2) */ - ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 (ESP32), GPIO8 (ESP32-S2) */ -#if CONFIG_IDF_TARGET_ESP32 + ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */ + ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */ + ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 */ + ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 */ + ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 */ + ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 */ + ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 */ + ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 */ ADC1_CHANNEL_MAX, -#elif CONFIG_IDF_TARGET_ESP32S2 - ADC1_CHANNEL_8, /*!< ADC1 channel 6 is GPIO9 (ESP32-S2)*/ - ADC1_CHANNEL_9, /*!< ADC1 channel 7 is GPIO10 (ESP32-S2) */ - ADC1_CHANNEL_MAX, -#endif } adc1_channel_t; +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776 +/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ +typedef enum { + ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO1 */ + ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO2 */ + ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO3 */ + ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO4 */ + ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO5 */ + ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO6 */ + ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO7 */ + ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO8 */ + ADC1_CHANNEL_8, /*!< ADC1 channel 6 is GPIO9 */ + ADC1_CHANNEL_9, /*!< ADC1 channel 7 is GPIO10 */ + ADC1_CHANNEL_MAX, +} adc1_channel_t; +#elif CONFIG_IDF_TARGET_ESP32C3 +/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ +typedef enum { + ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */ + ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */ + ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO2 */ + ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO3 */ + ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO34 */ + ADC1_CHANNEL_MAX, +} adc1_channel_t; +#endif // CONFIG_IDF_TARGET_* +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776 /**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ typedef enum { ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4 (ESP32), GPIO11 (ESP32-S2) */ @@ -57,6 +79,14 @@ typedef enum { ADC2_CHANNEL_9, /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */ ADC2_CHANNEL_MAX, } adc2_channel_t; +#elif CONFIG_IDF_TARGET_ESP32C3 +/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ +typedef enum { + ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */ + ADC2_CHANNEL_MAX, +} adc2_channel_t; +#endif + /** * @brief ADC rtc controller attenuation option. @@ -73,6 +103,13 @@ typedef enum { #define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11 #define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12 +#if CONFIG_IDF_TARGET_ESP32C3 +/** + * @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports + */ +#define ADC_MAX_DELAY UINT32_MAX +#endif + /** * @brief ADC digital controller encode option. * @@ -84,6 +121,20 @@ typedef enum { ADC_ENCODE_MAX, } adc_i2s_encode_t; +#if CONFIG_IDF_TARGET_ESP32C3 +//This feature is currently supported on ESP32C3, will be supported on other chips soon +/** + * @brief Digital ADC DMA configuration + */ +typedef struct adc_digi_init_config_s { + uint32_t max_store_buf_size; ///< Max length of the converted data that driver can store before they are processed. When this length is reached, driver will dump out all the old data and start to store them again. + uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt. + uint32_t dma_chan; ///< DMA channel. + uint16_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized. + uint16_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized. +} adc_digi_init_config_t; +#endif + /*--------------------------------------------------------------- Common setting ---------------------------------------------------------------*/ @@ -392,7 +443,8 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated)); /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ - +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 +//These APIs are only supported on ESP32 and ESP32-S2. On ESP32-C3 and later chips, please use ``adc_digi_initialize`` and ``adc_digi_deinitialize`` /** * @brief ADC digital controller initialization. * @return @@ -406,17 +458,78 @@ esp_err_t adc_digi_init(void); * - ESP_OK Success */ esp_err_t adc_digi_deinit(void); +#endif /** * @brief Setting the digital controller. * - * @param config Pointer to digital controller paramter. Refer to `adc_digi_config_t`. + * @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``. * * @return * - ESP_OK Success */ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config); +#if CONFIG_IDF_TARGET_ESP32C3 +//This feature is currently supported on ESP32C3, will be supported on other chips soon +/*--------------------------------------------------------------- + DMA setting +---------------------------------------------------------------*/ +/** + * @brief Initialize the Digital ADC. + * + * @param init_config Pointer to Digital ADC initilisation config. Refer to ``adc_digi_init_config_t``. + * + * @return + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags + * - ESP_ERR_NO_MEM If out of memory + * - ESP_OK On success + */ +esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config); + +/** + * @brief Start the Digital ADC and DMA peripherals. After this, the hardware starts working. + * + * @return + * - ESP_OK On success + */ +esp_err_t adc_digi_start(void); + +/** + * @brief Stop the Digital ADC and DMA peripherals. After this, the hardware stops working. + * + * @return + * - ESP_OK On success + */ +esp_err_t adc_digi_stop(void); + +/** + * @brief Read bytes from Digital ADC through DMA. + * + * @param[out] buf Buffer to read from ADC. + * @param[in] length_max Expected length of data read from the ADC. + * @param[out] out_length Real length of data read from the ADC via this API. + * @param[in] timeout_ms Time to wait for data via this API, in millisecond. + * + * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate. + * - ESP_ERR_TIMEOUT Operation timed out + * - ESP_OK On success + */ +esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms); + +/** + * @brief Deinitialize the Digital ADC. + * + * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. + * - ESP_OK On success + */ +esp_err_t adc_digi_deinitialize(void); + +#endif //#if CONFIG_IDF_TARGET_ESP32C3 + #ifdef __cplusplus } #endif diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index b2fa310e09..6b4b2654cb 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -13,7 +13,9 @@ // limitations under the License. #include "hal/adc_hal.h" +#if !CONFIG_IDF_TARGET_ESP32C3 #include "hal/adc_hal_conf.h" +#endif void adc_hal_init(void) { @@ -24,6 +26,7 @@ void adc_hal_init(void) adc_hal_pwdet_set_cct(SOC_ADC_PWDET_CCT_DEFAULT); adc_ll_digi_output_invert(ADC_NUM_1, SOC_ADC_DIGI_DATA_INVERT_DEFAULT(ADC_NUM_1)); adc_ll_digi_output_invert(ADC_NUM_2, SOC_ADC_DIGI_DATA_INVERT_DEFAULT(ADC_NUM_2)); + adc_ll_digi_set_clk_div(SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT); } void adc_hal_deinit(void) @@ -39,3 +42,84 @@ int adc_hal_convert(adc_ll_num_t adc_n, int channel, int *value) *value = adc_ll_rtc_get_convert_value(adc_n); return (int)adc_ll_rtc_analysis_raw_data(adc_n, (uint16_t)(*value)); } + +#if CONFIG_IDF_TARGET_ESP32C3 +//This feature is currently supported on ESP32C3, will be supported on other chips soon +/*--------------------------------------------------------------- + DMA setting +---------------------------------------------------------------*/ +void adc_hal_digi_dma_multi_descriptor(adc_dma_hal_config_t *dma_config, uint8_t *data_buf, uint32_t size, uint32_t num) +{ + assert(((uint32_t)data_buf % 4) == 0); + assert((size % 4) == 0); + dma_descriptor_t *desc = dma_config->rx_desc; + uint32_t n = 0; + + while (num--) { + desc[n].dw0.size = size; + desc[n].dw0.suc_eof = 0; + desc[n].dw0.owner = 1; + desc[n].buffer = data_buf; + desc[n].next = &desc[n+1]; + data_buf += size; + n++; + } + desc[n-1].next = NULL; +} + +void adc_hal_digi_rxdma_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) +{ + gdma_ll_rx_reset_channel(adc_dma_ctx->dev, dma_config->dma_chan); + gdma_ll_rx_set_desc_addr(adc_dma_ctx->dev, dma_config->dma_chan, (uint32_t)dma_config->rx_desc); + gdma_ll_rx_start(adc_dma_ctx->dev, dma_config->dma_chan); +} + +void adc_hal_digi_rxdma_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) +{ + gdma_ll_rx_stop(adc_dma_ctx->dev, dma_config->dma_chan); +} + +void adc_hal_digi_ena_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask) +{ + gdma_ll_enable_interrupt(adc_dma_ctx->dev, dma_config->dma_chan, mask, true); +} + +void adc_hal_digi_clr_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask) +{ + gdma_ll_clear_interrupt_status(adc_dma_ctx->dev, dma_config->dma_chan, mask); +} + +void adc_hal_digi_dis_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask) +{ + gdma_ll_enable_interrupt(adc_dma_ctx->dev, dma_config->dma_chan, mask, false); +} + +void adc_hal_digi_set_eof_num(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t num) +{ + adc_ll_digi_dma_set_eof_num(num); +} + +void adc_hal_digi_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) +{ + //Set to 1: the ADC data will be sent to the DMA + adc_ll_digi_dma_enable(); + //enable sar adc timer + adc_ll_digi_trigger_enable(); +} + +void adc_hal_digi_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) +{ + //Set to 0: the ADC data won't be sent to the DMA + adc_ll_digi_dma_disable(); + //disable sar adc timer + adc_ll_digi_trigger_disable(); +} + +void adc_hal_digi_init(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) +{ + adc_dma_ctx->dev = &GDMA; + gdma_ll_enable_clock(adc_dma_ctx->dev, true); + gdma_ll_clear_interrupt_status(adc_dma_ctx->dev, dma_config->dma_chan, UINT32_MAX); + gdma_ll_rx_connect_to_periph(adc_dma_ctx->dev, dma_config->dma_chan, GDMA_LL_TRIG_SRC_ADC_DAC); +} +#endif diff --git a/components/hal/esp32/adc_hal.c b/components/hal/esp32/adc_hal.c index 7d82dd44aa..5cda3e5bce 100644 --- a/components/hal/esp32/adc_hal.c +++ b/components/hal/esp32/adc_hal.c @@ -18,12 +18,6 @@ #include "hal/adc_hal_conf.h" #include "hal/adc_types.h" -void adc_hal_digi_init(void) -{ - adc_hal_init(); - adc_ll_digi_set_clk_div(SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT); -} - void adc_hal_digi_deinit(void) { adc_ll_digi_clear_pattern_table(ADC_NUM_1); diff --git a/components/hal/esp32c3/adc_hal.c b/components/hal/esp32c3/adc_hal.c index bf48c033bd..1b417f33e8 100644 --- a/components/hal/esp32c3/adc_hal.c +++ b/components/hal/esp32c3/adc_hal.c @@ -20,13 +20,6 @@ /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ - -void adc_hal_digi_init(void) -{ - adc_hal_init(); - adc_ll_digi_set_clk_div(SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT); -} - void adc_hal_digi_deinit(void) { adc_ll_digi_trigger_disable(); // boss @@ -40,37 +33,29 @@ void adc_hal_digi_deinit(void) adc_hal_deinit(); } +static inline void adc_set_init_code(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) +{ + uint32_t cal_val = adc_hal_calibration(adc_n, channel, atten, true, false); + adc_hal_set_calibration_param(adc_n, cal_val); +} + void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) { + //only one pattern table is supported on C3, but LL still needs one argument. + const int pattern_both = 0; + /* If enable digtal controller, adc xpd should always on. */ adc_ll_set_power_manage(ADC_POWER_SW_ON); - /* Single channel mode or multi channel mode. */ - adc_ll_digi_set_convert_mode(cfg->conv_mode); - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) { - if (cfg->adc1_pattern_len) { - adc_ll_digi_clear_pattern_table(ADC_NUM_1); - adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len); - for (int i = 0; i < cfg->adc1_pattern_len; i++) { - adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]); - } + if (cfg->adc_pattern_len) { + adc_ll_digi_clear_pattern_table(pattern_both); + adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len); + for (int i = 0; i < cfg->adc_pattern_len; i++) { + adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]); + adc_set_init_code(pattern_both, cfg->adc_pattern[i].channel, cfg->adc_pattern[i].atten); } } - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) { - if (cfg->adc2_pattern_len) { - adc_ll_digi_clear_pattern_table(ADC_NUM_2); - adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len); - for (int i = 0; i < cfg->adc2_pattern_len; i++) { - adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]); - } - } - } - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) { - adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG); - } - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) { - adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG); - } - adc_ll_digi_set_output_format(cfg->format); + + adc_ll_set_controller(pattern_both, ADC_CTRL_DIG); if (cfg->conv_limit_en) { adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); adc_ll_digi_convert_limit_enable(); @@ -80,7 +65,6 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) adc_ll_digi_set_trigger_interval(cfg->interval); adc_hal_digi_clk_config(&cfg->dig_clk); - adc_ll_digi_dma_set_eof_num(cfg->dma_eof_num); } /** @@ -154,27 +138,44 @@ void adc_hal_arbiter_config(adc_arbiter_t *config) /*--------------------------------------------------------------- ADC calibration setting ---------------------------------------------------------------*/ -#define ADC_HAL_CAL_TIMES (10) -#define ADC_HAL_CAL_OFFSET_RANGE (4096) -static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel) +#define ADC_HAL_CAL_OFFSET_RANGE (4096) +#define ADC_HAL_CAL_TIMES (10) + +static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} }; + +static uint32_t adc_hal_read_self_cal(adc_ll_num_t adc_n, int channel) { adc_ll_rtc_start_convert(adc_n, channel); while (adc_ll_rtc_convert_is_done(adc_n) != true); return (uint32_t)adc_ll_rtc_get_convert_value(adc_n); } -uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) +uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal) { - adc_hal_set_power_manage(ADC_POWER_SW_ON); + if (!force_cal) { + if (s_adc_cali_param[adc_n][atten]) { + return (uint32_t)s_adc_cali_param[adc_n][atten]; + } + } + uint32_t code_list[ADC_HAL_CAL_TIMES] = {0}; + uint32_t code_sum = 0; + uint32_t code_h = 0; + uint32_t code_l = 0; + uint32_t chk_code = 0; + uint32_t dout = 0; + + adc_hal_set_power_manage(ADC_POWER_SW_ON); if (adc_n == ADC_NUM_2) { adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); adc_hal_arbiter_config(&config); } adc_hal_set_controller(adc_n, ADC_CTRL_RTC); //Set controller + // adc_hal_arbiter_config(adc_arbiter_t *config) adc_ll_calibration_prepare(adc_n, channel, internal_gnd); + /* Enable/disable internal connect GND (for calibration). */ if (internal_gnd) { adc_ll_rtc_disable_channel(adc_n, channel); @@ -184,31 +185,25 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc adc_ll_set_atten(adc_n, channel, atten); } - uint32_t code_list[ADC_HAL_CAL_TIMES] = {0}; - uint32_t code_sum = 0; - uint32_t code_h = 0; - uint32_t code_l = 0; - uint32_t chk_code = 0; - for (uint8_t rpt = 0 ; rpt < ADC_HAL_CAL_TIMES ; rpt ++) { code_h = ADC_HAL_CAL_OFFSET_RANGE; code_l = 0; chk_code = (code_h + code_l) / 2; adc_ll_set_calibration_param(adc_n, chk_code); - uint32_t self_cal = read_cal_channel(adc_n, channel); + dout = adc_hal_read_self_cal(adc_n, channel); while (code_h - code_l > 1) { - if (self_cal == 0) { + if (dout == 0) { code_h = chk_code; } else { code_l = chk_code; } chk_code = (code_h + code_l) / 2; adc_ll_set_calibration_param(adc_n, chk_code); - self_cal = read_cal_channel(adc_n, channel); + dout = adc_hal_read_self_cal(adc_n, channel); if ((code_h - code_l == 1)) { chk_code += 1; adc_ll_set_calibration_param(adc_n, chk_code); - self_cal = read_cal_channel(adc_n, channel); + dout = adc_hal_read_self_cal(adc_n, channel); } } code_list[rpt] = chk_code; @@ -225,10 +220,12 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc } } chk_code = code_h + code_l; - uint32_t ret = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4) + dout = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4) ? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) : (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1; + adc_ll_set_calibration_param(adc_n, dout); adc_ll_calibration_finish(adc_n); - return ret; + s_adc_cali_param[adc_n][atten] = (uint16_t)dout; + return dout; } diff --git a/components/hal/esp32c3/include/hal/adc_hal.h b/components/hal/esp32c3/include/hal/adc_hal.h index 962528b4ab..9055be8868 100644 --- a/components/hal/esp32c3/include/hal/adc_hal.h +++ b/components/hal/esp32c3/include/hal/adc_hal.h @@ -34,11 +34,6 @@ extern "C" { /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ -/** - * Digital controller initialization. - */ -void adc_hal_digi_init(void); - /** * Digital controller deinitialization. */ diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h new file mode 100644 index 0000000000..aba319b621 --- /dev/null +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -0,0 +1,975 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include "soc/adc_periph.h" +#include "hal/adc_types.h" +#include "soc/apb_saradc_struct.h" +#include "soc/apb_saradc_reg.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/rtc_cntl_reg.h" +#include "regi2c_ctrl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ADC_NUM_1 = 0, /*!< SAR ADC 1 */ + ADC_NUM_2 = 1, /*!< SAR ADC 2 */ + ADC_NUM_MAX, +} adc_ll_num_t; + +typedef enum { + ADC_POWER_BY_FSM, /*!< ADC XPD controled by FSM. Used for polling mode */ + ADC_POWER_SW_ON, /*!< ADC XPD controled by SW. power on. Used for DMA mode */ + ADC_POWER_SW_OFF, /*!< ADC XPD controled by SW. power off. */ + ADC_POWER_MAX, /*!< For parameter check. */ +} adc_ll_power_t; + +typedef enum { + ADC_RTC_DATA_OK = 0, + ADC_RTC_CTRL_UNSELECTED = 1, + ADC_RTC_CTRL_BREAK = 2, + ADC_RTC_DATA_FAIL = -1, +} adc_ll_rtc_raw_data_t; + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +/** + * @brief Analyze whether the obtained raw data is correct. + * ADC2 use arbiter by default. The arbitration result can be judged by the flag bit in the original data. + * + */ +typedef struct { + union { + struct { + uint16_t data: 13; /*! 0), The data is invalid. */ + }; + uint16_t val; + }; +} adc_ll_rtc_output_data_t; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + +/** + * @brief ADC controller type selection. + * + * @note For ADC2, use the force option with care. The system power consumption detection will use ADC2. + * If it is forced to switch to another controller, it may cause the system to obtain incorrect values. + * @note Normally, there is no need to switch the controller manually. + */ +typedef enum { + ADC_CTRL_RTC = 0, /*!> offset)); // clear old data + tab |= ((uint32_t)pattern.val << 18) >> offset; // Fill in the new data + APB_SARADC.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back + +} + +/** + * Reset the pattern table pointer, then take the measurement rule from table header in next measurement. + * + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_clear_pattern_table(adc_ll_num_t adc_n) +{ + /* + * channel 可以配置为0~6, 其中 0~4 代表 ADC1 , 5 代表 ADC2 , 6 代表有 EN_TEST 的测试选项,可以采样内部的一些电压信号 + */ + APB_SARADC.ctrl.sar_patt_p_clear = 1; + APB_SARADC.ctrl.sar_patt_p_clear = 0; +} + +/** + * Sets the number of cycles required for the conversion to complete and wait for the arbiter to stabilize. + * + * @note Only ADC2 have arbiter function. + * @param cycle range: 0 ~ 4. + */ +static inline void adc_ll_digi_set_arbiter_stable_cycle(uint32_t cycle) +{ + APB_SARADC.ctrl.wait_arb_cycle = cycle; +} + +/** + * ADC Digital controller output data invert or not. + * + * @param adc_n ADC unit. + * @param inv_en data invert or not. + */ +static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en) +{ + if (adc_n == ADC_NUM_1) { + APB_SARADC.ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert + } else { // adc_n == ADC_NUM_2 + APB_SARADC.ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert + } +} + +/** + * Sets the number of interval clock cycles for the digital controller to trigger the measurement. + * + * @note The trigger interval should not be less than the sampling time of the SAR ADC. + * @param cycle The number of clock cycles for the trigger interval. The unit is the divided clock. Range: 40 ~ 4095. + */ +static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle) +{ + APB_SARADC.ctrl2.timer_target = cycle; +} + +/** + * Enable digital controller timer to trigger the measurement. + */ +static inline void adc_ll_digi_trigger_enable(void) +{ + APB_SARADC.ctrl2.timer_en = 1; +} + +/** + * Disable digital controller timer to trigger the measurement. + */ +static inline void adc_ll_digi_trigger_disable(void) +{ + APB_SARADC.ctrl2.timer_en = 0; +} + +/** + * Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock. + * Expression: controller_clk = APLL/APB * (div_num + div_b / div_a). + * + * @param div_num Division factor. Range: 1 ~ 255. + * @param div_b Division factor. Range: 1 ~ 63. + * @param div_a Division factor. Range: 1 ~ 63. + */ +static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) +{ + APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; + APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; +} + +/** + * Enable clock and select clock source for ADC digital controller. + * + * @param use_apll true: use APLL clock; false: use APB clock. + */ +static inline void adc_ll_digi_controller_clk_enable(bool use_apll) +{ + if (use_apll) { + APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock + } else { + APB_SARADC.apb_adc_clkm_conf.clk_sel = 2; // APB clock + } + APB_SARADC.ctrl.sar_clk_gated = 1; +} + +/** + * Disable clock for ADC digital controller. + */ +static inline void adc_ll_digi_controller_clk_disable(void) +{ + APB_SARADC.ctrl.sar_clk_gated = 0; + APB_SARADC.apb_adc_clkm_conf.clk_sel = 0; +} + +/** + * Reset adc digital controller filter. + * + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_filter_reset(adc_ll_num_t adc_n) +{ + APB_SARADC.filter_ctrl0.filter_reset = 1; +} + +/** + * Set adc digital controller filter factor. + * + * @param adc_n ADC unit. + * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). + */ +static inline void adc_ll_digi_filter_set_factor(adc_ll_num_t adc_n, adc_digi_filter_mode_t factor) +{ + adc_channel_t channel = 0; + if (!APB_SARADC.filter_ctrl0.filter_channel0) { + APB_SARADC.filter_ctrl0.filter_channel0 = (adc_n<<4) | channel; + APB_SARADC.filter_ctrl1.filter_factor0 = factor; + } else if (!APB_SARADC.filter_ctrl0.filter_channel1) { + APB_SARADC.filter_ctrl0.filter_channel1 = (adc_n<<4) | channel; + APB_SARADC.filter_ctrl1.filter_factor1 = factor; + } +} + +/** + * Get adc digital controller filter factor. + * + * @param adc_n ADC unit. + * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). + */ +static inline void adc_ll_digi_filter_get_factor(adc_ll_num_t adc_n, adc_digi_filter_mode_t *factor) +{ + abort(); // TODO ESP32-C3 IDF-2528 +} + +/** + * Enable/disable adc digital controller filter. + * Filtering the ADC data to obtain smooth data at higher sampling rates. + * + * @note The filter will filter all the enabled channel data of the each ADC unit at the same time. + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_filter_enable(adc_ll_num_t adc_n, bool enable) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Get the filtered data of adc digital controller filter. + * The data after each measurement and filtering is updated to the DMA by the digital controller. But it can also be obtained manually through this API. + * + * @note The filter will filter all the enabled channel data of the each ADC unit at the same time. + * @param adc_n ADC unit. + * @return Filtered data. + */ +static inline uint32_t adc_ll_digi_filter_read_data(adc_ll_num_t adc_n) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Set monitor mode of adc digital controller. + * + * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. + * @param adc_n ADC unit. + * @param is_larger true: If ADC_OUT > threshold, Generates monitor interrupt. + * false: If ADC_OUT < threshold, Generates monitor interrupt. + */ +static inline void adc_ll_digi_monitor_set_mode(adc_ll_num_t adc_n, bool is_larger) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Set monitor threshold of adc digital controller. + * + * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. + * @param adc_n ADC unit. + * @param threshold Monitor threshold. + */ +static inline void adc_ll_digi_monitor_set_thres(adc_ll_num_t adc_n, uint32_t threshold) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Enable/disable monitor of adc digital controller. + * + * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_monitor_enable(adc_ll_num_t adc_n, bool enable) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Enable interrupt of adc digital controller by bitmask. + * + * @param adc_n ADC unit. + * @param intr Interrupt bitmask. + */ +static inline void adc_ll_digi_intr_enable(adc_ll_num_t adc_n, adc_digi_intr_t intr) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Disable interrupt of adc digital controller by bitmask. + * + * @param adc_n ADC unit. + * @param intr Interrupt bitmask. + */ +static inline void adc_ll_digi_intr_disable(adc_ll_num_t adc_n, adc_digi_intr_t intr) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Clear interrupt of adc digital controller by bitmask. + * + * @param adc_n ADC unit. + * @param intr Interrupt bitmask. + */ +static inline void adc_ll_digi_intr_clear(adc_ll_num_t adc_n, adc_digi_intr_t intr) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Get interrupt status mask of adc digital controller. + * + * @param adc_n ADC unit. + * @return + * - intr Interrupt bitmask. + */ +static inline uint32_t adc_ll_digi_get_intr_status(adc_ll_num_t adc_n) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Set DMA eof num of adc digital controller. + * If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated. + * + * @param num eof num of DMA. + */ +static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) +{ + APB_SARADC.dma_conf.apb_adc_eof_num = num; +} + +/** + * Enable output data to DMA from adc digital controller. + */ +static inline void adc_ll_digi_dma_enable(void) +{ + APB_SARADC.dma_conf.apb_adc_trans = 1; +} + +/** + * Disable output data to DMA from adc digital controller. + */ +static inline void adc_ll_digi_dma_disable(void) +{ + APB_SARADC.dma_conf.apb_adc_trans = 0; +} + +/** + * Reset adc digital controller. + */ +static inline void adc_ll_digi_reset(void) +{ + APB_SARADC.dma_conf.apb_adc_reset_fsm = 1; + APB_SARADC.dma_conf.apb_adc_reset_fsm = 0; +} + +/*--------------------------------------------------------------- + PWDET(Power detect) controller setting +---------------------------------------------------------------*/ +/** + * Set adc cct for PWDET controller. + * + * @note Capacitor tuning of the PA power monitor. cct set to the same value with PHY. + * @param cct Range: 0 ~ 7. + */ +static inline void adc_ll_pwdet_set_cct(uint32_t cct) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Get adc cct for PWDET controller. + * + * @note Capacitor tuning of the PA power monitor. cct set to the same value with PHY. + * @return cct Range: 0 ~ 7. + */ +static inline uint32_t adc_ll_pwdet_get_cct(void) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/*--------------------------------------------------------------- + RTC controller setting +---------------------------------------------------------------*/ +/** + * Set adc output data format for RTC controller. + * + * @note ESP32S2 RTC controller only support 13bit. + * @prarm adc_n ADC unit. + * @prarm bits Output data bits width option. + */ +static inline void adc_ll_rtc_set_output_format(adc_ll_num_t adc_n, adc_bits_width_t bits) +{ + return; +} + +/** + * Enable adc channel to start convert. + * + * @note Only one channel can be selected for once measurement. + * + * @param adc_n ADC unit. + * @param channel ADC channel number for each ADCn. + */ +static inline void adc_ll_rtc_enable_channel(adc_ll_num_t adc_n, int channel) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Disable adc channel to start convert. + * + * @note Only one channel can be selected in once measurement. + * + * @param adc_n ADC unit. + * @param channel ADC channel number for each ADCn. + */ +static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n, int channel) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Start conversion once by software for RTC controller. + * + * @note It may be block to wait conversion idle for ADC1. + * + * @param adc_n ADC unit. + * @param channel ADC channel number for each ADCn. + */ +static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Check the conversion done flag for each ADCn for RTC controller. + * + * @param adc_n ADC unit. + * @return + * -true : The conversion process is finish. + * -false : The conversion process is not finish. + */ +static inline bool adc_ll_rtc_convert_is_done(adc_ll_num_t adc_n) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Get the converted value for each ADCn for RTC controller. + * + * @param adc_n ADC unit. + * @return + * - Converted value. + */ +static inline int adc_ll_rtc_get_convert_value(adc_ll_num_t adc_n) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * ADC module RTC output data invert or not. + * + * @param adc_n ADC unit. + * @param inv_en data invert or not. + */ +static inline void adc_ll_rtc_output_invert(adc_ll_num_t adc_n, bool inv_en) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Enable ADCn conversion complete interrupt for RTC controller. + * + * @param adc_n ADC unit. + */ +static inline void adc_ll_rtc_intr_enable(adc_ll_num_t adc_n) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Disable ADCn conversion complete interrupt for RTC controller. + * + * @param adc_n ADC unit. + */ +static inline void adc_ll_rtc_intr_disable(adc_ll_num_t adc_n) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Reset RTC controller FSM. + */ +static inline void adc_ll_rtc_reset(void) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Sets the number of cycles required for the conversion to complete and wait for the arbiter to stabilize. + * + * @note Only ADC2 have arbiter function. + * @param cycle range: [0,4]. + */ +static inline void adc_ll_rtc_set_arbiter_stable_cycle(uint32_t cycle) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Analyze whether the obtained raw data is correct. + * ADC2 can use arbiter. The arbitration result can be judged by the flag bit in the original data. + * + * @param adc_n ADC unit. + * @param raw_data ADC raw data input (convert value). + * @return + * - 0: The data is correct to use. + * - 1: The data is invalid. The current controller is not enabled by the arbiter. + * - 2: The data is invalid. The current controller process was interrupted by a higher priority controller. + * - -1: The data is error. + */ +static inline adc_ll_rtc_raw_data_t adc_ll_rtc_analysis_raw_data(adc_ll_num_t adc_n, uint16_t raw_data) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/*--------------------------------------------------------------- + Common setting +---------------------------------------------------------------*/ +/** + * Set ADC module power management. + * + * @param manage Set ADC power status. + */ +static inline void adc_ll_set_power_manage(adc_ll_power_t manage) +{ + // /* Bit1 0:Fsm 1: SW mode + // Bit0 0:SW mode power down 1: SW mode power on */ + if (manage == ADC_POWER_SW_ON) { + APB_SARADC.ctrl.sar_clk_gated = 1; + APB_SARADC.ctrl.xpd_sar_force = SENS_FORCE_XPD_SAR_PU; + } else if (manage == ADC_POWER_BY_FSM) { + APB_SARADC.ctrl.sar_clk_gated = 1; + APB_SARADC.ctrl.xpd_sar_force = SENS_FORCE_XPD_SAR_FSM; + } else if (manage == ADC_POWER_SW_OFF) { + APB_SARADC.ctrl.xpd_sar_force = SENS_FORCE_XPD_SAR_PD; + APB_SARADC.ctrl.sar_clk_gated = 1; + } +} + +/** + * Get ADC module power management. + * + * @return + * - ADC power status. + */ +static inline adc_ll_power_t adc_ll_get_power_manage(void) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`. + * + * @param div Division factor. + */ +static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Set the attenuation of a particular channel on ADCn. + * + * @note For any given channel, this function must be called before the first time conversion. + * + * The default ADC full-scale voltage is 1.1V. To read higher voltages (up to the pin maximum voltage, + * usually 3.3V) requires setting >0dB signal attenuation for that ADC channel. + * + * When VDD_A is 3.3V: + * + * - 0dB attenuaton (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V + * - 2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V + * - 6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V + * - 11dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9V (see note below) + * + * @note The full-scale voltage is the voltage corresponding to a maximum reading (depending on ADC1 configured + * bit width, this value is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.) + * + * @note At 11dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage. + * + * Due to ADC characteristics, most accurate results are obtained within the following approximate voltage ranges: + * + * - 0dB attenuaton (ADC_ATTEN_DB_0) between 100 and 950mV + * - 2.5dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250mV + * - 6dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750mV + * - 11dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450mV + * + * For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges. + * + * @param adc_n ADC unit. + * @param channel ADCn channel number. + * @param atten The attenuation option. + */ +static inline void adc_ll_set_atten(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Get the attenuation of a particular channel on ADCn. + * + * @param adc_n ADC unit. + * @param channel ADCn channel number. + * @return atten The attenuation option. + */ +static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t channel) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Set ADC module controller. + * There are five SAR ADC controllers: + * Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes; + * Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep; + * the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2. + * + * @param adc_n ADC unit. + * @param ctrl ADC controller. + */ +static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Set ADC2 module arbiter work mode. + * The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, + * the low priority controller will read the invalid ADC data, and the validity of the data can be judged by the flag bit in the data. + * + * @note Only ADC2 support arbiter. + * @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode. + * + * @param mode Refer to `adc_arbiter_mode_t`. + */ +static inline void adc_ll_set_arbiter_work_mode(adc_arbiter_mode_t mode) +{ + SENS.sar_meas2_mux.sar2_rtc_force = 0; // Enable arbiter in wakeup mode + if (mode == ADC_ARB_MODE_FIX) { + APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 0; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_fix_priority = 1; + } else if (mode == ADC_ARB_MODE_LOOP) { + APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 0; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_fix_priority = 0; + } else { + APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 1; // Shield arbiter. + } +} + +/** + * Set ADC2 module controller priority in arbiter. + * The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, + * the low priority controller will read the invalid ADC data, and the validity of the data can be judged by the flag bit in the data. + * + * @note Only ADC2 support arbiter. + * @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode. + * @note Default priority: Wi-Fi(2) > RTC(1) > Digital(0); + * + * @param pri_rtc RTC controller priority. Range: 0 ~ 2. + * @param pri_dig Digital controller priority. Range: 0 ~ 2. + * @param pri_pwdet Wi-Fi controller priority. Range: 0 ~ 2. + */ +static inline void adc_ll_set_arbiter_priority(uint8_t pri_rtc, uint8_t pri_dig, uint8_t pri_pwdet) +{ + if (pri_rtc != pri_dig && pri_rtc != pri_pwdet && pri_dig != pri_pwdet) { + APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_priority = pri_rtc; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_priority = pri_dig; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_priority = pri_pwdet; + } + /* Should select highest priority controller. */ + if (pri_rtc > pri_dig) { + if (pri_rtc > pri_pwdet) { + APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 1; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 0; + } else { + APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 1; + } + } else { + if (pri_dig > pri_pwdet) { + APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 1; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 0; + } else { + APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0; + APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 1; + } + } +} + +/** + * Force switch ADC2 to RTC controller in sleep mode. Shield arbiter. + * In sleep mode, the arbiter is in power-down mode. + * Need to switch the controller to RTC to shield the control of the arbiter. + * After waking up, it needs to switch to arbiter control. + * + * @note The hardware will do this automatically. In normal use, there is no need to call this interface to manually switch the controller. + * @note Only support ADC2. + */ +static inline void adc_ll_enable_sleep_controller(void) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/** + * Force switch ADC2 to arbiter in wakeup mode. + * In sleep mode, the arbiter is in power-down mode. + * Need to switch the controller to RTC to shield the control of the arbiter. + * After waking up, it needs to switch to arbiter control. + * + * @note The hardware will do this automatically. In normal use, there is no need to call this interface to manually switch the controller. + * @note Only support ADC2. + */ +static inline void adc_ll_disable_sleep_controller(void) +{ + abort(); // TODO ESP32-C3 IDF-2094 +} + +/* ADC calibration code. */ +#define ADC_HAL_CAL_OFFSET_RANGE (4096) +#define ADC_HAL_CAL_TIMES (10) + +/** + * Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration. + * + * @note Different ADC units and different attenuation options use different calibration data (initial data). + * + * @param adc_n ADC index number. + * @param channel adc channel number. + * @param internal_gnd true: Disconnect from the IO port and use the internal GND as the calibration voltage. + * false: Use IO external voltage as calibration voltage. + */ +static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t channel, bool internal_gnd) +{ + // /* Enable i2s_write_reg function. */ + // void phy_get_romfunc_addr(void); + // phy_get_romfunc_addr(); + // //CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M); + // //SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); + // CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18)); + // SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16)); + + // /* Enable/disable internal connect GND (for calibration). */ + // if (adc_n == ADC_NUM_1) { + // REGI2C_WRITE_MASK(I2C_ADC, SAR1_DREF_ADDR, 4); + // if (internal_gnd) { + // REGI2C_WRITE_MASK(I2C_ADC, SAR1_ENCAL_GND_ADDR, 1); + // } else { + // REGI2C_WRITE_MASK(I2C_ADC, SAR1_ENCAL_GND_ADDR, 0); + // } + // } else { + // REGI2C_WRITE_MASK(I2C_ADC, SAR2_DREF_ADDR, 4); + // if (internal_gnd) { + // REGI2C_WRITE_MASK(I2C_ADC, SAR2_ENCAL_GND_ADDR, 1); + // } else { + // REGI2C_WRITE_MASK(I2C_ADC, SAR2_ENCAL_GND_ADDR, 0); + // } + // } +} + +/** + * Resume register status after calibration. + * + * @param adc_n ADC index number. + */ +static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n) +{ + // if (adc_n == ADC_NUM_1) { + // REGI2C_WRITE_MASK(I2C_ADC, SAR1_ENCAL_GND_ADDR, 0); + // } else { + // REGI2C_WRITE_MASK(I2C_ADC, SAR2_ENCAL_GND_ADDR, 0); + // } +} + +/** + * Set the calibration result to ADC. + * + * @note Different ADC units and different attenuation options use different calibration data (initial data). + * + * @param adc_n ADC index number. + */ +static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t param) +{ + // uint8_t msb = param >> 8; + // uint8_t lsb = param & 0xFF; + // /* Enable i2s_write_reg function. */ + // void phy_get_romfunc_addr(void); + // phy_get_romfunc_addr(); + // //SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); + // CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18)); + // SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16)); + + // if (adc_n == ADC_NUM_1) { + // REGI2C_WRITE_MASK(I2C_ADC, SAR1_INITIAL_CODE_HIGH_ADDR, msb); + // REGI2C_WRITE_MASK(I2C_ADC, SAR1_INITIAL_CODE_LOW_ADDR, lsb); + // } else { + // REGI2C_WRITE_MASK(I2C_ADC, SAR2_INITIAL_CODE_HIGH_ADDR, msb); + // REGI2C_WRITE_MASK(I2C_ADC, SAR2_INITIAL_CODE_LOW_ADDR, lsb); + // } +} +/* Temp code end. */ + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/adc_hal.c b/components/hal/esp32s2/adc_hal.c index 5797b677d7..e2eb67e27b 100644 --- a/components/hal/esp32s2/adc_hal.c +++ b/components/hal/esp32s2/adc_hal.c @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// The HAL layer for ADC (esp32s2 specific part) +// The HAL layer for ADC (ESP32-S2 specific part) #include "sdkconfig.h" #include "hal/adc_hal.h" @@ -23,13 +23,6 @@ /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ - -void adc_hal_digi_init(void) -{ - adc_hal_init(); - adc_ll_digi_set_clk_div(SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT); -} - void adc_hal_digi_deinit(void) { adc_ll_digi_trigger_disable(); // boss diff --git a/components/hal/esp32s2/include/hal/adc_ll.h b/components/hal/esp32s2/include/hal/adc_ll.h index cf4cd6e5eb..7eedf5b936 100644 --- a/components/hal/esp32s2/include/hal/adc_ll.h +++ b/components/hal/esp32s2/include/hal/adc_ll.h @@ -49,7 +49,7 @@ typedef struct { }; uint16_t val; }; -} adc_rtc_output_data_t; +} adc_ll_rtc_output_data_t; /** * @brief ADC controller type selection. @@ -67,7 +67,7 @@ typedef enum { ADC2_CTRL_FORCE_RTC = 4, /*!flag == 0) { return ADC_RTC_DATA_OK; } else if (temp->flag == 1) { @@ -980,7 +980,7 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha * @param adc_n ADC unit. * @param ctrl ADC controller. */ -static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_controller_t ctrl) +static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl) { if (adc_n == ADC_NUM_1) { switch ( ctrl ) { diff --git a/components/hal/esp32s3/include/hal/adc_hal.h b/components/hal/esp32s3/include/hal/adc_hal.h index 1eaf7e72b8..25b85eede8 100644 --- a/components/hal/esp32s3/include/hal/adc_hal.h +++ b/components/hal/esp32s3/include/hal/adc_hal.h @@ -34,11 +34,6 @@ extern "C" { /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ -/** - * Digital controller initialization. - */ -void adc_hal_digi_init(void); - /** * Digital controller deinitialization. */ diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index 8a79ea6f0e..b37575193a 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -64,7 +64,7 @@ typedef struct { }; uint16_t val; }; -} adc_rtc_output_data_t; +} adc_ll_rtc_output_data_t; #ifdef _MSC_VER #pragma pack(pop) @@ -86,7 +86,7 @@ typedef enum { ADC2_CTRL_FORCE_RTC = 4, /*!flag == 0) { return ADC_RTC_DATA_OK; } else if (temp->flag == 1) { @@ -872,7 +872,7 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha * @param adc_n ADC unit. * @param ctrl ADC controller. */ -static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_controller_t ctrl) +static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl) { if (adc_n == ADC_NUM_1) { switch ( ctrl ) { diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index 3a0a5a5c55..a2cfe407dc 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -185,11 +185,6 @@ int adc_hal_convert(adc_ll_num_t adc_n, int channel, int *value); /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ -/** - * Digital controller initialization. - */ -void adc_hal_digi_init(void); - /** * Digital controller deinitialization. */ @@ -208,3 +203,46 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg); * @param adc_n ADC unit. */ #define adc_hal_digi_clear_pattern_table(adc_n) adc_ll_digi_clear_pattern_table(adc_n) + +#if CONFIG_IDF_TARGET_ESP32C3 +/*--------------------------------------------------------------- + DMA setting +---------------------------------------------------------------*/ +#include "soc/gdma_struct.h" +#include "hal/gdma_ll.h" +#include "hal/dma_types.h" +#include "hal/adc_ll.h" +#include "hal/dma_types.h" + +typedef struct adc_dma_hal_context_t { + gdma_dev_t *dev; //address of the general DMA +} adc_dma_hal_context_t; + +typedef struct adc_dma_hal_config_t { + dma_descriptor_t *rx_desc; //dma descriptor + dma_descriptor_t *cur_desc_ptr; //pointer to the current descriptor + uint32_t desc_max_num; //number of the descriptors linked once + uint32_t desc_cnt; + uint32_t dma_chan; +} adc_dma_hal_config_t; + +void adc_hal_digi_dma_multi_descriptor(adc_dma_hal_config_t *dma_config, uint8_t *data_buf, uint32_t size, uint32_t num); + +void adc_hal_digi_rxdma_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); + +void adc_hal_digi_rxdma_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); + +void adc_hal_digi_ena_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask); + +void adc_hal_digi_clr_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask); + +void adc_hal_digi_dis_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask); + +void adc_hal_digi_set_eof_num(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t num); + +void adc_hal_digi_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); + +void adc_hal_digi_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); + +void adc_hal_digi_init(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); +#endif //#if CONFIG_IDF_TARGET_ESP32C3 diff --git a/components/hal/include/hal/adc_types.h b/components/hal/include/hal/adc_types.h index bbe3d08e2f..6f6f0e9613 100644 --- a/components/hal/include/hal/adc_types.h +++ b/components/hal/include/hal/adc_types.h @@ -95,6 +95,7 @@ typedef enum { ADC_WIDTH_MAX, } adc_bits_width_t; + /** * @brief ADC digital controller (DMA mode) work mode. * @@ -123,16 +124,21 @@ typedef struct { 1: measurement range 0 - 1100mV, 2: measurement range 0 - 1350mV, 3: measurement range 0 - 2600mV. */ -#ifdef CONFIG_IDF_TARGET_ESP32 +#if CONFIG_IDF_TARGET_ESP32 uint8_t bit_width: 2; /*!< ADC resolution. - 0: 9 bit; - 1: 10 bit; - 2: 11 bit; - 3: 12 bit. */ -#else + int8_t channel: 4; /*!< ADC channel index. */ +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + uint8_t reserved: 2; /*!< reserved0 */ + uint8_t channel: 4; /*!< ADC channel index. */ +#elif CONFIG_IDF_TARGET_ESP32C3 + uint8_t channel: 3; /*!< ADC channel index. */ + uint8_t unit: 1; /*!< ADC unit index. */ uint8_t reserved: 2; /*!< reserved0 */ #endif - uint8_t channel: 4; /*!< ADC channel index. */ }; uint8_t val; /*! ADC_CHANNEL_MAX), The data is invalid. */ + uint32_t unit: 1; /*! Date: Mon, 23 Nov 2020 15:35:09 +0800 Subject: [PATCH 3/9] rtc: add function to en/disable the rtc clock --- components/esp_hw_support/CMakeLists.txt | 8 ++- components/esp_hw_support/clk_ctrl_os.c | 56 +++++++++++++++++++ components/esp_hw_support/component.mk | 4 ++ .../esp_hw_support/include/soc/clk_ctrl_os.h | 50 +++++++++++++++++ .../esp_hw_support/port/esp32/rtc_clk.c | 13 +++++ .../esp_hw_support/port/esp32/rtc_time.c | 8 +++ .../esp_hw_support/port/esp32c3/rtc_clk.c | 13 +++++ .../esp_hw_support/port/esp32c3/rtc_time.c | 8 +++ .../esp_hw_support/port/esp32s2/rtc_clk.c | 13 +++++ .../esp_hw_support/port/esp32s2/rtc_time.c | 8 +++ .../esp_hw_support/port/esp32s3/rtc_clk.c | 13 +++++ .../esp_hw_support/port/esp32s3/rtc_time.c | 8 +++ components/soc/esp32/include/soc/rtc.h | 23 ++++++++ components/soc/esp32c3/include/soc/rtc.h | 23 ++++++++ components/soc/esp32s2/include/soc/rtc.h | 23 ++++++++ components/soc/esp32s3/include/soc/rtc.h | 23 ++++++++ 16 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 components/esp_hw_support/clk_ctrl_os.c create mode 100644 components/esp_hw_support/include/soc/clk_ctrl_os.h diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 4119a1ede6..7b8994d950 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -5,8 +5,12 @@ if(${target} STREQUAL "esp32") list(APPEND requires efuse) endif() -idf_component_register(SRCS "compare_set.c" - "cpu_util.c" +set(srcs "compare_set.c" "cpu_util.c") +if(NOT BOOTLOADER_BUILD) + list(APPEND srcs "clk_ctrl_os.c") +endif() + +idf_component_register(SRCS ${srcs} INCLUDE_DIRS include REQUIRES ${requires} PRIV_REQUIRES efuse diff --git a/components/esp_hw_support/clk_ctrl_os.c b/components/esp_hw_support/clk_ctrl_os.c new file mode 100644 index 0000000000..ae1d42c0ed --- /dev/null +++ b/components/esp_hw_support/clk_ctrl_os.c @@ -0,0 +1,56 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "soc/clk_ctrl_os.h" + +#define DELAY_RTC_CLK_SWITCH 5 + +static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED; + +static uint8_t s_periph_ref_counts = 0; +static uint32_t s_rtc_clk_freq = 0; // Frequency of the 8M/256 clock in Hz + +bool periph_rtc_dig_clk8m_enable(void) +{ + portENTER_CRITICAL(&periph_spinlock); + if (s_periph_ref_counts == 0) { + rtc_dig_clk8m_enable(); + s_rtc_clk_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, 100)); + if (s_rtc_clk_freq == 0) { + portEXIT_CRITICAL(&periph_spinlock); + return false; + } + } + s_periph_ref_counts++; + portEXIT_CRITICAL(&periph_spinlock); + return true; +} + +uint32_t periph_rtc_dig_clk8m_get_freq(void) +{ + return s_rtc_clk_freq * 256; +} + +void periph_rtc_dig_clk8m_disable(void) +{ + portENTER_CRITICAL(&periph_spinlock); + assert(s_periph_ref_counts > 0); + s_periph_ref_counts--; + if (s_periph_ref_counts == 0) { + s_rtc_clk_freq = 0; + rtc_dig_clk8m_disable(); + } + portEXIT_CRITICAL(&periph_spinlock); +} diff --git a/components/esp_hw_support/component.mk b/components/esp_hw_support/component.mk index b1674229b3..da4d6c1e71 100644 --- a/components/esp_hw_support/component.mk +++ b/components/esp_hw_support/component.mk @@ -2,3 +2,7 @@ COMPONENT_SRCDIRS := . port/$(IDF_TARGET) COMPONENT_ADD_INCLUDEDIRS := . include port/$(IDF_TARGET)/private_include port/$(IDF_TARGET)/rtc_clk.o: CFLAGS += -fno-jump-tables -fno-tree-switch-conversion + +ifdef IS_BOOTLOADER_BUILD +COMPONENT_OBJEXCLUDE += clk_ctrl_os.o +endif diff --git a/components/esp_hw_support/include/soc/clk_ctrl_os.h b/components/esp_hw_support/include/soc/clk_ctrl_os.h new file mode 100644 index 0000000000..f4d769b801 --- /dev/null +++ b/components/esp_hw_support/include/soc/clk_ctrl_os.h @@ -0,0 +1,50 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "soc/rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief This function is used to enable the digital 8m rtc clock, + * to support the peripherals. + * + * @note If this function is called a number of times, the `periph_rtc_dig_clk8m_disable` + * function needs to be called same times to disable. + * + * @return true: success for enable the rtc 8M clock, false: rtc 8M clock enable failed + */ +bool periph_rtc_dig_clk8m_enable(void); + +/** + * @brief This function is used to disable the rtc digital clock, which should be called + * with the `periph_rtc_dig_clk8m_enable` pairedly + * + * @note If this function is called a number of times, the `periph_rtc_dig_clk8m_disable` + * function needs to be called same times to disable. + */ +void periph_rtc_dig_clk8m_disable(void); + +/** + * @brief This function is used to get the real clock frequency value of the rtc clock + * + * @return The real clock value + */ +uint32_t periph_rtc_dig_clk8m_get_freq(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index 2dac3a9c93..75c94f7fe7 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -101,6 +101,7 @@ #define RTC_PLL_FREQ_320M 320 #define RTC_PLL_FREQ_480M 480 +#define DELAY_RTC_CLK_SWITCH 5 static void rtc_clk_cpu_freq_to_8m(void); static void rtc_clk_bbpll_disable(void); @@ -773,6 +774,18 @@ uint32_t rtc_clk_apb_freq_get(void) return freq_hz - remainder; } +void rtc_dig_clk8m_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); +} + +void rtc_dig_clk8m_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); +} + /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_hw_support/port/esp32/rtc_time.c b/components/esp_hw_support/port/esp32/rtc_time.c index 0d2433d52c..99539e0d55 100644 --- a/components/esp_hw_support/port/esp32/rtc_time.c +++ b/components/esp_hw_support/port/esp32/rtc_time.c @@ -167,3 +167,11 @@ void rtc_clk_wait_for_slow_cycle(void) esp_rom_delay_us(1); } } + +uint32_t rtc_clk_freq_cal(uint32_t cal_val) +{ + if (cal_val == 0) { + return 0; // cal_val will be denominator, return 0 as the symbol of failure. + } + return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val; +} diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk.c b/components/esp_hw_support/port/esp32c3/rtc_clk.c index d85901963c..6c82c2103b 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c3/rtc_clk.c @@ -37,6 +37,7 @@ static const char *TAG = "rtc_clk"; #define RTC_PLL_FREQ_320M 320 #define RTC_PLL_FREQ_480M 480 +#define DELAY_RTC_CLK_SWITCH 5 // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. static int s_cur_pll_freq; @@ -559,6 +560,18 @@ void rtc_clk_8m_divider_set(uint32_t div) SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); } +void rtc_dig_clk8m_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); +} + +void rtc_dig_clk8m_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); +} + /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_hw_support/port/esp32c3/rtc_time.c b/components/esp_hw_support/port/esp32c3/rtc_time.c index e9996ba03d..12c0961a43 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_time.c +++ b/components/esp_hw_support/port/esp32c3/rtc_time.c @@ -179,3 +179,11 @@ void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any mor esp_rom_delay_us(1); } } + +uint32_t rtc_clk_freq_cal(uint32_t cal_val) +{ + if (cal_val == 0) { + return 0; // cal_val will be denominator, return 0 as the symbol of failure. + } + return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val; +} diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk.c b/components/esp_hw_support/port/esp32s2/rtc_clk.c index 49ab1ebfd6..8497cd3834 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk.c @@ -37,6 +37,7 @@ static const char *TAG = "rtc_clk"; #define RTC_PLL_FREQ_320M 320 #define RTC_PLL_FREQ_480M 480 +#define DELAY_RTC_CLK_SWITCH 5 // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. // On the ESP32-S2, 480MHz PLL is enabled at reset. @@ -539,6 +540,18 @@ void rtc_clk_8m_divider_set(uint32_t div) SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); } +void rtc_dig_clk8m_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); +} + +void rtc_dig_clk8m_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); +} + /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_hw_support/port/esp32s2/rtc_time.c b/components/esp_hw_support/port/esp32s2/rtc_time.c index 789352e140..a8987b698c 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_time.c +++ b/components/esp_hw_support/port/esp32s2/rtc_time.c @@ -184,3 +184,11 @@ void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any mor esp_rom_delay_us(1); } } + +uint32_t rtc_clk_freq_cal(uint32_t cal_val) +{ + if (cal_val == 0) { + return 0; // cal_val will be denominator, return 0 as the symbol of failure. + } + return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val; +} diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk.c b/components/esp_hw_support/port/esp32s3/rtc_clk.c index 3a9d069270..a1d2433aa8 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s3/rtc_clk.c @@ -38,6 +38,7 @@ static const char *TAG = "rtc_clk"; #define RTC_PLL_FREQ_320M 320 #define RTC_PLL_FREQ_480M 480 +#define DELAY_RTC_CLK_SWITCH 5 // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. static int s_cur_pll_freq = RTC_PLL_FREQ_480M; @@ -556,6 +557,18 @@ void rtc_clk_8m_divider_set(uint32_t div) SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); } +void rtc_dig_clk8m_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); +} + +void rtc_dig_clk8m_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); +} + /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_hw_support/port/esp32s3/rtc_time.c b/components/esp_hw_support/port/esp32s3/rtc_time.c index b529c19076..d2b78984af 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_time.c +++ b/components/esp_hw_support/port/esp32s3/rtc_time.c @@ -178,3 +178,11 @@ void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any mor esp_rom_delay_us(1); } } + +uint32_t rtc_clk_freq_cal(uint32_t cal_val) +{ + if (cal_val == 0) { + return 0; // cal_val will be denominator, return 0 as the symbol of failure. + } + return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val; +} diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index b283dadad3..7b09fde1eb 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -459,6 +459,29 @@ uint64_t rtc_time_get(void); */ void rtc_clk_wait_for_slow_cycle(void); +/** + * @brief Enable the rtc digital 8M clock + * + * This function is used to enable the digital rtc 8M clock to support peripherals. + * For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above. + */ +void rtc_dig_clk8m_enable(void); + +/** + * @brief Disable the rtc digital 8M clock + * + * This function is used to disable the digital rtc 8M clock, which is only used to support peripherals. + */ +void rtc_dig_clk8m_disable(void); + +/** + * @brief Caculate the real clock value after the clock calibration + * + * @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal` + * @return The real value of the clock has been measured + */ +uint32_t rtc_clk_freq_cal(uint32_t cal_val); + /** * @brief sleep configuration for rtc_sleep_init function */ diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index ed650f4950..3eafc77c1f 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -562,6 +562,29 @@ uint64_t rtc_deep_slp_time_get(void); */ void rtc_clk_wait_for_slow_cycle(void); +/** + * @brief Enable the rtc digital 8M clock + * + * This function is used to enable the digital rtc 8M clock to support peripherals. + * For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above. + */ +void rtc_dig_clk8m_enable(void); + +/** + * @brief Disable the rtc digital 8M clock + * + * This function is used to disable the digital rtc 8M clock, which is only used to support peripherals. + */ +void rtc_dig_clk8m_disable(void); + +/** + * @brief Caculate the real clock value after the clock calibration + * + * @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal` + * @return The real value of the clock has been measured + */ +uint32_t rtc_clk_freq_cal(uint32_t cal_val); + /** * @brief Power down flags for rtc_sleep_pd function */ diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index 11b1a7c8f9..2474c67bae 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -588,6 +588,29 @@ uint64_t rtc_deep_slp_time_get(void); */ void rtc_clk_wait_for_slow_cycle(void); +/** + * @brief Enable the rtc digital 8M clock + * + * This function is used to enable the digital rtc 8M clock to support peripherals. + * For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above. + */ +void rtc_dig_clk8m_enable(void); + +/** + * @brief Disable the rtc digital 8M clock + * + * This function is used to disable the digital rtc 8M clock, which is only used to support peripherals. + */ +void rtc_dig_clk8m_disable(void); + +/** + * @brief Caculate the real clock value after the clock calibration + * + * @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal` + * @return The real value of the clock has been measured + */ +uint32_t rtc_clk_freq_cal(uint32_t cal_val); + /** * @brief Power down flags for rtc_sleep_pd function */ diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index 035f7f9d9f..0287081d69 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -562,6 +562,29 @@ uint64_t rtc_deep_slp_time_get(void); */ void rtc_clk_wait_for_slow_cycle(void); +/** + * @brief Enable the rtc digital 8M clock + * + * This function is used to enable the digital rtc 8M clock to support peripherals. + * For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above. + */ +void rtc_dig_clk8m_enable(void); + +/** + * @brief Disable the rtc digital 8M clock + * + * This function is used to disable the digital rtc 8M clock, which is only used to support peripherals. + */ +void rtc_dig_clk8m_disable(void); + +/** + * @brief Caculate the real clock value after the clock calibration + * + * @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal` + * @return The real value of the clock has been measured + */ +uint32_t rtc_clk_freq_cal(uint32_t cal_val); + /** * @brief Power up flags for rtc_sleep_pd function */ From 8e0d423a5ed2a26cbda2171ee1a89f2c37d3dfed Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 17 Dec 2020 09:16:52 +1100 Subject: [PATCH 4/9] driver: Add rtc_io hold/wakeup c3 support Temporary implementation, should be moved to HAL Copied from internal commit 3ef01301ff --- components/driver/rtc_io.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/components/driver/rtc_io.c b/components/driver/rtc_io.c index 47f8bc826a..9c96b93b0b 100644 --- a/components/driver/rtc_io.c +++ b/components/driver/rtc_io.c @@ -160,23 +160,33 @@ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num) #endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED +#if SOC_RTCIO_HOLD_SUPPORTED + esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num) { +#ifdef CONFIG_IDF_TARGET_ESP32C3 // should use HAL here, TODO ESP32-C3 IDF-2511 + RTCIO_CHECK(gpio_num <= GPIO_NUM_5, "RTCIO number error", ESP_ERR_INVALID_ARG); + REG_SET_BIT(RTC_CNTL_PAD_HOLD_REG, BIT(gpio_num)); +#else RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); RTCIO_ENTER_CRITICAL(); rtcio_hal_hold_enable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); - +#endif return ESP_OK; } esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num) { +#ifdef CONFIG_IDF_TARGET_ESP32C3 // should use HAL here, TODO ESP32-C3 IDF-2511 + RTCIO_CHECK(gpio_num <= GPIO_NUM_5, "RTCIO number error", ESP_ERR_INVALID_ARG); + REG_CLR_BIT(RTC_CNTL_PAD_HOLD_REG, BIT(gpio_num)); +#else RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); RTCIO_ENTER_CRITICAL(); rtcio_hal_hold_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); - +#endif return ESP_OK; } @@ -208,8 +218,22 @@ esp_err_t rtc_gpio_force_hold_dis_all(void) return ESP_OK; } +#endif // SOC_RTCIO_HOLD_SUPPORTED + +#if SOC_RTCIO_WAKE_SUPPORTED + esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) { +#ifdef CONFIG_IDF_TARGET_ESP32C3 // should use HAL here, TODO ESP32-C3 IDF-2511 + RTCIO_CHECK(gpio_num <= GPIO_NUM_5, "RTCIO number error", ESP_ERR_INVALID_ARG); + REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_M >> gpio_num); + + uint32_t reg = REG_READ(RTC_CNTL_GPIO_WAKEUP_REG); + reg &= (~(RTC_CNTL_GPIO_PIN0_INT_TYPE_V << (RTC_CNTL_GPIO_PIN0_INT_TYPE_S - gpio_num * 3))); + reg |= (intr_type << (RTC_CNTL_GPIO_PIN0_INT_TYPE_S - gpio_num * 3)); + REG_WRITE(RTC_CNTL_GPIO_WAKEUP_REG, reg); + ESP_LOGD(RTCIO_TAG, "gpio wake up 0x%08x", REG_READ(RTC_CNTL_GPIO_WAKEUP_REG)); +#else RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); if (intr_type == GPIO_INTR_POSEDGE || intr_type == GPIO_INTR_NEGEDGE || intr_type == GPIO_INTR_ANYEDGE) { return ESP_ERR_INVALID_ARG; // Dont support this mode. @@ -217,16 +241,22 @@ esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) RTCIO_ENTER_CRITICAL(); rtcio_hal_wakeup_enable(rtc_io_number_get(gpio_num), intr_type); RTCIO_EXIT_CRITICAL(); - +#endif // CONFIG_IDF_TARGET_ESP32C3 return ESP_OK; } esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num) { +#ifdef CONFIG_IDF_TARGET_ESP32C3 // should use HAL here, TODO ESP32-C3 IDF-2511 + RTCIO_CHECK(gpio_num <= GPIO_NUM_5, "RTCIO number error", ESP_ERR_INVALID_ARG); + REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_M >> gpio_num); +#else RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); RTCIO_ENTER_CRITICAL(); rtcio_hal_wakeup_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); - +#endif return ESP_OK; } + +#endif // SOC_RTCIO_WAKE_SUPPORTED From 75dede2344c855c0d1f06c6cc9f713f3b0ff9005 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sat, 19 Dec 2020 08:36:40 +1100 Subject: [PATCH 5/9] esp_hw_support: Add esp32c3 regi2c headers --- .../esp32c3/private_include/regi2c_bbpll.h | 183 ++++++++++++++++++ .../esp32c3/private_include/regi2c_bias.h | 30 +++ .../esp32c3/private_include/regi2c_brownout.h | 30 +++ .../esp32c3/private_include/regi2c_dig_reg.h | 68 +++++++ .../esp32c3/private_include/regi2c_lp_bias.h | 43 ++++ .../esp32c3/private_include/regi2c_saradc.h | 83 ++++++++ .../esp_hw_support/port/esp32c3/regi2c_ctrl.h | 80 ++++++++ components/hal/esp32c3/include/hal/adc_ll.h | 49 +---- 8 files changed, 520 insertions(+), 46 deletions(-) create mode 100644 components/esp_hw_support/port/esp32c3/private_include/regi2c_bbpll.h create mode 100644 components/esp_hw_support/port/esp32c3/private_include/regi2c_bias.h create mode 100644 components/esp_hw_support/port/esp32c3/private_include/regi2c_brownout.h create mode 100644 components/esp_hw_support/port/esp32c3/private_include/regi2c_dig_reg.h create mode 100644 components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.h create mode 100644 components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h create mode 100644 components/esp_hw_support/port/esp32c3/regi2c_ctrl.h diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_bbpll.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_bbpll.h new file mode 100644 index 0000000000..842f702934 --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_bbpll.h @@ -0,0 +1,183 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @file regi2c_bbpll.h + * @brief Register definitions for digital PLL (BBPLL) + * + * This file lists register fields of BBPLL, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h, by + * rtc_clk_cpu_freq_set function in rtc_clk.c. + */ + +#define I2C_BBPLL 0x66 +#define I2C_BBPLL_HOSTID 0 + +#define I2C_BBPLL_IR_CAL_DELAY 0 +#define I2C_BBPLL_IR_CAL_DELAY_MSB 3 +#define I2C_BBPLL_IR_CAL_DELAY_LSB 0 + +#define I2C_BBPLL_IR_CAL_CK_DIV 0 +#define I2C_BBPLL_IR_CAL_CK_DIV_MSB 7 +#define I2C_BBPLL_IR_CAL_CK_DIV_LSB 4 + +#define I2C_BBPLL_IR_CAL_EXT_CAP 1 +#define I2C_BBPLL_IR_CAL_EXT_CAP_MSB 3 +#define I2C_BBPLL_IR_CAL_EXT_CAP_LSB 0 + +#define I2C_BBPLL_IR_CAL_ENX_CAP 1 +#define I2C_BBPLL_IR_CAL_ENX_CAP_MSB 4 +#define I2C_BBPLL_IR_CAL_ENX_CAP_LSB 4 + +#define I2C_BBPLL_IR_CAL_RSTB 1 +#define I2C_BBPLL_IR_CAL_RSTB_MSB 5 +#define I2C_BBPLL_IR_CAL_RSTB_LSB 5 + +#define I2C_BBPLL_IR_CAL_START 1 +#define I2C_BBPLL_IR_CAL_START_MSB 6 +#define I2C_BBPLL_IR_CAL_START_LSB 6 + +#define I2C_BBPLL_IR_CAL_UNSTOP 1 +#define I2C_BBPLL_IR_CAL_UNSTOP_MSB 7 +#define I2C_BBPLL_IR_CAL_UNSTOP_LSB 7 + +#define I2C_BBPLL_OC_REF_DIV 2 +#define I2C_BBPLL_OC_REF_DIV_MSB 3 +#define I2C_BBPLL_OC_REF_DIV_LSB 0 + +#define I2C_BBPLL_OC_DCHGP 2 +#define I2C_BBPLL_OC_DCHGP_MSB 6 +#define I2C_BBPLL_OC_DCHGP_LSB 4 + +#define I2C_BBPLL_OC_ENB_FCAL 2 +#define I2C_BBPLL_OC_ENB_FCAL_MSB 7 +#define I2C_BBPLL_OC_ENB_FCAL_LSB 7 + +#define I2C_BBPLL_OC_DIV_7_0 3 +#define I2C_BBPLL_OC_DIV_7_0_MSB 7 +#define I2C_BBPLL_OC_DIV_7_0_LSB 0 + +#define I2C_BBPLL_RSTB_DIV_ADC 4 +#define I2C_BBPLL_RSTB_DIV_ADC_MSB 0 +#define I2C_BBPLL_RSTB_DIV_ADC_LSB 0 + +#define I2C_BBPLL_MODE_HF 4 +#define I2C_BBPLL_MODE_HF_MSB 1 +#define I2C_BBPLL_MODE_HF_LSB 1 + +#define I2C_BBPLL_DIV_ADC 4 +#define I2C_BBPLL_DIV_ADC_MSB 3 +#define I2C_BBPLL_DIV_ADC_LSB 2 + +#define I2C_BBPLL_DIV_DAC 4 +#define I2C_BBPLL_DIV_DAC_MSB 4 +#define I2C_BBPLL_DIV_DAC_LSB 4 + +#define I2C_BBPLL_DIV_CPU 4 +#define I2C_BBPLL_DIV_CPU_MSB 5 +#define I2C_BBPLL_DIV_CPU_LSB 5 + +#define I2C_BBPLL_OC_ENB_VCON 4 +#define I2C_BBPLL_OC_ENB_VCON_MSB 6 +#define I2C_BBPLL_OC_ENB_VCON_LSB 6 + +#define I2C_BBPLL_OC_TSCHGP 4 +#define I2C_BBPLL_OC_TSCHGP_MSB 7 +#define I2C_BBPLL_OC_TSCHGP_LSB 7 + +#define I2C_BBPLL_OC_DR1 5 +#define I2C_BBPLL_OC_DR1_MSB 2 +#define I2C_BBPLL_OC_DR1_LSB 0 + +#define I2C_BBPLL_OC_DR3 5 +#define I2C_BBPLL_OC_DR3_MSB 6 +#define I2C_BBPLL_OC_DR3_LSB 4 + +#define I2C_BBPLL_EN_USB 5 +#define I2C_BBPLL_EN_USB_MSB 7 +#define I2C_BBPLL_EN_USB_LSB 7 + +#define I2C_BBPLL_OC_DCUR 6 +#define I2C_BBPLL_OC_DCUR_MSB 2 +#define I2C_BBPLL_OC_DCUR_LSB 0 + +#define I2C_BBPLL_INC_CUR 6 +#define I2C_BBPLL_INC_CUR_MSB 3 +#define I2C_BBPLL_INC_CUR_LSB 3 + +#define I2C_BBPLL_OC_DHREF_SEL 6 +#define I2C_BBPLL_OC_DHREF_SEL_MSB 5 +#define I2C_BBPLL_OC_DHREF_SEL_LSB 4 + +#define I2C_BBPLL_OC_DLREF_SEL 6 +#define I2C_BBPLL_OC_DLREF_SEL_MSB 7 +#define I2C_BBPLL_OC_DLREF_SEL_LSB 6 + +#define I2C_BBPLL_OR_CAL_CAP 8 +#define I2C_BBPLL_OR_CAL_CAP_MSB 3 +#define I2C_BBPLL_OR_CAL_CAP_LSB 0 + +#define I2C_BBPLL_OR_CAL_UDF 8 +#define I2C_BBPLL_OR_CAL_UDF_MSB 4 +#define I2C_BBPLL_OR_CAL_UDF_LSB 4 + +#define I2C_BBPLL_OR_CAL_OVF 8 +#define I2C_BBPLL_OR_CAL_OVF_MSB 5 +#define I2C_BBPLL_OR_CAL_OVF_LSB 5 + +#define I2C_BBPLL_OR_CAL_END 8 +#define I2C_BBPLL_OR_CAL_END_MSB 6 +#define I2C_BBPLL_OR_CAL_END_LSB 6 + +#define I2C_BBPLL_OR_LOCK 8 +#define I2C_BBPLL_OR_LOCK_MSB 7 +#define I2C_BBPLL_OR_LOCK_LSB 7 + +#define I2C_BBPLL_OC_VCO_DBIAS 9 +#define I2C_BBPLL_OC_VCO_DBIAS_MSB 1 +#define I2C_BBPLL_OC_VCO_DBIAS_LSB 0 + +#define I2C_BBPLL_BBADC_DELAY2 9 +#define I2C_BBPLL_BBADC_DELAY2_MSB 3 +#define I2C_BBPLL_BBADC_DELAY2_LSB 2 + +#define I2C_BBPLL_BBADC_DVDD 9 +#define I2C_BBPLL_BBADC_DVDD_MSB 5 +#define I2C_BBPLL_BBADC_DVDD_LSB 4 + +#define I2C_BBPLL_BBADC_DREF 9 +#define I2C_BBPLL_BBADC_DREF_MSB 7 +#define I2C_BBPLL_BBADC_DREF_LSB 6 + +#define I2C_BBPLL_BBADC_DCUR 10 +#define I2C_BBPLL_BBADC_DCUR_MSB 1 +#define I2C_BBPLL_BBADC_DCUR_LSB 0 + +#define I2C_BBPLL_BBADC_INPUT_SHORT 10 +#define I2C_BBPLL_BBADC_INPUT_SHORT_MSB 2 +#define I2C_BBPLL_BBADC_INPUT_SHORT_LSB 2 + +#define I2C_BBPLL_ENT_PLL 10 +#define I2C_BBPLL_ENT_PLL_MSB 3 +#define I2C_BBPLL_ENT_PLL_LSB 3 + +#define I2C_BBPLL_DTEST 10 +#define I2C_BBPLL_DTEST_MSB 5 +#define I2C_BBPLL_DTEST_LSB 4 + +#define I2C_BBPLL_ENT_ADC 10 +#define I2C_BBPLL_ENT_ADC_MSB 7 +#define I2C_BBPLL_ENT_ADC_LSB 6 diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_bias.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_bias.h new file mode 100644 index 0000000000..f459a344ba --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_bias.h @@ -0,0 +1,30 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @file regi2c_bias.h + * @brief Register definitions for bias + * + * This file lists register fields of BIAS. These definitions are used via macros defined in regi2c_ctrl.h, by + * bootloader_hardware_init function in bootloader_esp32c3.c. + */ + +#define I2C_BIAS 0X6A +#define I2C_BIAS_HOSTID 0 + +#define I2C_BIAS_DREG_1P1_PVT 1 +#define I2C_BIAS_DREG_1P1_PVT_MSB 3 +#define I2C_BIAS_DREG_1P1_PVT_LSB 0 diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_brownout.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_brownout.h new file mode 100644 index 0000000000..0b8b618bba --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_brownout.h @@ -0,0 +1,30 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @file regi2c_brownout.h + * @brief Register definitions for brownout detector + * + * This file lists register fields of the brownout detector, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h. + */ + +#define I2C_BOD 0x61 +#define I2C_BOD_HOSTID 1 + +#define I2C_BOD_THRESHOLD 0x5 +#define I2C_BOD_THRESHOLD_MSB 2 +#define I2C_BOD_THRESHOLD_LSB 0 diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_dig_reg.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_dig_reg.h new file mode 100644 index 0000000000..2510f43ae5 --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_dig_reg.h @@ -0,0 +1,68 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @file regi2c_dig_reg.h + * @brief Register definitions for digital to get rtc voltage & digital voltage + * by setting rtc_dbias_Wak & dig_dbias_wak or by analog self-calibration. + */ + +#define I2C_DIG_REG 0x6D +#define I2C_DIG_REG_HOSTID 0 + +#define I2C_DIG_REG_EXT_RTC_DREG 4 +#define I2C_DIG_REG_EXT_RTC_DREG_MSB 4 +#define I2C_DIG_REG_EXT_RTC_DREG_LSB 0 + +#define I2C_DIG_REG_ENX_RTC_DREG 4 +#define I2C_DIG_REG_ENX_RTC_DREG_MSB 7 +#define I2C_DIG_REG_ENX_RTC_DREG_LSB 7 + +#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP 5 +#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_MSB 4 +#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_LSB 0 + +#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP 5 +#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP_MSB 7 +#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP_LSB 7 + +#define I2C_DIG_REG_EXT_DIG_DREG 6 +#define I2C_DIG_REG_EXT_DIG_DREG_MSB 4 +#define I2C_DIG_REG_EXT_DIG_DREG_LSB 0 + +#define I2C_DIG_REG_ENX_DIG_DREG 6 +#define I2C_DIG_REG_ENX_DIG_DREG_MSB 7 +#define I2C_DIG_REG_ENX_DIG_DREG_LSB 7 + +#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP 7 +#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_MSB 4 +#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_LSB 0 + +#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP 7 +#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP_MSB 7 +#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP_LSB 7 + +#define I2C_DIG_REG_OR_EN_CONT_CAL 9 +#define I2C_DIG_REG_OR_EN_CONT_CAL_MSB 7 +#define I2C_DIG_REG_OR_EN_CONT_CAL_LSB 7 + +#define I2C_DIG_REG_XPD_RTC_REG 13 +#define I2C_DIG_REG_XPD_RTC_REG_MSB 2 +#define I2C_DIG_REG_XPD_RTC_REG_LSB 2 + +#define I2C_DIG_REG_XPD_DIG_REG 13 +#define I2C_DIG_REG_XPD_DIG_REG_MSB 3 +#define I2C_DIG_REG_XPD_DIG_REG_LSB 3 diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.h new file mode 100644 index 0000000000..a735e0a42e --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.h @@ -0,0 +1,43 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @file regi2c_lp_bias.h + * @brief Register definitions for analog to calibrate o_code for getting a more precise voltage. + * + * This file lists register fields of low power dbais, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h, by + * rtc_init function in rtc_init.c. + */ + +#define I2C_ULP 0x61 +#define I2C_ULP_HOSTID 0 + +#define I2C_ULP_IR_RESETB 0 +#define I2C_ULP_IR_RESETB_MSB 0 +#define I2C_ULP_IR_RESETB_LSB 0 + +#define I2C_ULP_O_DONE_FLAG 3 +#define I2C_ULP_O_DONE_FLAG_MSB 0 +#define I2C_ULP_O_DONE_FLAG_LSB 0 + +#define I2C_ULP_BG_O_DONE_FLAG 3 +#define I2C_ULP_BG_O_DONE_FLAG_MSB 3 +#define I2C_ULP_BG_O_DONE_FLAG_LSB 3 + +#define I2C_ULP_IR_FORCE_XPD_IPH 0 +#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 4 +#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 4 diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h new file mode 100644 index 0000000000..2345e0a5aa --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h @@ -0,0 +1,83 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @file regi2c_saradc.h + * @brief Register definitions for analog to calibrate initial code for getting a more precise voltage of SAR ADC. + * + * This file lists register fields of SAR, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h, by + * function in adc_ll.h. + */ + +#define I2C_SAR_ADC 0X69 +#define I2C_SAR_ADC_HOSTID 1 + +#define ADC_SAR1_ENCAL_GND_ADDR 0x7 +#define ADC_SAR1_ENCAL_GND_ADDR_MSB 5 +#define ADC_SAR1_ENCAL_GND_ADDR_LSB 5 + +#define ADC_SAR2_ENCAL_GND_ADDR 0x7 +#define ADC_SAR2_ENCAL_GND_ADDR_MSB 7 +#define ADC_SAR2_ENCAL_GND_ADDR_LSB 7 + +#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR 0x1 +#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3 +#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0 + +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR 0x0 +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB 0x7 +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB 0x0 + +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR 0x4 +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3 +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0 + +#define ADC_SAR2_INITIAL_CODE_LOW_ADDR 0x3 +#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB 0x7 +#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB 0x0 + +#define ADC_SAR1_DREF_ADDR 0x2 +#define ADC_SAR1_DREF_ADDR_MSB 0x6 +#define ADC_SAR1_DREF_ADDR_LSB 0x4 + +#define ADC_SAR2_DREF_ADDR 0x5 +#define ADC_SAR2_DREF_ADDR_MSB 0x6 +#define ADC_SAR2_DREF_ADDR_LSB 0x4 + +#define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2 +#define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2 +#define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0 + +#define ADC_SARADC_DTEST_RTC_ADDR 0x7 +#define ADC_SARADC_DTEST_RTC_ADDR_MSB 1 +#define ADC_SARADC_DTEST_RTC_ADDR_LSB 0 + +#define ADC_SARADC_ENT_TSENS_ADDR 0x7 +#define ADC_SARADC_ENT_TSENS_ADDR_MSB 2 +#define ADC_SARADC_ENT_TSENS_ADDR_LSB 2 + +#define ADC_SARADC_ENT_RTC_ADDR 0x7 +#define ADC_SARADC_ENT_RTC_ADDR_MSB 3 +#define ADC_SARADC_ENT_RTC_ADDR_LSB 3 + +#define ADC_SARADC_ENCAL_REF_ADDR 0x7 +#define ADC_SARADC_ENCAL_REF_ADDR_MSB 4 +#define ADC_SARADC_ENCAL_REF_ADDR_LSB 4 + +#define I2C_SARADC_TSENS_DAC 0x6 +#define I2C_SARADC_TSENS_DAC_MSB 3 +#define I2C_SARADC_TSENS_DAC_LSB 0 diff --git a/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h b/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h new file mode 100644 index 0000000000..a197b3c83b --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h @@ -0,0 +1,80 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "regi2c_bbpll.h" +#include "regi2c_lp_bias.h" +#include "regi2c_dig_reg.h" +#include "regi2c_bias.h" +#include "regi2c_saradc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Analog function control register */ +#define ANA_CONFIG_REG 0x6000E044 +#define ANA_CONFIG_S (8) +#define ANA_CONFIG_M (0x3FF) +/* Clear to enable APLL */ +#define I2C_APLL_M (BIT(14)) +/* Clear to enable BBPLL */ +#define I2C_BBPLL_M (BIT(17)) + +#define SAR_I2C_FORCE_PD BIT(18) +#define SAR_I2C_FORCE_PU BIT(16) + +#define ANA_CONFIG2_REG 0x6000E048 +#define ANA_CONFIG2_M (BIT(18)) + +/* ROM functions which read/write internal control bus */ +uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add); +uint8_t rom_i2c_readReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb); +void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); +void rom_i2c_writeReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data); + +/* Convenience macros for the above functions, these use register definitions + * from regi2c_bbpll.h/regi2c_dig_reg.h/regi2c_lp_bias.h/regi2c_bias.h header files. + */ +#define REGI2C_WRITE_MASK(block, reg_add, indata) \ + rom_i2c_writeReg_Mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata) + +#define REGI2C_READ_MASK(block, reg_add) \ + rom_i2c_readReg_Mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB) + +#define REGI2C_WRITE(block, reg_add, indata) \ + rom_i2c_writeReg(block, block##_HOSTID, reg_add, indata) + +#define REGI2C_READ(block, reg_add) \ + rom_i2c_readReg(block, block##_HOSTID, reg_add) + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h index aba319b621..31d0da4e05 100644 --- a/components/hal/esp32c3/include/hal/adc_ll.h +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -902,30 +902,7 @@ static inline void adc_ll_disable_sleep_controller(void) */ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t channel, bool internal_gnd) { - // /* Enable i2s_write_reg function. */ - // void phy_get_romfunc_addr(void); - // phy_get_romfunc_addr(); - // //CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M); - // //SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); - // CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18)); - // SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16)); - - // /* Enable/disable internal connect GND (for calibration). */ - // if (adc_n == ADC_NUM_1) { - // REGI2C_WRITE_MASK(I2C_ADC, SAR1_DREF_ADDR, 4); - // if (internal_gnd) { - // REGI2C_WRITE_MASK(I2C_ADC, SAR1_ENCAL_GND_ADDR, 1); - // } else { - // REGI2C_WRITE_MASK(I2C_ADC, SAR1_ENCAL_GND_ADDR, 0); - // } - // } else { - // REGI2C_WRITE_MASK(I2C_ADC, SAR2_DREF_ADDR, 4); - // if (internal_gnd) { - // REGI2C_WRITE_MASK(I2C_ADC, SAR2_ENCAL_GND_ADDR, 1); - // } else { - // REGI2C_WRITE_MASK(I2C_ADC, SAR2_ENCAL_GND_ADDR, 0); - // } - // } + abort(); // TODO ESP32-C3 IDF-2526 } /** @@ -935,11 +912,7 @@ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t */ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n) { - // if (adc_n == ADC_NUM_1) { - // REGI2C_WRITE_MASK(I2C_ADC, SAR1_ENCAL_GND_ADDR, 0); - // } else { - // REGI2C_WRITE_MASK(I2C_ADC, SAR2_ENCAL_GND_ADDR, 0); - // } + abort(); // TODO ESP32-C3 IDF-2526 } /** @@ -951,24 +924,8 @@ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n) */ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t param) { - // uint8_t msb = param >> 8; - // uint8_t lsb = param & 0xFF; - // /* Enable i2s_write_reg function. */ - // void phy_get_romfunc_addr(void); - // phy_get_romfunc_addr(); - // //SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); - // CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18)); - // SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16)); - - // if (adc_n == ADC_NUM_1) { - // REGI2C_WRITE_MASK(I2C_ADC, SAR1_INITIAL_CODE_HIGH_ADDR, msb); - // REGI2C_WRITE_MASK(I2C_ADC, SAR1_INITIAL_CODE_LOW_ADDR, lsb); - // } else { - // REGI2C_WRITE_MASK(I2C_ADC, SAR2_INITIAL_CODE_HIGH_ADDR, msb); - // REGI2C_WRITE_MASK(I2C_ADC, SAR2_INITIAL_CODE_LOW_ADDR, lsb); - // } + abort(); // TODO ESP32-C3 IDF-2526 } -/* Temp code end. */ #ifdef __cplusplus } From fa892eb01757f8575a9963579362b0f95217e8a3 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sat, 19 Dec 2020 08:39:22 +1100 Subject: [PATCH 6/9] soc: Explain units for rtc_clk_cal() function, fix typo --- components/soc/esp32/include/soc/rtc.h | 6 +++--- components/soc/esp32c3/include/soc/rtc.h | 6 +++--- components/soc/esp32s2/include/soc/rtc.h | 6 +++--- components/soc/esp32s3/include/soc/rtc.h | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index 7b09fde1eb..6efffc0203 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -475,10 +475,10 @@ void rtc_dig_clk8m_enable(void); void rtc_dig_clk8m_disable(void); /** - * @brief Caculate the real clock value after the clock calibration + * @brief Calculate the real clock value after the clock calibration * - * @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal` - * @return The real value of the clock has been measured + * @param cal_val Average slow clock period in microseconds, fixed point value as returned from `rtc_clk_cal` + * @return Frequency of the clock in Hz */ uint32_t rtc_clk_freq_cal(uint32_t cal_val); diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 3eafc77c1f..e6700f374f 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -578,10 +578,10 @@ void rtc_dig_clk8m_enable(void); void rtc_dig_clk8m_disable(void); /** - * @brief Caculate the real clock value after the clock calibration + * @brief Calculate the real clock value after the clock calibration * - * @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal` - * @return The real value of the clock has been measured + * @param cal_val Average slow clock period in microseconds, fixed point value as returned from `rtc_clk_cal` + * @return Frequency of the clock in Hz */ uint32_t rtc_clk_freq_cal(uint32_t cal_val); diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index 2474c67bae..0ea0716e6d 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -604,10 +604,10 @@ void rtc_dig_clk8m_enable(void); void rtc_dig_clk8m_disable(void); /** - * @brief Caculate the real clock value after the clock calibration + * @brief Calculate the real clock value after the clock calibration * - * @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal` - * @return The real value of the clock has been measured + * @param cal_val Average slow clock period in microseconds, fixed point value as returned from `rtc_clk_cal` + * @return Frequency of the clock in Hz */ uint32_t rtc_clk_freq_cal(uint32_t cal_val); diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index 0287081d69..be79674509 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -578,10 +578,10 @@ void rtc_dig_clk8m_enable(void); void rtc_dig_clk8m_disable(void); /** - * @brief Caculate the real clock value after the clock calibration + * @brief Calculate the real clock value after the clock calibration * - * @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal` - * @return The real value of the clock has been measured + * @param cal_val Average slow clock period in microseconds, fixed point value as returned from `rtc_clk_cal` + * @return Frequency of the clock in Hz */ uint32_t rtc_clk_freq_cal(uint32_t cal_val); From 2d37bfa126764c44c81b2064c3875ddaf04723db Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 15 Dec 2020 17:20:22 +0800 Subject: [PATCH 7/9] driver: Add adc_digi single conversion mode - add lock for single read and continuous read APIs - update onetime read start singal delay for hardware limitation[*] - move adc_caps to soc_caps.h - update license dates [*] There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller clock cycle. --- components/driver/esp32c3/adc.c | 772 +++++++++++------- .../driver/esp32c3/include/driver/adc.h | 12 +- components/driver/include/driver/adc_common.h | 11 +- components/hal/adc_hal.c | 112 ++- .../esp32c3/include/hal/adc_hal_conf.h} | 15 +- components/hal/esp32c3/include/hal/adc_ll.h | 89 ++ components/hal/include/hal/adc_hal.h | 28 + components/hal/include/hal/adc_types.h | 24 +- components/soc/esp32c3/include/soc/soc_caps.h | 16 +- 9 files changed, 735 insertions(+), 344 deletions(-) rename components/{soc/esp32c3/include/soc/adc_caps.h => hal/esp32c3/include/hal/adc_hal_conf.h} (75%) diff --git a/components/driver/esp32c3/adc.c b/components/driver/esp32c3/adc.c index e4b918f907..5e9748cd82 100644 --- a/components/driver/esp32c3/adc.c +++ b/components/driver/esp32c3/adc.c @@ -1,4 +1,4 @@ -// Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 2016-2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,22 +15,22 @@ #include #include #include +#include +#include "sdkconfig.h" +#include "esp_intr_alloc.h" #include "esp_log.h" #include "sys/lock.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/timers.h" -#include "esp_intr_alloc.h" +#include "freertos/ringbuf.h" +#include "esp32c3/rom/ets_sys.h" #include "driver/periph_ctrl.h" -#include "driver/rtc_io.h" -#include "driver/rtc_cntl.h" #include "driver/gpio.h" #include "driver/adc.h" -#include "sdkconfig.h" - -#include "esp32c3/rom/ets_sys.h" #include "hal/adc_types.h" #include "hal/adc_hal.h" +#include "hal/dma_types.h" #define ADC_CHECK_RET(fun_ret) ({ \ if (fun_ret != ESP_OK) { \ @@ -56,16 +56,473 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi #define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) #define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) +/*--------------------------------------------------------------- + Digital Controller Context +---------------------------------------------------------------*/ +/** + * 1. adc_digi_mutex: this mutex lock is used for ADC digital controller. On ESP32-C3, the ADC single read APIs (unit1 & unit2) + * and ADC DMA continuous read APIs share the ``apb_saradc_struct.h`` regs. + * + * 2. sar_adc_mutex: this mutex lock is used for SARADC2 module. On ESP32C-C3, the ADC single read APIs (unit2), ADC DMA + * continuous read APIs and WIFI share the SARADC2 analog IP. + * + * Sequence: + * Acquire: 1. sar_adc_mutex; 2. adc_digi_mutex; + * Release: 1. adc_digi_mutex; 2. sar_adc_mutex; + */ +static _lock_t adc_digi_mutex; +#define ADC_DIGI_LOCK_ACQUIRE() _lock_acquire(&adc_digi_mutex) +#define ADC_DIGI_LOCK_RELEASE() _lock_release(&adc_digi_mutex) +static _lock_t sar_adc2_mutex; +#define SAC_ADC2_LOCK_ACQUIRE() _lock_acquire(&sar_adc2_mutex) +#define SAC_ADC2_LOCK_RELEASE() _lock_release(&sar_adc2_mutex) + +#define INTERNAL_BUF_NUM 5 +#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF + +typedef struct adc_digi_context_t { + intr_handle_t dma_intr_hdl; //MD interrupt handle + uint32_t bytes_between_intr; //bytes between in suc eof intr + uint8_t *rx_dma_buf; //dma buffer + adc_dma_hal_context_t hal_dma; //dma context (hal) + adc_dma_hal_config_t hal_dma_config; //dma config (hal) + RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler + bool ringbuf_overflow_flag; //1: ringbuffer overflow + bool driver_start_flag; //1: driver is started; 0: driver is stoped + bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not. + adc_digi_config_t digi_controller_config; //Digital Controller Configuration +} adc_digi_context_t; + +static const char* ADC_DMA_TAG = "ADC_DMA:"; +static adc_digi_context_t *s_adc_digi_ctx = NULL; + + +/*--------------------------------------------------------------- + ADC Continuous Read Mode (via DMA) +---------------------------------------------------------------*/ +static void adc_dma_intr(void* arg); + +static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel) +{ + return adc_channel_io_map[adc_unit][adc_channel]; +} + +static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask) +{ + esp_err_t ret = ESP_OK; + uint64_t gpio_mask = 0; + uint32_t n = 0; + int8_t io = 0; + + while (channel_mask) { + if (channel_mask & 0x1) { + io = adc_digi_get_io_num(adc_unit, n); + if (io < 0) { + return ESP_ERR_INVALID_ARG; + } + gpio_mask |= BIT64(io); + } + channel_mask = channel_mask >> 1; + n++; + } + + gpio_config_t cfg = { + .pin_bit_mask = gpio_mask, + .mode = GPIO_MODE_DISABLE, + }; + ret = gpio_config(&cfg); + + return ret; +} + +esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) +{ + esp_err_t ret = ESP_OK; + + s_adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t)); + if (s_adc_digi_ctx == NULL) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + + ret = esp_intr_alloc(SOC_GDMA_ADC_INTR_SOURCE, 0, adc_dma_intr, (void *)s_adc_digi_ctx, &s_adc_digi_ctx->dma_intr_hdl); + if (ret != ESP_OK) { + goto cleanup; + } + + //ringbuffer + s_adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF); + if (!s_adc_digi_ctx->ringbuf_hdl) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + + //malloc internal buffer + s_adc_digi_ctx->bytes_between_intr = init_config->conv_num_each_intr; + s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, s_adc_digi_ctx->bytes_between_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL); + if (!s_adc_digi_ctx->rx_dma_buf) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + + //malloc dma descriptor + s_adc_digi_ctx->hal_dma_config.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA); + if (!s_adc_digi_ctx->hal_dma_config.rx_desc) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + s_adc_digi_ctx->hal_dma_config.desc_max_num = INTERNAL_BUF_NUM; + s_adc_digi_ctx->hal_dma_config.dma_chan = init_config->dma_chan; + + //malloc pattern table + s_adc_digi_ctx->digi_controller_config.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_table_t)); + if (!s_adc_digi_ctx->digi_controller_config.adc_pattern) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + + if (init_config->adc1_chan_mask) { + ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask); + if (ret != ESP_OK) { + goto cleanup; + } + } + if (init_config->adc2_chan_mask) { + ret = adc_digi_gpio_init(ADC_NUM_2, init_config->adc2_chan_mask); + if (ret != ESP_OK) { + goto cleanup; + } + } + + periph_module_enable(PERIPH_SARADC_MODULE); + periph_module_enable(PERIPH_GDMA_MODULE); + + return ret; + +cleanup: + adc_digi_deinitialize(); + return ret; + +} + +static IRAM_ATTR void adc_dma_intr(void *arg) +{ + portBASE_TYPE taskAwoken = 0; + BaseType_t ret; + + //clear the in suc eof interrupt + adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); + + while (s_adc_digi_ctx->hal_dma_config.cur_desc_ptr->dw0.owner == 0) { + + dma_descriptor_t *current_desc = s_adc_digi_ctx->hal_dma_config.cur_desc_ptr; + ret = xRingbufferSendFromISR(s_adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken); + if (ret == pdFALSE) { + //ringbuffer overflow + s_adc_digi_ctx->ringbuf_overflow_flag = 1; + } + + s_adc_digi_ctx->hal_dma_config.desc_cnt += 1; + //cycle the dma descriptor and buffers + s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.cur_desc_ptr->next; + if (!s_adc_digi_ctx->hal_dma_config.cur_desc_ptr) { + break; + } + } + + if (!s_adc_digi_ctx->hal_dma_config.cur_desc_ptr) { + + assert(s_adc_digi_ctx->hal_dma_config.desc_cnt == s_adc_digi_ctx->hal_dma_config.desc_max_num); + //reset the current descriptor status + s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.rx_desc; + s_adc_digi_ctx->hal_dma_config.desc_cnt = 0; + + //start next turns of dma operation + adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + } + + if(taskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +esp_err_t adc_digi_start(void) +{ + if (s_adc_digi_ctx->driver_start_flag != 0) { + ESP_LOGE(ADC_TAG, "The driver is already started"); + return ESP_ERR_INVALID_STATE; + } + //reset flags + s_adc_digi_ctx->ringbuf_overflow_flag = 0; + s_adc_digi_ctx->driver_start_flag = 1; + + //When using SARADC2 module, this task needs to be protected from WIFI + if (s_adc_digi_ctx->use_adc2) { + SAC_ADC2_LOCK_ACQUIRE(); + } + ADC_DIGI_LOCK_ACQUIRE(); + + adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); + adc_hal_init(); + adc_hal_arbiter_config(&config); + adc_hal_digi_init(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config); + + //create dma descriptors + adc_hal_digi_dma_multi_descriptor(&s_adc_digi_ctx->hal_dma_config, s_adc_digi_ctx->rx_dma_buf, s_adc_digi_ctx->bytes_between_intr, s_adc_digi_ctx->hal_dma_config.desc_max_num); + adc_hal_digi_set_eof_num(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, (s_adc_digi_ctx->bytes_between_intr)/4); + //set the current descriptor pointer + s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.rx_desc; + s_adc_digi_ctx->hal_dma_config.desc_cnt = 0; + + //enable in suc eof intr + adc_hal_digi_ena_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); + //start DMA + adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + //start ADC + adc_hal_digi_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + + return ESP_OK; +} + +esp_err_t adc_digi_stop(void) +{ + if (s_adc_digi_ctx->driver_start_flag != 1) { + ESP_LOGE(ADC_TAG, "The driver is already stopped"); + return ESP_ERR_INVALID_STATE; + } + s_adc_digi_ctx->driver_start_flag = 0; + + //disable the in suc eof intrrupt + adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); + //clear the in suc eof interrupt + adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); + //stop DMA + adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + //stop ADC + adc_hal_digi_stop(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + adc_hal_digi_deinit(); + + ADC_DIGI_LOCK_RELEASE(); + //When using SARADC2 module, this task needs to be protected from WIFI + if (s_adc_digi_ctx->use_adc2) { + SAC_ADC2_LOCK_RELEASE(); + } + + return ESP_OK; +} + +esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms) +{ + TickType_t ticks_to_wait; + esp_err_t ret = ESP_OK; + uint8_t *data = NULL; + size_t size = 0; + + ticks_to_wait = timeout_ms / portTICK_RATE_MS; + if (timeout_ms == ADC_MAX_DELAY) { + ticks_to_wait = portMAX_DELAY; + } + + data = xRingbufferReceiveUpTo(s_adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max); + if (!data) { + ESP_LOGW(ADC_DMA_TAG, "No data, increase timeout or reduce conv_num_each_intr"); + ret = ESP_ERR_TIMEOUT; + *out_length = 0; + return ret; + } + + memcpy(buf, data, size); + vRingbufferReturnItem(s_adc_digi_ctx->ringbuf_hdl, data); + assert((size % 4) == 0); + *out_length = size; + + if (s_adc_digi_ctx->ringbuf_overflow_flag) { + ret = ESP_ERR_INVALID_STATE; + } + return ret; +} + +esp_err_t adc_digi_deinitialize(void) +{ + if (!s_adc_digi_ctx) { + return ESP_ERR_INVALID_STATE; + } + + if (s_adc_digi_ctx->driver_start_flag != 0) { + ESP_LOGE(ADC_TAG, "The driver is not stopped"); + return ESP_ERR_INVALID_STATE; + } + + if (s_adc_digi_ctx->dma_intr_hdl) { + esp_intr_free(s_adc_digi_ctx->dma_intr_hdl); + } + + if(s_adc_digi_ctx->ringbuf_hdl) { + vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl); + s_adc_digi_ctx->ringbuf_hdl = NULL; + } + + free(s_adc_digi_ctx->hal_dma_config.rx_desc); + free(s_adc_digi_ctx->digi_controller_config.adc_pattern); + free(s_adc_digi_ctx); + s_adc_digi_ctx = NULL; + + periph_module_disable(PERIPH_SARADC_MODULE); + periph_module_disable(PERIPH_GDMA_MODULE); + + return ESP_OK; +} + +/*--------------------------------------------------------------- + ADC Single Read Mode +---------------------------------------------------------------*/ +static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC1, used by single read API +static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC2, used by single read API + +esp_err_t adc1_config_width(adc_bits_width_t width_bit) +{ + //On ESP32C3, the data width is always 13-bits. + if (width_bit != ADC_WIDTH_BIT_13) { + return ESP_ERR_INVALID_ARG; + } + + return ESP_OK; +} + +esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten) +{ + ADC_CHANNEL_CHECK(ADC_NUM_1, channel); + ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG); + + esp_err_t ret = ESP_OK; + s_atten1_single[channel] = atten; + ret = adc_digi_gpio_init(ADC_NUM_1, BIT(channel)); + + return ret; +} + +int adc1_get_raw(adc1_channel_t channel) +{ + int result = 0; + adc_digi_config_t dig_cfg = { + .conv_limit_en = 0, + .conv_limit_num = 250, + .interval = 40, + .dig_clk.use_apll = 0, + .dig_clk.div_num = 1, + .dig_clk.div_a = 0, + .dig_clk.div_b = 1, + }; + + ADC_DIGI_LOCK_ACQUIRE(); + + adc_hal_digi_controller_config(&dig_cfg); + + adc_hal_intr_clear(ADC_EVENT_ADC1_DONE); + + adc_hal_onetime_channel(ADC_NUM_1, channel); + adc_hal_set_onetime_atten(s_atten1_single[channel]); + + adc_hal_adc1_onetime_sample_enable(true); + //Trigger single read. + adc_hal_onetime_start(&dig_cfg); + + while (!adc_hal_intr_get_raw(ADC_EVENT_ADC1_DONE)); + adc_hal_intr_clear(ADC_EVENT_ADC1_DONE); + adc_hal_adc1_onetime_sample_enable(false); + + result = adc_hal_adc1_read(); + adc_hal_digi_deinit(); + + ADC_DIGI_LOCK_RELEASE(); + + return result; +} + +esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten) +{ + ADC_CHANNEL_CHECK(ADC_NUM_2, channel); + ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG); + + esp_err_t ret = ESP_OK; + s_atten2_single[channel] = atten; + ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel)); + + return ret; +} + +esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out) +{ + //On ESP32C3, the data width is always 13-bits. + if (width_bit != ADC_WIDTH_BIT_13) { + return ESP_ERR_INVALID_ARG; + } + + adc_digi_config_t dig_cfg = { + .conv_limit_en = 0, + .conv_limit_num = 250, + .interval = 40, + .dig_clk.use_apll = 0, + .dig_clk.div_num = 1, + .dig_clk.div_a = 0, + .dig_clk.div_b = 1, + }; + + SAC_ADC2_LOCK_ACQUIRE(); + ADC_DIGI_LOCK_ACQUIRE(); + + adc_hal_digi_controller_config(&dig_cfg); + + adc_hal_intr_clear(ADC_EVENT_ADC2_DONE); + + adc_hal_onetime_channel(ADC_NUM_2, channel); + adc_hal_set_onetime_atten(s_atten2_single[channel]); + + adc_hal_adc2_onetime_sample_enable(true); + //Trigger single read. + adc_hal_onetime_start(&dig_cfg); + + while (!adc_hal_intr_get_raw(ADC_EVENT_ADC2_DONE)); + adc_hal_intr_clear(ADC_EVENT_ADC2_DONE); + adc_hal_adc2_onetime_sample_enable(false); + + *raw_out = adc_hal_adc2_read(); + adc_hal_digi_deinit(); + + ADC_DIGI_LOCK_RELEASE(); + SAC_ADC2_LOCK_RELEASE(); + + return ESP_OK; +} + + /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) { - esp_err_t ret = ESP_OK; - ADC_ENTER_CRITICAL(); - adc_hal_digi_controller_config(config); - ADC_EXIT_CRITICAL(); - return ret; + if (!s_adc_digi_ctx) { + return ESP_ERR_INVALID_STATE; + } + + s_adc_digi_ctx->digi_controller_config.conv_limit_en = config->conv_limit_en; + s_adc_digi_ctx->digi_controller_config.conv_limit_num = config->conv_limit_num; + s_adc_digi_ctx->digi_controller_config.adc_pattern_len = config->adc_pattern_len; + s_adc_digi_ctx->digi_controller_config.interval = config->interval; + s_adc_digi_ctx->digi_controller_config.dig_clk = config-> dig_clk; + s_adc_digi_ctx->digi_controller_config.dma_eof_num = config->dma_eof_num; + memcpy(s_adc_digi_ctx->digi_controller_config.adc_pattern, config->adc_pattern, config->adc_pattern_len * sizeof(adc_digi_pattern_table_t)); + + //See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver + s_adc_digi_ctx->use_adc2 = 0; + for (int i = 0; i < config->adc_pattern_len; i++) { + if (config->adc_pattern->unit == ADC_NUM_2) { + s_adc_digi_ctx->use_adc2 = 1; + } + } + + return ESP_OK; } esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config) @@ -176,7 +633,6 @@ esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable) * @brief Get the filtered data of adc digital controller filter. For debug. * The data after each measurement and filtering is updated to the DMA by the digital controller. But it can also be obtained manually through this API. * - * @note For ESP32S2, The filter will filter all the enabled channel data of the each ADC unit at the same time. * @param idx Filter index. * @return Filtered data. if <0, the read data invalid. */ @@ -270,7 +726,7 @@ uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit) return ret; } -static uint8_t s_isr_registered = 0; +static bool s_isr_registered = 0; static intr_handle_t s_adc_isr_handle = NULL; esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags) @@ -300,291 +756,3 @@ esp_err_t adc_digi_isr_deregister(void) /*--------------------------------------------------------------- RTC controller setting ---------------------------------------------------------------*/ - - -//This feature is currently supported on ESP32C3, will be supported on other chips soon -/*--------------------------------------------------------------- - DMA setting ----------------------------------------------------------------*/ -#include "soc/system_reg.h" -#include "hal/dma_types.h" -#include "hal/gdma_ll.h" -#include "hal/adc_hal.h" -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "freertos/ringbuf.h" -#include - -#define INTERNAL_BUF_NUM 5 -#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF - -typedef struct adc_digi_context_t { - intr_handle_t dma_intr_hdl; //MD interrupt handle - uint32_t bytes_between_intr; //bytes between in suc eof intr - uint8_t *rx_dma_buf; //dma buffer - adc_dma_hal_context_t hal_dma; //dma context (hal) - adc_dma_hal_config_t hal_dma_config; //dma config (hal) - RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler - bool ringbuf_overflow_flag; //1: ringbuffer overflow - bool driver_state_flag; //1: driver is started; 2: driver is stoped -} adc_digi_context_t; - - -static const char* ADC_DMA_TAG = "ADC_DMA:"; -static adc_digi_context_t *adc_digi_ctx = NULL; - -static void adc_dma_intr(void* arg); - -static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel) -{ - return adc_channel_io_map[adc_unit][adc_channel]; -} - -static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask) -{ - esp_err_t ret = ESP_OK; - uint64_t gpio_mask = 0; - uint32_t n = 0; - int8_t io = 0; - - while (channel_mask) { - if (channel_mask & 0x1) { - io = adc_digi_get_io_num(adc_unit, n); - if (io < 0) { - return ESP_ERR_INVALID_ARG; - } - gpio_mask |= BIT64(io); - } - channel_mask = channel_mask >> 1; - n++; - } - - gpio_config_t cfg = { - .pin_bit_mask = gpio_mask, - .mode = GPIO_MODE_DISABLE, - }; - gpio_config(&cfg); - - return ret; -} - -esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) -{ - esp_err_t ret = ESP_OK; - - adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t)); - if (adc_digi_ctx == NULL) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } - - ret = esp_intr_alloc(SOC_GDMA_ADC_INTR_SOURCE, 0, adc_dma_intr, (void *)adc_digi_ctx, &adc_digi_ctx->dma_intr_hdl); - if (ret != ESP_OK) { - goto cleanup; - } - - //ringbuffer - adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF); - if (!adc_digi_ctx->ringbuf_hdl) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } - - //malloc internal buffer - adc_digi_ctx->bytes_between_intr = init_config->conv_num_each_intr; - adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, adc_digi_ctx->bytes_between_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL); - if (!adc_digi_ctx->rx_dma_buf) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } - - //malloc dma descriptor - adc_digi_ctx->hal_dma_config.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA); - if (!adc_digi_ctx->hal_dma_config.rx_desc) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } - adc_digi_ctx->hal_dma_config.desc_max_num = INTERNAL_BUF_NUM; - adc_digi_ctx->hal_dma_config.dma_chan = init_config->dma_chan; - - if (init_config->adc1_chan_mask) { - ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask); - if (ret != ESP_OK) { - goto cleanup; - } - } - if (init_config->adc2_chan_mask) { - ret = adc_digi_gpio_init(ADC_NUM_2, init_config->adc2_chan_mask); - if (ret != ESP_OK) { - goto cleanup; - } - } - - periph_module_enable(PERIPH_SARADC_MODULE); - periph_module_enable(PERIPH_GDMA_MODULE); - adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); - ADC_ENTER_CRITICAL(); - adc_hal_init(); - adc_hal_arbiter_config(&config); - adc_hal_digi_init(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); - ADC_EXIT_CRITICAL(); - - return ret; - -cleanup: - adc_digi_deinitialize(); - return ret; - -} - -static IRAM_ATTR void adc_dma_intr(void *arg) -{ - portBASE_TYPE taskAwoken = 0; - BaseType_t ret; - - //clear the in suc eof interrupt - adc_hal_digi_clr_intr(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); - - while (adc_digi_ctx->hal_dma_config.cur_desc_ptr->dw0.owner == 0) { - - dma_descriptor_t *current_desc = adc_digi_ctx->hal_dma_config.cur_desc_ptr; - ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken); - if (ret == pdFALSE) { - //ringbuffer overflow - adc_digi_ctx->ringbuf_overflow_flag = 1; - } - - adc_digi_ctx->hal_dma_config.desc_cnt += 1; - //cycle the dma descriptor and buffers - adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.cur_desc_ptr->next; - if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) { - break; - } - } - - if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) { - - assert(adc_digi_ctx->hal_dma_config.desc_cnt == adc_digi_ctx->hal_dma_config.desc_max_num); - //reset the current descriptor status - adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.rx_desc; - adc_digi_ctx->hal_dma_config.desc_cnt = 0; - - //start next turns of dma operation - adc_hal_digi_rxdma_start(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); - } - - if(taskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } -} - -esp_err_t adc_digi_start(void) -{ - assert(adc_digi_ctx->driver_state_flag == 0 && "the driver is already started"); - //reset flags - adc_digi_ctx->ringbuf_overflow_flag = 0; - adc_digi_ctx->driver_state_flag = 1; - - //create dma descriptors - adc_hal_digi_dma_multi_descriptor(&adc_digi_ctx->hal_dma_config, adc_digi_ctx->rx_dma_buf, adc_digi_ctx->bytes_between_intr, adc_digi_ctx->hal_dma_config.desc_max_num); - adc_hal_digi_set_eof_num(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, (adc_digi_ctx->bytes_between_intr)/4); - //set the current descriptor pointer - adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.rx_desc; - adc_digi_ctx->hal_dma_config.desc_cnt = 0; - - //enable in suc eof intr - adc_hal_digi_ena_intr(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, GDMA_LL_EVENT_RX_SUC_EOF); - //start DMA - adc_hal_digi_rxdma_start(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); - //start ADC - adc_hal_digi_start(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); - - return ESP_OK; -} - -esp_err_t adc_digi_stop(void) -{ - assert(adc_digi_ctx->driver_state_flag == 1 && "the driver is already stoped"); - adc_digi_ctx->driver_state_flag = 0; - - //disable the in suc eof intrrupt - adc_hal_digi_dis_intr(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); - //clear the in suc eof interrupt - adc_hal_digi_clr_intr(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); - //stop DMA - adc_hal_digi_rxdma_stop(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); - //stop ADC - adc_hal_digi_stop(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); - - return ESP_OK; -} - -esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms) -{ - TickType_t ticks_to_wait; - esp_err_t ret = ESP_OK; - uint8_t *data = NULL; - size_t size = 0; - - ticks_to_wait = timeout_ms / portTICK_RATE_MS; - if (timeout_ms == ADC_MAX_DELAY) { - ticks_to_wait = portMAX_DELAY; - } - - data = xRingbufferReceiveUpTo(adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max); - if (!data) { - ESP_EARLY_LOGW(ADC_DMA_TAG, "No data, increase timeout or reduce conv_num_each_intr"); - ret = ESP_ERR_TIMEOUT; - *out_length = 0; - return ret; - } - - memcpy(buf, data, size); - vRingbufferReturnItem(adc_digi_ctx->ringbuf_hdl, data); - assert((size % 4) == 0); - *out_length = size; - - if (adc_digi_ctx->ringbuf_overflow_flag) { - ret = ESP_ERR_INVALID_STATE; - } - return ret; -} - -static esp_err_t adc_digi_deinit(void) -{ - ADC_ENTER_CRITICAL(); - adc_hal_digi_deinit(); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_deinitialize(void) -{ - assert(adc_digi_ctx->driver_state_flag == 0 && "the driver is not stoped"); - - if (adc_digi_ctx == NULL) { - return ESP_ERR_INVALID_STATE; - } - - if (adc_digi_ctx->dma_intr_hdl) { - esp_intr_free(adc_digi_ctx->dma_intr_hdl); - } - - if(adc_digi_ctx->ringbuf_hdl) { - vRingbufferDelete(adc_digi_ctx->ringbuf_hdl); - adc_digi_ctx->ringbuf_hdl = NULL; - } - - if (adc_digi_ctx->hal_dma_config.rx_desc) { - free(adc_digi_ctx->hal_dma_config.rx_desc); - } - - free(adc_digi_ctx); - adc_digi_ctx = NULL; - - adc_digi_deinit(); - periph_module_disable(PERIPH_SARADC_MODULE); - periph_module_disable(PERIPH_GDMA_MODULE); - - return ESP_OK; -} diff --git a/components/driver/esp32c3/include/driver/adc.h b/components/driver/esp32c3/include/driver/adc.h index 197af316d4..463778a3a9 100644 --- a/components/driver/esp32c3/include/driver/adc.h +++ b/components/driver/esp32c3/include/driver/adc.h @@ -1,4 +1,4 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -57,8 +57,6 @@ esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx); /** * @brief Set adc digital controller filter configuration. * - * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. - * * @param idx Filter index. * @param config See ``adc_digi_filter_t``. * @@ -70,8 +68,6 @@ esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_ /** * @brief Get adc digital controller filter configuration. * - * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. - * * @param idx Filter index. * @param config See ``adc_digi_filter_t``. * @@ -84,8 +80,6 @@ esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_ * @brief Enable/disable adc digital controller filter. * Filtering the ADC data to obtain smooth data at higher sampling rates. * - * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. - * * @param idx Filter index. * @param enable Enable/Disable filter. * @@ -101,8 +95,6 @@ esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable); /** * @brief Config monitor of adc digital controller. * - * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * * @param idx Monitor index. * @param config See ``adc_digi_monitor_t``. * @@ -114,8 +106,6 @@ esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monit /** * @brief Enable/disable monitor of adc digital controller. * - * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * * @param idx Monitor index. * @param enable True or false enable monitor. * diff --git a/components/driver/include/driver/adc_common.h b/components/driver/include/driver/adc_common.h index 3f0b49dc4c..b0dfd1e659 100644 --- a/components/driver/include/driver/adc_common.h +++ b/components/driver/include/driver/adc_common.h @@ -307,10 +307,8 @@ esp_err_t adc_set_clk_div(uint8_t clk_div); /** * @brief Configure ADC capture width. * - * @note ESP32-S2 only supports ``ADC_WIDTH_BIT_13``. - * * @param adc_unit ADC unit index - * @param width_bit Bit capture width for ADC unit. ESP32-S2 only supports ``ADC_WIDTH_BIT_13``. + * @param width_bit Bit capture width for ADC unit. * * @return * - ESP_OK success @@ -397,7 +395,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten); * the low priority controller will read the invalid ADC2 data. Default priority: Wi-Fi > RTC > Digital; * * @param channel ADC2 channel to read - * @param width_bit Bit capture width for ADC2. ESP32-S2 only supports ``ADC_WIDTH_BIT_13``. + * @param width_bit Bit capture width for ADC2 * @param raw_out the variable to hold the output data. * * @return @@ -466,7 +464,8 @@ esp_err_t adc_digi_deinit(void); * @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``. * * @return - * - ESP_OK Success + * - ESP_ERR_INVALID_STATE Driver state is invalid. + * - ESP_OK On success */ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config); @@ -492,6 +491,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config); * @brief Start the Digital ADC and DMA peripherals. After this, the hardware starts working. * * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. * - ESP_OK On success */ esp_err_t adc_digi_start(void); @@ -500,6 +500,7 @@ esp_err_t adc_digi_start(void); * @brief Stop the Digital ADC and DMA peripherals. After this, the hardware stops working. * * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. * - ESP_OK On success */ esp_err_t adc_digi_stop(void); diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 6b4b2654cb..55576a1e4c 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -1,4 +1,4 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,8 +13,11 @@ // limitations under the License. #include "hal/adc_hal.h" -#if !CONFIG_IDF_TARGET_ESP32C3 #include "hal/adc_hal_conf.h" + +#if CONFIG_IDF_TARGET_ESP32C3 +#include "soc/soc.h" +#include "esp_rom_sys.h" #endif void adc_hal_init(void) @@ -122,4 +125,109 @@ void adc_hal_digi_init(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t gdma_ll_clear_interrupt_status(adc_dma_ctx->dev, dma_config->dma_chan, UINT32_MAX); gdma_ll_rx_connect_to_periph(adc_dma_ctx->dev, dma_config->dma_chan, GDMA_LL_TRIG_SRC_ADC_DAC); } + +/*--------------------------------------------------------------- + Single Read +---------------------------------------------------------------*/ +void adc_hal_onetime_start(adc_digi_config_t *adc_digi_config) +{ + /** + * There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the + * ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller + * clock cycle. + * + * This limitation will be removed in hardware future versions. + * + */ + uint32_t digi_clk = APB_CLK_FREQ / (adc_digi_config->dig_clk.div_num + adc_digi_config->dig_clk.div_a / adc_digi_config->dig_clk.div_b + 1); + //Convert frequency to time (us). Since decimals are removed by this division operation. Add 1 here in case of the fact that delay is not enough. + uint32_t delay = (1000 * 1000) / digi_clk + 1; + //3 ADC digital controller clock cycle + delay = delay * 3; + //This coefficient (8) is got from test. When digi_clk is not smaller than ``APB_CLK_FREQ/8``, no delay is needed. + if (digi_clk >= APB_CLK_FREQ/8) { + delay = 0; + } + + adc_ll_onetime_start(false); + esp_rom_delay_us(delay); + adc_ll_onetime_start(true); + //No need to delay here. Becuase if the start signal is not seen, there won't be a done intr. +} + +void adc_hal_adc1_onetime_sample_enable(bool enable) +{ + if (enable) { + adc_ll_adc1_onetime_sample_ena(); + } else { + adc_ll_adc1_onetime_sample_dis(); + } +} + +void adc_hal_adc2_onetime_sample_enable(bool enable) +{ + if (enable) { + adc_ll_adc2_onetime_sample_ena(); + } else { + adc_ll_adc2_onetime_sample_dis(); + } +} + +void adc_hal_onetime_channel(adc_ll_num_t unit, adc_channel_t channel) +{ + adc_ll_onetime_set_channel(unit, channel); +} + +void adc_hal_set_onetime_atten(adc_atten_t atten) +{ + adc_ll_onetime_set_atten(atten); +} + +uint32_t adc_hal_adc1_read(void) +{ + return adc_ll_adc1_read(); +} + +uint32_t adc_hal_adc2_read(void) +{ + return adc_ll_adc2_read(); +} + +//--------------------INTR------------------------------- +static adc_ll_intr_t get_event_intr(adc_event_t event) +{ + adc_ll_intr_t intr_mask = 0; + if (event & ADC_EVENT_ADC1_DONE) { + intr_mask |= ADC_LL_INTR_ADC1_DONE; + } + if (event & ADC_EVENT_ADC2_DONE) { + intr_mask |= ADC_LL_INTR_ADC2_DONE; + } + return intr_mask; +} + +void adc_hal_intr_enable(adc_event_t event) +{ + adc_ll_intr_enable(get_event_intr(event)); +} + +void adc_hal_intr_disable(adc_event_t event) +{ + adc_ll_intr_disable(get_event_intr(event)); +} + +void adc_hal_intr_clear(adc_event_t event) +{ + adc_ll_intr_clear(get_event_intr(event)); +} + +bool adc_hal_intr_get_raw(adc_event_t event) +{ + return adc_ll_intr_get_raw(get_event_intr(event)); +} + +bool adc_hal_intr_get_status(adc_event_t event) +{ + return adc_ll_intr_get_status(get_event_intr(event)); +} #endif diff --git a/components/soc/esp32c3/include/soc/adc_caps.h b/components/hal/esp32c3/include/hal/adc_hal_conf.h similarity index 75% rename from components/soc/esp32c3/include/soc/adc_caps.h rename to components/hal/esp32c3/include/hal/adc_hal_conf.h index 6572961ade..02e43632d2 100644 --- a/components/soc/esp32c3/include/soc/adc_caps.h +++ b/components/hal/esp32c3/include/hal/adc_hal_conf.h @@ -11,14 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #pragma once -#define SOC_ADC_PERIPH_NUM (2) -#define SOC_ADC_PATT_LEN_MAX (16) - -#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10) -#define SOC_ADC_MAX_CHANNEL_NUM (10) - #define SOC_ADC1_DATA_INVERT_DEFAULT (0) #define SOC_ADC2_DATA_INVERT_DEFAULT (0) @@ -29,14 +24,6 @@ #define SOC_ADC_FSM_STANDBY_WAIT_DEFAULT (100) #define ADC_FSM_SAMPLE_CYCLE_DEFAULT (2) -/** - * Check if adc support digital controller (DMA) mode. - * @value - * - 1 : support; - * - 0 : not support; - */ -#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) ((PERIPH_NUM==0)? 1: 1) - #define SOC_ADC_PWDET_CCT_DEFAULT (4) #define SOC_ADC_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) ((PERIPH_NUM==0)? 2 : 1) diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h index 31d0da4e05..4e923babb5 100644 --- a/components/hal/esp32c3/include/hal/adc_ll.h +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -22,6 +22,8 @@ #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" #include "regi2c_ctrl.h" +#include "esp_attr.h" + #ifdef __cplusplus extern "C" { @@ -47,6 +49,12 @@ typedef enum { ADC_RTC_DATA_FAIL = -1, } adc_ll_rtc_raw_data_t; +typedef enum { + ADC_LL_INTR_ADC2_DONE = BIT(30), + ADC_LL_INTR_ADC1_DONE = BIT(31), +} adc_ll_intr_t; +FLAG_ATTR(adc_ll_intr_t) + #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ @@ -927,6 +935,87 @@ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t par abort(); // TODO ESP32-C3 IDF-2526 } +/*--------------------------------------------------------------- + Single Read +---------------------------------------------------------------*/ +/** + * Trigger single read + * + * @param val Usage: set to 1 to start the ADC conversion. The step signal should at least keep 3 ADC digital controller clock cycle, + * otherwise the step signal may not be captured by the ADC digital controller when its frequency is slow. + * This hardware limitation will be removed in future versions. + */ +static inline void adc_ll_onetime_start(bool val) +{ + APB_SARADC.onetime_sample.onetime_start = val; +} + +static inline void adc_ll_onetime_set_channel(adc_ll_num_t unit, adc_channel_t channel) +{ + APB_SARADC.onetime_sample.onetime_channel = ((unit << 3) | channel); +} + +static inline void adc_ll_onetime_set_atten(adc_atten_t atten) +{ + APB_SARADC.onetime_sample.onetime_atten = atten; +} + +static inline void adc_ll_intr_enable(adc_ll_intr_t mask) +{ + APB_SARADC.int_ena.val |= mask; +} + +static inline void adc_ll_intr_disable(adc_ll_intr_t mask) +{ + APB_SARADC.int_ena.val &= ~mask; +} + +static inline void adc_ll_intr_clear(adc_ll_intr_t mask) +{ + APB_SARADC.int_clr.val |= mask; +} + +static inline bool adc_ll_intr_get_raw(adc_ll_intr_t mask) +{ + return (APB_SARADC.int_raw.val & mask); +} + +static inline bool adc_ll_intr_get_status(adc_ll_intr_t mask) +{ + return (APB_SARADC.int_st.val & mask); +} + +//--------------------------------adc1------------------------------// +static inline void adc_ll_adc1_onetime_sample_ena(void) +{ + APB_SARADC.onetime_sample.adc1_onetime_sample = 1; +} + +static inline void adc_ll_adc1_onetime_sample_dis(void) +{ + APB_SARADC.onetime_sample.adc1_onetime_sample = 0; +} + +static inline uint32_t adc_ll_adc1_read(void) +{ + return APB_SARADC.apb_saradc1_data_status.adc1_data; +} + +//--------------------------------adc2------------------------------// +static inline void adc_ll_adc2_onetime_sample_ena(void) +{ + APB_SARADC.onetime_sample.adc2_onetime_sample = 1; +} + +static inline void adc_ll_adc2_onetime_sample_dis(void) +{ + APB_SARADC.onetime_sample.adc2_onetime_sample = 0; +} + +static inline uint32_t adc_ll_adc2_read(void) +{ + return APB_SARADC.apb_saradc2_data_status.adc2_data; +} #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index a2cfe407dc..ea952b6472 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -245,4 +245,32 @@ void adc_hal_digi_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t void adc_hal_digi_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); void adc_hal_digi_init(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); + +/*--------------------------------------------------------------- + Single Read +---------------------------------------------------------------*/ +void adc_hal_onetime_start(adc_digi_config_t *adc_digi_config); + +void adc_hal_adc1_onetime_sample_enable(bool enable); + +void adc_hal_adc2_onetime_sample_enable(bool enable); + +void adc_hal_onetime_channel(adc_ll_num_t unit, adc_channel_t channel); + +void adc_hal_set_onetime_atten(adc_atten_t atten); + +uint32_t adc_hal_adc1_read(void); + +uint32_t adc_hal_adc2_read(void); + +void adc_hal_intr_enable(adc_event_t event); + +void adc_hal_intr_disable(adc_event_t event); + +void adc_hal_intr_clear(adc_event_t event); + +bool adc_hal_intr_get_raw(adc_event_t event); + +bool adc_hal_intr_get_status(adc_event_t event); + #endif //#if CONFIG_IDF_TARGET_ESP32C3 diff --git a/components/hal/include/hal/adc_types.h b/components/hal/include/hal/adc_types.h index 6f6f0e9613..dea8ab0ec1 100644 --- a/components/hal/include/hal/adc_types.h +++ b/components/hal/include/hal/adc_types.h @@ -81,16 +81,15 @@ typedef enum { /** * @brief ADC resolution setting option. * - * @note For ESP32-S2. Only 13 bit resolution is supported. - * For ESP32. 13 bit resolution is not supported. */ typedef enum { - ADC_WIDTH_BIT_9 = 0, /*!< ADC capture width is 9Bit. Only ESP32 is supported. */ - ADC_WIDTH_BIT_10 = 1, /*!< ADC capture width is 10Bit. Only ESP32 is supported. */ - ADC_WIDTH_BIT_11 = 2, /*!< ADC capture width is 11Bit. Only ESP32 is supported. */ - ADC_WIDTH_BIT_12 = 3, /*!< ADC capture width is 12Bit. Only ESP32 is supported. */ -#if !CONFIG_IDF_TARGET_ESP32 - ADC_WIDTH_BIT_13 = 4, /*!< ADC capture width is 13Bit. Only ESP32-S2 is supported. */ +#if CONFIG_IDF_TARGET_ESP32 + ADC_WIDTH_BIT_9 = 0, /*!< ADC capture width is 9Bit. */ + ADC_WIDTH_BIT_10 = 1, /*!< ADC capture width is 10Bit. */ + ADC_WIDTH_BIT_11 = 2, /*!< ADC capture width is 11Bit. */ + ADC_WIDTH_BIT_12 = 3, /*!< ADC capture width is 12Bit. */ +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + ADC_WIDTH_BIT_13 = 4, /*!< ADC capture width is 13Bit. */ #endif ADC_WIDTH_MAX, } adc_bits_width_t; @@ -196,7 +195,7 @@ typedef struct { If (channel > ADC_CHANNEL_MAX), The data is invalid. */ uint32_t unit: 1; /*! Date: Mon, 21 Dec 2020 10:22:18 +1100 Subject: [PATCH 8/9] driver: Only build dedic_gpio driver on supported chips --- components/driver/CMakeLists.txt | 1 - components/driver/component.mk | 2 +- components/driver/dedic_gpio.c | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index c0b8b11c43..83d232bf6e 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -27,7 +27,6 @@ if(${target} STREQUAL "esp32") # SDMMC and MCPWM are in ESP32 only. list(APPEND srcs "adc_common.c" "dac_common.c" - "dedic_gpio.c" "mcpwm.c" "sdio_slave.c" "sdmmc_host.c" diff --git a/components/driver/component.mk b/components/driver/component.mk index 382e1b490d..6da3a56f15 100644 --- a/components/driver/component.mk +++ b/components/driver/component.mk @@ -2,7 +2,7 @@ # Component Makefile # COMPONENT_SRCDIRS := . $(IDF_TARGET) -COMPONENT_OBJEXCLUDE += spi_slave_hd.o +COMPONENT_OBJEXCLUDE += spi_slave_hd.o dedic_gpio.o COMPONENT_ADD_INCLUDEDIRS := include $(IDF_TARGET)/include $(IDF_TARGET)/include/driver diff --git a/components/driver/dedic_gpio.c b/components/driver/dedic_gpio.c index 89909821e1..118c9aa5d0 100644 --- a/components/driver/dedic_gpio.c +++ b/components/driver/dedic_gpio.c @@ -28,7 +28,6 @@ #include "driver/periph_ctrl.h" #include "esp_rom_gpio.h" #include "freertos/FreeRTOS.h" -#if SOC_DEDICATED_GPIO_SUPPORTED #include "driver/dedic_gpio.h" #include "soc/dedic_gpio_periph.h" #if SOC_DEDIC_GPIO_ALLOW_REG_ACCESS @@ -402,4 +401,3 @@ err: return ret_code; } #endif // SOC_DEDIC_GPIO_HAS_INTERRUPT -#endif // SOC_DEDICATED_GPIO_SUPPORTED From 04c681443eae5c446279e2cbde43dd8dcc0cebf2 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 22 Dec 2020 15:16:17 +1100 Subject: [PATCH 9/9] hal esp32c3: Add placeholder rtc_io_ll.h --- .../hal/esp32c3/include/hal/rtc_io_ll.h | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 components/hal/esp32c3/include/hal/rtc_io_ll.h diff --git a/components/hal/esp32c3/include/hal/rtc_io_ll.h b/components/hal/esp32c3/include/hal/rtc_io_ll.h new file mode 100644 index 0000000000..624b8e3ae1 --- /dev/null +++ b/components/hal/esp32c3/include/hal/rtc_io_ll.h @@ -0,0 +1,145 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/******************************************************************************* + * NOTICE + * The ll is not public api, don't use in application code. + * See readme.md in soc/include/hal/readme.md + ******************************************************************************/ + + +/* Note: ESP32-C3 does not have a full RTC_IO module, this LL only controls + hold/wakeup/32kHz crystal functions for IOs */ + +#pragma once + +#include +#include "soc/rtc_cntl_reg.h" +#include "hal/rtc_io_types.h" +#include "hal/gpio_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + RTCIO_FUNC_RTC = 0x0, /*!< The pin controled by RTC module. */ + RTCIO_FUNC_DIGITAL = 0x1, /*!< The pin controlled by DIGITAL module. */ +} rtcio_ll_func_t; + +typedef enum { + RTCIO_WAKEUP_DISABLE = 0, /*!< Disable GPIO interrupt */ + RTCIO_WAKEUP_LOW_LEVEL = 0x4, /*!< GPIO interrupt type : input low level trigger */ + RTCIO_WAKEUP_HIGH_LEVEL = 0x5, /*!< GPIO interrupt type : input high level trigger */ +} rtcio_ll_wake_type_t; + +typedef enum { + RTCIO_OUTPUT_NORMAL = 0, /*!< RTCIO output mode is normal. */ + RTCIO_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */ +} rtcio_ll_out_mode_t; + +/** + * @brief Select the rtcio function. + * + * @note The RTC function must be selected before the pad analog function is enabled. + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param func Select pin function. + */ +static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) +{ + abort(); // TODO ESP32-C3 IDF-2407 +} + +/** + * Enable force hold function for RTC IO pad. + * + * Enabling HOLD function will cause the pad to lock current status, such as, + * input/output enable, input/output value, function, drive strength values. + * This function is useful when going into light or deep sleep mode to prevent + * the pin configuration from changing. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + */ +static inline void rtcio_ll_force_hold_enable(int rtcio_num) +{ + abort(); // TODO ESP32-C3 IDF-2407 +} + +/** + * Disable hold function on an RTC IO pad + * + * @note If disable the pad hold, the status of pad maybe changed in sleep mode. + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + */ +static inline void rtcio_ll_force_hold_disable(int rtcio_num) +{ + abort(); // TODO ESP32-C3 IDF-2407 +} + +/** + * Enable force hold function for RTC IO pad. + * + * Enabling HOLD function will cause the pad to lock current status, such as, + * input/output enable, input/output value, function, drive strength values. + * This function is useful when going into light or deep sleep mode to prevent + * the pin configuration from changing. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + */ +static inline void rtcio_ll_force_hold_all(void) +{ + abort(); // TODO ESP32-C3 IDF-2407 +} + +/** + * Disable hold function on an RTC IO pad + * + * @note If disable the pad hold, the status of pad maybe changed in sleep mode. + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + */ +static inline void rtcio_ll_force_unhold_all(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M); +} + +/** + * Enable wakeup function and set wakeup type from light sleep status for rtcio. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param type Wakeup on high level or low level. + */ +static inline void rtcio_ll_wakeup_enable(int rtcio_num, rtcio_ll_wake_type_t type) +{ + abort(); // TODO ESP32-C3 IDF-2407 +} + +/** + * Disable wakeup function from light sleep status for rtcio. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + */ +static inline void rtcio_ll_wakeup_disable(int rtcio_num) +{ + abort(); // TODO ESP32-C3 IDF-2407 +} + +static inline void rtcio_ll_ext0_set_wakeup_pin(int rtcio_num, int level) +{ + abort(); // TODO ESP32-C3 IDF-2106 IDF-2407 +} + + +#ifdef __cplusplus +} +#endif