1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/esp32: port periph/adc to ESP-IDF interface API

This commit is contained in:
Gunar Schorcht 2022-06-28 13:36:57 +02:00
parent 9e011b653f
commit 11c9703675
15 changed files with 414 additions and 494 deletions

View File

@ -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
@ -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

View File

@ -60,16 +60,17 @@ ifneq (,$(filter esp_idf_nvs_flash,$(USEMODULE)))
USEMODULE += mtd
endif
ifneq (,$(filter esp_idf_wifi,$(USEMODULE)))
# add additional modules required by esp_idf_wifi
USEMODULE += esp_idf_adc
endif
ifneq (,$(filter periph_rtc,$(USEMODULE)))
FEATURES_OPTIONAL += esp_rtc_timer_32k
FEATURES_OPTIONAL += esp_rtc_timer_32k
endif
ifneq (,$(filter esp_rtc_timer_32k,$(FEATURES_USED)))
USEMODULE += esp_rtc_timer_32k
endif
ifneq (,$(filter periph_adc periph_dac,$(USEMODULE)))
FEATURES_REQUIRED += periph_adc_ctrl
USEMODULE += esp_rtc_timer_32k
endif
ifneq (,$(filter periph_gpio,$(USEMODULE)))
@ -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

View File

@ -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)))

View File

@ -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)

View File

@ -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"

View File

@ -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.

View File

@ -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
@ -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 <gunar@schorcht.net>
* @}
@ -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;
/**
@ -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_attenuation_t atten);
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_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
}

View File

@ -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
* @{
*
* @file
* @brief Architecture specific internal ADC functions for ESP32
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef ADC_ARCH_PRIVATE_H
#define ADC_ARCH_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "hal/adc_types.h"
#include "periph/gpio.h"
#ifndef DOXYGEN /* hide implementation details from doxygen */
#define RTCIO_GPIO(n) n /* n-th RTCIO GPIO */
#define RTCIO_NA UINT8_MAX /* RTCIO pin not available */
/**
* @brief ADC hardware descriptor (for internal use only)
*/
typedef struct {
uint8_t rtc_gpio; /**< RTC GPIO number */
gpio_t gpio; /**< GPIO */
adc_unit_t adc_ctrl; /**< ADC controller */
adc_channel_t adc_channel; /**< channel of ADC controller */
char* pad_name; /**< symbolic name of pad */
} _adc_hw_desc_t;
/**
* @brief ADC hardware descriptor table (for internal use only)
*
* @note The index of entries in the table MUST correspond to the
* RTCIO GPIO number.
*/
extern const _adc_hw_desc_t _adc_hw[];
/**
* @brief GPIO to RTC IO map (for internal use only)
*/
extern const gpio_t _gpio_rtcio_map[];
#endif /* !DOXYGEN */
#ifdef __cplusplus
}
#endif
#endif /* ADC_ARCH_PRIVATE_H */

View File

@ -1,90 +0,0 @@
/*
* Copyright (C) 2019 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
* @{
*
* @file
* @brief ADC controller functions used by ADC and DAC peripherals
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef ADC_CTRL_H
#define ADC_CTRL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "periph/gpio.h"
/**
* @brief ADC controllers
*/
enum {
ADC1_CTRL, /**< ADC1 controller */
ADC2_CTRL /**< ADC2 controller */
};
/**
* @brief RTC IO pin type (does not correspond to RTC gpio num order)
*/
enum {
RTCIO_TOUCH0 = 0, /**< touch sensor 0 */
RTCIO_TOUCH1, /**< touch sensor 1 */
RTCIO_TOUCH2, /**< touch sensor 2 */
RTCIO_TOUCH3, /**< touch sensor 3 */
RTCIO_TOUCH4, /**< touch sensor 4 */
RTCIO_TOUCH5, /**< touch sensor 5 */
RTCIO_TOUCH6, /**< touch sensor 6 */
RTCIO_TOUCH7, /**< touch sensor 7 */
RTCIO_TOUCH8, /**< touch sensor 8, 32K_XP */
RTCIO_TOUCH9, /**< touch sensor 9, 32K_XN */
RTCIO_ADC_ADC1, /**< VDET_1 */
RTCIO_ADC_ADC2, /**< VDET_2 */
RTCIO_SENSOR_SENSE1, /**< SENSOR_VP */
RTCIO_SENSOR_SENSE2, /**< SENSOR_CAPP */
RTCIO_SENSOR_SENSE3, /**< SENSOR_CAPN */
RTCIO_SENSOR_SENSE4, /**< SENSOR_VN */
RTCIO_DAC1, /**< DAC output */
RTCIO_DAC2, /**< DAC output */
RTCIO_NA, /**< RTC pad not available */
};
/**
* @brief ADC pin hardware information type (for internal use only)
*/
struct _adc_hw_t {
gpio_t gpio; /**< GPIO */
uint8_t rtc_gpio; /**< corresponding RTC GPIO */
uint8_t adc_ctrl; /**< ADC controller */
uint8_t adc_channel; /**< channel of ADC controller */
char* pad_name; /**< symbolic name of pad */
};
/**
* @brief RTC hardware map
*
* The index corresponds to RTC pin type _rtcio_pin_t (Table 19 in Technical
* Reference)
*/
extern const struct _adc_hw_t _adc_hw[];
#ifdef __cplusplus
}
#endif
#endif /* ADC_CTRL_H */

View File

@ -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
@ -243,24 +243,6 @@ typedef enum {
* @{
*/
#ifndef DOXYGEN
/**
* @brief Possible ADC resolution settings
*/
#define HAVE_ADC_RES_T
typedef enum {
ADC_RES_6BIT = 0xf0, /**< ADC resolution: 6 bit is not supported */
ADC_RES_8BIT = 0xf1, /**< ADC resolution: 8 bit is not supported */
ADC_RES_9BIT = 0, /**< ADC resolution: 9 bit */
ADC_RES_10BIT = 1, /**< ADC resolution: 10 bit */
ADC_RES_11BIT = 2, /**< ADC resolution: 11 bit */
ADC_RES_12BIT = 3, /**< ADC resolution: 12 bit */
ADC_RES_14BIT = 0xf2, /**< ADC resolution: 14 bit is not supported */
ADC_RES_16BIT = 0xf3, /**< ADC resolution: 16 bit is not supported */
} adc_res_t;
/** @} */
#endif /* ndef DOXYGEN */
/**
* @brief Number of ADC channels that could be used at maximum
*
@ -268,7 +250,7 @@ typedef enum {
* therefore not usable. The maximum number of ADC channels (ADC_NUMOF_MAX)
* is therefore set to 16.
*/
#define ADC_NUMOF_MAX 16
#define ADC_NUMOF_MAX (SOC_ADC_CHANNEL_NUM(0) + SOC_ADC_CHANNEL_NUM(1))
/** @} */

View File

@ -14,11 +14,6 @@ config MODULE_ESP_RTC_TIMER_32K
help
Use RTC timer with external 32.768 kHz crystal as RTT.
config MODULE_PERIPH_ADC_CTRL
bool
depends on HAS_PERIPH_ADC_CTRL
default y if MODULE_PERIPH_ADC || MODULE_PERIPH_DAC
config MODULE_PERIPH_RTT_HW_SYS
bool
default y if MODULE_PERIPH_RTT

View File

@ -1,5 +1,9 @@
MODULE = periph
ifneq (,$(filter periph_adc periph_dac,$(USEMODULE)))
SRC += adc_arch.c
endif
ifneq (,$(filter periph_gpio,$(USEMODULE)))
SRC += gpio_arch.c
endif

View File

@ -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 directory for more
@ -14,61 +14,115 @@
* @file
* @brief Low-level ADC driver implementation
*
* 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 <gunar@schorcht.net>
*
* @}
*/
#include <assert.h>
#include "board.h"
#include "periph/adc.h"
#include "adc_arch.h"
#include "adc_ctrl.h"
#include "adc_arch_private.h"
#include "esp_common.h"
#include "gpio_arch.h"
#include "soc/rtc_io_struct.h"
#include "soc/rtc_cntl_struct.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "esp_idf_api/adc.h"
#define ENABLE_DEBUG 0
#include "debug.h"
/* declaration of external functions */
extern void _adc1_ctrl_init(void);
extern void _adc2_ctrl_init(void);
/* forward declarations of internal functions */
static bool _adc_conf_check(void);
static void _adc_module_init(void);
static bool _adc_module_initialized = false;
static void _adc1_ctrl_init(void);
static void _adc2_ctrl_init(void);
/* external variable declarations */
extern const gpio_t _gpio_rtcio_map[];
/*
* Structure for mapping RIOT's ADC resolutions to ESP-IDF resolutions
* of the according ESP32x SoC.
*/
typedef struct {
adc_bits_width_t res; /* used ESP-IDF resolution */
unsigned shift; /* bit shift number for results */
} _adc_esp_res_map_t;
/*
* Table for resolution mapping
*/
_adc_esp_res_map_t _adc_esp_res_map[] = {
#if defined(MCU_ESP32)
{ .res = ADC_WIDTH_BIT_9, .shift = 3 }, /* ADC_RES_6BIT */
{ .res = ADC_WIDTH_BIT_9, .shift = 1 }, /* ADC_RES_8BIT */
{ .res = ADC_WIDTH_BIT_10, .shift = 0 }, /* ADC_RES_10BIT */
{ .res = ADC_WIDTH_BIT_12, .shift = 0 }, /* ADC_RES_12BIT */
{ .res = ADC_WIDTH_MAX }, /* ADC_RES_14BIT */
{ .res = ADC_WIDTH_MAX }, /* ADC_RES_16BIT */
#elif SOC_ADC_MAX_BITWIDTH == 12
{ .res = ADC_WIDTH_BIT_12, .shift = 6 }, /* ADC_RES_6BIT */
{ .res = ADC_WIDTH_BIT_12, .shift = 4 }, /* ADC_RES_8BIT */
{ .res = ADC_WIDTH_BIT_12, .shift = 2 }, /* ADC_RES_10BIT */
{ .res = ADC_WIDTH_BIT_12, .shift = 0 }, /* ADC_RES_12BIT */
{ .res = ADC_WIDTH_MAX }, /* ADC_RES_14BIT */
{ .res = ADC_WIDTH_MAX }, /* ADC_RES_16BIT */
#elif SOC_ADC_MAX_BITWIDTH == 13
{ .res = ADC_WIDTH_BIT_13, .shift = 7 }, /* ADC_RES_6BIT */
{ .res = ADC_WIDTH_BIT_13, .shift = 5 }, /* ADC_RES_8BIT */
{ .res = ADC_WIDTH_BIT_13, .shift = 3 }, /* ADC_RES_10BIT */
{ .res = ADC_WIDTH_BIT_13, .shift = 1 }, /* ADC_RES_12BIT */
{ .res = ADC_WIDTH_MAX }, /* ADC_RES_14BIT */
{ .res = ADC_WIDTH_MAX }, /* ADC_RES_16BIT */
#endif
};
static bool _adc_module_initialized = false;
static inline void _adc1_ctrl_init(void)
{
/* nothing to do for the moment */
}
static inline void _adc2_ctrl_init(void)
{
/* nothing to do for the moment */
}
int adc_init(adc_t line)
{
CHECK_PARAM_RET (line < ADC_NUMOF, -1)
DEBUG("[adc] line=%u\n", line);
if (line >= ADC_NUMOF) {
return -1;
}
if (!_adc_module_initialized) {
/* do some configuration checks */
if (!_adc_conf_check()) {
return -1;
}
_adc_module_init();
_adc_module_initialized = true;
}
/* get the RTCIO pin number for the given GPIO defined as ADC channel */
uint8_t rtcio = _gpio_rtcio_map[adc_channels[line]];
if (_adc_hw[rtcio].adc_ctrl == ADC1_CTRL) {
_adc1_ctrl_init();
}
if (_adc_hw[rtcio].adc_ctrl == ADC2_CTRL) {
_adc2_ctrl_init();
/* check whether the GPIO is avalid ADC channel pin */
if (rtcio == RTCIO_NA) {
return -1;
}
/* try to initialize the pin as ADC input */
/* check whether the pin is not used for other purposes */
if (gpio_get_pin_usage(_adc_hw[rtcio].gpio) != _GPIO) {
LOG_TAG_ERROR("adc", "GPIO%d is used for %s and cannot be used as "
"ADC input\n", _adc_hw[rtcio].gpio,
@ -76,73 +130,25 @@ int adc_init(adc_t line)
return -1;
}
uint8_t idx;
/* disable the pad output */
RTCIO.enable_w1tc.val = BIT(_adc_hw[rtcio].rtc_gpio);
/* route pads to RTC and if possible, disable input, pull-up/pull-down */
switch (rtcio) {
case RTCIO_SENSOR_SENSE1: /* GPIO36, RTC0 */
RTCIO.sensor_pads.sense1_mux_sel = 1; /* route to RTC */
RTCIO.sensor_pads.sense1_fun_sel = 0; /* function ADC1_CH0 */
break;
case RTCIO_SENSOR_SENSE2: /* GPIO37, RTC1 */
RTCIO.sensor_pads.sense2_mux_sel = 1; /* route to RTC */
RTCIO.sensor_pads.sense2_fun_sel = 0; /* function ADC1_CH1 */
break;
case RTCIO_SENSOR_SENSE3: /* GPIO38, RTC2 */
RTCIO.sensor_pads.sense3_mux_sel = 1; /* route to RTC */
RTCIO.sensor_pads.sense3_fun_sel = 0; /* function ADC1_CH2 */
break;
case RTCIO_SENSOR_SENSE4: /* GPIO39, RTC3 */
RTCIO.sensor_pads.sense4_mux_sel = 1; /* route to RTC */
RTCIO.sensor_pads.sense4_fun_sel = 0; /* function ADC1_CH3 */
break;
case RTCIO_TOUCH0: /* GPIO4, RTC10 */
case RTCIO_TOUCH1: /* GPIO0, RTC11 */
case RTCIO_TOUCH2: /* GPIO2, RTC12 */
case RTCIO_TOUCH3: /* GPIO15, RTC13 */
case RTCIO_TOUCH4: /* GPIO13, RTC14 */
case RTCIO_TOUCH5: /* GPIO12, RTC15 */
case RTCIO_TOUCH6: /* GPIO14, RTC16 */
case RTCIO_TOUCH7: /* GPIO27, RTC17 */
case RTCIO_TOUCH8: /* GPIO33, RTC8 */
case RTCIO_TOUCH9: /* GPIO32, RTC9 */
idx = rtcio - RTCIO_TOUCH0;
RTCIO.touch_pad[idx].mux_sel = 1; /* route to RTC */
RTCIO.touch_pad[idx].fun_sel = 0; /* function ADC2_CH0..ADC2_CH9 */
RTCIO.touch_pad[idx].fun_ie = 0; /* input disabled */
RTCIO.touch_pad[idx].rue = 0; /* pull-up disabled */
RTCIO.touch_pad[idx].rde = 0; /* pull-down disabled */
RTCIO.touch_pad[idx].xpd = 0; /* touch sensor powered off */
break;
case RTCIO_ADC_ADC1: /* GPIO34, RTC4 */
RTCIO.adc_pad.adc1_mux_sel = 1; /* route to RTC */
RTCIO.adc_pad.adc1_fun_sel = 0; /* function ADC1_CH6 */
break;
case RTCIO_ADC_ADC2: /* GPIO35, RTC5 */
RTCIO.adc_pad.adc2_mux_sel = 1; /* route to RTC */
RTCIO.adc_pad.adc2_fun_sel = 0; /* function ADC1_CH7 */
break;
case RTCIO_DAC1: /* GPIO25, RTC6 */
case RTCIO_DAC2: /* GPIO26, RTC7 */
idx = rtcio - RTCIO_DAC1;
RTCIO.pad_dac[idx].mux_sel = 1; /* route to RTC */
RTCIO.pad_dac[idx].fun_sel = 0; /* function ADC2_CH8, ADC2_CH9 */
RTCIO.pad_dac[idx].fun_ie = 0; /* input disabled */
RTCIO.pad_dac[idx].rue = 0; /* pull-up disabled */
RTCIO.pad_dac[idx].rde = 0; /* pull-down disabled */
RTCIO.pad_dac[idx].xpd_dac = 0; /* DAC powered off */
break;
default: return -1;
if (_adc_hw[rtcio].adc_ctrl == ADC_UNIT_1) {
/* initialize the ADC1 unit if needed */
_adc1_ctrl_init();
/* set the attenuation and configure its associated GPIO pin mux */
esp_idf_adc1_config_channel_atten(_adc_hw[rtcio].adc_channel,
ADC_ATTEN_DB_11);
}
else if (_adc_hw[rtcio].adc_ctrl == ADC_UNIT_2) {
/* initialize the ADC2 unit if needed */
_adc2_ctrl_init();
/* set the attenuation and configure its associated GPIO pin mux */
esp_idf_adc2_config_channel_atten(_adc_hw[rtcio].adc_channel,
ADC_ATTEN_DB_11);
}
else {
return -1;
}
/* set pin usage type */
/* set pin usage type */
gpio_set_pin_usage(_adc_hw[rtcio].gpio, _ADC);
return 0;
@ -150,95 +156,83 @@ int adc_init(adc_t line)
int32_t adc_sample(adc_t line, adc_res_t res)
{
CHECK_PARAM_RET (line < ADC_NUMOF, -1)
CHECK_PARAM_RET (res <= ADC_RES_12BIT, -1)
DEBUG("[adc] line=%u res=%u\n", line, res);
if (_adc_esp_res_map[res].res == ADC_WIDTH_MAX) {
return -1;
}
uint8_t rtcio = _gpio_rtcio_map[adc_channels[line]];
int raw;
if (_adc_hw[rtcio].adc_ctrl == ADC1_CTRL) {
/* set the resolution for the measurement */
SENS.sar_start_force.sar1_bit_width = res;
SENS.sar_read_ctrl.sar1_sample_bit = res;
/* enable the pad in the pad enable bitmap */
SENS.sar_meas_start1.sar1_en_pad = (1 << _adc_hw[rtcio].adc_channel);
while (SENS.sar_slave_addr1.meas_status != 0) {}
/* start measurement by toggling the start bit and wait until the
measurement has been finished */
SENS.sar_meas_start1.meas1_start_sar = 0;
SENS.sar_meas_start1.meas1_start_sar = 1;
while (SENS.sar_meas_start1.meas1_done_sar == 0) {}
/* read out the result and return */
return SENS.sar_meas_start1.meas1_data_sar;
if (_adc_hw[rtcio].adc_ctrl == ADC_UNIT_1) {
esp_idf_adc1_config_width(_adc_esp_res_map[res].res);
raw = esp_idf_adc1_get_raw(_adc_hw[rtcio].adc_channel);
if (raw < 0) {
return -1;
}
}
else {
/* set the resolution for the measurement */
SENS.sar_start_force.sar2_bit_width = res;
SENS.sar_read_ctrl2.sar2_sample_bit = res;
/* enable the pad in the pad enable bitmap */
SENS.sar_meas_start2.sar2_en_pad = (1 << _adc_hw[rtcio].adc_channel);
/* start measurement by toggling the start bit and wait until the
measurement has been finished */
SENS.sar_meas_start2.meas2_start_sar = 0;
SENS.sar_meas_start2.meas2_start_sar = 1;
while (SENS.sar_meas_start2.meas2_done_sar == 0) {}
/* read out the result and return */
return SENS.sar_meas_start2.meas2_data_sar;
}
}
int adc_set_attenuation(adc_t line, adc_attenuation_t atten)
{
CHECK_PARAM_RET (line < ADC_NUMOF, -1)
uint8_t rtcio = _gpio_rtcio_map[adc_channels[line]];
if (_adc_hw[rtcio].adc_ctrl == ADC1_CTRL) {
SENS.sar_atten1 &= ~(0x3 << (_adc_hw[rtcio].adc_channel << 1));
SENS.sar_atten1 |= (atten << (_adc_hw[rtcio].adc_channel << 1));
}
else {
SENS.sar_atten2 &= ~(0x3 << (_adc_hw[rtcio].adc_channel << 1));
SENS.sar_atten2 |= (atten << (_adc_hw[rtcio].adc_channel << 1));
}
return 0;
}
int adc_vref_to_gpio25 (void)
{
/* determine ADC line for GPIO25 */
adc_t line = ADC_UNDEF;
for (unsigned i = 0; i < ADC_NUMOF; i++) { \
if (adc_channels[i] == GPIO25) { \
line = i;
break;
else if (_adc_hw[rtcio].adc_ctrl == ADC_UNIT_2) {
if (esp_idf_adc2_get_raw(_adc_hw[rtcio].adc_channel,
_adc_esp_res_map[res].res, &raw) < 0) {
return -1;
}
}
if (line == ADC_UNDEF) {
LOG_TAG_ERROR("adc", "Have no ADC line for GPIO25\n");
return -1;
return raw >> _adc_esp_res_map[res].shift;
}
int adc_set_attenuation(adc_t line, adc_atten_t atten)
{
DEBUG("[adc] line=%u atten=%u\n", line, atten);
uint8_t rtcio = _gpio_rtcio_map[adc_channels[line]];
assert(rtcio != RTCIO_NA);
if (_adc_hw[rtcio].adc_ctrl == ADC_UNIT_1) {
return esp_idf_adc1_config_channel_atten(_adc_hw[rtcio].adc_channel,
atten);
}
else if (_adc_hw[rtcio].adc_ctrl == ADC_UNIT_2) {
return esp_idf_adc2_config_channel_atten(_adc_hw[rtcio].adc_channel,
atten);
}
if (adc_init(line) == 0)
{
uint8_t rtcio = _gpio_rtcio_map[adc_channels[line]];
RTCCNTL.bias_conf.dbg_atten = 0;
RTCCNTL.test_mux.dtest_rtc = 1;
RTCCNTL.test_mux.ent_rtc = 1;
SENS.sar_start_force.sar2_en_test = 1;
SENS.sar_meas_start2.sar2_en_pad = (1 << _adc_hw[rtcio].adc_channel);
LOG_TAG_INFO("adc", "You can now measure Vref at GPIO25\n");
return 0;
return -1;
}
int adc_line_vref_to_gpio(adc_t line, gpio_t gpio)
{
uint8_t rtcio_vref = _gpio_rtcio_map[adc_channels[line]];
uint8_t rtcio_out = _gpio_rtcio_map[gpio];
/* both the ADC line and the GPIO for the output must be ADC channels */
assert(rtcio_vref != RTCIO_NA);
assert(rtcio_out != RTCIO_NA);
/* avoid compilation problems with NDEBUG defined */
(void)rtcio_out;
/* the GPIO for the output must be a channel of ADC2 */
assert(_adc_hw[rtcio_out].adc_ctrl == ADC_UNIT_2);
esp_err_t res = ESP_OK;
if (_adc_hw[rtcio_vref].adc_ctrl == ADC_UNIT_1) {
res = esp_idf_adc_vref_to_gpio(ADC_UNIT_1, gpio);
}
else if (_adc_hw[rtcio_vref].adc_ctrl == ADC_UNIT_2) {
res = esp_idf_adc_vref_to_gpio(ADC_UNIT_2, gpio);
}
if (res != ESP_OK) {
LOG_TAG_ERROR("adc", "Could not route Vref of ADC line %d to GPIO%d\n",
line, gpio);
return -1;
}
else {
LOG_TAG_ERROR("adc", "Could not init GPIO25 as Vref output\n");
return -1;
LOG_TAG_ERROR("adc", "Vref of ADC%d can now be measured at GPIO %d\n",
_adc_hw[rtcio_vref].adc_ctrl, gpio);
return 0;
}
}
@ -255,18 +249,6 @@ static bool _adc_conf_check(void)
return true;
}
static void _adc_module_init(void)
{
RTCIO.enable_w1tc.val = ~0x0;
/* always power on */
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
/* disable temperature sensor */
SENS.sar_tctrl.tsens_power_up_force = 1; /* controlled by SW */
SENS.sar_tctrl.tsens_power_up = 0; /* power down */
}
void adc_print_config(void)
{
printf("\tADC\t\tpins=[ ");

109
cpu/esp32/periph/adc_arch.c Normal file
View File

@ -0,0 +1,109 @@
/*
* 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
* @{
*
* @file
* @brief Architecture-specific ADC/DAC definitions for ESP32 variant (family)
*
* @author Gunar Schorcht <gunar@schorcht.net>
*
* @}
*/
#include "board.h"
#include "adc_arch_private.h"
#include "esp_common.h"
#include "soc/adc_channel.h"
#define ENABLE_DEBUG 0
#include "debug.h"
/**
* @brief ADC hardware descriptor table (for internal use only)
*
* Reference: Technical Reference Manual, Section 4.11 Table 19
* https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
*
* @note The index of entries in the table MUST correspond to the
* RTCIO GPIO number.
*/
const _adc_hw_desc_t _adc_hw[] = {
/* rtcio, gpio, adc_ctrl, adc_channel, pad_name */
{ RTCIO_GPIO(0), ADC1_CHANNEL_0_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_0, "SENSOR_VP" },
{ RTCIO_GPIO(1), ADC1_CHANNEL_1_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_1, "SENSOR_CAPP" },
{ RTCIO_GPIO(2), ADC1_CHANNEL_2_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_2, "SENSOR_CAPN" },
{ RTCIO_GPIO(3), ADC1_CHANNEL_3_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_3, "SENSOR_VN" },
{ RTCIO_GPIO(4), ADC1_CHANNEL_6_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_6, "VDET_1" },
{ RTCIO_GPIO(5), ADC1_CHANNEL_7_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_7, "VDET_2" },
{ RTCIO_GPIO(6), ADC2_CHANNEL_8_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_8, "GPIO25" },
{ RTCIO_GPIO(7), ADC2_CHANNEL_9_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_9, "GPIO26" },
{ RTCIO_GPIO(8), ADC1_CHANNEL_5_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_5, "32K_XN" },
{ RTCIO_GPIO(9), ADC1_CHANNEL_4_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_4, "32K_XP" },
{ RTCIO_GPIO(10), ADC2_CHANNEL_0_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_0, "GPIO4" },
{ RTCIO_GPIO(11), ADC2_CHANNEL_1_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_1, "GPIO0" },
{ RTCIO_GPIO(12), ADC2_CHANNEL_2_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_2, "GPIO2" },
{ RTCIO_GPIO(13), ADC2_CHANNEL_3_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_3, "MTDO" },
{ RTCIO_GPIO(14), ADC2_CHANNEL_4_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_4, "MTCK" },
{ RTCIO_GPIO(15), ADC2_CHANNEL_5_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_5, "MTDI" },
{ RTCIO_GPIO(16), ADC2_CHANNEL_6_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_6, "MTMS" },
{ RTCIO_GPIO(17), ADC2_CHANNEL_7_GPIO_NUM, ADC_UNIT_2, ADC_CHANNEL_7, "GPIO27" },
};
/**
* @brief GPIO to RTC IO map (for internal use only)
*
* Reference: Technical Reference Manual, Section 4.11 Table 19
* https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
*/
const gpio_t _gpio_rtcio_map[] = {
RTCIO_GPIO(11), /* GPIO0 */
RTCIO_NA, /* GPIO1 */
RTCIO_GPIO(12), /* GPIO2 */
RTCIO_NA, /* GPIO3 */
RTCIO_GPIO(10), /* GPIO4 */
RTCIO_NA, /* GPIO5 */
RTCIO_NA, /* GPIO6 */
RTCIO_NA, /* GPIO7 */
RTCIO_NA, /* GPIO8 */
RTCIO_NA, /* GPIO9 */
RTCIO_NA, /* GPIO10 */
RTCIO_NA, /* GPIO11 */
RTCIO_GPIO(15), /* GPIO12 MTDI */
RTCIO_GPIO(14), /* GPIO13 MTCK */
RTCIO_GPIO(16), /* GPIO14 MTMS */
RTCIO_GPIO(13), /* GPIO15 MTDO */
RTCIO_NA, /* GPIO16 */
RTCIO_NA, /* GPIO17 */
RTCIO_NA, /* GPIO18 */
RTCIO_NA, /* GPIO19 */
RTCIO_NA, /* GPIO20 */
RTCIO_NA, /* GPIO21 */
RTCIO_NA, /* GPIO22 */
RTCIO_NA, /* GPIO23 */
RTCIO_NA, /* GPIO24 */
RTCIO_GPIO(6), /* GPIO25 */
RTCIO_GPIO(7), /* GPIO26 */
RTCIO_GPIO(17), /* GPIO27 */
RTCIO_NA, /* GPIO28 */
RTCIO_NA, /* GPIO29 */
RTCIO_NA, /* GPIO30 */
RTCIO_NA, /* GPIO31 */
RTCIO_GPIO(9), /* GPIO32 32K_XP */
RTCIO_GPIO(8), /* GPIO33 32K_XN */
RTCIO_GPIO(4), /* GPIO34 VDET_1 */
RTCIO_GPIO(5), /* GPIO35 VDET_2 */
RTCIO_GPIO(0), /* GPIO36 SENSOR_VP */
RTCIO_GPIO(1), /* GPIO37 SENSOR_CAPP */
RTCIO_GPIO(2), /* GPIO38 SENSOR_CAPN */
RTCIO_GPIO(3), /* GPIO39 SENSOR_VN */
};

View File

@ -1,169 +0,0 @@
/*
* Copyright (C) 2019 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
* @{
*
* @file
* @brief ADC controller functions used by ADC and DAC peripherals
*
* @author Gunar Schorcht <gunar@schorcht.net>
*
* @}
*/
#include "board.h"
#include "adc_ctrl.h"
#include "esp_common.h"
#include "soc/rtc_io_struct.h"
#include "soc/rtc_cntl_struct.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#define ENABLE_DEBUG 0
#include "debug.h"
/**
* @brief RTC hardware map
*
* The index corresponds to RTC pin type _rtcio_pin_t (Table 19 in Technical
* Reference)
*/
const struct _adc_hw_t _adc_hw[] =
{
/* gpio rtc_gpio adc_ctrl adc_channel, pad_name */
{ GPIO4, 10, ADC2_CTRL, 0, "GPIO4" }, /* RTCIO_TOUCH0 */
{ GPIO0, 11, ADC2_CTRL, 1, "GPIO0" }, /* RTCIO_TOUCH1 */
{ GPIO2, 12, ADC2_CTRL, 2, "GPIO2" }, /* RTCIO_TOUCH2 */
{ GPIO15, 13, ADC2_CTRL, 3, "MTDO" }, /* RTCIO_TOUCH3 */
{ GPIO13, 14, ADC2_CTRL, 4, "MTCK" }, /* RTCIO_TOUCH4 */
{ GPIO12, 15, ADC2_CTRL, 5, "MTDI" }, /* RTCIO_TOUCH5 */
{ GPIO14, 16, ADC2_CTRL, 6, "MTMS" }, /* RTCIO_TOUCH6 */
{ GPIO27, 17, ADC2_CTRL, 7, "GPIO27" }, /* RTCIO_TOUCH7 */
{ GPIO33, 8, ADC1_CTRL, 5, "32K_XN" }, /* RTCIO_TOUCH8 */
{ GPIO32, 9, ADC1_CTRL, 4, "32K_XP" }, /* RTCIO_TOUCH9 */
{ GPIO34, 4, ADC1_CTRL, 6, "VDET_1" }, /* RTCIO_ADC_ADC1 */
{ GPIO35, 5, ADC1_CTRL, 7, "VDET_2" }, /* RTCIO_ADC_ADC2 */
{ GPIO36, 0, ADC1_CTRL, 0, "SENSOR_VP" }, /* RTCIO_SENSOR_SENSE1 */
{ GPIO37, 1, ADC1_CTRL, 1, "SENSOR_CAPP" }, /* RTCIO_SENSOR_SENSE2 */
{ GPIO38, 2, ADC1_CTRL, 2, "SENSOR_CAPN" }, /* RTCIO_SENSOR_SENSE3 */
{ GPIO39, 3, ADC1_CTRL, 3, "SENSOR_VN" }, /* RTCIO_SENSOR_SENSE4 */
{ GPIO25, 6, ADC2_CTRL, 8, "GPIO25" }, /* RTCIO_DAC1 */
{ GPIO26, 7, ADC2_CTRL, 9, "GPIO26" } /* RTCIO_DAC2 */
};
/* maps GPIO pin to RTC pin, this index is used to access ADC hardware table
(Table 19 in Technical Reference) */
const gpio_t _gpio_rtcio_map[] = {
RTCIO_TOUCH1, /* GPIO0 */
RTCIO_NA , /* GPIO1 */
RTCIO_TOUCH2, /* GPIO2 */
RTCIO_NA, /* GPIO3 */
RTCIO_TOUCH0, /* GPIO4 */
RTCIO_NA, /* GPIO5 */
RTCIO_NA, /* GPIO6 */
RTCIO_NA, /* GPIO7 */
RTCIO_NA, /* GPIO8 */
RTCIO_NA, /* GPIO9 */
RTCIO_NA, /* GPIO10 */
RTCIO_NA, /* GPIO11 */
RTCIO_TOUCH5, /* GPIO12 MTDI */
RTCIO_TOUCH4, /* GPIO13 MTCK */
RTCIO_TOUCH6, /* GPIO14 MTMS */
RTCIO_TOUCH3, /* GPIO15 MTDO */
RTCIO_NA, /* GPIO16 */
RTCIO_NA, /* GPIO17 */
RTCIO_NA, /* GPIO18 */
RTCIO_NA, /* GPIO19 */
RTCIO_NA, /* GPIO20 */
RTCIO_NA, /* GPIO21 */
RTCIO_NA, /* GPIO22 */
RTCIO_NA, /* GPIO23 */
RTCIO_NA, /* GPIO24 */
RTCIO_DAC1, /* GPIO25 */
RTCIO_DAC2, /* GPIO26 */
RTCIO_TOUCH7, /* GPIO27 */
RTCIO_NA, /* GPIO28 */
RTCIO_NA, /* GPIO29 */
RTCIO_NA, /* GPIO30 */
RTCIO_NA, /* GPIO31 */
RTCIO_TOUCH9, /* GPIO32 32K_XP */
RTCIO_TOUCH8, /* GPIO33 32K_XN */
RTCIO_ADC_ADC1, /* GPIO34 VDET_1 */
RTCIO_ADC_ADC2, /* GPIO35 VDET_2 */
RTCIO_SENSOR_SENSE1, /* GPIO36 SENSOR_VP */
RTCIO_SENSOR_SENSE2, /* GPIO37 SENSOR_CAPP */
RTCIO_SENSOR_SENSE3, /* GPIO38 SENSOR_CAPN */
RTCIO_SENSOR_SENSE4, /* GPIO39 SENSOR_VN */
};
/* flags to indicate whether the according controller is already initialized */
static bool _adc1_ctrl_initialized = false;
static bool _adc2_ctrl_initialized = false;
void _adc1_ctrl_init(void)
{
/* return if already initialized */
if (_adc1_ctrl_initialized) {
return;
}
/* always power on */
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
/* power off LN amp */
SENS.sar_meas_wait2.sar2_rstb_wait = 2;
SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0;
SENS.sar_meas_ctrl.amp_short_ref_fsm = 0;
SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
SENS.sar_meas_wait1.sar_amp_wait1 = 1;
SENS.sar_meas_wait1.sar_amp_wait2 = 1;
SENS.sar_meas_wait2.sar_amp_wait3 = 1;
SENS.sar_meas_wait2.force_xpd_amp = SENS_FORCE_XPD_AMP_PD;
/* SAR ADC1 controller configuration */
SENS.sar_read_ctrl.sar1_dig_force = 0; /* SAR ADC1 controlled by RTC */
SENS.sar_meas_start1.meas1_start_force = 1; /* SAR ADC1 started by SW */
SENS.sar_meas_start1.sar1_en_pad_force = 1; /* pad enable bitmap controlled by SW */
SENS.sar_touch_ctrl1.xpd_hall_force = 1; /* XPD HALL is controlled by SW */
SENS.sar_touch_ctrl1.hall_phase_force = 1; /* HALL PHASE is controlled by SW */
SENS.sar_read_ctrl.sar1_data_inv = 1; /* invert data */
SENS.sar_atten1 = 0xffffffff; /* set attenuation to 11 dB for all pads
(input range 0 ... 3,3 V) */
/* power off built-in hall sensor */
RTCIO.hall_sens.xpd_hall = 0;
/* set default resolution */
SENS.sar_start_force.sar1_bit_width = ADC_RES_12BIT;
SENS.sar_read_ctrl.sar1_sample_bit = ADC_RES_12BIT;
_adc1_ctrl_initialized = true;
}
void _adc2_ctrl_init(void)
{
/* return if already initialized */
if (_adc2_ctrl_initialized) {
return;
}
/* SAR ADC2 controller configuration */
SENS.sar_read_ctrl2.sar2_dig_force = 0; /* SAR ADC2 controlled by RTC not DIG*/
SENS.sar_meas_start2.meas2_start_force = 1; /* SAR ADC2 started by SW */
SENS.sar_meas_start2.sar2_en_pad_force = 1; /* pad enable bitmap controlled by SW */
SENS.sar_read_ctrl2.sar2_data_inv = 1; /* invert data */
SENS.sar_atten2 = 0xffffffff; /* set attenuation to 11 dB for all pads
(input range 0 ... 3,3 V) */
/* set default resolution */
SENS.sar_start_force.sar2_bit_width = ADC_RES_12BIT;
SENS.sar_read_ctrl2.sar2_sample_bit = ADC_RES_12BIT;
_adc2_ctrl_initialized = true;
}