Compare commits

..

1 Commits

Author SHA1 Message Date
Aditya Patwardhan 64b9d85a76 change(version): Update version to 5.4.0 2024-11-07 12:55:42 +05:50
515 changed files with 3332 additions and 14141 deletions
+8 -5
View File
@@ -40,7 +40,7 @@ variables:
GIT_FETCH_EXTRA_FLAGS: "--no-recurse-submodules --prune --prune-tags"
# we're using .cache folder for caches
GIT_CLEAN_FLAGS: -ffdx -e .cache/
LATEST_GIT_TAG: v5.4-dev
LATEST_GIT_TAG: v5.4-beta1
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
# by default we will fetch all submodules
@@ -55,12 +55,15 @@ variables:
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
# Docker images
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.5:1"
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.5:1-1"
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v5.5:1"
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.4:1"
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.4:1-1"
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v5.4:1"
SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:5"
PRE_COMMIT_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:1"
# target test repo parameters
TEST_ENV_CONFIG_REPO: "https://gitlab-ci-token:${BOT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/qa/ci-test-runner-configs.git"
# cache python dependencies
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
@@ -70,7 +73,7 @@ variables:
CI_PYTHON_CONSTRAINT_BRANCH: ""
# Update the filename for a specific ESP-IDF release. It is used only with CI_PYTHON_CONSTRAINT_BRANCH.
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v5.5.txt"
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v5.4.txt"
# Set this variable to repository name of a Python tool you wish to install and test in the context of ESP-IDF CI.
# Keep the variable empty when not used.
+8 -8
View File
@@ -261,14 +261,14 @@
- <<: *if-dev-push
changes: *patterns-python-files
#.rules:patterns:static-code-analysis-preview:
# rules:
# - <<: *if-dev-push
# changes: *patterns-c-files
# - <<: *if-dev-push
# changes: *patterns-python-files
# - <<: *if-dev-push
# changes: *patterns-sonarqube-files
.rules:patterns:static-code-analysis-preview:
rules:
- <<: *if-dev-push
changes: *patterns-c-files
- <<: *if-dev-push
changes: *patterns-python-files
- <<: *if-dev-push
changes: *patterns-sonarqube-files
.rules:patterns:idf-pytest-plugin:
rules:
+78 -78
View File
@@ -38,84 +38,84 @@ check_pylint:
fi
- if [ -z "$files" ]; then echo "No python files found"; exit 0; fi
- run_cmd pylint --exit-zero --load-plugins=pylint_gitlab --output-format=gitlab-codeclimate:pylint.json $files
# build stage
# Sonarqube related jobs put here for this reason:
# Here we have two jobs. code_quality_check and code_quality_report.
#
## build stage
## Sonarqube related jobs put here for this reason:
## Here we have two jobs. code_quality_check and code_quality_report.
##
## code_quality_check will analyze the code changes between your MR and
## code repo stored in sonarqube server. The analysis result is only shown in
## the comments under this MR and won't be transferred to the server.
##
## code_quality_report will analyze and transfer both of the newly added code
## and the analysis result to the server.
##
## Put in the front to ensure that the newly merged code can be stored in
## sonarqube server ASAP, in order to avoid reporting unrelated code issues
#.sonar_scan_template:
# stage: build
# extends: .pre_check_template
# # full clone since this image does not support fetch --shallow-since-cutoff
# # shiny runners are used for full clone
# tags: [build, shiny]
# image: $SONARQUBE_SCANNER_IMAGE
# before_script:
# - source tools/ci/utils.sh
# - export PYTHONPATH="$CI_PROJECT_DIR/tools:$CI_PROJECT_DIR/tools/ci/python_packages:$PYTHONPATH"
# - fetch_submodules
# # Exclude the submodules, all paths ends with /**
# - submodules=$(get_all_submodules)
# # get all exclude paths specified in tools/ci/sonar_exclude_list.txt | ignore lines start with # | xargs | replace all <space> to <comma>
# - custom_excludes=$(cat $CI_PROJECT_DIR/tools/ci/sonar_exclude_list.txt | grep -v '^#' | xargs | sed -e 's/ /,/g')
# # Exclude the report dir as well
# - export EXCLUSIONS="$custom_excludes,$submodules"
# - export SONAR_SCANNER_OPTS="-Xmx2048m"
# variables:
# GIT_DEPTH: 0
# REPORT_PATTERN: clang_tidy_reports/**/*.txt
# artifacts:
# paths:
# - $REPORT_PATTERN
# expire_in: 1 week
# when: always
# dependencies: # Here is not a hard dependency relationship, could be skipped when only python files changed. so we do not use "needs" here.
# - clang_tidy_check
# code_quality_check will analyze the code changes between your MR and
# code repo stored in sonarqube server. The analysis result is only shown in
# the comments under this MR and won't be transferred to the server.
#
#code_quality_check:
# extends:
# - .sonar_scan_template
# - .rules:patterns:static-code-analysis-preview
# allow_failure: true # it's using exit code to indicate the code analysis result,
# # we don't want to block ci when critical issues founded
# script:
# - export CI_MERGE_REQUEST_COMMITS=$(python ${CI_PROJECT_DIR}/tools/ci/ci_get_mr_info.py commits --src-branch ${CI_COMMIT_REF_NAME} | tr '\n' ',')
# # test if this branch have merge request, if not, exit 0
# - test -n "$CI_MERGE_REQUEST_IID" || exit 0
# - test -n "$CI_MERGE_REQUEST_COMMITS" || exit 0
# - sonar-scanner
# -Dsonar.analysis.mode=preview
# -Dsonar.branch.name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
# -Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN
# -Dsonar.exclusions=$EXCLUSIONS
# -Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID
# -Dsonar.gitlab.commit_sha=$CI_MERGE_REQUEST_COMMITS
# -Dsonar.gitlab.merge_request_discussion=true
# -Dsonar.gitlab.ref_name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
# -Dsonar.host.url=$SONAR_HOST_URL
# -Dsonar.login=$SONAR_LOGIN
# code_quality_report will analyze and transfer both of the newly added code
# and the analysis result to the server.
#
#code_quality_report:
# extends:
# - .sonar_scan_template
# - .rules:protected
# allow_failure: true # it's using exit code to indicate the code analysis result,
# # we don't want to block ci when critical issues founded
# script:
# - sonar-scanner
# -Dsonar.branch.name=$CI_COMMIT_REF_NAME
# -Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN
# -Dsonar.exclusions=$EXCLUSIONS
# -Dsonar.gitlab.commit_sha=$PIPELINE_COMMIT_SHA
# -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
# -Dsonar.host.url=$SONAR_HOST_URL
# -Dsonar.login=$SONAR_LOGIN
# Put in the front to ensure that the newly merged code can be stored in
# sonarqube server ASAP, in order to avoid reporting unrelated code issues
.sonar_scan_template:
stage: build
extends: .pre_check_template
# full clone since this image does not support fetch --shallow-since-cutoff
# shiny runners are used for full clone
tags: [build, shiny]
image: $SONARQUBE_SCANNER_IMAGE
before_script:
- source tools/ci/utils.sh
- export PYTHONPATH="$CI_PROJECT_DIR/tools:$CI_PROJECT_DIR/tools/ci/python_packages:$PYTHONPATH"
- fetch_submodules
# Exclude the submodules, all paths ends with /**
- submodules=$(get_all_submodules)
# get all exclude paths specified in tools/ci/sonar_exclude_list.txt | ignore lines start with # | xargs | replace all <space> to <comma>
- custom_excludes=$(cat $CI_PROJECT_DIR/tools/ci/sonar_exclude_list.txt | grep -v '^#' | xargs | sed -e 's/ /,/g')
# Exclude the report dir as well
- export EXCLUSIONS="$custom_excludes,$submodules"
- export SONAR_SCANNER_OPTS="-Xmx2048m"
variables:
GIT_DEPTH: 0
REPORT_PATTERN: clang_tidy_reports/**/*.txt
artifacts:
paths:
- $REPORT_PATTERN
expire_in: 1 week
when: always
dependencies: # Here is not a hard dependency relationship, could be skipped when only python files changed. so we do not use "needs" here.
- clang_tidy_check
code_quality_check:
extends:
- .sonar_scan_template
- .rules:patterns:static-code-analysis-preview
allow_failure: true # it's using exit code to indicate the code analysis result,
# we don't want to block ci when critical issues founded
script:
- export CI_MERGE_REQUEST_COMMITS=$(python ${CI_PROJECT_DIR}/tools/ci/ci_get_mr_info.py commits --src-branch ${CI_COMMIT_REF_NAME} | tr '\n' ',')
# test if this branch have merge request, if not, exit 0
- test -n "$CI_MERGE_REQUEST_IID" || exit 0
- test -n "$CI_MERGE_REQUEST_COMMITS" || exit 0
- sonar-scanner
-Dsonar.analysis.mode=preview
-Dsonar.branch.name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
-Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN
-Dsonar.exclusions=$EXCLUSIONS
-Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID
-Dsonar.gitlab.commit_sha=$CI_MERGE_REQUEST_COMMITS
-Dsonar.gitlab.merge_request_discussion=true
-Dsonar.gitlab.ref_name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.login=$SONAR_LOGIN
code_quality_report:
extends:
- .sonar_scan_template
- .rules:protected
allow_failure: true # it's using exit code to indicate the code analysis result,
# we don't want to block ci when critical issues founded
script:
- sonar-scanner
-Dsonar.branch.name=$CI_COMMIT_REF_NAME
-Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN
-Dsonar.exclusions=$EXCLUSIONS
-Dsonar.gitlab.commit_sha=$PIPELINE_COMMIT_SHA
-Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.login=$SONAR_LOGIN
@@ -58,7 +58,6 @@ foreach(component ${proj_components})
endforeach()
set(BOOTLOADER_BUILD 1)
set(NON_OS_BUILD 1)
include("${IDF_PATH}/tools/cmake/project.cmake")
set(common_req log esp_rom esp_common esp_hw_support newlib)
idf_build_set_property(EXTRA_COMPONENT_EXCLUDE_DIRS "${EXTRA_COMPONENT_EXCLUDE_DIRS}")
@@ -67,7 +66,6 @@ idf_build_set_property(__OUTPUT_SDKCONFIG 0)
project(bootloader)
idf_build_set_property(COMPILE_DEFINITIONS "BOOTLOADER_BUILD=1" APPEND)
idf_build_set_property(COMPILE_DEFINITIONS "NON_OS_BUILD=1" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
idf_component_get_property(main_args esptool_py FLASH_ARGS)
@@ -209,7 +207,7 @@ elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
COMMAND ${CMAKE_COMMAND} -E echo
"* After first boot, only re-flashes of this kind (with same key) will be accepted."
COMMAND ${CMAKE_COMMAND} -E echo
"* Not recommended to reuse the same secure boot keyfile on multiple production devices."
"* Not recommended to re-use the same secure boot keyfile on multiple production devices."
DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
VERBATIM)
elseif(
@@ -184,14 +184,12 @@ void esp_flash_encryption_init_checks(void);
*/
esp_err_t esp_flash_encryption_enable_secure_features(void);
#if CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY
/** @brief Enable the key manager for flash encryption
*
* @return
* - ESP_OK - On success
*/
esp_err_t esp_flash_encryption_enable_key_mgr(void);
#endif // CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY
#endif /* BOOTLOADER_BUILD && CONFIG_SECURE_FLASH_ENC_ENABLED */
@@ -11,8 +11,9 @@
#include "esp_efuse_table.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "hal/key_mgr_ll.h"
#include "hal/mspi_timing_tuning_ll.h"
#include "soc/keymng_reg.h"
#include "soc/pcr_reg.h"
#include "soc/pcr_struct.h"
static __attribute__((unused)) const char *TAG = "flash_encrypt";
@@ -61,21 +62,30 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
return ESP_OK;
}
// TODO: Update to use LL APIs once key manager support added in IDF-8621
esp_err_t esp_flash_encryption_enable_key_mgr(void)
{
// Enable and reset key manager
// To suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV
int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused));
key_mgr_ll_enable_bus_clock(true);
key_mgr_ll_enable_peripheral_clock(true);
key_mgr_ll_reset_register();
// Set the force power down bit to 0 to enable key manager
PCR.km_pd_ctrl.km_mem_force_pd = 0;
// Reset the key manager
PCR.km_conf.km_clk_en = 1;
PCR.km_conf.km_rst_en = 1;
PCR.km_conf.km_rst_en = 0;
while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) {
// Wait for key manager to be ready
while (!PCR.km_conf.km_ready) {
};
// Force Key Manager to use eFuse key for XTS-AES operation
key_mgr_ll_set_key_usage(ESP_KEY_MGR_XTS_AES_128_KEY, ESP_KEY_MGR_USE_EFUSE_KEY);
_mspi_timing_ll_reset_mspi();
// Wait for key manager state machine to be idle
while (REG_READ(KEYMNG_STATE_REG) != 0) {
};
// Set the key manager to use efuse key
REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, 2);
// Reset MSPI to re-load the flash encryption key
REG_SET_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
REG_CLR_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
return ESP_OK;
}
@@ -258,7 +258,8 @@ esp_err_t esp_flash_encrypt_contents(void)
REG_WRITE(SENSITIVE_XTS_AES_KEY_UPDATE_REG, 1);
#endif
#if CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY
// TODO: Remove C5 target config after key manager LL support- see IDF-8621
#if CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY || CONFIG_IDF_TARGET_ESP32C5
esp_flash_encryption_enable_key_mgr();
#endif
-3
View File
@@ -907,9 +907,6 @@ if(CONFIG_BLE_MESH_V11_SUPPORT)
elseif(CONFIG_IDF_TARGET_ESP32C6)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
elseif(CONFIG_IDF_TARGET_ESP32C61)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
elseif(CONFIG_IDF_TARGET_ESP32H2)
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a")
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
@@ -305,27 +305,19 @@ void bt_hci_log_data_show(bt_hci_log_t *p_hci_log_ctl)
osi_mutex_unlock(&mutex_lock);
}
static bool enable_hci_log_flag = true;
void bt_hci_log_record_hci_enable(bool enable)
{
enable_hci_log_flag = enable;
}
esp_err_t IRAM_ATTR bt_hci_log_record_hci_data(uint8_t data_type, uint8_t *data, uint8_t data_len)
{
if (!enable_hci_log_flag) return ESP_OK;
return bt_hci_log_record_data(&g_bt_hci_log_data_ctl, NULL, data_type, data, data_len);
}
esp_err_t IRAM_ATTR bt_hci_log_record_custom_data(char *string, uint8_t *data, uint8_t data_len)
{
if (!enable_hci_log_flag) return ESP_OK;
return bt_hci_log_record_data(&g_bt_hci_log_data_ctl, string, HCI_LOG_DATA_TYPE_SELF_DEFINE, data, data_len);
}
esp_err_t IRAM_ATTR bt_hci_log_record_hci_adv(uint8_t data_type, uint8_t *data, uint8_t data_len)
{
if (!enable_hci_log_flag) return ESP_OK;
return bt_hci_log_record_data(&g_bt_hci_log_adv_ctl, NULL, data_type, data, data_len);
}
-17
View File
@@ -478,23 +478,6 @@ config BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD
If you set `BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it
may cause adv packets lost more.
menu "BLE disconnect when instant passed"
config BTDM_BLE_LLCP_CONN_UPDATE
bool "BLE ACL connection update procedure"
depends on (BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM)
default n
help
If this option is enabled, Controller will terminate the connection
when instant passed during connection update procedure.
config BTDM_BLE_LLCP_CHAN_MAP_UPDATE
bool "BLE ACL channel map update procedure"
depends on (BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM)
default n
help
If this option is enabled, Controller will terminate the connection
when instant passed in channel map update procedure.
endmenu
config BTDM_RESERVE_DRAM
hex
@@ -489,26 +489,3 @@ config BT_CTRL_LE_PING_EN
help
If this option is disabled, The Controller will not start the LE authenticated payload timer.
This option is used for some compatibility problems related to LE ping procedure.
menu "BLE disconnect when instant passed"
config BT_CTRL_BLE_LLCP_CONN_UPDATE
bool "BLE ACL connection update procedure"
default n
help
If this option is enabled, Controller will terminate the connection
when instant passed during connection update procedure.
config BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE
bool "BLE ACL channel map update procedure"
default n
help
If this option is enabled, Controller will terminate the connection
when instant passed in channel map update procedure.
config BT_CTRL_BLE_LLCP_PHY_UPDATE
bool "BLE ACL PHY update procedure"
default n
help
If this option is enabled, Controller will terminate the connection
when instant passed in PHY update procedure.
endmenu
+10 -14
View File
@@ -184,6 +184,7 @@ const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG
static bool s_ble_active = false;
#ifdef CONFIG_PM_ENABLE
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
#define BTDM_MIN_TIMER_UNCERTAINTY_US (200)
#endif // CONFIG_PM_ENABLE
static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID;
@@ -403,7 +404,7 @@ static void sleep_modem_ble_mac_modem_state_deinit(void)
}
}
void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead)
void sleep_modem_light_sleep_overhead_set(uint32_t overhead)
{
r_esp_ble_set_wakeup_overhead(overhead);
}
@@ -423,19 +424,16 @@ esp_err_t controller_sleep_init(void)
BLE_RTC_DELAY_US_MODEM_SLEEP);
#endif /* FREERTOS_USE_TICKLESS_IDLE */
#endif // CONFIG_BT_LE_SLEEP_ENABLE
#ifdef CONFIG_PM_ENABLE
rc = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "bt", &s_pm_lock);
if (rc != ESP_OK) {
goto error;
}
#endif // CONFIG_PM_ENABLE
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
/* Create a new regdma link for BLE related register restoration */
rc = sleep_modem_ble_mac_modem_state_init(0);
if (rc != ESP_OK) {
goto error;
}
assert(rc == 0);
esp_sleep_enable_bt_wakeup();
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer");
@@ -448,21 +446,19 @@ esp_err_t controller_sleep_init(void)
sleep_modem_register_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare,
sleep_modem_mac_bb_power_up_prepare);
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD
#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
return rc;
#ifdef CONFIG_PM_ENABLE
error:
#endif // CONFIG_PM_ENABLE
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD
sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare,
sleep_modem_mac_bb_power_up_prepare);
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD
esp_sleep_disable_bt_wakeup();
esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set);
#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#ifdef CONFIG_PM_ENABLE
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
/*lock should release first and then delete*/
if (s_pm_lock != NULL) {
esp_pm_lock_delete(s_pm_lock);
@@ -475,7 +471,7 @@ error:
void controller_sleep_deinit(void)
{
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD
sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare,
sleep_modem_mac_bb_power_up_prepare);
+12 -16
View File
@@ -388,6 +388,7 @@ void esp_bt_read_ctrl_log_from_flash(bool output)
static bool s_ble_active = false;
#ifdef CONFIG_PM_ENABLE
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
#define BTDM_MIN_TIMER_UNCERTAINTY_US (200)
#endif // CONFIG_PM_ENABLE
static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID;
@@ -611,7 +612,7 @@ static void sleep_modem_ble_mac_modem_state_deinit(void)
}
}
void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead)
void sleep_modem_light_sleep_overhead_set(uint32_t overhead)
{
r_esp_ble_set_wakeup_overhead(overhead);
}
@@ -638,20 +639,17 @@ esp_err_t controller_sleep_init(void)
if (rc != ESP_OK) {
goto error;
}
#endif // CONFIG_PM_ENABLE
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if SOC_PM_RETENTION_HAS_CLOCK_BUG && !CONFIG_MAC_BB_PD
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_BT_LE_SLEEP_ENABLE && SOC_PM_RETENTION_HAS_CLOCK_BUG && !CONFIG_MAC_BB_PD
#error "CONFIG_MAC_BB_PD required for BLE light sleep to run properly"
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && !CONFIG_MAC_BB_PD
#endif // CONFIG_BT_LE_SLEEP_ENABLE && SOC_PM_RETENTION_HAS_CLOCK_BUG && !CONFIG_MAC_BB_PD
/* Create a new regdma link for BLE related register restoration */
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
rc = sleep_modem_ble_mac_modem_state_init(1);
#else
rc = sleep_modem_ble_mac_modem_state_init(0);
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG
if (rc != ESP_OK) {
goto error;
}
assert(rc == 0);
esp_sleep_enable_bt_wakeup();
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer");
@@ -664,21 +662,19 @@ esp_err_t controller_sleep_init(void)
sleep_modem_register_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare,
sleep_modem_mac_bb_power_up_prepare);
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD
#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
return rc;
#ifdef CONFIG_PM_ENABLE
error:
#endif // CONFIG_PM_ENABLE
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD
sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare,
sleep_modem_mac_bb_power_up_prepare);
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD
esp_sleep_disable_bt_wakeup();
esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set);
#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#ifdef CONFIG_PM_ENABLE
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
/*lock should release first and then delete*/
if (s_pm_lock != NULL) {
esp_pm_lock_delete(s_pm_lock);
@@ -691,7 +687,7 @@ error:
void controller_sleep_deinit(void)
{
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD
sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare,
sleep_modem_mac_bb_power_up_prepare);
@@ -700,7 +696,7 @@ void controller_sleep_deinit(void)
esp_sleep_disable_bt_wakeup();
sleep_modem_ble_mac_modem_state_deinit();
esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set);
#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#ifdef CONFIG_PM_ENABLE
/* lock should be released first */
esp_pm_lock_delete(s_pm_lock);
+12 -17
View File
@@ -385,6 +385,7 @@ void esp_bt_read_ctrl_log_from_flash(bool output)
static bool s_ble_active = false;
#ifdef CONFIG_PM_ENABLE
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
#define BTDM_MIN_TIMER_UNCERTAINTY_US (200)
#endif // CONFIG_PM_ENABLE
static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID;
@@ -603,7 +604,7 @@ static void sleep_modem_ble_mac_modem_state_deinit(void)
}
}
void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead)
void sleep_modem_light_sleep_overhead_set(uint32_t overhead)
{
r_esp_ble_set_wakeup_overhead(overhead);
}
@@ -630,17 +631,13 @@ esp_err_t controller_sleep_init(void)
if (rc != ESP_OK) {
goto error;
}
rc = esp_deep_sleep_register_hook(&r_esp_ble_stop_wakeup_timing);
if (rc != ESP_OK) {
goto error;
}
#endif //CONFIG_PM_ENABLE
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
assert(rc == 0);
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
/* Create a new regdma link for BLE related register restoration */
rc = sleep_modem_ble_mac_modem_state_init(0);
if (rc != ESP_OK) {
goto error;
}
assert(rc == 0);
esp_sleep_enable_bt_wakeup();
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer");
@@ -648,17 +645,15 @@ esp_err_t controller_sleep_init(void)
if (rc != ESP_OK) {
goto error;
}
#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
return rc;
#ifdef CONFIG_PM_ENABLE
error:
#endif // CONFIG_PM_ENABLE
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
esp_sleep_disable_bt_wakeup();
esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set);
#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#ifdef CONFIG_PM_ENABLE
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
esp_deep_sleep_deregister_hook(&r_esp_ble_stop_wakeup_timing);
/*lock should release first and then delete*/
if (s_pm_lock != NULL) {
@@ -672,12 +667,12 @@ error:
void controller_sleep_deinit(void)
{
#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
r_ble_rtc_wake_up_state_clr();
esp_sleep_disable_bt_wakeup();
sleep_modem_ble_mac_modem_state_deinit();
esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set);
#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#ifdef CONFIG_PM_ENABLE
esp_deep_sleep_deregister_hook(&r_esp_ble_stop_wakeup_timing);
/* lock should be released first */
@@ -1049,23 +1049,6 @@ esp_err_t esp_ble_gap_set_privacy_mode(esp_ble_addr_type_t addr_type, esp_bd_add
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gap_set_csa_support(uint8_t csa_select)
{
btc_msg_t msg;
btc_ble_gap_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GAP_BLE;
msg.act = BTC_GAP_BLE_SET_CSA_SUPPORT;
arg.set_csa_support.csa_select = csa_select;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#if (BLE_50_FEATURE_SUPPORT == TRUE)
esp_err_t esp_ble_gap_read_phy(esp_bd_addr_t bd_addr)
@@ -229,7 +229,6 @@ typedef enum {
ESP_GAP_BLE_ADD_DEV_TO_RESOLVING_LIST_COMPLETE_EVT, /*!< when add a device to the resolving list completes, the event comes*/
ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT, /*!< When vendor hci command complete, the event comes */
ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT, /*!< When set privacy mode complete, the event comes */
ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT, /*!< When set CSA support complete, the event comes */
ESP_GAP_BLE_EVT_MAX, /*!< when maximum advertising event complete, the event comes */
} esp_gap_ble_cb_event_t;
@@ -1573,12 +1572,6 @@ typedef union {
struct ble_set_privacy_mode_cmpl_evt_param {
esp_bt_status_t status; /*!< Indicate privacy mode set operation success status */
} set_privacy_mode_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT */
/**
* @brief ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT
*/
struct ble_set_csa_support_cmpl_evt_param {
esp_bt_status_t status; /*!< Indicate CSA support set operation success status */
} set_csa_support_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT */
} esp_ble_gap_cb_param_t;
/**
@@ -2751,23 +2744,6 @@ esp_err_t esp_ble_gap_vendor_command_send(esp_ble_vendor_cmd_params_t *vendor_cm
*/
esp_err_t esp_ble_gap_set_privacy_mode(esp_ble_addr_type_t addr_type, esp_bd_addr_t addr, esp_ble_privacy_mode_t mode);
/**
* @brief This function is used to set which channel selection algorithm(CSA) is supported.
*
* @note - This function should only be used when there are BLE compatibility issues about channel hopping after connected.
* For example, if the peer device only supports CSA#1, this function can be called to make the Controller use CSA#1.
* - This function is not supported on ESP32.
*
* @param[in] csa_select: 0: Channel Selection Algorighm will be selected by Controller
* 1: Select the LE Channel Selection Algorighm #1
* 2: Select the LE Channel Selection Algorighm #2
*
* @return
* - ESP_OK : success
* - other : failed
*/
esp_err_t esp_ble_gap_set_csa_support(uint8_t csa_select);
#ifdef __cplusplus
}
#endif
@@ -5859,12 +5859,6 @@ void bta_dm_ble_gap_set_privacy_mode(tBTA_DM_MSG *p_data)
p_data->ble_set_privacy_mode.privacy_mode, p_data->ble_set_privacy_mode.p_cback);
}
void bta_dm_ble_gap_set_csa_support(tBTA_DM_MSG *p_data)
{
APPL_TRACE_API("%s, csa_select = %d", __func__, p_data->ble_set_csa_support.csa_select);
BTM_BleSetCsaSupport(p_data->ble_set_csa_support.csa_select, p_data->ble_set_csa_support.p_cback);
}
#if (BLE_50_FEATURE_SUPPORT == TRUE)
void bta_dm_ble_gap_dtm_enhance_tx_start(tBTA_DM_MSG *p_data)
{
@@ -3025,19 +3025,6 @@ void BTA_DmClearRandAddress(void)
}
}
void BTA_DmBleGapSetCsaSupport(uint8_t csa_select, tBTA_SET_CSA_SUPPORT_CMPL_CBACK *p_callback)
{
tBTA_DM_API_BLE_SET_CSA_SUPPORT *p_msg;
if ((p_msg = (tBTA_DM_API_BLE_SET_CSA_SUPPORT *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_CSA_SUPPORT)))
!= NULL) {
p_msg->hdr.event = BTA_DM_API_BLE_SET_CSA_SUPPORT_EVT;
p_msg->csa_select = csa_select;
p_msg->p_cback = p_callback;
bta_sys_sendmsg(p_msg);
}
}
/*******************************************************************************
**
** Function BTA_VendorInit
@@ -235,7 +235,6 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
bta_dm_ble_gap_set_rpa_timeout, /* BTA_DM_API_SET_RPA_TIMEOUT_EVT */
bta_dm_ble_gap_add_dev_to_resolving_list, /* BTA_DM_API_ADD_DEV_TO_RESOLVING_LIST_EVT */
bta_dm_ble_gap_set_privacy_mode, /* BTA_DM_API_SET_PRIVACY_MODE_EVT */
bta_dm_ble_gap_set_csa_support, /* BTA_DM_API_BLE_SET_CSA_SUPPORT_EVT */
#endif
};
@@ -226,7 +226,6 @@ enum {
BTA_DM_API_SET_RPA_TIMEOUT_EVT,
BTA_DM_API_ADD_DEV_TO_RESOLVING_LIST_EVT,
BTA_DM_API_SET_PRIVACY_MODE_EVT,
BTA_DM_API_BLE_SET_CSA_SUPPORT_EVT,
#endif
BTA_DM_MAX_EVT
};
@@ -960,12 +959,6 @@ typedef struct {
tBTA_SET_PRIVACY_MODE_CMPL_CBACK *p_cback;
} tBTA_DM_API_SET_PRIVACY_MODE;
typedef struct {
BT_HDR hdr;
UINT8 csa_select;
tBTA_SET_CSA_SUPPORT_CMPL_CBACK *p_cback;
} tBTA_DM_API_BLE_SET_CSA_SUPPORT;
#endif /* BLE_INCLUDED */
/* data type for BTA_DM_API_REMOVE_ACL_EVT */
@@ -1372,7 +1365,6 @@ typedef union {
tBTA_DM_API_BLE_DTM_STOP dtm_stop;
tBTA_DM_API_CLEAR_ADV ble_clear_adv;
tBTA_DM_API_SET_PRIVACY_MODE ble_set_privacy_mode;
tBTA_DM_API_BLE_SET_CSA_SUPPORT ble_set_csa_support;
#endif
tBTA_DM_API_REMOVE_ACL remove_acl;
@@ -1825,7 +1817,6 @@ extern void bta_dm_ble_gap_clear_adv(tBTA_DM_MSG *p_data);
extern void bta_dm_ble_gap_set_rpa_timeout(tBTA_DM_MSG *p_data);
extern void bta_dm_ble_gap_add_dev_to_resolving_list(tBTA_DM_MSG *p_data);
extern void bta_dm_ble_gap_set_privacy_mode(tBTA_DM_MSG *p_data);
extern void bta_dm_ble_gap_set_csa_support(tBTA_DM_MSG *p_data);
#if (BLE_50_FEATURE_SUPPORT == TRUE)
extern void bta_dm_ble_gap_dtm_enhance_tx_start(tBTA_DM_MSG *p_data);
extern void bta_dm_ble_gap_dtm_enhance_rx_start(tBTA_DM_MSG *p_data);
@@ -538,14 +538,9 @@ void bta_gattc_deinit(void)
uint8_t bta_gattc_cl_rcb_active_count(void)
{
uint8_t count = 0;
uint8_t dm_gattc_uuid[16];
// When SDP is included, Bluedroid stack will register the DM GATTC application
memset(dm_gattc_uuid, 0x87, 16);
for (uint8_t i = 0; i < BTA_GATTC_CL_MAX; i ++) {
if (bta_gattc_cb.cl_rcb[i].in_use &&
memcmp(bta_gattc_cb.cl_rcb[i].app_uuid.uu.uuid128, dm_gattc_uuid, 16)) {
if (bta_gattc_cb.cl_rcb[i].in_use) {
count++;
}
}
@@ -439,8 +439,6 @@ typedef tBTM_ADD_DEV_TO_RESOLVING_LIST_CMPL_CBACK tBTA_ADD_DEV_TO_RESOLVING_LIST
typedef tBTM_SET_PRIVACY_MODE_CMPL_CBACK tBTA_SET_PRIVACY_MODE_CMPL_CBACK;
typedef tBTM_SET_CSA_SUPPORT_CMPL_CBACK tBTA_SET_CSA_SUPPORT_CMPL_CBACK;
typedef tBTM_CMPL_CB tBTA_CMPL_CB;
typedef tBTM_VSC_CMPL tBTA_VSC_CMPL;
@@ -2923,8 +2921,6 @@ extern void BTA_DmBleDtmStop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback);
extern void BTA_DmBleSetPrivacyMode(uint8_t addr_type, BD_ADDR addr, uint8_t privacy_mode, tBTA_SET_PRIVACY_MODE_CMPL_CBACK *p_cback);
extern void BTA_DmBleGapSetCsaSupport(uint8_t csa_select, tBTM_SET_CSA_SUPPORT_CMPL_CBACK *p_callback);
/*******************************************************************************
**
** Function BTA_DmBleSetStorageParams
@@ -1363,25 +1363,6 @@ static void btc_ble_set_privacy_mode_callback(UINT8 status)
}
}
static void btc_ble_set_csa_support_callback(UINT8 status)
{
esp_ble_gap_cb_param_t param;
bt_status_t ret;
btc_msg_t msg = {0};
msg.sig = BTC_SIG_API_CB;
msg.pid = BTC_PID_GAP_BLE;
msg.act = ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT;
param.set_csa_support_cmpl.status = btc_btm_status_to_esp_status(status);
ret = btc_transfer_context(&msg, &param, sizeof(esp_ble_gap_cb_param_t), NULL, NULL);
if (ret != BT_STATUS_SUCCESS) {
BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);
}
}
void btc_get_whitelist_size(uint16_t *length)
{
BTM_BleGetWhiteListSize(length);
@@ -2421,9 +2402,6 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
btc_ble_set_privacy_mode(arg->set_privacy_mode.addr_type, arg->set_privacy_mode.addr,
arg->set_privacy_mode.privacy_mode, btc_ble_set_privacy_mode_callback);
break;
case BTC_GAP_BLE_SET_CSA_SUPPORT:
BTA_DmBleGapSetCsaSupport(arg->set_csa_support.csa_select, btc_ble_set_csa_support_callback);
break;
default:
break;
}
@@ -106,7 +106,6 @@ typedef enum {
BTC_GAP_BLE_ACT_ADD_DEVICE_TO_RESOLVING_LIST,
BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT,
BTC_GAP_BLE_SET_PRIVACY_MODE,
BTC_GAP_BLE_SET_CSA_SUPPORT,
} btc_gap_ble_act_t;
/* btc_ble_gap_args_t */
@@ -275,10 +274,6 @@ typedef union {
esp_bd_addr_t addr;
uint8_t privacy_mode;
} set_privacy_mode;
// BTC_GAP_BLE_SET_CSA_SUPPORT
struct set_csa_support_args {
uint8_t csa_select;
} set_csa_support;
} btc_ble_gap_args_t;
#if (BLE_50_FEATURE_SUPPORT == TRUE)
@@ -4617,12 +4617,6 @@ void btm_ble_free (void)
#endif
}
static bool enable_topology_check_flag = true;
void esp_qa_enable_topology_check(bool enable)
{
// This is a workaround: If the topology check is disabled, the 'Supported States' will not be checked.
enable_topology_check_flag = enable;
}
/*******************************************************************************
**
** Function btm_ble_topology_check
@@ -4635,7 +4629,6 @@ void esp_qa_enable_topology_check(bool enable)
*******************************************************************************/
BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request_state_mask)
{
if(!enable_topology_check_flag) return TRUE;
BOOLEAN rt = FALSE;
UINT8 state_offset = 0;
@@ -4768,17 +4761,6 @@ BOOLEAN BTM_BleSetPrivacyMode(UINT8 addr_type, BD_ADDR bd_addr, UINT8 privacy_mo
return TRUE;
}
BOOLEAN BTM_BleSetCsaSupport(UINT8 csa_select, tBTM_SET_CSA_SUPPORT_CMPL_CBACK *p_callback)
{
if (btsnd_hcic_ble_set_csa_support(csa_select) != TRUE) {
BTM_TRACE_ERROR("LE SetCsaSupport csa_select=%d: error", csa_select);
return FALSE;
}
btm_cb.ble_ctr_cb.set_csa_support_cmpl_cb = p_callback;
return TRUE;
}
bool btm_ble_adv_pkt_ready(void)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
@@ -773,14 +773,6 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len,
}
break;
}
case HCI_VENDOR_BLE_SET_CSA_SUPPORT: {
uint8_t status;
STREAM_TO_UINT8(status, p);
if (ble_cb && ble_cb->set_csa_support_cmpl_cb) {
ble_cb->set_csa_support_cmpl_cb(status);
}
break;
}
default:
break;
}
@@ -377,7 +377,6 @@ typedef struct {
tBTM_BLE_STATE_MASK cur_states; /* bit mask of tBTM_BLE_STATE */
UINT8 link_count[2]; /* total link count master and slave*/
tBTM_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK *update_exceptional_list_cmp_cb;
tBTM_SET_CSA_SUPPORT_CMPL_CBACK *set_csa_support_cmpl_cb;
} tBTM_BLE_CB;
#ifdef __cplusplus
@@ -1910,7 +1910,7 @@ UINT8 btsnd_hcic_ble_set_default_periodic_adv_sync_trans_params(UINT8 mode, UINT
}
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
BOOLEAN btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode)
UINT8 btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode)
{
BT_HDR *p;
UINT8 *pp;
@@ -1933,26 +1933,4 @@ BOOLEAN btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 pri
btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
return (TRUE);
}
BOOLEAN btsnd_hcic_ble_set_csa_support (UINT8 csa_select)
{
BT_HDR *p;
UINT8 *pp;
if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_SET_CSA_SUPPORT)) == NULL) {
return (FALSE);
}
pp = (UINT8 *)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_CSA_SUPPORT;
p->offset = 0;
UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_SET_CSA_SUPPORT);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_SET_CSA_SUPPORT);
UINT8_TO_STREAM (pp, csa_select);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
return TRUE;
}
#endif
@@ -1007,7 +1007,6 @@ typedef void (tBTM_START_STOP_ADV_CMPL_CBACK) (UINT8 status);
typedef void (tBTM_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK) (tBTM_STATUS status, uint8_t subcode, uint32_t length, uint8_t *device_info);
typedef void (tBTM_CLEAR_ADV_CMPL_CBACK) (UINT8 status);
typedef void (tBTM_SET_PRIVACY_MODE_CMPL_CBACK) (tBTM_STATUS status);
typedef void (tBTM_SET_CSA_SUPPORT_CMPL_CBACK) (tBTM_STATUS status);
#if (BLE_50_FEATURE_SUPPORT == TRUE)
#define BTM_BLE_5_GAP_READ_PHY_COMPLETE_EVT 1
@@ -2725,20 +2724,6 @@ BOOLEAN BTM_BleSetPrivacyMode(UINT8 addr_type,
UINT8 privacy_mode,
tBTM_SET_PRIVACY_MODE_CMPL_CBACK *p_callback);
/*******************************************************************************
**
** Function BTM_BleSetCsaSupport
**
** Description This function is called to set the ChSel field of Advertising or Initiating PDUs
**
** Parameters csa_select - Select LE Channel Selection Algorithm.
** p_callback - Callback function to be called when the operation is completed.
**
** Returns TRUE if the operation was successful, otherwise FALSE.
**
*******************************************************************************/
BOOLEAN BTM_BleSetCsaSupport (UINT8 csa_select, tBTM_SET_CSA_SUPPORT_CMPL_CBACK *p_callback);
/*
#ifdef __cplusplus
}
@@ -422,7 +422,6 @@
#define HCI_SUBCODE_BLE_ADV_REPORT_FLOW_CONTROL 0x0A
#define HCI_SUBCODE_BLE_RD_STATIC_ADDR 0x0B
#define HCI_SUBCODE_BLE_CLEAR_ADV 0x0C
#define HCI_SUBCODE_BLE_SET_CSA_SUPPORT 0x12
#define HCI_SUBCODE_BLE_MAX 0x7F
//ESP BT subcode define
@@ -469,8 +468,6 @@
#define HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_ADV_REPORT_FLOW_CONTROL)
/* BLE clear legacy advertising */
#define HCI_VENDOR_BLE_CLEAR_ADV HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_CLEAR_ADV)
/* BLE set CSA support */
#define HCI_VENDOR_BLE_SET_CSA_SUPPORT HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_SET_CSA_SUPPORT)
//ESP BT HCI CMD
#define HCI_VENDOR_BT_SET_MIN_ENC_KEY_SIZE HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_SET_MIN_ENC_KEY_SIZE)
@@ -759,7 +759,6 @@ void btsnd_hcic_vendor_spec_cmd (BT_HDR *buffer, UINT16 opcode,
#define HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL 2
#define HCIC_PARAM_SIZE_BLE_CLEAR_ADV 0
#define HCIC_PARAM_SIZE_SET_PRIVACY_MODE 8
#define HCIC_PARAM_SIZE_BLE_SET_CSA_SUPPORT 1
#if (BLE_50_FEATURE_SUPPORT == TRUE)
#define HCIC_PARAM_SIZE_BLE_READ_PHY 2
#define HCIC_PARAM_SIZE_BLE_SET_DEF_PHY 3
@@ -915,12 +914,7 @@ BOOLEAN btsnd_hcic_ble_set_rand_priv_addr_timeout (UINT16 rpa_timout);
BOOLEAN btsnd_hcic_ble_clear_adv(void);
BOOLEAN btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode);
BOOLEAN btsnd_hcic_ble_set_csa_support (UINT8 csa_select);
#endif /* BLE_INCLUDED */
#if (BLE_50_FEATURE_SUPPORT == TRUE)
typedef struct {
UINT8 scan_type;
@@ -1048,6 +1042,8 @@ UINT8 btsnd_hcic_ble_write_rf_path_compensation(UINT16 rf_tx_path, UINT16 rf_rx_
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
UINT8 btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode);
#define HCIC_PARAM_SIZE_WRITE_AUTHENT_PAYLOAD_TOUT 4
#define HCI__WRITE_AUTHENT_PAYLOAD_TOUT_HANDLE_OFF 0
@@ -376,7 +376,6 @@ void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency;
p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
p_lcb->updating_param_flag = false;
p_lcb->ble_addr_type = type;
/* If there are any preferred connection parameters, set them now */
if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
@@ -477,7 +476,6 @@ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE typ
p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency;
p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
p_lcb->updating_param_flag = false;
p_lcb->ble_addr_type = type;
/* Tell BTM Acl management about the link */
p_dev_rec = btm_find_or_alloc_dev (bda);
@@ -331,7 +331,8 @@ BOOLEAN smp_send_msg_to_L2CAP(BD_ADDR rem_bda, BT_HDR *p_toL2CAP)
if ((l2cap_ret = L2CA_SendFixedChnlData (fixed_cid, rem_bda, p_toL2CAP)) == L2CAP_DW_FAILED) {
smp_cb.total_tx_unacked -= 1;
SMP_TRACE_ERROR("SMP failed to pass msg to L2CAP");
SMP_TRACE_ERROR("SMP failed to pass msg:0x%0x to L2CAP",
*((UINT8 *)(p_toL2CAP + 1) + p_toL2CAP->offset));
return FALSE;
} else {
return TRUE;
@@ -1124,7 +1125,7 @@ BOOLEAN smp_pairing_request_response_parameters_are_valid(tSMP_CB *p_cb)
SMP_TRACE_DEBUG("%s for cmd code 0x%02x\n", __func__, p_cb->rcvd_cmd_code);
if (io_caps >= BTM_IO_CAP_MAX) {
SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with IO Capability \
SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with IO Capabilty \
value (0x%02x) out of range).\n",
p_cb->rcvd_cmd_code, io_caps);
return FALSE;
+1 -18
View File
@@ -55,7 +55,7 @@ extern "C" {
*
* @note Please do not modify this value
*/
#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20240926
#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20240722
/**
* @brief Bluetooth Controller mode
@@ -178,21 +178,6 @@ the advertising packet will be discarded until the memory is restored. */
#else
#define BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX 0
#endif
#ifdef CONFIG_BTDM_BLE_LLCP_CONN_UPDATE
#define BTDM_BLE_LLCP_CONN_UPDATE (1<<0)
#else
#define BTDM_BLE_LLCP_CONN_UPDATE (0<<0)
#endif
#ifdef CONFIG_BTDM_BLE_LLCP_CHAN_MAP_UPDATE
#define BTDM_BLE_LLCP_CHAN_MAP_UPDATE (1<<1)
#else
#define BTDM_BLE_LLCP_CHAN_MAP_UPDATE (0<<1)
#endif
#define BTDM_BLE_LLCP_DISC_FLAG (BTDM_BLE_LLCP_CONN_UPDATE | BTDM_BLE_LLCP_CHAN_MAP_UPDATE)
/**
* @brief Default Bluetooth Controller configuration
*/
@@ -221,7 +206,6 @@ the advertising packet will be discarded until the memory is restored. */
.hli = BTDM_CTRL_HLI, \
.dup_list_refresh_period = SCAN_DUPL_CACHE_REFRESH_PERIOD, \
.ble_scan_backoff = BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \
.ble_llcp_disc_flag = BTDM_BLE_LLCP_DISC_FLAG, \
.magic = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL, \
}
@@ -274,7 +258,6 @@ typedef struct {
bool hli; /*!< True if using high level interrupt; false otherwise. Configurable in menuconfig */
uint16_t dup_list_refresh_period; /*!< Scan duplicate filtering list refresh period in seconds. Configurable in menuconfig */
bool ble_scan_backoff; /*!< True if BLE scan backoff is enabled; false otherwise. Configurable in menuconfig */
uint8_t ble_llcp_disc_flag; /*!< BLE disconnect flag when instant passed. Configurable in menuconfig */
uint32_t magic; /*!< Magic number */
} esp_bt_controller_config_t;
+1 -23
View File
@@ -19,7 +19,7 @@ extern "C" {
#endif
#define ESP_BT_CTRL_CONFIG_MAGIC_VAL 0x5A5AA5A5
#define ESP_BT_CTRL_CONFIG_VERSION 0x02409260
#define ESP_BT_CTRL_CONFIG_VERSION 0x02404010
#define ESP_BT_HCI_TL_MAGIC_VALUE 0xfadebead
#define ESP_BT_HCI_TL_VERSION 0x00010000
@@ -217,26 +217,6 @@ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status);
#define BLE_HW_TARGET_CODE_CHIP_ECO0 (0x02010000)
#endif
#ifdef CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE
#define BT_CTRL_BLE_LLCP_CONN_UPDATE (1<<0)
#else
#define BT_CTRL_BLE_LLCP_CONN_UPDATE (0<<0)
#endif
#ifdef CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE
#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (1<<1)
#else
#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (0<<1)
#endif
#ifdef CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE
#define BT_CTRL_BLE_LLCP_PHY_UPDATE (1<<2)
#else
#define BT_CTRL_BLE_LLCP_PHY_UPDATE (0<<2)
#endif
#define BT_CTRL_BLE_LLCP_DISC_FLAG (BT_CTRL_BLE_LLCP_CONN_UPDATE | BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE | BT_CTRL_BLE_LLCP_PHY_UPDATE)
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \
.magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL, \
.version = ESP_BT_CTRL_CONFIG_VERSION, \
@@ -275,7 +255,6 @@ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status);
.ble_data_lenth_zero_aux = BT_BLE_ADV_DATA_LENGTH_ZERO_AUX, \
.ble_chan_ass_en = BT_CTRL_CHAN_ASS_EN, \
.ble_ping_en = BT_CTRL_LE_PING_EN, \
.ble_llcp_disc_flag = BT_CTRL_BLE_LLCP_DISC_FLAG, \
}
#else
@@ -350,7 +329,6 @@ typedef struct {
uint8_t ble_data_lenth_zero_aux; /*!< Config ext adv aux option */
uint8_t ble_chan_ass_en; /*!< BLE channel assessment enable */
uint8_t ble_ping_en; /*!< BLE ping procedure enable */
uint8_t ble_llcp_disc_flag; /*!< BLE disconnect flag when instant passed */
} esp_bt_controller_config_t;
/**
@@ -1479,6 +1479,11 @@ static esp_err_t i2s_init_legacy(i2s_port_t i2s_num, int intr_alloc_flag)
/* Create power management lock */
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_lock = ESP_PM_APB_FREQ_MAX;
#if SOC_I2S_SUPPORTS_APLL
if (p_i2s[i2s_num]->use_apll) {
pm_lock = ESP_PM_NO_LIGHT_SLEEP;
}
#endif // SOC_I2S_SUPPORTS_APLL
ESP_RETURN_ON_ERROR(esp_pm_lock_create(pm_lock, 0, "i2s_driver", &p_i2s[i2s_num]->pm_lock), TAG, "I2S pm lock error");
#endif //CONFIG_PM_ENABLE
@@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@@ -12,7 +12,6 @@ from pytest_embedded import Dut
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.esp32p4
@pytest.mark.esp32c61
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
+1 -2
View File
@@ -1,5 +1,4 @@
idf_build_get_property(target IDF_TARGET)
idf_build_get_property(non_os_build NON_OS_BUILD)
if(CONFIG_EFUSE_VIRTUAL)
message(STATUS "Efuse virtual mode is enabled. If Secure boot or Flash encryption is on"
@@ -29,7 +28,7 @@ list(APPEND srcs "src/esp_efuse_api.c"
"src/esp_efuse_utility.c"
"src/efuse_controller/keys/${type}/esp_efuse_api_key.c")
if(non_os_build)
if(BOOTLOADER_BUILD)
idf_component_register(SRCS "${srcs}"
PRIV_REQUIRES bootloader_support soc spi_flash
INCLUDE_DIRS "${include_dirs}"
+5 -5
View File
@@ -13,7 +13,7 @@
const static char *TAG = "efuse";
#ifdef NON_OS_BUILD
#if defined(BOOTLOADER_BUILD)
#define EFUSE_LOCK_ACQUIRE_RECURSIVE()
#define EFUSE_LOCK_RELEASE_RECURSIVE()
#else
@@ -39,11 +39,11 @@ esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst,
do {
memset((uint8_t *)dst, 0, esp_efuse_utility_get_number_of_items(dst_size_bits, 8));
err = esp_efuse_utility_process(field, dst, dst_size_bits, esp_efuse_utility_fill_buff);
#ifndef NON_OS_BUILD
#ifndef BOOTLOADER_BUILD
if (err == ESP_ERR_DAMAGED_READING) {
vTaskDelay(1);
}
#endif // NON_OS_BUILD
#endif // BOOTLOADER_BUILD
} while (err == ESP_ERR_DAMAGED_READING);
}
return err;
@@ -67,11 +67,11 @@ esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_
do {
*out_cnt = 0;
err = esp_efuse_utility_process(field, out_cnt, 0, esp_efuse_utility_count_once);
#ifndef NON_OS_BUILD
#ifndef BOOTLOADER_BUILD
if (err == ESP_ERR_DAMAGED_READING) {
vTaskDelay(1);
}
#endif // NON_OS_BUILD
#endif // BOOTLOADER_BUILD
} while (err == ESP_ERR_DAMAGED_READING);
}
return err;
@@ -13,7 +13,7 @@ extern "C" {
/** Major version number (X.x.x) */
#define ESP_IDF_VERSION_MAJOR 5
/** Minor version number (x.X.x) */
#define ESP_IDF_VERSION_MINOR 5
#define ESP_IDF_VERSION_MINOR 4
/** Patch version number (x.x.X) */
#define ESP_IDF_VERSION_PATCH 0
+1 -1
View File
@@ -228,7 +228,7 @@ esp_err_t dac_continuous_new_channels(const dac_continuous_config_t *cont_cfg, d
/* Create PM lock */
#if CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_lock_type = ESP_PM_APB_FREQ_MAX;
esp_pm_lock_type_t pm_lock_type = cont_cfg->clk_src == DAC_DIGI_CLK_SRC_APLL ? ESP_PM_NO_LIGHT_SLEEP : ESP_PM_APB_FREQ_MAX;
ESP_GOTO_ON_ERROR(esp_pm_lock_create(pm_lock_type, 0, "dac_driver", &handle->pm_lock), err3, TAG, "Failed to create DAC pm lock");
#endif
handle->chan_cnt = __builtin_popcount(cont_cfg->chan_mask);
+16 -39
View File
@@ -312,27 +312,29 @@ static esp_err_t s_hp_i2c_pins_config(i2c_bus_handle_t handle)
int port_id = handle->port_num;
// SDA pin configurations
gpio_config_t sda_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT_OUTPUT_OD,
.pull_down_en = false,
.pull_up_en = handle->pull_up_enable ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE,
.pin_bit_mask = 1ULL << handle->sda_num,
};
ESP_RETURN_ON_ERROR(gpio_set_level(handle->sda_num, 1), TAG, "i2c sda pin set level failed");
gpio_input_enable(handle->sda_num);
gpio_od_enable(handle->sda_num);
if (handle->pull_up_enable) {
gpio_pullup_en(handle->sda_num);
} else {
gpio_pullup_dis(handle->sda_num);
}
ESP_RETURN_ON_ERROR(gpio_config(&sda_conf), TAG, "config GPIO failed");
gpio_func_sel(handle->sda_num, PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(handle->sda_num, i2c_periph_signal[port_id].sda_out_sig, 0, 0);
esp_rom_gpio_connect_in_signal(handle->sda_num, i2c_periph_signal[port_id].sda_in_sig, 0);
// SCL pin configurations
gpio_config_t scl_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT_OUTPUT_OD,
.pull_down_en = false,
.pull_up_en = handle->pull_up_enable ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE,
.pin_bit_mask = 1ULL << handle->scl_num,
};
ESP_RETURN_ON_ERROR(gpio_set_level(handle->scl_num, 1), TAG, "i2c scl pin set level failed");
gpio_input_enable(handle->scl_num);
gpio_od_enable(handle->scl_num);
if (handle->pull_up_enable) {
gpio_pullup_en(handle->scl_num);
} else {
gpio_pullup_dis(handle->scl_num);
}
ESP_RETURN_ON_ERROR(gpio_config(&scl_conf), TAG, "config GPIO failed");
gpio_func_sel(handle->scl_num, PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(handle->scl_num, i2c_periph_signal[port_id].scl_out_sig, 0, 0);
esp_rom_gpio_connect_in_signal(handle->scl_num, i2c_periph_signal[port_id].scl_in_sig, 0);
@@ -404,28 +406,3 @@ esp_err_t i2c_common_set_pins(i2c_bus_handle_t handle)
return ret;
}
esp_err_t i2c_common_deinit_pins(i2c_bus_handle_t handle)
{
int port_id = handle->port_num;
if (handle->is_lp_i2c == false) {
ESP_RETURN_ON_ERROR(gpio_output_disable(handle->sda_num), TAG, "disable i2c pins failed");
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].sda_in_sig, 0);
ESP_RETURN_ON_ERROR(gpio_output_disable(handle->scl_num), TAG, "disable i2c pins failed");
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].scl_in_sig, 0);
}
#if SOC_LP_I2C_SUPPORTED
else {
ESP_RETURN_ON_ERROR(rtc_gpio_deinit(handle->sda_num), TAG, "deinit rtc gpio failed");
ESP_RETURN_ON_ERROR(rtc_gpio_deinit(handle->scl_num), TAG, "deinit rtc gpio failed");
#if SOC_LP_GPIO_MATRIX_SUPPORTED
lp_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].scl_in_sig, 0);
lp_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].sda_in_sig, 0);
#endif
}
#endif
return ESP_OK;
}
-1
View File
@@ -784,7 +784,6 @@ static esp_err_t i2c_master_bus_destroy(i2c_master_bus_handle_t bus_handle)
{
ESP_RETURN_ON_FALSE(bus_handle, ESP_ERR_INVALID_ARG, TAG, "no memory for i2c master bus");
i2c_master_bus_handle_t i2c_master = bus_handle;
i2c_common_deinit_pins(i2c_master->base);
if (i2c_release_bus_handle(i2c_master->base) == ESP_OK) {
if (i2c_master) {
if (i2c_master->bus_lock_mux) {
-11
View File
@@ -258,17 +258,6 @@ esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, soc_module_clk_t clk_
*/
esp_err_t i2c_common_set_pins(i2c_bus_handle_t handle);
/**
* @brief Deinit I2C SCL/SDA pins
*
* @param handle I2C bus handle
* @return
* - ESP_OK: I2C set SCL/SDA pins successfully.
* - ESP_ERR_INVALID_ARG: Argument error.
* - Otherwise: Set SCL/SDA IOs error.
*/
esp_err_t i2c_common_deinit_pins(i2c_bus_handle_t handle);
/**
* @brief Check whether bus is acquired
*
-1
View File
@@ -294,7 +294,6 @@ static esp_err_t i2c_slave_bus_destroy(i2c_slave_dev_handle_t i2c_slave)
{
if (i2c_slave) {
i2c_ll_disable_intr_mask(i2c_slave->base->hal.dev, I2C_LL_SLAVE_EVENT_INTR);
i2c_common_deinit_pins(i2c_slave->base);
if (i2c_slave->slv_rx_mux) {
vSemaphoreDeleteWithCaps(i2c_slave->slv_rx_mux);
i2c_slave->slv_rx_mux = NULL;
@@ -260,22 +260,6 @@ esp_err_t i2c_master_bus_reset(i2c_master_bus_handle_t bus_handle);
*/
esp_err_t i2c_master_bus_wait_all_done(i2c_master_bus_handle_t bus_handle, int timeout_ms);
/**
* @brief Retrieves the I2C master bus handle for a specified I2C port number.
*
* This function retrieves the I2C master bus handle for the
* given I2C port number. Please make sure the handle has already been initialized, and this
* function would simply returns the existing handle. Note that the returned handle still can't be used concurrently
*
* @param port_num I2C port number for which the handle is to be retrieved.
* @param ret_handle Pointer to a variable where the retrieved handle will be stored.
* @return
* - ESP_OK: Success. The handle is retrieved successfully.
* - ESP_ERR_INVALID_ARG: Invalid argument, such as invalid port number
* - ESP_ERR_INVALID_STATE: Invalid state, such as the I2C port is not initialized.
*/
esp_err_t i2c_master_get_bus_handle(i2c_port_num_t port_num, i2c_master_bus_handle_t *ret_handle);
#ifdef __cplusplus
}
#endif
@@ -15,7 +15,21 @@
extern "C" {
#endif
// Empty file in order not cause breaking change. Should be removed in next version.
/**
* @brief Retrieves the I2C master bus handle for a specified I2C port number.
*
* This function retrieves the I2C master bus handle for the
* given I2C port number. Please make sure the handle has already been initialized, and this
* function would simply returns the existing handle. Note that the returned handle still can't be used concurrently
*
* @param port_num I2C port number for which the handle is to be retrieved.
* @param ret_handle Pointer to a variable where the retrieved handle will be stored.
* @return
* - ESP_OK: Success. The handle is retrieved successfully.
* - ESP_ERR_INVALID_ARG: Invalid argument, such as invalid port number
* - ESP_ERR_INVALID_STATE: Invalid state, such as the I2C port is not initialized.
*/
esp_err_t i2c_master_get_bus_handle(i2c_port_num_t port_num, i2c_master_bus_handle_t *ret_handle);
#ifdef __cplusplus
}
@@ -19,6 +19,7 @@
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "esp_private/i2c_platform.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
+5
View File
@@ -199,6 +199,11 @@ esp_err_t i2s_channel_init_pdm_tx_mode(i2s_chan_handle_t handle, const i2s_pdm_t
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX;
#if SOC_I2S_SUPPORTS_APLL
if (pdm_tx_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) {
pm_type = ESP_PM_NO_LIGHT_SLEEP;
}
#endif // SOC_I2S_SUPPORTS_APLL
ESP_RETURN_ON_ERROR(esp_pm_lock_create(pm_type, 0, "i2s_driver", &handle->pm_lock), TAG, "I2S pm lock create failed");
#endif
+5
View File
@@ -240,6 +240,11 @@ esp_err_t i2s_channel_init_std_mode(i2s_chan_handle_t handle, const i2s_std_conf
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX;
#if SOC_I2S_SUPPORTS_APLL
if (std_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) {
pm_type = ESP_PM_NO_LIGHT_SLEEP;
}
#endif // SOC_I2S_SUPPORTS_APLL
ESP_RETURN_ON_ERROR(esp_pm_lock_create(pm_type, 0, "i2s_driver", &handle->pm_lock), TAG, "I2S pm lock create failed");
#endif
+5
View File
@@ -246,6 +246,11 @@ esp_err_t i2s_channel_init_tdm_mode(i2s_chan_handle_t handle, const i2s_tdm_conf
#endif
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX;
#if SOC_I2S_SUPPORTS_APLL
if (tdm_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) {
pm_type = ESP_PM_NO_LIGHT_SLEEP;
}
#endif // SOC_I2S_SUPPORTS_APLL
ESP_RETURN_ON_ERROR(esp_pm_lock_create(pm_type, 0, "i2s_driver", &handle->pm_lock), TAG, "I2S pm lock create failed");
#endif
@@ -11,10 +11,6 @@ components/esp_driver_i2s/test_apps/i2s_multi_dev:
disable:
- if: SOC_I2S_SUPPORTED != 1
- if: SOC_I2S_HW_VERSION_2 != 1
disable_test:
- if: IDF_TARGET in ["esp32c61"] # TODO: [ESP32C61] IDF-11442
temporary: true
reason: lack of runners
depends_components:
- esp_driver_i2s
@@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@@ -12,7 +12,6 @@ from pytest_embedded import Dut
@pytest.mark.esp32s3
@pytest.mark.esp32h2
@pytest.mark.esp32p4
@pytest.mark.esp32c61
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
@@ -4,4 +4,3 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
CONFIG_PM_DFS_INIT_AUTO=y
@@ -1,3 +1,3 @@
| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- |
| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- |
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -33,18 +33,6 @@ extern "C" {
#define LEDC_ERR_DUTY (0xFFFFFFFF)
#define LEDC_ERR_VAL (-1)
/**
* @brief Strategies to be applied to the LEDC channel during system Light-sleep period
*/
typedef enum {
LEDC_SLEEP_MODE_NO_ALIVE_NO_PD = 0, /*!< The default mode: no LEDC output, and no power off the LEDC power domain. */
LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD, /*!< The low-power-consumption mode: no LEDC output, and allow to power off the LEDC power domain.
This can save power, but at the expense of more RAM being consumed to save register context.
This option is only available on targets that support TOP domain to be powered down. */
LEDC_SLEEP_MODE_KEEP_ALIVE, /*!< The high-power-consumption mode: keep LEDC output when the system enters Light-sleep. */
LEDC_SLEEP_MODE_INVALID, /*!< Invalid LEDC sleep mode strategy */
} ledc_sleep_mode_t;
/**
* @brief Configuration parameters of LEDC channel for ledc_channel_config function
*/
@@ -56,7 +44,6 @@ typedef struct {
ledc_timer_t timer_sel; /*!< Select the timer source of channel (0 - LEDC_TIMER_MAX-1) */
uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */
int hpoint; /*!< LEDC channel hpoint value, the range is [0, (2**duty_resolution)-1] */
ledc_sleep_mode_t sleep_mode; /*!< choose the desired behavior for the LEDC channel in Light-sleep */
struct {
unsigned int output_invert: 1;/*!< Enable (1) or disable (0) gpio output invert */
} flags; /*!< LEDC flags */
+10 -244
View File
@@ -25,12 +25,6 @@
#include "esp_private/esp_clk_tree_common.h"
#include "esp_private/esp_gpio_reserve.h"
#include "esp_memory_utils.h"
#include "esp_private/sleep_retention.h"
#if SOC_PMU_SUPPORTED // TODO: replace when icg API available IDF-7595
#include "soc/pmu_struct.h"
#include "hal/pmu_types.h"
#include "soc/pmu_icg_mapping.h"
#endif
static __attribute__((unused)) const char *LEDC_TAG = "ledc";
@@ -64,8 +58,6 @@ static __attribute__((unused)) const char *LEDC_TAG = "ledc";
#define LEDC_FUNC_CLOCK_ATOMIC()
#endif
#define LEDC_USE_RETENTION_LINK (SOC_LEDC_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
typedef enum {
LEDC_FSM_IDLE,
LEDC_FSM_HW_FADE,
@@ -95,10 +87,6 @@ typedef struct {
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
ledc_clk_src_t timer_specific_clk[LEDC_TIMER_MAX]; /*!< Tracks the timer-specific clock selection for each timer */
#endif
ledc_sleep_mode_t sleep_mode; /*!< Records the sleep strategy to be applied to the LEDC module */
bool channel_keep_alive[LEDC_CHANNEL_MAX]; /*!< Records whether each channel needs to keep output during sleep */
uint8_t timer_xpd_ref_cnt[LEDC_TIMER_MAX]; /*!< Records the timer (glb_clk) not power down during sleep requirement */
bool glb_clk_xpd; /*!< Records the power strategy applied to the global clock */
} ledc_obj_t;
static ledc_obj_t *p_ledc_obj[LEDC_SPEED_MODE_MAX] = {
@@ -130,37 +118,6 @@ static const ledc_slow_clk_sel_t s_glb_clks[] = LEDC_LL_GLOBAL_CLOCKS;
static const ledc_clk_src_t s_timer_specific_clks[] = LEDC_LL_TIMER_SPECIFIC_CLOCKS;
#endif
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
static esp_err_t ledc_create_sleep_retention_link_cb(void *arg)
{
#if SOC_LEDC_SUPPORT_SLEEP_RETENTION
sleep_retention_module_t module = ledc_reg_retention_info.module_id;
esp_err_t err = sleep_retention_entries_create(ledc_reg_retention_info.common.regdma_entry_array,
ledc_reg_retention_info.common.array_size,
REGDMA_LINK_PRI_LEDC, module);
bool slp_retention_create_failed = (err != ESP_OK);
for (int i = 0; i < SOC_LEDC_TIMER_NUM && !slp_retention_create_failed; i++) {
err = sleep_retention_entries_create(ledc_reg_retention_info.timer[i].regdma_entry_array,
ledc_reg_retention_info.timer[i].array_size,
REGDMA_LINK_PRI_LEDC, module);
slp_retention_create_failed |= (err != ESP_OK);
}
for (int j = 0; j < SOC_LEDC_CHANNEL_NUM && !slp_retention_create_failed; j++) {
err = sleep_retention_entries_create(ledc_reg_retention_info.channel[j].regdma_entry_array,
ledc_reg_retention_info.channel[j].array_size,
REGDMA_LINK_PRI_LEDC, module);
slp_retention_create_failed |= (err != ESP_OK);
}
ESP_RETURN_ON_FALSE(!slp_retention_create_failed, err, LEDC_TAG, "create retention link failed");
#endif
return ESP_OK;
}
#endif
static void ledc_ls_timer_update(ledc_mode_t speed_mode, ledc_timer_t timer_sel)
{
if (speed_mode == LEDC_LOW_SPEED_MODE) {
@@ -283,78 +240,15 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel
return ESP_OK;
}
/**
* return 1 if the global clock cannot keep alive in sleep, as an error raised
*/
static bool ledc_glb_clk_set_sleep_mode(ledc_mode_t speed_mode, bool xpd)
{
bool glb_clk_xpd_err = false;
if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_RC_FAST) {
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, xpd);
p_ledc_obj[speed_mode]->glb_clk_xpd = xpd;
}
#if SOC_LEDC_SUPPORT_XTAL_CLOCK
else if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_XTAL) {
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_XTAL_MODE, xpd);
p_ledc_obj[speed_mode]->glb_clk_xpd = xpd;
}
#endif
else {
if (xpd) {
glb_clk_xpd_err = true;
}
}
return glb_clk_xpd_err;
}
/**
* spinlock should wrap outside
* return 1 if the timer cannot keep alive in sleep, as an error raised
*/
static bool ledc_timer_clk_src_set_xpd_in_sleep(ledc_mode_t speed_mode, ledc_timer_t timer_sel)
{
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_sel]++;
bool timer_clock_xpd_err = false;
// if the timer has not been configured yet, leave the xpd configuration to ledc_timer_config
if (p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] && p_ledc_obj[speed_mode]->glb_clk != LEDC_SLOW_CLK_UNINIT && !p_ledc_obj[speed_mode]->glb_clk_xpd) {
timer_clock_xpd_err = ledc_glb_clk_set_sleep_mode(speed_mode, true);
}
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
else if (p_ledc_obj[speed_mode]->timer_specific_clk[timer_sel] != LEDC_TIMER_SPECIFIC_CLK_UNINIT) {
timer_clock_xpd_err = true;
}
#endif
if (timer_clock_xpd_err) {
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_sel]--;
}
return timer_clock_xpd_err;
}
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_timer_t timer_sel)
{
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
LEDC_ARG_CHECK(timer_sel < LEDC_TIMER_MAX, "timer_select");
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
bool timer_xpd_err = false;
ledc_timer_t old_timer_sel;
ledc_hal_get_channel_timer(&(p_ledc_obj[speed_mode]->ledc_hal), channel, &old_timer_sel);
portENTER_CRITICAL(&ledc_spinlock);
ledc_hal_bind_channel_timer(&(p_ledc_obj[speed_mode]->ledc_hal), channel, timer_sel);
ledc_ls_channel_update(speed_mode, channel);
if (p_ledc_obj[speed_mode]->channel_keep_alive[channel] && old_timer_sel != timer_sel) {
if (p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[old_timer_sel] > 0) {
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[old_timer_sel]--;
}
// timer clock source should not be powered down during sleep
timer_xpd_err = ledc_timer_clk_src_set_xpd_in_sleep(speed_mode, timer_sel);
}
portEXIT_CRITICAL(&ledc_spinlock);
if (timer_xpd_err) {
ESP_LOGW(LEDC_TAG, "the binded timer can't keep alive in sleep");
}
return ESP_OK;
}
@@ -422,24 +316,6 @@ static bool ledc_speed_mode_ctx_create(ledc_mode_t speed_mode)
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
memset(ledc_new_mode_obj->timer_specific_clk, LEDC_TIMER_SPECIFIC_CLK_UNINIT, sizeof(ledc_clk_src_t) * LEDC_TIMER_MAX);
#endif
ledc_new_mode_obj->sleep_mode = LEDC_SLEEP_MODE_INVALID;
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // for targets that is !SOC_LEDC_SUPPORT_SLEEP_RETENTION, retention module should still be inited to avoid TOP PD
// Initialize sleep retention module for LEDC
sleep_retention_module_t module = ledc_reg_retention_info.module_id;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = ledc_create_sleep_retention_link_cb,
.arg = NULL,
},
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM),
};
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
ESP_LOGW(LEDC_TAG, "init sleep retention failed for ledc, power domain may be turned off during sleep");
}
#endif
p_ledc_obj[speed_mode] = ledc_new_mode_obj;
}
}
@@ -654,8 +530,6 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
ESP_LOGD(LEDC_TAG, "Using clock source %d (in %s mode), divisor: 0x%"PRIx32,
timer_clk_src, (speed_mode == LEDC_LOW_SPEED_MODE ? "slow" : "fast"), div_param);
bool timer_clk_xpd_err = false;
/* The following block configures the global clock.
* Thus, in theory, this only makes sense when configuring the LOW_SPEED timer and the source clock is LEDC_SCLK (as
* HIGH_SPEED timers won't be clocked by the global clock). However, there are some limitations due to HW design.
@@ -689,6 +563,16 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
}
p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_num] = true;
if (p_ledc_obj[speed_mode]->glb_clk != glb_clk) {
#if SOC_LIGHT_SLEEP_SUPPORTED
/* keep ESP_PD_DOMAIN_RC_FAST on during light sleep */
if (glb_clk == LEDC_SLOW_CLK_RC_FAST) {
/* Keep ESP_PD_DOMAIN_RC_FAST on during light sleep */
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, true);
} else if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_RC_FAST) {
/* No need to keep ESP_PD_DOMAIN_RC_FAST on during light sleep anymore */
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, false);
}
#endif
// TODO: release old glb_clk (if not UNINIT), and acquire new glb_clk [clk_tree]
p_ledc_obj[speed_mode]->glb_clk = glb_clk;
esp_clk_tree_enable_src((soc_module_clk_t)glb_clk, true);
@@ -697,13 +581,6 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
ledc_hal_set_slow_clk_sel(&(p_ledc_obj[speed_mode]->ledc_hal), glb_clk);
}
}
// acquire power domain for the timer clock source if desired and possible
if (p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_num] > 0 && !p_ledc_obj[speed_mode]->glb_clk_xpd) {
timer_clk_xpd_err = ledc_glb_clk_set_sleep_mode(speed_mode, true);
if (timer_clk_xpd_err) {
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_num] = 0;
}
}
portEXIT_CRITICAL(&ledc_spinlock);
ESP_LOGD(LEDC_TAG, "In slow speed mode, global clk set: %d", glb_clk);
@@ -711,19 +588,6 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
/* The divisor is correct, we can write in the hardware. */
ledc_timer_set(speed_mode, timer_num, div_param, duty_resolution, timer_clk_src);
portENTER_CRITICAL(&ledc_spinlock);
if (p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_num] > 0 && !p_ledc_obj[speed_mode]->glb_clk_xpd) {
// if still get into here, it means the speed mode is high speed mode
assert(speed_mode != LEDC_LOW_SPEED_MODE);
timer_clk_xpd_err = true;
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_num] = 0;
}
portEXIT_CRITICAL(&ledc_spinlock);
if (timer_clk_xpd_err) {
ESP_LOGW(LEDC_TAG, "the timer can't keep alive in sleep");
}
return ESP_OK;
error:
@@ -748,20 +612,6 @@ static esp_err_t ledc_timer_del(ledc_mode_t speed_mode, ledc_timer_t timer_sel)
is_deleted = true;
p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] = false;
// TODO: release timer specific clk and global clk if possible [clk_tree]
// check if the acquired power domain for the timer clock source can be released
if (p_ledc_obj[speed_mode]->glb_clk_xpd) {
bool timer_clk_allow_pd = true;
for (int i = 0; i < LEDC_TIMER_MAX; i++) {
if (p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] && p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[i] > 0) {
timer_clk_allow_pd = false;
break;
}
}
if (timer_clk_allow_pd) {
ledc_glb_clk_set_sleep_mode(speed_mode, false);
}
}
}
portEXIT_CRITICAL(&ledc_spinlock);
ESP_RETURN_ON_FALSE(is_configured && is_deleted, ESP_ERR_INVALID_STATE, LEDC_TAG, "timer hasn't been configured, or it is still running, please stop it with ledc_timer_pause first");
@@ -837,10 +687,6 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num");
LEDC_ARG_CHECK(timer_select < LEDC_TIMER_MAX, "timer_select");
LEDC_ARG_CHECK(intr_type < LEDC_INTR_MAX, "intr_type");
LEDC_ARG_CHECK(ledc_conf->sleep_mode < LEDC_SLEEP_MODE_INVALID, "sleep_mode");
#if !SOC_LEDC_SUPPORT_SLEEP_RETENTION
ESP_RETURN_ON_FALSE(ledc_conf->sleep_mode != LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD, ESP_ERR_NOT_SUPPORTED, LEDC_TAG, "register back up is not supported");
#endif
esp_err_t ret = ESP_OK;
@@ -886,86 +732,6 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
/*set LEDC signal in gpio matrix*/
_ledc_set_pin(gpio_num, output_invert, speed_mode, ledc_channel);
// apply desired sleep strategy
bool slp_mode_conflict = false;
bool slp_retention_alloc __attribute__((unused)) = false;
bool slp_retention_free __attribute__((unused)) = false;
portENTER_CRITICAL(&ledc_spinlock);
if (ledc_conf->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD) {
#if LEDC_USE_RETENTION_LINK
if (p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_NO_PD || p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_KEEP_ALIVE) {
// conflict sleep strategy with other LEDC channels, power domain cannot be turned off
slp_mode_conflict = true;
} else {
p_ledc_obj[speed_mode]->sleep_mode = LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD;
slp_retention_alloc = true;
}
#endif
} else if (ledc_conf->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_NO_PD) {
if (p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_INVALID) {
p_ledc_obj[speed_mode]->sleep_mode = LEDC_SLEEP_MODE_NO_ALIVE_NO_PD;
}
#if LEDC_USE_RETENTION_LINK
else if (p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD) {
// conflict sleep strategy with other LEDC channels, power domain might still be turned off
slp_mode_conflict = true;
}
#endif
} else if (ledc_conf->sleep_mode == LEDC_SLEEP_MODE_KEEP_ALIVE) {
p_ledc_obj[speed_mode]->channel_keep_alive[ledc_channel] = true;
#if LEDC_USE_RETENTION_LINK
if (p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD) {
// conflict sleep strategy with other LEDC channels, power domain won't be turned off
slp_mode_conflict = true;
slp_retention_free = true;
}
#endif
p_ledc_obj[speed_mode]->sleep_mode = LEDC_SLEEP_MODE_KEEP_ALIVE;
}
portEXIT_CRITICAL(&ledc_spinlock);
if (slp_mode_conflict) {
ESP_LOGW(LEDC_TAG, "conflict sleep strategy with other LEDC channels, power domain may not be on/off as desired in sleep");
}
#if LEDC_USE_RETENTION_LINK
if (slp_retention_alloc) {
if (sleep_retention_module_allocate(ledc_reg_retention_info.module_id) != ESP_OK) {
ESP_LOGW(LEDC_TAG, "create retention module failed, power domain can't turn off");
}
}
if (slp_retention_free) {
sleep_retention_module_free(ledc_reg_retention_info.module_id);
}
#endif
if (ledc_conf->sleep_mode == LEDC_SLEEP_MODE_KEEP_ALIVE) {
// 1. timer clock source should not be powered down during sleep
bool timer_xpd_err = false;
portENTER_CRITICAL(&ledc_spinlock);
timer_xpd_err = ledc_timer_clk_src_set_xpd_in_sleep(speed_mode, timer_select);
portEXIT_CRITICAL(&ledc_spinlock);
if (timer_xpd_err) {
ESP_LOGW(LEDC_TAG, "the binded timer can't keep alive in sleep");
}
// 2. keep IO output during sleep
gpio_sleep_sel_dis(gpio_num);
#if CONFIG_IDF_TARGET_ESP32P4
// To workaround DIG-399, all LP IOs are held when LP_PERIPH is powered off to ensure EXT wakeup functionality
// But holding LP IOs will cause LEDC signal cannot output on the pad during sleep
// Therefore, we will force LP periph xpd in such case
if ((1ULL << gpio_num) & SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
}
#endif
// 3. keep related module integrated clock gating on during sleep
// TODO: use proper icg API IDF-7595
#if SOC_PMU_SUPPORTED && !CONFIG_IDF_TARGET_ESP32P4 // P4 does not have peripheral icg
uint32_t val = PMU.hp_sys[PMU_MODE_HP_SLEEP].icg_func;
PMU.hp_sys[PMU_MODE_HP_SLEEP].icg_func = (val | BIT(PMU_ICG_FUNC_ENA_LEDC) | BIT(PMU_ICG_FUNC_ENA_IOMUX));
#endif
}
return ret;
}
@@ -1,7 +1,5 @@
set(srcs "test_app_main.c"
"test_ledc.c"
"test_ledc_sleep.c"
"test_ledc_utils.c")
"test_ledc.c")
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
@@ -9,8 +9,7 @@
#include "esp_heap_caps.h"
// Some resources are lazy allocated in LEDC driver, the threshold is left for that case
// This leak is large since LEDC driver does not provide channel delete mechanism
#define TEST_MEMORY_LEAK_THRESHOLD (500)
#define TEST_MEMORY_LEAK_THRESHOLD (400)
void setUp(void)
{
@@ -22,7 +22,54 @@
#include "driver/ledc.h"
#include "soc/ledc_struct.h"
#include "esp_clk_tree.h"
#include "test_ledc_utils.h"
#define PULSE_IO 5
#define TEST_PWM_FREQ 2000
#if SOC_LEDC_SUPPORT_HS_MODE
#define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE
#define SPEED_MODE_LIST {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}
#else
#define TEST_SPEED_MODE LEDC_LOW_SPEED_MODE
#define SPEED_MODE_LIST {LEDC_LOW_SPEED_MODE}
#endif
#if SOC_LEDC_SUPPORT_APB_CLOCK
#define TEST_DEFAULT_CLK_CFG LEDC_USE_APB_CLK
#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
#if SOC_CLK_TREE_SUPPORTED
#define TEST_DEFAULT_CLK_CFG LEDC_USE_PLL_DIV_CLK
#else
#define TEST_DEFAULT_CLK_CFG LEDC_USE_XTAL_CLK
#endif
#endif
static ledc_channel_config_t initialize_channel_config(void)
{
ledc_channel_config_t config;
memset(&config, 0, sizeof(ledc_channel_config_t));
config.gpio_num = PULSE_IO;
config.speed_mode = TEST_SPEED_MODE;
config.channel = LEDC_CHANNEL_0;
config.intr_type = LEDC_INTR_DISABLE;
config.timer_sel = LEDC_TIMER_0;
config.duty = 4000;
config.hpoint = 0;
return config;
}
static ledc_timer_config_t create_default_timer_config(void)
{
ledc_timer_config_t ledc_time_config;
memset(&ledc_time_config, 0, sizeof(ledc_timer_config_t));
ledc_time_config.speed_mode = TEST_SPEED_MODE;
ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT;
ledc_time_config.timer_num = LEDC_TIMER_0;
ledc_time_config.freq_hz = TEST_PWM_FREQ;
ledc_time_config.clk_cfg = TEST_DEFAULT_CLK_CFG;
return ledc_time_config;
}
static void fade_setup(void)
{
@@ -427,6 +474,52 @@ TEST_CASE("LEDC multi fade test", "[ledc]")
#if SOC_PCNT_SUPPORTED // Note. C61, C3, C2 do not have PCNT peripheral, the following test cases cannot be tested
#include "driver/pulse_cnt.h"
#define HIGHEST_LIMIT 10000
#define LOWEST_LIMIT -10000
static pcnt_unit_handle_t pcnt_unit;
static pcnt_channel_handle_t pcnt_chan;
static void setup_testbench(void)
{
pcnt_unit_config_t unit_config = {
.high_limit = HIGHEST_LIMIT,
.low_limit = LOWEST_LIMIT,
};
TEST_ESP_OK(pcnt_new_unit(&unit_config, &pcnt_unit));
pcnt_chan_config_t chan_config = {
.edge_gpio_num = PULSE_IO,
.level_gpio_num = -1,
};
TEST_ESP_OK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit));
}
static void tear_testbench(void)
{
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit));
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
TEST_ESP_OK(pcnt_del_unit(pcnt_unit));
}
// use PCNT to test the waveform of LEDC
static int wave_count(int last_time)
{
// The input ability of PULSE_IO is disabled after ledc driver install, so we need to re-enable it again
gpio_ll_input_enable(&GPIO, PULSE_IO);
int test_counter = 0;
TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit));
TEST_ESP_OK(pcnt_unit_start(pcnt_unit));
vTaskDelay(pdMS_TO_TICKS(last_time));
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &test_counter));
return test_counter;
}
// the PCNT will count the frequency of it
static void frequency_set_get(ledc_mode_t speed_mode, ledc_timer_t timer, uint32_t desired_freq, int16_t theoretical_freq, int16_t error)
{
@@ -638,6 +731,8 @@ static void ledc_cpu_reset_test_second_stage(void)
int count;
TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason());
setup_testbench();
// reconfigure the GPIO again, as the GPIO output ability has been disabled during initialize pcnt peripheral
ledc_set_pin(PULSE_IO, TEST_SPEED_MODE, LEDC_CHANNEL_0);
count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, count);
tear_testbench();
@@ -1,99 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "test_ledc_utils.h"
#include "esp_sleep.h"
#include "esp_private/sleep_cpu.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h"
#include "soc/ledc_periph.h"
#include "esp_private/sleep_retention.h"
// Note. Test cases in this file cannot run one after another without reset
/**
* @brief Test LEDC can still output PWM signal after light sleep
*
* @param allow_pd Whether to allow powering down the peripheral in light sleep
*/
static void test_ledc_sleep_retention(bool allow_pd)
{
int pulse_count __attribute__((unused)) = 0;
ledc_timer_config_t ledc_time_config = create_default_timer_config();
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
ledc_channel_config_t ledc_ch_config = initialize_channel_config();
ledc_ch_config.sleep_mode = (allow_pd ? LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD : LEDC_SLEEP_MODE_NO_ALIVE_NO_PD);
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
vTaskDelay(50 / portTICK_PERIOD_MS);
#if SOC_PCNT_SUPPORTED
setup_testbench();
pulse_count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, pulse_count);
tear_testbench(); // tear down so that PCNT won't affect TOP PD
#endif
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(true));
#endif
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000));
printf("go to light sleep for 2 seconds\n");
TEST_ESP_OK(esp_light_sleep_start());
printf("Waked up! Let's see if LEDC peripheral can still work...\n");
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(false));
#endif
printf("check if the sleep happened as expected\r\n");
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
#if SOC_PMU_SUPPORTED
// check if the TOP power domain on/off as desired
TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
esp_sleep_set_sleep_context(NULL);
if (allow_pd) {
// check if the RO duty_r register field get synced back
TEST_ASSERT_EQUAL(4000, ledc_get_duty(TEST_SPEED_MODE, LEDC_CHANNEL_0));
}
#if SOC_PCNT_SUPPORTED
setup_testbench();
pulse_count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, pulse_count);
tear_testbench();
#endif
}
TEST_CASE("ledc can output after light sleep (LEDC power domain xpd)", "[ledc]")
{
test_ledc_sleep_retention(false);
}
#if SOC_LEDC_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
TEST_CASE("ledc can output after light sleep (LEDC power domain pd)", "[ledc]")
{
// test retention feature
test_ledc_sleep_retention(true);
// ledc driver does not have channel release, we will do retention release here to avoid memory leak
sleep_retention_module_t module = ledc_reg_retention_info.module_id;
sleep_retention_module_free(module);
sleep_retention_module_deinit(module);
}
#endif
@@ -1,84 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "unity.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "test_ledc_utils.h"
#include "soc/soc_caps.h"
ledc_channel_config_t initialize_channel_config(void)
{
ledc_channel_config_t config;
memset(&config, 0, sizeof(ledc_channel_config_t));
config.gpio_num = PULSE_IO;
config.speed_mode = TEST_SPEED_MODE;
config.channel = LEDC_CHANNEL_0;
config.intr_type = LEDC_INTR_DISABLE;
config.timer_sel = LEDC_TIMER_0;
config.duty = 4000;
config.hpoint = 0;
return config;
}
ledc_timer_config_t create_default_timer_config(void)
{
ledc_timer_config_t ledc_time_config;
memset(&ledc_time_config, 0, sizeof(ledc_timer_config_t));
ledc_time_config.speed_mode = TEST_SPEED_MODE;
ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT;
ledc_time_config.timer_num = LEDC_TIMER_0;
ledc_time_config.freq_hz = TEST_PWM_FREQ;
ledc_time_config.clk_cfg = TEST_DEFAULT_CLK_CFG;
return ledc_time_config;
}
// use PCNT to test the waveform of LEDC
#if SOC_PCNT_SUPPORTED
#include "driver/pulse_cnt.h"
#define HIGHEST_LIMIT 10000
#define LOWEST_LIMIT -10000
static pcnt_unit_handle_t pcnt_unit;
static pcnt_channel_handle_t pcnt_chan;
void setup_testbench(void)
{
pcnt_unit_config_t unit_config = {
.high_limit = HIGHEST_LIMIT,
.low_limit = LOWEST_LIMIT,
};
TEST_ESP_OK(pcnt_new_unit(&unit_config, &pcnt_unit));
pcnt_chan_config_t chan_config = {
.edge_gpio_num = PULSE_IO,
.level_gpio_num = -1,
};
TEST_ESP_OK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit));
}
void tear_testbench(void)
{
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit));
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
TEST_ESP_OK(pcnt_del_unit(pcnt_unit));
}
int wave_count(int last_time)
{
int test_counter = 0;
TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit));
TEST_ESP_OK(pcnt_unit_start(pcnt_unit));
vTaskDelay(pdMS_TO_TICKS(last_time));
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &test_counter));
return test_counter;
}
#endif
@@ -1,60 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "soc/soc_caps.h"
#include "driver/ledc.h"
#define PULSE_IO 5
#define TEST_PWM_FREQ 2000
#if SOC_LEDC_SUPPORT_HS_MODE
#define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE
#define SPEED_MODE_LIST {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}
#else
#define TEST_SPEED_MODE LEDC_LOW_SPEED_MODE
#define SPEED_MODE_LIST {LEDC_LOW_SPEED_MODE}
#endif
#if SOC_LEDC_SUPPORT_APB_CLOCK
#define TEST_DEFAULT_CLK_CFG LEDC_USE_APB_CLK
#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
#if SOC_CLK_TREE_SUPPORTED
#define TEST_DEFAULT_CLK_CFG LEDC_USE_PLL_DIV_CLK
#else
#define TEST_DEFAULT_CLK_CFG LEDC_USE_XTAL_CLK
#endif
#endif
/**
* Initialize a LEDC channel config structure
*/
ledc_channel_config_t initialize_channel_config(void);
/**
* Initialize a LEDC timer config structure
*/
ledc_timer_config_t create_default_timer_config(void);
#if SOC_PCNT_SUPPORTED
/**
* Setup PCNT test bench
*/
void setup_testbench(void);
/**
* Tear down PCNT test bench
*/
void tear_testbench(void);
/**
* Use PCNT to count pulse
*
* @param last_time Duration time in ms
* @return Pulse count
*/
int wave_count(int last_time);
#endif
@@ -1,6 +1,5 @@
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
@@ -2,5 +2,3 @@ CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT_INIT=n
# Disable memory protection, because "LEDC continue work after software reset" test case requires a cpu reset
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
# primitives for checking sleep internal state
CONFIG_ESP_SLEEP_DEBUG=y
@@ -41,9 +41,6 @@ typedef struct {
i.e. high level of valid gpio to enable the clock output, low to disable */
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
uint32_t io_no_init: 1 __attribute__((deprecated)); /*!< Deprecated. Driver won't change the GPIO configuration in inilization. */
uint32_t allow_pd: 1; /*!< Set to allow power down. When this flag set, the driver will backup/restore the PARLIO registers before/after entering/exist sleep mode.
By this approach, the system can power off PARLIO's power domain.
This can save power, but at the expense of more RAM being consumed. */
} flags; /*!< RX driver flags */
} parlio_rx_unit_config_t;
@@ -40,9 +40,6 @@ typedef struct {
the output clock will be controlled by the MSB bit of the data bus,
i.e. by data_gpio_nums[PARLIO_TX_UNIT_MAX_DATA_WIDTH-1]. High level to enable the clock output, low to disable */
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
uint32_t allow_pd: 1; /*!< Set to allow power down. When this flag set, the driver will backup/restore the PARLIO registers before/after entering/exist sleep mode.
By this approach, the system can power off PARLIO's power domain.
This can save power, but at the expense of more RAM being consumed. */
} flags; /*!< Extra configuration flags */
} parlio_tx_unit_config_t;
@@ -18,7 +18,6 @@
#include "soc/parlio_periph.h"
#include "hal/parlio_ll.h"
#include "esp_private/esp_clk.h"
#include "esp_private/sleep_retention.h"
#include "parlio_private.h"
static const char *TAG = "parlio";
@@ -47,23 +46,6 @@ parlio_group_t *parlio_acquire_group_handle(int group_id)
parlio_ll_enable_bus_clock(group_id, true);
parlio_ll_reset_register(group_id);
}
#if PARLIO_USE_RETENTION_LINK
sleep_retention_module_t module_id = parlio_reg_retention_info[group_id].retention_module;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = parlio_create_sleep_retention_link_cb,
.arg = group,
},
},
.depends = SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM
};
// we only do retention init here. Allocate retention module in the unit initialization
if (sleep_retention_module_init(module_id, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, PARLIO driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id);
}
#endif // PARLIO_USE_RETENTION_LINK
// hal layer initialize
parlio_hal_init(&group->hal);
group->dma_align = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
@@ -105,16 +87,6 @@ void parlio_release_group_handle(parlio_group_t *group)
_lock_release(&s_platform.mutex);
if (do_deinitialize) {
#if PARLIO_USE_RETENTION_LINK
const periph_retention_module_t module_id = parlio_reg_retention_info[group_id].retention_module;
if (sleep_retention_get_created_modules() & BIT(module_id)) {
assert(sleep_retention_get_inited_modules() & BIT(module_id));
sleep_retention_module_free(module_id);
}
if (sleep_retention_get_inited_modules() & BIT(module_id)) {
sleep_retention_module_deinit(module_id);
}
#endif // PARLIO_USE_RETENTION_LINK
free(group);
ESP_LOGD(TAG, "del group(%d)", group_id);
}
@@ -175,32 +147,3 @@ void parlio_unregister_unit_from_group(parlio_unit_base_handle_t unit)
/* the parlio unit has a reference of the group, release it now */
parlio_release_group_handle(group);
}
#if PARLIO_USE_RETENTION_LINK
esp_err_t parlio_create_sleep_retention_link_cb(void *arg)
{
parlio_group_t *group = (parlio_group_t *)arg;
int group_id = group->group_id;
sleep_retention_module_t module_id = parlio_reg_retention_info[group_id].retention_module;
esp_err_t err = sleep_retention_entries_create(parlio_reg_retention_info[group_id].regdma_entry_array,
parlio_reg_retention_info[group_id].array_size,
REGDMA_LINK_PRI_PARLIO, module_id);
ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed");
return ESP_OK;
}
void parlio_create_retention_module(parlio_group_t *group)
{
int group_id = group->group_id;
sleep_retention_module_t module_id = parlio_reg_retention_info[group_id].retention_module;
_lock_acquire(&s_platform.mutex);
if ((sleep_retention_get_inited_modules() & BIT(module_id)) && !(sleep_retention_get_created_modules() & BIT(module_id))) {
if (sleep_retention_module_allocate(module_id) != ESP_OK) {
// even though the sleep retention module create failed, PARLIO driver should still work, so just warning here
ESP_LOGW(TAG, "create retention module failed, power domain can't turn off");
}
}
_lock_release(&s_platform.mutex);
}
#endif // PARLIO_USE_RETENTION_LINK
@@ -24,7 +24,6 @@
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_gpio_reserve.h"
#include "esp_private/gpio.h"
#include "esp_private/sleep_retention.h"
#if CONFIG_PARLIO_ISR_IRAM_SAFE
#define PARLIO_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
@@ -45,9 +44,6 @@
#define PARLIO_INTR_ALLOC_FLAG (ESP_INTR_FLAG_LOWMED | PARLIO_INTR_ALLOC_FLAG_SHARED)
#endif
// Use retention link only when the target supports sleep retention is enabled
#define PARLIO_USE_RETENTION_LINK (SOC_PARLIO_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
#if defined(SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS) // Parlio uses GDMA
#if defined(SOC_GDMA_BUS_AHB) && (SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS == SOC_GDMA_BUS_AHB)
typedef dma_descriptor_align4_t parlio_dma_desc_t;
@@ -153,11 +149,6 @@ esp_err_t parlio_register_unit_to_group(parlio_unit_base_handle_t unit);
*/
void parlio_unregister_unit_from_group(parlio_unit_base_handle_t unit);
#if PARLIO_USE_RETENTION_LINK
esp_err_t parlio_create_sleep_retention_link_cb(void *arg);
void parlio_create_retention_module(parlio_group_t *group);
#endif
#ifdef __cplusplus
}
#endif
@@ -620,10 +620,6 @@ esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_un
esp_err_t ret = ESP_OK;
parlio_rx_unit_handle_t unit = NULL;
#if !SOC_PARLIO_SUPPORT_SLEEP_RETENTION
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
#endif // SOC_PARLIO_SUPPORT_SLEEP_RETENTION
/* Allocate unit memory */
unit = heap_caps_calloc(1, sizeof(parlio_rx_unit_t), PARLIO_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, TAG, "no memory for rx unit");
@@ -680,12 +676,6 @@ esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_un
}
#endif // SOC_PARLIO_RX_CLK_SUPPORT_GATING
#if PARLIO_USE_RETENTION_LINK
if (config->flags.allow_pd != 0) {
parlio_create_retention_module(group);
}
#endif // PARLIO_USE_RETENTION_LINK
/* return RX unit handle */
*ret_unit = unit;
+7 -21
View File
@@ -270,7 +270,7 @@ static esp_err_t parlio_select_periph_clock(parlio_tx_unit_t *tx_unit, const par
#endif
esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true);
PARLIO_CLOCK_SRC_ATOMIC() {
// turn on the tx module clock to sync the clock divider configuration because of the CDC (Cross Domain Crossing)
// turn on the tx module clock to sync the register configuration to the module
parlio_ll_tx_enable_clock(hal->regs, true);
parlio_ll_tx_set_clock_source(hal->regs, clk_src);
// set clock division
@@ -309,10 +309,6 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un
ESP_RETURN_ON_FALSE(config->flags.clk_gate_en == 0, ESP_ERR_NOT_SUPPORTED, TAG, "clock gating is not supported");
#endif // SOC_PARLIO_TX_CLK_SUPPORT_GATING
#if !SOC_PARLIO_SUPPORT_SLEEP_RETENTION
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
#endif // SOC_PARLIO_SUPPORT_SLEEP_RETENTION
// malloc unit memory
uint32_t mem_caps = PARLIO_MEM_ALLOC_CAPS;
unit = heap_caps_calloc(1, sizeof(parlio_tx_unit_t) + sizeof(parlio_tx_trans_desc_t) * config->trans_queue_depth, mem_caps);
@@ -385,12 +381,6 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un
// GPIO Matrix/MUX configuration
ESP_GOTO_ON_ERROR(parlio_tx_unit_configure_gpio(unit, config), err, TAG, "configure gpio failed");
#if PARLIO_USE_RETENTION_LINK
if (config->flags.allow_pd != 0) {
parlio_create_retention_module(group);
}
#endif // PARLIO_USE_RETENTION_LINK
portMUX_INITIALIZE(&unit->spinlock);
atomic_init(&unit->fsm, PARLIO_TX_FSM_INIT);
// return TX unit handle
@@ -478,11 +468,13 @@ static void IRAM_ATTR parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio
while (parlio_ll_tx_is_ready(hal->regs) == false);
// turn on the core clock after we start the TX unit
parlio_ll_tx_start(hal->regs, true);
PARLIO_CLOCK_SRC_ATOMIC() {
parlio_ll_tx_enable_clock(hal->regs, true);
}
}
esp_err_t parlio_tx_unit_enable(parlio_tx_unit_handle_t tx_unit)
{
parlio_hal_context_t *hal = &tx_unit->base.group->hal;
ESP_RETURN_ON_FALSE(tx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
parlio_tx_fsm_t expected_fsm = PARLIO_TX_FSM_INIT;
if (atomic_compare_exchange_strong(&tx_unit->fsm, &expected_fsm, PARLIO_TX_FSM_ENABLE_WAIT)) {
@@ -497,11 +489,6 @@ esp_err_t parlio_tx_unit_enable(parlio_tx_unit_handle_t tx_unit)
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_STATE, TAG, "unit not in init state");
}
// enable clock output
PARLIO_CLOCK_SRC_ATOMIC() {
parlio_ll_tx_enable_clock(hal->regs, true);
}
// check if we need to start one pending transaction
parlio_tx_trans_desc_t *t = NULL;
expected_fsm = PARLIO_TX_FSM_ENABLE;
@@ -544,10 +531,6 @@ esp_err_t parlio_tx_unit_disable(parlio_tx_unit_handle_t tx_unit)
// stop the TX engine
parlio_hal_context_t *hal = &tx_unit->base.group->hal;
// disable clock output
PARLIO_CLOCK_SRC_ATOMIC() {
parlio_ll_tx_enable_clock(hal->regs, false);
}
gdma_stop(tx_unit->dma_chan);
parlio_ll_tx_start(hal->regs, false);
parlio_ll_enable_interrupt(hal->regs, PARLIO_LL_EVENT_TX_EOF, false);
@@ -638,6 +621,9 @@ static void IRAM_ATTR parlio_tx_default_isr(void *args)
if (status & PARLIO_LL_EVENT_TX_EOF) {
parlio_ll_clear_interrupt_status(hal->regs, PARLIO_LL_EVENT_TX_EOF);
PARLIO_CLOCK_SRC_ATOMIC() {
parlio_ll_tx_enable_clock(hal->regs, false);
}
parlio_ll_tx_start(hal->regs, false);
parlio_tx_trans_desc_t *trans_desc = NULL;
@@ -7,10 +7,6 @@ if(CONFIG_PARLIO_ISR_IRAM_SAFE)
list(REMOVE_ITEM srcs "test_parlio_rx.c")
endif()
if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED AND CONFIG_PM_ENABLE)
list(APPEND srcs "test_parlio_sleep.c")
endif()
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
@@ -56,14 +56,14 @@ extern "C" {
#elif CONFIG_IDF_TARGET_ESP32P4
#define TEST_CLK_GPIO 33
#define TEST_VALID_GPIO 36
#define TEST_DATA0_GPIO 0
#define TEST_DATA1_GPIO 1
#define TEST_DATA2_GPIO 2
#define TEST_DATA3_GPIO 3
#define TEST_DATA4_GPIO 4
#define TEST_DATA5_GPIO 5
#define TEST_DATA6_GPIO 6
#define TEST_DATA7_GPIO 7
#define TEST_DATA0_GPIO 20
#define TEST_DATA1_GPIO 21
#define TEST_DATA2_GPIO 22
#define TEST_DATA3_GPIO 23
#define TEST_DATA4_GPIO 45
#define TEST_DATA5_GPIO 46
#define TEST_DATA6_GPIO 47
#define TEST_DATA7_GPIO 48
#else
#error "Unsupported target"
#endif
@@ -368,7 +368,7 @@ TEST_CASE("parallel_rx_unit_pulse_delimiter_test_via_i2s", "[parlio_rx]")
{
parlio_rx_pulse_delimiter_config_t pls_deli_cfg = {
.valid_sig_line_id = TEST_VALID_SIG,
.sample_edge = PARLIO_SAMPLE_EDGE_NEG,
.sample_edge = PARLIO_SAMPLE_EDGE_POS,
.bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB,
.eof_data_len = TEST_EOF_DATA_LEN,
.timeout_ticks = 0,
@@ -1,168 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "driver/parlio_tx.h"
#include "driver/parlio_rx.h"
#include "driver/gpio.h"
#include "soc/soc_caps.h"
#include "soc/parl_io_struct.h"
#include "esp_private/sleep_cpu.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h"
#include "esp_attr.h"
#include "test_board.h"
TEST_PARLIO_CALLBACK_ATTR
static bool test_parlio_rx_done_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_ctx)
{
BaseType_t high_task_wakeup = pdFALSE;
TaskHandle_t task = (TaskHandle_t)user_ctx;
vTaskNotifyGiveFromISR(task, &high_task_wakeup);
return high_task_wakeup == pdTRUE;
}
#define TEST_PAYLOAD_SIZE 64
static void test_parlio_sleep_retention(bool allow_pd)
{
printf("install parlio tx unit\r\n");
parlio_tx_unit_handle_t tx_unit = NULL;
parlio_tx_unit_config_t tx_config = {
.clk_src = PARLIO_CLK_SRC_DEFAULT,
.data_width = 4,
.clk_in_gpio_num = -1, // use internal clock source
.valid_gpio_num = TEST_VALID_GPIO,
.clk_out_gpio_num = TEST_CLK_GPIO,
.data_gpio_nums = {
TEST_DATA0_GPIO,
TEST_DATA1_GPIO,
TEST_DATA2_GPIO,
TEST_DATA3_GPIO,
},
.output_clk_freq_hz = 1 * 1000 * 1000,
.trans_queue_depth = 8,
.max_transfer_size = 128,
.bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB,
.sample_edge = PARLIO_SAMPLE_EDGE_POS,
.flags.allow_pd = allow_pd,
};
TEST_ESP_OK(parlio_new_tx_unit(&tx_config, &tx_unit));
printf("send packets and check event is fired\r\n");
parlio_transmit_config_t transmit_config = {
.idle_value = 0x00,
};
uint8_t tx_payload[TEST_PAYLOAD_SIZE] = {0};
for (int i = 0; i < TEST_PAYLOAD_SIZE; i++) {
tx_payload[i] = i;
}
printf("install parlio rx unit\r\n");
parlio_rx_unit_handle_t rx_unit = NULL;
parlio_rx_delimiter_handle_t deli = NULL;
parlio_rx_unit_config_t rx_config = {
.trans_queue_depth = 10,
.max_recv_size = 1024,
.data_width = 4,
.clk_src = PARLIO_CLK_SRC_DEFAULT,
.ext_clk_freq_hz = 0,
.clk_in_gpio_num = -1,
.exp_clk_freq_hz = 1 * 1000 * 1000,
.clk_out_gpio_num = -1,
.valid_gpio_num = TEST_VALID_GPIO,
.data_gpio_nums = {
TEST_DATA0_GPIO,
TEST_DATA1_GPIO,
TEST_DATA2_GPIO,
TEST_DATA3_GPIO,
},
.flags = {
.clk_gate_en = false,
.allow_pd = allow_pd,
}
};
rx_config.flags.free_clk = 1;
TEST_ESP_OK(parlio_new_rx_unit(&rx_config, &rx_unit));
parlio_rx_level_delimiter_config_t lvl_deli_cfg = {
.valid_sig_line_id = PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1,
.sample_edge = PARLIO_SAMPLE_EDGE_POS,
.bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB,
.eof_data_len = TEST_PAYLOAD_SIZE,
.timeout_ticks = 0,
.flags = {
.active_low_en = 0,
},
};
TEST_ESP_OK(parlio_new_rx_level_delimiter(&lvl_deli_cfg, &deli));
printf("register receive_done event callback\r\n");
parlio_rx_event_callbacks_t rx_cbs = {
.on_receive_done = test_parlio_rx_done_callback,
};
TEST_ESP_OK(parlio_rx_unit_register_event_callbacks(rx_unit, &rx_cbs, xTaskGetCurrentTaskHandle()));
parlio_receive_config_t recv_config = {
.delimiter = deli,
.flags.partial_rx_en = false,
};
__attribute__((aligned(TEST_PAYLOAD_SIZE))) uint8_t rx_payload[TEST_PAYLOAD_SIZE] = {0};
// go to sleep
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
printf("go to light sleep for 2 seconds\r\n");
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(true));
#endif
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000));
TEST_ESP_OK(esp_light_sleep_start());
printf("Waked up! Let's see if PARLIO driver can still work...\r\n");
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(false));
#endif
printf("check if the sleep happened as expected\r\n");
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
#if SOC_PARLIO_SUPPORT_SLEEP_RETENTION
// check if the power domain also is powered down
TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
esp_sleep_set_sleep_context(NULL);
printf("Testing tx and rx after sleep...\n");
TEST_ESP_OK(parlio_tx_unit_enable(tx_unit));
TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, 1));
TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, rx_payload, TEST_PAYLOAD_SIZE, &recv_config));
TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, tx_payload, TEST_PAYLOAD_SIZE * sizeof(uint8_t) * 8, &transmit_config));
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)));
for (int i = 0; i < TEST_PAYLOAD_SIZE; i++) {
printf("%.2d ", (rx_payload[i]));
TEST_ASSERT_EQUAL(tx_payload[i], rx_payload[i]);
if ((i + 1) % 16 == 0) {
printf("\n");
}
}
TEST_ESP_OK(parlio_tx_unit_disable(tx_unit));
TEST_ESP_OK(parlio_del_tx_unit(tx_unit));
TEST_ESP_OK(parlio_rx_unit_disable(rx_unit));
TEST_ESP_OK(parlio_del_rx_delimiter(deli));
TEST_ESP_OK(parlio_del_rx_unit(rx_unit));
}
TEST_CASE("parlio light sleep", "[parlio]")
{
test_parlio_sleep_retention(false);
#if SOC_PARLIO_SUPPORT_SLEEP_RETENTION
test_parlio_sleep_retention(true);
#endif
}
@@ -1,6 +1,5 @@
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
@@ -3,6 +3,3 @@
#
CONFIG_ESP_TASK_WDT_INIT=n
CONFIG_FREERTOS_HZ=1000
# primitives for checking sleep internal state
CONFIG_ESP_SLEEP_DEBUG=y
+2 -8
View File
@@ -234,22 +234,16 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf
.color_type_id = config->in_bg.blend_cm,
};
uint32_t in_bg_pixel_depth = color_hal_pixel_format_get_bit_depth(in_bg_pixel_format); // bits
// Usually C2M can let the msync do alignment internally, however, it only do L1-cacheline-size alignment for L1->L2, and then L2-cacheline-size alignment for L2->mem
// While M2C direction manual alignment is L2-cacheline-size alignment for mem->L2->L1
// Mismatching writeback and invalidate data size could cause synchronization error if in_bg/fg_buffer and out_buffer are the same one
uint32_t in_bg_ext_window = (uint32_t)config->in_bg.buffer + config->in_bg.block_offset_y * config->in_bg.pic_w * in_bg_pixel_depth / 8;
uint32_t in_bg_ext_window_aligned = PPA_ALIGN_DOWN(in_bg_ext_window, buf_alignment_size);
uint32_t in_bg_ext_window_len = config->in_bg.pic_w * config->in_bg.block_h * in_bg_pixel_depth / 8;
esp_cache_msync((void *)in_bg_ext_window_aligned, PPA_ALIGN_UP(in_bg_ext_window_len + (in_bg_ext_window - in_bg_ext_window_aligned), buf_alignment_size), ESP_CACHE_MSYNC_FLAG_DIR_C2M);
esp_cache_msync((void *)in_bg_ext_window, in_bg_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
color_space_pixel_format_t in_fg_pixel_format = {
.color_type_id = config->in_fg.blend_cm,
};
uint32_t in_fg_pixel_depth = color_hal_pixel_format_get_bit_depth(in_fg_pixel_format); // bits
uint32_t in_fg_ext_window = (uint32_t)config->in_fg.buffer + config->in_fg.block_offset_y * config->in_fg.pic_w * in_fg_pixel_depth / 8;
// Same for fg_buffer msync, do manual alignment
uint32_t in_fg_ext_window_aligned = PPA_ALIGN_DOWN(in_fg_ext_window, buf_alignment_size);
uint32_t in_fg_ext_window_len = config->in_fg.pic_w * config->in_fg.block_h * in_fg_pixel_depth / 8;
esp_cache_msync((void *)in_fg_ext_window_aligned, PPA_ALIGN_UP(in_fg_ext_window_len + (in_fg_ext_window - in_fg_ext_window_aligned), buf_alignment_size), ESP_CACHE_MSYNC_FLAG_DIR_C2M);
esp_cache_msync((void *)in_fg_ext_window, in_fg_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
// Invalidate out_buffer extended window (alignment strict on M2C direction)
uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8;
uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size);
+5 -9
View File
@@ -194,17 +194,14 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
config->out.block_offset_x % 2 == 0 && config->out.block_offset_y % 2 == 0,
ESP_ERR_INVALID_ARG, TAG, "YUV420 output does not support odd h/w/offset_x/offset_y");
}
ESP_RETURN_ON_FALSE(config->in.block_w <= (config->in.pic_w - config->in.block_offset_x) &&
config->in.block_h <= (config->in.pic_h - config->in.block_offset_y),
ESP_ERR_INVALID_ARG, TAG, "in.block_w/h + in.block_offset_x/y does not fit in the in pic");
color_space_pixel_format_t out_pixel_format = {
.color_type_id = config->out.srm_cm,
};
uint32_t out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format); // bits
uint32_t out_pic_len = config->out.pic_w * config->out.pic_h * out_pixel_depth / 8;
ESP_RETURN_ON_FALSE(out_pic_len <= config->out.buffer_size, ESP_ERR_INVALID_ARG, TAG, "out.pic_w/h mismatch with out.buffer_size");
ESP_RETURN_ON_FALSE(config->scale_x < PPA_LL_SRM_SCALING_INT_MAX && config->scale_x >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX) &&
config->scale_y < PPA_LL_SRM_SCALING_INT_MAX && config->scale_y >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX),
ESP_RETURN_ON_FALSE(config->scale_x < (PPA_LL_SRM_SCALING_INT_MAX + 1) && config->scale_x >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX) &&
config->scale_y < (PPA_LL_SRM_SCALING_INT_MAX + 1) && config->scale_y >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX),
ESP_ERR_INVALID_ARG, TAG, "invalid scale");
uint32_t new_block_w = 0;
uint32_t new_block_h = 0;
@@ -246,8 +243,7 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
// Invalidate out_buffer extended window (alignment strict on M2C direction)
uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8;
uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size);
uint32_t out_ext_window_len = config->out.pic_w * new_block_h * out_pixel_depth / 8; // actual ext_window_len must be less than or equal to this, since actual block_h <= new_block_h (may round down)
assert(out_ext_window + out_ext_window_len <= (uint32_t)config->out.buffer + config->out.buffer_size);
uint32_t out_ext_window_len = config->out.pic_w * config->in.block_h * out_pixel_depth / 8;
esp_cache_msync((void *)out_ext_window_aligned, PPA_ALIGN_UP(out_ext_window_len + (out_ext_window - out_ext_window_aligned), buf_alignment_size), ESP_CACHE_MSYNC_FLAG_DIR_M2C);
esp_err_t ret = ESP_OK;
@@ -260,9 +256,9 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
ppa_srm_oper_t *srm_trans_desc = (ppa_srm_oper_t *)trans_on_picked_desc->srm_desc;
memcpy(srm_trans_desc, config, sizeof(ppa_srm_oper_config_t));
srm_trans_desc->scale_x_int = (uint32_t)srm_trans_desc->scale_x;
srm_trans_desc->scale_x_frag = (uint32_t)(srm_trans_desc->scale_x * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1);
srm_trans_desc->scale_x_frag = (uint32_t)(srm_trans_desc->scale_x * (PPA_LL_SRM_SCALING_FRAG_MAX + 1)) & PPA_LL_SRM_SCALING_FRAG_MAX;
srm_trans_desc->scale_y_int = (uint32_t)srm_trans_desc->scale_y;
srm_trans_desc->scale_y_frag = (uint32_t)(srm_trans_desc->scale_y * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1);
srm_trans_desc->scale_y_frag = (uint32_t)(srm_trans_desc->scale_y * (PPA_LL_SRM_SCALING_FRAG_MAX + 1)) & PPA_LL_SRM_SCALING_FRAG_MAX;
srm_trans_desc->alpha_value = new_alpha_value;
srm_trans_desc->data_burst_length = ppa_client->data_burst_length;
+10 -8
View File
@@ -29,7 +29,6 @@
#include "soc/sdm_periph.h"
#include "esp_private/esp_clk.h"
#include "esp_private/io_mux.h"
#include "esp_private/gpio.h"
#if CONFIG_SDM_CTRL_FUNC_IN_IRAM
#define SDM_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
@@ -230,12 +229,16 @@ esp_err_t sdm_new_channel(const sdm_config_t *config, sdm_channel_handle_t *ret_
// SDM clock comes from IO MUX, but IO MUX clock might be shared with other submodules as well
ESP_GOTO_ON_ERROR(io_mux_set_clock_source((soc_module_clk_t)(group->clk_src)), err, TAG, "set IO MUX clock source failed");
gpio_func_sel(config->gpio_num, PIN_FUNC_GPIO);
// deprecated, to be removed in in esp-idf v6.0
if (config->flags.io_loop_back) {
gpio_input_enable(config->gpio_num);
}
// connect the signal to the GPIO by matrix, it will also enable the output path properly
// GPIO configuration
gpio_config_t gpio_conf = {
.intr_type = GPIO_INTR_DISABLE,
// also enable the input path is `io_loop_back` is on, this is useful for debug
.mode = GPIO_MODE_OUTPUT | (config->flags.io_loop_back ? GPIO_MODE_INPUT : 0),
.pull_down_en = false,
.pull_up_en = true,
.pin_bit_mask = 1ULL << config->gpio_num,
};
ESP_GOTO_ON_ERROR(gpio_config(&gpio_conf), err, TAG, "config GPIO failed");
esp_rom_gpio_connect_out_signal(config->gpio_num, sigma_delta_periph_signals.channels[chan_id].sd_sig, config->flags.invert_out, false);
chan->gpio_num = config->gpio_num;
@@ -280,7 +283,6 @@ esp_err_t sdm_del_channel(sdm_channel_handle_t chan)
sdm_group_t *group = chan->group;
int group_id = group->group_id;
int chan_id = chan->chan_id;
gpio_output_disable(chan->gpio_num);
ESP_LOGD(TAG, "del channel (%d,%d)", group_id, chan_id);
// recycle memory resource
ESP_RETURN_ON_ERROR(sdm_destroy(chan), TAG, "destroy channel failed");
@@ -4,7 +4,6 @@ import pytest
from pytest_embedded_idf import IdfDut
@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C5 C61 GPSPI same, so testing on C5 is enough')
@pytest.mark.esp32
@pytest.mark.esp32s3
@pytest.mark.esp32c3
@@ -64,7 +64,6 @@ extern "C"
#define SPICOMMON_BUSFLAG_IO4_IO7 (1<<8) ///< Check existing of IO4~IO7 pins. Or indicates IO4~IO7 pins initialized.
#define SPICOMMON_BUSFLAG_OCTAL (SPICOMMON_BUSFLAG_QUAD|SPICOMMON_BUSFLAG_IO4_IO7) ///< Check existing of MOSI/MISO/WP/HD/SPIIO4/SPIIO5/SPIIO6/SPIIO7 pins as output. Or indicates bus able to work under octal mode.
#define SPICOMMON_BUSFLAG_NATIVE_PINS SPICOMMON_BUSFLAG_IOMUX_PINS
#define SPICOMMON_BUSFLAG_SLP_ALLOW_PD (1<<9) ///< Allow to power down the peripheral during light sleep, and auto recover then.
/**
* @brief SPI DMA channels
@@ -21,7 +21,6 @@
#include "esp_private/spi_common_internal.h"
#include "esp_private/spi_share_hw_ctrl.h"
#include "esp_private/esp_cache_private.h"
#include "esp_private/sleep_retention.h"
#include "esp_dma_utils.h"
#include "hal/spi_hal.h"
#include "hal/gpio_hal.h"
@@ -50,7 +49,6 @@ static const char *SPI_TAG = "spi";
typedef struct {
int host_id;
_lock_t mutex; // mutex for controller
spi_destroy_func_t destroy_func;
void* destroy_arg;
spi_bus_attr_t bus_attr;
@@ -589,8 +587,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
}
uint32_t missing_flag = flags & ~temp_flag;
missing_flag &= ~SPICOMMON_BUSFLAG_MASTER; //don't check this flag
missing_flag &= ~SPICOMMON_BUSFLAG_SLP_ALLOW_PD;
missing_flag &= ~SPICOMMON_BUSFLAG_MASTER;//don't check this flag
if (missing_flag != 0) {
//check pins existence
@@ -781,16 +778,6 @@ spi_bus_lock_handle_t spi_bus_lock_get_by_id(spi_host_device_t host_id)
return bus_ctx[host_id]->bus_attr.lock;
}
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
static esp_err_t s_bus_create_sleep_retention_cb(void *arg)
{
spicommon_bus_context_t *ctx = arg;
return sleep_retention_entries_create(spi_reg_retention_info[ctx->host_id - 1].entry_array,
spi_reg_retention_info[ctx->host_id - 1].array_size,
REGDMA_LINK_PRI_GPSPI,
spi_reg_retention_info[ctx->host_id - 1].module_id);
}
#endif // SOC_SPI_SUPPORT_SLEEP_RETENTION
//----------------------------------------------------------master bus init-------------------------------------------------------//
esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, spi_dma_chan_t dma_chan)
{
@@ -859,34 +846,6 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
goto cleanup;
}
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = s_bus_create_sleep_retention_cb,
.arg = ctx,
},
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM),
};
_lock_acquire(&ctx->mutex);
if (sleep_retention_module_init(spi_reg_retention_info[host_id - 1].module_id, &init_param) == ESP_OK) {
if ((bus_attr->bus_cfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) && (sleep_retention_module_allocate(spi_reg_retention_info[host_id - 1].module_id) != ESP_OK)) {
// even though the sleep retention create failed, SPI driver should still work, so just warning here
ESP_LOGW(SPI_TAG, "alloc sleep recover failed, peripherals may hold power on");
}
} else {
// even the sleep retention init failed, SPI driver should still work, so just warning here
ESP_LOGW(SPI_TAG, "init sleep recover failed, spi may offline after sleep");
}
_lock_release(&ctx->mutex);
#else
if (bus_attr->bus_cfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) {
ESP_LOGE(SPI_TAG, "power down peripheral in sleep is not enabled or not supported on your target");
}
#endif // SOC_SPI_SUPPORT_SLEEP_RETENTION
#ifdef CONFIG_PM_ENABLE
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_master",
&bus_attr->pm_lock);
@@ -968,24 +927,9 @@ esp_err_t spi_bus_free(spi_host_device_t host_id)
}
spicommon_bus_free_io_cfg(&bus_attr->bus_cfg);
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
const periph_retention_module_t retention_id = spi_reg_retention_info[host_id - 1].module_id;
_lock_acquire(&ctx->mutex);
if (sleep_retention_get_created_modules() & BIT(retention_id)) {
assert(sleep_retention_get_inited_modules() & BIT(retention_id));
sleep_retention_module_free(retention_id);
}
if (sleep_retention_get_inited_modules() & BIT(retention_id)) {
sleep_retention_module_deinit(retention_id);
}
_lock_release(&ctx->mutex);
_lock_close(&ctx->mutex);
#endif
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_delete(bus_attr->pm_lock);
#endif
spi_bus_deinit_lock(bus_attr->lock);
if (ctx->dma_ctx) {
free(ctx->dma_ctx->dmadesc_tx);
@@ -345,7 +345,8 @@ static esp_err_t spi_master_deinit_driver(void* arg)
int host_id = host->id;
SPI_CHECK(is_valid_host(host_id), "invalid host_id", ESP_ERR_INVALID_ARG);
for (int x = 0; x < DEV_NUM_MAX; x++) {
int x;
for (x = 0; x < DEV_NUM_MAX; x++) {
SPI_CHECK(host->device[x] == NULL, "not all CSses freed", ESP_ERR_INVALID_STATE);
}
@@ -8,7 +8,7 @@ set(srcs
# sct test using slave hd APIs, need slave hd support
# tmp skip sct test under iram_safe, both sct and slave hd are not cleaned
if(CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2 AND CONFIG_SOC_SPI_SCT_SUPPORTED AND NOT CONFIG_COMPILER_DUMP_RTL_FILES)
if(CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2 AND NOT CONFIG_COMPILER_DUMP_RTL_FILES)
list(APPEND srcs "test_spi_master_sct.c")
endif()
@@ -19,9 +19,6 @@
#include "esp_private/cache_utils.h"
#include "esp_private/spi_common_internal.h"
#include "esp_private/esp_clk.h"
#include "esp_private/sleep_cpu.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h"
#include "esp_heap_caps.h"
#include "esp_clk_tree.h"
#include "esp_timer.h"
@@ -1791,135 +1788,3 @@ TEST_CASE("test_bus_free_safty_to_remain_devices", "[spi]")
TEST_ESP_OK(spi_bus_remove_device(dev1));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
}
TEST_CASE("test_spi_master_sleep_retention", "[spi]")
{
// Prepare a TOP PD sleep
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000));
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(true));
#endif
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
spi_device_handle_t dev_handle;
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
buscfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
buscfg.flags |= SPICOMMON_BUSFLAG_SLP_ALLOW_PD;
uint8_t send[16] = "hello spi x\n";
uint8_t recv[16];
spi_transaction_t trans_cfg = {
.length = 8 * sizeof(send),
.tx_buffer = send,
.rx_buffer = recv,
};
for (int periph = SPI2_HOST; periph < SPI_HOST_MAX; periph ++) {
for (int test_dma = 0; test_dma <= 1; test_dma ++) {
int use_dma = SPI_DMA_DISABLED;
#if SOC_GDMA_SUPPORT_SLEEP_RETENTION // TODO: IDF-11317 test dma on esp32 and s2
use_dma = test_dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED;
#endif
printf("Retention on GPSPI%d with dma: %d\n", periph + 1, use_dma);
TEST_ESP_OK(spi_bus_initialize(periph, &buscfg, use_dma));
// set spi "self-loop" after bus initialized
spitest_gpio_output_sel(buscfg.miso_io_num, FUNC_GPIO, spi_periph_signal[periph].spid_out);
TEST_ESP_OK(spi_bus_add_device(periph, &devcfg, &dev_handle));
for (uint8_t cnt = 0; cnt < 3; cnt ++) {
printf("Going into sleep...\n");
TEST_ESP_OK(esp_light_sleep_start());
printf("Waked up!\n");
// check if the sleep happened as expected
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// check if the power domain also is powered down
TEST_ASSERT_EQUAL((buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
memset(recv, 0, sizeof(recv));
send[10] = cnt + 'A';
TEST_ESP_OK(spi_device_transmit(dev_handle, &trans_cfg));
printf("%s", recv);
spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, sizeof(send));
}
TEST_ESP_OK(spi_bus_remove_device(dev_handle));
TEST_ESP_OK(spi_bus_free(periph));
}
}
esp_sleep_set_sleep_context(NULL);
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(false));
#endif
}
#if 0 /* Temp disable, TODO: IDFCI-2455*/
#if CONFIG_PM_ENABLE
TEST_CASE("test_spi_master_auto_sleep_retention", "[spi]")
{
// Configure dynamic frequency scaling:
// maximum and minimum frequencies are set in sdkconfig,
// automatic light sleep is enabled if tickless idle support is enabled.
uint32_t xtal_hz = 0;
esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_XTAL, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &xtal_hz);
esp_pm_config_t pm_config = {
.max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ,
.min_freq_mhz = xtal_hz / 1000000,
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
.light_sleep_enable = true,
#endif
};
TEST_ESP_OK(esp_pm_configure(&pm_config));
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
for (uint8_t allow_pd = 0; allow_pd < 2; allow_pd ++) {
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
buscfg.flags = (allow_pd) ? SPICOMMON_BUSFLAG_SLP_ALLOW_PD : 0;
buscfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_DISABLED));
// set spi "self-loop" after bus initialized
spitest_gpio_output_sel(buscfg.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out);
spi_device_handle_t dev_handle;
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev_handle));
uint8_t send[13] = "hello spi 0\n";
uint8_t recv[13];
spi_transaction_t trans_cfg = {
.length = 8 * sizeof(send),
.tx_buffer = send,
.rx_buffer = recv,
};
for (uint8_t cnt = 0; cnt < 3; cnt ++) {
printf("Going into Auto sleep with power %s ...\n", (buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? "down" : "hold");
vTaskDelay(1000); //auto light sleep here
printf("Waked up!\n");
// check if the sleep happened as expected
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// check if the power domain also is powered down
TEST_ASSERT_EQUAL((buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
memset(recv, 0, sizeof(recv));
send[10] = cnt + '0';
TEST_ESP_OK(spi_device_polling_transmit(dev_handle, &trans_cfg));
printf("%s", recv);
spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, sizeof(send));
}
TEST_ESP_OK(spi_bus_remove_device(dev_handle));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
}
esp_sleep_set_sleep_context(NULL);
pm_config.light_sleep_enable = false;
TEST_ESP_OK(esp_pm_configure(&pm_config));
}
#endif //CONFIG_PM_ENABLE
#endif // 0
@@ -15,9 +15,6 @@
#include "esp_heap_caps.h"
#include "driver/spi_master.h"
#include "esp_private/spi_master_internal.h"
#include "esp_private/sleep_cpu.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h"
#include "driver/spi_slave_hd.h"
#include "driver/spi_slave.h"
#include "soc/spi_pins.h"
@@ -25,6 +22,7 @@
__attribute__((unused)) static const char *TAG = "SCT";
#if (SOC_SPI_SUPPORT_SLAVE_HD_VER2 && SOC_SPI_SCT_SUPPORTED)
/*-----------------------------------------------------------
* HD SCT Functional Test
*-----------------------------------------------------------*/
@@ -232,6 +230,7 @@ TEST_CASE_MULTIPLE_DEVICES("SPI_Master_SCT_HD_Functional", "[spi_ms]", hd_master
TEST_CASE("spi_master: test_sct_dma_desc_oob_on_tail", "[spi]")
{
spi_device_handle_t handle;
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
buscfg.max_transfer_sz = 4092 * 8;
@@ -292,127 +291,4 @@ TEST_CASE("spi_master: test_sct_dma_desc_oob_on_tail", "[spi]")
TEST_ESP_OK(spi_bus_free(SPI2_HOST));
}
/*-----------------------------------------------------------
* Sleep Retention Test
*-----------------------------------------------------------*/
#define TEST_SLP_DATA_LEN 64
//Master write, slave read, wrt slave reg
#define TEST_SLP_BUF_ID 12
#define TEST_SLP_BUF_VAL 0x11223344
static void sleep_master(void)
{
// Prepare a TOP PD sleep
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000));
#if ESP_SLEEP_POWER_DOWN_CPU
sleep_cpu_configure(true);
#endif
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
spi_device_handle_t handle;
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
buscfg.max_transfer_sz = 4092 * 10;
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
buscfg.flags |= SPICOMMON_BUSFLAG_SLP_ALLOW_PD;
#endif
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
devcfg.command_bits = 8;
devcfg.address_bits = 8;
devcfg.dummy_bits = 8;
devcfg.flags = SPI_DEVICE_HALFDUPLEX;
TEST_ESP_OK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
TEST_ESP_OK(spi_bus_add_device(SPI2_HOST, &devcfg, &handle));
TEST_ESP_OK(spi_bus_multi_trans_mode_enable(handle, true));
unity_send_signal("Master ready");
//Test data preparation
uint32_t master_tx_val = TEST_SLP_BUF_VAL;
uint8_t *master_tx_buf = heap_caps_calloc(1, TEST_SLP_DATA_LEN, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
test_fill_random_to_buffers_dualboard(199, master_tx_buf, master_tx_buf, TEST_SLP_DATA_LEN);
//---------------------Master TX---------------------------//
spi_multi_transaction_t *ret_seg_trans = NULL;
spi_multi_transaction_t tx_seg_trans[3] = {
{
.base = {
.cmd = 0x1,
.addr = TEST_SLP_BUF_ID,
.length = 4 * 8,
.tx_buffer = (uint8_t *) &master_tx_val,
},
},
{
.base = {
.cmd = 0x3,
.addr = 0xf2,
.length = TEST_SLP_DATA_LEN * 8,
.tx_buffer = master_tx_buf,
},
.dummy_bits = 8,
},
{
.base = {
.cmd = 0x7,
},
},
};
unity_wait_for_signal("Slave ready");
printf("Going into sleep with power down ...\n");
TEST_ESP_OK(esp_light_sleep_start());
printf("Waked up!\n");
// check if the sleep happened as expected
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// check if the power domain also is powered down
TEST_ASSERT_EQUAL((buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
TEST_ESP_OK(spi_device_queue_multi_trans(handle, tx_seg_trans, 3, portMAX_DELAY));
TEST_ESP_OK(spi_device_get_multi_trans_result(handle, &ret_seg_trans, portMAX_DELAY));
TEST_ASSERT(ret_seg_trans == tx_seg_trans);
ESP_LOG_BUFFER_HEX("Master tx", master_tx_buf, TEST_SLP_DATA_LEN);
free(master_tx_buf);
TEST_ESP_OK(spi_bus_multi_trans_mode_enable(handle, false));
TEST_ESP_OK(spi_bus_remove_device(handle));
TEST_ESP_OK(spi_bus_free(SPI2_HOST));
esp_sleep_set_sleep_context(NULL);
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(false));
#endif
}
static void sleep_slave(void)
{
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG();
slave_hd_cfg.dma_chan = SPI_DMA_CH_AUTO,
TEST_ESP_OK(spi_slave_hd_init(SPI2_HOST, &buscfg, &slave_hd_cfg));
//Test data preparation
uint32_t slave_rx_val = 0;
uint8_t *slave_rx_buf = heap_caps_calloc(1, TEST_SLP_DATA_LEN, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *master_tx_buf = heap_caps_calloc(1, TEST_SLP_DATA_LEN, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
test_fill_random_to_buffers_dualboard(199, master_tx_buf, master_tx_buf, TEST_SLP_DATA_LEN);
//---------------------Slave RX---------------------------//
spi_slave_hd_data_t *ret_trans = NULL;
spi_slave_hd_data_t slave_rx_trans = {
.data = slave_rx_buf,
.len = TEST_SLP_DATA_LEN,
};
unity_wait_for_signal("Master ready");
TEST_ESP_OK(spi_slave_hd_queue_trans(SPI2_HOST, SPI_SLAVE_CHAN_RX, &slave_rx_trans, portMAX_DELAY));
unity_send_signal("Slave ready");
TEST_ESP_OK(spi_slave_hd_get_trans_res(SPI2_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY));
TEST_ASSERT(ret_trans == &slave_rx_trans);
spitest_cmp_or_dump(master_tx_buf, slave_rx_buf, TEST_SLP_DATA_LEN);
spi_slave_hd_read_buffer(SPI2_HOST, TEST_SLP_BUF_ID, (uint8_t *)&slave_rx_val, 4);
ESP_LOGI("Slave", "Slave Reg[%d] value is: 0x%" PRIx32, TEST_SLP_BUF_ID, slave_rx_val);
TEST_ASSERT(slave_rx_val == TEST_SLP_BUF_VAL);
free(master_tx_buf);
free(slave_rx_buf);
TEST_ESP_OK(spi_slave_hd_deinit(SPI2_HOST));
}
TEST_CASE_MULTIPLE_DEVICES("test_spi_master_sct_sleep_retention", "[spi_ms]", sleep_master, sleep_slave);
#endif //#if (SOC_SPI_SUPPORT_SLAVE_HD_VER2 && SOC_SPI_SCT_SUPPORTED)
@@ -0,0 +1,2 @@
# don't delete.
# used for CI to compile a default config when 'sdkconfig.ci.xxxx' is exist
@@ -1,3 +1 @@
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE=y
@@ -1,4 +1,3 @@
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
@@ -1,4 +1,2 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT_INIT=n
# primitives for checking sleep internal state
CONFIG_ESP_SLEEP_DEBUG=y
CONFIG_ESP_TASK_WDT=n
@@ -47,9 +47,9 @@ typedef struct {
#endif
};
struct {
uint32_t allow_pd: 1; /*!< If set, driver allows the power domain to be powered off when system enters sleep mode.
This can save power, but at the expense of more RAM being consumed to save register context. */
uint32_t backup_before_sleep: 1; /*!< @deprecated, same meaning as allow_pd */
uint32_t backup_before_sleep: 1; /*!< If set, the driver will backup/restore the HP UART registers before entering/after exiting sleep mode.
By this approach, the system can power off HP UART's power domain.
This can save power, but at the expense of more RAM being consumed */
} flags; /*!< Configuration flags */
} uart_config_t;
+8 -9
View File
@@ -221,7 +221,7 @@ static void uart_module_enable(uart_port_t uart_num)
// Initialize sleep retention module for HP UART
if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { // Console uart retention has been taken care in sleep_sys_periph_stdout_console_uart_retention_init
assert(!uart_context[uart_num].retention_link_inited);
sleep_retention_module_t module = uart_reg_retention_info[uart_num].module;
sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num);
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
@@ -260,7 +260,7 @@ static void uart_module_disable(uart_port_t uart_num)
if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM && uart_num < SOC_UART_HP_NUM) {
#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// Uninitialize sleep retention module for HP UART
sleep_retention_module_t module = uart_reg_retention_info[uart_num].module;
sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num);
assert(!uart_context[uart_num].retention_link_created); // HP UART sleep retention should have been freed at this moment
if (uart_context[uart_num].retention_link_inited) {
sleep_retention_module_deinit(module);
@@ -856,9 +856,8 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
ESP_RETURN_ON_FALSE((uart_config->flow_ctrl < UART_HW_FLOWCTRL_MAX), ESP_FAIL, UART_TAG, "hw_flowctrl mode error");
ESP_RETURN_ON_FALSE((uart_config->data_bits < UART_DATA_BITS_MAX), ESP_FAIL, UART_TAG, "data bit error");
bool allow_pd __attribute__((unused)) = (uart_config->flags.allow_pd || uart_config->flags.backup_before_sleep);
#if !SOC_UART_SUPPORT_SLEEP_RETENTION
ESP_RETURN_ON_FALSE(allow_pd == 0, ESP_ERR_NOT_SUPPORTED, UART_TAG, "not able to power down in light sleep");
ESP_RETURN_ON_FALSE(uart_config->flags.backup_before_sleep == 0, ESP_ERR_NOT_SUPPORTED, UART_TAG, "register back up is not supported");
#endif
uart_module_enable(uart_num);
@@ -867,8 +866,8 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
// Create sleep retention link if desired
if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM && uart_num < SOC_UART_HP_NUM) {
_lock_acquire(&(uart_context[uart_num].mutex));
sleep_retention_module_t module = uart_reg_retention_info[uart_num].module;
if (allow_pd && !uart_context[uart_num].retention_link_created) {
sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num);
if (uart_config->flags.backup_before_sleep && !uart_context[uart_num].retention_link_created) {
if (uart_context[uart_num].retention_link_inited) {
if (sleep_retention_module_allocate(module) == ESP_OK) {
uart_context[uart_num].retention_link_created = true;
@@ -879,7 +878,7 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
} else {
ESP_LOGW(UART_TAG, "retention module not initialized first, unable to create retention module");
}
} else if (!allow_pd && uart_context[uart_num].retention_link_created) {
} else if (!uart_config->flags.backup_before_sleep && uart_context[uart_num].retention_link_created) {
assert(uart_context[uart_num].retention_link_inited);
sleep_retention_module_free(module);
uart_context[uart_num].retention_link_created = false;
@@ -1806,7 +1805,7 @@ esp_err_t uart_driver_delete(uart_port_t uart_num)
#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// Free sleep retention link for HP UART
if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM && uart_num < SOC_UART_HP_NUM) {
sleep_retention_module_t module = uart_reg_retention_info[uart_num].module;
sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num);
_lock_acquire(&(uart_context[uart_num].mutex));
if (uart_context[uart_num].retention_link_created) {
assert(uart_context[uart_num].retention_link_inited);
@@ -1980,7 +1979,7 @@ static esp_err_t uart_create_sleep_retention_link_cb(void *arg)
{
uart_context_t *group = (uart_context_t *)arg;
uart_port_t uart_num = group->port_id;
sleep_retention_module_t module = uart_reg_retention_info[uart_num].module;
sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num);
esp_err_t err = sleep_retention_entries_create(uart_reg_retention_info[uart_num].regdma_entry_array,
uart_reg_retention_info[uart_num].array_size,
REGDMA_LINK_PRI_UART, module);
@@ -17,7 +17,7 @@
static const uart_port_t uart_num = UART_NUM_1;
static void uart_init(bool allow_pd)
static void uart_init(bool backup_before_sleep)
{
uart_config_t uart_config = {
.baud_rate = 115200,
@@ -26,7 +26,7 @@ static void uart_init(bool allow_pd)
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
.flags.allow_pd = allow_pd,
.flags.backup_before_sleep = backup_before_sleep,
};
TEST_ESP_OK(uart_driver_install(uart_num, 256, 0, 20, NULL, 0));
@@ -120,7 +120,7 @@ TEST_CASE("uart won't be powered down in light sleep if retention not created",
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000));
sleep_cpu_configure(true);
uart_init(false); // allow_pd set to false, sleep retention module will be inited, but not created
uart_init(false); // backup_before_sleep set to false, sleep retention module will be inited, but not created
// Ensure UART is fully idle before starting loopback RX/TX test
TEST_ESP_OK(uart_wait_tx_done(uart_num, portMAX_DELAY));
+5 -5
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -86,7 +86,7 @@ static esp_err_t verify_url (http_parser *parser)
ESP_LOGD(TAG, LOG_FMT("received URI = %s"), r->uri);
/* Make sure version is HTTP/1.1 */
if (!((parser->http_major == 1) && (parser->http_minor == 1))) {
if ((parser->http_major != 1) && (parser->http_minor != 1)) {
ESP_LOGW(TAG, LOG_FMT("unsupported HTTP version = %d.%d"),
parser->http_major, parser->http_minor);
parser_data->error = HTTPD_505_VERSION_NOT_SUPPORTED;
@@ -106,7 +106,7 @@ static esp_err_t verify_url (http_parser *parser)
}
/* http_parser callback on finding url in HTTP request
* Will be invoked AT LEAST once every packet
* Will be invoked ATLEAST once every packet
*/
static esp_err_t cb_url(http_parser *parser,
const char *at, size_t length)
@@ -191,7 +191,7 @@ static size_t continue_parsing(http_parser *parser, size_t length)
}
/* http_parser callback on header field in HTTP request
* May be invoked AT LEAST once every header field
* May be invoked ATLEAST once every header field
*/
static esp_err_t cb_header_field(http_parser *parser, const char *at, size_t length)
{
@@ -250,7 +250,7 @@ static esp_err_t cb_header_field(http_parser *parser, const char *at, size_t len
}
/* http_parser callback on header value in HTTP request.
* May be invoked AT LEAST once every header value
* May be invoked ATLEAST once every header value
*/
static esp_err_t cb_header_value(http_parser *parser, const char *at, size_t length)
{

Some files were not shown because too many files have changed in this diff Show More