ソースを参照

Merge branch 'feature/ulp_fsm_adc_s3' into 'master'

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

Closes IDFGH-6299

See merge request espressif/esp-idf!19924
Marius Vikhammer 3 年 前
コミット
cb48a7b9f9

+ 2 - 2
components/ulp/CMakeLists.txt

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

+ 34 - 0
components/ulp/ulp_common/include/ulp_adc.h

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

+ 17 - 4
components/ulp/ulp_riscv/ulp_riscv_adc.c → components/ulp/ulp_common/ulp_adc.c

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

+ 5 - 14
components/ulp/ulp_riscv/include/ulp_riscv_adc.h

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

+ 1 - 1
examples/system/.build-test-rules.yml

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

+ 3 - 3
examples/system/ulp_fsm/ulp_adc/README.md

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

+ 7 - 2
examples/system/ulp_fsm/ulp_adc/main/ulp/adc.S

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

+ 16 - 0
examples/system/ulp_fsm/ulp_adc/main/ulp/example_config.h

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

+ 24 - 20
examples/system/ulp_fsm/ulp_adc/main/ulp_adc_example_main.c

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

+ 1 - 0
examples/system/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py

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

+ 8 - 7
examples/system/ulp_riscv/adc/main/ulp_riscv_adc_example_main.c

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