From 1792aba1dcc5ae7cf8aead79663d244787a2bbc2 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 26 Sep 2024 16:18:30 +0800 Subject: [PATCH 1/4] feat(vad): lp vad driver and wakeup feature --- components/esp_driver_i2s/CMakeLists.txt | 4 + .../include/driver/lp_i2s_vad.h | 153 ++++++++++++++++++ .../include/esp_private/lp_i2s_private.h | 27 ++++ components/esp_driver_i2s/lp_i2s.c | 13 ++ components/esp_driver_i2s/lp_i2s_vad.c | 112 +++++++++++++ .../hal/esp32p4/include/hal/lp_core_ll.h | 2 +- .../hal/esp32p4/include/hal/lp_i2s_ll.h | 106 +++++++++++- .../esp32p4/include/soc/Kconfig.soc_caps.in | 12 ++ components/soc/esp32p4/include/soc/soc_caps.h | 5 + components/ulp/CMakeLists.txt | 4 + components/ulp/cmake/IDFULPProject.cmake | 1 + components/ulp/lp_core/include/ulp_lp_core.h | 1 + components/ulp/lp_core/lp_core.c | 5 +- .../ulp/lp_core/lp_core/lp_core_utils.c | 11 ++ .../include/ulp_lp_core_lp_vad_shared.h | 121 ++++++++++++++ .../shared/ulp_lp_core_lp_vad_shared.c | 65 ++++++++ 16 files changed, 635 insertions(+), 7 deletions(-) create mode 100644 components/esp_driver_i2s/include/driver/lp_i2s_vad.h create mode 100644 components/esp_driver_i2s/include/esp_private/lp_i2s_private.h create mode 100644 components/esp_driver_i2s/lp_i2s_vad.c create mode 100644 components/ulp/lp_core/shared/include/ulp_lp_core_lp_vad_shared.h create mode 100644 components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c diff --git a/components/esp_driver_i2s/CMakeLists.txt b/components/esp_driver_i2s/CMakeLists.txt index cc39943ae6..2498fa6126 100644 --- a/components/esp_driver_i2s/CMakeLists.txt +++ b/components/esp_driver_i2s/CMakeLists.txt @@ -30,6 +30,10 @@ if(CONFIG_SOC_LP_I2S_SUPPORTED) list(APPEND srcs "lp_i2s.c" "lp_i2s_std.c" "lp_i2s_pdm.c") endif() +if(CONFIG_SOC_LP_I2S_SUPPORT_VAD) + list(APPEND srcs "lp_i2s_vad.c") +endif() + idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${include} PRIV_REQUIRES esp_driver_gpio esp_pm esp_mm diff --git a/components/esp_driver_i2s/include/driver/lp_i2s_vad.h b/components/esp_driver_i2s/include/driver/lp_i2s_vad.h new file mode 100644 index 0000000000..ce52370cde --- /dev/null +++ b/components/esp_driver_i2s/include/driver/lp_i2s_vad.h @@ -0,0 +1,153 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/soc_caps.h" +#include "esp_err.h" +#include "driver/i2s_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief State Machine + ┌──────────────────────────────────┐ + │ │ + ┌─────────────┤ speak-activity-listening-state │ ◄───────────────┐ + │ │ │ │ + │ └──────────────────────────────────┘ │ + │ ▲ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ +detected speak activity │ │ detected speak activity │ detected speak activity + >= │ │ >= │ >= +'speak_activity_thresh' │ │ 'min_speak_activity_thresh' │ 'max_speak_activity_thresh' + │ │ │ + │ │ && │ + │ │ │ + │ │ detected non-speak activity │ + │ │ < │ + │ │ 'non_speak_activity_thresh' │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ ┌───────────┴─────────────────────┐ │ + │ │ │ │ + └───────────► │ speak-activity-detected-state ├─────────────────┘ + │ │ + └─┬───────────────────────────────┘ + │ + │ ▲ + │ │ + │ │ + │ │ detected speak activity + │ │ >= + │ │ 'min_speak_activity_thresh' + │ │ + │ │ && + │ │ + │ │ detected non-speak activity + │ │ < + └─────────────────────┘ 'non_speak_activity_thresh' +*/ + +/** + * @brief LP VAD peripheral + */ +typedef uint32_t lp_vad_t; + +/** + * @brief Type of VAD unit handle + */ +typedef struct vad_unit_ctx_t *vad_unit_handle_t; + +/** + * @brief LP VAD configurations + */ +typedef struct { + int init_frame_num; /**< Number of init frames that are used for VAD to denoise, this helps the VAD to decrease the accidental trigger ratio. + Note too big values may lead to voice activity miss */ + int min_energy_thresh; ///< Min energy threshold. + bool skip_band_energy_thresh; ///< Skip band energy threshold or not + + int speak_activity_thresh; /**< When in speak-activity-listening-state, if number of the detected speak activity is higher than this value, VAD runs into speak-activity-detected-state */ + + int non_speak_activity_thresh; /**< When in speak-activity-detected-state, if the number of the detected speak activity is higher than this value, but lower than `max_speak_activity_thresh`: + - if the number of the detected non-speak activity is higher than this value, VAD runs into speak-activity-listening-state + - if the number of the detected non-speak activity is lower than this value, VAD keeps in speak-activity-detected-state */ + + int min_speak_activity_thresh; /**< When in speak-activity-detected-state, if the number of the detected speak activity is higher than this value, but lower than `max_speak_activity_thresh`, + then the VAD state machine will depends on the value of `non_speak_activity_thresh` */ + + int max_speak_activity_thresh; /**< When in speak-activity-detected-state, if the number of the detected speak activity is higher than this value, VAD runs into speak-activity-listening-state */ +} lp_vad_config_t; + +typedef struct { + lp_i2s_chan_handle_t lp_i2s_chan; ///< LP I2S channel handle + lp_vad_config_t vad_config; ///< LP VAD config +} lp_vad_init_config_t; + +/** + * @brief New LP VAD unit + * @param[in] vad_id VAD id + * @param[in] init_config Initial configurations + * @param[out] ret_unit Unit handle + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_i2s_vad_new_unit(lp_vad_t vad_id, const lp_vad_init_config_t *init_config, vad_unit_handle_t *ret_unit); + +/** + * @brief Enable LP VAD + * + * @param[in] unit VAD handle + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_i2s_vad_enable(vad_unit_handle_t unit); + +/** + * @brief Disable LP VAD + * + * @param[in] unit VAD handle + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_i2s_vad_disable(vad_unit_handle_t unit); + +/** + * @brief Delete LP VAD unit + * @param[in] unit VAD handle + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_i2s_vad_del_unit(vad_unit_handle_t unit); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_i2s/include/esp_private/lp_i2s_private.h b/components/esp_driver_i2s/include/esp_private/lp_i2s_private.h new file mode 100644 index 0000000000..2785ca0263 --- /dev/null +++ b/components/esp_driver_i2s/include/esp_private/lp_i2s_private.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "hal/lp_i2s_hal.h" +#include "driver/i2s_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get LP I2S soc handle + * + * @param[in] chan LP I2S channel handle + * + * @return LP I2S soc handle + */ +lp_i2s_soc_handle_t lp_i2s_get_soc_handle(lp_i2s_chan_handle_t chan); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_i2s/lp_i2s.c b/components/esp_driver_i2s/lp_i2s.c index 7084fc8947..0d5e43dd8d 100644 --- a/components/esp_driver_i2s/lp_i2s.c +++ b/components/esp_driver_i2s/lp_i2s.c @@ -25,6 +25,7 @@ #include "driver/lp_i2s.h" #include "esp_private/periph_ctrl.h" #include "esp_private/i2s_platform.h" +#include "esp_private/lp_i2s_private.h" #include "i2s_private.h" #include "soc/i2s_periph.h" @@ -329,3 +330,15 @@ static void IRAM_ATTR s_i2s_default_isr(void *arg) portYIELD_FROM_ISR(); } } + +/*--------------------------------------------------------------- + HELPERS +---------------------------------------------------------------*/ +lp_i2s_soc_handle_t lp_i2s_get_soc_handle(lp_i2s_chan_handle_t chan) +{ + if (!chan) { + return NULL; + } + + return chan->ctlr->hal.dev; +} diff --git a/components/esp_driver_i2s/lp_i2s_vad.c b/components/esp_driver_i2s/lp_i2s_vad.c new file mode 100644 index 0000000000..f1cc63559e --- /dev/null +++ b/components/esp_driver_i2s/lp_i2s_vad.c @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "soc/soc_caps.h" +#include "stdatomic.h" +#if SOC_LP_VAD_SUPPORTED +#include "esp_check.h" +#include "esp_err.h" +#include "driver/lp_i2s_vad.h" +#include "esp_heap_caps.h" +#include "hal/lp_i2s_ll.h" +#include "hal/lp_i2s_hal.h" +#include "esp_private/lp_i2s_private.h" + +#define LP_VAD_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) + +static const char *LP_VAD_TAG = "LP_VAD"; + +typedef enum { + VAD_FSM_INIT, + VAD_FSM_ENABLE, +} vad_fsm_t; + +typedef struct vad_unit_ctx_t { + lp_i2s_soc_handle_t hw; + lp_vad_t vad_id; + vad_fsm_t fsm; +} vad_unit_ctx_t; + +static atomic_bool s_vad_id_claimed[SOC_ADC_PERIPH_NUM] = {ATOMIC_VAR_INIT(false)}; + +static bool s_vad_claim(lp_vad_t vad_id) +{ + bool false_var = false; + return atomic_compare_exchange_strong(&s_vad_id_claimed[vad_id], &false_var, true); +} + +static bool s_vad_free(lp_vad_t vad_id) +{ + bool true_var = true; + return atomic_compare_exchange_strong(&s_vad_id_claimed[vad_id], &true_var, false); +} + +esp_err_t lp_i2s_vad_new_unit(lp_vad_t vad_id, const lp_vad_init_config_t *init_config, vad_unit_handle_t *ret_unit) +{ + esp_err_t ret = ESP_OK; + ESP_RETURN_ON_FALSE(init_config, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg"); + ESP_RETURN_ON_FALSE(init_config->lp_i2s_chan, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "LP I2S not initialised"); + ESP_RETURN_ON_FALSE(init_config->vad_config.init_frame_num >= LP_VAD_LL_INIT_FRAME_MIN && init_config->vad_config.init_frame_num <= LP_VAD_LL_INIT_FRAME_MAX, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid init frame num"); + + bool success_claim = s_vad_claim(vad_id); + ESP_RETURN_ON_FALSE(success_claim, ESP_ERR_NOT_FOUND, LP_VAD_TAG, "vad%"PRId32" is already in use", vad_id); + + vad_unit_ctx_t *unit = heap_caps_calloc(1, sizeof(vad_unit_ctx_t), LP_VAD_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, LP_VAD_TAG, "no mem for unit"); + + unit->hw = lp_i2s_get_soc_handle(init_config->lp_i2s_chan); + ESP_LOGD(LP_VAD_TAG, "unit->hw: %p", unit->hw); + lp_vad_ll_set_init_frame_num(unit->hw, init_config->vad_config.init_frame_num); + lp_vad_ll_set_init_min_energy(unit->hw, init_config->vad_config.min_energy_thresh); + lp_vad_ll_set_speak_activity_thresh(unit->hw, init_config->vad_config.speak_activity_thresh); + lp_vad_ll_set_non_speak_activity_thresh(unit->hw, init_config->vad_config.non_speak_activity_thresh); + lp_vad_ll_set_min_speak_activity_thresh(unit->hw, init_config->vad_config.min_speak_activity_thresh); + lp_vad_ll_set_max_speak_activity_thresh(unit->hw, init_config->vad_config.max_speak_activity_thresh); + lp_vad_ll_skip_band_energy(unit->hw, init_config->vad_config.skip_band_energy_thresh); + unit->fsm = VAD_FSM_INIT; + *ret_unit = unit; + + return ESP_OK; +err: + bool success_free = s_vad_free(vad_id); + assert(success_free); + + return ret; +} + +esp_err_t lp_i2s_vad_enable(vad_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg"); + ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_INIT, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is enabled already"); + + lp_vad_ll_enable(unit->hw, true); + unit->fsm = VAD_FSM_ENABLE; + return ESP_OK; +} + +esp_err_t lp_i2s_vad_disable(vad_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg"); + ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_ENABLE, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is not enabled yet"); + + lp_vad_ll_enable(unit->hw, false); + unit->fsm = VAD_FSM_INIT; + return ESP_OK; +} + +esp_err_t lp_i2s_vad_del_unit(vad_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg"); + ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_INIT, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is still in enabled state"); + + bool success_free = s_vad_free(unit->vad_id); + ESP_RETURN_ON_FALSE(success_free, ESP_ERR_NOT_FOUND, LP_VAD_TAG, "vad%"PRId32" isn't in use", unit->vad_id); + + free(unit); + return ESP_OK; +} +#endif /* SOC_LP_VAD_SUPPORTED */ diff --git a/components/hal/esp32p4/include/hal/lp_core_ll.h b/components/hal/esp32p4/include/hal/lp_core_ll.h index 27a9a0997f..eb2c57be31 100644 --- a/components/hal/esp32p4/include/hal/lp_core_ll.h +++ b/components/hal/esp32p4/include/hal/lp_core_ll.h @@ -28,7 +28,7 @@ extern "C" { #define LP_CORE_LL_WAKEUP_SOURCE_LP_BOD BIT(14) #define LP_CORE_LL_WAKEUP_SOURCE_ETM BIT(17) #define LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER_1 BIT(18) -#define LP_CORE_LL_WAKEUP_SOURCE_LP_I2S BIT(19) +#define LP_CORE_LL_WAKEUP_SOURCE_LP_VAD BIT(19) #define LP_CORE_LL_WAKEUP_SOURCE_HP_CPU BIT(22) /* Use lp timer 1 as the normal wakeup timer, timer 0 is used by deep sleep */ diff --git a/components/hal/esp32p4/include/hal/lp_i2s_ll.h b/components/hal/esp32p4/include/hal/lp_i2s_ll.h index c9f0d5611b..23e81cd2a5 100644 --- a/components/hal/esp32p4/include/hal/lp_i2s_ll.h +++ b/components/hal/esp32p4/include/hal/lp_i2s_ll.h @@ -32,6 +32,8 @@ extern "C" { #define LP_I2S_LL_EVENT_RX_DONE_INT (1<<0) #define LP_I2S_LL_EVENT_RX_HUNG_INT_INT (1<<1) #define LP_I2S_LL_EVENT_RX_FIFOMEM_UDF_INT (1<<2) +#define LP_I2S_LL_EVENT_VAD_DONE_INT (1<<3) +#define LP_I2S_LL_EVENT_VAD_RESET_DONE_INT (1<<4) #define LP_I2S_LL_EVENT_RX_MEM_THRESHOLD_INT (1<<5) #define LP_I2S_LL_TDM_CH_MASK (0x03UL) @@ -709,9 +711,9 @@ static inline uint32_t lp_i2s_ll_get_intr_status_reg_addr(lp_i2s_dev_t *hw) /** * @brief Enable LP I2S RX channel interrupt * - * @param hw LP I2S hardware instance - * @param mask mask - * @param enable enable or disable + * @param[in] hw LP I2S hardware instance + * @param[in] mask mask + * @param[in] enable enable or disable */ static inline void lp_i2s_ll_rx_enable_interrupt(lp_i2s_dev_t *hw, uint32_t mask, bool enable) { @@ -727,8 +729,8 @@ static inline void lp_i2s_ll_rx_enable_interrupt(lp_i2s_dev_t *hw, uint32_t mask /** * @brief Clear LP I2S RX channel interrupt * - * @param hw LP I2S hardware instance - * @param mask mask + * @param[in] hw LP I2S hardware instance + * @param[in] mask mask */ __attribute__((always_inline)) static inline void lp_i2s_ll_rx_clear_interrupt_status(lp_i2s_dev_t *hw, uint32_t mask) @@ -736,6 +738,100 @@ static inline void lp_i2s_ll_rx_clear_interrupt_status(lp_i2s_dev_t *hw, uint32_ hw->int_clr.val = mask; } +/*--------------------------------------------------------------- + VAD +---------------------------------------------------------------*/ +#define LP_VAD_LL_INIT_FRAME_MIN 100 +#define LP_VAD_LL_INIT_FRAME_MAX 200 + +/** + * @brief Set VAD init frame number + * + * @param[in] hw LP I2S hardware instance + * @param[in] frame_num Frame number + */ +static inline void lp_vad_ll_set_init_frame_num(lp_i2s_dev_t *hw, int frame_num) +{ + hw->vad_param0.param_init_frame_num = frame_num; +} + +/** + * @brief Set VAD min energy + * + * @param[in] hw LP I2S hardware instance + * @param[in] min_energy Min energy + */ +static inline void lp_vad_ll_set_init_min_energy(lp_i2s_dev_t *hw, int min_energy) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->vad_param0, param_min_energy, min_energy); +} + +/** + * @brief Set VAD speak activity thresh + * + * @param[in] hw LP I2S hardware instance + * @param[in] thresh Threshold + */ +static inline void lp_vad_ll_set_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) +{ + hw->vad_param1.param_hangover_speech = thresh; +} + +/** + * @brief Set VAD non speak activity thresh + * + * @param[in] hw LP I2S hardware instance + * @param[in] thresh Threshold + */ +static inline void lp_vad_ll_set_non_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) +{ + hw->vad_param1.param_hangover_silent = thresh; +} + +/** + * @brief Set VAD min speak activity thresh + * + * @param[in] hw LP I2S hardware instance + * @param[in] thresh Threshold + */ +static inline void lp_vad_ll_set_min_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) +{ + hw->vad_param1.param_min_speech_count = thresh; +} + +/** + * @brief Set VAD max speak activity thresh + * + * @param[in] hw LP I2S hardware instance + * @param[in] thresh Threshold + */ +static inline void lp_vad_ll_set_max_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) +{ + hw->vad_param1.param_max_speech_count = thresh; +} + +/** + * @brief Skip band energy check + * + * @param[in] hw LP I2S hardware instance + * @param[in] skip 1: skip; 0: not skip + */ +static inline void lp_vad_ll_skip_band_energy(lp_i2s_dev_t *hw, bool skip) +{ + hw->vad_param1.param_skip_band_energy = skip; +} + +/** + * @brief Enable LP I2S 24 fill + * + * @param[in] hw LP I2S hardware instance + * @param[in] en enable or disable + */ +static inline void lp_vad_ll_enable(lp_i2s_dev_t *hw, bool en) +{ + hw->vad_conf.vad_en = en; +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index f8319e722e..eac76a74a3 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -263,6 +263,10 @@ config SOC_LP_ADC_SUPPORTED bool default y +config SOC_LP_VAD_SUPPORTED + bool + default y + config SOC_SPIRAM_SUPPORTED bool default y @@ -1763,6 +1767,10 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y +config SOC_LP_I2S_SUPPORT_VAD + bool + default y + config SOC_COEX_HW_PTI bool default y @@ -1962,3 +1970,7 @@ config SOC_LP_CORE_SUPPORT_ETM config SOC_LP_CORE_SUPPORT_LP_ADC bool default y + +config SOC_LP_CORE_SUPPORT_LP_VAD + bool + default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index a8a90bda86..16d2aa7643 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -83,6 +83,7 @@ #define SOC_LP_I2S_SUPPORTED 1 #define SOC_LP_SPI_SUPPORTED 1 #define SOC_LP_ADC_SUPPORTED 1 +#define SOC_LP_VAD_SUPPORTED 1 #define SOC_SPIRAM_SUPPORTED 1 #define SOC_PSRAM_DMA_CAPABLE 1 #define SOC_SDMMC_HOST_SUPPORTED 1 @@ -662,6 +663,9 @@ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) +/*-------------------------- LP_VAD CAPS -------------------------------------*/ +#define SOC_LP_I2S_SUPPORT_VAD (1) + // TODO: IDF-5679 (Copy from esp32c3, need check) /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) @@ -745,3 +749,4 @@ /*------------------------------------- ULP CAPS -------------------------------------*/ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ #define SOC_LP_CORE_SUPPORT_LP_ADC (1) /*!< LP ADC can be accessed from the LP-Core */ +#define SOC_LP_CORE_SUPPORT_LP_VAD (1) /*!< LP VAD can be accessed from the LP-Core */ diff --git a/components/ulp/CMakeLists.txt b/components/ulp/CMakeLists.txt index 058d05922b..dbe990e652 100644 --- a/components/ulp/CMakeLists.txt +++ b/components/ulp/CMakeLists.txt @@ -78,6 +78,10 @@ if(CONFIG_ULP_COPROC_TYPE_LP_CORE) if(CONFIG_SOC_LP_ADC_SUPPORTED) list(APPEND srcs "lp_core/shared/ulp_lp_core_lp_adc_shared.c") endif() + + if(CONFIG_SOC_LP_VAD_SUPPORTED) + list(APPEND srcs "lp_core/shared/ulp_lp_core_lp_vad_shared.c") + endif() endif() idf_component_register(SRCS ${srcs} diff --git a/components/ulp/cmake/IDFULPProject.cmake b/components/ulp/cmake/IDFULPProject.cmake index 04da71b00c..fd90cfd87f 100644 --- a/components/ulp/cmake/IDFULPProject.cmake +++ b/components/ulp/cmake/IDFULPProject.cmake @@ -126,6 +126,7 @@ function(ulp_apply_default_sources ulp_app_name) "${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_spi.c" "${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_ubsan.c" "${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_adc_shared.c" + "${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c" "${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_critical_section_shared.c") set(target_folder ${IDF_TARGET}) diff --git a/components/ulp/lp_core/include/ulp_lp_core.h b/components/ulp/lp_core/include/ulp_lp_core.h index d737d638ac..6a0373aefa 100644 --- a/components/ulp/lp_core/include/ulp_lp_core.h +++ b/components/ulp/lp_core/include/ulp_lp_core.h @@ -22,6 +22,7 @@ extern "C" { #define ULP_LP_CORE_WAKEUP_SOURCE_LP_IO BIT(2) // Enable wake-up by LP IO interrupt #define ULP_LP_CORE_WAKEUP_SOURCE_ETM BIT(3) // Enable wake-up by ETM event #define ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER BIT(4) // Enable wake-up by LP timer +#define ULP_LP_CORE_WAKEUP_SOURCE_LP_VAD BIT(5) // Enable wake-up by LP VAD /** * @brief ULP LP core init parameters diff --git a/components/ulp/lp_core/lp_core.c b/components/ulp/lp_core/lp_core.c index aedcf0e78e..cfc8fc81cc 100644 --- a/components/ulp/lp_core/lp_core.c +++ b/components/ulp/lp_core/lp_core.c @@ -35,7 +35,7 @@ extern uint32_t _rtc_ulp_memory_start; const static char* TAG = "ulp-lp-core"; -#define WAKEUP_SOURCE_MAX_NUMBER 5 +#define WAKEUP_SOURCE_MAX_NUMBER 6 #define RESET_HANDLER_ADDR (intptr_t)(&_rtc_ulp_memory_start + 0x80 / 4) // Placed after the 0x80 byte long vector table @@ -46,6 +46,9 @@ static uint32_t wakeup_src_sw_to_hw_flag_lookup[WAKEUP_SOURCE_MAX_NUMBER] = { LP_CORE_LL_WAKEUP_SOURCE_LP_IO, LP_CORE_LL_WAKEUP_SOURCE_ETM, LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER, +#if SOC_LP_VAD_SUPPORTED + LP_CORE_LL_WAKEUP_SOURCE_LP_VAD, +#endif }; /* Convert the wake-up sources defined in ulp_lp_core.h to the actual HW wake-up source values */ diff --git a/components/ulp/lp_core/lp_core/lp_core_utils.c b/components/ulp/lp_core/lp_core/lp_core_utils.c index 8b358741fb..d3e8664907 100644 --- a/components/ulp/lp_core/lp_core/lp_core_utils.c +++ b/components/ulp/lp_core/lp_core/lp_core_utils.c @@ -14,6 +14,10 @@ #include "hal/pmu_ll.h" #include "hal/uart_ll.h" #include "hal/rtc_io_ll.h" +#if SOC_LP_I2S_SUPPORT_VAD +//For VAD +#include "hal/lp_i2s_ll.h" +#endif #if SOC_LP_TIMER_SUPPORTED #include "hal/lp_timer_ll.h" @@ -56,6 +60,13 @@ void ulp_lp_core_update_wakeup_cause(void) rtcio_ll_clear_interrupt_status(); } +#if SOC_LP_VAD_SUPPORTED + if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_LP_VAD)) { + lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_LP_VAD; + lp_i2s_ll_rx_clear_interrupt_status(&LP_I2S, LP_I2S_LL_EVENT_VAD_DONE_INT); + } +#endif + #if SOC_ETM_SUPPORTED if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_ETM) \ && lp_core_ll_get_etm_wakeup_flag()) { diff --git a/components/ulp/lp_core/shared/include/ulp_lp_core_lp_vad_shared.h b/components/ulp/lp_core/shared/include/ulp_lp_core_lp_vad_shared.h new file mode 100644 index 0000000000..8a37dee54d --- /dev/null +++ b/components/ulp/lp_core/shared/include/ulp_lp_core_lp_vad_shared.h @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/lp_i2s_vad.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LP VAD configurations + */ +typedef lp_vad_init_config_t lp_core_lp_vad_cfg_t; + +/** + * @brief State Machine + ┌──────────────────────────────────┐ + │ │ + ┌─────────────┤ speak-activity-listening-state │ ◄───────────────┐ + │ │ │ │ + │ └──────────────────────────────────┘ │ + │ ▲ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ +detected speak activity │ │ detected speak activity │ detected speak activity + >= │ │ >= │ >= +'speak_activity_thresh' │ │ 'min_speak_activity_thresh' │ 'max_speak_activity_thresh' + │ │ │ + │ │ && │ + │ │ │ + │ │ detected non-speak activity │ + │ │ < │ + │ │ 'non_speak_activity_thresh' │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ ┌───────────┴─────────────────────┐ │ + │ │ │ │ + └───────────► │ speak-activity-detected-state ├─────────────────┘ + │ │ + └─┬───────────────────────────────┘ + │ + │ ▲ + │ │ + │ │ + │ │ detected speak activity + │ │ >= + │ │ 'min_speak_activity_thresh' + │ │ + │ │ && + │ │ + │ │ detected non-speak activity + │ │ < + └─────────────────────┘ 'non_speak_activity_thresh' +*/ + +/** + * @brief LP VAD init + * + * @param[in] vad_id VAD ID + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_core_lp_vad_init(lp_vad_t vad_id, const lp_core_lp_vad_cfg_t *init_config); + +/** + * @brief Enable LP VAD + * + * @param[in] vad_id VAD ID + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_core_lp_vad_enable(lp_vad_t vad_id); + +/** + * @brief Disable LP VAD + * + * @param[in] vad_id VAD ID + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_core_lp_vad_disable(lp_vad_t vad_id); + +/** + * @brief Deinit LP VAD + * + * @param[in] vad_id VAD ID + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_core_lp_vad_deinit(lp_vad_t vad_id); + +#ifdef __cplusplus +} +#endif diff --git a/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c b/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c new file mode 100644 index 0000000000..db78e74633 --- /dev/null +++ b/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" +#if SOC_LP_VAD_SUPPORTED +#include "esp_check.h" +#include "esp_err.h" +#include "ulp_lp_core_lp_vad_shared.h" +#if SOC_LP_I2S_SUPPORT_VAD +//For VAD +#include "hal/lp_i2s_ll.h" +#include "hal/lp_i2s_hal.h" +#include "esp_private/lp_i2s_private.h" +#endif //SOC_LP_I2S_SUPPORT_VAD + +//make this available for multi vad id in future +vad_unit_handle_t s_vad_handle; + +esp_err_t lp_core_lp_vad_init(lp_vad_t vad_id, const lp_core_lp_vad_cfg_t *init_config) +{ +#if IS_ULP_COCPU + // Not supported + return ESP_ERR_NOT_SUPPORTED; +#else + esp_err_t ret = lp_i2s_vad_new_unit(vad_id, init_config, &s_vad_handle); + return ret; +#endif +} + +esp_err_t lp_core_lp_vad_enable(lp_vad_t vad_id) +{ +#if IS_ULP_COCPU + // Not supported + return ESP_ERR_NOT_SUPPORTED; +#else + esp_err_t ret = lp_i2s_vad_enable(s_vad_handle); + return ret; +#endif +} + +esp_err_t lp_core_lp_vad_disable(lp_vad_t vad_id) +{ +#if IS_ULP_COCPU + // Not supported + return ESP_ERR_NOT_SUPPORTED; +#else + esp_err_t ret = lp_i2s_vad_disable(s_vad_handle); + return ret; +#endif +} + +esp_err_t lp_core_lp_vad_deinit(lp_vad_t vad_id) +{ +#if IS_ULP_COCPU + // Not supported + return ESP_ERR_NOT_SUPPORTED; +#else + esp_err_t ret = lp_i2s_vad_del_unit(s_vad_handle); + return ret; +#endif +} +#endif /* SOC_LP_VAD_SUPPORTED */ From 60c005d1dc8db9d09c2d9b04b58ee82544955880 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 26 Sep 2024 16:20:30 +0800 Subject: [PATCH 2/4] test(vad): vad wakeup test --- .../lp_core_basic_tests/main/CMakeLists.txt | 15 +- .../main/Kconfig.projbuild | 9 + .../main/lp_core/test_main_vad.c | 18 ++ .../main/test_lp_core_vad.c | 154 ++++++++++++++++++ .../lp_core_basic_tests/main/test_vad_8k.pcm | Bin 0 -> 34272 bytes .../pytest_lp_core_basic.py | 13 ++ .../lp_core_basic_tests/sdkconfig.ci.default | 0 .../lp_core_basic_tests/sdkconfig.ci.lp_vad | 2 + 8 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 components/ulp/test_apps/lp_core/lp_core_basic_tests/main/Kconfig.projbuild create mode 100644 components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_vad.c create mode 100644 components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_vad.c create mode 100644 components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_vad_8k.pcm delete mode 100644 components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.default create mode 100644 components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt index 63d8f905d7..239b78cf33 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt @@ -20,6 +20,10 @@ if(CONFIG_SOC_LP_ADC_SUPPORTED) list(APPEND app_sources "test_lp_core_adc.c") endif() +if(CONFIG_SOC_LP_VAD_SUPPORTED) + list(APPEND app_sources "test_lp_core_vad.c") +endif() + set(lp_core_sources "lp_core/test_main.c") set(lp_core_sources_counter "lp_core/test_main_counter.c") @@ -46,10 +50,15 @@ if(CONFIG_SOC_LP_ADC_SUPPORTED) set(lp_core_sources_adc "lp_core/test_main_adc.c") endif() +if(CONFIG_SOC_LP_VAD_SUPPORTED) + set(lp_core_sources_vad "lp_core/test_main_vad.c") +endif() + idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "lp_core" REQUIRES ulp unity esp_timer test_utils - WHOLE_ARCHIVE) + WHOLE_ARCHIVE + EMBED_FILES "test_vad_8k.pcm") set(lp_core_exp_dep_srcs ${app_sources}) @@ -79,3 +88,7 @@ endif() if(CONFIG_SOC_LP_ADC_SUPPORTED) ulp_embed_binary(lp_core_test_app_adc "${lp_core_sources_adc}" "${lp_core_exp_dep_srcs}") endif() + +if(CONFIG_SOC_LP_VAD_SUPPORTED) + ulp_embed_binary(lp_core_test_app_vad "${lp_core_sources_vad}" "${lp_core_exp_dep_srcs}") +endif() diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/Kconfig.projbuild b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/Kconfig.projbuild new file mode 100644 index 0000000000..5783fc5daf --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "Test Configurations" + + config TEST_LP_CORE_VAD_ENABLE + bool "Enable LP VAD test" + default n + help + Enable this to trigger LP VAD test + +endmenu diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_vad.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_vad.c new file mode 100644 index 0000000000..5f6198fe37 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_vad.c @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +volatile bool vad_wakup; + +int main(void) +{ + vad_wakup = true; + + return 0; +} diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_vad.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_vad.c new file mode 100644 index 0000000000..16a3c059dd --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_vad.c @@ -0,0 +1,154 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "unity.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "driver/lp_i2s.h" +#include "driver/lp_i2s_std.h" +#include "driver/i2s_std.h" +#include "ulp_lp_core.h" +#include "ulp_lp_core_lp_vad_shared.h" +#include "lp_core_test_app_vad.h" + +#if CONFIG_TEST_LP_CORE_VAD_ENABLE + +#define TEST_I2S_FRAME_SIZE (128) // Frame numbers in every writing / reading +#define TEST_I2S_TRANS_SIZE (4096) // Trans size + +extern const uint8_t test_vad_pcm_start[] asm("_binary_test_vad_8k_pcm_start"); +extern const uint8_t test_vad_pcm_end[] asm("_binary_test_vad_8k_pcm_end"); +extern const uint8_t lp_core_main_vad_bin_start[] asm("_binary_lp_core_test_app_vad_bin_start"); +extern const uint8_t lp_core_main_vad_bin_end[] asm("_binary_lp_core_test_app_vad_bin_end"); +static const char *TAG = "TEST_VAD"; + +static void load_and_start_lp_core_firmware(ulp_lp_core_cfg_t* cfg, const uint8_t* firmware_start, const uint8_t* firmware_end) +{ + TEST_ASSERT(ulp_lp_core_load_binary(firmware_start, + (firmware_end - firmware_start)) == ESP_OK); + + TEST_ASSERT(ulp_lp_core_run(cfg) == ESP_OK); +} + +void test_lp_vad(lp_vad_t vad_id) +{ + esp_err_t ret = ESP_FAIL; + int pcm_size = test_vad_pcm_end - test_vad_pcm_start; + printf("pcm_size: %d\n", pcm_size); + + lp_i2s_chan_handle_t rx_handle = NULL; + lp_i2s_chan_config_t config = { + .id = 0, + .role = I2S_ROLE_SLAVE, + .threshold = 512, + }; + TEST_ESP_OK(lp_i2s_new_channel(&config, NULL, &rx_handle)); + + i2s_chan_handle_t tx_handle = NULL; + i2s_chan_config_t i2s_channel_config = { + .id = I2S_NUM_0, + .role = I2S_ROLE_MASTER, + .dma_desc_num = 4, + .dma_frame_num = TEST_I2S_FRAME_SIZE, + .auto_clear = false, + }; + TEST_ESP_OK(i2s_new_channel(&i2s_channel_config, &tx_handle, NULL)); + + lp_i2s_std_config_t lp_std_cfg = { + .pin_cfg = { + .bck = 4, + .ws = 5, + .din = 6, + }, + }; + lp_std_cfg.slot_cfg = (lp_i2s_std_slot_config_t)LP_I2S_STD_PCM_SHORT_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + TEST_ESP_OK(lp_i2s_channel_init_std_mode(rx_handle, &lp_std_cfg)); + + i2s_std_config_t i2s_std_config = { + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = GPIO_NUM_7, + .ws = GPIO_NUM_8, + .dout = GPIO_NUM_21, + .din = -1, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + i2s_std_config.clk_cfg = (i2s_std_clk_config_t)I2S_STD_CLK_DEFAULT_CONFIG(16000); + i2s_std_config.slot_cfg = (i2s_std_slot_config_t)I2S_STD_PCM_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &i2s_std_config)); + + // LP VAD Init + lp_vad_init_config_t init_config = { + .lp_i2s_chan = rx_handle, + .vad_config = { + .init_frame_num = 100, + .min_energy_thresh = 100, + .speak_activity_thresh = 10, + .non_speak_activity_thresh = 30, + .min_speak_activity_thresh = 3, + .max_speak_activity_thresh = 100, + }, + }; + TEST_ESP_OK(lp_core_lp_vad_init(0, &init_config)); + + /* Load ULP firmware and start the coprocessor */ + ulp_lp_core_cfg_t cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_VAD, + }; + load_and_start_lp_core_firmware(&cfg, lp_core_main_vad_bin_start, lp_core_main_vad_bin_end); + + uint8_t *txbuf = (uint8_t *)heap_caps_calloc(1, TEST_I2S_TRANS_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(txbuf); + + uint8_t *prebuf = (uint8_t *)heap_caps_calloc(1, TEST_I2S_TRANS_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(prebuf); + + memcpy(prebuf, test_vad_pcm_start, TEST_I2S_TRANS_SIZE); + memcpy(txbuf, test_vad_pcm_start, TEST_I2S_TRANS_SIZE); + + for (int i = 0; i < TEST_I2S_TRANS_SIZE; i++) { + ESP_LOGD(TAG, "prebuf[%d]: %d", i, prebuf[i]); + ESP_LOGD(TAG, "txbuf[%d]: %d", i, txbuf[i]); + } + + size_t bytes_written = 0; + TEST_ESP_OK(i2s_channel_preload_data(tx_handle, prebuf, TEST_I2S_TRANS_SIZE, &bytes_written)); + TEST_ESP_OK(lp_i2s_channel_enable(rx_handle)); + TEST_ESP_OK(lp_core_lp_vad_enable(0)); + TEST_ESP_OK(i2s_channel_enable(tx_handle)); + + ret = i2s_channel_write(tx_handle, txbuf, TEST_I2S_TRANS_SIZE, &bytes_written, 0); + if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) { + TEST_ESP_OK(ret); + } + ESP_LOGD(TAG, "bytes_written: %d", bytes_written); + + while (!ulp_vad_wakup) { + ; + } + + ESP_LOGI(TAG, "wakeup"); + + TEST_ESP_OK(lp_i2s_channel_disable(rx_handle)); + TEST_ESP_OK(lp_i2s_del_channel(rx_handle)); + TEST_ESP_OK(i2s_channel_disable(tx_handle)); + TEST_ESP_OK(i2s_del_channel(tx_handle)); + free(txbuf); + free(prebuf); +} + +TEST_CASE("LP VAD wakeup test", "[lp_core][lp_vad]") +{ + test_lp_vad(0); +} +#endif //CONFIG_TEST_LP_CORE_VAD_ENABLE diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_vad_8k.pcm b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_vad_8k.pcm new file mode 100644 index 0000000000000000000000000000000000000000..5b6c32a03731f5cee7ba8bfa178b38477ac7f5f4 GIT binary patch literal 34272 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 literal 0 HcmV?d00001 diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py index 53178dca4e..33e7b3c950 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py @@ -33,6 +33,19 @@ def test_lp_core_xtal(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.esp32p4 +@pytest.mark.lp_i2s +@pytest.mark.parametrize( + 'config', + [ + 'lp_vad', + ], + indirect=True, +) +def test_lp_vad(dut: Dut) -> None: + dut.run_all_single_board_cases(group='lp_vad') + + @pytest.mark.esp32c6 # TODO: Enable LP I2C test for esp32p4 (IDF-9407) @pytest.mark.generic_multi_device diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.default b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.default deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad new file mode 100644 index 0000000000..8397edb939 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad @@ -0,0 +1,2 @@ +CONFIG_TEST_LP_CORE_VAD_ENABLE=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y From 6db48cff2574dab3d0e65d6bf76f6d2526c0daaf Mon Sep 17 00:00:00 2001 From: Armando Date: Wed, 9 Oct 2024 11:26:57 +0800 Subject: [PATCH 3/4] feat(sleep): support vad wakeup hp core --- .../include/esp_private/esp_pmu.h | 8 +++++++ .../include/esp_private/esp_sleep_internal.h | 1 + components/esp_hw_support/include/esp_sleep.h | 11 ++++++++++ .../esp_hw_support/port/esp32p4/pmu_sleep.c | 5 +++++ components/esp_hw_support/sleep_modes.c | 21 ++++++++++++++++++- .../hal/esp32p4/include/hal/clk_gate_ll.h | 13 ++++++++++++ .../esp32p4/include/soc/Kconfig.soc_caps.in | 8 +++++++ components/soc/esp32p4/include/soc/soc_caps.h | 2 ++ 8 files changed, 68 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 5b48194607..6d347788a2 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -50,6 +50,7 @@ typedef enum { #define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17) #define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature #define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19) +#define RTC_SLEEP_LP_PERIPH_USE_XTAL BIT(20) #if SOC_PM_SUPPORT_EXT0_WAKEUP #define RTC_EXT0_TRIG_EN PMU_EXT0_WAKEUP_EN //!< EXT0 wakeup @@ -109,6 +110,12 @@ typedef enum { #define RTC_LP_CORE_TRIG_EN 0 #endif //SOC_LP_CORE_SUPPORTED +#if SOC_LP_VAD_SUPPORTED +#define RTC_LP_VAD_TRIG_EN PMU_LP_I2S_WAKEUP_EN //!< LP VAD wakeup +#else +#define RTC_LP_VAD_TRIG_EN 0 +#endif //SOC_LP_VAD_SUPPORTED + #define RTC_XTAL32K_DEAD_TRIG_EN 0 // TODO #define RTC_BROWNOUT_DET_TRIG_EN 0 // TODO @@ -127,6 +134,7 @@ typedef enum { RTC_TOUCH_TRIG_EN | \ RTC_XTAL32K_DEAD_TRIG_EN | \ RTC_USB_TRIG_EN | \ + RTC_LP_VAD_TRIG_EN | \ RTC_BROWNOUT_DET_TRIG_EN) diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index df9c2a79e2..7805b71495 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -38,6 +38,7 @@ typedef enum { ESP_SLEEP_ULTRA_LOW_MODE, //!< In ultra low mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. ESP_SLEEP_RTC_FAST_USE_XTAL_MODE, //!< The mode in which the crystal is used as the RTC_FAST clock source, need keep XTAL on in HP_SLEEP mode when ULP is working. ESP_SLEEP_DIG_USE_XTAL_MODE, //!< The mode requested by digital peripherals to keep XTAL clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the XTAL domain config by esp_sleep_pd_config) + ESP_SLEEP_LP_USE_XTAL_MODE, //!< The mode requested by lp peripherals to keep XTAL clock on during sleep. Only valid for lightsleep. ESP_SLEEP_MODE_MAX, } esp_sleep_sub_mode_t; diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index de25aeb268..76233f1d62 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -118,6 +118,7 @@ typedef enum { ESP_SLEEP_WAKEUP_COCPU, //!< Wakeup caused by COCPU int ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG, //!< Wakeup caused by COCPU crash ESP_SLEEP_WAKEUP_BT, //!< Wakeup caused by BT (light sleep only) + ESP_SLEEP_WAKEUP_VAD, //!< Wakeup caused by VAD } esp_sleep_source_t; /** @@ -179,6 +180,16 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void); */ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us); +#if SOC_LP_VAD_SUPPORTED +/** + * @brief Enable wakeup by VAD + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_sleep_enable_vad_wakeup(void); +#endif + #if SOC_TOUCH_SENSOR_SUPPORTED /** * @brief Enable wakeup by touch sensor diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index 97c112aa6b..b6be295d10 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -29,6 +29,7 @@ #include "hal/pmu_hal.h" #include "hal/psram_ctrlr_ll.h" #include "hal/lp_sys_ll.h" +#include "hal/clk_gate_ll.h" #include "esp_private/esp_pmu.h" #include "pmu_param.h" #include "esp_rom_sys.h" @@ -202,6 +203,10 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->analog.hp_sys.analog.dbias = HP_CALI_ACTIVE_DBIAS_DEFAULT; } + if (sleep_flags & RTC_SLEEP_LP_PERIPH_USE_XTAL) { + _clk_gate_ll_xtal_to_lp_periph_en(true); + } + config->power = power_default; pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags); config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period); diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index ed81134542..b790ade738 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -222,7 +222,7 @@ typedef struct { } domain[ESP_PD_DOMAIN_MAX]; portMUX_TYPE lock; uint64_t sleep_duration; - uint32_t wakeup_triggers : 15; + uint32_t wakeup_triggers : 20; #if SOC_PM_SUPPORT_EXT1_WAKEUP uint32_t ext1_trigger_mode : 22; // 22 is the maximum RTCIO number in all chips uint32_t ext1_rtc_gpio_mask : 22; @@ -917,6 +917,12 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m sleep_flags |= RTC_SLEEP_XTAL_AS_RTC_FAST; } +#if SOC_LP_VAD_SUPPORTED + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_LP_USE_XTAL_MODE] && !deep_sleep) { + sleep_flags |= RTC_SLEEP_LP_PERIPH_USE_XTAL; + } +#endif + #if CONFIG_ESP_SLEEP_DEBUG if (s_sleep_ctx != NULL) { s_sleep_ctx->sleep_flags = sleep_flags; @@ -1645,6 +1651,14 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us) return ESP_OK; } +#if SOC_LP_VAD_SUPPORTED +esp_err_t esp_sleep_enable_vad_wakeup(void) +{ + s_config.wakeup_triggers |= RTC_LP_VAD_TRIG_EN; + return esp_sleep_sub_mode_config(ESP_SLEEP_LP_USE_XTAL_MODE, true); +} +#endif + static esp_err_t timer_wakeup_prepare(int64_t sleep_duration) { if (sleep_duration < 0) { @@ -2165,6 +2179,10 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) #if SOC_LP_CORE_SUPPORTED } else if (wakeup_cause & RTC_LP_CORE_TRIG_EN) { return ESP_SLEEP_WAKEUP_ULP; +#endif +#if SOC_LP_VAD_SUPPORTED + } else if (wakeup_cause & RTC_LP_VAD_TRIG_EN) { + return ESP_SLEEP_WAKEUP_VAD; #endif } else { return ESP_SLEEP_WAKEUP_UNDEFINED; @@ -2229,6 +2247,7 @@ int32_t* esp_sleep_sub_mode_dump_config(FILE *stream) { [ESP_SLEEP_ULTRA_LOW_MODE] = "ESP_SLEEP_ULTRA_LOW_MODE", [ESP_SLEEP_RTC_FAST_USE_XTAL_MODE] = "ESP_SLEEP_RTC_FAST_USE_XTAL_MODE", [ESP_SLEEP_DIG_USE_XTAL_MODE] = "ESP_SLEEP_DIG_USE_XTAL_MODE", + [ESP_SLEEP_LP_USE_XTAL_MODE] = "ESP_SLEEP_LP_USE_XTAL_MODE", }[mode], s_sleep_sub_mode_ref_cnt[mode] ? "ENABLED" : "DISABLED", s_sleep_sub_mode_ref_cnt[mode]); diff --git a/components/hal/esp32p4/include/hal/clk_gate_ll.h b/components/hal/esp32p4/include/hal/clk_gate_ll.h index 8c5fc05cfb..9a49fd41e0 100644 --- a/components/hal/esp32p4/include/hal/clk_gate_ll.h +++ b/components/hal/esp32p4/include/hal/clk_gate_ll.h @@ -14,6 +14,7 @@ extern "C" { #include #include "esp_attr.h" #include "soc/hp_sys_clkrst_struct.h" +#include "soc/lp_clkrst_struct.h" /** * Enable or disable the clock gate for ref_20m. @@ -75,6 +76,18 @@ FORCE_INLINE_ATTR void _clk_gate_ll_ref_240m_clk_en(bool enable) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define clk_gate_ll_ref_240m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_240m_clk_en(__VA_ARGS__) +/** + * Enable or disable the clock gate for xtal to lp periph + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_xtal_to_lp_periph_en(bool enable) +{ + LP_AON_CLKRST.lp_clk_en.xtal_clk_force_on = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_xtal_to_lp_periph_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_xtal_to_lp_periph_en(__VA_ARGS__) + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index eac76a74a3..ed47efb446 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1859,6 +1859,14 @@ config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE bool default y +config SOC_SLEEP_SYSTIMER_STALL_WORKAROUND + bool + default y + +config SOC_SLEEP_TGWDT_STOP_WORKAROUND + bool + default y + config SOC_PSRAM_VDD_POWER_MPLL bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 16d2aa7643..bf411fb3b7 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -702,6 +702,8 @@ #define SOC_CPU_IN_TOP_DOMAIN (1) #define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1) +#define SOC_SLEEP_SYSTIMER_STALL_WORKAROUND 1 //TODO IDF-11381: replace with all xtal field clk gate control +#define SOC_SLEEP_TGWDT_STOP_WORKAROUND 1 //TODO IDF-11381: replace with all xtal field clk gate control /*-------------------------- PSRAM CAPS ----------------------------*/ #define SOC_PSRAM_VDD_POWER_MPLL (1) From 56af6b5fc4fe1fcef4a44bfc6f2341bcc93b55da Mon Sep 17 00:00:00 2001 From: Armando Date: Wed, 9 Oct 2024 14:50:00 +0800 Subject: [PATCH 4/4] test(sleep): vad wakeup hp core test --- .../test_apps/lp_i2s/sdkconfig.ci.defaults | 1 - .../test_apps/.build-test-rules.yml | 4 + .../test_apps/vad_wakeup/CMakeLists.txt | 8 + .../test_apps/vad_wakeup/README.md | 3 + .../test_apps/vad_wakeup/main/CMakeLists.txt | 7 + .../test_apps/vad_wakeup/main/test_app_main.c | 27 +++ .../test_apps/vad_wakeup/main/test_vad_8k.pcm | Bin 0 -> 34272 bytes .../vad_wakeup/main/test_vad_wakeup.c | 162 ++++++++++++++++++ .../test_apps/vad_wakeup/pytest_wakeup_vad.py | 11 ++ .../test_apps/vad_wakeup/sdkconfig.defaults | 8 + .../lp_core_basic_tests/sdkconfig.ci.lp_vad | 1 - 11 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 components/esp_hw_support/test_apps/vad_wakeup/CMakeLists.txt create mode 100644 components/esp_hw_support/test_apps/vad_wakeup/README.md create mode 100644 components/esp_hw_support/test_apps/vad_wakeup/main/CMakeLists.txt create mode 100644 components/esp_hw_support/test_apps/vad_wakeup/main/test_app_main.c create mode 100644 components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_8k.pcm create mode 100644 components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_wakeup.c create mode 100644 components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py create mode 100644 components/esp_hw_support/test_apps/vad_wakeup/sdkconfig.defaults diff --git a/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults b/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults index 5e9f8e25bd..e69de29bb2 100644 --- a/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults +++ b/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults @@ -1 +0,0 @@ -CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y diff --git a/components/esp_hw_support/test_apps/.build-test-rules.yml b/components/esp_hw_support/test_apps/.build-test-rules.yml index b61d8878c6..a13010cf3a 100644 --- a/components/esp_hw_support/test_apps/.build-test-rules.yml +++ b/components/esp_hw_support/test_apps/.build-test-rules.yml @@ -42,6 +42,10 @@ components/esp_hw_support/test_apps/rtc_power_modes: temporary: true reason: the other targets are not tested yet +components/esp_hw_support/test_apps/vad_wakeup: + disable: + - if: SOC_LP_VAD_SUPPORTED != 1 + components/esp_hw_support/test_apps/wakeup_tests: disable: - if: IDF_TARGET in ["esp32c5", "esp32p4", "linux", "esp32c61"] diff --git a/components/esp_hw_support/test_apps/vad_wakeup/CMakeLists.txt b/components/esp_hw_support/test_apps/vad_wakeup/CMakeLists.txt new file mode 100644 index 0000000000..5036560011 --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/CMakeLists.txt @@ -0,0 +1,8 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(vad_wakeup) diff --git a/components/esp_hw_support/test_apps/vad_wakeup/README.md b/components/esp_hw_support/test_apps/vad_wakeup/README.md new file mode 100644 index 0000000000..f8ea707124 --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/README.md @@ -0,0 +1,3 @@ +| Supported Targets | ESP32-P4 | +| ----------------- | -------- | + diff --git a/components/esp_hw_support/test_apps/vad_wakeup/main/CMakeLists.txt b/components/esp_hw_support/test_apps/vad_wakeup/main/CMakeLists.txt new file mode 100644 index 0000000000..3a92a5d2bd --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/main/CMakeLists.txt @@ -0,0 +1,7 @@ +set(srcs "test_app_main.c" + "test_vad_wakeup.c") + +idf_component_register(SRCS ${srcs} + REQUIRES unity esp_driver_i2s esp_driver_uart ulp esp_timer + WHOLE_ARCHIVE + EMBED_FILES "test_vad_8k.pcm") diff --git a/components/esp_hw_support/test_apps/vad_wakeup/main/test_app_main.c b/components/esp_hw_support/test_apps/vad_wakeup/main/test_app_main.c new file mode 100644 index 0000000000..1d34b63e44 --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/main/test_app_main.c @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "unity_test_utils.h" + +#define LEAKS (400) + + +void setUp(void) +{ + unity_utils_record_free_mem(); +} + +void tearDown(void) +{ + unity_utils_evaluate_leaks_direct(LEAKS); +} + +void app_main(void) +{ + unity_run_menu(); +} diff --git a/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_8k.pcm b/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_8k.pcm new file mode 100644 index 0000000000000000000000000000000000000000..5b6c32a03731f5cee7ba8bfa178b38477ac7f5f4 GIT binary patch literal 34272 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 literal 0 HcmV?d00001 diff --git a/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_wakeup.c b/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_wakeup.c new file mode 100644 index 0000000000..2a245bfc6f --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_wakeup.c @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "driver/uart.h" +#include "driver/lp_i2s.h" +#include "driver/lp_i2s_std.h" +#include "driver/i2s_std.h" +#include "ulp_lp_core_lp_vad_shared.h" +#include "unity.h" +#include "esp_timer.h" + +#define TEST_I2S_FRAME_SIZE (128) // Frame numbers in every writing / reading +#define TEST_I2S_TRANS_SIZE (4096) // Trans size +#define TEST_LP_I2S_PIN_BCK 4 +#define TEST_LP_I2S_PIN_WS 5 +#define TEST_LP_I2S_PIN_DIN 6 + + +extern const uint8_t test_vad_pcm_start[] asm("_binary_test_vad_8k_pcm_start"); +extern const uint8_t test_vad_pcm_end[] asm("_binary_test_vad_8k_pcm_end"); +static const char *TAG = "TEST_VAD"; + +static void s_hp_i2s_config(void) +{ + esp_err_t ret = ESP_FAIL; + int pcm_size = test_vad_pcm_end - test_vad_pcm_start; + printf("pcm_size: %d\n", pcm_size); + + i2s_chan_handle_t tx_handle = NULL; + i2s_chan_config_t i2s_channel_config = { + .id = I2S_NUM_0, + .role = I2S_ROLE_MASTER, + .dma_desc_num = 16, + .dma_frame_num = TEST_I2S_FRAME_SIZE, + .auto_clear = false, + }; + TEST_ESP_OK(i2s_new_channel(&i2s_channel_config, &tx_handle, NULL)); + + + i2s_std_config_t i2s_std_config = { + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = GPIO_NUM_7, + .ws = GPIO_NUM_8, + .dout = GPIO_NUM_21, + .din = -1, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + i2s_std_config.clk_cfg = (i2s_std_clk_config_t)I2S_STD_CLK_DEFAULT_CONFIG(16000); + i2s_std_config.slot_cfg = (i2s_std_slot_config_t)I2S_STD_PCM_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &i2s_std_config)); + + + uint8_t *txbuf = (uint8_t *)heap_caps_calloc(1, TEST_I2S_TRANS_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(txbuf); + + uint8_t *prebuf = (uint8_t *)heap_caps_calloc(1, TEST_I2S_TRANS_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(prebuf); + + memcpy(prebuf, test_vad_pcm_start, TEST_I2S_TRANS_SIZE); + memcpy(txbuf, test_vad_pcm_start, TEST_I2S_TRANS_SIZE); + + for (int i = 0; i < TEST_I2S_TRANS_SIZE; i++) { + ESP_LOGD(TAG, "prebuf[%d]: %d", i, prebuf[i]); + ESP_LOGD(TAG, "txbuf[%d]: %d", i, txbuf[i]); + } + + size_t bytes_written = 0; + TEST_ESP_OK(i2s_channel_preload_data(tx_handle, prebuf, TEST_I2S_TRANS_SIZE, &bytes_written)); + + TEST_ESP_OK(i2s_channel_enable(tx_handle)); + + while (1) { + ret = i2s_channel_write(tx_handle, txbuf, TEST_I2S_TRANS_SIZE, &bytes_written, 0); + if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) { + TEST_ESP_OK(ret); + } + ESP_LOGD(TAG, "bytes_written: %d", bytes_written); + vTaskDelay(1); + } +} + +static void s_lp_vad_config(void) +{ + ESP_ERROR_CHECK(esp_sleep_enable_vad_wakeup()); + ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)); + ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON)); + + lp_i2s_chan_handle_t rx_handle = NULL; + lp_i2s_chan_config_t config = { + .id = 0, + .role = I2S_ROLE_SLAVE, + .threshold = 512, + }; + TEST_ESP_OK(lp_i2s_new_channel(&config, NULL, &rx_handle)); + + lp_i2s_std_config_t lp_std_cfg = { + .pin_cfg = { + .bck = TEST_LP_I2S_PIN_BCK, + .ws = TEST_LP_I2S_PIN_WS, + .din = TEST_LP_I2S_PIN_DIN, + }, + }; + lp_std_cfg.slot_cfg = (lp_i2s_std_slot_config_t)LP_I2S_STD_PCM_SHORT_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + TEST_ESP_OK(lp_i2s_channel_init_std_mode(rx_handle, &lp_std_cfg)); + + // LP VAD Init + lp_vad_init_config_t init_config = { + .lp_i2s_chan = rx_handle, + .vad_config = { + .init_frame_num = 100, + .min_energy_thresh = 100, + .speak_activity_thresh = 10, + .non_speak_activity_thresh = 30, + .min_speak_activity_thresh = 3, + .max_speak_activity_thresh = 100, + }, + }; + TEST_ESP_OK(lp_core_lp_vad_init(0, &init_config)); + TEST_ESP_OK(lp_i2s_channel_enable(rx_handle)); + TEST_ESP_OK(lp_core_lp_vad_enable(0)); + + printf("Entering light sleep\n"); + /* To make sure the complete line is printed before entering sleep mode, + * need to wait until UART TX FIFO is empty: + */ + uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); + + /* Enter sleep mode */ + esp_light_sleep_start(); + + /* Determine wake up reason */ + const char* wakeup_reason; + switch (esp_sleep_get_wakeup_cause()) { + case ESP_SLEEP_WAKEUP_VAD: + wakeup_reason = "vad"; + break; + default: + wakeup_reason = "other"; + TEST_ASSERT(false); + break; + } + + ESP_LOGI(TAG, "wakeup, reason: %s", wakeup_reason); +} + +TEST_CASE_MULTIPLE_DEVICES("test LP VAD wakeup", "[vad][ignore][manual]", s_hp_i2s_config, s_lp_vad_config); diff --git a/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py b/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py new file mode 100644 index 0000000000..b4d9f85aff --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32p4 +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='lack of runners for now') +@pytest.mark.lp_i2s +def test_efuse(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/vad_wakeup/sdkconfig.defaults b/components/esp_hw_support/test_apps/vad_wakeup/sdkconfig.defaults new file mode 100644 index 0000000000..cac3f9a01f --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/sdkconfig.defaults @@ -0,0 +1,8 @@ +CONFIG_ESP_TASK_WDT_INIT=n + +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_TYPE_LP_CORE=y +CONFIG_ULP_COPROC_RESERVE_MEM=12000 +CONFIG_ULP_PANIC_OUTPUT_ENABLE=y + +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad index 8397edb939..766d6c83cd 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad @@ -1,2 +1 @@ CONFIG_TEST_LP_CORE_VAD_ENABLE=y -CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y