ulp-fsm: Update ulp-fsm ADC example with S3 support

Closes https://github.com/espressif/esp-idf/issues/7963
This commit is contained in:
Marius Vikhammer 2022-09-02 16:18:14 +08:00
parent ee2ae1d589
commit 77ba84eeb7
11 changed files with 118 additions and 53 deletions

View File

@ -6,7 +6,8 @@ set(includes "")
if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED)
list(APPEND srcs
"ulp_common/ulp_common.c")
"ulp_common/ulp_common.c"
"ulp_common/ulp_adc.c")
list(APPEND includes
ulp_common/include
@ -25,7 +26,6 @@ if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED)
list(APPEND srcs
"ulp_riscv/ulp_riscv.c"
"ulp_riscv/ulp_riscv_lock.c"
"ulp_riscv/ulp_riscv_adc.c"
"ulp_riscv/ulp_riscv_i2c.c")
list(APPEND includes

View File

@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "hal/adc_types.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
adc_unit_t adc_n; // ADC Unit
adc_channel_t channel; // ADC channel
adc_atten_t atten; // ADC channel attenuation
adc_bitwidth_t width; // ADC bit width, only used for ADC unit 1
adc_ulp_mode_t ulp_mode; // ADC ULP Mode
} ulp_adc_cfg_t; // ULP FSM ADC configuration parameters
/**
* @brief Initialize and calibrate the ADC for use by ULP FSM
*
* @param cfg Configuration parameters
* @return esp_err_t ESP_OK for successful.
*/
esp_err_t ulp_adc_init(const ulp_adc_cfg_t *cfg);
#ifdef __cplusplus
}
#endif

View File

@ -4,7 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "ulp_riscv_adc.h"
#include "sdkconfig.h"
#include "ulp_adc.h"
#include "esp_err.h"
#include "esp_check.h"
#include "esp_log.h"
@ -13,9 +14,9 @@
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/adc_share_hw_ctrl.h"
static const char *TAG = "ulp_riscv_adc";
static const char *TAG = "ulp_adc";
esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg)
esp_err_t ulp_adc_init(const ulp_adc_cfg_t *cfg)
{
esp_err_t ret = ESP_OK;
@ -24,10 +25,19 @@ esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg)
//-------------ADC1 Init---------------//
adc_oneshot_unit_handle_t adc1_handle;
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = cfg->adc_n,
.ulp_mode = ADC_ULP_MODE_RISCV,
.ulp_mode = cfg->ulp_mode,
};
if (init_config1.ulp_mode == ADC_ULP_MODE_DISABLE) {
/* Default to RISCV for backward compatibility */
ESP_LOGI(TAG, "No ulp mode specified in cfg struct, default to riscv");
init_config1.ulp_mode = ADC_ULP_MODE_RISCV;
}
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
//-------------ADC1 Config---------------//
@ -38,7 +48,10 @@ esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg)
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, cfg->channel, &config));
//Calibrate the ADC
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
adc_set_hw_calibration_code(cfg->adc_n, cfg->atten);
#endif
esp_sleep_enable_adc_tsens_monitor(true);
err:

View File

@ -9,24 +9,15 @@
#include "hal/adc_types.h"
#include "esp_err.h"
#include "ulp_adc.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
adc_unit_t adc_n; // ADC Unit
adc_channel_t channel; // ADC channel
adc_atten_t atten; // ADC channel attenuation
adc_bitwidth_t width; // ADC bit width, only used for ADC unit 1
} ulp_riscv_adc_cfg_t; // ULP Riscv ADC configuration parameters
/**
* @brief Initialize and calibrate the ADC for use by ULP RISCV
*
* @param cfg Configuration parameters
* @return esp_err_t ESP_OK for successful.
*/
esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg);
/* Kept for backwards compatibilty */
#define ulp_riscv_adc_cfg_t ulp_adc_cfg_t
#define ulp_riscv_adc_init ulp_adc_init
#ifdef __cplusplus
}

View File

@ -160,7 +160,7 @@ examples/system/ulp_fsm/ulp:
examples/system/ulp_fsm/ulp_adc:
enable:
- if: IDF_TARGET == "esp32"
- if: IDF_TARGET in ["esp32", "esp32s3"]
temporary: true
reason: the other targets are not tested yet

View File

@ -1,11 +1,11 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
| Supported Targets | ESP32 | ESP32-S3 |
| ----------------- | ----- | -------- |
# ULP ADC Example
This example demonstrates how to use the ULP coprocessor to poll ADC in deep sleep.
ULP program periodically measures the input voltage on GPIO34. The voltage is compared to two thresholds. If the voltage is less than the low threshold, or higher than the high threshold, ULP wakes up the system.
ULP program periodically measures the input voltage on ADC_CHANNEL_6 (GPIO34 on ESP32, GPIO7 on ESP32-S3). The voltage is compared to two thresholds. If the voltage is less than the low threshold, or higher than the high threshold, ULP wakes up the system.
By default, thresholds are set to 1.35V and 1.75V, approximately.

View File

@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* ULP Example: using ADC in deep sleep
This example code is in the Public Domain (or CC0 licensed, at your option.)
@ -22,9 +27,9 @@
*/
#include "soc/rtc_cntl_reg.h"
#include "soc/soc_ulp.h"
#include "example_config.h"
/* ADC1 channel 6, GPIO34 */
.set adc_channel, 6
.set adc_channel, EXAMPLE_ADC_CHANNEL
/* Configure the number of ADC samples to average on each measurement.
For convenience, make it a power of 2. */

View File

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
/* Ints are used here to be able to include the file in assembly as well */
#define EXAMPLE_ADC_CHANNEL 6 // ADC_CHANNEL_6, GPIO34 on ESP32, GPIO7 on ESP32-S3
#define EXAMPLE_ADC_UNIT 0 // ADC_UNIT_1
#define EXAMPLE_ADC_ATTEN 3 // ADC_ATTEN_DB_11
#define EXAMPLE_ADC_WIDTH 0 // ADC_BITWIDTH_DEFAULT
/* Set low and high thresholds, approx. 1.35V - 1.75V*/
#define EXAMPLE_ADC_LOW_TRESHOLD 1500
#define EXAMPLE_ADC_HIGH_TRESHOLD 2000

View File

@ -10,16 +10,18 @@
#include <stdio.h>
#include <string.h>
#include "esp_sleep.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/gpio.h"
#include "driver/rtc_io.h"
#include "driver/dac.h"
#include "esp32/ulp.h"
#include "ulp.h"
#include "ulp_main.h"
#include "esp_adc/adc_oneshot.h"
#include "ulp/example_config.h"
#include "ulp_adc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
@ -51,6 +53,12 @@ void app_main(void)
printf("Entering deep sleep\n\n");
start_ulp_program();
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
#if !CONFIG_IDF_TARGET_ESP32
/* RTC peripheral power domain needs to be kept on to keep SAR ADC related configs during sleep */
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
#endif
esp_deep_sleep_start();
}
@ -60,35 +68,31 @@ static void init_ulp_program(void)
(ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
ESP_ERROR_CHECK(err);
//-------------ADC1 Init---------------//
adc_oneshot_unit_handle_t adc1_handle;
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1,
ulp_adc_cfg_t cfg = {
.adc_n = EXAMPLE_ADC_UNIT,
.channel = EXAMPLE_ADC_CHANNEL,
.width = EXAMPLE_ADC_WIDTH,
.atten = EXAMPLE_ADC_ATTEN,
.ulp_mode = ADC_ULP_MODE_FSM,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
//-------------ADC1 Channel Config---------------//
// Note: when changing channel here, also change 'adc_channel' constant in adc.S
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_DEFAULT,
.atten = ADC_ATTEN_DB_11,
};
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_6, &config));
ESP_ERROR_CHECK(ulp_adc_init(&cfg));
/* Set low and high thresholds, approx. 1.35V - 1.75V*/
ulp_low_thr = 1500;
ulp_high_thr = 2000;
ulp_low_thr = EXAMPLE_ADC_LOW_TRESHOLD;
ulp_high_thr = EXAMPLE_ADC_HIGH_TRESHOLD;
/* Set ULP wake up period to 20ms */
ulp_set_wakeup_period(0, 20000);
#if CONFIG_IDF_TARGET_ESP32
/* Disconnect GPIO12 and GPIO15 to remove current drain through
* pullup/pulldown resistors.
* pullup/pulldown resistors on modules which have these (e.g. ESP32-WROVER)
* GPIO12 may be pulled high to select flash voltage.
*/
rtc_gpio_isolate(GPIO_NUM_12);
rtc_gpio_isolate(GPIO_NUM_15);
#endif // CONFIG_IDF_TARGET_ESP32
esp_deep_sleep_disable_rom_logging(); // suppress boot messages
}

View File

@ -8,6 +8,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s3
@pytest.mark.generic
def test_ulp_fsm_adc(dut: Dut) -> None:

View File

@ -15,7 +15,7 @@
#include <stdio.h>
#include "esp_sleep.h"
#include "ulp_riscv.h"
#include "ulp_riscv_adc.h"
#include "ulp_adc.h"
#include "ulp_main.h"
#include "ulp/example_config.h"
@ -56,14 +56,15 @@ void app_main(void)
static void init_ulp_program(void)
{
ulp_riscv_adc_cfg_t cfg = {
.adc_n = EXAMPLE_ADC_UNIT,
.channel = EXAMPLE_ADC_CHANNEL,
.width = EXAMPLE_ADC_WIDTH,
.atten = EXAMPLE_ADC_ATTEN,
ulp_adc_cfg_t cfg = {
.adc_n = EXAMPLE_ADC_UNIT,
.channel = EXAMPLE_ADC_CHANNEL,
.width = EXAMPLE_ADC_WIDTH,
.atten = EXAMPLE_ADC_ATTEN,
.ulp_mode = ADC_ULP_MODE_RISCV,
};
ESP_ERROR_CHECK(ulp_riscv_adc_init(&cfg));
ESP_ERROR_CHECK(ulp_adc_init(&cfg));
esp_err_t err = ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start));
ESP_ERROR_CHECK(err);