diff --git a/components/esp_adc/Kconfig b/components/esp_adc/Kconfig index 0bdf4dd73ea..74f84dbb265 100644 --- a/components/esp_adc/Kconfig +++ b/components/esp_adc/Kconfig @@ -77,6 +77,27 @@ menu "ADC and ADC Calibration" If you stick to this, you can enable this option to force use ADC2 under above conditions. For more details, you can search for errata on espressif website. + config ADC_DIGI_CLK_DIV_DEFAULT + bool "Use default adc clk divisor" + depends on !IDF_TARGET_ESP32 + default y + help + Force use of default digital controller clk divisors. + + config ADC_SARADC_TARGET_CLK + int "Set SARADC target clock frequency" + depends on !ADC_DIGI_CLK_DIV_DEFAULT + default 5280000 + help + The SARADC clock frequency will be set to the nearest integer multiple of sample freq. + The fractional divisor parameters will be calculated at runtime. + + config ADC_CONTINUOUS_NUM_DMA + int "Set the number of DMA buffers" + default 5 + help + Configure the number of DMA buffers used by adc + config ADC_ENABLE_DEBUG_LOG bool "Enable ADC debug log" default n diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index ab63bf393de..b98cd118451 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -55,7 +55,11 @@ 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) +#ifndef CONFIG_ADC_CONTINUOUS_NUM_DMA #define INTERNAL_BUF_NUM 5 +#else +#define INTERNAL_BUF_NUM CONFIG_ADC_CONTINUOUS_NUM_DMA +#endif /*--------------------------------------------------------------- ADC Continuous Read Mode (via DMA) @@ -65,7 +69,7 @@ static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) { BaseType_t taskAwoken = 0; bool need_yield = false; - BaseType_t ret; + BaseType_t ret = 0; adc_hal_dma_desc_status_t status = false; uint8_t *finished_buffer = NULL; uint32_t finished_size = 0; @@ -82,8 +86,10 @@ static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) } #endif - ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); - need_yield |= (taskAwoken == pdTRUE); + if (adc_digi_ctx->ringbuf_hdl) { + ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); + need_yield |= (taskAwoken == pdTRUE); + } if (adc_digi_ctx->cbs.on_conv_done) { adc_continuous_evt_data_t edata = { @@ -95,30 +101,32 @@ static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) } } - if (ret == pdFALSE) { - if (adc_digi_ctx->flags.flush_pool) { - size_t actual_size = 0; - uint8_t *old_data = xRingbufferReceiveUpToFromISR(adc_digi_ctx->ringbuf_hdl, &actual_size, adc_digi_ctx->ringbuf_size); - /** - * Replace by ringbuffer reset API when this API is ready. - * Now we do manual reset. - * For old_data == NULL condition (equals to the future ringbuffer reset fail condition), we don't care this time data, - * as this only happens when the ringbuffer size is small, new data will be filled in soon. - */ - if (old_data) { - vRingbufferReturnItemFromISR(adc_digi_ctx->ringbuf_hdl, old_data, &taskAwoken); - xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); - if (taskAwoken == pdTRUE) { - need_yield |= true; + if (adc_digi_ctx->ringbuf_hdl) { + if (ret == pdFALSE) { + if (adc_digi_ctx->flags.flush_pool) { + size_t actual_size = 0; + uint8_t *old_data = xRingbufferReceiveUpToFromISR(adc_digi_ctx->ringbuf_hdl, &actual_size, adc_digi_ctx->ringbuf_size); + /** + * Replace by ringbuffer reset API when this API is ready. + * Now we do manual reset. + * For old_data == NULL condition (equals to the future ringbuffer reset fail condition), we don't care this time data, + * as this only happens when the ringbuffer size is small, new data will be filled in soon. + */ + if (old_data) { + vRingbufferReturnItemFromISR(adc_digi_ctx->ringbuf_hdl, old_data, &taskAwoken); + xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); + if (taskAwoken == pdTRUE) { + need_yield |= true; + } } } - } - //ringbuffer overflow happens before - if (adc_digi_ctx->cbs.on_pool_ovf) { - adc_continuous_evt_data_t edata = {}; - if (adc_digi_ctx->cbs.on_pool_ovf(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) { - need_yield |= true; + //ringbuffer overflow happens before + if (adc_digi_ctx->cbs.on_pool_ovf) { + adc_continuous_evt_data_t edata = {}; + if (adc_digi_ctx->cbs.on_pool_ovf(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) { + need_yield |= true; + } } } } @@ -174,18 +182,22 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi //ringbuffer storage/struct buffer adc_ctx->ringbuf_size = hdl_config->max_store_buf_size; - adc_ctx->ringbuf_storage = heap_caps_calloc(1, hdl_config->max_store_buf_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - adc_ctx->ringbuf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - if (!adc_ctx->ringbuf_storage || !adc_ctx->ringbuf_struct) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } + if (hdl_config->max_store_buf_size) { + adc_ctx->ringbuf_storage = heap_caps_calloc(1, hdl_config->max_store_buf_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + adc_ctx->ringbuf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!adc_ctx->ringbuf_storage || !adc_ctx->ringbuf_struct) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } - //ringbuffer - adc_ctx->ringbuf_hdl = xRingbufferCreateStatic(hdl_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF, adc_ctx->ringbuf_storage, adc_ctx->ringbuf_struct); - if (!adc_ctx->ringbuf_hdl) { - ret = ESP_ERR_NO_MEM; - goto cleanup; + //ringbuffer + adc_ctx->ringbuf_hdl = xRingbufferCreateStatic(hdl_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF, adc_ctx->ringbuf_storage, adc_ctx->ringbuf_struct); + if (!adc_ctx->ringbuf_hdl) { + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + } else { + adc_ctx->ringbuf_hdl = NULL; } //malloc internal buffer used by DMA @@ -391,6 +403,10 @@ esp_err_t adc_continuous_read(adc_continuous_handle_t handle, uint8_t *buf, uint uint8_t *data = NULL; size_t size = 0; + if (!handle->ringbuf_hdl) { + *out_length = 0; + return ret; + } ticks_to_wait = timeout_ms / portTICK_PERIOD_MS; if (timeout_ms == ADC_MAX_DELAY) { ticks_to_wait = portMAX_DELAY; @@ -564,6 +580,10 @@ esp_err_t adc_continuous_flush_pool(adc_continuous_handle_t handle) size_t actual_size = 0; uint8_t *old_data = NULL; + if (!handle->ringbuf_hdl) { + return ESP_OK; + } + while ((old_data = xRingbufferReceiveUpTo(handle->ringbuf_hdl, &actual_size, 0, handle->ringbuf_size))) { vRingbufferReturnItem(handle->ringbuf_hdl, old_data); } diff --git a/components/esp_driver_i2s/Kconfig b/components/esp_driver_i2s/Kconfig index 72628d820e3..574d80942ef 100644 --- a/components/esp_driver_i2s/Kconfig +++ b/components/esp_driver_i2s/Kconfig @@ -7,6 +7,13 @@ menu "ESP-Driver:I2S Configurations" Ensure the I2S interrupt is IRAM-Safe by allowing the interrupt handler to be executable when the cache is disabled (e.g. SPI Flash write). + config I2S_FORCE_FRAC_DIVISOR + bool "Force fractional divisor for PDM mode on v2 HW" + default y + help + Force fractional part of clock divisor to known value. + This seems to help reducing noise. + config I2S_ENABLE_DEBUG_LOG bool "Enable I2S debug log" default n diff --git a/components/esp_driver_i2s/i2s_pdm.c b/components/esp_driver_i2s/i2s_pdm.c index 919f975a0bf..8cac2d66d7d 100644 --- a/components/esp_driver_i2s/i2s_pdm.c +++ b/components/esp_driver_i2s/i2s_pdm.c @@ -89,10 +89,12 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx I2S_CLOCK_SRC_ATOMIC() { i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); } -#if SOC_I2S_HW_VERSION_2 +#if SOC_I2S_HW_VERSION_2 && I2S_FORCE_FRAC_DIVISOR /* Work around for PDM TX clock, overwrite the raw division directly to reduce the noise * This set of coefficients is a special division to reduce the background noise in PDM TX mode */ i2s_ll_tx_set_raw_clk_div(handle->controller->hal.dev, clk_info.mclk_div, 1, 1, 0, 0); +#else +#warning "I2S PDM clock workaround disabled" #endif portEXIT_CRITICAL(&g_i2s.spinlock); diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 4235e184e21..298662cba55 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -147,6 +147,10 @@ if(NOT non_os_build) list(APPEND srcs "esp_clock_output.c") endif() + if(CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY) + set_source_files_properties(sleep_modes.c PROPERTIES COMPILE_OPTIONS -mtext-section-literals) + endif() + if(CONFIG_SOC_BOD_SUPPORTED) list(APPEND srcs "power_supply/brownout.c") endif() diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 7bfd4576d8d..72b63ad4943 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -330,6 +330,12 @@ static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void { #define _SYM2STR(s) # s #define SYM2STR(s) _SYM2STR(s) + goto __after_literal; + __asm__ __volatile__ ( + ".literal_position \n" + ".align 4 \n" + ); +__after_literal: #ifdef __riscv __asm__ __volatile__ ( diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index e71c70f1de0..e6f003a9eaa 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -8,8 +8,10 @@ #include "sdkconfig.h" #include "hal/adc_hal.h" #include "hal/assert.h" +#include "hal/hal_utils.h" #include "soc/lldesc.h" #include "soc/soc_caps.h" +#include "hal/log.h" #if CONFIG_IDF_TARGET_ESP32 //ADC utilises I2S0 DMA on ESP32 @@ -119,11 +121,32 @@ static adc_ll_digi_convert_mode_t get_convert_mode(adc_digi_convert_mode_t conve static void adc_hal_digi_sample_freq_config(adc_hal_dma_ctx_t *hal, adc_continuous_clk_src_t clk_src, uint32_t clk_src_freq_hz, uint32_t sample_freq_hz) { #if !CONFIG_IDF_TARGET_ESP32 - uint32_t interval = clk_src_freq_hz / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / sample_freq_hz; +#if CONFIG_ADC_DIGI_CLK_DIV_DEFAULT + uint32_t interval = (((long long)clk_src_freq_hz<<10) / (((long long)ADC_LL_CLKM_DIV_NUM_DEFAULT<<10) + ((long long)ADC_LL_CLKM_DIV_B_DEFAULT<<10) / ADC_LL_CLKM_DIV_A_DEFAULT) /sample_freq_hz +1) /2; //set sample interval adc_ll_digi_set_trigger_interval(interval); //Here we set the clock divider factor to make the digital clock to 5M Hz adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT); +#else + uint32_t interval; + hal_utils_clk_info_t digi_clk_info = { + .src_freq_hz = clk_src_freq_hz, + .exp_freq_hz = (CONFIG_ADC_SARADC_TARGET_CLK/sample_freq_hz)*sample_freq_hz, + .max_integ = APB_SARADC_CLKM_DIV_NUM, + .min_integ = 1, + .max_fract = APB_SARADC_CLKM_DIV_A, + }; + hal_utils_clk_div_t clk_div; + hal_utils_calc_clk_div_frac_fast(&digi_clk_info, &clk_div); + interval = (((long long)clk_src_freq_hz<<10) / (((long long)(clk_div.integer)<<10) + ((long long)(clk_div.numerator)<<10) / clk_div.denominator ) / sample_freq_hz +1) /2; + + HAL_EARLY_LOGD("ADC_HAL","sclk = %ld, Div = %ld + %ld/%ld, Interval = %ld, Fs = %ld", clk_src_freq_hz, clk_div.integer, clk_div.numerator, clk_div.denominator, interval, (int32_t)(((int64_t)clk_src_freq_hz*clk_div.denominator / ((clk_div.integer*clk_div.denominator + clk_div.numerator) * interval ) +1) /2)); + + //set sample interval + adc_ll_digi_set_trigger_interval(interval); + //Here we set the clock divider factor to make the digital clock to CONFIG_ADC_SARADC_TARGET_CLK Hz + adc_ll_digi_controller_clk_div(clk_div.integer-1, clk_div.denominator, clk_div.numerator); +#endif adc_ll_digi_clk_sel(clk_src); #else i2s_ll_rx_clk_set_src(adc_hal_i2s_dev, I2S_CLK_SRC_DEFAULT); /*!< Clock from PLL_D2_CLK(160M)*/ diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index 6911924b0d2..2f2d23e2f3f 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -56,8 +56,8 @@ extern "C" { #define ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT (1) #define ADC_LL_CLKM_DIV_NUM_DEFAULT 15 -#define ADC_LL_CLKM_DIV_B_DEFAULT 1 -#define ADC_LL_CLKM_DIV_A_DEFAULT 0 +#define ADC_LL_CLKM_DIV_B_DEFAULT 5 +#define ADC_LL_CLKM_DIV_A_DEFAULT 33 #define ADC_LL_DEFAULT_CONV_LIMIT_EN 0 #define ADC_LL_DEFAULT_CONV_LIMIT_NUM 10 diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 25310ca4de0..dba7d498fdf 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -233,6 +233,9 @@ static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) case I2S_CLK_SRC_XTAL: hw->tx_clkm_conf.tx_clk_sel = 0; break; + case I2S_CLK_SRC_PLL_D2: + hw->tx_clkm_conf.tx_clk_sel = 1; + break; case I2S_CLK_SRC_PLL_160M: hw->tx_clkm_conf.tx_clk_sel = 2; break; @@ -258,6 +261,9 @@ static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) case I2S_CLK_SRC_XTAL: hw->rx_clkm_conf.rx_clk_sel = 0; break; + case I2S_CLK_SRC_PLL_D2: + hw->rx_clkm_conf.rx_clk_sel = 1; + break; case I2S_CLK_SRC_PLL_160M: hw->rx_clkm_conf.rx_clk_sel = 2; break; diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index c445af2761b..4c4daf6223b 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -10,6 +10,7 @@ #include "soc/soc.h" #include "hal/assert.h" #include "hal/i2s_hal.h" +#include "hal/log.h" #if SOC_I2S_HW_VERSION_2 && (SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER) /* PDM tx high pass filter cut-off frequency and coefficients list @@ -58,7 +59,7 @@ void i2s_hal_calc_mclk_precise_division(uint32_t sclk, uint32_t mclk, hal_utils_ .min_integ = 1, .max_fract = I2S_LL_CLK_FRAC_DIV_AB_MAX, }; - hal_utils_calc_clk_div_frac_accurate(&i2s_clk_info, mclk_div); + hal_utils_calc_clk_div_frac_fast(&i2s_clk_info, mclk_div); } void i2s_hal_init(i2s_hal_context_t *hal, int port_id) @@ -114,6 +115,8 @@ void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *cl i2s_hal_calc_mclk_precise_division(clk_info->sclk, clk_info->mclk, &mclk_div); i2s_ll_tx_set_mclk(hal->dev, &mclk_div); i2s_ll_tx_set_bck_div_num(hal->dev, clk_info->bclk_div); + HAL_EARLY_LOGD("I2S_HAL","src_clk = %ld, div = %ld + %ld/%ld, bdiv = %d, Fs = %ld",clk_info->sclk, mclk_div.integer, mclk_div.numerator, mclk_div.denominator, clk_info->bclk_div, + (int32_t)((((int64_t)clk_info->sclk*mclk_div.denominator) / ((mclk_div.integer*mclk_div.denominator + mclk_div.numerator)*clk_info->bclk_div)+64)/128) ); } else { i2s_ll_tx_clk_set_src(hal->dev, clk_src); } diff --git a/components/soc/esp32s3/include/soc/clk_tree_defs.h b/components/soc/esp32s3/include/soc/clk_tree_defs.h index 4f3bea99858..21d00438d94 100644 --- a/components/soc/esp32s3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s3/include/soc/clk_tree_defs.h @@ -301,6 +301,7 @@ typedef enum { */ typedef enum { I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default source clock */ + I2S_CLK_SRC_PLL_D2 = SOC_MOD_CLK_PLL_D2, /*!< Select PLL_D2 as the source clock */ I2S_CLK_SRC_PLL_160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ I2S_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ I2S_CLK_SRC_EXTERNAL = -1, /*!< Select external clock as source clock */