kopia lustrzana https://github.com/espressif/esp-idf
ulp-riscv: add support for using ADC as well as an example show-casing it.
rodzic
627b171a3c
commit
e8b5096f52
|
@ -83,8 +83,6 @@ void bootloader_random_disable(void)
|
|||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
|
||||
|
||||
//Stop SAR ADC clock
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_SARADC_CLK_EN);
|
||||
//Power off SAR ADC
|
||||
REG_SET_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0);
|
||||
//return to ADC RTC controller
|
||||
|
|
|
@ -225,7 +225,7 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
|
|||
#if SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
static uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan)
|
||||
uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan)
|
||||
{
|
||||
adc_atten_t atten = adc_ll_get_atten(adc_n, chan);
|
||||
extern uint32_t adc_get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten);
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enables the use of ADC and temperature sensor in monitor (ULP) mode
|
||||
*
|
||||
* @note This state is kept in RTC memory and will keep its value after a deep sleep wakeup
|
||||
*
|
||||
*/
|
||||
void esp_sleep_enable_adc_tsens_monitor(bool enable);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -182,7 +182,7 @@ static bool s_light_sleep_wakeup = false;
|
|||
static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static const char *TAG = "sleep";
|
||||
static bool s_adc_tsen_enabled = false;
|
||||
static RTC_FAST_ATTR bool s_adc_tsen_enabled = false;
|
||||
//in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT.
|
||||
static bool s_ultra_low_enabled = false;
|
||||
|
||||
|
@ -1386,7 +1386,7 @@ void esp_deep_sleep_disable_rom_logging(void)
|
|||
rtc_suppress_rom_log();
|
||||
}
|
||||
|
||||
void rtc_sleep_enable_adc_tesn_monitor(bool enable)
|
||||
void esp_sleep_enable_adc_tsens_monitor(bool enable)
|
||||
{
|
||||
s_adc_tsen_enabled = enable;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ This test app is to enter 7 different sub power modes we have, so that the power
|
|||
Currently there are 6 sub power modes, 3 for deepsleep and 3 for lightsleep. Show as below (priority from high to low).
|
||||
|
||||
## Deepsleep
|
||||
1. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mode, call `rtc_sleep_enable_adc_tesn_monitor`.
|
||||
1. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mode, call `esp_sleep_enable_adc_tsens_monitor`.
|
||||
2. Default mode.
|
||||
3. Ultra low power mode. To enable this mode, call `rtc_sleep_enable_ultra_low`. Note if mode 1 has higher priority than this.
|
||||
|
||||
## Lightsleep
|
||||
1. Mode for using 40 MHz XTAL in lightsleep. To enable this mode, call `esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON)`.
|
||||
2. Mode for using 8M clock by digital system (peripherals). To enable this mode, initialize LEDC with 8M clock source.
|
||||
3. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mdoe, call `rtc_sleep_enable_adc_tesn_monitor`.
|
||||
3. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mdoe, call `esp_sleep_enable_adc_tsens_monitor`.
|
||||
4. Default mode.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "soc/soc_caps.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
|
||||
static const char TAG[] = "rtc_power";
|
||||
|
||||
|
@ -30,8 +31,7 @@ TEST_CASE("Power Test: Deepsleep (with ADC/TSEN in monitor)", "[pm]")
|
|||
{
|
||||
rtc_dig_clk8m_disable(); //This is workaround for bootloader not disable 8M as digital clock source
|
||||
|
||||
extern void rtc_sleep_enable_adc_tesn_monitor(bool);
|
||||
rtc_sleep_enable_adc_tesn_monitor(true);
|
||||
esp_sleep_enable_adc_tsens_monitor(true);
|
||||
test_deepsleep();
|
||||
}
|
||||
|
||||
|
@ -108,8 +108,8 @@ TEST_CASE("Power Test: Lightsleep (with ADC/TSEN in monitor)", "[pm]")
|
|||
{
|
||||
rtc_dig_clk8m_disable(); //This is workaround for bootloader not disable 8M as digital clock source
|
||||
|
||||
extern void rtc_sleep_enable_adc_tesn_monitor(bool);
|
||||
rtc_sleep_enable_adc_tesn_monitor(true);
|
||||
extern void esp_sleep_enable_adc_tsens_monitor(bool);
|
||||
esp_sleep_enable_adc_tsens_monitor(true);
|
||||
test_lightsleep();
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,9 @@ extern void abort(void);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 1 // silent
|
||||
#if IS_ULP_COCPU
|
||||
#define HAL_ASSERT(__e) ((void)(__e))
|
||||
#elif CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 1 // silent
|
||||
#define HAL_ASSERT(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : abort())
|
||||
#elif CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 2 // full assertion
|
||||
#define HAL_ASSERT(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : __assert_func(__FILE__, __LINE__, __ASSERT_FUNC, #__e))
|
||||
|
|
|
@ -23,7 +23,8 @@ if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED)
|
|||
|
||||
elseif(CONFIG_ULP_COPROC_TYPE_RISCV)
|
||||
list(APPEND srcs
|
||||
"ulp_riscv/ulp_riscv.c")
|
||||
"ulp_riscv/ulp_riscv.c"
|
||||
"ulp_riscv/ulp_riscv_adc.c")
|
||||
|
||||
list(APPEND includes
|
||||
ulp_riscv/include)
|
||||
|
@ -31,4 +32,5 @@ if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED)
|
|||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${includes})
|
||||
INCLUDE_DIRS ${includes}
|
||||
REQUIRES driver)
|
||||
|
|
|
@ -71,8 +71,9 @@ add_custom_target(${ULP_APP_NAME}_ld_script
|
|||
if(ULP_COCPU_IS_RISCV)
|
||||
#risc-v ulp uses extra files for building:
|
||||
list(APPEND ULP_S_SOURCES
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/start.S"
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_riscv_utils.c")
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/start.S"
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_adc.c"
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c")
|
||||
|
||||
#dummy loop to force pre-processed linker file generation:
|
||||
foreach(ulp_s_source ${ULP_S_SOURCES})
|
||||
|
@ -95,7 +96,9 @@ if(ULP_COCPU_IS_RISCV)
|
|||
list(APPEND EXTRA_LINKER_ARGS "-Wl,--gc-sections")
|
||||
list(APPEND EXTRA_LINKER_ARGS "-Wl,-Map=\"${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME}.map\"")
|
||||
#Makes the csr utillies for riscv visible:
|
||||
target_include_directories(${ULP_APP_NAME} PRIVATE "${IDF_PATH}/components/ulp/ulp_riscv/include")
|
||||
target_include_directories(${ULP_APP_NAME} PRIVATE "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/include")
|
||||
target_link_libraries(${ULP_APP_NAME} "-T \"${IDF_PATH}/components/ulp/ld/${IDF_TARGET}.periperals.ld\"")
|
||||
target_compile_definitions(${ULP_APP_NAME} PRIVATE IS_ULP_COCPU)
|
||||
|
||||
else()
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
PROVIDE ( RTCCNTL = 0x8000 );
|
||||
PROVIDE ( RTCIO = 0xA400 );
|
||||
PROVIDE ( SENS = 0xC800 );
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
PROVIDE ( RTCCNTL = 0x8000 );
|
||||
PROVIDE ( RTCIO = 0xA400 );
|
||||
PROVIDE ( SENS = 0xC800 );
|
|
@ -58,6 +58,7 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs)
|
|||
-DULP_APP_NAME=${app_name}
|
||||
-DCOMPONENT_DIR=${COMPONENT_DIR}
|
||||
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
|
||||
-DIDF_TARGET=${idf_target}
|
||||
-DIDF_PATH=${idf_path}
|
||||
-DSDKCONFIG_HEADER=${SDKCONFIG_HEADER}
|
||||
-DPYTHON=${python}
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
if(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
|
||||
#Disabled for now due to RTC bug IDF-4801
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT CONFIG_ULP_COPROC_TYPE_FSM AND NOT CONFIG_ULP_COPROC_TYPE_RISCV)
|
||||
# Nothing to test if no co-processor enabled
|
||||
return()
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
#pragma once
|
||||
|
||||
#warning Contents of ulp_riscv/ulp_riscv.h have been deprecated. Please include the header which contains the actual definitions you are trying to use, e.g. "ulp_riscv_register_ops.h".
|
||||
#include "../ulp_riscv_register_ops.h"
|
||||
#include "../../ulp_core/include/ulp_riscv_register_ops.h"
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#warning "ulp_riscv_gpio.h has been moved one level up. Please include the file without the ulp_riscv prefix."
|
||||
#include "../ulp_riscv_gpio.h"
|
||||
#warning "ulp_riscv_gpio.h has been moved. Please include the file without the ulp_riscv prefix."
|
||||
#include "../../ulp_core/include/ulp_riscv_gpio.h"
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#warning ulp_riscv_register_ops.h has been moved one level up. Please include the file without the ulp_riscv prefix.
|
||||
#include "../ulp_riscv_register_ops.h"
|
||||
#warning ulp_riscv_register_ops.h has been moved. Please include the file without the ulp_riscv prefix.
|
||||
#include "../../ulp_core/include/ulp_riscv_register_ops.h"
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#warning ulp_riscv_utils.h has been moved one level up. Please include the file without the ulp_riscv prefix.
|
||||
#include "../ulp_riscv_utils.h"
|
||||
#warning ulp_riscv_utils.h has been moved. Please include the file without the ulp_riscv prefix.
|
||||
#include "../../ulp_core/include/ulp_riscv_utils.h"
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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_bits_width_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);
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/adc_ll.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Start an ADC conversion and get the converted value.
|
||||
*
|
||||
* @note Will block until the conversion is completed
|
||||
*
|
||||
* @note ADC should be initilized for ULP by main CPU by calling ulp_riscv_adc_init()
|
||||
* before calling this.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param channel ADC channel number.
|
||||
*
|
||||
* @return Converted value, -1 if conversion failed
|
||||
*/
|
||||
int32_t ulp_riscv_adc_read_channel(adc_unit_t adc_n, int channel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,3 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
.section .text.vectors
|
||||
.global irq_vector
|
||||
.global reset_vector
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "ulp_riscv_adc.h"
|
||||
#include "hal/adc_ll.h"
|
||||
|
||||
int32_t ulp_riscv_adc_read_channel(adc_unit_t adc_n, int channel)
|
||||
{
|
||||
uint32_t event = (adc_n == ADC_UNIT_1) ? ADC_LL_EVENT_ADC1_ONESHOT_DONE : ADC_LL_EVENT_ADC2_ONESHOT_DONE;
|
||||
adc_oneshot_ll_clear_event(event);
|
||||
adc_oneshot_ll_disable_all_unit();
|
||||
adc_oneshot_ll_enable(adc_n);
|
||||
adc_oneshot_ll_set_channel(adc_n, channel);
|
||||
|
||||
adc_oneshot_ll_start(adc_n);
|
||||
while (adc_oneshot_ll_get_event(event) != true) {
|
||||
;
|
||||
}
|
||||
int32_t out_raw = adc_oneshot_ll_get_raw_result(adc_n);
|
||||
if (adc_oneshot_ll_raw_check_valid(adc_n, out_raw) == false) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//HW workaround: when enabling periph clock, this should be false
|
||||
adc_oneshot_ll_disable_all_unit();
|
||||
|
||||
return out_raw;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ulp_riscv_adc.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/adc.h"
|
||||
#include "hal/adc_hal_common.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
|
||||
|
||||
/* Will be refactored when ADC NG is merged, TODO IDF-5513 */
|
||||
extern esp_err_t adc1_rtc_mode_acquire(void);
|
||||
extern uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan);
|
||||
|
||||
static const char *TAG = "ulp_riscv_adc";
|
||||
|
||||
esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_GOTO_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, err, TAG, "cfg == NULL");
|
||||
ESP_GOTO_ON_FALSE(cfg->adc_n == ADC_UNIT_1, ESP_ERR_INVALID_ARG, err, TAG, "Only ADC_UNIT_1 is supported for now");
|
||||
|
||||
adc1_config_channel_atten(cfg->channel, cfg->atten);
|
||||
adc1_config_width(cfg->width);
|
||||
|
||||
//Calibrate the ADC
|
||||
uint32_t cal_val = get_calibration_offset(cfg->adc_n, cfg->channel);
|
||||
adc_hal_set_calibration_param(cfg->adc_n, cal_val);
|
||||
|
||||
adc1_rtc_mode_acquire();
|
||||
|
||||
esp_sleep_enable_adc_tsens_monitor(true);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(ulp-riscv-adc-example)
|
|
@ -0,0 +1,32 @@
|
|||
| Supported Targets | ESP32-S3 |
|
||||
| ----------------- | -------- |
|
||||
|
||||
# ULP-RISC-V ADC Example
|
||||
|
||||
This example demonstrates how to use the ULP-RISC-V coprocessor to poll the ADC in deep sleep.
|
||||
|
||||
The ULP program periodically measures the input voltage on EXAMPLE_ADC_CHANNEL (by default ADC1 channel 0, GPIO1 on both ESP32-S2 and ESP32-S3). The voltage is compared to an upper threshold. If the voltage is higher than the threshold, the ULP wakes up the system.
|
||||
|
||||
By default, the threshold is set to 1.75V, approximately.
|
||||
|
||||
In this example, you need to connect a voltage source (e.g. a DC power supply) to the GPIO pin corresponding to the ADC channel specified in `ulp/example_config.h` (see the macros defined on the top of the header file). Feel free to modify the channel setting.
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with a SOC which has a RISC-V ULP coprocessor (e.g., ESP32-S2 Saola)
|
||||
* A USB cable for power supply and programming
|
||||
|
||||
## Example output
|
||||
|
||||
Below is the output from this example.
|
||||
|
||||
```
|
||||
Not a ULP-RISC-V wakeup (cause = 0), initializing it!
|
||||
Entering in deep sleep
|
||||
|
||||
ULP-RISC-V woke up the main CPU
|
||||
Threshold: high = 2000
|
||||
Value = 4095 was above threshold
|
||||
Entering in deep sleep
|
||||
```
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
idf_component_register(SRCS "ulp_riscv_adc_example_main.c"
|
||||
INCLUDE_DIRS ""
|
||||
REQUIRES soc ulp esp_adc_cal)
|
||||
|
||||
|
||||
#
|
||||
# ULP support additions to component CMakeLists.txt.
|
||||
#
|
||||
# 1. The ULP app name must be unique (if multiple components use ULP).
|
||||
set(ulp_app_name ulp_${COMPONENT_NAME})
|
||||
#
|
||||
# 2. Specify all C and Assembly source files.
|
||||
# Files should be placed into a separate directory (in this case, ulp/),
|
||||
# which should not be added to COMPONENT_SRCS.
|
||||
set(ulp_riscv_sources "ulp/main.c")
|
||||
|
||||
#
|
||||
# 3. List all the component source files which include automatically
|
||||
# generated ULP export file, ${ulp_app_name}.h:
|
||||
set(ulp_exp_dep_srcs "ulp_riscv_adc_example_main.c")
|
||||
|
||||
#
|
||||
# 4. Call function to build ULP binary and embed in project using the argument
|
||||
# values above.
|
||||
ulp_embed_binary(${ulp_app_name} "${ulp_riscv_sources}" "${ulp_exp_dep_srcs}")
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#define EXAMPLE_ADC_CHANNEL ADC_CHANNEL_0
|
||||
#define EXAMPLE_ADC_UNIT ADC_UNIT_1
|
||||
#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_11
|
||||
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_12
|
||||
|
||||
/* Set high threshold, approx. 1.75V*/
|
||||
#define EXAMPLE_ADC_TRESHOLD 2000
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/* ULP-RISC-V example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
This code runs on ULP-RISC-V coprocessor
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ulp_riscv_utils.h"
|
||||
#include "ulp_riscv_adc_ulp_core.h"
|
||||
|
||||
#include "example_config.h"
|
||||
|
||||
uint32_t adc_threshold = EXAMPLE_ADC_TRESHOLD;
|
||||
int32_t wakeup_result;
|
||||
|
||||
int main (void)
|
||||
{
|
||||
int32_t last_result = ulp_riscv_adc_read_channel(EXAMPLE_ADC_UNIT, EXAMPLE_ADC_CHANNEL);
|
||||
|
||||
if (last_result > adc_threshold) {
|
||||
wakeup_result = last_result;
|
||||
ulp_riscv_wakeup_main_processor();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/* ULP riscv example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_sleep.h"
|
||||
#include "ulp_riscv.h"
|
||||
#include "ulp_riscv_adc.h"
|
||||
#include "ulp_main.h"
|
||||
#include "ulp/example_config.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");
|
||||
|
||||
static void init_ulp_program(void);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
|
||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||
|
||||
/* not a wakeup from ULP, load the firmware */
|
||||
if ((cause != ESP_SLEEP_WAKEUP_ULP) && (cause != ESP_SLEEP_WAKEUP_TIMER)) {
|
||||
printf("Not a ULP-RISC-V wakeup (cause = %d), initializing it! \n", cause);
|
||||
init_ulp_program();
|
||||
}
|
||||
|
||||
/* ULP Risc-V read and detected a temperature above the limit */
|
||||
if (cause == ESP_SLEEP_WAKEUP_ULP) {
|
||||
printf("ULP-RISC-V woke up the main CPU\n");
|
||||
printf("Threshold: high = %d\n", ulp_adc_threshold);
|
||||
printf("Value = %d was above threshold\n", ulp_wakeup_result);
|
||||
}
|
||||
|
||||
/* Go back to sleep, only the ULP Risc-V will run */
|
||||
printf("Entering in deep sleep\n\n");
|
||||
|
||||
/* 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);
|
||||
|
||||
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup());
|
||||
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(ulp_riscv_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);
|
||||
|
||||
/* The first argument is the period index, which is not used by the ULP-RISC-V timer
|
||||
* The second argument is the period in microseconds, which gives a wakeup time period of: 20ms
|
||||
*/
|
||||
ulp_set_wakeup_period(0, 20000);
|
||||
|
||||
/* Start the program */
|
||||
err = ulp_riscv_run();
|
||||
ESP_ERROR_CHECK(err);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
# Enable ULP
|
||||
CONFIG_ULP_COPROC_ENABLED=y
|
||||
CONFIG_ULP_COPROC_RISCV=y
|
||||
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
||||
# Set log level to Warning to produce clean output
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
|
||||
CONFIG_LOG_DEFAULT_LEVEL=2
|
Ładowanie…
Reference in New Issue