adc_digi: update_adc_api_for_5M_freq_limit

The ``adc_digi_config_t`` struct is modified on esp32c3: configuration
of clock divider factors are not provided anymore. The SARADC sampling
frequency is provided instead. In this way, we can handle the frequency
limit better.
This commit is contained in:
Armando 2020-12-25 14:24:19 +08:00 committed by bot
parent 56919682be
commit d8a4b247b9
10 changed files with 50 additions and 59 deletions

View File

@ -97,7 +97,6 @@ typedef struct adc_digi_context_t {
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;
static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten);
@ -344,7 +343,7 @@ esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_l
data = xRingbufferReceiveUpTo(s_adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max);
if (!data) {
ESP_LOGV(ADC_DMA_TAG, "No data, increase timeout or reduce conv_num_each_intr");
ESP_LOGV(ADC_TAG, "No data, increase timeout or reduce conv_num_each_intr");
ret = ESP_ERR_TIMEOUT;
*out_length = 0;
return ret;
@ -428,11 +427,7 @@ int adc1_get_raw(adc1_channel_t channel)
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 = 15,
.dig_clk.div_a = 0,
.dig_clk.div_b = 1,
.sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH,
};
ADC_DIGI_LOCK_ACQUIRE();
@ -489,11 +484,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
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 = 15,
.dig_clk.div_a = 0,
.dig_clk.div_b = 1,
.sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH,
};
SAC_ADC2_LOCK_ACQUIRE();
@ -540,32 +531,34 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
if (!s_adc_digi_ctx) {
return ESP_ERR_INVALID_STATE;
}
ADC_CHECK(config->sample_freq_hz <= 83333 && config->sample_freq_hz >= 610, "ADC sampling frequency out of range", ESP_ERR_INVALID_ARG);
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;
s_adc_digi_ctx->digi_controller_config.sample_freq_hz = config->sample_freq_hz;
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->adc1_atten = ADC_ATTEN_MAX;
s_adc_digi_ctx->adc2_atten = ADC_ATTEN_MAX;
const int atten_uninitialised = 999;
s_adc_digi_ctx->adc1_atten = atten_uninitialised;
s_adc_digi_ctx->adc2_atten = atten_uninitialised;
s_adc_digi_ctx->use_adc1 = 0;
s_adc_digi_ctx->use_adc2 = 0;
for (int i = 0; i < config->adc_pattern_len; i++) {
const adc_digi_pattern_table_t* pat = &config->adc_pattern[i];
if (pat->unit == ADC_NUM_1) {
s_adc_digi_ctx->use_adc1 = 1;
if (s_adc_digi_ctx->adc1_atten == ADC_ATTEN_MAX) {
if (s_adc_digi_ctx->adc1_atten == atten_uninitialised) {
s_adc_digi_ctx->adc1_atten = pat->atten;
} else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
return ESP_ERR_INVALID_ARG;
}
} else if (pat->unit == ADC_NUM_2) {
//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 = 1;
if (s_adc_digi_ctx->adc2_atten == ADC_ATTEN_MAX) {
if (s_adc_digi_ctx->adc2_atten == atten_uninitialised) {
s_adc_digi_ctx->adc2_atten = pat->atten;
} else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
return ESP_ERR_INVALID_ARG;

View File

@ -477,6 +477,7 @@ esp_err_t adc_digi_deinit(void);
*
* @return
* - ESP_ERR_INVALID_STATE Driver state is invalid.
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_OK On success
*/
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);

View File

@ -132,11 +132,7 @@ static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask
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 = 15,
.dig_clk.div_a = 0,
.dig_clk.div_b = 1,
.sample_freq_hz = 83333,
};
dig_cfg.adc_pattern_len = channel_num;

View File

@ -145,7 +145,7 @@ void adc_hal_onetime_start(adc_digi_config_t *adc_digi_config)
* 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);
uint32_t digi_clk = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 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

View File

@ -18,6 +18,7 @@
#include "soc/soc_caps.h"
#include "hal/adc_hal.h"
#include "hal/adc_types.h"
#include "soc/soc.h"
//Currently we don't have context for the ADC HAL. So HAL variables are temporarily put here. But
//please don't follow this code. Create a context for your own HAL!
@ -67,24 +68,17 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
adc_ll_digi_convert_limit_disable();
}
adc_ll_digi_set_trigger_interval(cfg->interval);
adc_hal_digi_clk_config(&cfg->dig_clk);
//clock
uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / cfg->sample_freq_hz;
adc_ll_digi_set_trigger_interval(interval);
adc_hal_digi_clk_config();
}
/**
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
* Enable clock and select clock source for ADC digital controller.
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
*
* @note ADC and DAC digital controller share the same frequency divider.
* Please set a reasonable frequency division factor to meet the sampling frequency of the ADC and the output frequency of the DAC.
*
* @param clk Refer to ``adc_digi_clk_t``.
*/
void adc_hal_digi_clk_config(const adc_digi_clk_t *clk)
void adc_hal_digi_clk_config(void)
{
adc_ll_digi_controller_clk_div(clk->div_num, clk->div_b, clk->div_a);
adc_ll_digi_controller_clk_enable(clk->use_apll);
//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);
adc_ll_digi_controller_clk_enable(0);
}
/**

View File

@ -75,11 +75,11 @@ void adc_hal_digi_disable(void);
/**
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
* Enable clock and select clock source for ADC digital controller.
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
* Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1).
*
* @param clk Refer to `adc_digi_clk_t`.
*/
void adc_hal_digi_clk_config(const adc_digi_clk_t *clk);
void adc_hal_digi_clk_config(void);
/**
* Reset adc digital controller filter.

View File

@ -29,7 +29,10 @@
extern "C" {
#endif
#define ADC_LL_ADC2_CHANNEL_MAX 1
#define ADC_LL_ADC2_CHANNEL_MAX 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
typedef enum {
ADC_NUM_1 = 0, /*!< SAR ADC 1 */
@ -180,8 +183,8 @@ static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pa
uint8_t offset = (pattern_index % 4) * 6;
tab = APB_SARADC.sar_patt_tab[index].sar_patt_tab1; // Read old register value
tab &= (~(0xFC0000 >> offset)); // clear old data
tab |= ((uint32_t)pattern.val << 18) >> offset; // Fill in the new data
tab &= (~(0xFC0000 >> offset)); // Clear old data
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
APB_SARADC.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back
}
@ -223,10 +226,11 @@ static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en)
}
/**
* Sets the number of interval clock cycles for the digital controller to trigger the measurement.
* Set the interval clock cycle for the digital controller to trigger the measurement.
* Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval.
*
* @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.
* @note The trigger interval should not be smaller than the sampling time of the SAR ADC.
* @param cycle The clock cycle (trigger interval) of the measurement. Range: 30 ~ 4095.
*/
static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle)
{

View File

@ -268,11 +268,11 @@ static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en)
}
/**
* Sets the number of interval clock cycles for the digital controller to trigger the measurement.
* Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
* Set the interval clock cycle for the digital controller to trigger the measurement.
* Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval.
*
* @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.
* @note The trigger interval should be larger than the sampling time of the SAR ADC.
* @param cycle The clock cycle (trigger interval) of the measurement. Range: 40 ~ 4095.
*/
static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle)
{

View File

@ -275,7 +275,7 @@ typedef struct {
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
adc_digi_pattern_table_t *adc_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc_pattern_len`. */
#endif
#if !CONFIG_IDF_TARGET_ESP32
#if CONFIG_IDF_TARGET_ESP32S2
uint32_t interval; /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
The unit is the divided clock. Range: 40 ~ 4095.
Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
@ -285,6 +285,13 @@ typedef struct {
uint32_t dma_eof_num; /*!<DMA eof num of adc digital controller.
If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated in DMA.
Note: The converted data in the DMA in link buffer will be multiple of two bytes. */
#elif CONFIG_IDF_TARGET_ESP32C3
uint32_t sample_freq_hz; /*!< The expected ADC sampling frequency in Hz. Range: 610Hz ~ 83333Hz
Fs: sampling frequency;
Fd: digital controller frequency
interval: interval between 2 measurement trigger signal
Fs = Fd / interval / 2
Range: the smallest interval should not be smaller than the ADC measurement period. The largest interval should not be larger than 4095. */
#endif
} adc_digi_config_t;

View File

@ -28,11 +28,7 @@ static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask
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 = 15,
.dig_clk.div_a = 0,
.dig_clk.div_b = 1,
.sample_freq_hz = 83333,
};
dig_cfg.adc_pattern_len = channel_num;