Skip to content

Commit

Permalink
Merge pull request #18271 from gschorcht/periph_hal_esp32_adc
Browse files Browse the repository at this point in the history
cpu/esp32: use ESP-IDF adc/dac HAL for periph/adc and periph/dac
  • Loading branch information
benpicco authored Jul 17, 2022
2 parents eb12f44 + 43d2340 commit 2c9f338
Show file tree
Hide file tree
Showing 23 changed files with 688 additions and 552 deletions.
6 changes: 0 additions & 6 deletions cpu/esp32/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ config CPU_FAM_ESP32
select HAS_CPU_ESP32
select HAS_ESP_HW_COUNTER
select HAS_ESP_WIFI_ENTERPRISE
select HAS_PERIPH_ADC_CTRL
select HAS_PUF_SRAM

select PACKAGE_ESP32_SDK if TEST_KCONFIG
Expand Down Expand Up @@ -81,11 +80,6 @@ config HAS_ESP_SPI_RAM
Indicates that an external RAM is connected via the FSPI interface in
the board.

config HAS_PERIPH_ADC_CTRL
bool
help
Indicates that an ESP32 ADC controller peripheral is present.

## Common CPU symbols
config CPU_CORE
default "xtensa-lx6" if CPU_CORE_XTENSA_LX6
Expand Down
17 changes: 11 additions & 6 deletions cpu/esp32/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,17 @@ ifneq (,$(filter esp_idf_nvs_flash,$(USEMODULE)))
USEMODULE += mtd
endif

ifneq (,$(filter periph_rtc,$(USEMODULE)))
FEATURES_OPTIONAL += esp_rtc_timer_32k
ifneq (,$(filter esp_idf_wifi,$(USEMODULE)))
# add additional modules required by esp_idf_wifi
USEMODULE += esp_idf_adc
endif

ifneq (,$(filter esp_rtc_timer_32k,$(FEATURES_USED)))
USEMODULE += esp_rtc_timer_32k
ifneq (,$(filter periph_rtc,$(USEMODULE)))
FEATURES_OPTIONAL += esp_rtc_timer_32k
endif

ifneq (,$(filter periph_adc periph_dac,$(USEMODULE)))
FEATURES_REQUIRED += periph_adc_ctrl
ifneq (,$(filter esp_rtc_timer_32k,$(FEATURES_USED)))
USEMODULE += esp_rtc_timer_32k
endif

ifneq (,$(filter periph_gpio,$(USEMODULE)))
Expand Down Expand Up @@ -113,6 +114,10 @@ ifneq (,$(filter mtd,$(USEMODULE)))
USEMODULE += esp_idf_spi_flash
endif

ifneq (,$(filter periph_adc,$(USEMODULE)))
USEMODULE += esp_idf_adc
endif

ifneq (,$(filter periph_rtc,$(USEMODULE)))
USEMODULE += rtt_rtc
endif
Expand Down
1 change: 0 additions & 1 deletion cpu/esp32/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ include $(RIOTCPU)/esp_common/Makefile.features
FEATURES_PROVIDED += arch_esp32
FEATURES_PROVIDED += esp_wifi_enterprise
FEATURES_PROVIDED += esp_hw_counter
FEATURES_PROVIDED += periph_adc_ctrl
FEATURES_PROVIDED += puf_sram

ifneq (,$(filter esp32-wrover%,$(CPU_MODEL)))
Expand Down
6 changes: 3 additions & 3 deletions cpu/esp32/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -704,15 +704,15 @@ Attenuation | Voltage Range | Symbol
</center><br>

@note The reference voltage Vref can vary from device to device in the range of 1.0V and 1.2V. The
Vref of a device can be read with the `#adc_vref_to_gpio25` function at GPIO 25.<br>
Vref of a device can be read with the `#adc_line_vref_to_gpio` function at GPIO 25.<br>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
extern int adc_vref_to_gpio25 (void);
extern int adc_line_vref_to_gpio(adc_t line, gpio_t gpio);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For that purpose GPIO25 is initialized automatically as ADC channel and is connected internally to
Vref to measure the current voltage. Once the initialization is finished and the function returns
with success, the current voltage can be read from GPIO25. The results of the ADC input can then be
adjusted accordingly. The `#adc_vref_to_gpio25` function can be used to determine the current
adjusted accordingly. The `#adc_line_vref_to_gpio` function can be used to determine the current
voltage at ESP32.

[Back to table of contents](#esp32_toc)
Expand Down
65 changes: 65 additions & 0 deletions cpu/esp32/esp-idf-api/adc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup cpu_esp32_esp_idf_api
* @{
*
* @file
* @brief Interface for the ESP-IDF ADC HAL API
*
* @author Gunar Schorcht <[email protected]>
* @}
*/

#include <stdbool.h>

#include "driver/adc.h"

void esp_idf_adc_power_acquire(void)
{
adc_power_acquire();
}

void esp_idf_adc_power_release(void)
{
adc_power_release();
}

esp_err_t esp_idf_adc1_config_width(adc_bits_width_t width_bit)
{
return adc1_config_width(width_bit);
}

esp_err_t esp_idf_adc1_config_channel_atten(adc_channel_t channel,
adc_atten_t atten)
{
return adc1_config_channel_atten(channel, atten);
}

int esp_idf_adc1_get_raw(adc1_channel_t channel)
{
return adc1_get_raw(channel);
}

esp_err_t esp_idf_adc2_config_channel_atten(adc_channel_t channel,
adc_atten_t atten)
{
return adc2_config_channel_atten(channel, atten);
}

esp_err_t esp_idf_adc2_get_raw(adc2_channel_t channel,
adc_bits_width_t width_bit, int *raw_out)
{
return adc2_get_raw(channel, width_bit, raw_out);
}

esp_err_t esp_idf_adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
{
return adc_vref_to_gpio(adc_unit, gpio);
}
37 changes: 37 additions & 0 deletions cpu/esp32/esp-idf-api/dac.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup cpu_esp32_esp_idf_api
* @{
*
* @file
* @brief Interface for the ESP-IDF DAC HAL API
*
* @author Gunar Schorcht <[email protected]>
* @}
*/

#include <stdbool.h>

#include "driver/dac_common.h"

esp_err_t esp_idf_dac_output_voltage(dac_channel_t channel, uint8_t dac_value)
{
return dac_output_voltage(channel, dac_value);
}

esp_err_t esp_idf_dac_output_enable(dac_channel_t channel)
{
return dac_output_enable(channel);
}

esp_err_t esp_idf_dac_output_disable(dac_channel_t channel)
{
return dac_output_disable(channel);
}
1 change: 1 addition & 0 deletions cpu/esp32/esp-idf/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ config MODULE_ESP_IDF
help
Espressif IoT Development Framework.

rsource "adc/Kconfig"
rsource "common/Kconfig"
rsource "efuse/Kconfig"
rsource "eth/Kconfig"
Expand Down
4 changes: 4 additions & 0 deletions cpu/esp32/esp-idf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ export ESP_IDF_PATH = $(shell pwd)

# Add a list of subdirectories, that should also be built:

ifneq (,$(filter esp_idf_adc,$(USEMODULE)))
DIRS += adc
endif

ifneq (,$(filter esp_idf_common,$(USEMODULE)))
DIRS += common
endif
Expand Down
16 changes: 16 additions & 0 deletions cpu/esp32/esp-idf/adc/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright (c) 2022 Gunar Schorcht
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
#

config MODULE_ESP_IDF_ADC
bool
depends on TEST_KCONFIG
depends on MODULE_ESP_IDF

default y if MODULE_PERIPH_ADC

help
ESP-IDF code for ADC peripherals.
25 changes: 25 additions & 0 deletions cpu/esp32/esp-idf/adc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
MODULE = esp_idf_adc

# source files to be compiled for this module
ESP32_SDK_SRC = \
components/driver/adc.c \
components/driver/adc_common.c \
components/hal/adc_hal.c \
components/soc/$(CPU)/adc_periph.c \
#

ifneq (,$(filter esp32c3 esp32s3,$(CPU)))
ESP32_SDK_SRC += components/driver/$(CPU)/adc2_init_cal.c
INCLUDES += -I$(ESP32_SDK_DIR)/components/driver/include/driver
endif

ifneq (,$(filter esp32c3 esp32h2 esp32s3,$(CPU)))
ESP32_SDK_SRC += components/efuse/$(CPU)/esp_efuse_rtc_calib.c
endif

include $(RIOTBASE)/Makefile.base

ESP32_SDK_BIN = $(BINDIR)/$(MODULE)

include ../esp_idf.mk
include ../esp_idf_cflags.mk
3 changes: 3 additions & 0 deletions cpu/esp32/esp-idf/wifi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ config MODULE_ESP_IDF_WIFI
bool
depends on TEST_KCONFIG
depends on MODULE_ESP_IDF

select MODULE_ESP_IDF_ADC

help
ESP-IDF code required for accessing the WiFi interface.
78 changes: 59 additions & 19 deletions cpu/esp32/include/adc_arch.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand All @@ -11,7 +11,14 @@
* @{
*
* @file
* @brief Architecture specific ADC functions for ESP32
* @brief Architecture specific ADC definitions and functions for ESP32
*
* All ESP32x SoCs have two SAR ADC units each. However, these have
* functionalities as well as specific properties that vary between the
* ESP32x SoC and therefore require different handling for each ESP32x SoC.
* This is already taken into account in the high-level API of the ESP-IDF.
* To avoid having to reimplement these specifics and the different handling,
* the high-level API of the ESP-IDF is used directly for the ADC peripherals.
*
* @author Gunar Schorcht <[email protected]>
* @}
Expand All @@ -24,17 +31,25 @@
extern "C" {
#endif

#include "periph/gpio.h"
#include "periph/adc.h"
#include "periph/gpio.h"

#include "hal/adc_types.h"

#include "esp_idf_api/adc.h"

/**
* @brief Attenuations that can be set for ADC lines
*
* Event though ESP-IDF type `adc_atten_t` and `ADC_ATTEN_DB_*` are used
* now, the `adc_attenuation_t` type with constants `ADC_ATTENUATION_*_DB` are
* kept for compatibility.
*/
typedef enum {
ADC_ATTENUATION_0_DB = 0, /**< full-range is about 1.1 V (Vref) */
ADC_ATTENUATION_3_DB, /**< full-range is about 1.5 V */
ADC_ATTENUATION_6_DB, /**< full-range is about 2.2 V */
ADC_ATTENUATION_11_DB /**< full-range is about 3.3 V */
ADC_ATTENUATION_0_DB = ADC_ATTEN_DB_0, /**< full-range is about 1.1 V (Vref) */
ADC_ATTENUATION_3_DB = ADC_ATTEN_DB_2_5, /**< full-range is about 1.5 V */
ADC_ATTENUATION_6_DB = ADC_ATTEN_DB_6, /**< full-range is about 2.2 V */
ADC_ATTENUATION_11_DB = ADC_ATTEN_DB_11, /**< full-range is about 3.3 V */
} adc_attenuation_t;

/**
Expand All @@ -51,32 +66,57 @@ typedef enum {
*
* Attenuation | Voltage Range | Symbol
* ----------------|-------------------|----------------------
* 0 dB | 0 ... 1.1V (Vref) | ADC_ATTENUATION_0_DB
* 3 dB | 0 ... 1.5V | ADC_ATTENUATION_3_DB
* 6 dB | 0 ... 2.2V | ADC_ATTENUATION_6_DB
* 11 dB (default) | 0 ... 3.3V | ADC_ATTENUATION_11_DB
* 0 dB | 0 ... 1.1V (Vref) | ADC_ATTEN_DB_0
* 2.5 dB | 0 ... 1.5V | ADC_ATTEN_DB_2_5
* 6 dB | 0 ... 2.2V | ADC_ATTEN_DB_6
* 11 dB (default) | 0 ... 3.3V | ADC_ATTEN_DB_11
*
* </center>
*
* Please note: The reference voltage Vref can vary from device to device in
* the range of 1.0V and 1.2V. The Vref of a device can be read with the
* function *adc_vref_to_gpio25* at the pin GPIO 25. The results of the ADC
* input can then be adjusted accordingly.
* @note: The reference voltage Vref can vary from ADC unit to ADC unit in
* the range of 1.0V and 1.2V. The Vref of a unit can be routed with
* function *adc_vref_to_gpio* to a GPIO pin.
*
* @param line ADC line for which the attenuation is set
* @param atten Attenuation, see type definition of *adc_attenuation_t
* @return 0 on success
* @return -1 on invalid ADC line
* @return 0 on success
* @return -1 on error
*/
int adc_set_attenuation(adc_t line, adc_atten_t atten);

/**
* @brief Output reference voltage of a ADC line to GPIO n
*
* The Vref of the ADC unit of the given ADC line is routed to a GPIO pin n.
* This allows to measure the Vref used by the ADC unit to adjusted the
* results of the conversions accordingly.
*
* @note
* - The given GPIO must be a valid ADC channel of ADC2 unit.
* - For ESP32 and ESP32C3, the given ADC line has to be a channel of ADC2 unit.
*
* @param line ADC line for which Vref of its ADC unit is routed to the GPIO
* @param gpio GPIO to which Vref is routed (ADC2 channel GPIOs only)
*
* @return 0 on success
* @return -1 on error
*/
int adc_set_attenuation(adc_t line, adc_attenuation_t atten);
int adc_line_vref_to_gpio(adc_t line, gpio_t gpio);

#if defined(MCU_ESP32)
/**
* @brief Output ADC reference voltage to GPIO25
*
* This function is deprecated and will be removed in future versions.
*
* @return 0 on success
* @return -1 on invalid ADC line
*/
int adc_vref_to_gpio25 (void);
static inline int adc_vref_to_gpio25 (void)
{
return esp_idf_adc_vref_to_gpio(ADC_UNIT_2, GPIO25);
}
#endif

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 2c9f338

Please sign in to comment.