mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
Merge branch 'fix/wrong_channel_gpio_num_on_p4_adc2_v5.5' into 'release/v5.5'
ADC: add continuous parse data API (v5.5) See merge request espressif/esp-idf!42205
This commit is contained in:
@@ -475,17 +475,16 @@ esp_err_t adc_continuous_config(adc_continuous_handle_t handle, const adc_contin
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_FALSE(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC sampling frequency out of range");
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
|
||||
handle->format = ADC_DIGI_OUTPUT_FORMAT_TYPE1;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
if (config->conv_mode == ADC_CONV_BOTH_UNIT || config->conv_mode == ADC_CONV_ALTER_UNIT) {
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
|
||||
handle->format = ADC_DIGI_OUTPUT_FORMAT_TYPE2;
|
||||
} else if (config->conv_mode == ADC_CONV_SINGLE_UNIT_1 || config->conv_mode == ADC_CONV_SINGLE_UNIT_2) {
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
|
||||
handle->format = ADC_DIGI_OUTPUT_FORMAT_TYPE1;
|
||||
}
|
||||
#else
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
|
||||
handle->format = ADC_DIGI_OUTPUT_FORMAT_TYPE2;
|
||||
#endif
|
||||
|
||||
uint32_t clk_src_freq_hz = 0;
|
||||
@@ -583,3 +582,88 @@ esp_err_t adc_continuous_channel_to_io(adc_unit_t unit_id, adc_channel_t channel
|
||||
{
|
||||
return adc_channel_to_io(unit_id, channel, io_num);
|
||||
}
|
||||
|
||||
esp_err_t adc_continuous_parse_data(adc_continuous_handle_t handle,
|
||||
const uint8_t *raw_data,
|
||||
uint32_t raw_data_size,
|
||||
adc_continuous_data_t *parsed_data,
|
||||
uint32_t *num_parsed_samples)
|
||||
{
|
||||
// Parameter validation
|
||||
ESP_RETURN_ON_FALSE(handle && raw_data && parsed_data && num_parsed_samples, ESP_ERR_INVALID_ARG, ADC_TAG, "invalid argument");
|
||||
|
||||
// Buffer size validation
|
||||
if (raw_data_size == 0 || raw_data_size % SOC_ADC_DIGI_RESULT_BYTES != 0) {
|
||||
*num_parsed_samples = 0;
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
// Calculate number of samples
|
||||
uint32_t samples_to_parse = raw_data_size / SOC_ADC_DIGI_RESULT_BYTES;
|
||||
|
||||
for (uint32_t i = 0; i < samples_to_parse; i++) {
|
||||
adc_digi_output_data_t *p = (adc_digi_output_data_t*)&raw_data[i * SOC_ADC_DIGI_RESULT_BYTES];
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
parsed_data[i].unit = ADC_UNIT_1;
|
||||
parsed_data[i].channel = p->type1.channel;
|
||||
parsed_data[i].raw_data = p->type1.data;
|
||||
parsed_data[i].valid = (parsed_data[i].channel < SOC_ADC_CHANNEL_NUM(parsed_data[i].unit));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
if (handle->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2) {
|
||||
parsed_data[i].unit = p->type2.unit ? ADC_UNIT_2 : ADC_UNIT_1;
|
||||
parsed_data[i].channel = p->type2.channel;
|
||||
parsed_data[i].raw_data = p->type2.data;
|
||||
parsed_data[i].valid = (parsed_data[i].channel < SOC_ADC_CHANNEL_NUM(parsed_data[i].unit));
|
||||
} else if (handle->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1) {
|
||||
parsed_data[i].unit = handle->use_adc1 ? ADC_UNIT_1 : ADC_UNIT_2;
|
||||
parsed_data[i].channel = p->type1.channel;
|
||||
parsed_data[i].raw_data = p->type1.data;
|
||||
parsed_data[i].valid = (parsed_data[i].channel < SOC_ADC_CHANNEL_NUM(parsed_data[i].unit));
|
||||
}
|
||||
#else
|
||||
#if CONFIG_SOC_ADC_PERIPH_NUM == 1
|
||||
parsed_data[i].unit = ADC_UNIT_1;
|
||||
#else
|
||||
parsed_data[i].unit = p->type2.unit ? ADC_UNIT_2 : ADC_UNIT_1;
|
||||
#endif
|
||||
parsed_data[i].channel = (parsed_data[i].unit == ADC_UNIT_2) ? p->type2.channel - ADC_LL_UNIT2_CHANNEL_SUBSTRATION : p->type2.channel;
|
||||
parsed_data[i].raw_data = p->type2.data;
|
||||
parsed_data[i].valid = (parsed_data[i].channel < SOC_ADC_CHANNEL_NUM(parsed_data[i].unit));
|
||||
#endif
|
||||
}
|
||||
|
||||
*num_parsed_samples = samples_to_parse;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_continuous_read_parse(adc_continuous_handle_t handle,
|
||||
adc_continuous_data_t *parsed_data,
|
||||
uint32_t max_samples,
|
||||
uint32_t *num_samples,
|
||||
uint32_t timeout_ms)
|
||||
{
|
||||
// Parameter validation
|
||||
ESP_RETURN_ON_FALSE(handle && parsed_data && num_samples, ESP_ERR_INVALID_ARG, ADC_TAG, "invalid argument");
|
||||
|
||||
// Allocate raw data buffer based on max_samples
|
||||
uint32_t raw_buffer_size = max_samples * SOC_ADC_DIGI_RESULT_BYTES;
|
||||
uint8_t *raw_data = malloc(raw_buffer_size);
|
||||
if (raw_data == NULL) {
|
||||
*num_samples = 0;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
uint32_t out_length = 0;
|
||||
esp_err_t read_ret = adc_continuous_read(handle, raw_data, raw_buffer_size, &out_length, timeout_ms);
|
||||
if (read_ret != ESP_OK) {
|
||||
free(raw_data);
|
||||
*num_samples = 0;
|
||||
return read_ret;
|
||||
}
|
||||
|
||||
esp_err_t parse_ret = adc_continuous_parse_data(handle, raw_data, out_length, parsed_data, num_samples);
|
||||
|
||||
free(raw_data);
|
||||
|
||||
return parse_ret;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ struct adc_continuous_ctx_t {
|
||||
adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
|
||||
adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
|
||||
adc_hal_digi_ctrlr_cfg_t hal_digi_ctrlr_cfg; //Hal digital controller configuration
|
||||
adc_digi_output_format_t format; //ADC DMA conversion output format
|
||||
adc_continuous_evt_cbs_t cbs; //Callbacks
|
||||
void *user_data; //User context
|
||||
esp_pm_lock_handle_t pm_lock; //For power management
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -238,6 +238,66 @@ esp_err_t adc_continuous_io_to_channel(int io_num, adc_unit_t * const unit_id, a
|
||||
*/
|
||||
esp_err_t adc_continuous_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int * const io_num);
|
||||
|
||||
/**
|
||||
* @brief Parsed ADC continuous mode data structure
|
||||
*/
|
||||
typedef struct {
|
||||
adc_unit_t unit; ///< ADC unit (ADC_UNIT_1 or ADC_UNIT_2)
|
||||
adc_channel_t channel; ///< ADC channel number (0-9)
|
||||
uint32_t raw_data; ///< ADC raw data value (0-4095, 12-bit resolution)
|
||||
bool valid; ///< Whether the data is valid
|
||||
} adc_continuous_data_t;
|
||||
|
||||
/**
|
||||
* @brief Parse ADC continuous mode raw data
|
||||
*
|
||||
* @param[in] handle ADC continuous mode driver handle
|
||||
* @param[in] raw_data Raw data buffer obtained from adc_continuous_read()
|
||||
* @param[in] raw_data_size Size of raw data buffer in bytes
|
||||
* @param[out] parsed_data Parsed data array
|
||||
* @param[out] num_parsed_samples Number of samples actually parsed and stored in parsed_data
|
||||
*
|
||||
* @note The function will parse all available samples from raw_data. User should ensure
|
||||
* parsed_data array is large enough to hold raw_data_size/SOC_ADC_DIGI_RESULT_BYTES samples.
|
||||
* The function includes comprehensive bounds checking to prevent buffer overflow and integer overflow.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid arguments
|
||||
* - ESP_ERR_INVALID_SIZE: raw_data_size is not aligned to SOC_ADC_DIGI_RESULT_BYTES,
|
||||
* integer overflow detected, or buffer overflow detected
|
||||
*/
|
||||
esp_err_t adc_continuous_parse_data(adc_continuous_handle_t handle,
|
||||
const uint8_t *raw_data,
|
||||
uint32_t raw_data_size,
|
||||
adc_continuous_data_t *parsed_data,
|
||||
uint32_t *num_parsed_samples);
|
||||
|
||||
/**
|
||||
* @brief Read and parse ADC continuous mode data in one call
|
||||
*
|
||||
* @param[in] handle ADC continuous mode driver handle
|
||||
* @param[out] parsed_data Parsed data array
|
||||
* @param[in] max_samples Maximum number of samples that can be stored in parsed_data array
|
||||
* @param[out] num_samples Number of samples actually parsed and stored in parsed_data
|
||||
* @param[in] timeout_ms Timeout in milliseconds
|
||||
*
|
||||
* @note This function automatically handles raw data buffer allocation and cleanup.
|
||||
* User only needs to provide parsed_data array and specify max_samples.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid arguments
|
||||
* - ESP_ERR_INVALID_SIZE: Buffer size issues or overflow detected
|
||||
* - ESP_ERR_TIMEOUT: Operation timed out
|
||||
* - ESP_ERR_NO_MEM: Memory allocation failed
|
||||
*/
|
||||
esp_err_t adc_continuous_read_parse(adc_continuous_handle_t handle,
|
||||
adc_continuous_data_t *parsed_data,
|
||||
uint32_t max_samples,
|
||||
uint32_t *num_samples,
|
||||
uint32_t timeout_ms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,8 @@ extern "C" {
|
||||
#define ADC_LL_EVENT_ADC1_ONESHOT_DONE (1 << 0)
|
||||
#define ADC_LL_EVENT_ADC2_ONESHOT_DONE (1 << 1)
|
||||
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 0
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -38,6 +38,8 @@ extern "C" {
|
||||
#define ADC_LL_GET_HIGH_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_THRES0_HIGH_INT_ST_M : APB_SARADC_THRES1_HIGH_INT_ST_M)
|
||||
#define ADC_LL_GET_LOW_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_THRES0_LOW_INT_ST_M : APB_SARADC_THRES1_LOW_INT_ST_M)
|
||||
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 0
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -40,6 +40,8 @@ extern "C" {
|
||||
#define ADC_LL_GET_LOW_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_APB_SARADC_THRES0_LOW_INT_ST_M : APB_SARADC_APB_SARADC_THRES1_LOW_INT_ST_M)
|
||||
|
||||
#define ADC_LL_ADC_FE_ON_MODEM_DOMAIN (1)
|
||||
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 0
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -39,6 +39,8 @@ extern "C" {
|
||||
#define ADC_LL_GET_LOW_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_APB_SARADC_THRES0_LOW_INT_ST_M : APB_SARADC_APB_SARADC_THRES1_LOW_INT_ST_M)
|
||||
|
||||
#define ADC_LL_ADC_FE_ON_MODEM_DOMAIN (1)
|
||||
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 0
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -40,6 +40,8 @@ extern "C" {
|
||||
#define ADC_LL_GET_LOW_THRES_MASK(monitor_id) ((monitor_id == 0) ? SARADC_THRES0_LOW_INT_ST_M : SARADC_THRES1_LOW_INT_ST_M)
|
||||
|
||||
#define ADC_LL_ADC_FE_ON_MODEM_DOMAIN (1)
|
||||
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 0
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -39,6 +39,8 @@ extern "C" {
|
||||
#define ADC_LL_GET_LOW_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_APB_SARADC_THRES0_LOW_INT_ST_M : APB_SARADC_APB_SARADC_THRES1_LOW_INT_ST_M)
|
||||
|
||||
#define ADC_LL_ADC_FE_ON_MODEM_DOMAIN (1)
|
||||
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 0
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -34,6 +34,11 @@ extern "C" {
|
||||
#define LP_ADC_FORCE_XPD_SAR_PD 2 // Force power down
|
||||
#define LP_ADC_FORCE_XPD_SAR_PU 3 // Force power up
|
||||
|
||||
// ESP32P4 ADC2 channel is 2-7, so we need to subtract 2 to get the correct channel
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 2
|
||||
|
||||
#define ADC_LL_NEED_APB_PERIPH_CLAIM(ADC_UNIT) (((ADC_UNIT) == ADC_UNIT_1) ? 0 : 1)
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
@@ -352,13 +357,14 @@ static inline void adc_ll_digi_set_pattern_table(adc_unit_t adc_n, uint32_t patt
|
||||
uint8_t offset = (pattern_index % 4) * 6;
|
||||
adc_ll_digi_pattern_table_t pattern = {0};
|
||||
|
||||
pattern.val = (table.atten & 0x3) | ((table.channel & 0xF) << 2);
|
||||
if (table.unit == ADC_UNIT_1){
|
||||
pattern.val = (table.atten & 0x3) | ((table.channel & 0xF) << 2);
|
||||
tab = ADC.sar1_patt_tab[index].sar1_patt_tab; //Read old register value
|
||||
tab &= (~(0xFC0000 >> offset)); //Clear old data
|
||||
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; //Fill in the new data
|
||||
ADC.sar1_patt_tab[index].sar1_patt_tab = tab; //Write back
|
||||
} else {
|
||||
pattern.val = (table.atten & 0x3) | (((table.channel + 2) & 0xF) << 2);
|
||||
tab = ADC.sar2_patt_tab[index].sar2_patt_tab; //Read old register value
|
||||
tab &= (~(0xFC0000 >> offset)); //clear old data
|
||||
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; //Fill in the new data
|
||||
|
||||
@@ -36,6 +36,8 @@ extern "C" {
|
||||
#define ADC_LL_GET_HIGH_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_ADC1_THRES_INT_ST_M : APB_SARADC_ADC2_THRES_INT_ST_M)
|
||||
#define ADC_LL_GET_LOW_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_ADC1_THRES_INT_ST_M : APB_SARADC_ADC2_THRES_INT_ST_M)
|
||||
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 0
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -38,6 +38,8 @@ extern "C" {
|
||||
#define ADC_LL_GET_HIGH_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_THRES0_HIGH_INT_ST_M : APB_SARADC_THRES1_HIGH_INT_ST_M)
|
||||
#define ADC_LL_GET_LOW_THRES_MASK(monitor_id) ((monitor_id == 0) ? APB_SARADC_THRES0_LOW_INT_ST_M : APB_SARADC_THRES1_LOW_INT_ST_M)
|
||||
|
||||
#define ADC_LL_UNIT2_CHANNEL_SUBSTRATION 0
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
Reference in New Issue
Block a user