Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADC memory leak (IDFGH-14005) #14828

Closed
3 tasks done
dizcza opened this issue Nov 5, 2024 · 5 comments
Closed
3 tasks done

ADC memory leak (IDFGH-14005) #14828

dizcza opened this issue Nov 5, 2024 · 5 comments
Assignees
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Bug bugs in IDF

Comments

@dizcza
Copy link
Contributor

dizcza commented Nov 5, 2024

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

v5.1.4-991-g725e8d6392 (latest v5.1)

Espressif SoC revision.

ESP32-D0WDQ6-V3

Operating System used.

Linux

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

None

Development Kit.

TTGO T8

Power Supply used.

USB

What is the expected behavior?

No memory leaks when an ADC is created and destroyed.

What is the actual behavior?

Memory leak of 44 bytes when an ADC is created and destroyed.

Steps to reproduce.

#define BATTERY_ADC_UNIT       ADC_UNIT_1
#define BATTERY_ADC_CHANNEL    ADC_CHANNEL_7
#define BATTERY_ADC_BITWIDTH   ADC_BITWIDTH_12

/*---------------------------------------------------------------
        ADC Calibration
---------------------------------------------------------------*/
static void battery_adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle)
{
	static bool calibration_printed = false;
    esp_err_t ret = ESP_FAIL;
    bool calibrated = false;

#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
    if (!calibrated) {
        adc_cali_curve_fitting_config_t cali_config = {
            .unit_id = unit,
            .atten = atten,
            .bitwidth = BATTERY_ADC_BITWIDTH,
        };
        ret = adc_cali_create_scheme_curve_fitting(&cali_config, out_handle);
        if (ret == ESP_OK) {
			if (!calibration_printed) {
            	ESP_LOGI(TAG, "ADC calibrated mode Curve Fitting");
            	calibration_printed = true;
			}
            calibrated = true;
        }
    }
#endif

#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
    if (!calibrated) {
        adc_cali_line_fitting_config_t cali_config = {
            .unit_id = unit,
            .atten = atten,
            .bitwidth = BATTERY_ADC_BITWIDTH,
        };
        ret = adc_cali_create_scheme_line_fitting(&cali_config, out_handle);
        if (ret == ESP_OK) {
			if (!calibration_printed) {
            	ESP_LOGI(TAG, "ADC calibrated mode Line Fitting");
            	calibration_printed = true;
			}
            calibrated = true;
        }
    }
#endif

    if (ret != ESP_OK) {
        ESP_LOGW(TAG, "ADC not calibrated");
    }
}



/**
 * Initialize an analog SDP sensor with ADC
 *
 * @param sensor  sensor handle
 * @return        err code
 */
esp_err_t battery_init() {
    adc_oneshot_unit_init_cfg_t adc_init_cfg = {
        .unit_id = BATTERY_ADC_UNIT,
        .ulp_mode = false
    };
    BSP_SOFTCHECK(adc_oneshot_new_unit(&adc_init_cfg, &m_adc_handle));

    adc_oneshot_chan_cfg_t adc_chan_cfg = {
        .bitwidth = BATTERY_ADC_BITWIDTH,
        .atten = ADC_ATTEN_DB_12,
    };
    BSP_SOFTCHECK(adc_oneshot_config_channel(m_adc_handle, BATTERY_ADC_CHANNEL, &adc_chan_cfg));

    battery_adc_calibration_init(BATTERY_ADC_UNIT, ADC_ATTEN_DB_12, &m_adc_cali_handle);

    return ESP_OK;
}

void battery_deinit() {
	if (m_adc_handle) {
		adc_oneshot_del_unit(m_adc_handle);
		m_adc_handle = NULL;
	}
}


void esp_dump_per_task_heap_info(const char *name)
{
	static size_t s_prepopulated_num = 0;
	static heap_task_totals_t s_totals_arr[MAX_TASK_NUM];
	static heap_task_block_t s_block_arr[MAX_BLOCK_NUM];
	
	TaskHandle_t tasks[] = {xTaskGetCurrentTaskHandle()};

    heap_task_info_params_t heap_info = {0};
    heap_info.caps[0] = MALLOC_CAP_8BIT;        // Gets heap with CAP_8BIT capabilities
    heap_info.mask[0] = MALLOC_CAP_8BIT;
    heap_info.tasks = tasks;                     // Passing NULL captures heap info for all tasks
    heap_info.num_tasks = 1;
    heap_info.totals = s_totals_arr;            // Gets task wise allocation details
    heap_info.num_totals = &s_prepopulated_num;
    heap_info.max_totals = MAX_TASK_NUM;        // Maximum length of "s_totals_arr"
    heap_info.blocks = s_block_arr;             // Gets block wise allocation details. For each block, gets owner task, address and size
    heap_info.max_blocks = MAX_BLOCK_NUM;       // Maximum length of "s_block_arr"

    heap_caps_get_per_task_info(&heap_info);
    ESP_LOGI(TAG, "%s %zu", name, heap_info.totals[0].size[0]);
}

        ...
	esp_dump_per_task_heap_info("before");
	battery_init();
    	battery_deinit();
    	esp_dump_per_task_heap_info("after");

Let me know if I can examine the heap size of the current task other than with heap_caps_get_per_task_info.

Debug Logs.

I (09:57:33.737) bsp: before 873560
I (09:57:33.746) bsp: after 873604
I (09:57:33.768) bsp: before 873604
I (09:57:33.777) bsp: after 873648
I (09:57:33.788) bsp: before 873648
I (09:57:33.796) bsp: after 873692

More Information.

No response

@dizcza dizcza added the Type: Bug bugs in IDF label Nov 5, 2024
@github-actions github-actions bot changed the title ADC memory leak ADC memory leak (IDFGH-14005) Nov 5, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Nov 5, 2024
@dizcza
Copy link
Contributor Author

dizcza commented Nov 5, 2024

adc_cali_create_scheme_line_fitting is used here.

@dizcza
Copy link
Contributor Author

dizcza commented Nov 5, 2024

Question: does it make sense to init and deinit an ADC to measure once per minute? Or, from the power perspective, we can init the ADC only once and read measurements each minute: does ADC consume power when it's inactive and not destroyed?

@rosmianto
Copy link

@dizcza If you use adc_cali_create_scheme_curve_fitting, you have to use adc_cali_delete_scheme_curve_fitting to free up the memory allocation.

@dizcza
Copy link
Contributor Author

dizcza commented Nov 9, 2024

@rosmianto didn't know that! thanks

@dizcza dizcza closed this as completed Nov 9, 2024
@dizcza
Copy link
Contributor Author

dizcza commented Nov 9, 2024

I'd like to know though, does ADC consume power when it's inactive and not destroyed?

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: Done Issue is done internally and removed Status: Opened Issue is new labels Feb 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

4 participants