2020#include "esp_adc/adc_oneshot.h"
2121#include "esp_adc/adc_continuous.h"
2222#include "esp_adc/adc_cali_scheme.h"
23+ #include "esp_heap_caps.h"
2324
2425#if CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_REV_MIN_FULL >= 300
2526// NOTE: These weak definitions allow successful linkage if the real efuse calibration functions are missing.
@@ -403,43 +404,39 @@ adc_continuous_result_t *adc_result = NULL;
403404static bool adcContinuousDetachBus (void * adc_unit_number ) {
404405 adc_unit_t adc_unit = (adc_unit_t )adc_unit_number - 1 ;
405406
407+ // Guard against double-cleanup: check if already cleaned up
406408 if (adc_handle [adc_unit ].adc_continuous_handle == NULL ) {
407409 return true;
408- } else {
409- esp_err_t err = adc_continuous_deinit (adc_handle [adc_unit ].adc_continuous_handle );
410+ }
411+
412+ // Clean up ADC driver
413+ esp_err_t err = adc_continuous_deinit (adc_handle [adc_unit ].adc_continuous_handle );
414+ if (err != ESP_OK ) {
415+ return false;
416+ }
417+ adc_handle [adc_unit ].adc_continuous_handle = NULL ;
418+
419+ // Clean up calibration handle if exists
420+ if (adc_handle [adc_unit ].adc_cali_handle != NULL ) {
421+ #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
422+ err = adc_cali_delete_scheme_curve_fitting (adc_handle [adc_unit ].adc_cali_handle );
410423 if (err != ESP_OK ) {
411424 return false;
412425 }
413- adc_handle [adc_unit ].adc_continuous_handle = NULL ;
414- if (adc_handle [adc_unit ].adc_cali_handle != NULL ) {
415- #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
416- err = adc_cali_delete_scheme_curve_fitting (adc_handle [adc_unit ].adc_cali_handle );
417- if (err != ESP_OK ) {
418- return false;
419- }
420426#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
421- err = adc_cali_delete_scheme_line_fitting (adc_handle [adc_unit ].adc_cali_handle );
422- if (err != ESP_OK ) {
423- return false;
424- }
425- #else
426- log_e ("ADC Calibration scheme is not supported!" );
427+ err = adc_cali_delete_scheme_line_fitting (adc_handle [adc_unit ].adc_cali_handle );
428+ if (err != ESP_OK ) {
427429 return false;
428- #endif
429430 }
431+ #else
432+ log_e ("ADC Calibration scheme is not supported!" );
433+ return false;
434+ #endif
430435 adc_handle [adc_unit ].adc_cali_handle = NULL ;
431-
432- //set all used pins to INIT state
433- for (uint8_t channel = 0 ; channel < SOC_ADC_CHANNEL_NUM (adc_unit ); channel ++ ) {
434- int io_pin ;
435- adc_oneshot_channel_to_io (adc_unit , channel , & io_pin );
436- if (perimanGetPinBusType (io_pin ) == ESP32_BUS_TYPE_ADC_CONT ) {
437- if (!perimanClearPinBus (io_pin )) {
438- return false;
439- }
440- }
441- }
442436 }
437+
438+ // Don't call perimanClearPinBus() here - the peripheral manager already handles it
439+ // This callback is only responsible for cleaning up the ADC driver itself
443440 return true;
444441}
445442
@@ -549,6 +546,14 @@ bool analogContinuous(const uint8_t pins[], size_t pins_count, uint32_t conversi
549546 }
550547#endif
551548
549+ #if CONFIG_IDF_TARGET_ESP32P4
550+ // Align conversion frame size to cache line size (required for DMA on targets with cache)
551+ uint32_t alignment_remainder = adc_handle [adc_unit ].conversion_frame_size % CONFIG_CACHE_L1_CACHE_LINE_SIZE ;
552+ if (alignment_remainder != 0 ) {
553+ adc_handle [adc_unit ].conversion_frame_size += (CONFIG_CACHE_L1_CACHE_LINE_SIZE - alignment_remainder );
554+ }
555+ #endif
556+
552557 adc_handle [adc_unit ].buffer_size = adc_handle [adc_unit ].conversion_frame_size * 2 ;
553558
554559 //Conversion frame size buffer cant be bigger than 4092 bytes
@@ -626,8 +631,21 @@ bool analogContinuousRead(adc_continuous_result_t **buffer, uint32_t timeout_ms)
626631 uint32_t bytes_read = 0 ;
627632 uint32_t read_raw [used_adc_channels ];
628633 uint32_t read_count [used_adc_channels ];
629- uint8_t adc_read [adc_handle [ADC_UNIT_1 ].conversion_frame_size ];
630- memset (adc_read , 0xcc , sizeof (adc_read ));
634+
635+ // Allocate DMA buffer with cache line alignment (required for ESP32-P4 and other targets with cache)
636+ size_t buffer_size = adc_handle [ADC_UNIT_1 ].conversion_frame_size ;
637+ #if CONFIG_IDF_TARGET_ESP32P4
638+ uint8_t * adc_read = (uint8_t * )heap_caps_aligned_alloc (CONFIG_CACHE_L1_CACHE_LINE_SIZE , buffer_size , MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL );
639+ #else
640+ uint8_t * adc_read = (uint8_t * )heap_caps_malloc (buffer_size , MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL );
641+ #endif
642+ if (adc_read == NULL ) {
643+ log_e ("Failed to allocate DMA buffer" );
644+ * buffer = NULL ;
645+ return false;
646+ }
647+
648+ memset (adc_read , 0xcc , buffer_size );
631649 memset (read_raw , 0 , sizeof (read_raw ));
632650 memset (read_count , 0 , sizeof (read_count ));
633651
@@ -638,6 +656,8 @@ bool analogContinuousRead(adc_continuous_result_t **buffer, uint32_t timeout_ms)
638656 } else {
639657 log_e ("Reading data failed with error: %X" , err );
640658 }
659+ free (adc_read );
660+ adc_read = NULL ;
641661 * buffer = NULL ;
642662 return false;
643663 }
@@ -676,6 +696,8 @@ bool analogContinuousRead(adc_continuous_result_t **buffer, uint32_t timeout_ms)
676696 }
677697 }
678698
699+ free (adc_read );
700+ adc_read = NULL ;
679701 * buffer = adc_result ;
680702 return true;
681703
@@ -708,16 +730,29 @@ bool analogContinuousStop() {
708730}
709731
710732bool analogContinuousDeinit () {
711- if (adc_handle [ADC_UNIT_1 ].adc_continuous_handle != NULL ) {
712- esp_err_t err = adc_continuous_deinit (adc_handle [ADC_UNIT_1 ].adc_continuous_handle );
713- if (err != ESP_OK ) {
714- return false;
733+ if (adc_handle [ADC_UNIT_1 ].adc_continuous_handle == NULL ) {
734+ log_i ("ADC Continuous was not initialized" );
735+ return true;
736+ }
737+
738+ // Clear all used pins from peripheral manager
739+ // This will trigger adcContinuousDetachBus() callback which cleans up the ADC driver
740+ for (uint8_t channel = 0 ; channel < SOC_ADC_CHANNEL_NUM (ADC_UNIT_1 ); channel ++ ) {
741+ int io_pin ;
742+ adc_oneshot_channel_to_io (ADC_UNIT_1 , channel , & io_pin );
743+ if (perimanGetPinBusType (io_pin ) == ESP32_BUS_TYPE_ADC_CONT ) {
744+ if (!perimanClearPinBus (io_pin )) {
745+ return false;
746+ }
715747 }
748+ }
749+
750+ // Free the result buffer (callback doesn't do this)
751+ if (adc_result != NULL ) {
716752 free (adc_result );
717- adc_handle [ADC_UNIT_1 ].adc_continuous_handle = NULL ;
718- } else {
719- log_i ("ADC Continuous was not initialized" );
753+ adc_result = NULL ;
720754 }
755+
721756 return true;
722757}
723758
0 commit comments