diff --git a/.codespellrc b/.codespellrc index a886554427db..e9be43f21608 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,4 +1,4 @@ [codespell] skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem -ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn,registr,oen +ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn,registr,oen,parms write-changes = true diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index b1ef4019e94b..b29aceb40500 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -2,245 +2,5 @@ # # https://docs.gitlab.com/ee/user/project/code_owners.html#the-syntax-of-code-owners-files # -# If more than one rule matches a given file, the latest rule is used. -# The file should be generally kept sorted, except when it is necessary -# to use a different order due to the fact above. In that case, use -# '# sort-order-reset' comment line to reset the sort order. -# -# Recipes for a few common cases: -# -# 1. Specific directory with all its contents: -# -# /components/app_trace/ -# -# Note the trailing slash! -# -# 2. File with certain extension in any subdirectory of a certain directory: -# -# /examples/**/*.py -# -# This includes an *.py files in /examples/ directory as well. -# -# 3. Contents of a directory with a certain name, anywhere in the tree: -# -# test_*_host/ -# -# Will match everything under components/efuse/test_efuse_host/, -# components/heap/test_multi_heap_host/, components/lwip/test_afl_host/, etc. -# -# 4. Same as above, except limited to a specific place in the tree: -# -# /components/esp32*/ -# -# Matches everything under /components/esp32, /components/esp32s2, etc. -# Doesn't match /tools/some-test/components/esp32s5. -# -# 5. Specific file: -# -# /tools/tools.json -# -# 6. File with a certain name anywhere in the tree -# -# .gitignore -# - -* @esp-idf-codeowners/other - -/.* @esp-idf-codeowners/tools -/.codespellrc @esp-idf-codeowners/ci -/.github/workflows/ @esp-idf-codeowners/ci -/.gitlab-ci.yml @esp-idf-codeowners/ci -/.gitlab/ci/ @esp-idf-codeowners/ci -/.pre-commit-config.yaml @esp-idf-codeowners/ci -/.readthedocs.yml @esp-idf-codeowners/docs -/.vale.ini @esp-idf-codeowners/docs -/CMakeLists.txt @esp-idf-codeowners/build-config -/COMPATIBILITY*.md @esp-idf-codeowners/peripherals -/CONTRIBUTING.md @esp-idf-codeowners/docs -/Kconfig @esp-idf-codeowners/build-config -/README*.md @esp-idf-codeowners/docs -/ROADMAP*.md @esp-idf-codeowners/docs -/SUPPORT_POLICY*.md @esp-idf-codeowners/docs -/add_path.sh @esp-idf-codeowners/tools -/conftest.py @esp-idf-codeowners/ci -/export.* @esp-idf-codeowners/tools -/install.* @esp-idf-codeowners/tools -/pytest.ini @esp-idf-codeowners/ci -/sdkconfig.rename @esp-idf-codeowners/build-config -/sonar-project.properties @esp-idf-codeowners/ci - -# sort-order-reset - -/components/app_trace/ @esp-idf-codeowners/debugging -/components/app_update/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities -/components/bootloader*/ @esp-idf-codeowners/system @esp-idf-codeowners/security -/components/bootloader_support/bootloader_flash/ @esp-idf-codeowners/peripherals -/components/bt/ @esp-idf-codeowners/bluetooth -/components/cmock/ @esp-idf-codeowners/system -/components/console/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities/console -/components/cxx/ @esp-idf-codeowners/system -/components/driver/ @esp-idf-codeowners/peripherals -/components/efuse/ @esp-idf-codeowners/system -/components/esp_adc/ @esp-idf-codeowners/peripherals -/components/esp_app_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities -/components/esp_bootloader_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities -/components/esp_coex/ @esp-idf-codeowners/wifi @esp-idf-codeowners/bluetooth @esp-idf-codeowners/ieee802154 -/components/esp_common/ @esp-idf-codeowners/system -/components/esp_driver_*/ @esp-idf-codeowners/peripherals -/components/esp_driver_sdmmc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/storage -/components/esp_eth/ @esp-idf-codeowners/network -/components/esp_event/ @esp-idf-codeowners/system -/components/esp_gdbstub/ @esp-idf-codeowners/debugging -/components/esp_hid/ @esp-idf-codeowners/bluetooth -/components/esp_http_client/ @esp-idf-codeowners/app-utilities -/components/esp_http_server/ @esp-idf-codeowners/app-utilities -/components/esp_https_ota/ @esp-idf-codeowners/app-utilities -/components/esp_https_server/ @esp-idf-codeowners/app-utilities -/components/esp_hw_support/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals -/components/esp_hw_support/lowpower/ @esp-idf-codeowners/power-management -/components/esp_lcd/ @esp-idf-codeowners/peripherals -/components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities -/components/esp_mm/ @esp-idf-codeowners/peripherals -/components/esp_netif/ @esp-idf-codeowners/network -/components/esp_netif_stack/ @esp-idf-codeowners/network -/components/esp_partition/ @esp-idf-codeowners/storage -/components/esp_phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154 -/components/esp_pm/ @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/system -/components/esp_psram/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system -/components/esp_ringbuf/ @esp-idf-codeowners/system -/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi -/components/esp_security/ @esp-idf-codeowners/security -/components/esp_system/ @esp-idf-codeowners/system -/components/esp_timer/ @esp-idf-codeowners/system -/components/esp-tls/ @esp-idf-codeowners/app-utilities -/components/esp_vfs_*/ @esp-idf-codeowners/storage -/components/esp_vfs_console/ @esp-idf-codeowners/storage @esp-idf-codeowners/system -/components/esp_wifi/ @esp-idf-codeowners/wifi -/components/espcoredump/ @esp-idf-codeowners/debugging -/components/esptool_py/ @esp-idf-codeowners/tools -/components/fatfs/ @esp-idf-codeowners/storage -/components/freertos/ @esp-idf-codeowners/system -/components/hal/ @esp-idf-codeowners/peripherals -/components/hal/test_apps/crypto/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security -/components/heap/ @esp-idf-codeowners/system -/components/http_parser/ @esp-idf-codeowners/app-utilities -/components/idf_test/ @esp-idf-codeowners/ci -/components/ieee802154/ @esp-idf-codeowners/ieee802154 -/components/json/ @esp-idf-codeowners/app-utilities -/components/linux/ @esp-idf-codeowners/system -/components/log/ @esp-idf-codeowners/system -/components/lwip/ @esp-idf-codeowners/lwip -/components/mbedtls/ @esp-idf-codeowners/app-utilities/mbedtls @esp-idf-codeowners/security -/components/mqtt/ @esp-idf-codeowners/network -/components/newlib/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain -/components/nvs_flash/ @esp-idf-codeowners/storage -/components/nvs_sec_provider/ @esp-idf-codeowners/storage @esp-idf-codeowners/security -/components/openthread/ @esp-idf-codeowners/ieee802154 -/components/partition_table/ @esp-idf-codeowners/system -/components/perfmon/ @esp-idf-codeowners/debugging -/components/protobuf-c/ @esp-idf-codeowners/app-utilities -/components/protocomm/ @esp-idf-codeowners/app-utilities/provisioning -/components/pthread/ @esp-idf-codeowners/system -/components/riscv/ @esp-idf-codeowners/system -/components/rt/ @esp-idf-codeowners/system -/components/sdmmc/ @esp-idf-codeowners/storage -/components/soc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system -/components/spi_flash/ @esp-idf-codeowners/peripherals -/components/spiffs/ @esp-idf-codeowners/storage -/components/tcp_transport/ @esp-idf-codeowners/network -/components/touch_element/ @esp-idf-codeowners/peripherals -/components/ulp/ @esp-idf-codeowners/system -/components/unity/ @esp-idf-codeowners/ci -/components/usb/ @esp-idf-codeowners/peripherals/usb -/components/vfs/ @esp-idf-codeowners/storage -/components/wear_levelling/ @esp-idf-codeowners/storage -/components/wifi_provisioning/ @esp-idf-codeowners/app-utilities/provisioning -/components/wpa_supplicant/ @esp-idf-codeowners/wifi @esp-idf-codeowners/app-utilities/mbedtls -/components/xtensa/ @esp-idf-codeowners/system - -/docs/ @esp-idf-codeowners/docs -/docs/**/api-guides/tools/ @esp-idf-codeowners/tools -/docs/en/api-guides/core_dump.rst @esp-idf-codeowners/debugging -/docs/en/api-guides/jtag-debugging/ @esp-idf-codeowners/debugging -/docs/**/api-reference/bluetooth/ @esp-idf-codeowners/bluetooth -/docs/**/api-reference/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi -/docs/**/api-reference/peripherals/ @esp-idf-codeowners/peripherals -/docs/**/api-reference/peripherals/usb* @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb -/docs/**/api-reference/peripherals/usb*/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb -/docs/**/api-reference/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities -/docs/**/api-reference/provisioning/ @esp-idf-codeowners/app-utilities/provisioning -/docs/**/api-reference/storage/ @esp-idf-codeowners/storage -/docs/**/api-reference/system/ @esp-idf-codeowners/system -/docs/**/security/ @esp-idf-codeowners/security -/docs/**/migration-guides/ @esp-idf-codeowners/docs @esp-idf-codeowners/all-maintainers -/docs/**/contribute/install-pre-commit-hook.rst @esp-idf-codeowners/ci @esp-idf-codeowners/tools - -/examples/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci -/examples/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools -/examples/bluetooth/ @esp-idf-codeowners/bluetooth -/examples/build_system/ @esp-idf-codeowners/build-config -/examples/common_components/ @esp-idf-codeowners/system @esp-idf-codeowners/wifi @esp-idf-codeowners/lwip @esp-idf-codeowners/network -/examples/custom_bootloader/ @esp-idf-codeowners/system -/examples/cxx/ @esp-idf-codeowners/system -/examples/ethernet/ @esp-idf-codeowners/network -/examples/get-started/ @esp-idf-codeowners/system -/examples/ieee802154/ @esp-idf-codeowners/ieee802154 -/examples/mesh/ @esp-idf-codeowners/wifi -/examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi -/examples/openthread/ @esp-idf-codeowners/ieee802154 -/examples/peripherals/ @esp-idf-codeowners/peripherals -/examples/peripherals/usb/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb -/examples/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154 -/examples/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities -/examples/provisioning/ @esp-idf-codeowners/app-utilities/provisioning -/examples/security/ @esp-idf-codeowners/security -/examples/storage/ @esp-idf-codeowners/storage -/examples/system/ @esp-idf-codeowners/system -/examples/system/ota/ @esp-idf-codeowners/app-utilities -/examples/wifi/ @esp-idf-codeowners/wifi -/examples/zigbee/ @esp-idf-codeowners/ieee802154 - -/tools/ @esp-idf-codeowners/tools -/tools/ble/ @esp-idf-codeowners/app-utilities -/tools/catch/ @esp-idf-codeowners/ci -/tools/ci/ @esp-idf-codeowners/ci -/tools/cmake/ @esp-idf-codeowners/build-config -/tools/cmake/toolchain-*.cmake @esp-idf-codeowners/toolchain -/tools/esp_app_trace/ @esp-idf-codeowners/debugging -/tools/esp_prov/ @esp-idf-codeowners/app-utilities -/tools/gdb_panic_server.py @esp-idf-codeowners/debugging -/tools/kconfig*/ @esp-idf-codeowners/build-config -/tools/ldgen/ @esp-idf-codeowners/build-config -/tools/mass_mfg/ @esp-idf-codeowners/app-utilities -/tools/mocks/ @esp-idf-codeowners/system - -/tools/test_apps/ @esp-idf-codeowners/ci -/tools/test_apps/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci - -## Note: owners here should be the same as the owners for the same example subdir, above -/tools/test_apps/build_system/ @esp-idf-codeowners/build-config -/tools/test_apps/configs/ @esp-idf-codeowners/system -/tools/test_apps/linux_compatible/ @esp-idf-codeowners/system -/tools/test_apps/peripherals/ @esp-idf-codeowners/peripherals -/tools/test_apps/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154 -/tools/test_apps/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities -/tools/test_apps/security/ @esp-idf-codeowners/security -/tools/test_apps/storage/ @esp-idf-codeowners/storage -/tools/test_apps/system/ @esp-idf-codeowners/system - -/tools/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools - -/tools/test_build_system/ @esp-idf-codeowners/tools @esp-idf-codeowners/build-config - -/tools/tools.json @esp-idf-codeowners/tools @esp-idf-codeowners/toolchain @esp-idf-codeowners/debugging - -/tools/unit-test-app/ @esp-idf-codeowners/system @esp-idf-codeowners/tools - -# sort-order-reset - -/components/**/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools -# ignore lists -/tools/ci/check_copyright_config.yaml @esp-idf-codeowners/all-maintainers -/tools/ci/check_copyright_ignore.txt @esp-idf-codeowners/all-maintainers -/tools/ci/mypy_ignore_list.txt @esp-idf-codeowners/tools +* @esp-idf-codeowners/all-maintainers diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index ce6ccfd2764f..376946d0bda1 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -1,7 +1,7 @@ .build_template: stage: build extends: - - .after_script:build:ccache:upload-when-fail + - .after_script:build:ccache-show-stats:upload-failed-job-logs image: $ESP_ENV_IMAGE tags: - build @@ -16,7 +16,7 @@ extends: - .build_template - .before_script:build - - .after_script:build:ccache + - .after_script:build:ccache-show-stats dependencies: # set dependencies to null to avoid missing artifacts issue needs: - job: fast_template_app @@ -246,15 +246,16 @@ pytest_build_system_macos: extends: - .test_build_system_template - .before_script:build:macos - - .after_script:build:macos:upload-when-fail + - .after_script:build:macos:upload-failed-job-logs:ccache-show-stats - .rules:build:macos tags: - macos_shell parallel: 3 variables: PYENV_VERSION: "3.8" - CI_CCACHE_DISABLE: "1" # ccache: error: Read-only file system - + # CCACHE_DIR: "/cache/idf_ccache". On macOS, you cannot write to this folder due to insufficient permissions. + CCACHE_DIR: "" # ccache will use "$HOME/Library/Caches/ccache". + CCACHE_MAXSIZE: "5G" # To preserve the limited Macbook storage. CCACHE automatically prunes old caches to fit the set limit. build_docker: extends: - .before_script:minimal @@ -309,7 +310,11 @@ generate_build_child_pipeline: - non_test_related_apps.txt expire_in: 1 week when: always + variables: + PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1" script: + # requires basic pytest dependencies + - run_cmd bash install.sh --enable-pytest - run_cmd python tools/ci/dynamic_pipelines/scripts/generate_build_child_pipeline.py build_child_pipeline: diff --git a/.gitlab/ci/common.yml b/.gitlab/ci/common.yml index 9708396b5fd0..1de35a74b4bb 100644 --- a/.gitlab/ci/common.yml +++ b/.gitlab/ci/common.yml @@ -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 @@ -61,9 +61,6 @@ variables: 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" @@ -91,7 +88,7 @@ variables: CI_CLANG_DISTRO_URL: "" # Set this variable to specify the file name for the known failure cases. - KNOWN_FAILURE_CASES_FILE_NAME: "master.txt" + KNOWN_FAILURE_CASES_FILE_NAME: "5.4.txt" IDF_CI_BUILD: 1 @@ -230,13 +227,14 @@ variables: - *setup_tools_and_idf_python_venv - fetch_submodules -.after_script:build:macos:upload-when-fail: +.after_script:build:macos:upload-failed-job-logs:ccache-show-stats: after_script: # macos is running shell executor, which means it would use # the system installed /usr/local/bin/python3 by default. # Ensure pyenv and PYENV_VERSION installed - eval "$(pyenv init -)" - *upload_failed_job_log_artifacts + - *show_ccache_statistics .before_script:build: before_script: @@ -247,11 +245,11 @@ variables: - export EXTRA_CFLAGS=${PEDANTIC_CFLAGS} - export EXTRA_CXXFLAGS=${PEDANTIC_CXXFLAGS} -.after_script:build:ccache: +.after_script:build:ccache-show-stats: after_script: - *show_ccache_statistics -.after_script:build:ccache:upload-when-fail: +.after_script:build:ccache-show-stats:upload-failed-job-logs: after_script: - *show_ccache_statistics - *upload_failed_job_log_artifacts diff --git a/.gitlab/ci/host-test.yml b/.gitlab/ci/host-test.yml index c646f0c235d4..b383c77b0a4a 100644 --- a/.gitlab/ci/host-test.yml +++ b/.gitlab/ci/host-test.yml @@ -34,22 +34,16 @@ check_public_headers: - IDF_TARGET=esp32p4 python tools/ci/check_public_headers.py --jobs 4 --prefix riscv32-esp-elf- - IDF_TARGET=esp32c61 python tools/ci/check_public_headers.py --jobs 4 --prefix riscv32-esp-elf- -test_nvs_on_host: - extends: .host_test_template - script: - - cd components/nvs_flash/test_nvs_host - - make test - test_nvs_coverage: extends: - .host_test_template - .rules:labels:nvs_coverage artifacts: paths: - - components/nvs_flash/test_nvs_host/coverage_report + - components/nvs_flash/host_test/nvs_host_test/coverage_report script: - - cd components/nvs_flash/test_nvs_host - - make coverage_report + - cd components/nvs_flash/host_test/nvs_host_test + - idf.py build coverage # the 'long' host tests take approx 11 hours on our current runners. Adding some margin here for possible CPU contention timeout: 18 hours diff --git a/.gitlab/ci/pre_check.yml b/.gitlab/ci/pre_check.yml index 7bf24fb158fd..5b1adf24297c 100644 --- a/.gitlab/ci/pre_check.yml +++ b/.gitlab/ci/pre_check.yml @@ -44,6 +44,9 @@ check_blobs: - IDF_TARGET=esp32c2 $IDF_PATH/components/esp_wifi/test_md5/test_md5.sh - IDF_TARGET=esp32c3 $IDF_PATH/components/esp_wifi/test_md5/test_md5.sh - IDF_TARGET=esp32c6 $IDF_PATH/components/esp_wifi/test_md5/test_md5.sh + - IDF_TARGET=esp32c5 $IDF_PATH/components/esp_wifi/test_md5/test_md5.sh + - IDF_TARGET=esp32c61 $IDF_PATH/components/esp_wifi/test_md5/test_md5.sh + - IDF_TARGET=esp32_host $IDF_PATH/components/esp_wifi/test_md5/test_md5.sh # Check if Coexistence library header files match between IDF and the version used when compiling the libraries - IDF_TARGET=esp32 $IDF_PATH/components/esp_coex/test_md5/test_md5.sh - IDF_TARGET=esp32s2 $IDF_PATH/components/esp_coex/test_md5/test_md5.sh @@ -52,6 +55,8 @@ check_blobs: - IDF_TARGET=esp32c3 $IDF_PATH/components/esp_coex/test_md5/test_md5.sh - IDF_TARGET=esp32c6 $IDF_PATH/components/esp_coex/test_md5/test_md5.sh - IDF_TARGET=esp32h2 $IDF_PATH/components/esp_coex/test_md5/test_md5.sh + - IDF_TARGET=esp32c5 $IDF_PATH/components/esp_coex/test_md5/test_md5.sh + - IDF_TARGET=esp32c61 $IDF_PATH/components/esp_coex/test_md5/test_md5.sh # Check if Wi-Fi, PHY, BT blobs contain references to specific symbols - bash $IDF_PATH/tools/ci/check_blobs.sh @@ -112,8 +117,10 @@ check_test_scripts_build_test_rules: extends: - .pre_check_template - .before_script:build + variables: + PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1" script: - # required pytest related packages + # requires basic pytest dependencies - run_cmd bash install.sh --enable-pytest - python tools/ci/check_build_test_rules.py check-test-scripts examples/ tools/test_apps components @@ -176,12 +183,24 @@ baseline_manifest_sha: tags: [fast_run, shiny] script: - | - if [ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]; then + # merged results pipelines, by default + # diff between target-branch-head and merged-result-head + if [ -n "$CI_MERGE_REQUEST_TARGET_BRANCH_SHA" ]; then + git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_SHA --depth=1 + git checkout FETCH_HEAD + idf-build-apps dump-manifest-sha \ + --manifest-files $(find . -name ".build-test-rules.yml" | xargs) \ + --output .manifest_sha + # merge request pipelines, when the mr got conflicts + # diff between diff-base-sha and merge-request-head + elif [ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]; then git fetch origin $CI_MERGE_REQUEST_DIFF_BASE_SHA --depth=1 git checkout FETCH_HEAD idf-build-apps dump-manifest-sha \ --manifest-files $(find . -name ".build-test-rules.yml" | xargs) \ --output .manifest_sha + # other pipelines, like the protected branches pipelines + # not triggered in this job fi artifacts: paths: diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index cc386ac506b1..7b348fbe0956 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -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: diff --git a/.gitlab/ci/static-code-analysis.yml b/.gitlab/ci/static-code-analysis.yml index d22f524d54a0..2773d2cbf7f4 100644 --- a/.gitlab/ci/static-code-analysis.yml +++ b/.gitlab/ci/static-code-analysis.yml @@ -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. # -# 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. +## 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 to +# - 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_report will analyze and transfer both of the newly added code -# and the analysis result 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 # -# 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 to - - 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 +#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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6dcd0531efed..915dd2bdaa06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -264,7 +264,9 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU") endif() if(CMAKE_C_COMPILER_ID MATCHES "Clang") - list(APPEND compile_options "-fno-use-cxa-atexit") + list(APPEND compile_options "-fno-use-cxa-atexit") # TODO IDF-10934 +else() + list(APPEND cxx_compile_options "-fuse-cxa-atexit") endif() if(COMPILER_RT_LIB_NAME) diff --git a/Kconfig b/Kconfig index 028061232e11..13d6c564cbe4 100644 --- a/Kconfig +++ b/Kconfig @@ -678,3 +678,5 @@ mainmenu "Espressif IoT Development Framework Configuration" - CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH - CONFIG_ESP_WIFI_EAP_TLS1_3 - CONFIG_ESP_WIFI_ENABLE_ROAMING_APP + - CONFIG_USB_HOST_EXT_PORT_SUPPORT_LS + - CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS diff --git a/README.md b/README.md index ce807d91da87..d90e7e0eee93 100644 --- a/README.md +++ b/README.md @@ -15,17 +15,18 @@ ESP-IDF is the development framework for Espressif SoCs supported on Windows, Li The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. The preview support is usually limited in time and intended for beta versions of chips. Please use an ESP-IDF release where the desired SoC is already supported. -|Chip | v5.0 | v5.1 | v5.2 | v5.3 | | -|:----------- | :---------------------:| :--------------------: | :--------------------: | :--------------------: | :--------------------------------------------------------- | -|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [Announcement](https://www.espressif.com/en/news/ESP32_S3) | -|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [Announcement](https://www.espressif.com/en/news/ESP32-C2) | -|ESP32-C6 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [Announcement](https://www.espressif.com/en/news/ESP32_C6) | -|ESP32-H2 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [Announcement](https://www.espressif.com/en/news/ESP32_H2) | -|ESP32-P4 | | | | ![alt text][supported] | [Announcement](https://www.espressif.com/en/news/ESP32-P4) | -|ESP32-C5 | | | | ![alt text][preview] | [Announcement](https://www.espressif.com/en/news/ESP32-C5) | +|Chip | v5.0 | v5.1 | v5.2 | v5.3 | v5.4 | | +|:----------- | :---------------------:| :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------- | +|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) | +|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) | +|ESP32-C6 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) | +|ESP32-H2 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) | +|ESP32-P4 | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) | +|ESP32-C5 | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) | +|ESP32-C61 | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) | [supported]: https://img.shields.io/badge/-supported-green "supported" [preview]: https://img.shields.io/badge/-preview-orange "preview" diff --git a/README_CN.md b/README_CN.md index e8f21600d1d6..6aeb55a5ac7b 100644 --- a/README_CN.md +++ b/README_CN.md @@ -15,17 +15,18 @@ ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux 下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。预览支持状态通常有时间限制,而且仅适用于测试版芯片。请确保使用与芯片相匹配的 ESP-IDF 版本。 -|芯片 | v5.0 | v5.1 | v5.2 | v5.3 | | -|:----------- | :---------------------:| :--------------------: | :--------------------: | :--------------------: | :-------------------------------------------------------------- | -|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) | -|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) | -|ESP32-C6 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) | -|ESP32-H2 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) | -|ESP32-P4 | | | | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) | -|ESP32-C5 | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) | +|芯片 | v5.0 | v5.1 | v5.2 | v5.3 | v5.4 | | +|:----------- | :---------------------:| :--------------------: | :--------------------: | :--------------------: | :--------------------: | :------------------------------------------------------------------------ | +|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) | +|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) | +|ESP32-C6 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) | +|ESP32-H2 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) | +|ESP32-P4 | | | | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) | +|ESP32-C5 | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) | +|ESP32-C61 | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) | [supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported" [preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview" diff --git a/components/app_trace/port/riscv/port.c b/components/app_trace/port/riscv/port.c index 3e5ceca966c9..14fe223623c9 100644 --- a/components/app_trace/port/riscv/port.c +++ b/components/app_trace/port/riscv/port.c @@ -57,7 +57,13 @@ static bool esp_apptrace_riscv_host_data_pending(void); const static char *TAG = "esp_apptrace"; -static esp_apptrace_riscv_ctrl_block_t s_tracing_ctrl[CONFIG_FREERTOS_NUMBER_OF_CORES]; +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +#define APPTRACE_DRAM_ATTR TCM_DRAM_ATTR +#else +#define APPTRACE_DRAM_ATTR +#endif + +static APPTRACE_DRAM_ATTR esp_apptrace_riscv_ctrl_block_t s_tracing_ctrl[CONFIG_FREERTOS_NUMBER_OF_CORES]; esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data) { @@ -92,7 +98,7 @@ esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data) } /* Advertises apptrace control block address to host. - This function can be overriden with custom implementation, + This function can be overridden with custom implementation, e.g. OpenOCD flasher stub use own implementation of it. */ __attribute__((weak)) int esp_apptrace_advertise_ctrl_block(void *ctrl_block_addr) { @@ -103,7 +109,7 @@ __attribute__((weak)) int esp_apptrace_advertise_ctrl_block(void *ctrl_block_add } /* Returns up buffers config. - This function can be overriden with custom implementation, + This function can be overridden with custom implementation, e.g. OpenOCD flasher stub use own implementation of it. */ __attribute__((weak)) void esp_apptrace_get_up_buffers(esp_apptrace_mem_block_t mem_blocks_cfg[2]) { @@ -165,7 +171,7 @@ static esp_err_t esp_apptrace_riscv_init(esp_apptrace_riscv_data_t *hw_data) } // notify host about control block address int res = esp_apptrace_advertise_ctrl_block(&s_tracing_ctrl[core_id]); - assert(res == 0 && "Falied to send config to host!"); + assert(res == 0 && "Failed to send config to host!"); return ESP_OK; } diff --git a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c index fcf33d365af7..c01cbed67ea4 100644 --- a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c +++ b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-1-Clause * - * SPDX-FileContributor: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2017-2024 Espressif Systems (Shanghai) CO LTD */ /********************************************************************* * SEGGER Microcontroller GmbH * @@ -58,6 +58,7 @@ File : SEGGER_SYSVIEW_Config_FreeRTOS.c Purpose : Sample setup configuration of SystemView with FreeRTOS. Revision: $Rev: 7745 $ */ +#include #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "SEGGER_SYSVIEW.h" @@ -156,15 +157,16 @@ static esp_apptrace_lock_t s_sys_view_lock = {.mux = portMUX_INITIALIZER_UNLOCKE * Sends SystemView description strings. */ static void _cbSendSystemDesc(void) { - char irq_str[32]; + char irq_str[32] = "I#"; SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C="SYSVIEW_CORE_NAME",O=FreeRTOS"); - snprintf(irq_str, sizeof(irq_str), "I#%d=SysTick", SYSTICK_INTR_ID); + strcat(itoa(SYSTICK_INTR_ID, irq_str + 2, 10), "=SysTick"); SEGGER_SYSVIEW_SendSysDesc(irq_str); size_t isr_count = sizeof(esp_isr_names)/sizeof(esp_isr_names[0]); for (size_t i = 0; i < isr_count; ++i) { if (esp_isr_names[i] == NULL || (ETS_INTERNAL_INTR_SOURCE_OFF + i) == SYSTICK_INTR_ID) continue; - snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, esp_isr_names[i]); + strcat(itoa(ETS_INTERNAL_INTR_SOURCE_OFF + i, irq_str + 2, 10), "="); + strncat(irq_str, esp_isr_names[i], sizeof(irq_str) - strlen(irq_str) - 1); SEGGER_SYSVIEW_SendSysDesc(irq_str); } } diff --git a/components/app_update/test_apps/test_app_update/main/test_switch_ota.c b/components/app_update/test_apps/test_app_update/main/test_switch_ota.c index f71276668d66..f38802b7aeec 100644 --- a/components/app_update/test_apps/test_app_update/main/test_switch_ota.c +++ b/components/app_update/test_apps/test_app_update/main/test_switch_ota.c @@ -101,24 +101,6 @@ static void copy_app_partition_with_offset(esp_ota_handle_t update_handle, const ESP_LOGI(TAG, "finish the copy process"); } -#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST) -/* @brief Copies partition from source partition to destination partition. - * - * Partitions can be of any types and subtypes. - * @param[in] dst_partition - Destination partition - * @param[in] src_partition - Source partition - */ -static void copy_partition(const esp_partition_t *dst_partition, const esp_partition_t *src_partition) -{ - const void *partition_bin = NULL; - esp_partition_mmap_handle_t data_map; - TEST_ESP_OK(esp_partition_mmap(src_partition, 0, src_partition->size, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map)); - TEST_ESP_OK(esp_partition_erase_range(dst_partition, 0, dst_partition->size)); - TEST_ESP_OK(esp_partition_write(dst_partition, 0, (const void *)partition_bin, dst_partition->size)); - esp_partition_munmap(data_map); -} -#endif - /* @brief Get the next partition of OTA for the update. * * @return The next partition of OTA(OTA0-15). @@ -530,7 +512,7 @@ static void test_flow5(void) ESP_LOGI(TAG, "Factory"); TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype); set_output_pin(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST); - copy_partition(esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEST, NULL), cur_app); + esp_partition_copy(esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEST, NULL), 0, cur_app, 0, cur_app->size); esp_restart(); break; case 3: diff --git a/components/bootloader/Kconfig.log.format b/components/bootloader/Kconfig.log.format index b1b877b0a99c..6d87bc560124 100644 --- a/components/bootloader/Kconfig.log.format +++ b/components/bootloader/Kconfig.log.format @@ -2,7 +2,7 @@ menu "Format" config BOOTLOADER_LOG_COLORS bool "Color" - default y + default n help Use ANSI terminal colors in log output Enable ANSI terminal color codes. diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt index e4881b4bc55e..f630bcc46c7d 100644 --- a/components/bootloader/subproject/CMakeLists.txt +++ b/components/bootloader/subproject/CMakeLists.txt @@ -58,6 +58,7 @@ 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}") @@ -66,6 +67,7 @@ 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) @@ -207,7 +209,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 re-use the same secure boot keyfile on multiple production devices." + "* Not recommended to reuse the same secure boot keyfile on multiple production devices." DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin VERBATIM) elseif( diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index ea1057922150..adff675c260a 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -670,7 +670,6 @@ void bootloader_spi_flash_reset(void) #define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT #define XMC_VENDOR_ID_1 0x20 -#define XMC_VENDOR_ID_2 0x46 #if BOOTLOADER_BUILD #define BOOTLOADER_FLASH_LOG(level, ...) ESP_EARLY_LOG##level(TAG, ##__VA_ARGS__) @@ -687,7 +686,7 @@ static IRAM_ATTR bool is_xmc_chip_strict(uint32_t rdid) uint32_t mfid = BYTESHIFT(rdid, 1); uint32_t cpid = BYTESHIFT(rdid, 0); - if (vendor_id != XMC_VENDOR_ID_1 && vendor_id != XMC_VENDOR_ID_2) { + if (vendor_id != XMC_VENDOR_ID_1) { return false; } @@ -720,7 +719,7 @@ esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void) // Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow const int sfdp_mfid_addr = 0x10; uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff); - if ((mf_id != XMC_VENDOR_ID_1) && (mf_id != XMC_VENDOR_ID_2)) { + if (mf_id != XMC_VENDOR_ID_1) { BOOTLOADER_FLASH_LOG(D, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id); return ESP_OK; } @@ -752,7 +751,7 @@ esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void) static IRAM_ATTR bool is_xmc_chip(uint32_t rdid) { uint32_t vendor_id = (rdid >> 16) & 0xFF; - return ((vendor_id == XMC_VENDOR_ID_1) || (vendor_id == XMC_VENDOR_ID_2)); + return (vendor_id == XMC_VENDOR_ID_1); } esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void) diff --git a/components/bootloader_support/include/esp_flash_encrypt.h b/components/bootloader_support/include/esp_flash_encrypt.h index e942d7f54d79..efc061edf502 100644 --- a/components/bootloader_support/include/esp_flash_encrypt.h +++ b/components/bootloader_support/include/esp_flash_encrypt.h @@ -184,12 +184,14 @@ 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 */ diff --git a/components/bootloader_support/include/esp_flash_partitions.h b/components/bootloader_support/include/esp_flash_partitions.h index 47fe97596109..d05ded654fee 100644 --- a/components/bootloader_support/include/esp_flash_partitions.h +++ b/components/bootloader_support/include/esp_flash_partitions.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,6 +29,14 @@ extern "C" { #define PART_SUBTYPE_DATA_NVS_KEYS 0x04 #define PART_SUBTYPE_DATA_EFUSE_EM 0x05 +#define PART_TYPE_BOOTLOADER 0x02 +#define PART_SUBTYPE_BOOTLOADER_PRIMARY 0x00 +#define PART_SUBTYPE_BOOTLOADER_OTA 0x01 + +#define PART_TYPE_PARTITION_TABLE 0x03 +#define PART_SUBTYPE_PARTITION_TABLE_PRIMARY 0x00 +#define PART_SUBTYPE_PARTITION_TABLE_OTA 0x01 + #define PART_TYPE_END 0xff #define PART_SUBTYPE_END 0xff @@ -41,7 +49,11 @@ extern "C" { /* Pre-partition table fixed flash offsets */ #define ESP_BOOTLOADER_DIGEST_OFFSET 0x0 #define ESP_BOOTLOADER_OFFSET CONFIG_BOOTLOADER_OFFSET_IN_FLASH /* Offset of bootloader image. Has matching value in bootloader KConfig.projbuild file. */ +#define ESP_PRIMARY_BOOTLOADER_OFFSET CONFIG_BOOTLOADER_OFFSET_IN_FLASH /* Offset of Primary bootloader image. */ #define ESP_PARTITION_TABLE_OFFSET CONFIG_PARTITION_TABLE_OFFSET /* Offset of partition table. Backwards-compatible name.*/ +#define ESP_PRIMARY_PARTITION_TABLE_OFFSET CONFIG_PARTITION_TABLE_OFFSET /* Offset of partition table. */ +#define ESP_PARTITION_TABLE_SIZE (0x1000) /* The partition table occupies 1 sector of flash (SPI_FLASH_SEC_SIZE) */ +#define ESP_BOOTLOADER_SIZE (ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET) #define ESP_PARTITION_TABLE_MAX_LEN 0xC00 /* Maximum length of partition table data */ #define ESP_PARTITION_TABLE_MAX_ENTRIES (ESP_PARTITION_TABLE_MAX_LEN / sizeof(esp_partition_info_t)) /* Maximum length of partition table data, including terminating entry */ diff --git a/components/bootloader_support/private_include/bootloader_soc.h b/components/bootloader_support/private_include/bootloader_soc.h index d854112f6382..acce77cfb6c7 100644 --- a/components/bootloader_support/private_include/bootloader_soc.h +++ b/components/bootloader_support/private_include/bootloader_soc.h @@ -24,6 +24,14 @@ void bootloader_ana_super_wdt_reset_config(bool enable); */ void bootloader_ana_clock_glitch_reset_config(bool enable); +/** + * @brief Configure analog power glitch reset & glitch reset dref + * + * @param enable Boolean to enable or disable power glitch reset + * @param dref voltage threshold + */ +void bootloader_power_glitch_reset_config(bool enable, uint8_t dref); + #ifdef __cplusplus } #endif diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 30dd5049fc39..d27aaaf53977 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -199,6 +199,26 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs) break; } break; /* PARTITION_USAGE_DATA */ + case PART_TYPE_BOOTLOADER: /* Bootloader partition */ + switch (partition->subtype) { + case PART_SUBTYPE_BOOTLOADER_PRIMARY: + partition_usage = "primary bootloader"; + break; + case PART_SUBTYPE_BOOTLOADER_OTA: + partition_usage = "ota bootloader"; + break; + } + break; /* PART_TYPE_BOOTLOADER */ + case PART_TYPE_PARTITION_TABLE: /* Partition table partition */ + switch (partition->subtype) { + case PART_SUBTYPE_PARTITION_TABLE_PRIMARY: + partition_usage = "primary partition_table"; + break; + case PART_SUBTYPE_PARTITION_TABLE_OTA: + partition_usage = "ota partition_table"; + break; + } + break; /* PART_TYPE_PARTITION_TABLE */ default: /* other partition type */ break; } diff --git a/components/bootloader_support/src/esp32c5/bootloader_esp32c5.c b/components/bootloader_support/src/esp32c5/bootloader_esp32c5.c index 0f53f259ad5d..d7258e52c2ce 100644 --- a/components/bootloader_support/src/esp32c5/bootloader_esp32c5.c +++ b/components/bootloader_support/src/esp32c5/bootloader_esp32c5.c @@ -92,11 +92,13 @@ static inline void bootloader_hardware_init(void) static inline void bootloader_ana_reset_config(void) { - // TODO: [ESP32C5] IDF-8650 - //Enable super WDT reset. - // bootloader_ana_super_wdt_reset_config(true); //Enable BOD reset (mode1) brownout_ll_ana_reset_enable(true); + if (efuse_hal_chip_revision() == 0) { + // decrease power glitch reset voltage to avoid start the glitch reset + uint8_t power_glitch_dref = 0; + bootloader_power_glitch_reset_config(true, power_glitch_dref); + } } esp_err_t bootloader_init(void) diff --git a/components/bootloader_support/src/esp32c5/bootloader_soc.c b/components/bootloader_support/src/esp32c5/bootloader_soc.c index 95238f511e9e..1e4335491b98 100644 --- a/components/bootloader_support/src/esp32c5/bootloader_soc.c +++ b/components/bootloader_support/src/esp32c5/bootloader_soc.c @@ -7,18 +7,29 @@ #include #include "soc/soc.h" #include "soc/lp_analog_peri_reg.h" -// TODO: [ESP32C5] IDF-8667 remove esp_log.h -#include "esp_log.h" - -void bootloader_ana_super_wdt_reset_config(bool enable) -{ - // TODO: [ESP32C5] IDF-8667 - ESP_EARLY_LOGW("bootloader", "bootloader_ana_super_wdt_reset_config() has not been implemented on C5 yet"); -} +#include "soc/pmu_reg.h" +#include "hal/regi2c_ctrl.h" +#include "soc/regi2c_saradc.h" //Not supported but common bootloader calls the function. Do nothing void bootloader_ana_clock_glitch_reset_config(bool enable) { - // TODO: [ESP32C5] IDF-8667, PM-207 (void)enable; } + +void bootloader_power_glitch_reset_config(bool enable, uint8_t dref) +{ + assert(dref < 8); + REG_SET_FIELD(LP_ANA_FIB_ENABLE_REG, LP_ANA_ANA_FIB_PWR_GLITCH_ENA, 0); + if (enable) { + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); + REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PERIF, dref); + REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_VDDPST, dref); + REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_XTAL, dref); + REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PLL, dref); + REG_SET_FIELD(LP_ANA_CK_GLITCH_CNTL_REG, LP_ANA_PWR_GLITCH_RESET_ENA, 0xf); + } else { + REG_SET_FIELD(LP_ANA_CK_GLITCH_CNTL_REG, LP_ANA_PWR_GLITCH_RESET_ENA, 0); + } +} diff --git a/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c b/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c index 03af18a1dbfb..ad90f306c01f 100644 --- a/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c +++ b/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c @@ -11,9 +11,8 @@ #include "esp_efuse_table.h" #include "esp_log.h" #include "sdkconfig.h" -#include "soc/keymng_reg.h" -#include "soc/pcr_reg.h" -#include "soc/pcr_struct.h" +#include "hal/key_mgr_ll.h" +#include "hal/mspi_timing_tuning_ll.h" static __attribute__((unused)) const char *TAG = "flash_encrypt"; @@ -62,30 +61,21 @@ 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) { - // 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; + // 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(); - // Wait for key manager to be ready - while (!PCR.km_conf.km_ready) { + while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) { }; - // 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); + // 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(); return ESP_OK; } diff --git a/components/bootloader_support/src/esp32c61/bootloader_esp32c61.c b/components/bootloader_support/src/esp32c61/bootloader_esp32c61.c index 8d62e4746e8b..d9b65d3e33b5 100644 --- a/components/bootloader_support/src/esp32c61/bootloader_esp32c61.c +++ b/components/bootloader_support/src/esp32c61/bootloader_esp32c61.c @@ -93,17 +93,17 @@ static inline void bootloader_hardware_init(void) static inline void bootloader_ana_reset_config(void) { - //Enable super WDT reset. - bootloader_ana_super_wdt_reset_config(true); //Enable BOD reset (mode1) brownout_ll_ana_reset_enable(true); + uint8_t power_glitch_dref = 0; + bootloader_power_glitch_reset_config(true, power_glitch_dref); } esp_err_t bootloader_init(void) { esp_err_t ret = ESP_OK; bootloader_hardware_init(); - // bootloader_ana_reset_config(); //TODO: [ESP32C61] IDF-9260 + bootloader_ana_reset_config(); bootloader_super_wdt_auto_feed(); // In RAM_APP, memory will be initialized in `call_start_cpu0` diff --git a/components/bootloader_support/src/esp32c61/bootloader_soc.c b/components/bootloader_support/src/esp32c61/bootloader_soc.c index e2876607d664..055fe372bdd8 100644 --- a/components/bootloader_support/src/esp32c61/bootloader_soc.c +++ b/components/bootloader_support/src/esp32c61/bootloader_soc.c @@ -7,19 +7,29 @@ #include #include "soc/soc.h" #include "soc/lp_analog_peri_reg.h" - -//TODO: [ESP32C61] IDF-9260, commented in verify code, check - -void bootloader_ana_super_wdt_reset_config(bool enable) -{ - //C61 doesn't support bypass super WDT reset - assert(enable); - // lp_analog_peri_reg.h updated, now following registers - // REG_CLR_BIT(LP_ANALOG_PERI_LP_ANA_FIB_ENABLE_REG, LP_ANALOG_PERI_LP_ANA_FIB_SUPER_WDT_RST); -} +#include "soc/pmu_reg.h" +#include "hal/regi2c_ctrl.h" +#include "soc/regi2c_saradc.h" //Not supported but common bootloader calls the function. Do nothing void bootloader_ana_clock_glitch_reset_config(bool enable) { (void)enable; } + +void bootloader_power_glitch_reset_config(bool enable, uint8_t dref) +{ + assert(dref < 8); + REG_SET_FIELD(LP_ANA_FIB_ENABLE_REG, LP_ANA_ANA_FIB_PWR_GLITCH_ENA, 0); + if (enable) { + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); + REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PERIF, dref); + REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_VDDPST, dref); + REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PLLBB, dref); + REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PLL, dref); + REG_SET_FIELD(LP_ANA_POWER_GLITCH_CNTL_REG, LP_ANA_POWER_GLITCH_RESET_ENA, 0xf); + } else { + REG_SET_FIELD(LP_ANA_POWER_GLITCH_CNTL_REG, LP_ANA_POWER_GLITCH_RESET_ENA, 0); + } +} diff --git a/components/bootloader_support/src/flash_encryption/flash_encrypt.c b/components/bootloader_support/src/flash_encryption/flash_encrypt.c index 92bc72b21f68..810cd36c2d10 100644 --- a/components/bootloader_support/src/flash_encryption/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encryption/flash_encrypt.c @@ -258,8 +258,7 @@ esp_err_t esp_flash_encrypt_contents(void) REG_WRITE(SENSITIVE_XTS_AES_KEY_UPDATE_REG, 1); #endif -// 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 +#if CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY esp_flash_encryption_enable_key_mgr(); #endif diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 70f8aacbbe1a..143c8e3efb21 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -39,12 +39,20 @@ set(ble_mesh_include_dirs "esp_ble_mesh/api/core/include" "esp_ble_mesh/api/models/include" "esp_ble_mesh/api" +) + +set(ble_mesh_v11_include_dirs "esp_ble_mesh/lib/include" "esp_ble_mesh/v1.1/api/core/include" "esp_ble_mesh/v1.1/api/models/include" "esp_ble_mesh/v1.1/btc/include" ) +if(CONFIG_IDF_DOC_BUILD) + list(APPEND ble_mesh_include_dirs + ${ble_mesh_v11_include_dirs}) +endif() + set(bluedroid_include_dirs host/bluedroid/api/include/api) if(CONFIG_BT_CONTROLLER_ENABLED OR CONFIG_IDF_DOC_BUILD) @@ -524,34 +532,41 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/models/server/server_common.c" "esp_ble_mesh/models/server/state_binding.c" "esp_ble_mesh/models/server/state_transition.c" - "esp_ble_mesh/models/server/time_scene_server.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_agg_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_brc_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_cm_data_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_df_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_lcd_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_odp_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_prb_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_sar_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_srpl_model_api.c" - "esp_ble_mesh/v1.1/api/models/esp_ble_mesh_mbt_model_api.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_agg_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_brc_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_df_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_lcd_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_mbt_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_odp_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_prb_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c" - "esp_ble_mesh/lib/ext.c") - - if(CONFIG_BLE_MESH_SAR_ENHANCEMENT) - list(APPEND srcs "esp_ble_mesh/core/transport.enh.c") + "esp_ble_mesh/models/server/time_scene_server.c") + if(CONFIG_BLE_MESH_V11_SUPPORT) + list(APPEND include_dirs ${ble_mesh_v11_include_dirs}) + + list(APPEND srcs + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_agg_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_brc_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_cm_data_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_df_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_lcd_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_odp_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_prb_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_sar_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_srpl_model_api.c" + "esp_ble_mesh/v1.1/api/models/esp_ble_mesh_mbt_model_api.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_agg_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_brc_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_df_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_lcd_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_mbt_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_odp_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_prb_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c" + "esp_ble_mesh/lib/ext.c") + if(CONFIG_BLE_MESH_SAR_ENHANCEMENT) + list(APPEND srcs "esp_ble_mesh/core/transport.enh.c") + else() + list(APPEND srcs "esp_ble_mesh/core/transport.c") + endif() else() - list(APPEND srcs "esp_ble_mesh/core/transport.c") + list(APPEND srcs + "esp_ble_mesh/core/transport.c") endif() endif() @@ -850,11 +865,19 @@ if(CONFIG_BT_ENABLED) elseif(CONFIG_IDF_TARGET_ESP32C3) target_link_directories(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32c3") - target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app_flash) + else() + target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + endif() elseif(CONFIG_IDF_TARGET_ESP32S3) target_link_directories(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32s3") - target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app_flash) + else() + target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + endif() elseif(CONFIG_BT_CONTROLLER_ENABLED) if(CONFIG_IDF_TARGET_ESP32C6) add_prebuilt_library(libble_app @@ -879,7 +902,7 @@ if(CONFIG_BT_ENABLED) target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") endif() -if(CONFIG_BLE_MESH) +if(CONFIG_BLE_MESH_V11_SUPPORT) if(CONFIG_IDF_TARGET_ESP32) add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32/libble_mesh.a") target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh) @@ -892,6 +915,9 @@ if(CONFIG_BLE_MESH) 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) diff --git a/components/bt/common/btc/core/btc_task.c b/components/bt/common/btc/core/btc_task.c index 875f64b18a52..3729c3dc8dc2 100644 --- a/components/bt/common/btc/core/btc_task.c +++ b/components/bt/common/btc/core/btc_task.c @@ -69,6 +69,12 @@ #include "btc_ble_mesh_prov.h" #include "btc_ble_mesh_health_model.h" #include "btc_ble_mesh_config_model.h" +#include "btc_ble_mesh_generic_model.h" +#include "btc_ble_mesh_lighting_model.h" +#include "btc_ble_mesh_sensor_model.h" +#include "btc_ble_mesh_time_scene_model.h" +#if CONFIG_BLE_MESH_V11_SUPPORT +#include "btc_ble_mesh_mbt_model.h" #include "btc_ble_mesh_agg_model.h" #include "btc_ble_mesh_brc_model.h" #include "btc_ble_mesh_df_model.h" @@ -78,11 +84,7 @@ #include "btc_ble_mesh_rpr_model.h" #include "btc_ble_mesh_sar_model.h" #include "btc_ble_mesh_srpl_model.h" -#include "btc_ble_mesh_generic_model.h" -#include "btc_ble_mesh_lighting_model.h" -#include "btc_ble_mesh_sensor_model.h" -#include "btc_ble_mesh_time_scene_model.h" -#include "btc_ble_mesh_mbt_model.h" +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #endif /* #if CONFIG_BLE_MESH */ #define BTC_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE) @@ -380,7 +382,7 @@ static void btc_deinit_mem(void) { btc_profile_cb_tab = NULL; } -#if (BLE_INCLUDED == TRUE) +#if (BLE_42_FEATURE_SUPPORT == TRUE) if (gl_bta_adv_data_ptr) { osi_free(gl_bta_adv_data_ptr); gl_bta_adv_data_ptr = NULL; @@ -390,7 +392,7 @@ static void btc_deinit_mem(void) { osi_free(gl_bta_scan_rsp_data_ptr); gl_bta_scan_rsp_data_ptr = NULL; } -#endif ///BLE_INCLUDED == TRUE +#endif // BLE_42_FEATURE_SUPPORT #if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE if (btc_creat_tab_env_ptr) { @@ -442,7 +444,8 @@ static bt_status_t btc_init_mem(void) { } memset((void *)btc_profile_cb_tab, 0, sizeof(void *) * BTC_PID_NUM); -#if (BLE_INCLUDED == TRUE) +#if BTC_DYNAMIC_MEMORY == TRUE +#if (BLE_42_FEATURE_SUPPORT == TRUE) if ((gl_bta_adv_data_ptr = (tBTA_BLE_ADV_DATA *)osi_malloc(sizeof(tBTA_BLE_ADV_DATA))) == NULL) { goto error_exit; } @@ -452,7 +455,8 @@ static bt_status_t btc_init_mem(void) { goto error_exit; } memset((void *)gl_bta_scan_rsp_data_ptr, 0, sizeof(tBTA_BLE_ADV_DATA)); -#endif ///BLE_INCLUDED == TRUE +#endif // (BLE_42_FEATURE_SUPPORT == TRUE) +#endif // BTC_DYNAMIC_MEMORY == TRUE #if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE if ((btc_creat_tab_env_ptr = (esp_btc_creat_tab_t *)osi_malloc(sizeof(esp_btc_creat_tab_t))) == NULL) { diff --git a/components/bt/common/hci_log/bt_hci_log.c b/components/bt/common/hci_log/bt_hci_log.c index e35bf1a7a688..ac85179a7070 100644 --- a/components/bt/common/hci_log/bt_hci_log.c +++ b/components/bt/common/hci_log/bt_hci_log.c @@ -305,19 +305,27 @@ 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); } diff --git a/components/bt/common/osi/allocator.c b/components/bt/common/osi/allocator.c index fba9cf0a9e01..86fb705b071d 100644 --- a/components/bt/common/osi/allocator.c +++ b/components/bt/common/osi/allocator.c @@ -241,5 +241,8 @@ void *osi_calloc_func(size_t size) void osi_free_func(void *ptr) { +#if HEAP_MEMORY_DEBUG + osi_mem_dbg_clean(ptr, __func__, __LINE__); +#endif free(ptr); } diff --git a/components/bt/common/osi/include/osi/allocator.h b/components/bt/common/osi/include/osi/allocator.h index 25eca3431b1f..d95040538d86 100644 --- a/components/bt/common/osi/include/osi/allocator.h +++ b/components/bt/common/osi/include/osi/allocator.h @@ -29,6 +29,15 @@ void *osi_malloc_func(size_t size); void *osi_calloc_func(size_t size); void osi_free_func(void *ptr); +// Memory alloc function without print and assertion +#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST +#define osi_malloc_base(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) +#define osi_calloc_base(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) +#else +#define osi_malloc_base(size) malloc((size)) +#define osi_calloc_base(size) calloc(1, (size)) +#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ + #if HEAP_MEMORY_DEBUG void osi_mem_dbg_init(void); @@ -41,33 +50,10 @@ void osi_men_dbg_set_section_start(uint8_t index); void osi_men_dbg_set_section_end(uint8_t index); uint32_t osi_mem_dbg_get_max_size_section(uint8_t index); -#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST -#define osi_malloc(size) \ -({ \ - void *p; \ - p = heap_caps_malloc_prefer(size, 2, \ - MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, \ - MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \ - osi_mem_dbg_record(p, size, __func__, __LINE__); \ - (void *)p; \ -}) - -#define osi_calloc(size) \ -({ \ - void *p; \ - p = heap_caps_calloc_prefer(1, size, 2, \ - MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, \ - MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \ - osi_mem_dbg_record(p, size, __func__, __LINE__); \ - (void *)p; \ -}) - -#else - #define osi_malloc(size) \ ({ \ void *p; \ - p = malloc((size)); \ + p = osi_malloc_base(size); \ osi_mem_dbg_record(p, size, __func__, __LINE__); \ (void *)p; \ }) @@ -75,14 +61,11 @@ uint32_t osi_mem_dbg_get_max_size_section(uint8_t index); #define osi_calloc(size) \ ({ \ void *p; \ - p = calloc(1, (size)); \ + p = osi_calloc_base(size); \ osi_mem_dbg_record(p, size, __func__, __LINE__); \ (void *)p; \ }) -#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ - - #if 0 #define osi_malloc(size) \ do { \ @@ -122,15 +105,6 @@ do { \ #else -// Memory alloc function without print and assertion -#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST -#define osi_malloc_base(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) -#define osi_calloc_base(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) -#else -#define osi_malloc_base(size) malloc((size)) -#define osi_calloc_base(size) calloc(1, (size)) -#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ - // Memory alloc function with print and assertion when fails #define osi_malloc(size) osi_malloc_func((size)) #define osi_calloc(size) osi_calloc_func((size)) diff --git a/components/bt/controller/esp32/Kconfig.in b/components/bt/controller/esp32/Kconfig.in index 191738d0d227..0fd0b6e4137b 100644 --- a/components/bt/controller/esp32/Kconfig.in +++ b/components/bt/controller/esp32/Kconfig.in @@ -300,10 +300,10 @@ menu "MODEM SLEEP Options" the bluetooth low power clock source. config BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL - bool "External 32kHz crystal" - depends on RTC_CLK_SRC_EXT_CRYS + bool "External 32kHz crystal/oscillator" + depends on RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC help - External 32kHz crystal has a nominal frequency of 32.768kHz and provides good frequency + External 32kHz crystal/oscillator has a nominal frequency of 32.768kHz and provides good frequency stability. If used as Bluetooth low power clock, External 32kHz can support Bluetooth modem sleep to be used with both DFS and light sleep. endchoice @@ -478,6 +478,23 @@ 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 diff --git a/components/bt/controller/esp32c3/Kconfig.in b/components/bt/controller/esp32c3/Kconfig.in index 5178ef860210..0121b3404a19 100644 --- a/components/bt/controller/esp32c3/Kconfig.in +++ b/components/bt/controller/esp32c3/Kconfig.in @@ -226,6 +226,7 @@ config BT_CTRL_DFT_TX_POWER_LEVEL_EFF config BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP bool "BLE adv report flow control supported" + depends on (!BT_CTRL_RUN_IN_FLASH_ONLY) || (BT_CTRL_RUN_IN_FLASH_ONLY && BT_CTRL_BLE_SCAN) default y help The function is mainly used to enable flow control for advertising reports. When it is enabled, @@ -402,10 +403,10 @@ menu "MODEM SLEEP Options" bluetooth can work under light sleep enabled. Main crystal has a relatively better performance than other bluetooth low power clock sources. config BT_CTRL_LPCLK_SEL_EXT_32K_XTAL - bool "External 32kHz crystal" - depends on RTC_CLK_SRC_EXT_CRYS + bool "External 32kHz crystal/oscillator" + depends on RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC help - External 32kHz crystal has a nominal frequency of 32.768kHz and provides good frequency + External 32kHz crystal/oscillator has a nominal frequency of 32.768kHz and provides good frequency stability. If used as Bluetooth low power clock, External 32kHz can support Bluetooth modem sleep to be used with both DFS and light sleep. @@ -489,3 +490,61 @@ 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 +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Put all BLE Controller code in flash" + default n + help + If this option is enabled, all code for the Bluetooth controller will be moved from ROM and IRAM + to flash, saving over 20K bytes of memory. However, it will require more flash resources and the + performance of Bluetooth will decrease If this option is enabled, Bluetooth may not work properly + during erasing flash. It is recommended to turn on the auto suspend function of flash. After auto + suspend is turned on, Bluetooth interrupts can be executed normally during erasing flash, with less + impact on Bluetooth performance. + +config BT_CTRL_DTM_ENABLE + depends on BT_CTRL_RUN_IN_FLASH_ONLY + bool "Enable direct test mode feature" + default n + +config BT_CTRL_BLE_MASTER + depends on BT_CTRL_RUN_IN_FLASH_ONLY + bool "Enable BLE master role feature" + default y + +config BT_CTRL_BLE_TEST + depends on BT_CTRL_RUN_IN_FLASH_ONLY + bool "Enable BLE QA test feature" + default n + +config BT_CTRL_BLE_SCAN + depends on BT_CTRL_RUN_IN_FLASH_ONLY + bool "Enable BLE scan feature" + default y + +config BT_CTRL_BLE_SECURITY_ENABLE + depends on BT_CTRL_RUN_IN_FLASH_ONLY && BT_CONTROLLER_ONLY + bool "Enable BLE security feature" + default y diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index 34c6ff9816d6..c943fb92fad1 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -499,7 +499,11 @@ static int interrupt_alloc_wrapper(int cpu_id, int source, intr_handler_t handle { btdm_isr_alloc_t p; p.source = source; +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + p.flags = ESP_INTR_FLAG_LEVEL3; +#else p.flags = ESP_INTR_FLAG_LEVEL3 | ESP_INTR_FLAG_IRAM; +#endif p.fn = handler; p.arg = arg; p.handle = (intr_handle_t *)ret_handle; @@ -1426,6 +1430,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGI(BT_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version()); +#if (CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + ESP_LOGI(BT_LOG_TAG,"Put all controller code in flash"); +#endif + if ((err = btdm_low_power_mode_init(cfg)) != ESP_OK) { ESP_LOGE(BT_LOG_TAG, "Low power module initialization failed"); goto error; diff --git a/components/bt/controller/esp32c5/bt.c b/components/bt/controller/esp32c5/bt.c index c0ed4fff553f..de235b3fe025 100644 --- a/components/bt/controller/esp32c5/bt.c +++ b/components/bt/controller/esp32c5/bt.c @@ -184,7 +184,6 @@ 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; @@ -404,7 +403,7 @@ static void sleep_modem_ble_mac_modem_state_deinit(void) } } -void sleep_modem_light_sleep_overhead_set(uint32_t overhead) +void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead) { r_esp_ble_set_wakeup_overhead(overhead); } @@ -424,16 +423,19 @@ 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; } -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // CONFIG_PM_ENABLE + +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE /* Create a new regdma link for BLE related register restoration */ rc = sleep_modem_ble_mac_modem_state_init(0); - assert(rc == 0); + if (rc != ESP_OK) { + goto error; + } esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); @@ -446,19 +448,21 @@ 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_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ return rc; +#ifdef CONFIG_PM_ENABLE error: - -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#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 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_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#ifdef CONFIG_PM_ENABLE /*lock should release first and then delete*/ if (s_pm_lock != NULL) { esp_pm_lock_delete(s_pm_lock); @@ -471,7 +475,7 @@ esp_err_t controller_sleep_init(void) void controller_sleep_deinit(void) { -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if CONFIG_BT_LE_SLEEP_ENABLE && 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); diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index 8bc3992e4415..828efa09f6e3 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -388,7 +388,6 @@ 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; @@ -612,7 +611,7 @@ static void sleep_modem_ble_mac_modem_state_deinit(void) } } -void sleep_modem_light_sleep_overhead_set(uint32_t overhead) +void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead) { r_esp_ble_set_wakeup_overhead(overhead); } @@ -639,17 +638,20 @@ esp_err_t controller_sleep_init(void) if (rc != ESP_OK) { goto error; } -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE -#if CONFIG_BT_LE_SLEEP_ENABLE && SOC_PM_RETENTION_HAS_CLOCK_BUG && !CONFIG_MAC_BB_PD +#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 #error "CONFIG_MAC_BB_PD required for BLE light sleep to run properly" -#endif // CONFIG_BT_LE_SLEEP_ENABLE && SOC_PM_RETENTION_HAS_CLOCK_BUG && !CONFIG_MAC_BB_PD +#endif // 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 - assert(rc == 0); + if (rc != ESP_OK) { + goto error; + } esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); @@ -662,19 +664,21 @@ 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_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ return rc; +#ifdef CONFIG_PM_ENABLE error: - -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#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 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_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#ifdef CONFIG_PM_ENABLE /*lock should release first and then delete*/ if (s_pm_lock != NULL) { esp_pm_lock_delete(s_pm_lock); @@ -687,7 +691,7 @@ esp_err_t controller_sleep_init(void) void controller_sleep_deinit(void) { -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if CONFIG_BT_LE_SLEEP_ENABLE && 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); @@ -696,7 +700,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_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ #ifdef CONFIG_PM_ENABLE /* lock should be released first */ esp_pm_lock_delete(s_pm_lock); diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index 9a46b2ca6c2c..8830a2018e75 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -385,7 +385,6 @@ 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; @@ -604,7 +603,7 @@ static void sleep_modem_ble_mac_modem_state_deinit(void) } } -void sleep_modem_light_sleep_overhead_set(uint32_t overhead) +void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead) { r_esp_ble_set_wakeup_overhead(overhead); } @@ -631,13 +630,17 @@ 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); - assert(rc == 0); -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + if (rc != ESP_OK) { + goto error; + } +#endif //CONFIG_PM_ENABLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE /* Create a new regdma link for BLE related register restoration */ rc = sleep_modem_ble_mac_modem_state_init(0); - assert(rc == 0); + if (rc != ESP_OK) { + goto error; + } esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); @@ -645,15 +648,17 @@ esp_err_t controller_sleep_init(void) if (rc != ESP_OK) { goto error; } -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ return rc; +#ifdef CONFIG_PM_ENABLE error: - -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // CONFIG_PM_ENABLE +#if CONFIG_BT_LE_SLEEP_ENABLE && 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_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#ifdef CONFIG_PM_ENABLE esp_deep_sleep_deregister_hook(&r_esp_ble_stop_wakeup_timing); /*lock should release first and then delete*/ if (s_pm_lock != NULL) { @@ -667,12 +672,12 @@ esp_err_t controller_sleep_init(void) void controller_sleep_deinit(void) { -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if CONFIG_BT_LE_SLEEP_ENABLE && 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_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && 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 */ diff --git a/components/bt/controller/lib_esp32 b/components/bt/controller/lib_esp32 index 22a4e62193eb..c3f6258cfbd7 160000 --- a/components/bt/controller/lib_esp32 +++ b/components/bt/controller/lib_esp32 @@ -1 +1 @@ -Subproject commit 22a4e62193eb8bf9c747c9ec826fece57b40c042 +Subproject commit c3f6258cfbd776d51e30bd6168f42b0cf5d73ea8 diff --git a/components/bt/controller/lib_esp32c3_family b/components/bt/controller/lib_esp32c3_family index 061e70c31957..6470c01165cf 160000 --- a/components/bt/controller/lib_esp32c3_family +++ b/components/bt/controller/lib_esp32c3_family @@ -1 +1 @@ -Subproject commit 061e70c319576bf28b5695f5478dbe01ad18b18d +Subproject commit 6470c01165cf4edeed5d826ce4082a90deb92efd diff --git a/components/bt/controller/lib_esp32c6/esp32c6-bt-lib b/components/bt/controller/lib_esp32c6/esp32c6-bt-lib index 69f16a7a63a0..b86a06d38cc3 160000 --- a/components/bt/controller/lib_esp32c6/esp32c6-bt-lib +++ b/components/bt/controller/lib_esp32c6/esp32c6-bt-lib @@ -1 +1 @@ -Subproject commit 69f16a7a63a08032d81ee86649ca0e6f5d343f40 +Subproject commit b86a06d38cc3de4660b67d992259f727ba590296 diff --git a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib index 50f567fff506..90f1ef76ab90 160000 --- a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib +++ b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib @@ -1 +1 @@ -Subproject commit 50f567fff506f63b4d06ebea80d0405fe9e39568 +Subproject commit 90f1ef76ab9021b123e3037e9df782549f386e30 diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index 17d23ba94ec6..47c6fad2c030 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -6,6 +6,12 @@ if BLE_MESH help It is a temporary solution and needs further modifications. + config BLE_MESH_V11_SUPPORT + bool "Support ESP BLE Mesh v1.1 features (Preview)" + default y + help + Support BLE Mesh v1.1 features + config BLE_MESH_RANDOM_ADV_INTERVAL bool "Support using random adv interval for mesh packets" select BT_BLE_HIGH_DUTY_ADV_INTERVAL if BT_BLUEDROID_ENABLED @@ -32,6 +38,7 @@ if BLE_MESH config BLE_MESH_ACTIVE_SCAN bool "Support Active Scan in BLE Mesh" + depends on BLE_MESH_V11_SUPPORT help Enable this option to allow using BLE Active Scan for BLE Mesh. @@ -281,6 +288,7 @@ if BLE_MESH config BLE_MESH_PROV_EPA bool "BLE Mesh enhanced provisioning authentication" depends on BLE_MESH_PROV + depends on BLE_MESH_V11_SUPPORT default y help Enable this option to support BLE Mesh enhanced provisioning authentication @@ -290,6 +298,7 @@ if BLE_MESH config BLE_MESH_CERT_BASED_PROV bool "Support Certificate-based provisioning" depends on BLE_MESH_PROV + depends on BLE_MESH_V11_SUPPORT default n help Enable this option to support BLE Mesh Certificate-Based Provisioning. @@ -390,6 +399,7 @@ if BLE_MESH config BLE_MESH_PROXY_SOLIC_PDU_RX bool "Support receiving Proxy Solicitation PDU" depends on BLE_MESH_GATT_PROXY_SERVER + depends on BLE_MESH_V11_SUPPORT help Enable this option to support receiving Proxy Solicitation PDU. @@ -417,6 +427,7 @@ if BLE_MESH config BLE_MESH_PROXY_SOLIC_PDU_TX bool "Support sending Proxy Solicitation PDU" depends on BLE_MESH_GATT_PROXY_CLIENT + depends on BLE_MESH_V11_SUPPORT help Enable this option to support sending Proxy Solicitation PDU. @@ -703,6 +714,7 @@ if BLE_MESH to perform the IV index recovery procedure. config BLE_MESH_SAR_ENHANCEMENT + depends on BLE_MESH_V11_SUPPORT bool "Segmentation and reassembly enhancement" default n help @@ -1102,253 +1114,257 @@ if BLE_MESH help Enable support for Health Server model. - config BLE_MESH_BRC_CLI - bool "Bridge Configuration Client model" - help - Enable support for Bridge Configuration Client model. - - config BLE_MESH_BRC_SRV - bool "Bridge Configuration Server model" - default n - help - Enable support for Bridge Configuration Server model. - - if BLE_MESH_BRC_SRV + if BLE_MESH_V11_SUPPORT - config BLE_MESH_MAX_BRIDGING_TABLE_ENTRY_COUNT - int "Maximum number of Bridging Table entries" - range 16 65535 - default 16 + config BLE_MESH_BRC_CLI + bool "Bridge Configuration Client model" help - Maximum number of Bridging Table entries that the Bridge Configuration Server can support. + Enable support for Bridge Configuration Client model. - config BLE_MESH_BRIDGE_CRPL - int "Maximum capacity of bridge replay protection list" - default 5 - range 1 255 + config BLE_MESH_BRC_SRV + bool "Bridge Configuration Server model" + default n help - This option specifies the maximum capacity of the bridge replay - protection list. The bridge replay protection list is used to - prevent a bridged subnet from replay attack, which will store the - source address and sequence number of the received bridge messages. + Enable support for Bridge Configuration Server model. - endif #BLE_MESH_BRC_SRV + if BLE_MESH_BRC_SRV - config BLE_MESH_PRB_CLI - bool "Mesh Private Beacon Client model" - help - Enable support for Mesh Private Beacon Client model. + config BLE_MESH_MAX_BRIDGING_TABLE_ENTRY_COUNT + int "Maximum number of Bridging Table entries" + range 16 65535 + default 16 + help + Maximum number of Bridging Table entries that the Bridge Configuration Server can support. - config BLE_MESH_PRB_SRV - bool "Mesh Private Beacon Server model" - help - Enable support for Mesh Private Beacon Server model. + config BLE_MESH_BRIDGE_CRPL + int "Maximum capacity of bridge replay protection list" + default 5 + range 1 255 + help + This option specifies the maximum capacity of the bridge replay + protection list. The bridge replay protection list is used to + prevent a bridged subnet from replay attack, which will store the + source address and sequence number of the received bridge messages. - config BLE_MESH_ODP_CLI - bool "On-Demand Private Proxy Client model" - help - Enable support for On-Demand Private Proxy Client model. + endif #BLE_MESH_BRC_SRV - config BLE_MESH_ODP_SRV - bool "On-Demand Private Proxy Server model" - depends on BLE_MESH_PROXY_SOLIC_PDU_RX - select BLE_MESH_SRPL_SRV - help - Enable support for On-Demand Private Proxy Server model. + config BLE_MESH_PRB_CLI + bool "Mesh Private Beacon Client model" + help + Enable support for Mesh Private Beacon Client model. - config BLE_MESH_SRPL_CLI - bool "Solicitation PDU RPL Configuration Client model" - help - Enable support for Solicitation PDU RPL Configuration Client model. + config BLE_MESH_PRB_SRV + bool "Mesh Private Beacon Server model" + help + Enable support for Mesh Private Beacon Server model. - config BLE_MESH_SRPL_SRV - bool "Solicitation PDU RPL Configuration Server model" - depends on BLE_MESH_PROXY_SOLIC_PDU_RX - help - Enable support for Solicitation PDU RPL Configuration Server model. - Note: - This option depends on the functionality of receiving Solicitation - PDU. If the device doesn't support receiving Solicitation PDU, then - there is no need to enable this server model. + config BLE_MESH_ODP_CLI + bool "On-Demand Private Proxy Client model" + help + Enable support for On-Demand Private Proxy Client model. - config BLE_MESH_AGG_CLI - bool "Opcodes Aggregator Client model" - help - Enable support for Opcodes Aggregator Client model. + config BLE_MESH_ODP_SRV + bool "On-Demand Private Proxy Server model" + depends on BLE_MESH_PROXY_SOLIC_PDU_RX + select BLE_MESH_SRPL_SRV + help + Enable support for On-Demand Private Proxy Server model. - config BLE_MESH_AGG_SRV - bool "Opcodes Aggregator Server model" - help - Enable support for Opcodes Aggregator Server model. + config BLE_MESH_SRPL_CLI + bool "Solicitation PDU RPL Configuration Client model" + help + Enable support for Solicitation PDU RPL Configuration Client model. - config BLE_MESH_SAR_CLI - bool "SAR Configuration Client model" - help - Enable support for SAR Configuration Client model. + config BLE_MESH_SRPL_SRV + bool "Solicitation PDU RPL Configuration Server model" + depends on BLE_MESH_PROXY_SOLIC_PDU_RX + help + Enable support for Solicitation PDU RPL Configuration Server model. + Note: + This option depends on the functionality of receiving Solicitation + PDU. If the device doesn't support receiving Solicitation PDU, then + there is no need to enable this server model. + + config BLE_MESH_AGG_CLI + bool "Opcodes Aggregator Client model" + help + Enable support for Opcodes Aggregator Client model. - config BLE_MESH_SAR_SRV - bool "SAR Configuration Server model" - help - Enable support for SAR Configuration Server model. + config BLE_MESH_AGG_SRV + bool "Opcodes Aggregator Server model" + help + Enable support for Opcodes Aggregator Server model. - config BLE_MESH_COMP_DATA_1 - bool "Support Composition Data Page 1" - help - Composition Data Page 1 contains information about the relationships - among models. - Each model either can be a root model or can extend other models. + config BLE_MESH_SAR_CLI + bool "SAR Configuration Client model" + help + Enable support for SAR Configuration Client model. - config BLE_MESH_COMP_DATA_128 - bool "Support Composition Data Page 128" - help - Composition Data Page 128 is used to indicate the structure of - elements, features, and models of a node after the successful - execution of the Node Address Refresh procedure or the Node - Composition Refresh procedure, or after the execution of the - Node Removal procedure followed by the provisioning process. - Composition Data Page 128 shall be present if the node supports - the Remote Provisioning Server model; otherwise it is optional. + config BLE_MESH_SAR_SRV + bool "SAR Configuration Server model" + help + Enable support for SAR Configuration Server model. - config BLE_MESH_MODELS_METADATA_0 - bool "Support Models Metadata Page 0" - help - The Models Metadata state contains metadata of a node’s models. - The Models Metadata state is composed of a number of pages of - information. - Models Metadata Page 0 shall be present if the node supports - the Large Composition Data Server model. + config BLE_MESH_COMP_DATA_1 + bool "Support Composition Data Page 1" + help + Composition Data Page 1 contains information about the relationships + among models. + Each model either can be a root model or can extend other models. - config BLE_MESH_MODELS_METADATA_128 - bool "Support Models Metadata Page 128" - depends on BLE_MESH_MODELS_METADATA_0 - help - The Models Metadata state contains metadata of a node’s models. - The Models Metadata state is composed of a number of pages of - information. - Models Metadata Page 128 contains metadata for the node’s models - after the successful execution of the Node Address Refresh - procedure or the Node Composition Refresh procedure, or after - the execution of the Node Removal procedure followed by the - provisioning process. - Models Metadata Page 128 shall be present if the node supports - the Remote Provisioning Server model and the node supports the - Large Composition Data Server model. + config BLE_MESH_COMP_DATA_128 + bool "Support Composition Data Page 128" + help + Composition Data Page 128 is used to indicate the structure of + elements, features, and models of a node after the successful + execution of the Node Address Refresh procedure or the Node + Composition Refresh procedure, or after the execution of the + Node Removal procedure followed by the provisioning process. + Composition Data Page 128 shall be present if the node supports + the Remote Provisioning Server model; otherwise it is optional. + + config BLE_MESH_MODELS_METADATA_0 + bool "Support Models Metadata Page 0" + help + The Models Metadata state contains metadata of a node’s models. + The Models Metadata state is composed of a number of pages of + information. + Models Metadata Page 0 shall be present if the node supports + the Large Composition Data Server model. + + config BLE_MESH_MODELS_METADATA_128 + bool "Support Models Metadata Page 128" + depends on BLE_MESH_MODELS_METADATA_0 + help + The Models Metadata state contains metadata of a node’s models. + The Models Metadata state is composed of a number of pages of + information. + Models Metadata Page 128 contains metadata for the node’s models + after the successful execution of the Node Address Refresh + procedure or the Node Composition Refresh procedure, or after + the execution of the Node Removal procedure followed by the + provisioning process. + Models Metadata Page 128 shall be present if the node supports + the Remote Provisioning Server model and the node supports the + Large Composition Data Server model. + + config BLE_MESH_LCD_CLI + bool "Large Composition Data Client model" + help + Enable support for Large Composition Data Client model. - config BLE_MESH_LCD_CLI - bool "Large Composition Data Client model" - help - Enable support for Large Composition Data Client model. + config BLE_MESH_LCD_SRV + bool "Large Composition Data Server model" + select BLE_MESH_MODELS_METADATA_0 + help + Enable support for Large Composition Data Server model. - config BLE_MESH_LCD_SRV - bool "Large Composition Data Server model" - select BLE_MESH_MODELS_METADATA_0 - help - Enable support for Large Composition Data Server model. + config BLE_MESH_RPR_CLI + bool "Remote Provisioning Client model" + depends on BLE_MESH_PROVISIONER + select BLE_MESH_PROV + help + Enable support for Remote Provisioning Client model - config BLE_MESH_RPR_CLI - bool "Remote Provisioning Client model" - depends on BLE_MESH_PROVISIONER - select BLE_MESH_PROV - help - Enable support for Remote Provisioning Client model + if BLE_MESH_RPR_CLI - if BLE_MESH_RPR_CLI + config BLE_MESH_RPR_CLI_PROV_SAME_TIME + int "Maximum number of PB-Remote running at the same time by Provisioner" + range 1 5 + default 2 + help + This option specifies how many devices can be provisioned at the same time + using PB-REMOTE. For example, if the value is 2, it means a Provisioner can + provision two unprovisioned devices with PB-REMOTE at the same time. - config BLE_MESH_RPR_CLI_PROV_SAME_TIME - int "Maximum number of PB-Remote running at the same time by Provisioner" - range 1 5 - default 2 + endif # BLE_MESH_RPR_CLI + + config BLE_MESH_RPR_SRV + bool "Remote Provisioning Server model" + depends on BLE_MESH_NODE + select BLE_MESH_PB_ADV help - This option specifies how many devices can be provisioned at the same time - using PB-REMOTE. For example, if the value is 2, it means a Provisioner can - provision two unprovisioned devices with PB-REMOTE at the same time. + Enable support for Remote Provisioning Server model - endif # BLE_MESH_RPR_CLI + if BLE_MESH_RPR_SRV - config BLE_MESH_RPR_SRV - bool "Remote Provisioning Server model" - depends on BLE_MESH_NODE - select BLE_MESH_PB_ADV - help - Enable support for Remote Provisioning Server model + config BLE_MESH_RPR_SRV_MAX_SCANNED_ITEMS + int "Maximum number of device information can be scanned" + range 4 255 + default 10 + help + This option specifies how many device information can a Remote + Provisioning Server store each time while scanning. - if BLE_MESH_RPR_SRV + config BLE_MESH_RPR_SRV_ACTIVE_SCAN + bool "Support Active Scan for remote provisioning" + select BLE_MESH_ACTIVE_SCAN + help + Enable this option to support Active Scan for remote provisioning. - config BLE_MESH_RPR_SRV_MAX_SCANNED_ITEMS - int "Maximum number of device information can be scanned" - range 4 255 - default 10 - help - This option specifies how many device information can a Remote - Provisioning Server store each time while scanning. + config BLE_MESH_RPR_SRV_MAX_EXT_SCAN + int "Maximum number of extended scan procedures" + range 1 10 + default 1 + help + This option specifies how many extended scan procedures can be + started by the Remote Provisioning Server. - config BLE_MESH_RPR_SRV_ACTIVE_SCAN - bool "Support Active Scan for remote provisioning" - select BLE_MESH_ACTIVE_SCAN - help - Enable this option to support Active Scan for remote provisioning. + endif # BLE_MESH_RPR_SRV - config BLE_MESH_RPR_SRV_MAX_EXT_SCAN - int "Maximum number of extended scan procedures" - range 1 10 - default 1 + config BLE_MESH_DF_CLI + bool "Directed Forwarding Configuration Client model" help - This option specifies how many extended scan procedures can be - started by the Remote Provisioning Server. + Enable support for Directed Forwarding Configuration Client model. - endif # BLE_MESH_RPR_SRV + config BLE_MESH_DF_SRV + bool "Directed Forwarding Configuration Server model" + help + Enable support for Directed Forwarding Configuration Server model. - config BLE_MESH_DF_CLI - bool "Directed Forwarding Configuration Client model" - help - Enable support for Directed Forwarding Configuration Client model. + if BLE_MESH_DF_SRV - config BLE_MESH_DF_SRV - bool "Directed Forwarding Configuration Server model" - help - Enable support for Directed Forwarding Configuration Server model. + config BLE_MESH_MAX_DISC_TABLE_ENTRY_COUNT + int "Maximum number of discovery table entries in a given subnet" + range 2 255 + default 2 + help + Maximum number of Discovery Table entries supported by the node in a given subnet. - if BLE_MESH_DF_SRV + config BLE_MESH_MAX_FORWARD_TABLE_ENTRY_COUNT + int "Maximum number of forward table entries in a given subnet" + range 2 64 + default 2 + help + Maximum number of Forward Table entries supported by the node in a given subnet. - config BLE_MESH_MAX_DISC_TABLE_ENTRY_COUNT - int "Maximum number of discovery table entries in a given subnet" - range 2 255 - default 2 - help - Maximum number of Discovery Table entries supported by the node in a given subnet. + config BLE_MESH_MAX_DEPS_NODES_PER_PATH + int "Maximum number of dependent nodes per path" + range 2 64 + default 2 + help + Maximum size of dependent nodes list supported by each forward table entry. - config BLE_MESH_MAX_FORWARD_TABLE_ENTRY_COUNT - int "Maximum number of forward table entries in a given subnet" - range 2 64 - default 2 - help - Maximum number of Forward Table entries supported by the node in a given subnet. + config BLE_MESH_PATH_MONITOR_TEST + bool "Enable Path Monitoring test mode" + default n + help + The option only removes the Path Use timer; all other behavior of the + device is not changed. + If Path Monitoring test mode is going to be used, this option should + be enabled. - config BLE_MESH_MAX_DEPS_NODES_PER_PATH - int "Maximum number of dependent nodes per path" - range 2 64 - default 2 - help - Maximum size of dependent nodes list supported by each forward table entry. + if BLE_MESH_GATT_PROXY_SERVER + config BLE_MESH_SUPPORT_DIRECTED_PROXY + bool "Enable Directed Proxy functionality" + default y + help + Support Directed Proxy functionality. + endif - config BLE_MESH_PATH_MONITOR_TEST - bool "Enable Path Monitoring test mode" - default n - help - The option only removes the Path Use timer; all other behavior of the - device is not changed. - If Path Monitoring test mode is going to be used, this option should - be enabled. - - if BLE_MESH_GATT_PROXY_SERVER - config BLE_MESH_SUPPORT_DIRECTED_PROXY - bool "Enable Directed Proxy functionality" - default y - help - Support Directed Proxy functionality. - endif + endif # BLE_MESH_DF_SRV - endif # BLE_MESH_DF_SRV + endif # BLE_MESH_V11_SUPPORT endmenu #Support for BLE Mesh Foundation models @@ -1465,6 +1481,7 @@ if BLE_MESH config BLE_MESH_MBT_CLI bool "BLOB Transfer Client model" + depends on BLE_MESH_V11_SUPPORT default n help Enable support for BLOB Transfer Client model. @@ -1483,6 +1500,7 @@ if BLE_MESH config BLE_MESH_MBT_SRV bool "BLOB Transfer Server model" + depends on BLE_MESH_V11_SUPPORT default n help Enable support for BLOB Transfer Server model. diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index 67d5353be8fa..f6cdb426f1b5 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -10,11 +10,13 @@ #include "btc_ble_mesh_prov.h" #include "btc_ble_mesh_config_model.h" #include "btc_ble_mesh_health_model.h" -#include "btc_ble_mesh_prb_model.h" #include "btc_ble_mesh_generic_model.h" #include "btc_ble_mesh_time_scene_model.h" #include "btc_ble_mesh_sensor_model.h" #include "btc_ble_mesh_lighting_model.h" + +#if CONFIG_BLE_MESH_V11_SUPPORT +#include "btc_ble_mesh_prb_model.h" #include "btc_ble_mesh_brc_model.h" #include "btc_ble_mesh_odp_model.h" #include "btc_ble_mesh_srpl_model.h" @@ -24,6 +26,8 @@ #include "btc_ble_mesh_rpr_model.h" #include "btc_ble_mesh_df_model.h" #include "btc_ble_mesh_mbt_model.h" +#include "mesh_v1.1/utils.h" +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #include "adv.h" #include "mesh/kernel.h" @@ -65,8 +69,6 @@ #include "mesh/state_binding.h" #include "local.h" -#include "mesh_v1.1/utils.h" - #include "esp_ble_mesh_common_api.h" #include "esp_ble_mesh_provisioning_api.h" #include "esp_ble_mesh_networking_api.h" diff --git a/components/bt/esp_ble_mesh/core/access.c b/components/bt/esp_ble_mesh/core/access.c index 9606581eb89f..3791add9e34f 100644 --- a/components/bt/esp_ble_mesh/core/access.c +++ b/components/bt/esp_ble_mesh/core/access.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ #include #include "mesh.h" +#include "tag.h" #include "adv.h" #include "lpn.h" #include "friend.h" @@ -22,7 +23,9 @@ #include "fast_prov.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define BLE_MESH_SDU_MAX_LEN 384 @@ -814,6 +817,135 @@ static bool ready_to_send(uint16_t dst) return false; } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static bool use_friend_cred(uint16_t net_idx, uint16_t dst) +{ + /* Currently LPN only supports using NetKey in bt_mesh.sub[0] */ + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && + net_idx == 0 && + bt_mesh_lpn_match(dst)) { + return true; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + bt_mesh_friend_match(net_idx, dst)) { + return true; + } + + return false; +} + +bool bt_mesh_valid_security_cred(struct bt_mesh_net_tx *tx) +{ + /* If the message is tagged with immutable-credentials, + * then the security credentials shall not be changed + * in lower layers. + * If not, later a better security credentials could be + * chosen for the message. + */ + if (!bt_mesh_tag_immutable_cred(tx->ctx->send_tag)) { + return true; + } + + if (tx->ctx->send_cred > BLE_MESH_FRIENDSHIP_CRED) { + return false; + } + + if (tx->ctx->send_cred == BLE_MESH_FRIENDSHIP_CRED && + !use_friend_cred(tx->ctx->net_idx, tx->ctx->addr)) { + return false; + } + + return true; +} + +void bt_mesh_choose_better_security_cred(struct bt_mesh_net_tx *tx) +{ + uint8_t send_cred = 0U; + uint8_t send_tag = 0U; + uint16_t net_idx = 0U; + uint16_t addr = 0U; + + send_cred = tx->ctx->send_cred; + send_tag = tx->ctx->send_tag; + net_idx = tx->ctx->net_idx; + addr = tx->ctx->addr; + + /* If the message is tagged with immutable-credentials, + * then the security credentials shall not be changed. + */ + if (bt_mesh_tag_immutable_cred(send_tag)) { + return; + } + + if (send_cred > BLE_MESH_FRIENDSHIP_CRED) { + BT_INFO("Use managed flooding security credentials"); + tx->ctx->send_cred = BLE_MESH_FLOODING_CRED; + return; + } + + if (send_cred == BLE_MESH_FRIENDSHIP_CRED) { + if (!use_friend_cred(net_idx, addr)) { + BT_INFO("Use managed flooding security credentials"); + tx->ctx->send_cred = BLE_MESH_FLOODING_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + } else { + /* TODO: + * For LPN, do we need to change the friendship security + * credentials to managed flooding credentials? + * If changed, this could increase the possibility that + * the corresponding Friend node receives this message. + */ + } + return; + } + + /* If the message is destinated to a LPN, the following could be + * introduced to send the message with the friendship credentials. + * + * For LPN, this optimization should not be introduced, since it + * may cause the message failed to received by the Friend node, + * using friendship credentials will make the message can not be + * relayed by other mesh nodes. + */ + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + BLE_MESH_ADDR_IS_UNICAST(addr) && + bt_mesh_friend_match(net_idx, addr)) { + BT_INFO("Use friendship security credentials"); + tx->ctx->send_cred = BLE_MESH_FRIENDSHIP_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + return; + } + + /** + * Spec 3.7.3.1 + * The Low power node in friendship should use friendship security + * material. + * + * But in Spec 3.6.6.2 + * Depending on the value of the Publish Friendship Credentials Flag + * (see Section 4.2.3.4), the Low Power node model publishes messages + * using either the friendship security credentials or the managed + * flooding security credentials (see Section 3.9.6.3.1). + * + * So use the BLE_MESH_TAG_IMMUTABLE_CRED to indicate that the + * credentials of the message should not be changed when the + * message is sent by model publishing, even though the spec + * didn't require this flag to be set when model publishing. + */ + +#if CONFIG_BLE_MESH_LOW_POWER + if (BLE_MESH_ADDR_IS_UNICAST(addr) && + bt_mesh.lpn.frnd == addr && + !bt_mesh_tag_immutable_cred(send_tag)) { + tx->ctx->send_cred = BLE_MESH_FRIENDSHIP_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + return; + } +#endif +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static int model_send(struct bt_mesh_model *model, struct bt_mesh_net_tx *tx, bool implicit_bind, struct net_buf_simple *msg, @@ -1108,11 +1240,13 @@ size_t bt_mesh_rx_devkey_size(void) #if CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioned()) { size = 1; +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_dev_key_ca_valid()) { size += 1; } +#endif /* CONFIG_BLE_MESH_RPR_SRV */ } -#endif +#endif /* CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER */ #if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { @@ -1122,9 +1256,11 @@ size_t bt_mesh_rx_devkey_size(void) #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER size = 1; +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_dev_key_ca_valid()) { size += 1; } +#endif /* CONFIG_BLE_MESH_RPR_SRV */ if (bt_mesh_is_provisioner_en()) { size += 1; } @@ -1156,7 +1292,9 @@ const uint8_t *bt_mesh_rx_devkey_get(size_t index, uint16_t src) #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (index == 0) { key = bt_mesh.dev_key; - } else if (index == 1 && bt_mesh_dev_key_ca_valid()) { + } else +#if CONFIG_BLE_MESH_RPR_SRV + if (index == 1 && bt_mesh_dev_key_ca_valid()) { /* If index == 1, there are two cases. * 1. bt_mesh_dev_key_ca_valid() is true, it should be return bt_mesh.dev_key_ca. * 2. bt_mesh_is_provisioner_en() is true, it should be return bt_mesh_provisioner_dev_key_get(src). @@ -1166,7 +1304,9 @@ const uint8_t *bt_mesh_rx_devkey_get(size_t index, uint16_t src) * Then this round of function bt_mesh_rx_devkey_get(2, src) will return bt_mesh_provisioner_dev_key_get(src). */ key = bt_mesh.dev_key_ca; - } else { + } else +#endif + { key = bt_mesh_provisioner_dev_key_get(src); } #endif diff --git a/components/bt/esp_ble_mesh/core/beacon.c b/components/bt/esp_ble_mesh/core/beacon.c index 488a3c5f6d08..45e4a2d1a952 100644 --- a/components/bt/esp_ble_mesh/core/beacon.c +++ b/components/bt/esp_ble_mesh/core/beacon.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,7 +25,9 @@ #include "pvnr_mgmt.h" #include "mesh/common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if defined(CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL) #define UNPROV_BEACON_INTERVAL K_SECONDS(CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL) @@ -472,12 +474,13 @@ void bt_mesh_beacon_recv(struct net_buf_simple *buf, int8_t rssi) bt_mesh_provisioner_unprov_beacon_recv(buf, rssi); } - if (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && - bt_mesh_is_provisioned()) { +#if CONFIG_BLE_MESH_RPR_SRV + if (bt_mesh_is_provisioned()) { const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr(); bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type()); bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi); } +#endif break; case BEACON_TYPE_SECURE: secure_beacon_recv(buf); diff --git a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index e0fc33b48448..f16456d6dd9d 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -32,7 +32,9 @@ #include "net.h" #include "beacon.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif struct bt_mesh_dev bt_mesh_dev; diff --git a/components/bt/esp_ble_mesh/core/cfg_srv.c b/components/bt/esp_ble_mesh/core/cfg_srv.c index 9d91cb217b3c..a8fe1af424db 100644 --- a/components/bt/esp_ble_mesh/core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/core/cfg_srv.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,7 +30,9 @@ #include "mesh/common.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define DEFAULT_TTL 7 @@ -38,6 +40,158 @@ static struct bt_mesh_cfg_srv *conf; static struct label labels[CONFIG_BLE_MESH_LABEL_COUNT]; +#if !CONFIG_BLE_MESH_V11_SUPPORT +const void *comp_0; + +static uint8_t bt_mesh_comp_page_check(uint8_t page, bool largest) +{ + /* If the page doesn't exist, TWO situations currently: + * 1. For Composition Data Get: + * With the Page field set to the largest page number of + * the Composition Data that the node supports and that is + * less than the Page field value of the received Config + * Composition Data Get message; + * 2. For Large Composition Data Get: + * The Page field shall be set to the largest page number + * of the Composition Data that the node supports. + */ + ARG_UNUSED(largest); + + if (page != 0) { + BT_WARN("Composition Data Page %d not exists", page); + } + + return 0; +} + +static inline uint16_t get_comp_elem_size(struct bt_mesh_elem *elem) +{ + return (4 + elem->model_count * 2 + elem->vnd_model_count * 4); +} + +static uint16_t get_comp_data_size(const struct bt_mesh_comp *comp) +{ + uint16_t size = 10; /* CID + PID + VID + CRPL + Features */ + + for (int i = 0; i < comp->elem_count; i++) { + size += get_comp_elem_size(&(comp->elem[i])); + } + + return size; +} + +static void get_comp_data(struct net_buf_simple *buf, + const struct bt_mesh_comp *comp, + bool full_element) +{ + struct bt_mesh_model *model = NULL; + struct bt_mesh_elem *elem = NULL; + uint16_t feat = 0; + + if (IS_ENABLED(CONFIG_BLE_MESH_RELAY)) { + feat |= BLE_MESH_FEAT_RELAY; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { + feat |= BLE_MESH_FEAT_PROXY; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + feat |= BLE_MESH_FEAT_FRIEND; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { + feat |= BLE_MESH_FEAT_LOW_POWER; + } + + net_buf_simple_add_le16(buf, comp->cid); + net_buf_simple_add_le16(buf, comp->pid); + net_buf_simple_add_le16(buf, comp->vid); + net_buf_simple_add_le16(buf, CONFIG_BLE_MESH_CRPL); + net_buf_simple_add_le16(buf, feat); + + for (size_t i = 0; i < comp->elem_count; i++) { + elem = &(comp->elem[i]); + + /* If "full_element" is true, which means the complete list + * of models within the element needs to fit in the data, + * otherwise the element shall not be reported. + */ + if (full_element && + net_buf_simple_tailroom(buf) < get_comp_elem_size(elem)) { + return; + } + + net_buf_simple_add_le16(buf, elem->loc); + net_buf_simple_add_u8(buf, elem->model_count); + net_buf_simple_add_u8(buf, elem->vnd_model_count); + + for (size_t j = 0; j < elem->model_count; j++) { + model = &(elem->models[j]); + net_buf_simple_add_le16(buf, model->id); + } + + for (size_t j = 0; j < elem->vnd_model_count; j++) { + model = &(elem->vnd_models[j]); + net_buf_simple_add_le16(buf, model->vnd.company); + net_buf_simple_add_le16(buf, model->vnd.id); + } + } +} + +static int fetch_comp_data(struct net_buf_simple *buf, + const struct bt_mesh_comp *comp, + uint8_t page, uint16_t offset, + bool full_element) +{ + uint16_t size = get_comp_data_size(comp); + + if (offset >= size) { + BT_WARN("Too large offset %d for comp data %d, size %d", + page, offset, size); + return 0; + } + + if (net_buf_simple_tailroom(buf) < 10 || + size - offset > net_buf_simple_tailroom(buf)) { + BT_ERR("Too small buffer for comp data %d, %d, expected %d", + page, buf->size, size - offset); + return -EINVAL; + } + + if (offset) { + struct net_buf_simple *pdu = bt_mesh_alloc_buf(size); + if (pdu == NULL) { + BT_ERR("%s, Out of memory", __func__); + return -ENOMEM; + } + + get_comp_data(pdu, comp, false); + + /* Get part of Composition Data Page 0/128 */ + net_buf_simple_add_mem(buf, pdu->data + offset, pdu->len - offset); + + bt_mesh_free_buf(pdu); + } else { + get_comp_data(buf, comp, full_element); + } + + return 0; +} + +static int bt_mesh_get_comp_data(struct net_buf_simple *buf, + uint8_t page, uint16_t offset, + bool full_element) +{ + if (page == 0) { + return fetch_comp_data(buf, comp_0, page, offset, full_element); + } + + BT_ERR("Invalid Composition Data Page %d", page); + return -EINVAL; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static void comp_data_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) @@ -2758,7 +2912,7 @@ static void node_reset(struct bt_mesh_model *model, bt_mesh_model_msg_init(&msg, OP_NODE_RESET_STATUS); - /* Send the response first since we wont have any keys left to + /* Send the response first since we won't have any keys left to * send it later. */ if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { diff --git a/components/bt/esp_ble_mesh/core/crypto.c b/components/bt/esp_ble_mesh/core/crypto.c index 9b762fb5ed3c..2577c65efba2 100644 --- a/components/bt/esp_ble_mesh/core/crypto.c +++ b/components/bt/esp_ble_mesh/core/crypto.c @@ -22,7 +22,9 @@ #include "mesh/common.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4) #define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4) diff --git a/components/bt/esp_ble_mesh/core/friend.c b/components/bt/esp_ble_mesh/core/friend.c index b1a298d5a97a..aa9607492b22 100644 --- a/components/bt/esp_ble_mesh/core/friend.c +++ b/components/bt/esp_ble_mesh/core/friend.c @@ -21,7 +21,9 @@ #include "mesh/common.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef CONFIG_BLE_MESH_FRIEND diff --git a/components/bt/esp_ble_mesh/core/lpn.c b/components/bt/esp_ble_mesh/core/lpn.c index f445be5632c4..80f5b4321afc 100644 --- a/components/bt/esp_ble_mesh/core/lpn.c +++ b/components/bt/esp_ble_mesh/core/lpn.c @@ -10,6 +10,7 @@ #include #include "crypto.h" +#include "tag.h" #include "adv.h" #include "scan.h" #include "mesh.h" @@ -23,7 +24,9 @@ #include "mesh/cfg_srv.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef CONFIG_BLE_MESH_LOW_POWER diff --git a/components/bt/esp_ble_mesh/core/main.c b/components/bt/esp_ble_mesh/core/main.c index ad94e2c88b2a..94a43c19b147 100644 --- a/components/bt/esp_ble_mesh/core/main.c +++ b/components/bt/esp_ble_mesh/core/main.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,7 +30,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif static bool mesh_init = false; @@ -161,9 +163,9 @@ void bt_mesh_node_reset(void) bt_mesh_clear_seq(); bt_mesh_clear_dkca(); bt_mesh_clear_role(); - if (IS_ENABLED(CONFIG_BLE_MESH_DF_SRV)) { - bt_mesh_clear_all_directed_forwarding_table_data(); - } +#if CONFIG_BLE_MESH_DF_SRV + bt_mesh_clear_all_directed_forwarding_table_data(); +#endif } memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags)); @@ -405,12 +407,14 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, return -EALREADY; } +#if CONFIG_BLE_MESH_V11_SUPPORT extern int bt_mesh_v11_ext_init(void); err = bt_mesh_v11_ext_init(); if (err) { BT_ERR("Bluetooth Mesh v1.1 init failed"); return err; } +#endif bt_mesh_mutex_init(); diff --git a/components/bt/esp_ble_mesh/core/mesh.h b/components/bt/esp_ble_mesh/core/mesh.h index c9392240696e..127844790fb7 100644 --- a/components/bt/esp_ble_mesh/core/mesh.h +++ b/components/bt/esp_ble_mesh/core/mesh.h @@ -11,6 +11,7 @@ #define _MESH_H_ #include "net.h" +#include "tag.h" #ifdef __cplusplus extern "C" { diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index d5b768c7d221..15d099cc5cd3 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -31,7 +31,9 @@ #include "proxy_server.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* Minimum valid Mesh Network PDU length. The Network headers * themselves take up 9 bytes. After that there is a minimum of 1 byte @@ -1019,6 +1021,33 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf, return bt_mesh_net_obfuscate(buf->data, BLE_MESH_NET_IVI_TX, priv); } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static void bt_mesh_net_adv_xmit_update(struct bt_mesh_net_tx *tx) +{ + /* When transmitting a Network PDU that is tagged as friendship, + * the Advertising Bearer Network Interface shall transmit the + * Network PDU over the advertising bearer only once. + * + * Note: Currently when transmitting a packet with the friendship + * credentials used, the message flow will not reach here. It + * will be enqueued into the friend queue in transport.c, and + * waited to be sent. + */ + if (bt_mesh_tag_friendship(tx->ctx->send_tag)) { + tx->xmit = BLE_MESH_TRANSMIT(0, BLE_MESH_TRANSMIT_INT(bt_mesh_net_transmit_get())); + return; + } + + if (bt_mesh_tag_relay(tx->ctx->send_tag)) { + tx->xmit = bt_mesh_relay_retransmit_get(); + } else { + tx->xmit = bt_mesh_net_transmit_get(); + } + + return; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, const struct bt_mesh_send_cb *cb, void *cb_data) { @@ -1418,13 +1447,94 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if) case BLE_MESH_NET_IF_ADV: return (bt_mesh_relay_get() == BLE_MESH_RELAY_ENABLED); case BLE_MESH_NET_IF_PROXY: - return (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED || - bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED); + return (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED +#if CONFIG_BLE_MESH_PRB_SRV + || bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED +#endif + ); default: return false; } } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static uint8_t net_retransmission_adv(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->ctx.recv_cred == BLE_MESH_FLOODING_CRED) { + uint8_t bearer = BLE_MESH_NONE_BEARER; + + /* Inbound bearer: ADV; + * Inbound Security Material: managed flooding; + */ + + /* Condition: Relay is enabled. */ + if (IS_ENABLED(CONFIG_BLE_MESH_RELAY) && + bt_mesh_relay_get() == BLE_MESH_RELAY_ENABLED) { + bearer |= BLE_MESH_ADV_BEARER; + *cred = BLE_MESH_FLOODING_CRED; + /* Additional action: Tag as relay */ + *tag |= BLE_MESH_TAG_RELAY; + } + + /* Condition: Proxy is enabled. */ + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { + bearer |= BLE_MESH_GATT_BEARER; + *cred = BLE_MESH_FLOODING_CRED; + } + + return bearer; + } + + if (rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED && + IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + bt_mesh_friend_get() == BLE_MESH_FRIEND_ENABLED) { + + /* Condition: Directed friend is disabled. */ + *cred = BLE_MESH_FLOODING_CRED; + return BLE_MESH_ALL_BEARERS; + } + + return BLE_MESH_NONE_BEARER; +} + +static uint8_t net_retransmission_gatt(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->ctx.recv_cred == BLE_MESH_FLOODING_CRED) { + /* Inbound bearer: GATT; + * Inbound Security Material: managed flooding; + * Condition: Proxy is enabled; + */ + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { + /* Condition: Directed proxy is disabled. */ + *cred = BLE_MESH_FLOODING_CRED; + return BLE_MESH_ALL_BEARERS; + } + + return BLE_MESH_NONE_BEARER; + } + + return BLE_MESH_NONE_BEARER; +} + +static uint8_t bt_mesh_net_retrans_match(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->net_if == BLE_MESH_NET_IF_ADV) { + return net_retransmission_adv(rx, cred, tag); + } + + if (rx->net_if == BLE_MESH_NET_IF_PROXY) { + return net_retransmission_gatt(rx, cred, tag); + } + + return BLE_MESH_NONE_BEARER; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static void bt_mesh_net_relay(struct net_buf_simple *sbuf, struct bt_mesh_net_rx *rx) { @@ -1621,7 +1731,9 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, (bearer & BLE_MESH_GATT_BEARER) && ((bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED && cred != BLE_MESH_FRIENDSHIP_CRED) || +#if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED || +#endif rx->net_if == BLE_MESH_NET_IF_LOCAL || rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED)) { if (bt_mesh_proxy_server_relay(&buf->b, rx->ctx.recv_dst) && @@ -1819,7 +1931,9 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, bt_mesh_elem_find(rx.ctx.recv_dst)); if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && +#if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_gatt_proxy_state_get() != BLE_MESH_PRIVATE_GATT_PROXY_ENABLED && +#endif net_if == BLE_MESH_NET_IF_PROXY) { bt_mesh_proxy_server_addr_add(data, rx.ctx.addr); diff --git a/components/bt/esp_ble_mesh/core/prov_common.h b/components/bt/esp_ble_mesh/core/prov_common.h index 561712ef1467..d2a8771bec84 100644 --- a/components/bt/esp_ble_mesh/core/prov_common.h +++ b/components/bt/esp_ble_mesh/core/prov_common.h @@ -17,7 +17,9 @@ #include "mesh/timer.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/components/bt/esp_ble_mesh/core/prov_node.c b/components/bt/esp_ble_mesh/core/prov_node.c index 4871a1cb1ebd..8053ac82018b 100644 --- a/components/bt/esp_ble_mesh/core/prov_node.c +++ b/components/bt/esp_ble_mesh/core/prov_node.c @@ -22,7 +22,9 @@ #include "prov_common.h" #include "prov_node.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_NODE diff --git a/components/bt/esp_ble_mesh/core/prov_pvnr.c b/components/bt/esp_ble_mesh/core/prov_pvnr.c index e2e0fe5850db..9066597e8768 100644 --- a/components/bt/esp_ble_mesh/core/prov_pvnr.c +++ b/components/bt/esp_ble_mesh/core/prov_pvnr.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,7 +22,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_PROVISIONER @@ -1413,7 +1415,7 @@ static int prov_auth(struct bt_mesh_prov_link *link, return -EINVAL; } - /* Provisioner ouput number/string and wait for device's Provisioning Input Complete PDU */ + /* Provisioner output number/string and wait for device's Provisioning Input Complete PDU */ link->expect = PROV_INPUT_COMPLETE; /* NOTE: The Bluetooth SIG recommends that mesh implementations enforce a randomly diff --git a/components/bt/esp_ble_mesh/core/proxy_client.c b/components/bt/esp_ble_mesh/core/proxy_client.c index 9382cf61478e..1719e4737dfb 100644 --- a/components/bt/esp_ble_mesh/core/proxy_client.c +++ b/components/bt/esp_ble_mesh/core/proxy_client.c @@ -21,7 +21,9 @@ #include "pvnr_mgmt.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT diff --git a/components/bt/esp_ble_mesh/core/proxy_client.h b/components/bt/esp_ble_mesh/core/proxy_client.h index d2d85017019b..ef8db32f6d27 100644 --- a/components/bt/esp_ble_mesh/core/proxy_client.h +++ b/components/bt/esp_ble_mesh/core/proxy_client.h @@ -11,7 +11,9 @@ #include "mesh/adapter.h" #include "prov_common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/components/bt/esp_ble_mesh/core/proxy_server.c b/components/bt/esp_ble_mesh/core/proxy_server.c index 020793dc6e81..532b23d823c1 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.c +++ b/components/bt/esp_ble_mesh/core/proxy_server.c @@ -22,7 +22,9 @@ #include "prov_common.h" #include "prov_node.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER diff --git a/components/bt/esp_ble_mesh/core/pvnr_mgmt.c b/components/bt/esp_ble_mesh/core/pvnr_mgmt.c index 2531a2d2fdba..96ad2feb324c 100644 --- a/components/bt/esp_ble_mesh/core/pvnr_mgmt.c +++ b/components/bt/esp_ble_mesh/core/pvnr_mgmt.c @@ -22,7 +22,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_PROVISIONER diff --git a/components/bt/esp_ble_mesh/core/scan.c b/components/bt/esp_ble_mesh/core/scan.c index e1b43dd2f631..72b1ccb30006 100644 --- a/components/bt/esp_ble_mesh/core/scan.c +++ b/components/bt/esp_ble_mesh/core/scan.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,7 +27,9 @@ #include "prov_pvnr.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* Scan Window and Interval are equal for continuous scanning */ #define SCAN_INTERVAL 0x20 @@ -263,12 +265,13 @@ static void handle_adv_service_data(struct net_buf_simple *buf, bt_mesh_provisioner_prov_adv_recv(buf, addr, rssi); } - if (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && - bt_mesh_is_provisioned()) { +#if CONFIG_BLE_MESH_RPR_SRV + if (bt_mesh_is_provisioned()) { const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr(); bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type()); bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi); } +#endif break; #endif #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT diff --git a/components/bt/esp_ble_mesh/core/storage/settings.c b/components/bt/esp_ble_mesh/core/storage/settings.c index 34a40d2d303f..ad2232017698 100644 --- a/components/bt/esp_ble_mesh/core/storage/settings.c +++ b/components/bt/esp_ble_mesh/core/storage/settings.c @@ -22,7 +22,9 @@ #include "pvnr_mgmt.h" #include "prov_pvnr.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* BLE Mesh NVS Key and corresponding data struct. * Note: The length of nvs key must be <= 15. diff --git a/components/bt/esp_ble_mesh/core/tag.h b/components/bt/esp_ble_mesh/core/tag.h new file mode 100644 index 000000000000..d1b9831094a0 --- /dev/null +++ b/components/bt/esp_ble_mesh/core/tag.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_v11_TAG_H_ +#define _BLE_MESH_v11_TAG_H_ + +#include +#include + +#include "mesh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !CONFIG_BLE_MESH_V11_SUPPORT + +/* TAG - additional metadata */ +#define BLE_MESH_TAG_SEND_SEGMENTED BIT(0) +#define BLE_MESH_TAG_IMMUTABLE_CRED BIT(1) +#define BLE_MESH_TAG_RELAY BIT(3) +#define BLE_MESH_TAG_FRIENDSHIP BIT(4) + +static inline bool bt_mesh_tag_send_segmented(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_SEND_SEGMENTED); +} + +static inline bool bt_mesh_tag_immutable_cred(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_IMMUTABLE_CRED); +} + +static inline bool bt_mesh_tag_relay(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_RELAY); +} + +static inline bool bt_mesh_tag_friendship(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_FRIENDSHIP); +} + +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_v11_TAG_H_ */ diff --git a/components/bt/esp_ble_mesh/core/transport.c b/components/bt/esp_ble_mesh/core/transport.c index 70589706dae3..4f125b99df70 100644 --- a/components/bt/esp_ble_mesh/core/transport.c +++ b/components/bt/esp_ble_mesh/core/transport.c @@ -11,6 +11,7 @@ #include #include "crypto.h" +#include "tag.h" #include "adv.h" #include "mesh.h" #include "lpn.h" @@ -26,7 +27,9 @@ #include "mesh/cfg_srv.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* The transport layer needs at least three buffers for itself to avoid * deadlocks. Ensure that there are a sufficient number of advertising @@ -1039,18 +1042,18 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, return 0; } - if (IS_ENABLED(CONFIG_BLE_MESH_DF_SRV)) { - switch (ctl_op) { - case TRANS_CTL_OP_PATH_REQ: - case TRANS_CTL_OP_PATH_REPLY: - case TRANS_CTL_OP_PATH_CFM: - case TRANS_CTL_OP_PATH_ECHO_REQ: - case TRANS_CTL_OP_PATH_ECHO_REPLY: - case TRANS_CTL_OP_DEP_NODE_UPDATE: - case TRANS_CTL_OP_PATH_REQ_SOLIC: - return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); - } +#if CONFIG_BLE_MESH_DF_SRV + switch (ctl_op) { + case TRANS_CTL_OP_PATH_REQ: + case TRANS_CTL_OP_PATH_REPLY: + case TRANS_CTL_OP_PATH_CFM: + case TRANS_CTL_OP_PATH_ECHO_REQ: + case TRANS_CTL_OP_PATH_ECHO_REPLY: + case TRANS_CTL_OP_DEP_NODE_UPDATE: + case TRANS_CTL_OP_PATH_REQ_SOLIC: + return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); } +#endif if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { switch (ctl_op) { @@ -1759,8 +1762,6 @@ void bt_mesh_trans_init(void) { int i; - bt_mesh_sar_init(); - for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { k_delayed_work_init(&seg_tx[i].rtx_timer, seg_retransmit); } diff --git a/components/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h b/components/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h index 71a02314c812..d8e80b196ffd 100644 --- a/components/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h +++ b/components/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/bt/esp_ble_mesh/lib/lib b/components/bt/esp_ble_mesh/lib/lib index cba99c5a2e7f..031cc5d3b8ca 160000 --- a/components/bt/esp_ble_mesh/lib/lib +++ b/components/bt/esp_ble_mesh/lib/lib @@ -1 +1 @@ -Subproject commit cba99c5a2e7f5d4bccb04e8f3f968dc888bb5667 +Subproject commit 031cc5d3b8ca6ada831ae1419219fb2895c37907 diff --git a/components/bt/esp_ble_mesh/models/client/client_common.c b/components/bt/esp_ble_mesh/models/client/client_common.c index db87851613d7..7e5448707d96 100644 --- a/components/bt/esp_ble_mesh/models/client/client_common.c +++ b/components/bt/esp_ble_mesh/models/client/client_common.c @@ -14,7 +14,9 @@ #include "mesh/client_common.h" #include "mesh/common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define HCI_TIME_FOR_START_ADV K_MSEC(5) /* Three adv related hci commands may take 4 ~ 5ms */ diff --git a/components/bt/host/bluedroid/api/esp_gap_ble_api.c b/components/bt/host/bluedroid/api/esp_gap_ble_api.c index d37f3724be80..a4122529799b 100644 --- a/components/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -1049,6 +1049,23 @@ 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) diff --git a/components/bt/host/bluedroid/api/esp_gattc_api.c b/components/bt/host/bluedroid/api/esp_gattc_api.c index 5f078b280987..904fb32a0cc3 100644 --- a/components/bt/host/bluedroid/api/esp_gattc_api.c +++ b/components/bt/host/bluedroid/api/esp_gattc_api.c @@ -363,10 +363,14 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_CHAR; @@ -400,10 +404,14 @@ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (start_handle == 0 || end_handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_BY_TYPE; @@ -432,7 +440,7 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } @@ -468,7 +476,7 @@ esp_err_t esp_ble_gattc_read_multiple_variable(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } @@ -504,10 +512,14 @@ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_CHAR_DESCR; @@ -537,10 +549,14 @@ esp_err_t esp_ble_gattc_write_char(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_WRITE_CHAR; @@ -576,10 +592,14 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_WRITE_CHAR_DESCR; @@ -615,10 +635,14 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_PREPARE_WRITE; @@ -652,10 +676,14 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_PREPARE_WRITE_CHAR_DESCR; @@ -694,6 +722,10 @@ esp_err_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_REG_FOR_NOTIFY; @@ -712,6 +744,10 @@ esp_err_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_UNREG_FOR_NOTIFY; diff --git a/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h b/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h index 589945b3175a..83fea16a99cb 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h @@ -229,6 +229,7 @@ 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; @@ -1572,6 +1573,12 @@ 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; /** @@ -2744,6 +2751,23 @@ 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 diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index 0ff6dc6c2ca4..58d545d3b948 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -5859,6 +5859,12 @@ 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) { diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c index 7ec61ee99943..71555246373c 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c @@ -3025,6 +3025,19 @@ 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 diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_cfg.c b/components/bt/host/bluedroid/bta/dm/bta_dm_cfg.c index a4792ce8469a..81bbd4667f86 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_cfg.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_cfg.c @@ -151,13 +151,13 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { (BTA_DM_PM_SSR2), /* the SSR entry */ #endif { - {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */ + {{BTA_DM_PM_SNIFF_AG_OPEN_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ {{BTA_DM_PM_SNIFF_SCO_OPEN_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */ - {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ + {{BTA_DM_PM_SNIFF_SCO_CLOSE_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ + {{BTA_DM_PM_SNIFF_AG_IDLE_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ {{BTA_DM_PM_RETRY, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ } @@ -231,9 +231,9 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ + {{BTA_DM_PM_SNIFF3, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */ + {{BTA_DM_PM_SNIFF, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ + {{BTA_DM_PM_SNIFF, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ {{BTA_DM_PM_RETRY, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ } @@ -409,7 +409,7 @@ tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] = { /*max_lat, min_rmt_to, min_loc_to*/ {0, 0, 0}, /* BTA_DM_PM_SSR0 - do not use SSR */ {0, 0, 2}, /* BTA_DM_PM_SSR1 - HH, can NOT share entry with any other profile, - seting default max latency and min remote timeout as 0, + setting default max latency and min remote timeout as 0, and always read individual device preference from HH module */ {1200, 2, 2}, /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/ {360, 160, 1600} /* BTA_DM_PM_SSR3 - HD */ @@ -466,7 +466,7 @@ tBTA_DM_EIR_CONF bta_dm_eir_cfg = { { /* mask of UUID list in EIR */ 0xFFFFFFFF, /* LSB is the first UUID of the first 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */ 0xFFFFFFFF /* LSB is the first UUID of the next 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */ - /* BTM_EIR_UUID_LKUP_TBL can be overrided */ + /* BTM_EIR_UUID_LKUP_TBL can be overridden */ }, #endif // BTA_EIR_CANNED_UUID_LIST FALSE, /* Not included TX power*/ diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c index 99736d8ececb..2d747f5b0784 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c @@ -235,6 +235,7 @@ 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 }; diff --git a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h index 862393fe8ab7..29af35c6dc5d 100644 --- a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h @@ -226,6 +226,7 @@ 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 }; @@ -959,6 +960,12 @@ 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 */ @@ -1365,6 +1372,7 @@ 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; @@ -1817,6 +1825,7 @@ 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); diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_main.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_main.c index 0cc55995a5f6..47f210c8729f 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_main.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_main.c @@ -538,9 +538,14 @@ 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) { + if (bta_gattc_cb.cl_rcb[i].in_use && + memcmp(bta_gattc_cb.cl_rcb[i].app_uuid.uu.uuid128, dm_gattc_uuid, 16)) { count++; } } diff --git a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_act.c b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_act.c index 0e0c43addf66..930f30a57d45 100644 --- a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_act.c +++ b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_act.c @@ -511,7 +511,9 @@ void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA *p_data) break; } + bta_sys_busy(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); bta_hf_client_at_parse(buf, len); + bta_sys_idle(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); /* no more data to read, we're done */ if (len < BTA_HF_CLIENT_RFC_READ_MAX) { diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_api.h index 32dc716bc65d..c0cabab2c71d 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -439,6 +439,8 @@ 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; @@ -1351,10 +1353,22 @@ typedef UINT8 tBTA_DM_PM_ACTION; #define BTA_DM_PM_SNIFF_HD_IDLE_IDX BTA_DM_PM_SNIFF4 #endif +#ifndef BTA_DM_PM_SNIFF_AG_OPEN_IDX +#define BTA_DM_PM_SNIFF_AG_OPEN_IDX BTA_DM_PM_SNIFF +#endif + +#ifndef BTA_DM_PM_SNIFF_AG_IDLE_IDX +#define BTA_DM_PM_SNIFF_AG_IDLE_IDX BTA_DM_PM_SNIFF +#endif + #ifndef BTA_DM_PM_SNIFF_SCO_OPEN_IDX #define BTA_DM_PM_SNIFF_SCO_OPEN_IDX BTA_DM_PM_SNIFF3 #endif +#ifndef BTA_DM_PM_SNIFF_SCO_CLOSE_IDX +#define BTA_DM_PM_SNIFF_SCO_CLOSE_IDX BTA_DM_PM_SNIFF +#endif + #ifndef BTA_DM_PM_SNIFF_HD_ACTIVE_IDX #define BTA_DM_PM_SNIFF_HD_ACTIVE_IDX BTA_DM_PM_SNIFF5 #endif @@ -2909,6 +2923,8 @@ 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 diff --git a/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c b/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c index 159731e78372..a783d5e35042 100644 --- a/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c +++ b/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c @@ -175,8 +175,7 @@ bool btc_avrc_ct_init_p(void) bool btc_avrc_tg_connected_p(void) { return (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC) && - (btc_rc_cb.rc_connected == TRUE) && - (btc_rc_cb.rc_features & BTA_AV_FEAT_RCCT); + (btc_rc_cb.rc_connected == TRUE); } bool btc_avrc_ct_connected_p(void) @@ -507,7 +506,7 @@ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); } - if (p_rc_open->peer_features & BTA_AV_FEAT_RCCT) { + if (btc_avrc_tg_init_p()) { esp_avrc_tg_cb_param_t param; memset(¶m, 0, sizeof(esp_avrc_tg_cb_param_t)); param.conn_stat.connected = true; @@ -580,7 +579,7 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close) btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); } - if (rc_features & BTA_AV_FEAT_RCCT) { + if (btc_avrc_tg_init_p()) { esp_avrc_tg_cb_param_t param; memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); param.conn_stat.connected = false; @@ -1006,14 +1005,10 @@ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t)); btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); } - if ((p_data->rc_feat.peer_features & BTA_AV_FEAT_RCCT) && - !(old_feats & BTA_AV_FEAT_RCCT)) { - esp_avrc_tg_cb_param_t param; - memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); - param.conn_stat.connected = true; - memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t)); - btc_avrc_tg_cb_to_app(ESP_AVRC_TG_CONNECTION_STATE_EVT, ¶m); - } + /** + * @note ESP_AVRC_TG_CONNECTION_STATE_EVT has been reported on rc connect/disconnect event, + * it doesn't rely on the SDP results. + */ } while (0); btc_rc_cb.rc_features = p_data->rc_feat.peer_features; btc_rc_cb.rc_ct_features = p_data->rc_feat.peer_ct_features; diff --git a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c index 464f032417c8..b48670334667 100644 --- a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -1363,6 +1363,25 @@ 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, ¶m, 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); @@ -2402,6 +2421,9 @@ 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; } diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h index e540116de19f..3157c8c813c4 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h @@ -11,11 +11,13 @@ #include "esp_gap_ble_api.h" #if BTC_DYNAMIC_MEMORY == TRUE +#if (BLE_42_FEATURE_SUPPORT == TRUE) #include "bta/bta_api.h" extern tBTA_BLE_ADV_DATA *gl_bta_adv_data_ptr; extern tBTA_BLE_ADV_DATA *gl_bta_scan_rsp_data_ptr; #define gl_bta_adv_data (*gl_bta_adv_data_ptr) #define gl_bta_scan_rsp_data (*gl_bta_scan_rsp_data_ptr) +#endif // BLE_42_FEATURE_SUPPORT #endif #define BLE_ISVALID_PARAM(x, min, max) (((x) >= (min) && (x) <= (max))) @@ -106,6 +108,7 @@ 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 */ @@ -274,6 +277,10 @@ 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) diff --git a/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c b/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c index 7c5157736a95..12e55c621841 100644 --- a/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c +++ b/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -281,7 +281,7 @@ static void close_timeout_handler(void *arg) status = btc_transfer_context(&msg, slot->alarm_arg, sizeof(tBTA_JV), NULL, NULL); if (slot->alarm_arg) { - free(slot->alarm_arg); + osi_free(slot->alarm_arg); slot->alarm_arg = NULL; } @@ -832,7 +832,7 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) // if rx still has data, delay free slot if (slot->close_alarm == NULL && slot->rx.queue && fixed_queue_length(slot->rx.queue) > 0) { tBTA_JV *p_arg = NULL; - if ((p_arg = malloc(sizeof(tBTA_JV))) == NULL) { + if ((p_arg = osi_malloc(sizeof(tBTA_JV))) == NULL) { param.close.status = ESP_BT_L2CAP_NO_RESOURCE; osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); BTC_TRACE_ERROR("%s unable to malloc slot close_alarm arg!", __func__); @@ -842,7 +842,7 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) slot->alarm_arg = (void *)p_arg; if ((slot->close_alarm = osi_alarm_new("slot", close_timeout_handler, (void *)slot, VFS_CLOSE_TIMEOUT)) == NULL) { - free(p_arg); + osi_free(p_arg); slot->alarm_arg = NULL; param.close.status = ESP_BT_L2CAP_NO_RESOURCE; osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); @@ -850,7 +850,7 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) break; } if (osi_alarm_set(slot->close_alarm, VFS_CLOSE_TIMEOUT) != OSI_ALARM_ERR_PASS) { - free(p_arg); + osi_free(p_arg); slot->alarm_arg = NULL; osi_alarm_free(slot->close_alarm); param.close.status = ESP_BT_L2CAP_BUSY; diff --git a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index cf334494487d..181f2014164c 100644 --- a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1199,7 +1199,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) slot->alarm_arg = (void *)p_arg; if ((slot->close_alarm = osi_alarm_new("slot", close_timeout_handler, (void *)slot, VFS_CLOSE_TIMEOUT)) == NULL) { - free(p_arg); + osi_free(p_arg); slot->alarm_arg = NULL; param.close.status = ESP_SPP_NO_RESOURCE; osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -1207,7 +1207,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) break; } if (osi_alarm_set(slot->close_alarm, VFS_CLOSE_TIMEOUT) != OSI_ALARM_ERR_PASS) { - free(p_arg); + osi_free(p_arg); slot->alarm_arg = NULL; osi_alarm_free(slot->close_alarm); param.close.status = ESP_SPP_BUSY; @@ -1488,7 +1488,7 @@ static ssize_t spp_vfs_write(int fd, const void * data, size_t size) BTC_TRACE_DEBUG("%s items_waiting:%d, fd:%d\n", __func__, items_waiting, fd); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); - // block untill under water level, be closed or time out + // block until under water level, be closed or time out tx_event_group_val = xEventGroupWaitBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial) | SLOT_CLOSE_BIT(serial), pdTRUE, pdFALSE, VFS_WRITE_TIMEOUT / portTICK_PERIOD_MS); diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index da3be907074b..f5b16385eb57 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -593,7 +593,11 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) } #endif pkt_size = BT_PKT_LINKED_HDR_SIZE + BT_HDR_SIZE + len; + #if HEAP_MEMORY_DEBUG + linked_pkt = (pkt_linked_item_t *) osi_calloc(pkt_size); + #else linked_pkt = (pkt_linked_item_t *) osi_calloc_base(pkt_size); + #endif if (!linked_pkt) { #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) hci_adv_credits_consumed(1); diff --git a/components/bt/host/bluedroid/hci/hci_packet_parser.c b/components/bt/host/bluedroid/hci/hci_packet_parser.c index 1ee5033112f1..d25caf3506e2 100644 --- a/components/bt/host/bluedroid/hci/hci_packet_parser.c +++ b/components/bt/host/bluedroid/hci/hci_packet_parser.c @@ -219,7 +219,6 @@ static void parse_ble_read_adv_max_len_response( // Size: 2 Octets ; Value: 0x001F – 0x0672 ; Maximum supported advertising data length STREAM_TO_UINT16(*adv_max_len_ptr, stream); } - osi_free(response); } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c index a85f6a16112d..415805fe520d 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c @@ -4617,6 +4617,12 @@ 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 @@ -4629,6 +4635,7 @@ void btm_ble_free (void) *******************************************************************************/ 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; @@ -4761,6 +4768,17 @@ 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; diff --git a/components/bt/host/bluedroid/stack/btm/btm_devctl.c b/components/bt/host/bluedroid/stack/btm/btm_devctl.c index bab88739a080..d3c4ac61da2f 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_devctl.c @@ -773,6 +773,14 @@ 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; } diff --git a/components/bt/host/bluedroid/stack/btm/btm_main.c b/components/bt/host/bluedroid/stack/btm/btm_main.c index e9e443380c8f..1519ecb990a3 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_main.c +++ b/components/bt/host/bluedroid/stack/btm/btm_main.c @@ -110,6 +110,9 @@ void btm_free(void) fixed_queue_free(btm_cb.sec_pending_q, osi_free_func); btm_acl_free(); btm_sec_dev_free(); +#if BTM_SCO_INCLUDED == TRUE + btm_sco_free(); +#endif #if BTM_DYNAMIC_MEMORY FREE_AND_RESET(btm_cb_ptr); #endif diff --git a/components/bt/host/bluedroid/stack/btm/btm_sco.c b/components/bt/host/bluedroid/stack/btm/btm_sco.c index 53a9768a1aeb..7dede5d4d3f8 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_sco.c +++ b/components/bt/host/bluedroid/stack/btm/btm_sco.c @@ -123,6 +123,22 @@ void btm_sco_init (void) btm_cb.sco_cb.desired_sco_mode = BTM_DEFAULT_SCO_MODE; } +/******************************************************************************* +** +** Function btm_sco_free +** +** Description Free sco specific fixed_queue from btm control block +** +*******************************************************************************/ +void btm_sco_free(void) +{ +#if (BTM_SCO_HCI_INCLUDED == TRUE) + for (int i = 0; i < BTM_MAX_SCO_LINKS; i++) { + fixed_queue_free(btm_cb.sco_cb.sco_db[i].xmit_data_q, osi_free_func); + } +#endif +} + /******************************************************************************* ** ** Function btm_esco_conn_rsp @@ -233,7 +249,7 @@ void btm_sco_process_num_bufs (UINT16 num_lm_sco_bufs) ** pointer is used, PCM parameter maintained in ** the control block will be used; otherwise update ** control block value. -** err_data_rpt: Lisbon feature to enable the erronous data report +** err_data_rpt: Lisbon feature to enable the erroneous data report ** or not. ** ** Returns BTM_SUCCESS if the successful. @@ -947,7 +963,7 @@ void btm_sco_conn_req (BD_ADDR bda, DEV_CLASS dev_class, UINT8 link_type) for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { /* * If the sco state is in the SCO_ST_CONNECTING state, we still need - * to return accept sco to avoid race conditon for sco creation + * to return accept sco to avoid race condition for sco creation */ int rem_bd_matches = p->rem_bd_known && !memcmp (p->esco.data.bd_addr, bda, BD_ADDR_LEN); diff --git a/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h b/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h index 0f8888fb1bd1..d81a03c0a92c 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h @@ -377,6 +377,7 @@ 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 diff --git a/components/bt/host/bluedroid/stack/btm/include/btm_int.h b/components/bt/host/bluedroid/stack/btm/include/btm_int.h index 64bcc300cd29..df7e435db1a7 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_int.h @@ -1119,6 +1119,7 @@ void btm_ble_periodic_adv_sync_trans_complete(UINT16 op_code, UINT8 hci_status, ******************************************** */ void btm_sco_init (void); +void btm_sco_free(void); void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle, tBTM_ESCO_DATA *p_esco_data); void btm_esco_proc_conn_chg (UINT8 status, UINT16 handle, UINT8 tx_interval, diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_db.c b/components/bt/host/bluedroid/stack/gatt/gatt_db.c index efae6413ad2b..8844ef5dc8e7 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_db.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_db.c @@ -60,7 +60,7 @@ static BOOLEAN gatts_add_char_desc_value_check (tGATT_ATTR_VAL *attr_val, tGATTS ** Parameter p_db: database pointer. ** len: size of the memory space. ** -** Returns Status of te operation. +** Returns Status of the operation. ** *******************************************************************************/ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri, @@ -94,7 +94,7 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN ** Parameter p_db: database pointer. ** len: size of the memory space. ** -** Returns Status of te operation. +** Returns Status of the operation. ** *******************************************************************************/ tBT_UUID *gatts_get_service_uuid (tGATT_SVC_DB *p_db) @@ -497,14 +497,14 @@ UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e ** Function gatts_add_characteristic ** ** Description This function add a characteristics and its descriptor into -** a servce identified by the service database pointer. +** a service identified by the service database pointer. ** ** Parameter p_db: database pointer. ** perm: permission (authentication and key size requirements) ** property: property of the characteristic. ** p_char: characteristic value information. ** -** Returns Status of te operation. +** Returns Status of the operation. ** *******************************************************************************/ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, @@ -1173,40 +1173,40 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, if ((op_code == GATT_SIGN_CMD_WRITE) && !(perm & GATT_WRITE_SIGNED_PERM)) { status = GATT_WRITE_NOT_PERMIT; - GATT_TRACE_DEBUG( "gatts_write_attr_perm_check - sign cmd write not allowed,handle:0x%04x",handle); + GATT_TRACE_DEBUG( "gatts_write_attr_perm_check - sign cmd write not allowed,handle %04x,perm %04x", handle, perm); } if ((op_code == GATT_SIGN_CMD_WRITE) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { status = GATT_INVALID_PDU; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - Error!! sign cmd write sent on a encypted link,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - Error!! sign cmd write sent on a encrypted link,handle %04x,perm %04x", handle, perm); } else if (!(perm & GATT_WRITE_ALLOWED)) { status = GATT_WRITE_NOT_PERMIT; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT,handle:0x%04x",handle); + GATT_TRACE_ERROR("gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT,handle %04x, perm %04x", handle, perm); } /* require authentication, but not been authenticated */ else if ((perm & GATT_WRITE_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED)) { status = GATT_INSUF_AUTHENTICATION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION,handle %04x, perm %04x", handle, perm); } else if ((perm & GATT_WRITE_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) { status = GATT_INSUF_AUTHENTICATION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: MITM required,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: MITM required,handle %04x,perm %04x", handle, perm); } else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { status = GATT_INSUF_ENCRYPTION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_ENCRYPTION,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_ENCRYPTION,handle:0x%04x, perm:0x%04x", handle, perm); } else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) { status = GATT_INSUF_KEY_SIZE; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE,handle %04x,perm %04x", handle, perm); } /* LE Authorization check*/ else if ((perm & GATT_WRITE_AUTHORIZATION) && (!(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED) || !(sec_flag & GATT_SEC_FLAG_AUTHORIZATION))){ status = GATT_INSUF_AUTHORIZATION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHORIZATION,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHORIZATION,handle %04x,perm %04x", handle, perm); } /* LE security mode 2 attribute */ else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (perm & GATT_WRITE_ALLOWED) == 0) { status = GATT_INSUF_AUTHENTICATION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required,handle:0x%04x",handle); - } else { /* writable: must be char value declaration or char descritpors */ + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required,handle %04x,perm %04x", handle, perm); + } else { /* writable: must be char value declaration or char descriptors */ if (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) { switch (p_attr->uuid) { case GATT_UUID_CHAR_PRESENT_FORMAT:/* should be readable only */ @@ -1215,13 +1215,19 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, case GATT_UUID_CHAR_VALID_RANGE: status = GATT_WRITE_NOT_PERMIT; break; - + case GATT_UUID_GAP_ICON:/* The Appearance characteristic value shall be 2 octets in length */ case GATT_UUID_CHAR_CLIENT_CONFIG: /* coverity[MISSING_BREAK] */ /* intnended fall through, ignored */ /* fall through */ case GATT_UUID_CHAR_SRVR_CONFIG: max_size = 2; + status = GATT_SUCCESS; + break; + case GATT_UUID_CLIENT_SUP_FEAT: + max_size = 1; + status = GATT_SUCCESS; + break; case GATT_UUID_CHAR_DESCRIPTION: default: /* any other must be character value declaration */ status = GATT_SUCCESS; @@ -1242,17 +1248,17 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, else if ( (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) && (p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG || p_attr->uuid == GATT_UUID_CHAR_SRVR_CONFIG || - p_attr->uuid == GATT_UUID_CLIENT_SUP_FEAT || + p_attr->uuid == GATT_UUID_CLIENT_SUP_FEAT || p_attr->uuid == GATT_UUID_GAP_ICON ) ) // btla-specific -- { if (op_code == GATT_REQ_PREPARE_WRITE) { /* does not allow write blob */ status = GATT_REQ_NOT_SUPPORTED; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_REQ_NOT_SUPPORTED,handle:0x%04x",handle); + GATT_TRACE_ERROR("gatts_write_attr_perm_check - GATT_REQ_NOT_SUPPORTED,handle %04x,opcode %4x", handle, op_code); } else if (len != max_size) { /* data does not match the required format */ status = GATT_INVALID_ATTR_LEN; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INVALID_ATTR_LEN,handle:0x%04x",handle); + GATT_TRACE_ERROR("gatts_write_attr_perm_check - GATT_INVALID_ATTR_LEN,handle %04x,op_code %04x,len %d,max_size %d", handle, op_code, len, max_size); } else { status = GATT_SUCCESS; } @@ -1554,7 +1560,7 @@ static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_ uuid.uu.uuid16 = GATT_UUID_SEC_SERVICE; } - /* add service declration record */ + /* add service declaration record */ if ((p_attr = (tGATT_ATTR16 *)(allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ))) != NULL) { if (copy_extra_byte_in_db (p_db, (void **)&p_attr->p_value, sizeof(tBT_UUID))) { if (p_service->len == LEN_UUID_16) { diff --git a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c index 52a2b2dc09ef..c51746b1aaec 100644 --- a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c +++ b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c @@ -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) -UINT8 btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode) +BOOLEAN btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode) { BT_HDR *p; UINT8 *pp; @@ -1933,4 +1933,26 @@ UINT8 btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 priva 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 diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h index 21d783dd2b10..3dc7dc8b3315 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h @@ -1007,6 +1007,7 @@ 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 @@ -2724,6 +2725,20 @@ 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 } diff --git a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h index b77e8854767b..0943c624f929 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h @@ -422,6 +422,7 @@ #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 @@ -468,6 +469,8 @@ #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) diff --git a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h index 951e5b703a7f..252efa721917 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h @@ -759,6 +759,7 @@ 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 @@ -914,7 +915,12 @@ 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; @@ -1042,8 +1048,6 @@ 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 diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c index 01edf9caf537..36f91cfe0876 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c @@ -376,6 +376,7 @@ 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 ) && @@ -476,6 +477,7 @@ 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); diff --git a/components/bt/host/bluedroid/stack/smp/smp_utils.c b/components/bt/host/bluedroid/stack/smp/smp_utils.c index 2e9fac77c9a6..48ba6c0ae302 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_utils.c +++ b/components/bt/host/bluedroid/stack/smp/smp_utils.c @@ -331,8 +331,7 @@ 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:0x%0x to L2CAP", - *((UINT8 *)(p_toL2CAP + 1) + p_toL2CAP->offset)); + SMP_TRACE_ERROR("SMP failed to pass msg to L2CAP"); return FALSE; } else { return TRUE; @@ -1125,7 +1124,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 Capabilty \ + SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with IO Capability \ value (0x%02x) out of range).\n", p_cb->rcvd_cmd_code, io_caps); return FALSE; diff --git a/components/bt/host/nimble/Kconfig.in b/components/bt/host/nimble/Kconfig.in index cfde045be4d0..6984cc02923a 100644 --- a/components/bt/host/nimble/Kconfig.in +++ b/components/bt/host/nimble/Kconfig.in @@ -648,7 +648,7 @@ config BT_NIMBLE_PERIODIC_ADV_ENH config BT_NIMBLE_AOA_AOD bool "Direction Finding" - depends on BT_NIMBLE_50_FEATURE_SUPPORT && SOC_BLE_CTE_SUPPORTED + depends on BT_NIMBLE_50_FEATURE_SUPPORT && (BT_CONTROLLER_DISABLED || SOC_BLE_CTE_SUPPORTED) default n help Enable support for Connectionless and Connection Oriented Direction Finding diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index 03462b6686cf..32b2124f5423 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit 03462b6686cf49bb0bb026461300fec593c6f4c5 +Subproject commit 32b2124f54238e70ecd4c72a753698babdd939f7 diff --git a/components/bt/include/esp32/include/esp_bt.h b/components/bt/include/esp32/include/esp_bt.h index 722da480de04..43c475e7e6d1 100644 --- a/components/bt/include/esp32/include/esp_bt.h +++ b/components/bt/include/esp32/include/esp_bt.h @@ -55,7 +55,7 @@ extern "C" { * * @note Please do not modify this value */ -#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20240722 +#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20240926 /** * @brief Bluetooth Controller mode @@ -178,6 +178,21 @@ 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 */ @@ -206,6 +221,7 @@ 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, \ } @@ -258,6 +274,7 @@ 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; diff --git a/components/bt/include/esp32c3/include/esp_bt.h b/components/bt/include/esp32c3/include/esp_bt.h index d8ff356f9d96..1cd79be90217 100644 --- a/components/bt/include/esp32c3/include/esp_bt.h +++ b/components/bt/include/esp32c3/include/esp_bt.h @@ -19,7 +19,7 @@ extern "C" { #endif #define ESP_BT_CTRL_CONFIG_MAGIC_VAL 0x5A5AA5A5 -#define ESP_BT_CTRL_CONFIG_VERSION 0x02404010 +#define ESP_BT_CTRL_CONFIG_VERSION 0x02410230 #define ESP_BT_HCI_TL_MAGIC_VALUE 0xfadebead #define ESP_BT_HCI_TL_VERSION 0x00010000 @@ -217,6 +217,80 @@ 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) +#if defined(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) +#define BT_CTRL_RUN_IN_FLASH_ONLY CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +#else +#define BT_CTRL_RUN_IN_FLASH_ONLY (0) +#endif + +#if (BT_CTRL_RUN_IN_FLASH_ONLY == 1) + +#if defined(CONFIG_BT_CTRL_DTM_ENABLE) +#define BT_CTRL_DTM_ENABLE CONFIG_BT_CTRL_DTM_ENABLE +#else +#define BT_CTRL_DTM_ENABLE (0) +#endif + +#if defined(CONFIG_BT_CTRL_BLE_MASTER) +#define BT_CTRL_BLE_MASTER CONFIG_BT_CTRL_BLE_MASTER +#else +#define BT_CTRL_BLE_MASTER (0) +#endif + +#if defined(CONFIG_BT_CTRL_BLE_TEST) +#define BT_CTRL_BLE_TEST CONFIG_BT_CTRL_BLE_TEST +#else +#define BT_CTRL_BLE_TEST (0) +#endif + +#if defined (CONFIG_BT_NIMBLE_SECURITY_ENABLE) || defined (CONFIG_BT_BLE_SMP_ENABLE) +#ifdef CONFIG_BT_NIMBLE_SECURITY_ENABLE +#define BLE_SECURITY_ENABLE (CONFIG_BT_NIMBLE_SECURITY_ENABLE) +#endif //CONFIG_BT_NIMBLE_SECURITY_ENABLE +#ifdef CONFIG_BT_BLE_SMP_ENABLE +#define BLE_SECURITY_ENABLE (CONFIG_BT_BLE_SMP_ENABLE) +#endif //CONFIG_BT_BLE_SMP_ENABLE +#else +#if defined (CONFIG_BT_CTRL_BLE_SECURITY_ENABLE) +#define BLE_SECURITY_ENABLE (CONFIG_BT_CTRL_BLE_SECURITY_ENABLE) +#else +#define BLE_SECURITY_ENABLE (0) +#endif +#endif // (CONFIG_BT_NIMBLE_SECURITY_ENABLE) || (CONFIG_BT_BLE_SMP_ENABLE) + +#if defined (CONFIG_BT_CTRL_BLE_SCAN) +#define BT_CTRL_BLE_SCAN CONFIG_BT_CTRL_BLE_SCAN +#else +#define BT_CTRL_BLE_SCAN (0) +#endif + +#else +#define BT_CTRL_BLE_MASTER (1) +#define BT_CTRL_DTM_ENABLE (1) +#define BT_CTRL_BLE_TEST (1) +#define BLE_SECURITY_ENABLE (1) +#define BT_CTRL_BLE_SCAN (1) +#endif // (BT_CTRL_RUN_IN_FLASH_ONLY == 1) + #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \ .magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL, \ .version = ESP_BT_CTRL_CONFIG_VERSION, \ @@ -255,6 +329,13 @@ 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, \ + .run_in_flash = BT_CTRL_RUN_IN_FLASH_ONLY, \ + .dtm_en = BT_CTRL_DTM_ENABLE, \ + .enc_en = BLE_SECURITY_ENABLE, \ + .qa_test = BT_CTRL_BLE_TEST, \ + .master_en = BT_CTRL_BLE_MASTER, \ + .scan_en = BT_CTRL_BLE_SCAN, \ } #else @@ -329,6 +410,13 @@ 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 */ + bool run_in_flash; /*!< Check if controller code is in flash */ + bool dtm_en; /*!< Controller DTM feature is enabled or not */ + bool enc_en; /*!< Controller encryption feature is enabled or not */ + bool qa_test; /*!< Controller QA test feature is enabled or not */ + bool master_en; /*!< Controller master feature is enabled or not */ + bool scan_en; /*!< Controller scan feature is enabled or not */ } esp_bt_controller_config_t; /** diff --git a/components/cxx/cxx_guards.cpp b/components/cxx/cxx_guards.cpp index 0a76173769ef..e4f9f905a66e 100644 --- a/components/cxx/cxx_guards.cpp +++ b/components/cxx/cxx_guards.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -210,6 +210,12 @@ extern "C" void __cxa_guard_abort(__guard* pg) throw() } } +/* Originally, this should come with crtbegin.o from the toolchain (if GCC is configured with --enable-__cxa_atexit). + Since we do not link with crtbegin.o and have not configured GCC with --enable-__cxa_atexit, it is declared here. + Note: It should have a unique value in every shared object; in the main program its value is zero. */ +extern "C" void *__dso_handle __attribute__((__visibility__("hidden"))); +void *__dso_handle = 0; + /** * Dummy function used to force linking this file instead of the same one in libstdc++. * This works via -u __cxa_guard_dummy flag in component.mk diff --git a/components/cxx/test_apps/general/main/test_cxx_general.cpp b/components/cxx/test_apps/general/main/test_cxx_general.cpp index 0e483ab655af..858b16bc16aa 100644 --- a/components/cxx/test_apps/general/main/test_cxx_general.cpp +++ b/components/cxx/test_apps/general/main/test_cxx_general.cpp @@ -197,7 +197,7 @@ struct PriorityInitTest { int PriorityInitTest::order = 0; -// init_priority objects are initialized from the lowest to the heighest priority number +// init_priority objects are initialized from the lowest to the highest priority number // Default init_priority is always the lowest (highest priority number) PriorityInitTest g_static_init_priority_test2; PriorityInitTest g_static_init_priority_test1 __attribute__((init_priority(1000))); @@ -243,6 +243,36 @@ TEST_CASE("can use std::vector", "[misc]") TEST_ASSERT_EQUAL(51, std::accumulate(std::begin(v), std::end(v), 0)); } +static volatile bool is_tls_class_destructor_called; +struct TestTLS { + TestTLS() { } + ~TestTLS() + { + is_tls_class_destructor_called = true; + } + void foo() { } +}; + +thread_local TestTLS s_testTLS; + +void test_thread_local_destructors(void * arg) +{ + s_testTLS.foo(); + xSemaphoreGive(s_slow_init_sem); + vTaskDelete(NULL); +} + +TEST_CASE("call destructors for thread_local classes CXX", "[misc]") +{ + is_tls_class_destructor_called = false; + s_slow_init_sem = xSemaphoreCreateCounting(1, 0); + xTaskCreate(test_thread_local_destructors, "test_thread_local_destructors", 2048, NULL, 10, NULL); + vTaskDelay(1); /* Triggers IDLE task to call prvCheckTasksWaitingTermination() which cleans task-specific data */ + TEST_ASSERT_TRUE(xSemaphoreTake(s_slow_init_sem, 500 / portTICK_PERIOD_MS)); + vSemaphoreDelete(s_slow_init_sem); + TEST_ASSERT_TRUE(is_tls_class_destructor_called); +} + /* These test cases pull a lot of code from libstdc++ and are disabled for now */ #if 0 @@ -291,6 +321,7 @@ TEST_CASE("stack smashing protection CXX", "[stack_smash]") extern "C" void app_main(void) { + s_testTLS.foo(); /* allocates memory that will be reused */ printf("CXX GENERAL TEST\n"); unity_run_menu(); } diff --git a/components/driver/deprecated/i2s_legacy.c b/components/driver/deprecated/i2s_legacy.c index 36996697b284..5f4a033fcfcd 100644 --- a/components/driver/deprecated/i2s_legacy.c +++ b/components/driver/deprecated/i2s_legacy.c @@ -1479,11 +1479,6 @@ 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 diff --git a/components/driver/i2c/i2c.c b/components/driver/i2c/i2c.c index 12f2a25d7b71..1450f9af1e8b 100644 --- a/components/driver/i2c/i2c.c +++ b/components/driver/i2c/i2c.c @@ -280,7 +280,7 @@ static void i2c_hw_enable(i2c_port_t i2c_num) static esp_err_t i2c_sleep_retention_init(void *arg) { i2c_port_t i2c_num = *(i2c_port_t *)arg; - esp_err_t ret = sleep_retention_entries_create(i2c_regs_retention[i2c_num].link_list, i2c_regs_retention[i2c_num].link_num, REGDMA_LINK_PRI_I2C, I2C_SLEEP_RETENTION_MODULE(i2c_num)); + esp_err_t ret = sleep_retention_entries_create(i2c_regs_retention[i2c_num].link_list, i2c_regs_retention[i2c_num].link_num, REGDMA_LINK_PRI_I2C, i2c_regs_retention[i2c_num].module_id); ESP_RETURN_ON_ERROR(ret, I2C_TAG, "failed to allocate mem for sleep retention"); return ret; } @@ -428,9 +428,9 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = i2c_sleep_retention_init, .arg = &i2c_num } } }; - ret = sleep_retention_module_init(I2C_SLEEP_RETENTION_MODULE(i2c_num), &init_param); + ret = sleep_retention_module_init(i2c_regs_retention[i2c_num].module_id, &init_param); if (ret == ESP_OK) { - sleep_retention_module_allocate(I2C_SLEEP_RETENTION_MODULE(i2c_num)); + sleep_retention_module_allocate(i2c_regs_retention[i2c_num].module_id); } #endif return ESP_OK; @@ -486,9 +486,9 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num) p_i2c->intr_handle = NULL; #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_I2C_SUPPORT_SLEEP_RETENTION - esp_err_t err = sleep_retention_module_free(I2C_SLEEP_RETENTION_MODULE(i2c_num)); + esp_err_t err = sleep_retention_module_free(i2c_regs_retention[i2c_num].module_id); if (err == ESP_OK) { - err = sleep_retention_module_deinit(I2C_SLEEP_RETENTION_MODULE(i2c_num)); + err = sleep_retention_module_deinit(i2c_regs_retention[i2c_num].module_id); } #endif diff --git a/components/driver/test_apps/components/test_driver_utils/include/test_spi_utils.h b/components/driver/test_apps/components/test_driver_utils/include/test_spi_utils.h index 0fdcb27e4939..6bcac2a72d9a 100644 --- a/components/driver/test_apps/components/test_driver_utils/include/test_spi_utils.h +++ b/components/driver/test_apps/components/test_driver_utils/include/test_spi_utils.h @@ -94,11 +94,6 @@ #define WIRE_DELAY 12.5 #endif //CONFIG_IDF_TARGET_ESP32 -#define GET_DMA_CHAN(HOST) (HOST) - -#define TEST_DMA_CHAN_MASTER GET_DMA_CHAN(TEST_SPI_HOST) -#define TEST_DMA_CHAN_SLAVE GET_DMA_CHAN(TEST_SLAVE_HOST) - #define FUNC_SPI SPI2_FUNC_NUM #define FUNC_GPIO PIN_FUNC_GPIO diff --git a/components/driver/test_apps/components/test_driver_utils/test_spi_utils.c b/components/driver/test_apps/components/test_driver_utils/test_spi_utils.c index 124021167f77..8e23021d84b6 100644 --- a/components/driver/test_apps/components/test_driver_utils/test_spi_utils.c +++ b/components/driver/test_apps/components/test_driver_utils/test_spi_utils.c @@ -91,6 +91,7 @@ void spitest_slave_task(void* arg) t.length = txdata.len; t.tx_buffer = txdata.start; t.rx_buffer = recvbuf + 8; + t.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO; //loop until trans_len != 0 to skip glitches do { TEST_ESP_OK(spi_slave_transmit(context->spi, &t, portMAX_DELAY)); @@ -231,6 +232,7 @@ void spitest_gpio_input_sel(uint32_t gpio_num, int func, uint32_t signal_idx) esp_rom_gpio_connect_in_signal(gpio_num, signal_idx, 0); } +#if (TEST_SPI_PERIPH_NUM >= 2) //Note this cs_dev_id is the ID of the connected devices' ID, e.g. if 2 devices are connected to the bus, //then the cs_dev_id of the 1st and 2nd devices are 0 and 1 respectively. void same_pin_func_sel(spi_bus_config_t bus, spi_device_interface_config_t dev, uint8_t cs_dev_id) @@ -247,3 +249,4 @@ void same_pin_func_sel(spi_bus_config_t bus, spi_device_interface_config_t dev, spitest_gpio_output_sel(bus.sclk_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spiclk_out); spitest_gpio_input_sel(bus.sclk_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiclk_in); } +#endif //(TEST_SPI_PERIPH_NUM >= 2) diff --git a/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/README.md b/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/README.md index 46d16c788ce9..844e5ee973b9 100644 --- a/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/README.md +++ b/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/pytest_legacy_i2s.py b/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/pytest_legacy_i2s.py index a5a9a9a1fff6..bb70f8ee6a76 100644 --- a/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/pytest_legacy_i2s.py +++ b/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/pytest_legacy_i2s.py @@ -12,6 +12,7 @@ @pytest.mark.esp32c6 @pytest.mark.esp32h2 @pytest.mark.esp32p4 +@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/driver/test_apps/twai/main/test_twai_loop_back.c b/components/driver/test_apps/twai/main/test_twai_loop_back.c index 7fea86000bfe..dccc92230547 100644 --- a/components/driver/test_apps/twai/main/test_twai_loop_back.c +++ b/components/driver/test_apps/twai/main/test_twai_loop_back.c @@ -12,6 +12,9 @@ #include "driver/twai.h" #include "soc/soc_caps.h" #include "esp_attr.h" +#include "esp_private/sleep_cpu.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" TEST_CASE("driver_life_cycle", "[twai-loop-back]") { @@ -130,3 +133,90 @@ TEST_CASE("twai_mode_ext_no_ack_250kbps", "[twai-loop-back]") TEST_ESP_OK(twai_driver_uninstall_v2(twai_buses[i])); } } + +static void s_test_sleep_retention(bool allow_pd) +{ + // 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); + + twai_handle_t twai_buses[SOC_TWAI_CONTROLLER_NUM] = {0}; + twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS(); + twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); + // bind the TX and RX to the same GPIO to act like a loopback + twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(0, 0, TWAI_MODE_NO_ACK); + g_config.general_flags.sleep_allow_pd = allow_pd; + twai_message_t tx_msg = { + .identifier = 0x12345, + .data_length_code = 6, + .data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}, + .self = true, // Transmitted message will also received by the same node + .extd = true, // Extended Frame Format (29bit ID) + }; + + for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) { + g_config.controller_id = i; + g_config.tx_io = i; + g_config.rx_io = i; + printf("install twai driver %d\r\n", g_config.controller_id); + TEST_ESP_OK(twai_driver_install_v2(&g_config, &t_config, &f_config, &twai_buses[i])); + } + + 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_TWAI_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 + + for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) { + TEST_ESP_OK(twai_start_v2(twai_buses[i])); + } + + for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) { + printf("transmit message from %d\r\n", i); + tx_msg.data[5] = SOC_TWAI_CONTROLLER_NUM - i; + TEST_ESP_OK(twai_transmit_v2(twai_buses[i], &tx_msg, pdMS_TO_TICKS(1000))); + } + + twai_message_t rx_msg; + for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) { + printf("receive message from %d\r\n", i); + TEST_ESP_OK(twai_receive_v2(twai_buses[i], &rx_msg, pdMS_TO_TICKS(1000))); + TEST_ASSERT_TRUE(rx_msg.data_length_code == 6); + tx_msg.data[5] = SOC_TWAI_CONTROLLER_NUM - i; + for (int i = 0; i < 6; i++) { + TEST_ASSERT_EQUAL(tx_msg.data[i], rx_msg.data[i]); + } + } + + for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) { + TEST_ESP_OK(twai_stop_v2(twai_buses[i])); + TEST_ESP_OK(twai_driver_uninstall_v2(twai_buses[i])); + } + + esp_sleep_set_sleep_context(NULL); +#if ESP_SLEEP_POWER_DOWN_CPU + TEST_ESP_OK(sleep_cpu_configure(false)); +#endif +} + +#if SOC_TWAI_SUPPORT_SLEEP_RETENTION +TEST_CASE("twai_mode_ext_no_ack_250kbps with sleep retention (allow pd)", "[twai-loop-back]") +{ + s_test_sleep_retention(true); +} +#endif + +TEST_CASE("twai_mode_ext_no_ack_250kbps with sleep retention (no pd)", "[twai-loop-back]") +{ + s_test_sleep_retention(false); +} diff --git a/components/driver/test_apps/twai/sdkconfig.ci.release b/components/driver/test_apps/twai/sdkconfig.ci.release index 91d93f163e62..29ef87d9695f 100644 --- a/components/driver/test_apps/twai/sdkconfig.ci.release +++ b/components/driver/test_apps/twai/sdkconfig.ci.release @@ -3,3 +3,5 @@ CONFIG_FREERTOS_USE_TICKLESS_IDLE=y 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 diff --git a/components/driver/test_apps/twai/sdkconfig.defaults b/components/driver/test_apps/twai/sdkconfig.defaults index b308cb2ddda0..feceba725e21 100644 --- a/components/driver/test_apps/twai/sdkconfig.defaults +++ b/components/driver/test_apps/twai/sdkconfig.defaults @@ -1,2 +1,4 @@ CONFIG_FREERTOS_HZ=1000 CONFIG_ESP_TASK_WDT=n +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/driver/twai/include/driver/twai.h b/components/driver/twai/include/driver/twai.h index 78bc71106a7a..6cde097f0cd6 100644 --- a/components/driver/twai/include/driver/twai.h +++ b/components/driver/twai/include/driver/twai.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -114,6 +114,11 @@ typedef struct { uint32_t alerts_enabled; /**< Bit field of alerts to enable (see documentation) */ uint32_t clkout_divider; /**< CLKOUT divider. Can be 1 or any even number from 2 to 14 (optional, set to 0 if unused) */ int intr_flags; /**< Interrupt flags to set the priority of the driver's ISR. Note that to use the ESP_INTR_FLAG_IRAM, the CONFIG_TWAI_ISR_IN_IRAM option should be enabled first. */ + struct { + uint32_t sleep_allow_pd; /**< Set to allow power down. When this flag set, the driver will backup/restore the TWAI registers before/after entering/exist sleep mode. + By this approach, the system can power off TWAI's power domain. + This can save power, but at the expense of more RAM being consumed. */ + } general_flags; /**< General flags */ } twai_general_config_t; /** diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index b6e0e982b5cb..0878239115a5 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -28,6 +28,9 @@ #include "soc/gpio_sig_map.h" #include "hal/twai_hal.h" #include "esp_rom_gpio.h" +#if SOC_TWAI_SUPPORT_SLEEP_RETENTION +#include "esp_private/sleep_retention.h" +#endif /* ---------------------------- Definitions --------------------------------- */ //Internal Macros @@ -64,6 +67,8 @@ #define TWAI_PERI_ATOMIC() #endif +#define TWAI_USE_RETENTION_LINK (SOC_TWAI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + /* ------------------ Typedefs, structures, and variables ------------------- */ //Control structure for TWAI driver @@ -96,6 +101,11 @@ typedef struct twai_obj_t { static twai_handle_t g_twai_objs[SOC_TWAI_CONTROLLER_NUM]; static portMUX_TYPE g_spinlock = portMUX_INITIALIZER_UNLOCKED; +/* -------------------- Sleep Retention ------------------------ */ +#if TWAI_USE_RETENTION_LINK +static esp_err_t s_twai_create_sleep_retention_link_cb(void *obj); +#endif + /* -------------------- Interrupt and Alert Handlers ------------------------ */ static void twai_alert_handler(twai_obj_t *p_twai_obj, uint32_t alert_code, int *alert_req) @@ -334,6 +344,19 @@ static void twai_free_driver_obj(twai_obj_t *p_obj) if (p_obj->alert_semphr != NULL) { vSemaphoreDeleteWithCaps(p_obj->alert_semphr); } + +#if TWAI_USE_RETENTION_LINK + const periph_retention_module_t retention_id = twai_reg_retention_info[p_obj->controller_id].module_id; + 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); + } + +#endif + heap_caps_free(p_obj); } @@ -365,6 +388,9 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw if (ret != ESP_OK) { goto err; } + + p_obj->controller_id = controller_id; + #if CONFIG_PM_ENABLE #if SOC_TWAI_CLK_SUPPORT_APB // DFS can change APB frequency. So add lock to prevent sleep and APB freq from changing @@ -384,6 +410,28 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw #endif //SOC_TWAI_CLK_SUPPORT_APB #endif //CONFIG_PM_ENABLE +#if TWAI_USE_RETENTION_LINK + sleep_retention_module_t module = twai_reg_retention_info[controller_id].module_id; + sleep_retention_module_init_param_t init_param = { + .cbs = { + .create = { + .handle = s_twai_create_sleep_retention_link_cb, + .arg = p_obj, + }, + }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) + }; + if (sleep_retention_module_init(module, &init_param) != ESP_OK) { + ESP_LOGW(TWAI_TAG, "init sleep retention failed for TWAI%d, power domain may be turned off during sleep", controller_id); + } + + if (g_config->general_flags.sleep_allow_pd) { + if (sleep_retention_module_allocate(module) != ESP_OK) { + ESP_LOGW(TWAI_TAG, "create retention module failed, power domain can't turn off"); + } + } +#endif + *p_twai_obj_ret = p_obj; return ESP_OK; @@ -408,6 +456,9 @@ esp_err_t twai_driver_install_v2(const twai_general_config_t *g_config, const tw #endif int controller_id = g_config->controller_id; TWAI_CHECK(g_twai_objs[controller_id] == NULL, ESP_ERR_INVALID_STATE); +#if !SOC_TWAI_SUPPORT_SLEEP_RETENTION + TWAI_CHECK(!g_config->general_flags.sleep_allow_pd, ESP_ERR_INVALID_ARG); +#endif //Get clock source resolution uint32_t clock_source_hz = 0; @@ -437,7 +488,6 @@ esp_err_t twai_driver_install_v2(const twai_general_config_t *g_config, const tw //Initialize flags and variables. All other members are already set to zero by twai_alloc_driver_obj() portMUX_INITIALIZE(&p_twai_obj->spinlock); - p_twai_obj->controller_id = controller_id; p_twai_obj->state = TWAI_STATE_STOPPED; p_twai_obj->mode = g_config->mode; p_twai_obj->alerts_enabled = g_config->alerts_enabled; @@ -874,3 +924,14 @@ esp_err_t twai_clear_receive_queue(void) // the handle-less driver API only support one TWAI controller, i.e. the g_twai_objs[0] return twai_clear_receive_queue_v2(g_twai_objs[0]); } + +#if TWAI_USE_RETENTION_LINK +static esp_err_t s_twai_create_sleep_retention_link_cb(void *obj) +{ + twai_obj_t *host = (twai_obj_t *)obj; + return sleep_retention_entries_create(twai_reg_retention_info[host->controller_id].entry_array, + twai_reg_retention_info[host->controller_id].array_size, + REGDMA_LINK_PRI_TWAI, + twai_reg_retention_info[host->controller_id].module_id); +} +#endif diff --git a/components/efuse/CMakeLists.txt b/components/efuse/CMakeLists.txt index e0f57b1d3431..8b5d587213ed 100644 --- a/components/efuse/CMakeLists.txt +++ b/components/efuse/CMakeLists.txt @@ -1,4 +1,5 @@ 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" @@ -28,7 +29,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(BOOTLOADER_BUILD) +if(non_os_build) idf_component_register(SRCS "${srcs}" PRIV_REQUIRES bootloader_support soc spi_flash INCLUDE_DIRS "${include_dirs}" diff --git a/components/efuse/src/esp_efuse_api.c b/components/efuse/src/esp_efuse_api.c index 64059f72a10b..36c555435c54 100644 --- a/components/efuse/src/esp_efuse_api.c +++ b/components/efuse/src/esp_efuse_api.c @@ -13,7 +13,7 @@ const static char *TAG = "efuse"; -#if defined(BOOTLOADER_BUILD) +#ifdef NON_OS_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 BOOTLOADER_BUILD +#ifndef NON_OS_BUILD if (err == ESP_ERR_DAMAGED_READING) { vTaskDelay(1); } -#endif // BOOTLOADER_BUILD +#endif // NON_OS_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 BOOTLOADER_BUILD +#ifndef NON_OS_BUILD if (err == ESP_ERR_DAMAGED_READING) { vTaskDelay(1); } -#endif // BOOTLOADER_BUILD +#endif // NON_OS_BUILD } while (err == ESP_ERR_DAMAGED_READING); } return err; diff --git a/components/esp_coex/Kconfig b/components/esp_coex/Kconfig index 5fb0eac973aa..bc37b3820b2d 100644 --- a/components/esp_coex/Kconfig +++ b/components/esp_coex/Kconfig @@ -217,7 +217,7 @@ menu "Wireless Coexistence" default 12 if IDF_TARGET_ESP32S3 default 3 if IDF_TARGET_ESP32C2 default 22 if IDF_TARGET_ESP32C6 - default 16 if IDF_TARGET_ESP32C5 + default 10 if IDF_TARGET_ESP32C5 default 13 if IDF_TARGET_ESP32C61 default 11 @@ -231,7 +231,7 @@ menu "Wireless Coexistence" default 13 if IDF_TARGET_ESP32S3 default 2 if IDF_TARGET_ESP32C2 default 21 if IDF_TARGET_ESP32C6 - default 0 if IDF_TARGET_ESP32C5 + default 9 if IDF_TARGET_ESP32C5 default 12 if IDF_TARGET_ESP32C61 default 12 diff --git a/components/esp_coex/esp32c2/esp_coex_adapter.c b/components/esp_coex/esp32c2/esp_coex_adapter.c index 4954fb9f8506..b98c9c94742d 100644 --- a/components/esp_coex/esp32c2/esp_coex_adapter.c +++ b/components/esp_coex/esp32c2/esp_coex_adapter.c @@ -152,6 +152,11 @@ static int esp_coexist_debug_matrix_init_wrapper(int evt, int sig, bool rev) #endif } +static IRAM_ATTR int esp_coex_common_xtal_freq_get_wrapper(void) +{ + return rtc_clk_xtal_freq_get(); +} + coex_adapter_funcs_t g_coex_adapter_funcs = { ._version = COEX_ADAPTER_VERSION, ._task_yield_from_isr = esp_coex_common_task_yield_from_isr_wrapper, @@ -172,5 +177,6 @@ coex_adapter_funcs_t g_coex_adapter_funcs = { ._timer_setfn = esp_coex_common_timer_setfn_wrapper, ._timer_arm_us = esp_coex_common_timer_arm_us_wrapper, ._debug_matrix_init = esp_coexist_debug_matrix_init_wrapper, + ._xtal_freq_get = esp_coex_common_xtal_freq_get_wrapper, ._magic = COEX_ADAPTER_MAGIC, }; diff --git a/components/esp_coex/esp32c5/esp_coex_adapter.c b/components/esp_coex/esp32c5/esp_coex_adapter.c index b5e761ffbd9f..8588b7348d10 100644 --- a/components/esp_coex/esp32c5/esp_coex_adapter.c +++ b/components/esp_coex/esp32c5/esp_coex_adapter.c @@ -151,6 +151,11 @@ static int esp_coexist_debug_matrix_init_wrapper(int evt, int sig, bool rev) #endif } +static IRAM_ATTR int esp_coex_common_xtal_freq_get_wrapper(void) +{ + return rtc_clk_xtal_freq_get(); +} + coex_adapter_funcs_t g_coex_adapter_funcs = { ._version = COEX_ADAPTER_VERSION, ._task_yield_from_isr = esp_coex_common_task_yield_from_isr_wrapper, @@ -170,5 +175,6 @@ coex_adapter_funcs_t g_coex_adapter_funcs = { ._timer_setfn = esp_coex_common_timer_setfn_wrapper, ._timer_arm_us = esp_coex_common_timer_arm_us_wrapper, ._debug_matrix_init = esp_coexist_debug_matrix_init_wrapper, + ._xtal_freq_get = esp_coex_common_xtal_freq_get_wrapper, ._magic = COEX_ADAPTER_MAGIC, }; diff --git a/components/esp_coex/esp32c6/esp_coex_adapter.c b/components/esp_coex/esp32c6/esp_coex_adapter.c index 81b4eef2b1e7..4b920ce15951 100644 --- a/components/esp_coex/esp32c6/esp_coex_adapter.c +++ b/components/esp_coex/esp32c6/esp_coex_adapter.c @@ -152,6 +152,11 @@ static int esp_coexist_debug_matrix_init_wrapper(int evt, int sig, bool rev) #endif } +static IRAM_ATTR int esp_coex_common_xtal_freq_get_wrapper(void) +{ + return rtc_clk_xtal_freq_get(); +} + coex_adapter_funcs_t g_coex_adapter_funcs = { ._version = COEX_ADAPTER_VERSION, ._task_yield_from_isr = esp_coex_common_task_yield_from_isr_wrapper, @@ -171,5 +176,6 @@ coex_adapter_funcs_t g_coex_adapter_funcs = { ._timer_setfn = esp_coex_common_timer_setfn_wrapper, ._timer_arm_us = esp_coex_common_timer_arm_us_wrapper, ._debug_matrix_init = esp_coexist_debug_matrix_init_wrapper, + ._xtal_freq_get = esp_coex_common_xtal_freq_get_wrapper, ._magic = COEX_ADAPTER_MAGIC, }; diff --git a/components/esp_coex/esp32c61/esp_coex_adapter.c b/components/esp_coex/esp32c61/esp_coex_adapter.c index 547e1dbd3630..059160f7bab4 100644 --- a/components/esp_coex/esp32c61/esp_coex_adapter.c +++ b/components/esp_coex/esp32c61/esp_coex_adapter.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -152,6 +152,11 @@ static int esp_coexist_debug_matrix_init_wrapper(int evt, int sig, bool rev) #endif } +static IRAM_ATTR int esp_coex_common_xtal_freq_get_wrapper(void) +{ + return rtc_clk_xtal_freq_get(); +} + coex_adapter_funcs_t g_coex_adapter_funcs = { ._version = COEX_ADAPTER_VERSION, ._task_yield_from_isr = esp_coex_common_task_yield_from_isr_wrapper, @@ -171,5 +176,6 @@ coex_adapter_funcs_t g_coex_adapter_funcs = { ._timer_setfn = esp_coex_common_timer_setfn_wrapper, ._timer_arm_us = esp_coex_common_timer_arm_us_wrapper, ._debug_matrix_init = esp_coexist_debug_matrix_init_wrapper, + ._xtal_freq_get = esp_coex_common_xtal_freq_get_wrapper, ._magic = COEX_ADAPTER_MAGIC, }; diff --git a/components/esp_coex/esp32h2/esp_coex_adapter.c b/components/esp_coex/esp32h2/esp_coex_adapter.c index f00cade6f6bd..1fa2243ae9ab 100644 --- a/components/esp_coex/esp32h2/esp_coex_adapter.c +++ b/components/esp_coex/esp32h2/esp_coex_adapter.c @@ -144,6 +144,11 @@ static int esp_coexist_debug_matrix_init_wrapper(int evt, int sig, bool rev) #endif } +static IRAM_ATTR int esp_coex_common_xtal_freq_get_wrapper(void) +{ + return rtc_clk_xtal_freq_get(); +} + coex_adapter_funcs_t g_coex_adapter_funcs = { ._version = COEX_ADAPTER_VERSION, ._task_yield_from_isr = esp_coex_common_task_yield_from_isr_wrapper, @@ -163,5 +168,6 @@ coex_adapter_funcs_t g_coex_adapter_funcs = { ._timer_setfn = esp_coex_common_timer_setfn_wrapper, ._timer_arm_us = esp_coex_common_timer_arm_us_wrapper, ._debug_matrix_init = esp_coexist_debug_matrix_init_wrapper, + ._xtal_freq_get = esp_coex_common_xtal_freq_get_wrapper, ._magic = COEX_ADAPTER_MAGIC, }; diff --git a/components/esp_coex/include/private/esp_coexist_adapter.h b/components/esp_coex/include/private/esp_coexist_adapter.h index aca50a6161a2..15e8ef7114fe 100644 --- a/components/esp_coex/include/private/esp_coexist_adapter.h +++ b/components/esp_coex/include/private/esp_coexist_adapter.h @@ -47,6 +47,7 @@ typedef struct { void (* _timer_setfn)(void *ptimer, void *pfunction, void *parg); void (* _timer_arm_us)(void *ptimer, uint32_t us, bool repeat); int (* _debug_matrix_init)(int event, int signal, bool rev); + int (* _xtal_freq_get)(void); int32_t _magic; } coex_adapter_funcs_t; diff --git a/components/esp_coex/include/private/esp_coexist_debug.h b/components/esp_coex/include/private/esp_coexist_debug.h index 26147262c753..80bfbbd5aa6f 100644 --- a/components/esp_coex/include/private/esp_coexist_debug.h +++ b/components/esp_coex/include/private/esp_coexist_debug.h @@ -108,7 +108,7 @@ typedef enum { #endif /* wifi callback -> debug */ -void wifi_set_gpio_debug_cb(void (* cb)(int, int)); +void wifi_set_gpio_debug_cb(void (* cb)(int, coex_gpio_debug_sig_t)); int wifi_gpio_debug_max_event_get(void); /* functions to check if in ROM */ @@ -128,9 +128,10 @@ void pm_check_state(void); void pm_tx_null_data_done_process(void); void pm_start(void); void pm_stop(void); +void pm_disconnected_wake(void); /* coex callback -> debug */ -void coex_set_gpio_debug_cb(void (*cb)(int, int)); +void coex_set_gpio_debug_cb(void (*cb)(int, coex_gpio_debug_sig_t)); int coex_gpio_debug_max_event_get(void); esp_err_t coex_gpio_debug_matrix_init(void); @@ -142,4 +143,10 @@ void wifi_bind_io_to_evt(uint8_t io_idx, uint8_t evt); void coex_bind_io_to_evt(uint8_t io_idx, uint8_t evt); void diagram_bind_io_to_evt(void); +/* coex -> debug + * configure single gpio debug event */ +esp_err_t coex_gpio_debug_matrix_config(int event); +/* debug -> internal use */ +esp_err_t esp_coexist_gpio_debug_matrix_config(int event); + #endif diff --git a/components/esp_coex/lib b/components/esp_coex/lib index e15e7a161fc1..9baa4202b6bd 160000 --- a/components/esp_coex/lib +++ b/components/esp_coex/lib @@ -1 +1 @@ -Subproject commit e15e7a161fc1a48e8fb4fd0b3da74623c30ba1cb +Subproject commit 9baa4202b6bddac85aa5f318c171a1b413e2caea diff --git a/components/esp_coex/src/coexist_debug.c b/components/esp_coex/src/coexist_debug.c index 7c38eea8e515..8ef1eb6de168 100644 --- a/components/esp_coex/src/coexist_debug.c +++ b/components/esp_coex/src/coexist_debug.c @@ -13,37 +13,20 @@ #include "esp_attr.h" #include "esp_log.h" -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/rom/gpio.h" -#include "esp32/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32S2) -#include "esp32s2/rom/gpio.h" -#include "esp32s2/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#include "esp32c3/rom/gpio.h" -#include "esp32c3/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C2) -#include "esp32c2/rom/gpio.h" -#include "esp32c2/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C6) -#include "esp32c6/rom/gpio.h" -#include "esp32c6/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C5) -#include "esp32c5/rom/gpio.h" -#include "esp32c5/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C61) -#include "esp32c61/rom/gpio.h" -#include "esp32c61/rom/ets_sys.h" -#endif +#include "rom/gpio.h" +#include "rom/ets_sys.h" #include "driver/gpio.h" #include "soc/gpio_sig_map.h" #include "esp_rom_gpio.h" #include "soc/soc.h" +#if SOC_MODEM_CLOCK_IS_INDEPENDENT +#include "esp_private/esp_modem_clock.h" +#endif #if CONFIG_ESP_COEX_GPIO_DEBUG static char* TAG = "coexist debug"; -__attribute__((weak)) void wifi_set_gpio_debug_cb(void (* cb)(int, int)) +__attribute__((weak)) void wifi_set_gpio_debug_cb(void (* cb)(int, coex_gpio_debug_sig_t)) { ESP_LOGW(TAG, "Not support: %s", __FUNCTION__); } @@ -53,7 +36,7 @@ __attribute__((weak)) int wifi_gpio_debug_max_event_get(void) return 0; } -__attribute__((weak)) void coex_set_gpio_debug_cb(void (*cb)(int, int)) +__attribute__((weak)) void coex_set_gpio_debug_cb(void (*cb)(int, coex_gpio_debug_sig_t)) { ESP_LOGW(TAG, "Not support: %s", __FUNCTION__); } @@ -89,6 +72,7 @@ static const void* rom_funcs[] = { pm_tx_null_data_done_process, pm_start, pm_stop, + pm_disconnected_wake, #endif }; static const char* rom_funcs_name[] = { @@ -109,6 +93,7 @@ static const char* rom_funcs_name[] = { "pm_tx_null_data_done_process", "pm_start", "pm_stop", + "pm_disconnected_wake", #endif }; @@ -205,6 +190,18 @@ esp_err_t esp_coexist_debug_matrix_init(int evt, int sig, bool rev) return ESP_OK; } +esp_err_t esp_coexist_gpio_debug_matrix_config(int event) +{ +#if SOC_MODEM_CLOCK_IS_INDEPENDENT + modem_clock_module_enable(PERIPH_COEX_MODULE); +#endif + esp_err_t ret = coex_gpio_debug_matrix_config(event); +#if SOC_MODEM_CLOCK_IS_INDEPENDENT + modem_clock_module_disable(PERIPH_COEX_MODULE); +#endif + return ret; +} + esp_err_t esp_coexist_debug_init(void) { if (check_funcs_in_rom()) { @@ -268,8 +265,14 @@ esp_err_t esp_coexist_debug_init(void) gpio_set_level(s_io_nums[i], false); } +#if SOC_MODEM_CLOCK_IS_INDEPENDENT + modem_clock_module_enable(PERIPH_COEX_MODULE); +#endif /* Init coexist hardware signal */ ESP_ERROR_CHECK(coex_gpio_debug_matrix_init()); +#if SOC_MODEM_CLOCK_IS_INDEPENDENT + modem_clock_module_disable(PERIPH_COEX_MODULE); +#endif return ESP_OK; } diff --git a/components/esp_coex/test_md5/test_md5.sh b/components/esp_coex/test_md5/test_md5.sh index 24f80b76e3bb..429796bdfa75 100755 --- a/components/esp_coex/test_md5/test_md5.sh +++ b/components/esp_coex/test_md5/test_md5.sh @@ -32,40 +32,74 @@ case $IDF_TARGET in esac LIB_DIR=${IDF_TARGET} -ELF_FILE=test.elf +COEX_ELF_FILE=coex.elf +TEST_ELF_FILE=test.elf FAILURES=0 function check_md5() +{ + if [ "$1" != "$2" ]; then + echo " error: MD5 mismatch!" + FAILURES=$(($FAILURES+1)) + fi +} + +function check_md5_file_lib() { FILENAME=$1 SYMBOL=$2 - ${PREFIX}ld --unresolved-symbols=ignore-all --entry 0 -o ${ELF_FILE} \ + ${PREFIX}ld --unresolved-symbols=ignore-all --entry 0 -o ${COEX_ELF_FILE} \ -u ${SYMBOL} \ ${IDF_PATH}/components/esp_coex/lib/${LIB_DIR}/*.a GDB_COMMAND="printf \"%s\\n\", (const char*) ${SYMBOL}" - MD5_FROM_LIB=$(${PREFIX}gdb -n -batch ${ELF_FILE} -ex "${GDB_COMMAND}") + MD5_FROM_LIB=$(${PREFIX}gdb -n -batch ${COEX_ELF_FILE} -ex "${GDB_COMMAND}") MD5_FROM_HEADER=$(md5sum ${FILENAME} | cut -c 1-7) - echo "Checking ${FILENAME}:" echo " ${MD5_FROM_HEADER} - from header file" echo " ${MD5_FROM_LIB} - from library" - if [ "${MD5_FROM_LIB}" != "${MD5_FROM_HEADER}" ]; then - echo " error: MD5 mismatch!" - FAILURES=$(($FAILURES+1)) - fi + check_md5 ${MD5_FROM_HEADER} ${MD5_FROM_LIB} +} + +function check_md5_libs() +{ + COEX_SYMBOL=$1 + TEST_SYMBOL=$2 + TEST_PATH=$3 + + ${PREFIX}ld --unresolved-symbols=ignore-all --entry 0 -o ${COEX_ELF_FILE} \ + -u ${COEX_SYMBOL} \ + ${IDF_PATH}/components/esp_coex/lib/${LIB_DIR}/*.a + + ${PREFIX}ld --unresolved-symbols=ignore-all --entry 0 -o ${TEST_ELF_FILE} \ + -u ${TEST_SYMBOL} \ + ${TEST_PATH}/*.a + + COEX_GDB_COMMAND="printf \"%s\\n\", (const char*) ${COEX_SYMBOL}" + TEST_GDB_COMMAND="printf \"%s\\n\", (const char*) ${TEST_SYMBOL}" + COEX_MD5_FROM_LIB=$(${PREFIX}gdb -n -batch ${COEX_ELF_FILE} -ex "${COEX_GDB_COMMAND}") + TEST_MD5_FROM_LIB=$(${PREFIX}gdb -n -batch ${TEST_ELF_FILE} -ex "${TEST_GDB_COMMAND}") + + echo "Checking ${TEST_PATH}/${TEST_SYMBOL} " + echo " ${COEX_MD5_FROM_LIB} - from coexist library" + echo " ${TEST_MD5_FROM_LIB} - from test library" + check_md5 ${COEX_MD5_FROM_LIB} ${TEST_MD5_FROM_LIB} } echo "Checking libraries for target ${IDF_TARGET}..." -check_md5 ${IDF_PATH}/components/esp_coex/include/private/esp_coexist_adapter.h g_coex_adapter_funcs_md5 +check_md5_file_lib ${IDF_PATH}/components/esp_coex/include/private/esp_coexist_adapter.h g_coex_adapter_funcs_md5 case $IDF_TARGET in esp32c6|esp32h2|esp32c5) - check_md5 ${IDF_PATH}/components/esp_coex/include/esp_coex_i154.h g_coex_i154_funcs_md5 + check_md5_file_lib ${IDF_PATH}/components/esp_coex/include/esp_coex_i154.h g_coex_i154_funcs_md5 ;; esac +if [[ ! "$IDF_TARGET" =~ ^(esp32h2)$ ]]; then + check_md5_libs g_coex_basic_md5 g_wifi_coex_basic_md5 ${IDF_PATH}/components/esp_wifi/lib/${LIB_DIR} +fi + if [ $FAILURES -gt 0 ]; then exit 1 fi diff --git a/components/esp_common/include/esp_macros.h b/components/esp_common/include/esp_macros.h index 183c947a44fd..0893878e7eb3 100644 --- a/components/esp_common/include/esp_macros.h +++ b/components/esp_common/include/esp_macros.h @@ -50,15 +50,15 @@ extern "C" { /* Count number of arguments of __VA_ARGS__ * - reference https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s * - __GET_NTH_ARG__() takes args >= N (64) but only expand to Nth one (64th) - * - __RSEQ_N__() is reverse sequential to N to add padding to have Nth + * - ESP_RSEQ_N() is reverse sequential to N to add padding to have Nth * position is the same as the number of arguments * - ##__VA_ARGS__ is used to deal with 0 parameter (swallows comma) */ -#ifndef __VA_NARG__ -# define __VA_NARG__(...) __NARG__(_0, ##__VA_ARGS__, __RSEQ_N__()) +#ifndef ESP_VA_NARG +# define ESP_VA_NARG(...) ESP_NARG(_0, ##__VA_ARGS__, ESP_RSEQ_N()) -# define __NARG__(...) __GET_NTH_ARG__(__VA_ARGS__) -# define __GET_NTH_ARG__( \ +# define ESP_NARG(...) ESP_GET_NTH_ARG(__VA_ARGS__) +# define ESP_GET_NTH_ARG( \ _01,_02,_03,_04,_05,_06,_07,_08,_09,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ @@ -66,7 +66,7 @@ extern "C" { _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63,N,...) N -# define __RSEQ_N__() \ +# define ESP_RSEQ_N() \ 62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ @@ -80,25 +80,6 @@ extern "C" { #define ESP_UNUSED(x) ((void)(x)) #endif -/* test macros */ -#define foo_args(...) 1 -#define foo_no_args() 2 -#if defined(__cplusplus) && (__cplusplus > 201703L) -#define foo(...) CHOOSE_MACRO_VA_ARG(foo_args, foo_no_args __VA_OPT__(,) __VA_ARGS__)(__VA_ARGS__) -#else -#define foo(...) CHOOSE_MACRO_VA_ARG(foo_args, foo_no_args, ##__VA_ARGS__)(__VA_ARGS__) -#endif - -ESP_STATIC_ASSERT(foo() == 2, "CHOOSE_MACRO_VA_ARG() result does not match for 0 arguments"); -ESP_STATIC_ASSERT(foo(42) == 1, "CHOOSE_MACRO_VA_ARG() result does not match for 1 argument"); -#if defined(__cplusplus) && (__cplusplus > 201703L) -ESP_STATIC_ASSERT(foo(42, 87) == 1, "CHOOSE_MACRO_VA_ARG() result does not match for n arguments"); -#endif - -#undef foo -#undef foo_args -#undef foo_no_args - #define ESP_INFINITE_LOOP() \ do { \ ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-infinite-loop") \ diff --git a/components/esp_common/test_apps/esp_common/main/CMakeLists.txt b/components/esp_common/test_apps/esp_common/main/CMakeLists.txt index d1e953e63823..f45ce0708cd0 100644 --- a/components/esp_common/test_apps/esp_common/main/CMakeLists.txt +++ b/components/esp_common/test_apps/esp_common/main/CMakeLists.txt @@ -1,4 +1,4 @@ -idf_component_register(SRCS "test_app_main.c" "test_attr.c" +idf_component_register(SRCS "test_app_main.c" "test_attr.c" "test_esp_macro.c" INCLUDE_DIRS "." PRIV_REQUIRES unity esp_mm esp_psram WHOLE_ARCHIVE) diff --git a/components/esp_common/test_apps/esp_common/main/test_esp_macro.c b/components/esp_common/test_apps/esp_common/main/test_esp_macro.c new file mode 100644 index 000000000000..334fa9806722 --- /dev/null +++ b/components/esp_common/test_apps/esp_common/main/test_esp_macro.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "esp_macros.h" + +/* test macros */ +#define foo_args(...) 1 +#define foo_no_args() 2 +#if defined(__cplusplus) && (__cplusplus > 201703L) +#define foo(...) CHOOSE_MACRO_VA_ARG(foo_args, foo_no_args __VA_OPT__(,) __VA_ARGS__)(__VA_ARGS__) +#else +#define foo(...) CHOOSE_MACRO_VA_ARG(foo_args, foo_no_args, ##__VA_ARGS__)(__VA_ARGS__) +#endif + +ESP_STATIC_ASSERT(foo() == 2, "CHOOSE_MACRO_VA_ARG() result does not match for 0 arguments"); +ESP_STATIC_ASSERT(foo(42) == 1, "CHOOSE_MACRO_VA_ARG() result does not match for 1 argument"); +#if defined(__cplusplus) && (__cplusplus > 201703L) +ESP_STATIC_ASSERT(foo(42, 87) == 1, "CHOOSE_MACRO_VA_ARG() result does not match for n arguments"); +#endif diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 index 0d33cfbf8f43..5470efa12084 100644 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 +++ b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 @@ -5,4 +5,4 @@ CONFIG_SPIRAM=y CONFIG_SPIRAM_XIP_FROM_PSRAM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 index fd9b7e865c3c..3c7418b55d97 100644 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 +++ b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 @@ -5,4 +5,4 @@ CONFIG_SPIRAM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_RODATA=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 index 3b1db1f233fd..53125cb9b8ba 100644 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 +++ b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 @@ -5,4 +5,4 @@ CONFIG_SPIRAM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_RODATA=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y diff --git a/components/esp_driver_dac/dac_continuous.c b/components/esp_driver_dac/dac_continuous.c index b3f8f9c25e01..c7e4ffb5eaea 100644 --- a/components/esp_driver_dac/dac_continuous.c +++ b/components/esp_driver_dac/dac_continuous.c @@ -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 = cont_cfg->clk_src == DAC_DIGI_CLK_SRC_APLL ? ESP_PM_NO_LIGHT_SLEEP : ESP_PM_APB_FREQ_MAX; + esp_pm_lock_type_t pm_lock_type = 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); diff --git a/components/esp_driver_gpio/include/esp_private/gpio.h b/components/esp_driver_gpio/include/esp_private/gpio.h index b2186295c0a5..2e06192f633c 100644 --- a/components/esp_driver_gpio/include/esp_private/gpio.h +++ b/components/esp_driver_gpio/include/esp_private/gpio.h @@ -52,6 +52,17 @@ esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num); */ esp_err_t gpio_func_sel(gpio_num_t gpio_num, uint32_t func); +/** + * @brief Enable output for an IO + * + * @param gpio_num GPIO number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO number error + */ +esp_err_t gpio_output_enable(gpio_num_t gpio_num); + /** * @brief Disable output for an IO * diff --git a/components/esp_driver_gpio/src/dedic_gpio.c b/components/esp_driver_gpio/src/dedic_gpio.c index bbc66995b2c9..3faf0d9de7e7 100644 --- a/components/esp_driver_gpio/src/dedic_gpio.c +++ b/components/esp_driver_gpio/src/dedic_gpio.c @@ -269,6 +269,7 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_ if (config->flags.in_en) { for (size_t i = 0; i < config->array_size; i++) { gpio_func_sel(config->gpio_array[i], PIN_FUNC_GPIO); + gpio_input_enable(config->gpio_array[i]); esp_rom_gpio_connect_in_signal(config->gpio_array[i], dedic_gpio_periph_signals.cores[core_id].in_sig_per_channel[in_offset + i], config->flags.in_invert); } } @@ -325,6 +326,17 @@ esp_err_t dedic_gpio_del_bundle(dedic_gpio_bundle_handle_t bundle) } portEXIT_CRITICAL(&s_platform[core_id]->spinlock); + if (bundle->in_mask > 0) { + for (size_t i = 0; i < bundle->nr_gpio; i++) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, dedic_gpio_periph_signals.cores[core_id].in_sig_per_channel[bundle->in_offset + i], 0); + } + } + if (bundle->out_mask > 0) { + for (size_t i = 0; i < bundle->nr_gpio; i++) { + gpio_output_disable(bundle->gpio_array[i]); + } + } + free(bundle); if (recycle_all) { diff --git a/components/esp_driver_gpio/src/gpio.c b/components/esp_driver_gpio/src/gpio.c index cffca8e8e834..a63ab11375aa 100644 --- a/components/esp_driver_gpio/src/gpio.c +++ b/components/esp_driver_gpio/src/gpio.c @@ -211,7 +211,7 @@ esp_err_t gpio_output_disable(gpio_num_t gpio_num) return ESP_OK; } -static esp_err_t gpio_output_enable(gpio_num_t gpio_num) +esp_err_t gpio_output_enable(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG); gpio_hal_matrix_out_default(gpio_context.gpio_hal, gpio_num); // No peripheral output signal routed to the pin, just as a simple GPIO output diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_dedicated_gpio.c b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_dedicated_gpio.c index fb306b523ee0..9b3f73635e6b 100644 --- a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_dedicated_gpio.c +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_dedicated_gpio.c @@ -70,16 +70,8 @@ static void test_dedic_gpio_on_specific_core(void *args) uint32_t value = 0; dedic_gpio_cpu_ll_write_all(0x0); // clear all out channels - // configure a group of GPIOs, output only - const int bundleA_gpios[] = {ctx->gpios[0], ctx->gpios[1]}; - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - }; - for (int i = 0; i < sizeof(bundleA_gpios) / sizeof(bundleA_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundleA_gpios[i]; - gpio_config(&io_conf); - } // Create bundleA, output only + const int bundleA_gpios[] = {ctx->gpios[0], ctx->gpios[1]}; dedic_gpio_bundle_handle_t bundleA = NULL; dedic_gpio_bundle_config_t bundleA_config = { .gpio_array = bundleA_gpios, @@ -90,15 +82,8 @@ static void test_dedic_gpio_on_specific_core(void *args) }; TEST_ESP_OK(dedic_gpio_new_bundle(&bundleA_config, &bundleA)); - // configure another group of GPIOs, input and output - const int bundleB_gpios[] = {ctx->gpios[2], ctx->gpios[3]}; - io_conf.mode = GPIO_MODE_INPUT_OUTPUT; - for (int i = 0; i < sizeof(bundleB_gpios) / sizeof(bundleB_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundleB_gpios[i]; - gpio_config(&io_conf); - } - // GPIO bundleB, input and output + const int bundleB_gpios[] = {ctx->gpios[2], ctx->gpios[3]}; dedic_gpio_bundle_handle_t bundleB = NULL; dedic_gpio_bundle_config_t bundleB_config = { .gpio_array = bundleB_gpios, @@ -192,13 +177,6 @@ TEST_CASE("Dedicated_GPIO_interrupt_and_callback", "[dedic_gpio]") #else const int bundle_gpios[] = {0, 1}; #endif - gpio_config_t io_conf = { - .mode = GPIO_MODE_INPUT_OUTPUT, - }; - for (int i = 0; i < sizeof(bundle_gpios) / sizeof(bundle_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundle_gpios[i]; - gpio_config(&io_conf); - } dedic_gpio_bundle_handle_t bundle = NULL; dedic_gpio_bundle_config_t bundle_config = { .gpio_array = bundle_gpios, diff --git a/components/esp_driver_gptimer/src/gptimer_common.c b/components/esp_driver_gptimer/src/gptimer_common.c index 928ce3c84ad2..8338ebb2f491 100644 --- a/components/esp_driver_gptimer/src/gptimer_common.c +++ b/components/esp_driver_gptimer/src/gptimer_common.c @@ -27,24 +27,21 @@ static esp_err_t gptimer_create_sleep_retention_link_cb(void *arg) { gptimer_group_t *group = (gptimer_group_t *)arg; int group_id = group->group_id; - sleep_retention_module_t module = group->sleep_retention_module; esp_err_t err = sleep_retention_entries_create(tg_timer_reg_retention_info[group_id].regdma_entry_array, tg_timer_reg_retention_info[group_id].array_size, - REGDMA_LINK_PRI_GPTIMER, module); - ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed"); - return ESP_OK; + REGDMA_LINK_PRI_GPTIMER, tg_timer_reg_retention_info[group_id].module); + return err; } void gptimer_create_retention_module(gptimer_group_t *group) { - sleep_retention_module_t module = group->sleep_retention_module; + int group_id = group->group_id; + sleep_retention_module_t module = tg_timer_reg_retention_info[group_id].module; _lock_acquire(&s_platform.mutex); - if (group->retention_link_created == false) { + if ((sleep_retention_get_inited_modules() & BIT(module)) && !(sleep_retention_get_created_modules() & BIT(module))) { if (sleep_retention_module_allocate(module) != ESP_OK) { // even though the sleep retention module create failed, GPTimer driver should still work, so just warning here - ESP_LOGW(TAG, "create retention module for group %d retention, power domain can't turn off", group->group_id); - } else { - group->retention_link_created = true; + ESP_LOGW(TAG, "create retention link failed %d, power domain won't be turned off during sleep", group_id); } } _lock_release(&s_platform.mutex); @@ -97,9 +94,7 @@ gptimer_group_t *gptimer_acquire_group_handle(int group_id) }, .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) }; - if (sleep_retention_module_init(module, &init_param) == ESP_OK) { - group->sleep_retention_module = module; - } else { + if (sleep_retention_module_init(module, &init_param) != ESP_OK) { // even though the sleep retention module init failed, RMT 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); } @@ -132,11 +127,12 @@ void gptimer_release_group_handle(gptimer_group_t *group) } } #if GPTIMER_USE_RETENTION_LINK - if (group->sleep_retention_module) { - if (group->retention_link_created) { - sleep_retention_module_free(group->sleep_retention_module); - } - sleep_retention_module_deinit(group->sleep_retention_module); + sleep_retention_module_t module = tg_timer_reg_retention_info[group_id].module; + if (sleep_retention_get_created_modules() & BIT(module)) { + sleep_retention_module_free(module); + } + if (sleep_retention_get_inited_modules() & BIT(module)) { + sleep_retention_module_deinit(module); } #endif free(group); diff --git a/components/esp_driver_gptimer/src/gptimer_priv.h b/components/esp_driver_gptimer/src/gptimer_priv.h index 3c117af44f9d..b5d4d1c0e662 100644 --- a/components/esp_driver_gptimer/src/gptimer_priv.h +++ b/components/esp_driver_gptimer/src/gptimer_priv.h @@ -59,10 +59,6 @@ typedef struct gptimer_group_t { int group_id; portMUX_TYPE spinlock; // to protect per-group register level concurrent access gptimer_t *timers[SOC_TIMER_GROUP_TIMERS_PER_GROUP]; -#if GPTIMER_USE_RETENTION_LINK - sleep_retention_module_t sleep_retention_module; // sleep retention module - bool retention_link_created; // mark if the retention link is created -#endif } gptimer_group_t; typedef enum { diff --git a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c index 34a437159898..5b7e5879d57a 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c +++ b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c @@ -10,6 +10,8 @@ #include "freertos/task.h" #include "unity.h" #include "driver/gptimer.h" +#include "driver/gpio_etm.h" +#include "driver/gpio.h" #include "soc/soc_caps.h" #include "esp_sleep.h" #include "esp_private/sleep_cpu.h" @@ -117,3 +119,135 @@ TEST_CASE("gptimer can work after light sleep", "[gptimer]") test_gptimer_sleep_retention(true); #endif } + +#if SOC_TIMER_SUPPORT_ETM +/** + * @brief Test the GPTimer and ETM subsystem can still work after light sleep + * + * @param back_up_before_sleep Whether to back up GPTimer registers before sleep + */ +static void test_gptimer_etm_sleep_retention(bool back_up_before_sleep) +{ + const uint32_t output_gpio = 1; + // GPTimer alarm ---> ETM channel A ---> GPTimer alarm re-enable + // GPTimer alarm ---> ETM channel B ---> GPIO toggle + printf("allocate etm channel\r\n"); + esp_etm_channel_config_t etm_config = { + .flags.allow_pd = back_up_before_sleep, + }; + esp_etm_channel_handle_t etm_channel_a, etm_channel_b; + TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_a)); + TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_b)); + + printf("initialize gpio\r\n"); + gpio_config_t task_gpio_config = { + .intr_type = GPIO_INTR_DISABLE, + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1ULL << output_gpio, + }; + TEST_ESP_OK(gpio_config(&task_gpio_config)); + + printf("create a gptimer\r\n"); + gptimer_handle_t gptimer = NULL; + gptimer_config_t timer_config = { + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us + .flags.backup_before_sleep = back_up_before_sleep, + }; + TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimer)); + + printf("get gptimer etm event and task handle\r\n"); + esp_etm_event_handle_t gptimer_event = NULL; + gptimer_etm_event_config_t gptimer_etm_event_conf = { + .event_type = GPTIMER_ETM_EVENT_ALARM_MATCH, + }; + TEST_ESP_OK(gptimer_new_etm_event(gptimer, &gptimer_etm_event_conf, &gptimer_event)); + esp_etm_task_handle_t gptimer_task = NULL; + gptimer_etm_task_config_t gptimer_etm_task_conf = { + .task_type = GPTIMER_ETM_TASK_EN_ALARM, + }; + TEST_ESP_OK(gptimer_new_etm_task(gptimer, &gptimer_etm_task_conf, & gptimer_task)); + + printf("connect event and task to the channel a\r\n"); + TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, gptimer_event, gptimer_task)); + + printf("enable etm channels\r\n"); + TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a)); + TEST_ESP_OK(esp_etm_channel_enable(etm_channel_b)); + + printf("set timer alarm action\r\n"); + gptimer_alarm_config_t alarm_config = { + .reload_count = 0, + .alarm_count = 100, // 100us per alarm event + .flags.auto_reload_on_alarm = true, + }; + TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config)); + + // before going to sleep, ensure the gptimer is not enabled yet, otherwise it will acquire power management lock + + 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 GPTimer and ETM 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_RMT_SUPPORT_SLEEP_RETENTION + // check if the power domain also is powered down + TEST_ASSERT_EQUAL(back_up_before_sleep ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); +#endif + esp_sleep_set_sleep_context(NULL); + + printf("enable and start timer\r\n"); + TEST_ESP_OK(gptimer_enable(gptimer)); + TEST_ESP_OK(gptimer_start(gptimer)); + + printf("allocate GPIO etm task\r\n"); + esp_etm_task_handle_t gpio_task = NULL; + gpio_etm_task_config_t gpio_task_config = { + .action = GPIO_ETM_TASK_ACTION_TOG, + }; + TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config, &gpio_task)); + // set gpio number for the gpio etm primitives + TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task, output_gpio)); + printf("connect event and task to the channel b\r\n"); + TEST_ESP_OK(esp_etm_channel_connect(etm_channel_b, gptimer_event, gpio_task)); + + // delay sometime for us to view the waveform, should see a 5KHz square waveform + vTaskDelay(pdMS_TO_TICKS(1000)); + + // delete gptimer + TEST_ESP_OK(gptimer_stop(gptimer)); + TEST_ESP_OK(gptimer_disable(gptimer)); + TEST_ESP_OK(gptimer_del_timer(gptimer)); + + // delete etm primitives + TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio)); + TEST_ESP_OK(esp_etm_del_task(gpio_task)); + TEST_ESP_OK(esp_etm_del_task(gptimer_task)); + TEST_ESP_OK(esp_etm_del_event(gptimer_event)); + TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a)); + TEST_ESP_OK(esp_etm_channel_disable(etm_channel_b)); + TEST_ESP_OK(esp_etm_del_channel(etm_channel_a)); + TEST_ESP_OK(esp_etm_del_channel(etm_channel_b)); +} + +TEST_CASE("gptimer and ETM can work after light sleep", "[gptimer]") +{ + test_gptimer_etm_sleep_retention(false); +#if SOC_TIMER_SUPPORT_SLEEP_RETENTION && SOC_ETM_SUPPORT_SLEEP_RETENTION + test_gptimer_etm_sleep_retention(true); +#endif +} + +#endif // SOC_TIMER_SUPPORT_ETM diff --git a/components/esp_driver_i2c/i2c_common.c b/components/esp_driver_i2c/i2c_common.c index 87bad063b03e..87042b404ae4 100644 --- a/components/esp_driver_i2c/i2c_common.c +++ b/components/esp_driver_i2c/i2c_common.c @@ -33,7 +33,7 @@ #include "soc/rtc_io_channel.h" #include "driver/lp_io.h" #endif -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP +#if I2C_USE_RETENTION_LINK #include "esp_private/sleep_retention.h" #endif @@ -47,15 +47,31 @@ typedef struct i2c_platform_t { static i2c_platform_t s_i2c_platform = {}; // singleton platform -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_I2C_SUPPORT_SLEEP_RETENTION +#if I2C_USE_RETENTION_LINK static esp_err_t s_i2c_sleep_retention_init(void *arg) { i2c_bus_t *bus = (i2c_bus_t *)arg; i2c_port_num_t port_num = bus->port_num; - esp_err_t ret = sleep_retention_entries_create(i2c_regs_retention[port_num].link_list, i2c_regs_retention[port_num].link_num, REGDMA_LINK_PRI_I2C, I2C_SLEEP_RETENTION_MODULE(port_num)); + esp_err_t ret = sleep_retention_entries_create(i2c_regs_retention[port_num].link_list, i2c_regs_retention[port_num].link_num, REGDMA_LINK_PRI_I2C, i2c_regs_retention[port_num].module_id); ESP_RETURN_ON_ERROR(ret, TAG, "failed to allocate mem for sleep retention"); return ret; } + +void i2c_create_retention_module(i2c_bus_handle_t handle) +{ + i2c_port_num_t port_num = handle->port_num; + _lock_acquire(&s_i2c_platform.mutex); + if (handle->retention_link_created == false) { + if (sleep_retention_module_allocate(i2c_regs_retention[port_num].module_id) != ESP_OK) { + // even though the sleep retention module create failed, I2C driver should still work, so just warning here + ESP_LOGW(TAG, "create retention module failed, power domain can't turn off"); + } else { + handle->retention_link_created = true; + } + } + _lock_release(&s_i2c_platform.mutex); + +} #endif static esp_err_t s_i2c_bus_handle_acquire(i2c_port_num_t port_num, i2c_bus_handle_t *i2c_new_bus, i2c_bus_mode_t mode) @@ -77,14 +93,14 @@ static esp_err_t s_i2c_bus_handle_acquire(i2c_port_num_t port_num, i2c_bus_handl bus->bus_mode = mode; bus->is_lp_i2c = (bus->port_num < SOC_HP_I2C_NUM) ? false : true; -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_I2C_SUPPORT_SLEEP_RETENTION +#if I2C_USE_RETENTION_LINK if (bus->is_lp_i2c == false) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = s_i2c_sleep_retention_init, .arg = (void *)bus } } }; - ret = sleep_retention_module_init(I2C_SLEEP_RETENTION_MODULE(port_num), &init_param); - if (ret == ESP_OK) { - sleep_retention_module_allocate(I2C_SLEEP_RETENTION_MODULE(port_num)); + esp_err_t err = sleep_retention_module_init(i2c_regs_retention[port_num].module_id, &init_param); + if (err != ESP_OK) { + ESP_LOGW(TAG, "init sleep retention failed on bus %d, power domain may be turned off during sleep", port_num); } } else { ESP_LOGW(TAG, "Detected PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP is enabled while LP_I2C is used. Sleep retention is not supported on LP I2C. Please use it properly"); @@ -175,12 +191,12 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus) if (s_i2c_platform.count[port_num] == 0) { do_deinitialize = true; s_i2c_platform.buses[port_num] = NULL; -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_I2C_SUPPORT_SLEEP_RETENTION +#if I2C_USE_RETENTION_LINK if (i2c_bus->is_lp_i2c == false) { - esp_err_t err = sleep_retention_module_free(I2C_SLEEP_RETENTION_MODULE(port_num)); - if (err == ESP_OK) { - err = sleep_retention_module_deinit(I2C_SLEEP_RETENTION_MODULE(port_num)); + if (i2c_bus->retention_link_created) { + sleep_retention_module_free(i2c_regs_retention[port_num].module_id); } + sleep_retention_module_deinit(i2c_regs_retention[port_num].module_id); } #endif if (i2c_bus->intr_handle) { @@ -296,29 +312,27 @@ 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"); - ESP_RETURN_ON_ERROR(gpio_config(&sda_conf), TAG, "config GPIO 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); + } 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"); - ESP_RETURN_ON_ERROR(gpio_config(&scl_conf), TAG, "config GPIO 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); + } 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); @@ -390,3 +404,28 @@ 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; +} diff --git a/components/esp_driver_i2c/i2c_master.c b/components/esp_driver_i2c/i2c_master.c index ad18d2806d35..5b1ef7c7237d 100644 --- a/components/esp_driver_i2c/i2c_master.c +++ b/components/esp_driver_i2c/i2c_master.c @@ -784,6 +784,7 @@ 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) { @@ -932,6 +933,10 @@ esp_err_t i2c_new_master_bus(const i2c_master_bus_config_t *bus_config, i2c_mast ESP_RETURN_ON_FALSE((bus_config->i2c_port < SOC_I2C_NUM || bus_config->i2c_port == -1), ESP_ERR_INVALID_ARG, TAG, "invalid i2c port number"); ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(bus_config->sda_io_num) && GPIO_IS_VALID_GPIO(bus_config->scl_io_num), ESP_ERR_INVALID_ARG, TAG, "invalid SDA/SCL pin number"); +#if !SOC_I2C_SUPPORT_SLEEP_RETENTION + ESP_RETURN_ON_FALSE(bus_config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep"); +#endif // SOC_I2C_SUPPORT_SLEEP_RETENTION + i2c_master = heap_caps_calloc(1, sizeof(i2c_master_bus_t) + 20 * sizeof(i2c_transaction_t), I2C_MEM_ALLOC_CAPS); ESP_RETURN_ON_FALSE(i2c_master, ESP_ERR_NO_MEM, TAG, "no memory for i2c master bus"); @@ -980,6 +985,12 @@ esp_err_t i2c_new_master_bus(const i2c_master_bus_config_t *bus_config, i2c_mast ESP_RETURN_ON_FALSE(1 << (bus_config->intr_priority) & I2C_ALLOW_INTR_PRIORITY_MASK, ESP_ERR_INVALID_ARG, TAG, "invalid interrupt priority:%d", bus_config->intr_priority); } +#if I2C_USE_RETENTION_LINK + if (bus_config->flags.allow_pd != 0) { + i2c_create_retention_module(i2c_master->base); + } +#endif // I2C_USE_RETENTION_LINK + xSemaphoreTake(i2c_master->bus_lock_mux, portMAX_DELAY); SLIST_INIT(&i2c_master->device_list); xSemaphoreGive(i2c_master->bus_lock_mux); diff --git a/components/esp_driver_i2c/i2c_private.h b/components/esp_driver_i2c/i2c_private.h index a78dfdd06743..b5be2a800bf0 100644 --- a/components/esp_driver_i2c/i2c_private.h +++ b/components/esp_driver_i2c/i2c_private.h @@ -54,6 +54,9 @@ extern "C" { #define I2C_INTR_ALLOC_FLAG (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED) #endif +// Use retention link only when the target supports sleep retention and PM is enabled +#define I2C_USE_RETENTION_LINK (SOC_I2C_SUPPORT_SLEEP_RETENTION && CONFIG_PM_ENABLE && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + #define I2C_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED #define I2C_PM_LOCK_NAME_LEN_MAX 16 @@ -119,6 +122,9 @@ struct i2c_bus_t { char pm_lock_name[I2C_PM_LOCK_NAME_LEN_MAX]; // pm lock name #endif i2c_bus_mode_t bus_mode; // I2C bus mode +#if SOC_I2C_SUPPORT_SLEEP_RETENTION + bool retention_link_created; // mark if the retention link is created. +#endif }; typedef struct i2c_master_device_list { @@ -252,6 +258,17 @@ 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 * @@ -260,6 +277,13 @@ esp_err_t i2c_common_set_pins(i2c_bus_handle_t handle); */ bool i2c_bus_occupied(i2c_port_num_t port_num); +/** + * @brief Create sleep retention link + * + * @param handle I2C bus handle + */ +void i2c_create_retention_module(i2c_bus_handle_t handle); + #ifdef __cplusplus } #endif diff --git a/components/esp_driver_i2c/i2c_slave.c b/components/esp_driver_i2c/i2c_slave.c index 6b000ef66ede..b5f16fb9fc03 100644 --- a/components/esp_driver_i2c/i2c_slave.c +++ b/components/esp_driver_i2c/i2c_slave.c @@ -235,6 +235,12 @@ esp_err_t i2c_new_slave_device(const i2c_slave_config_t *slave_config, i2c_slave ret = esp_intr_alloc_intrstatus(i2c_periph_signal[i2c_port_num].irq, isr_flags, (uint32_t)i2c_ll_get_interrupt_status_reg(hal->dev), I2C_LL_SLAVE_EVENT_INTR, s_slave_isr_handle_default, i2c_slave, &i2c_slave->base->intr_handle); ESP_GOTO_ON_ERROR(ret, err, TAG, "install i2c slave interrupt failed"); +#if I2C_USE_RETENTION_LINK + if (slave_config->flags.allow_pd != 0) { + i2c_create_retention_module(i2c_slave->base); + } +#endif // I2C_USE_RETENTION_LINK + portENTER_CRITICAL(&i2c_slave->base->spinlock); i2c_ll_clear_intr_mask(hal->dev, I2C_LL_SLAVE_EVENT_INTR); i2c_hal_slave_init(hal); @@ -288,6 +294,7 @@ 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; diff --git a/components/esp_driver_i2c/include/driver/i2c_master.h b/components/esp_driver_i2c/include/driver/i2c_master.h index a7b1a0d4c725..8518a45d0cd4 100644 --- a/components/esp_driver_i2c/include/driver/i2c_master.h +++ b/components/esp_driver_i2c/include/driver/i2c_master.h @@ -33,6 +33,9 @@ typedef struct { size_t trans_queue_depth; /*!< Depth of internal transfer queue, increase this value can support more transfers pending in the background, only valid in asynchronous transaction. (Typically max_device_num * per_transaction)*/ struct { uint32_t enable_internal_pullup: 1; /*!< Enable internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. Recommend proper external pull-up if possible */ + uint32_t allow_pd: 1; /*!< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode. + By this approach, the system can power off I2C's power domain. + This can save power, but at the expense of more RAM being consumed */ } flags; /*!< I2C master config flags */ } i2c_master_bus_config_t; @@ -257,6 +260,22 @@ 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 diff --git a/components/esp_driver_i2c/include/driver/i2c_slave.h b/components/esp_driver_i2c/include/driver/i2c_slave.h index 897b9899ed03..5a443a174c9a 100644 --- a/components/esp_driver_i2c/include/driver/i2c_slave.h +++ b/components/esp_driver_i2c/include/driver/i2c_slave.h @@ -40,6 +40,9 @@ typedef struct { #if SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH uint32_t slave_unmatch_en: 1; /*!< Can trigger unmatch interrupt when slave address does not match what master sends*/ #endif + uint32_t allow_pd: 1; /*!< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode. + By this approach, the system can power off I2C's power domain. + This can save power, but at the expense of more RAM being consumed */ } flags; /*!< I2C slave config flags */ } i2c_slave_config_t; diff --git a/components/esp_driver_i2c/include/esp_private/i2c_platform.h b/components/esp_driver_i2c/include/esp_private/i2c_platform.h index f18cf53c99c0..3b8bee7b252b 100644 --- a/components/esp_driver_i2c/include/esp_private/i2c_platform.h +++ b/components/esp_driver_i2c/include/esp_private/i2c_platform.h @@ -15,21 +15,7 @@ extern "C" { #endif -/** - * @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); +// Empty file in order not cause breaking change. Should be removed in next version. #ifdef __cplusplus } diff --git a/components/esp_driver_i2c/test_apps/.build-test-rules.yml b/components/esp_driver_i2c/test_apps/.build-test-rules.yml index b363f05a9910..5436c0467eaf 100644 --- a/components/esp_driver_i2c/test_apps/.build-test-rules.yml +++ b/components/esp_driver_i2c/test_apps/.build-test-rules.yml @@ -5,8 +5,3 @@ components/esp_driver_i2c/test_apps/i2c_test_apps: - if: SOC_I2C_SUPPORTED != 1 depends_components: - esp_driver_i2c - # Following dependency is needed because they might increase lazy installed memory - # that can cause sleep retention memory leak check failed. - - components/ieee802154/** - - components/esp_coex/** - - components/esp_phy/** diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/CMakeLists.txt b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/CMakeLists.txt index 2f653da9aeb1..564a14d2d1f4 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/CMakeLists.txt +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/CMakeLists.txt @@ -25,13 +25,10 @@ if(CONFIG_SOC_LP_I2C_SUPPORTED) list(APPEND srcs "test_lp_i2c.c") endif() -# Only build this file with `CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP` and `CONFIG_IEEE802154_ENABLED` enabled -# Enable `CONFIG_IEEE802154_ENABLED` is for modem domain really power down. -# This reliable can be removed if the sleep retention got finished. -if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP AND CONFIG_IEEE802154_ENABLED) +if(CONFIG_SOC_I2C_SUPPORT_SLEEP_RETENTION) list(APPEND srcs "test_i2c_sleep_retention.c") endif() idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity driver test_utils ieee802154 + PRIV_REQUIRES unity driver test_utils WHOLE_ARCHIVE) diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c index 91296a6eedd5..55d7064b86f8 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c @@ -19,7 +19,6 @@ #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" diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_sleep_retention.c b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_sleep_retention.c index 8f1ca39d8e8b..845791cfed72 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_sleep_retention.c +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_sleep_retention.c @@ -43,6 +43,7 @@ static void i2c_master_write_sleep_retention_test(void) .scl_io_num = I2C_MASTER_SCL_IO, .sda_io_num = I2C_MASTER_SDA_IO, .flags.enable_internal_pullup = true, + .flags.allow_pd = true, }; i2c_master_bus_handle_t bus_handle; @@ -68,7 +69,9 @@ static void i2c_master_write_sleep_retention_test(void) TEST_ESP_OK(i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1)); unity_wait_for_signal("i2c slave receive once, master to sleep"); +#if ESP_SLEEP_POWER_DOWN_CPU TEST_ESP_OK(sleep_cpu_configure(true)); +#endif TEST_ESP_OK(esp_sleep_enable_timer_wakeup(3 * 1000 * 1000)); TEST_ESP_OK(esp_light_sleep_start()); @@ -84,7 +87,9 @@ static void i2c_master_write_sleep_retention_test(void) unity_send_signal("master write again"); unity_wait_for_signal("ready to delete"); +#if ESP_SLEEP_POWER_DOWN_CPU TEST_ESP_OK(sleep_cpu_configure(false)); +#endif TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle)); TEST_ESP_OK(i2c_del_master_bus(bus_handle)); @@ -103,6 +108,7 @@ static void i2c_slave_read_sleep_retention_test(void) .scl_io_num = I2C_SLAVE_SCL_IO, .sda_io_num = I2C_SLAVE_SDA_IO, .slave_addr = 0x58, + .flags.allow_pd = true, }; i2c_slave_dev_handle_t slave_handle; @@ -128,7 +134,9 @@ static void i2c_slave_read_sleep_retention_test(void) unity_send_signal("i2c slave receive once, master to sleep"); // Slave sleep as well.. +#if ESP_SLEEP_POWER_DOWN_CPU TEST_ESP_OK(sleep_cpu_configure(true)); +#endif TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000)); TEST_ESP_OK(esp_light_sleep_start()); @@ -147,7 +155,9 @@ static void i2c_slave_read_sleep_retention_test(void) vQueueDelete(s_receive_queue); unity_send_signal("ready to delete"); +#if ESP_SLEEP_POWER_DOWN_CPU TEST_ESP_OK(sleep_cpu_configure(false)); +#endif TEST_ESP_OK(i2c_del_slave_device(slave_handle)); } diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py b/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py index 56a8eb0bf898..4683913b5c04 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py @@ -31,6 +31,8 @@ def test_i2c(dut: Dut) -> None: 'count, config', [ (2, 'defaults',), + (2, 'release',), + (2, 'iram_safe',), ], indirect=True ) @@ -38,19 +40,3 @@ def test_i2c_multi_device(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) - - -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.generic_multi_device -@pytest.mark.parametrize( - 'count, config', - [ - (2, 'sleep_retention',), - ], - indirect=True -) -def test_i2c_sleep_retention(case_tester) -> None: # type: ignore - for case in case_tester.test_menu: - if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': - case_tester.run_multi_dev_case(case=case, reset=True, timeout=250) diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.iram_safe b/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.iram_safe index 3d8248686352..05c3f1a8d133 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.iram_safe +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.iram_safe @@ -2,5 +2,6 @@ CONFIG_PM_ENABLE=y CONFIG_COMPILER_DUMP_RTL_FILES=y CONFIG_FREERTOS_USE_TICKLESS_IDLE=y CONFIG_COMPILER_OPTIMIZATION_NONE=y +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y CONFIG_I2C_ISR_IRAM_SAFE=y diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.release b/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.release index 91d93f163e62..eb643d4d06bc 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.release +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.release @@ -1,4 +1,5 @@ CONFIG_PM_ENABLE=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y CONFIG_FREERTOS_USE_TICKLESS_IDLE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y diff --git a/components/esp_driver_i2s/CMakeLists.txt b/components/esp_driver_i2s/CMakeLists.txt index cc39943ae665..2498fa6126a5 100644 --- a/components/esp_driver_i2s/CMakeLists.txt +++ b/components/esp_driver_i2s/CMakeLists.txt @@ -30,6 +30,10 @@ if(CONFIG_SOC_LP_I2S_SUPPORTED) list(APPEND srcs "lp_i2s.c" "lp_i2s_std.c" "lp_i2s_pdm.c") endif() +if(CONFIG_SOC_LP_I2S_SUPPORT_VAD) + list(APPEND srcs "lp_i2s_vad.c") +endif() + idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${include} PRIV_REQUIRES esp_driver_gpio esp_pm esp_mm diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index 8659694466cc..06f4449d2507 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -41,6 +41,9 @@ #include "esp_private/i2s_platform.h" #include "esp_private/esp_clk.h" +#if SOC_I2S_SUPPORT_SLEEP_RETENTION +#include "esp_private/sleep_retention.h" +#endif #include "driver/gpio.h" #include "esp_private/gpio.h" @@ -85,6 +88,34 @@ inline void *i2s_dma_calloc(i2s_chan_handle_t handle, size_t num, size_t size) Scope: This file only ----------------------------------------------------------------------------*/ +#if I2S_USE_RETENTION_LINK +static esp_err_t s_i2s_create_sleep_retention_link_cb(void *arg) +{ + i2s_controller_t *i2s_obj = (i2s_controller_t *)arg; + ESP_RETURN_ON_ERROR(sleep_retention_entries_create(i2s_reg_retention_info[i2s_obj->id].entry_array, + i2s_reg_retention_info[i2s_obj->id].array_size, + REGDMA_LINK_PRI_I2S, i2s_obj->slp_retention_mod), + TAG, "create retention link failed"); + return ESP_OK; +} + +static void s_i2s_create_retention_module(i2s_controller_t *i2s_obj) +{ + sleep_retention_module_t module = i2s_obj->slp_retention_mod; + + _lock_acquire(&i2s_obj->mutex); + if (i2s_obj->retention_link_created == false) { + if (sleep_retention_module_allocate(module) != ESP_OK) { + // even though the sleep retention module create failed, I2S driver should still work, so just warning here + ESP_LOGW(TAG, "create retention module failed, power domain can't turn off"); + } else { + i2s_obj->retention_link_created = true; + } + } + _lock_release(&i2s_obj->mutex); +} +#endif // I2S_USE_RETENTION_LINK + static void i2s_tx_channel_start(i2s_chan_handle_t handle) { i2s_hal_tx_reset(&(handle->controller->hal)); @@ -175,6 +206,14 @@ static esp_err_t i2s_destroy_controller_obj(i2s_controller_t **i2s_obj) #if SOC_I2S_HW_VERSION_1 i2s_ll_enable_dma((*i2s_obj)->hal.dev, false); #endif +#if I2S_USE_RETENTION_LINK + if ((*i2s_obj)->slp_retention_mod) { + if ((*i2s_obj)->retention_link_created) { + sleep_retention_module_free((*i2s_obj)->slp_retention_mod); + } + sleep_retention_module_deinit((*i2s_obj)->slp_retention_mod); + } +#endif // I2S_USE_RETENTION_LINK free(*i2s_obj); *i2s_obj = NULL; return i2s_platform_release_occupation(I2S_CTLR_HP, id); @@ -219,6 +258,25 @@ static i2s_controller_t *i2s_acquire_controller_obj(int id) adc_ll_digi_set_data_source(0); } #endif + +#if I2S_USE_RETENTION_LINK + sleep_retention_module_t module = i2s_reg_retention_info[id].retention_module; + sleep_retention_module_init_param_t init_param = { + .cbs = { + .create = { + .handle = s_i2s_create_sleep_retention_link_cb, + .arg = i2s_obj, + }, + }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) + }; + if (sleep_retention_module_init(module, &init_param) == ESP_OK) { + i2s_obj->slp_retention_mod = module; + } else { + // even the sleep retention module init failed, I2S driver should still work, so just warning here + ESP_LOGW(TAG, "init sleep retention failed for I2S%d, power domain may be turned off during sleep", id); + } +#endif // I2S_USE_RETENTION_LINK } else { free(pre_alloc); portENTER_CRITICAL(&g_i2s.spinlock); @@ -879,6 +937,9 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * ESP_RETURN_ON_FALSE(chan_cfg->id < SOC_I2S_NUM || chan_cfg->id == I2S_NUM_AUTO, ESP_ERR_INVALID_ARG, TAG, "invalid I2S port id"); ESP_RETURN_ON_FALSE(chan_cfg->dma_desc_num >= 2, ESP_ERR_INVALID_ARG, TAG, "there should be at least 2 DMA buffers"); ESP_RETURN_ON_FALSE(chan_cfg->intr_priority >= 0 && chan_cfg->intr_priority <= 7, ESP_ERR_INVALID_ARG, TAG, "intr_priority should be within 0~7"); +#if !SOC_I2S_SUPPORT_SLEEP_RETENTION + ESP_RETURN_ON_FALSE(!chan_cfg->allow_pd, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported"); +#endif esp_err_t ret = ESP_OK; i2s_controller_t *i2s_obj = NULL; @@ -937,6 +998,11 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * if ((tx_handle != NULL) && (rx_handle != NULL)) { i2s_obj->full_duplex = true; } +#if I2S_USE_RETENTION_LINK + if (chan_cfg->allow_pd) { + s_i2s_create_retention_module(i2s_obj); + } +#endif return ESP_OK; /* i2s_obj allocated but register channel failed */ diff --git a/components/esp_driver_i2s/i2s_pdm.c b/components/esp_driver_i2s/i2s_pdm.c index 9d10058af490..86d899a933f3 100644 --- a/components/esp_driver_i2s/i2s_pdm.c +++ b/components/esp_driver_i2s/i2s_pdm.c @@ -199,11 +199,6 @@ 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 diff --git a/components/esp_driver_i2s/i2s_private.h b/components/esp_driver_i2s/i2s_private.h index 40ff52fce56f..bc2cc1f8b4c7 100644 --- a/components/esp_driver_i2s/i2s_private.h +++ b/components/esp_driver_i2s/i2s_private.h @@ -6,6 +6,7 @@ #pragma once +#include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/queue.h" @@ -25,6 +26,9 @@ #endif #include "esp_private/periph_ctrl.h" #include "esp_private/esp_gpio_reserve.h" +#if SOC_I2S_SUPPORT_SLEEP_RETENTION +#include "esp_private/sleep_retention.h" +#endif #include "esp_pm.h" #include "esp_err.h" #include "sdkconfig.h" @@ -56,6 +60,8 @@ extern "C" { #define I2S_RCC_ATOMIC() #endif +#define I2S_USE_RETENTION_LINK (SOC_I2S_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + #define I2S_NULL_POINTER_CHECK(tag, p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, tag, "input parameter '"#p"' is NULL") /** @@ -130,6 +136,11 @@ typedef struct { bool full_duplex; /*!< is full_duplex */ i2s_chan_handle_t tx_chan; /*!< tx channel handler */ i2s_chan_handle_t rx_chan; /*!< rx channel handler */ + _lock_t mutex; /*!< mutex for controller */ +#if SOC_I2S_SUPPORT_SLEEP_RETENTION + sleep_retention_module_t slp_retention_mod; /*!< Sleep retention module */ + bool retention_link_created; /*!< Whether the retention link is created */ +#endif int mclk; /*!< MCK out pin, shared by tx/rx*/ #if CONFIG_IDF_TARGET_ESP32 esp_clock_output_mapping_handle_t mclk_out_hdl; /*!< The handle of MCLK output signal */ diff --git a/components/esp_driver_i2s/i2s_std.c b/components/esp_driver_i2s/i2s_std.c index 109aaa0bc51f..564f2cd4f715 100644 --- a/components/esp_driver_i2s/i2s_std.c +++ b/components/esp_driver_i2s/i2s_std.c @@ -240,11 +240,6 @@ 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 diff --git a/components/esp_driver_i2s/i2s_tdm.c b/components/esp_driver_i2s/i2s_tdm.c index 6d579105ed57..f0dce4d55a1c 100644 --- a/components/esp_driver_i2s/i2s_tdm.c +++ b/components/esp_driver_i2s/i2s_tdm.c @@ -246,11 +246,6 @@ 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 diff --git a/components/esp_driver_i2s/include/driver/i2s_common.h b/components/esp_driver_i2s/include/driver/i2s_common.h index eaeb397a0dc7..fd7a249da309 100644 --- a/components/esp_driver_i2s/include/driver/i2s_common.h +++ b/components/esp_driver_i2s/include/driver/i2s_common.h @@ -26,6 +26,7 @@ extern "C" { .dma_frame_num = 240, \ .auto_clear_after_cb = false, \ .auto_clear_before_cb = false, \ + .allow_pd = false, \ .intr_priority = 0, \ } @@ -73,6 +74,10 @@ typedef struct { bool auto_clear_before_cb; /*!< Set to auto clear DMA TX buffer before `on_sent` callback, I2S will always send zero automatically if no data to send * So that user can access data in the callback that just finished to send. */ + bool allow_pd; /*!< Set to allow power down. When this flag set, the driver will backup/restore the I2S registers before/after entering/exist sleep mode. + * By this approach, the system can power off I2S's power domain. + * This can save power, but at the expense of more RAM being consumed. + */ int intr_priority; /*!< I2S interrupt priority, range [0, 7], if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) */ } i2s_chan_config_t; diff --git a/components/esp_driver_i2s/include/driver/lp_i2s_vad.h b/components/esp_driver_i2s/include/driver/lp_i2s_vad.h new file mode 100644 index 000000000000..ce52370cde69 --- /dev/null +++ b/components/esp_driver_i2s/include/driver/lp_i2s_vad.h @@ -0,0 +1,153 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/soc_caps.h" +#include "esp_err.h" +#include "driver/i2s_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief State Machine + ┌──────────────────────────────────┐ + │ │ + ┌─────────────┤ speak-activity-listening-state │ ◄───────────────┐ + │ │ │ │ + │ └──────────────────────────────────┘ │ + │ ▲ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ +detected speak activity │ │ detected speak activity │ detected speak activity + >= │ │ >= │ >= +'speak_activity_thresh' │ │ 'min_speak_activity_thresh' │ 'max_speak_activity_thresh' + │ │ │ + │ │ && │ + │ │ │ + │ │ detected non-speak activity │ + │ │ < │ + │ │ 'non_speak_activity_thresh' │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ ┌───────────┴─────────────────────┐ │ + │ │ │ │ + └───────────► │ speak-activity-detected-state ├─────────────────┘ + │ │ + └─┬───────────────────────────────┘ + │ + │ ▲ + │ │ + │ │ + │ │ detected speak activity + │ │ >= + │ │ 'min_speak_activity_thresh' + │ │ + │ │ && + │ │ + │ │ detected non-speak activity + │ │ < + └─────────────────────┘ 'non_speak_activity_thresh' +*/ + +/** + * @brief LP VAD peripheral + */ +typedef uint32_t lp_vad_t; + +/** + * @brief Type of VAD unit handle + */ +typedef struct vad_unit_ctx_t *vad_unit_handle_t; + +/** + * @brief LP VAD configurations + */ +typedef struct { + int init_frame_num; /**< Number of init frames that are used for VAD to denoise, this helps the VAD to decrease the accidental trigger ratio. + Note too big values may lead to voice activity miss */ + int min_energy_thresh; ///< Min energy threshold. + bool skip_band_energy_thresh; ///< Skip band energy threshold or not + + int speak_activity_thresh; /**< When in speak-activity-listening-state, if number of the detected speak activity is higher than this value, VAD runs into speak-activity-detected-state */ + + int non_speak_activity_thresh; /**< When in speak-activity-detected-state, if the number of the detected speak activity is higher than this value, but lower than `max_speak_activity_thresh`: + - if the number of the detected non-speak activity is higher than this value, VAD runs into speak-activity-listening-state + - if the number of the detected non-speak activity is lower than this value, VAD keeps in speak-activity-detected-state */ + + int min_speak_activity_thresh; /**< When in speak-activity-detected-state, if the number of the detected speak activity is higher than this value, but lower than `max_speak_activity_thresh`, + then the VAD state machine will depends on the value of `non_speak_activity_thresh` */ + + int max_speak_activity_thresh; /**< When in speak-activity-detected-state, if the number of the detected speak activity is higher than this value, VAD runs into speak-activity-listening-state */ +} lp_vad_config_t; + +typedef struct { + lp_i2s_chan_handle_t lp_i2s_chan; ///< LP I2S channel handle + lp_vad_config_t vad_config; ///< LP VAD config +} lp_vad_init_config_t; + +/** + * @brief New LP VAD unit + * @param[in] vad_id VAD id + * @param[in] init_config Initial configurations + * @param[out] ret_unit Unit handle + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_i2s_vad_new_unit(lp_vad_t vad_id, const lp_vad_init_config_t *init_config, vad_unit_handle_t *ret_unit); + +/** + * @brief Enable LP VAD + * + * @param[in] unit VAD handle + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_i2s_vad_enable(vad_unit_handle_t unit); + +/** + * @brief Disable LP VAD + * + * @param[in] unit VAD handle + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_i2s_vad_disable(vad_unit_handle_t unit); + +/** + * @brief Delete LP VAD unit + * @param[in] unit VAD handle + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_i2s_vad_del_unit(vad_unit_handle_t unit); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_i2s/include/esp_private/lp_i2s_private.h b/components/esp_driver_i2s/include/esp_private/lp_i2s_private.h new file mode 100644 index 000000000000..2785ca026336 --- /dev/null +++ b/components/esp_driver_i2s/include/esp_private/lp_i2s_private.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "hal/lp_i2s_hal.h" +#include "driver/i2s_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get LP I2S soc handle + * + * @param[in] chan LP I2S channel handle + * + * @return LP I2S soc handle + */ +lp_i2s_soc_handle_t lp_i2s_get_soc_handle(lp_i2s_chan_handle_t chan); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_i2s/lp_i2s.c b/components/esp_driver_i2s/lp_i2s.c index 7084fc8947e6..0d5e43dd8d01 100644 --- a/components/esp_driver_i2s/lp_i2s.c +++ b/components/esp_driver_i2s/lp_i2s.c @@ -25,6 +25,7 @@ #include "driver/lp_i2s.h" #include "esp_private/periph_ctrl.h" #include "esp_private/i2s_platform.h" +#include "esp_private/lp_i2s_private.h" #include "i2s_private.h" #include "soc/i2s_periph.h" @@ -329,3 +330,15 @@ static void IRAM_ATTR s_i2s_default_isr(void *arg) portYIELD_FROM_ISR(); } } + +/*--------------------------------------------------------------- + HELPERS +---------------------------------------------------------------*/ +lp_i2s_soc_handle_t lp_i2s_get_soc_handle(lp_i2s_chan_handle_t chan) +{ + if (!chan) { + return NULL; + } + + return chan->ctlr->hal.dev; +} diff --git a/components/esp_driver_i2s/lp_i2s_vad.c b/components/esp_driver_i2s/lp_i2s_vad.c new file mode 100644 index 000000000000..f1cc63559ece --- /dev/null +++ b/components/esp_driver_i2s/lp_i2s_vad.c @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "soc/soc_caps.h" +#include "stdatomic.h" +#if SOC_LP_VAD_SUPPORTED +#include "esp_check.h" +#include "esp_err.h" +#include "driver/lp_i2s_vad.h" +#include "esp_heap_caps.h" +#include "hal/lp_i2s_ll.h" +#include "hal/lp_i2s_hal.h" +#include "esp_private/lp_i2s_private.h" + +#define LP_VAD_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) + +static const char *LP_VAD_TAG = "LP_VAD"; + +typedef enum { + VAD_FSM_INIT, + VAD_FSM_ENABLE, +} vad_fsm_t; + +typedef struct vad_unit_ctx_t { + lp_i2s_soc_handle_t hw; + lp_vad_t vad_id; + vad_fsm_t fsm; +} vad_unit_ctx_t; + +static atomic_bool s_vad_id_claimed[SOC_ADC_PERIPH_NUM] = {ATOMIC_VAR_INIT(false)}; + +static bool s_vad_claim(lp_vad_t vad_id) +{ + bool false_var = false; + return atomic_compare_exchange_strong(&s_vad_id_claimed[vad_id], &false_var, true); +} + +static bool s_vad_free(lp_vad_t vad_id) +{ + bool true_var = true; + return atomic_compare_exchange_strong(&s_vad_id_claimed[vad_id], &true_var, false); +} + +esp_err_t lp_i2s_vad_new_unit(lp_vad_t vad_id, const lp_vad_init_config_t *init_config, vad_unit_handle_t *ret_unit) +{ + esp_err_t ret = ESP_OK; + ESP_RETURN_ON_FALSE(init_config, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg"); + ESP_RETURN_ON_FALSE(init_config->lp_i2s_chan, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "LP I2S not initialised"); + ESP_RETURN_ON_FALSE(init_config->vad_config.init_frame_num >= LP_VAD_LL_INIT_FRAME_MIN && init_config->vad_config.init_frame_num <= LP_VAD_LL_INIT_FRAME_MAX, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid init frame num"); + + bool success_claim = s_vad_claim(vad_id); + ESP_RETURN_ON_FALSE(success_claim, ESP_ERR_NOT_FOUND, LP_VAD_TAG, "vad%"PRId32" is already in use", vad_id); + + vad_unit_ctx_t *unit = heap_caps_calloc(1, sizeof(vad_unit_ctx_t), LP_VAD_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, LP_VAD_TAG, "no mem for unit"); + + unit->hw = lp_i2s_get_soc_handle(init_config->lp_i2s_chan); + ESP_LOGD(LP_VAD_TAG, "unit->hw: %p", unit->hw); + lp_vad_ll_set_init_frame_num(unit->hw, init_config->vad_config.init_frame_num); + lp_vad_ll_set_init_min_energy(unit->hw, init_config->vad_config.min_energy_thresh); + lp_vad_ll_set_speak_activity_thresh(unit->hw, init_config->vad_config.speak_activity_thresh); + lp_vad_ll_set_non_speak_activity_thresh(unit->hw, init_config->vad_config.non_speak_activity_thresh); + lp_vad_ll_set_min_speak_activity_thresh(unit->hw, init_config->vad_config.min_speak_activity_thresh); + lp_vad_ll_set_max_speak_activity_thresh(unit->hw, init_config->vad_config.max_speak_activity_thresh); + lp_vad_ll_skip_band_energy(unit->hw, init_config->vad_config.skip_band_energy_thresh); + unit->fsm = VAD_FSM_INIT; + *ret_unit = unit; + + return ESP_OK; +err: + bool success_free = s_vad_free(vad_id); + assert(success_free); + + return ret; +} + +esp_err_t lp_i2s_vad_enable(vad_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg"); + ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_INIT, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is enabled already"); + + lp_vad_ll_enable(unit->hw, true); + unit->fsm = VAD_FSM_ENABLE; + return ESP_OK; +} + +esp_err_t lp_i2s_vad_disable(vad_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg"); + ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_ENABLE, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is not enabled yet"); + + lp_vad_ll_enable(unit->hw, false); + unit->fsm = VAD_FSM_INIT; + return ESP_OK; +} + +esp_err_t lp_i2s_vad_del_unit(vad_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg"); + ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_INIT, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is still in enabled state"); + + bool success_free = s_vad_free(unit->vad_id); + ESP_RETURN_ON_FALSE(success_free, ESP_ERR_NOT_FOUND, LP_VAD_TAG, "vad%"PRId32" isn't in use", unit->vad_id); + + free(unit); + return ESP_OK; +} +#endif /* SOC_LP_VAD_SUPPORTED */ diff --git a/components/esp_driver_i2s/test_apps/.build-test-rules.yml b/components/esp_driver_i2s/test_apps/.build-test-rules.yml index 7ba0e4b61bfd..78e2a417f166 100644 --- a/components/esp_driver_i2s/test_apps/.build-test-rules.yml +++ b/components/esp_driver_i2s/test_apps/.build-test-rules.yml @@ -3,10 +3,6 @@ components/esp_driver_i2s/test_apps/i2s: disable: - if: SOC_I2S_SUPPORTED != 1 - disable_test: - - if: IDF_TARGET == "esp32c5" - temporary: true - reason: target test failed # TODO [ESP32C5] IDF-10343 depends_components: - esp_driver_i2s - esp_driver_pcnt @@ -16,7 +12,7 @@ components/esp_driver_i2s/test_apps/i2s_multi_dev: - if: SOC_I2S_SUPPORTED != 1 - if: SOC_I2S_HW_VERSION_2 != 1 disable_test: - - if: IDF_TARGET in ["esp32p4", "esp32c5"] # TODO: [ESP32C5] IDF- 10321 + - if: IDF_TARGET in ["esp32c61"] # TODO: [ESP32C61] IDF-11442 temporary: true reason: lack of runners depends_components: diff --git a/components/esp_driver_i2s/test_apps/i2s/README.md b/components/esp_driver_i2s/test_apps/i2s/README.md index 46d16c788ce9..844e5ee973b9 100644 --- a/components/esp_driver_i2s/test_apps/i2s/README.md +++ b/components/esp_driver_i2s/test_apps/i2s/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_driver_i2s/test_apps/i2s/main/CMakeLists.txt b/components/esp_driver_i2s/test_apps/i2s/main/CMakeLists.txt index 34b5a6d39f84..d90f51c9f47e 100644 --- a/components/esp_driver_i2s/test_apps/i2s/main/CMakeLists.txt +++ b/components/esp_driver_i2s/test_apps/i2s/main/CMakeLists.txt @@ -1,11 +1,12 @@ set(srcs "test_app_main.c" "test_i2s.c" - "test_i2s_iram.c") + "test_i2s_iram.c" + "test_i2s_sleep.c") if(CONFIG_SOC_I2S_SUPPORTS_ETM AND CONFIG_SOC_GPIO_SUPPORT_ETM) set(srcs ${srcs} "test_i2s_etm.c") endif() idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity esp_driver_pcnt spi_flash esp_driver_gpio esp_driver_i2s + PRIV_REQUIRES unity esp_driver_pcnt spi_flash esp_driver_gpio esp_driver_i2s esp_driver_uart WHOLE_ARCHIVE) diff --git a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c index bf1172c3c78e..43b2c705266b 100644 --- a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c +++ b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c @@ -94,7 +94,7 @@ static void i2s_test_io_config(int mode) } } -static void i2s_read_write_test(i2s_chan_handle_t tx_chan, i2s_chan_handle_t rx_chan) +void i2s_read_write_test(i2s_chan_handle_t tx_chan, i2s_chan_handle_t rx_chan) { #define I2S_SEND_BUF_LEN 100 #define I2S_RECV_BUF_LEN 10000 @@ -776,7 +776,7 @@ static void i2s_test_common_sample_rate(i2s_chan_handle_t rx_chan, i2s_std_clk_c printf("[%"PRIu32" Hz] %d pulses, expected %d, err %d\n", test_freq[i], real_pulse, expt_pulse, real_pulse - expt_pulse); TEST_ESP_OK(i2s_channel_disable(rx_chan)); // Check if the error between real pulse number and expected pulse number is within 1% - TEST_ASSERT_INT_WITHIN(expt_pulse * 0.01, expt_pulse, real_pulse); + TEST_ASSERT_INT_WITHIN(expt_pulse * 0.02, expt_pulse, real_pulse); } TEST_ESP_OK(pcnt_del_channel(pcnt_chan)); TEST_ESP_OK(pcnt_unit_stop(pcnt_unit)); diff --git a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c new file mode 100644 index 000000000000..6b5b944f3114 --- /dev/null +++ b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c @@ -0,0 +1,145 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity.h" +#include "unity_test_utils.h" +#include "driver/i2s_std.h" +#include "driver/uart.h" +#include "soc/i2s_struct.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 "../../test_inc/test_i2s.h" + +#define TEST_I2S_PD_SLEEP (SOC_I2S_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + +extern void i2s_read_write_test(i2s_chan_handle_t tx_chan, i2s_chan_handle_t rx_chan); + +static void s_test_i2s_enter_light_sleep(int sec, bool allow_power_down) +{ + esp_sleep_context_t sleep_ctx; + esp_sleep_set_sleep_context(&sleep_ctx); + printf("Entering light sleep for %d seconds\n", sec); +#if ESP_SLEEP_POWER_DOWN_CPU + printf("Enable CPU power down\n"); + TEST_ESP_OK(sleep_cpu_configure(true)); +#endif + uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(sec * 1000 * 1000)); + TEST_ESP_OK(esp_light_sleep_start()); + +#if ESP_SLEEP_POWER_DOWN_CPU + TEST_ESP_OK(sleep_cpu_configure(false)); +#endif + printf("Woke up from light sleep\n"); + + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); +#if SOC_I2S_SUPPORT_SLEEP_RETENTION + // check if the power domain also is powered down + TEST_ASSERT_EQUAL(allow_power_down ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); +#endif + esp_sleep_set_sleep_context(NULL); +} + +static void s_test_i2s_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle, bool allow_power_down) +{ + /* Enter light sleep before I2S channel enabled and wake up after 1 second */ + s_test_i2s_enter_light_sleep(1, allow_power_down); + /* Check whether I2S can work correctly after light sleep */ + TEST_ESP_OK(i2s_channel_enable(tx_handle)); + TEST_ESP_OK(i2s_channel_enable(rx_handle)); + i2s_read_write_test(tx_handle, rx_handle); +} + +static void s_test_i2s_power_on_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle) +{ + s_test_i2s_sleep(tx_handle, rx_handle, false); +} + +#if TEST_I2S_PD_SLEEP +static void s_test_i2s_power_down_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle) +{ +#if SOC_GDMA_SUPPORT_SLEEP_RETENTION + s_test_i2s_sleep(tx_handle, rx_handle, true); +#else + /* I2S retention is depended on GDMA retention. + * Only take two registers as sample to check the I2S retention when GDMA retention has not been supported. */ + i2s_tx_conf_reg_t tx_reg_before_slp = I2S0.tx_conf; + i2s_rx_conf_reg_t rx_reg_before_slp = I2S0.rx_conf; + /* Enter light sleep before I2S channel enabled and wake up after 1 second */ + s_test_i2s_enter_light_sleep(1, true); + /* Only check whether the register values are restored if GDMA retention has not been supported */ + i2s_tx_conf_reg_t tx_reg_after_slp = I2S0.tx_conf; + i2s_rx_conf_reg_t rx_reg_after_slp = I2S0.rx_conf; + + TEST_ASSERT_EQUAL_UINT32(tx_reg_before_slp.val, tx_reg_after_slp.val); + TEST_ASSERT_EQUAL_UINT32(rx_reg_before_slp.val, rx_reg_after_slp.val); + + TEST_ESP_OK(i2s_channel_enable(tx_handle)); + TEST_ESP_OK(i2s_channel_enable(rx_handle)); + + tx_reg_before_slp.val = I2S0.tx_conf.val; + rx_reg_before_slp.val = I2S0.rx_conf.val; + /* Enter light sleep before I2S channel enabled and wake up after 1 second */ + s_test_i2s_enter_light_sleep(1, true); + /* Only check whether the register values are restored if GDMA retention has not been supported */ + tx_reg_after_slp.val = I2S0.tx_conf.val; + rx_reg_after_slp.val = I2S0.rx_conf.val; + + TEST_ASSERT_EQUAL_UINT32(tx_reg_before_slp.val, tx_reg_after_slp.val); + TEST_ASSERT_EQUAL_UINT32(rx_reg_before_slp.val, rx_reg_after_slp.val); +#endif // SOC_GDMA_SUPPORT_SLEEP_RETENTION +} +#endif // TEST_I2S_PD_SLEEP + +void test_i2s_sleep_usability(bool allow_power_down) +{ + i2s_chan_handle_t tx_handle; + i2s_chan_handle_t rx_handle; + + i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); + chan_cfg.allow_pd = allow_power_down; + i2s_std_config_t std_cfg = { + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE), + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(SAMPLE_BITS, I2S_SLOT_MODE_STEREO), + .gpio_cfg = I2S_TEST_MASTER_DEFAULT_PIN, + }; + std_cfg.gpio_cfg.din = std_cfg.gpio_cfg.dout; + TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle)); + TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &std_cfg)); + TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg)); + + if (!allow_power_down) { + s_test_i2s_power_on_sleep(tx_handle, rx_handle); + } +#if TEST_I2S_PD_SLEEP + else { + s_test_i2s_power_down_sleep(tx_handle, rx_handle); + } +#endif + + printf("I2S works as expected after light sleep\n"); + + TEST_ESP_OK(i2s_channel_disable(tx_handle)); + TEST_ESP_OK(i2s_channel_disable(rx_handle)); + TEST_ESP_OK(i2s_del_channel(tx_handle)); + TEST_ESP_OK(i2s_del_channel(rx_handle)); +} + +TEST_CASE("I2S_light_sleep_usability_test", "[i2s]") +{ + printf("\nTesting I2S power on light sleep...\n"); + test_i2s_sleep_usability(false); +#if TEST_I2S_PD_SLEEP + printf("\nTesting I2S power down light sleep...\n"); + test_i2s_sleep_usability(true); +#endif +} diff --git a/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py b/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py index eeb7eefaaf97..138769c5948c 100644 --- a/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py +++ b/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut @@ -7,11 +7,12 @@ @pytest.mark.esp32 @pytest.mark.esp32s2 @pytest.mark.esp32c3 -# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF-10343 +@pytest.mark.esp32c5 @pytest.mark.esp32c6 @pytest.mark.esp32s3 @pytest.mark.esp32h2 @pytest.mark.esp32p4 +@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/esp_driver_i2s/test_apps/i2s/sdkconfig.ci.release b/components/esp_driver_i2s/test_apps/i2s/sdkconfig.ci.release index 91d93f163e62..7c7f2a2efa64 100644 --- a/components/esp_driver_i2s/test_apps/i2s/sdkconfig.ci.release +++ b/components/esp_driver_i2s/test_apps/i2s/sdkconfig.ci.release @@ -3,3 +3,5 @@ CONFIG_FREERTOS_USE_TICKLESS_IDLE=y 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 diff --git a/components/esp_driver_i2s/test_apps/i2s/sdkconfig.defaults b/components/esp_driver_i2s/test_apps/i2s/sdkconfig.defaults index b56409727b88..0f8b7b2f540d 100644 --- a/components/esp_driver_i2s/test_apps/i2s/sdkconfig.defaults +++ b/components/esp_driver_i2s/test_apps/i2s/sdkconfig.defaults @@ -1,2 +1,4 @@ CONFIG_I2S_ENABLE_DEBUG_LOG=y CONFIG_ESP_TASK_WDT_EN=n +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/esp_driver_i2s/test_apps/i2s_multi_dev/README.md b/components/esp_driver_i2s/test_apps/i2s_multi_dev/README.md index 61d1e0279205..c91eb572ca8a 100644 --- a/components/esp_driver_i2s/test_apps/i2s_multi_dev/README.md +++ b/components/esp_driver_i2s/test_apps/i2s_multi_dev/README.md @@ -1,3 +1,3 @@ -| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | diff --git a/components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c b/components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c index 18a7092511a5..5a6d02511737 100644 --- a/components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c +++ b/components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -23,7 +23,7 @@ static const char *TAG = "i2s_multi_dev_test"; #define TEST_I2S_FRAME_SIZE (128) // Frame numbers in every writing / reading #define TEST_I2S_ARRAY_LENGTH (1024) // The loop data length for verification -#define TEST_I2S_MAX_DATA (256) // The maximum data value in the data buffer +#define TEST_I2S_MAX_DATA (128) // The maximum data value in the data buffer #define TEST_I2S_MAX_FAIL_CNT (3) // Max broken packet count #define TEST_I2S_FRAME_TIMEOUT_SEC (10.0f) // Timeout seconds of waiting for a correct frame @@ -161,6 +161,9 @@ static void test_i2s_tdm_slave(uint32_t sample_rate, i2s_data_bit_width_t bit_wi if (sample_rate >= 96000) { i2s_tdm_config.clk_cfg.bclk_div = 12; } +#if SOC_I2S_SUPPORTS_APLL + i2s_tdm_config.clk_cfg.clk_src = I2S_CLK_SRC_APLL; +#endif TEST_ESP_OK(i2s_channel_init_tdm_mode(i2s_tdm_tx_handle, &i2s_tdm_config)); TEST_ESP_OK(i2s_channel_init_tdm_mode(i2s_tdm_rx_handle, &i2s_tdm_config)); @@ -254,6 +257,8 @@ static void test_i2s_tdm_slave_48k_16bits_8slots(void) TEST_CASE_MULTIPLE_DEVICES("I2S_TDM_full_duplex_test_in_48k_16bits_8slots", "[I2S_TDM]", test_i2s_tdm_master_48k_16bits_8slots, test_i2s_tdm_slave_48k_16bits_8slots); +// The max clock source APLL on P4 is 125M which can't satisfy the following config in slave mode +#if !CONFIG_IDF_TARGET_ESP32P4 static void test_i2s_tdm_master_96k_16bits_4slots(void) { test_i2s_tdm_master(96000, I2S_DATA_BIT_WIDTH_16BIT, I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3); @@ -266,6 +271,7 @@ static void test_i2s_tdm_slave_96k_16bits_4slots(void) TEST_CASE_MULTIPLE_DEVICES("I2S_TDM_full_duplex_test_in_96k_16bits_4slots", "[I2S_TDM]", test_i2s_tdm_master_96k_16bits_4slots, test_i2s_tdm_slave_96k_16bits_4slots); +#endif // !CONFIG_IDF_TARGET_ESP32P4 #endif // !CONFIG_IDF_TARGET_ESP32H2 static void test_i2s_external_clk_src(bool is_master, bool is_external) diff --git a/components/esp_driver_i2s/test_apps/i2s_multi_dev/pytest_i2s_multi_dev.py b/components/esp_driver_i2s/test_apps/i2s_multi_dev/pytest_i2s_multi_dev.py index 3d53063d50e5..000bb65e3997 100644 --- a/components/esp_driver_i2s/test_apps/i2s_multi_dev/pytest_i2s_multi_dev.py +++ b/components/esp_driver_i2s/test_apps/i2s_multi_dev/pytest_i2s_multi_dev.py @@ -5,9 +5,10 @@ @pytest.mark.esp32s3 @pytest.mark.esp32c3 -# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF- 10321 +@pytest.mark.esp32c5 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic_multi_device @pytest.mark.parametrize('count', [ 2, diff --git a/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults b/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults index 5e9f8e25bd87..e69de29bb2d1 100644 --- a/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults +++ b/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults @@ -1 +0,0 @@ -CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y diff --git a/components/esp_driver_i2s/test_apps/test_inc/test_i2s.h b/components/esp_driver_i2s/test_apps/test_inc/test_i2s.h index cbf25114cea6..0be715c450b3 100644 --- a/components/esp_driver_i2s/test_apps/test_inc/test_i2s.h +++ b/components/esp_driver_i2s/test_apps/test_inc/test_i2s.h @@ -22,23 +22,7 @@ extern "C" { #define SLAVE_WS_IO 22 #define DATA_IN_IO 19 #define DATA_OUT_IO 18 -#elif CONFIG_IDF_TARGET_ESP32S2 -#define MASTER_MCK_IO 0 -#define MASTER_BCK_IO 4 -#define MASTER_WS_IO 5 -#define SLAVE_BCK_IO 14 -#define SLAVE_WS_IO 15 -#define DATA_IN_IO 19 -#define DATA_OUT_IO 18 -#elif CONFIG_IDF_TARGET_ESP32C3 -#define MASTER_MCK_IO 0 -#define MASTER_BCK_IO 4 -#define MASTER_WS_IO 5 -#define SLAVE_BCK_IO 14 -#define SLAVE_WS_IO 15 -#define DATA_IN_IO 19 -#define DATA_OUT_IO 18 -#elif CONFIG_IDF_TARGET_ESP32S3 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 #define MASTER_MCK_IO 0 #define MASTER_BCK_IO 4 #define MASTER_WS_IO 5 @@ -50,8 +34,8 @@ extern "C" { #define MASTER_MCK_IO 51 #define MASTER_BCK_IO 45 #define MASTER_WS_IO 46 -#define SLAVE_BCK_IO 22 -#define SLAVE_WS_IO 23 +#define SLAVE_BCK_IO 49 +#define SLAVE_WS_IO 50 #define DATA_IN_IO 47 #define DATA_OUT_IO 48 #elif CONFIG_IDF_TARGET_ESP32C5 diff --git a/components/esp_driver_isp/CMakeLists.txt b/components/esp_driver_isp/CMakeLists.txt index 3cffb62c4c09..ab7761edb658 100644 --- a/components/esp_driver_isp/CMakeLists.txt +++ b/components/esp_driver_isp/CMakeLists.txt @@ -34,6 +34,10 @@ if(CONFIG_SOC_ISP_COLOR_SUPPORTED) list(APPEND srcs "src/isp_color.c") endif() +if(CONFIG_SOC_ISP_LSC_SUPPORTED) + list(APPEND srcs "src/isp_lsc.c") +endif() + if(NOT ${target} STREQUAL "linux") list(APPEND requires esp_mm) endif() diff --git a/components/esp_driver_isp/include/driver/isp.h b/components/esp_driver_isp/include/driver/isp.h index 92370fb4279b..235aca350ef6 100644 --- a/components/esp_driver_isp/include/driver/isp.h +++ b/components/esp_driver_isp/include/driver/isp.h @@ -22,3 +22,4 @@ #include "driver/isp_hist.h" #include "driver/isp_sharpen.h" #include "driver/isp_color.h" +#include "driver/isp_lsc.h" diff --git a/components/esp_driver_isp/include/driver/isp_core.h b/components/esp_driver_isp/include/driver/isp_core.h index ef8307645c75..c1f61928bf19 100644 --- a/components/esp_driver_isp/include/driver/isp_core.h +++ b/components/esp_driver_isp/include/driver/isp_core.h @@ -10,6 +10,7 @@ #include #include "esp_err.h" #include "driver/isp_types.h" +#include "hal/color_types.h" #ifdef __cplusplus extern "C" { @@ -30,6 +31,7 @@ typedef struct { bool has_line_end_packet; ///< Enable line end packet uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame + color_raw_element_order_t bayer_order; ///< Bayer order int intr_priority; ///< The interrupt priority, range 0~3, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) } esp_isp_processor_cfg_t; diff --git a/components/esp_driver_isp/include/driver/isp_lsc.h b/components/esp_driver_isp/include/driver/isp_lsc.h new file mode 100644 index 000000000000..db32c74ff1ac --- /dev/null +++ b/components/esp_driver_isp/include/driver/isp_lsc.h @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/isp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LSC Gain array + */ +typedef struct { + isp_lsc_gain_t *gain_r; ///< Gain for R channel + isp_lsc_gain_t *gain_gr; ///< Gain for GR channel + isp_lsc_gain_t *gain_gb; ///< Gain for GB channel + isp_lsc_gain_t *gain_b; ///< Gain for B channel +} esp_isp_lsc_gain_array_t; + +/** + * @brief ISP LSC configurations + */ +typedef struct { + esp_isp_lsc_gain_array_t *gain_array; ///< Gain array +} esp_isp_lsc_config_t; + +/** + * @brief Helper function to allocate gain array for LSC + * + * @param[in] proc Processor handle + * @param[in] gain_array Gain array to be allocated + * @param[out] out_array_size_per_channel Array size + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_STATE Not allowed to be called under current state + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t esp_isp_lsc_allocate_gain_array(isp_proc_handle_t isp_proc, esp_isp_lsc_gain_array_t *gain_array, size_t *out_array_size_per_channel); + +/** + * @brief ISP LSC configuration + * + * @note After calling this API, LSC doesn't take into effect until `esp_isp_lsc_enable` is called + * + * @param[in] proc Processor handle + * @param[in] config LSC configurations + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_STATE Not allowed to be called under current state + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid + * - ESP_ERR_NOT_SUPPORTED Not supported + */ +esp_err_t esp_isp_lsc_configure(isp_proc_handle_t isp_proc, const esp_isp_lsc_config_t *config); + +/** + * @brief Enable ISP LSC function + * + * @param[in] proc Processor handle + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_ERR_INVALID_STATE Driver state is invalid. + */ +esp_err_t esp_isp_lsc_enable(isp_proc_handle_t isp_proc); + +/** + * @brief Disable ISP LSC function + * + * @param[in] proc Processor handle + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_ERR_INVALID_STATE Driver state is invalid. + */ +esp_err_t esp_isp_lsc_disable(isp_proc_handle_t isp_proc); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_isp/include/esp_private/isp_private.h b/components/esp_driver_isp/include/esp_private/isp_private.h index 1f96bea135c9..a0e6913ca59e 100644 --- a/components/esp_driver_isp/include/esp_private/isp_private.h +++ b/components/esp_driver_isp/include/esp_private/isp_private.h @@ -64,6 +64,7 @@ typedef struct isp_processor_t { color_space_pixel_format_t out_color_format; uint32_t h_res; uint32_t v_res; + color_raw_element_order_t bayer_order; /* sub module contexts */ isp_af_ctlr_t af_ctlr[SOC_ISP_AF_CTLR_NUMS]; isp_awb_ctlr_t awb_ctlr; @@ -73,6 +74,7 @@ typedef struct isp_processor_t { isp_fsm_t demosaic_fsm; isp_fsm_t sharpen_fsm; isp_fsm_t color_fsm; + isp_fsm_t lsc_fsm; esp_isp_evt_cbs_t cbs; void *user_data; @@ -85,7 +87,7 @@ typedef struct isp_processor_t { uint32_t ae_isr_added: 1; uint32_t awb_isr_added: 1; uint32_t sharp_isr_added: 1; - uint32_t hist_isr_added: 1; + uint32_t hist_isr_added: 1; } isr_users; } isp_processor_t; diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index f3ff71e625fe..f964aaa1ccba 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -139,6 +139,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ isp_ll_enable_line_end_packet_exist(proc->hal.hw, proc_config->has_line_end_packet); isp_ll_set_intput_data_h_pixel_num(proc->hal.hw, proc_config->h_res); isp_ll_set_intput_data_v_row_num(proc->hal.hw, proc_config->v_res); + isp_ll_set_bayer_mode(proc->hal.hw, proc_config->bayer_order); isp_ll_yuv_set_std(proc->hal.hw, proc_config->yuv_std); if (out_color_format.color_space == COLOR_SPACE_YUV) { isp_ll_yuv_set_range(proc->hal.hw, proc_config->yuv_range); @@ -148,6 +149,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ proc->out_color_format = out_color_format; proc->h_res = proc_config->h_res; proc->v_res = proc_config->v_res; + proc->bayer_order = proc_config->bayer_order; *ret_proc = proc; diff --git a/components/esp_driver_isp/src/isp_lsc.c b/components/esp_driver_isp/src/isp_lsc.c new file mode 100644 index 000000000000..d8996e290598 --- /dev/null +++ b/components/esp_driver_isp/src/isp_lsc.c @@ -0,0 +1,110 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_check.h" +#include "freertos/FreeRTOS.h" +#include "driver/isp_core.h" +#include "driver/isp_bf.h" +#include "driver/isp_lsc.h" +#include "esp_private/isp_private.h" +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" + +/*--------------------------------------------------------------- + LSC +---------------------------------------------------------------*/ +#define ISP_LSC_GET_GRIDS(res) (((res) - 1) / 2 / ISP_LL_LSC_GRID_HEIGHT + 2) + +static const char *TAG = "ISP_LSC"; + +esp_err_t esp_isp_lsc_allocate_gain_array(isp_proc_handle_t isp_proc, esp_isp_lsc_gain_array_t *gain_array, size_t *out_array_size_per_channel) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); + + int num_grids_x_max = ISP_LSC_GET_GRIDS(ISP_LL_HSIZE_MAX); + int num_grids_y_max = ISP_LSC_GET_GRIDS(ISP_LL_VSIZE_MAX); + int num_grids_x = ISP_LSC_GET_GRIDS(isp_proc->h_res); + int num_grids_y = ISP_LSC_GET_GRIDS(isp_proc->v_res); + ESP_LOGD(TAG, "num_grids_x_max: %d, num_grids_x: %d, num_grids_y_max: %d, num_grids_y: %d", num_grids_x_max, num_grids_y_max, num_grids_x, num_grids_y); + ESP_RETURN_ON_FALSE(num_grids_x <= num_grids_x_max && num_grids_y <= num_grids_y_max, ESP_ERR_INVALID_ARG, TAG, "invalid h_res or v_res"); + + gain_array->gain_r = (isp_lsc_gain_t *)heap_caps_calloc(1, num_grids_x * num_grids_y * sizeof(isp_lsc_gain_t), ISP_MEM_ALLOC_CAPS); + gain_array->gain_gr = (isp_lsc_gain_t *)heap_caps_calloc(1, num_grids_x * num_grids_y * sizeof(isp_lsc_gain_t), ISP_MEM_ALLOC_CAPS); + gain_array->gain_gb = (isp_lsc_gain_t *)heap_caps_calloc(1, num_grids_x * num_grids_y * sizeof(isp_lsc_gain_t), ISP_MEM_ALLOC_CAPS); + gain_array->gain_b = (isp_lsc_gain_t *)heap_caps_calloc(1, num_grids_x * num_grids_y * sizeof(isp_lsc_gain_t), ISP_MEM_ALLOC_CAPS); + + if (!gain_array->gain_r || !gain_array->gain_gr || !gain_array->gain_gb || !gain_array->gain_b) { + ESP_LOGE(TAG, "no enough mem for gain arrays"); + return ESP_ERR_NO_MEM; + } + ESP_LOGD(TAG, "gain_array->gain_r: %p, gain_array->gain_gr: %p, gain_array->gain_gb: %p, gain_array->gain_b: %p", gain_array->gain_r, gain_array->gain_gr, gain_array->gain_gb, gain_array->gain_b); + *out_array_size_per_channel = num_grids_x * num_grids_y; + return ESP_OK; +} + +esp_err_t esp_isp_lsc_configure(isp_proc_handle_t isp_proc, const esp_isp_lsc_config_t *config) +{ +#if CONFIG_IDF_TARGET_ESP32P4 + unsigned chip_version = efuse_hal_chip_revision(); + if (!ESP_CHIP_REV_ABOVE(chip_version, 100)) { + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "LSC is not supported on ESP32P4 chips prior than ECO2"); + } +#endif + + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + + int num_grids_x_max = ISP_LSC_GET_GRIDS(ISP_LL_HSIZE_MAX); + int num_grids_y_max = ISP_LSC_GET_GRIDS(ISP_LL_VSIZE_MAX); + int num_grids_x = ISP_LSC_GET_GRIDS(isp_proc->h_res); + int num_grids_y = ISP_LSC_GET_GRIDS(isp_proc->v_res); + ESP_LOGD(TAG, "num_grids_x_max: %d, num_grids_x: %d, num_grids_y_max: %d, num_grids_y: %d", num_grids_x_max, num_grids_y_max, num_grids_x, num_grids_y); + ESP_RETURN_ON_FALSE(num_grids_x <= num_grids_x_max && num_grids_y <= num_grids_y_max, ESP_ERR_INVALID_ARG, TAG, "invalid h_res or v_res"); + ESP_RETURN_ON_FALSE(config->gain_array->gain_r && config->gain_array->gain_gr && config->gain_array->gain_gb && config->gain_array->gain_b, ESP_ERR_INVALID_ARG, TAG, "null pointer to gain arrays"); + + isp_ll_lsc_set_xtablesize(isp_proc->hal.hw, num_grids_x); + + for (int y = 0; y < num_grids_y; y++) { + for (int x = 0; x < num_grids_x; x++) { + int i = y * num_grids_x + x; + isp_ll_lut_set_wdata_r_gr(isp_proc->hal.hw, config->gain_array->gain_r[i], config->gain_array->gain_gr[i]); + isp_ll_lut_set_cmd(isp_proc->hal.hw, true, false, i, ISP_LL_LUT_LSC); + isp_ll_lut_set_wdata_gb_b(isp_proc->hal.hw, config->gain_array->gain_gb[i], config->gain_array->gain_b[i]); + isp_ll_lut_set_cmd(isp_proc->hal.hw, true, true, i, ISP_LL_LUT_LSC); + } + } + + return ESP_OK; +} + +esp_err_t esp_isp_lsc_enable(isp_proc_handle_t isp_proc) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); + + isp_ll_lsc_clk_enable(isp_proc->hal.hw, true); + isp_ll_lsc_enable(isp_proc->hal.hw, true); + isp_proc->lsc_fsm = ISP_FSM_ENABLE; + + return ESP_OK; +} + +esp_err_t esp_isp_lsc_disable(isp_proc_handle_t isp_proc) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "lsc isn't enabled yet"); + + isp_ll_lsc_enable(isp_proc->hal.hw, false); + isp_ll_lsc_clk_enable(isp_proc->hal.hw, false); + isp_proc->lsc_fsm = ISP_FSM_INIT; + + return ESP_OK; +} diff --git a/components/esp_driver_ledc/include/driver/ledc.h b/components/esp_driver_ledc/include/driver/ledc.h index bd644e1d6811..4245ae83da02 100644 --- a/components/esp_driver_ledc/include/driver/ledc.h +++ b/components/esp_driver_ledc/include/driver/ledc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,6 +33,18 @@ 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 */ @@ -44,6 +56,7 @@ 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 */ diff --git a/components/esp_driver_ledc/src/ledc.c b/components/esp_driver_ledc/src/ledc.c index 9e9be008e2c5..b3495e3c0635 100644 --- a/components/esp_driver_ledc/src/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -25,6 +25,12 @@ #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"; @@ -58,6 +64,8 @@ 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, @@ -87,6 +95,10 @@ 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] = { @@ -118,6 +130,37 @@ 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) { @@ -240,15 +283,78 @@ 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; } @@ -316,6 +422,24 @@ 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; } } @@ -530,6 +654,8 @@ 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. @@ -563,16 +689,6 @@ 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); @@ -581,6 +697,13 @@ 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); @@ -588,6 +711,19 @@ 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: @@ -612,6 +748,20 @@ 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"); @@ -687,6 +837,10 @@ 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; @@ -732,6 +886,86 @@ 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; } diff --git a/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt b/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt index 63794907bf1a..8aeea8c40d06 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt +++ b/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt @@ -1,5 +1,10 @@ set(srcs "test_app_main.c" - "test_ledc.c") + "test_ledc.c" + "test_ledc_utils.c") + +if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED) + list(APPEND srcs "test_ledc_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 diff --git a/components/esp_driver_ledc/test_apps/ledc/main/idf_component.yml b/components/esp_driver_ledc/test_apps/ledc/main/idf_component.yml new file mode 100644 index 000000000000..f5001494e215 --- /dev/null +++ b/components/esp_driver_ledc/test_apps/ledc/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + test_utils: + path: ${IDF_PATH}/tools/unit-test-app/components/test_utils diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_app_main.c b/components/esp_driver_ledc/test_apps/ledc/main/test_app_main.c index 5beebdc5157e..dabba32336ad 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/test_app_main.c +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_app_main.c @@ -9,7 +9,8 @@ #include "esp_heap_caps.h" // Some resources are lazy allocated in LEDC driver, the threshold is left for that case -#define TEST_MEMORY_LEAK_THRESHOLD (400) +// This leak is large since LEDC driver does not provide channel delete mechanism +#define TEST_MEMORY_LEAK_THRESHOLD (500) void setUp(void) { diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c index df27ae3e19d9..fb180423eed7 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c @@ -22,54 +22,7 @@ #include "driver/ledc.h" #include "soc/ledc_struct.h" #include "esp_clk_tree.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; -} +#include "test_ledc_utils.h" static void fade_setup(void) { @@ -474,52 +427,6 @@ 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) { @@ -731,8 +638,6 @@ 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(); diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c new file mode 100644 index 000000000000..c3c57a4e0328 --- /dev/null +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c @@ -0,0 +1,159 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "test_utils.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" +#include "esp_rom_uart.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 + +#if SOC_PCNT_SUPPORTED +static const ledc_clk_src_t test_ledc_clk_in_slp[] = { + LEDC_USE_RC_FAST_CLK, +#if SOC_LEDC_SUPPORT_XTAL_CLOCK + LEDC_USE_XTAL_CLK, +#endif +}; + +static const int test_clks_num = sizeof(test_ledc_clk_in_slp) / sizeof(test_ledc_clk_in_slp[0]); + +static void ledc_output_monitor(void) +{ + setup_testbench(); + + for (int i = 0; i < test_clks_num; i++) { + unity_wait_for_signal("Go to light sleep for 3 seconds"); + vTaskDelay(500 / portTICK_PERIOD_MS); + int pulse_count = wave_count(1000); + uint32_t acceptable_delta = (test_ledc_clk_in_slp[i] == (ledc_clk_src_t)LEDC_USE_RC_FAST_CLK) ? 20 : 5; // RC_FAST as the clk src has a bigger error range is reasonable + TEST_ASSERT_UINT32_WITHIN(acceptable_delta, TEST_PWM_LOW_FREQ, pulse_count); + unity_wait_for_signal("Waked up!"); + } + + tear_testbench(); +} + +static void ledc_output_in_sleep(void) +{ + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(3 * 1000 * 1000)); + + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); + ledc_ch_config.speed_mode = LEDC_LOW_SPEED_MODE; + ledc_ch_config.sleep_mode = LEDC_SLEEP_MODE_KEEP_ALIVE; + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); + + for (int i = 0; i < test_clks_num; i++) { + ledc_timer_config_t ledc_time_config = create_default_timer_config(); + ledc_time_config.speed_mode = LEDC_LOW_SPEED_MODE; + ledc_time_config.clk_cfg = test_ledc_clk_in_slp[i]; + ledc_time_config.freq_hz = TEST_PWM_LOW_FREQ; + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + + TEST_ESP_OK(ledc_update_duty(ledc_ch_config.speed_mode, ledc_ch_config.channel)); + + unity_send_signal("Go to light sleep for 3 seconds"); + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); // wait until the signal sent + TEST_ESP_OK(esp_light_sleep_start()); + unity_send_signal("Waked up!"); + + TEST_ESP_OK(ledc_timer_pause(ledc_time_config.speed_mode, ledc_time_config.timer_num)); + ledc_time_config.deconfigure = 1; + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + } +} + +TEST_CASE_MULTIPLE_DEVICES("ledc can output during light sleep", "[ledc][test_env=generic_multi_device]", ledc_output_in_sleep, ledc_output_monitor); +#endif // SOC_PCNT_SUPPORTED diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.c b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.c new file mode 100644 index 000000000000..5fce63fddd5b --- /dev/null +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.c @@ -0,0 +1,84 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#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 diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.h b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.h new file mode 100644 index 000000000000..d3c3c7e64366 --- /dev/null +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.h @@ -0,0 +1,61 @@ +/* + * 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 +#define TEST_PWM_LOW_FREQ 200 + +#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 diff --git a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py index 0b7ae925e902..22687a67fc9e 100644 --- a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py +++ b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py @@ -32,3 +32,19 @@ def test_ledc(dut: IdfDut) -> None: ) def test_ledc_psram(dut: IdfDut) -> None: dut.run_all_single_board_cases(reset=True) + + +@pytest.mark.supported_targets +@pytest.mark.temp_skip_ci(targets=['esp32s3', 'esp32c61'], + reason='s3 multi device runner has no psram, c61 lack of runner IDF-10949') +@pytest.mark.generic_multi_device +@pytest.mark.parametrize( + 'count, config', + [ + (2, 'iram_safe',), + (2, 'release',), + ], + indirect=True +) +def test_ledc_multi_device(case_tester) -> None: # type: ignore + case_tester.run_all_multi_dev_cases(reset=True) diff --git a/components/esp_driver_ledc/test_apps/ledc/sdkconfig.ci.release b/components/esp_driver_ledc/test_apps/ledc/sdkconfig.ci.release index 91d93f163e62..17aaee1e8ece 100644 --- a/components/esp_driver_ledc/test_apps/ledc/sdkconfig.ci.release +++ b/components/esp_driver_ledc/test_apps/ledc/sdkconfig.ci.release @@ -1,5 +1,6 @@ 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 diff --git a/components/esp_driver_ledc/test_apps/ledc/sdkconfig.defaults b/components/esp_driver_ledc/test_apps/ledc/sdkconfig.defaults index 568a2ae79fc7..cbdb4160e280 100644 --- a/components/esp_driver_ledc/test_apps/ledc/sdkconfig.defaults +++ b/components/esp_driver_ledc/test_apps/ledc/sdkconfig.defaults @@ -2,3 +2,5 @@ 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 diff --git a/components/esp_driver_mcpwm/include/driver/mcpwm_cap.h b/components/esp_driver_mcpwm/include/driver/mcpwm_cap.h index 6e2808608763..601454b82a47 100644 --- a/components/esp_driver_mcpwm/include/driver/mcpwm_cap.h +++ b/components/esp_driver_mcpwm/include/driver/mcpwm_cap.h @@ -145,8 +145,7 @@ typedef struct { uint32_t pull_down: 1; /*!< Whether to pull down internally */ uint32_t invert_cap_signal: 1; /*!< Invert the input capture signal */ 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 keep_io_conf_at_exit: 1; /*!< For debug/test, whether to keep the GPIO configuration when capture channel is deleted. - By default, driver will reset the GPIO pin at exit. */ + uint32_t keep_io_conf_at_exit: 1 __attribute__((deprecated)); /*!< Deprecated. Driver won't change the GPIO configuration in deinilization. */ } flags; /*!< Extra configuration flags for capture channel */ } mcpwm_capture_channel_config_t; diff --git a/components/esp_driver_mcpwm/src/mcpwm_cap.c b/components/esp_driver_mcpwm/src/mcpwm_cap.c index 0baf6b090cbb..c80eedd68178 100644 --- a/components/esp_driver_mcpwm/src/mcpwm_cap.c +++ b/components/esp_driver_mcpwm/src/mcpwm_cap.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,9 +24,11 @@ #include "soc/soc_caps.h" #include "soc/mcpwm_periph.h" #include "hal/mcpwm_ll.h" +#include "hal/gpio_hal.h" #include "driver/mcpwm_cap.h" #include "driver/gpio.h" #include "mcpwm_private.h" +#include "esp_private/gpio.h" static const char *TAG = "mcpwm"; @@ -289,20 +291,25 @@ esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mc if (config->gpio_num >= 0) { // GPIO configuration - gpio_config_t gpio_conf = { - .intr_type = GPIO_INTR_DISABLE, - .mode = GPIO_MODE_INPUT | (config->flags.io_loop_back ? GPIO_MODE_OUTPUT : 0), // also enable the output path if `io_loop_back` is enabled - .pin_bit_mask = (1ULL << config->gpio_num), - .pull_down_en = config->flags.pull_down, - .pull_up_en = config->flags.pull_up, - }; - ESP_GOTO_ON_ERROR(gpio_config(&gpio_conf), err, TAG, "config capture GPIO failed"); + gpio_func_sel(config->gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(config->gpio_num); esp_rom_gpio_connect_in_signal(config->gpio_num, mcpwm_periph_signals.groups[group->group_id].captures[cap_chan_id].cap_sig, 0); + if (config->flags.pull_down) { + gpio_pulldown_en(config->gpio_num); + } + if (config->flags.pull_up) { + gpio_pullup_en(config->gpio_num); + } + + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_ll_output_enable(&GPIO, config->gpio_num); + } } cap_chan->gpio_num = config->gpio_num; cap_chan->fsm = MCPWM_CAP_CHAN_FSM_INIT; - cap_chan->flags.reset_io_at_exit = !config->flags.keep_io_conf_at_exit && config->gpio_num >= 0; + *ret_cap_channel = cap_chan; ESP_LOGD(TAG, "new capture channel (%d,%d) at %p", group->group_id, cap_chan_id, cap_chan); return ESP_OK; @@ -323,15 +330,16 @@ esp_err_t mcpwm_del_capture_channel(mcpwm_cap_channel_handle_t cap_channel) int cap_chan_id = cap_channel->cap_chan_id; ESP_LOGD(TAG, "del capture channel (%d,%d)", group->group_id, cap_channel->cap_chan_id); - if (cap_channel->flags.reset_io_at_exit) { - gpio_reset_pin(cap_channel->gpio_num); - } portENTER_CRITICAL(&group->spinlock); mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_chan_id), false); mcpwm_ll_intr_clear_status(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_chan_id)); portEXIT_CRITICAL(&group->spinlock); + // disconnect signal from the GPIO pin + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, + mcpwm_periph_signals.groups[group->group_id].captures[cap_chan_id].cap_sig, 0); + // recycle memory resource ESP_RETURN_ON_ERROR(mcpwm_capture_channel_destroy(cap_channel), TAG, "destroy capture channel failed"); return ESP_OK; diff --git a/components/esp_driver_mcpwm/src/mcpwm_fault.c b/components/esp_driver_mcpwm/src/mcpwm_fault.c index b2539e2048fb..d1ccde6912d8 100644 --- a/components/esp_driver_mcpwm/src/mcpwm_fault.c +++ b/components/esp_driver_mcpwm/src/mcpwm_fault.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,9 +22,11 @@ #include "soc/soc_caps.h" #include "soc/mcpwm_periph.h" #include "hal/mcpwm_ll.h" +#include "hal/gpio_hal.h" #include "driver/mcpwm_fault.h" #include "driver/gpio.h" #include "mcpwm_private.h" +#include "esp_private/gpio.h" static const char *TAG = "mcpwm"; @@ -112,16 +114,22 @@ esp_err_t mcpwm_new_gpio_fault(const mcpwm_gpio_fault_config_t *config, mcpwm_fa ESP_GOTO_ON_ERROR(mcpwm_check_intr_priority(group, config->intr_priority), err, TAG, "set group interrupt priority failed"); // GPIO configuration - gpio_config_t gpio_conf = { - .intr_type = GPIO_INTR_DISABLE, - .mode = GPIO_MODE_INPUT | (config->flags.io_loop_back ? GPIO_MODE_OUTPUT : 0), // also enable the output path if `io_loop_back` is enabled - .pin_bit_mask = (1ULL << config->gpio_num), - .pull_down_en = config->flags.pull_down, - .pull_up_en = config->flags.pull_up, - }; - ESP_GOTO_ON_ERROR(gpio_config(&gpio_conf), err, TAG, "config fault GPIO failed"); + gpio_func_sel(config->gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(config->gpio_num); esp_rom_gpio_connect_in_signal(config->gpio_num, mcpwm_periph_signals.groups[group_id].gpio_faults[fault_id].fault_sig, 0); + if (config->flags.pull_down) { + gpio_pulldown_en(config->gpio_num); + } + if (config->flags.pull_up) { + gpio_pullup_en(config->gpio_num); + } + + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_ll_output_enable(&GPIO, config->gpio_num); + } + // set fault detection polarity // different gpio faults share the same config register, using a group level spin lock portENTER_CRITICAL(&group->spinlock); @@ -151,10 +159,10 @@ static esp_err_t mcpwm_del_gpio_fault(mcpwm_fault_handle_t fault) mcpwm_gpio_fault_t *gpio_fault = __containerof(fault, mcpwm_gpio_fault_t, base); mcpwm_group_t *group = fault->group; mcpwm_hal_context_t *hal = &group->hal; + int group_id = group->group_id; int fault_id = gpio_fault->fault_id; ESP_LOGD(TAG, "del GPIO fault (%d,%d)", group->group_id, fault_id); - gpio_reset_pin(gpio_fault->gpio_num); portENTER_CRITICAL(&group->spinlock); mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_FAULT_MASK(fault_id), false); @@ -164,6 +172,10 @@ static esp_err_t mcpwm_del_gpio_fault(mcpwm_fault_handle_t fault) // disable fault detection mcpwm_ll_fault_enable_detection(hal->dev, fault_id, false); + // disconnect signal from the GPIO pin + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, + mcpwm_periph_signals.groups[group_id].gpio_faults[fault_id].fault_sig, 0); + // recycle memory resource ESP_RETURN_ON_ERROR(mcpwm_gpio_fault_destroy(gpio_fault), TAG, "destroy GPIO fault failed"); return ESP_OK; diff --git a/components/esp_driver_mcpwm/src/mcpwm_gen.c b/components/esp_driver_mcpwm/src/mcpwm_gen.c index 0851f744c617..85ca5cb8f2bd 100644 --- a/components/esp_driver_mcpwm/src/mcpwm_gen.c +++ b/components/esp_driver_mcpwm/src/mcpwm_gen.c @@ -21,10 +21,12 @@ #include "soc/soc_caps.h" #include "soc/mcpwm_periph.h" #include "hal/mcpwm_ll.h" +#include "hal/gpio_hal.h" #include "driver/gpio.h" #include "driver/mcpwm_gen.h" #include "mcpwm_private.h" #include "esp_private/esp_gpio_reserve.h" +#include "esp_private/gpio.h" static const char *TAG = "mcpwm"; @@ -84,27 +86,29 @@ esp_err_t mcpwm_new_generator(mcpwm_oper_handle_t oper, const mcpwm_generator_co // reset generator mcpwm_hal_generator_reset(hal, oper_id, gen_id); - // GPIO configuration gen->gen_gpio_num = -1; // gpio not initialized yet - gpio_config_t gpio_conf = { - .intr_type = GPIO_INTR_DISABLE, - // also enable the input path if `io_loop_back` is enabled - .mode = (config->flags.io_od_mode ? GPIO_MODE_OUTPUT_OD : GPIO_MODE_OUTPUT) | (config->flags.io_loop_back ? GPIO_MODE_INPUT : 0), - .pin_bit_mask = (1ULL << config->gen_gpio_num), - .pull_down_en = config->flags.pull_down, - .pull_up_en = config->flags.pull_up, - }; - ESP_GOTO_ON_ERROR(gpio_config(&gpio_conf), err, TAG, "config gen GPIO failed"); // reserve the GPIO output path, because we don't expect another peripheral to signal to the same GPIO uint64_t old_gpio_rsv_mask = esp_gpio_reserve(BIT64(config->gen_gpio_num)); // check if the GPIO is already used by others if (old_gpio_rsv_mask & BIT64(config->gen_gpio_num)) { ESP_LOGW(TAG, "GPIO %d is not usable, maybe conflict with others", config->gen_gpio_num); } + + // GPIO Matrix/MUX configuration + gpio_func_sel(config->gen_gpio_num, PIN_FUNC_GPIO); + // connect the signal to the GPIO by matrix, it will also enable the output path properly esp_rom_gpio_connect_out_signal(config->gen_gpio_num, mcpwm_periph_signals.groups[group->group_id].operators[oper_id].generators[gen_id].pwm_sig, config->flags.invert_pwm, 0); + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_ll_input_enable(&GPIO, config->gen_gpio_num); + } + if (config->flags.io_od_mode) { + gpio_ll_od_enable(&GPIO, config->gen_gpio_num); + } + // fill in other generator members gen->gen_gpio_num = config->gen_gpio_num; gen->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; @@ -126,9 +130,9 @@ esp_err_t mcpwm_del_generator(mcpwm_gen_handle_t gen) mcpwm_group_t *group = oper->group; ESP_LOGD(TAG, "del generator (%d,%d,%d)", group->group_id, oper->oper_id, gen->gen_id); - // reset GPIO + // disable GPIO output if (gen->gen_gpio_num >= 0) { - gpio_reset_pin(gen->gen_gpio_num); + gpio_output_disable(gen->gen_gpio_num); esp_gpio_revoke(BIT64(gen->gen_gpio_num)); } // recycle memory resource @@ -401,6 +405,10 @@ esp_err_t mcpwm_generator_set_dead_time(mcpwm_gen_handle_t in_generator, mcpwm_g mcpwm_ll_deadtime_set_falling_delay(hal->dev, oper_id, config->negedge_delay_ticks); } + if (delay_on_both_edge && in_generator->gen_id == 0 && oper->generators[1]) { + ESP_LOGW(TAG, "generator B will not function correctly. To set deadtime on both edges for one generator while bypassing the deadtime for the other, please set the deadtime for generator B only."); + } + ESP_LOGD(TAG, "operator (%d,%d) dead time (R:%"PRIu32",F:%"PRIu32"), topology code:%"PRIx32, group->group_id, oper_id, config->posedge_delay_ticks, config->negedge_delay_ticks, mcpwm_ll_deadtime_get_switch_topology(hal->dev, oper_id)); return ESP_OK; diff --git a/components/esp_driver_mcpwm/src/mcpwm_private.h b/components/esp_driver_mcpwm/src/mcpwm_private.h index cc3e2fcd4909..e299d3dd80b8 100644 --- a/components/esp_driver_mcpwm/src/mcpwm_private.h +++ b/components/esp_driver_mcpwm/src/mcpwm_private.h @@ -250,9 +250,6 @@ struct mcpwm_cap_channel_t { intr_handle_t intr; // Interrupt handle mcpwm_capture_event_cb_t on_cap; // Callback function which would be invoked in capture interrupt routine void *user_data; // user data which would be passed to the capture callback - struct { - uint32_t reset_io_at_exit: 1; // Whether to reset the GPIO configuration when capture channel is deleted - } flags; }; mcpwm_group_t *mcpwm_acquire_group_handle(int group_id); diff --git a/components/esp_driver_mcpwm/src/mcpwm_sync.c b/components/esp_driver_mcpwm/src/mcpwm_sync.c index dede456adc33..3fe84b5fb26a 100644 --- a/components/esp_driver_mcpwm/src/mcpwm_sync.c +++ b/components/esp_driver_mcpwm/src/mcpwm_sync.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,9 +22,11 @@ #include "soc/soc_caps.h" #include "soc/mcpwm_periph.h" #include "hal/mcpwm_ll.h" +#include "hal/gpio_hal.h" #include "driver/mcpwm_sync.h" #include "driver/gpio.h" #include "mcpwm_private.h" +#include "esp_private/gpio.h" static const char *TAG = "mcpwm"; @@ -192,16 +194,23 @@ esp_err_t mcpwm_new_gpio_sync_src(const mcpwm_gpio_sync_src_config_t *config, mc int sync_id = gpio_sync_src->sync_id; // GPIO configuration - gpio_config_t gpio_conf = { - .intr_type = GPIO_INTR_DISABLE, - .mode = GPIO_MODE_INPUT | (config->flags.io_loop_back ? GPIO_MODE_OUTPUT : 0), // also enable the output path if `io_loop_back` is enabled - .pin_bit_mask = (1ULL << config->gpio_num), - .pull_down_en = config->flags.pull_down, - .pull_up_en = config->flags.pull_up, - }; - ESP_GOTO_ON_ERROR(gpio_config(&gpio_conf), err, TAG, "config sync GPIO failed"); + gpio_func_sel(config->gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(config->gpio_num); + esp_rom_gpio_connect_in_signal(config->gpio_num, mcpwm_periph_signals.groups[group_id].gpio_synchros[sync_id].sync_sig, 0); + if (config->flags.pull_down) { + gpio_pulldown_en(config->gpio_num); + } + if (config->flags.pull_up) { + gpio_pullup_en(config->gpio_num); + } + + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_ll_output_enable(&GPIO, config->gpio_num); + } + // different ext sync share the same config register, using a group level spin lock portENTER_CRITICAL(&group->spinlock); mcpwm_ll_invert_gpio_sync_input(group->hal.dev, sync_id, config->flags.active_neg); @@ -226,9 +235,11 @@ static esp_err_t mcpwm_del_gpio_sync_src(mcpwm_sync_t *sync_src) { mcpwm_gpio_sync_src_t *gpio_sync_src = __containerof(sync_src, mcpwm_gpio_sync_src_t, base); mcpwm_group_t *group = sync_src->group; + int group_id = group->group_id; + int sync_id = gpio_sync_src->sync_id; ESP_LOGD(TAG, "del gpio sync_src (%d,%d)", group->group_id, gpio_sync_src->sync_id); - gpio_reset_pin(gpio_sync_src->gpio_num); + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, mcpwm_periph_signals.groups[group_id].gpio_synchros[sync_id].sync_sig, 0); // recycle memory resource ESP_RETURN_ON_ERROR(mcpwm_gpio_sync_src_destroy(gpio_sync_src), TAG, "destroy GPIO sync_src failed"); diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_cap.c b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_cap.c index 228d0648cf70..8c01654f4f8a 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_cap.c +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_cap.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -71,6 +71,14 @@ static bool test_capture_callback(mcpwm_cap_channel_handle_t cap_channel, const TEST_CASE("mcpwm_capture_ext_gpio", "[mcpwm]") { + printf("init a gpio to simulate the external capture signal\r\n"); + const int cap_gpio = TEST_CAP_GPIO; + gpio_config_t ext_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT(cap_gpio), + }; + TEST_ESP_OK(gpio_config(&ext_gpio_conf)); + printf("install mcpwm capture timer\r\n"); mcpwm_cap_timer_handle_t cap_timer = NULL; mcpwm_capture_timer_config_t cap_timer_config = { @@ -80,7 +88,6 @@ TEST_CASE("mcpwm_capture_ext_gpio", "[mcpwm]") }; TEST_ESP_OK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer)); - const int cap_gpio = TEST_CAP_GPIO; // put the GPIO into a preset state gpio_set_level(cap_gpio, 0); @@ -91,7 +98,6 @@ TEST_CASE("mcpwm_capture_ext_gpio", "[mcpwm]") .prescale = 1, .flags.pos_edge = true, .flags.neg_edge = true, - .flags.io_loop_back = true, // so we can use GPIO functions to simulate the external capture signal .flags.pull_up = true, }; TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &pps_channel)); @@ -127,6 +133,7 @@ TEST_CASE("mcpwm_capture_ext_gpio", "[mcpwm]") TEST_ESP_OK(mcpwm_del_capture_channel(pps_channel)); TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer)); TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer)); + TEST_ESP_OK(gpio_reset_pin(cap_gpio)); } typedef struct { diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_fault.c b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_fault.c index 38a852c06f87..2dc14b34d398 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_fault.c +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_fault.c @@ -58,15 +58,21 @@ static bool IRAM_ATTR test_fault_exit_callback(mcpwm_fault_handle_t detector, co TEST_CASE("mcpwm_gpio_fault_event_callbacks", "[mcpwm]") { - printf("create gpio fault\r\n"); + printf("init a gpio to simulate the fault signal\r\n"); const int fault_gpio = TEST_FAULT_GPIO; + gpio_config_t fault_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT(fault_gpio), + }; + TEST_ESP_OK(gpio_config(&fault_gpio_conf)); + + printf("create gpio fault\r\n"); mcpwm_fault_handle_t fault = NULL; mcpwm_gpio_fault_config_t gpio_fault_config = { .group_id = 0, .gpio_num = fault_gpio, .flags.active_level = true, // active on high level .flags.pull_down = true, - .flags.io_loop_back = true, // for debug, so that we can use gpio_set_level to mimic a fault source }; TEST_ESP_OK(mcpwm_new_gpio_fault(&gpio_fault_config, &fault)); @@ -80,7 +86,7 @@ TEST_CASE("mcpwm_gpio_fault_event_callbacks", "[mcpwm]") }; TaskHandle_t task_to_notify = xTaskGetCurrentTaskHandle(); TEST_ESP_OK(mcpwm_fault_register_event_callbacks(fault, &cbs, task_to_notify)); - TEST_ASSERT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000))); + TEST_ASSERT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(100))); printf("trigget a fault event\r\n"); gpio_set_level(fault_gpio, 1); @@ -91,4 +97,5 @@ TEST_CASE("mcpwm_gpio_fault_event_callbacks", "[mcpwm]") TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(10))); TEST_ESP_OK(mcpwm_del_fault(fault)); + TEST_ESP_OK(gpio_reset_pin(fault_gpio)); } diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_gen.c b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_gen.c index a00bed330905..1182f74e7df2 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_gen.c +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_gen.c @@ -7,6 +7,7 @@ #include "freertos/task.h" #include "unity.h" #include "soc/soc_caps.h" +#include "driver/mcpwm_cap.h" #include "driver/mcpwm_timer.h" #include "driver/mcpwm_oper.h" #include "driver/mcpwm_cmpr.h" @@ -15,6 +16,7 @@ #include "driver/mcpwm_sync.h" #include "driver/gpio.h" #include "test_mcpwm_utils.h" +#include "esp_clk_tree.h" TEST_CASE("mcpwm_generator_install_uninstall", "[mcpwm]") { @@ -46,6 +48,14 @@ TEST_CASE("mcpwm_generator_install_uninstall", "[mcpwm]") TEST_CASE("mcpwm_generator_force_level_hold_on", "[mcpwm]") { + const int gen_gpio = TEST_PWMA_GPIO; + printf("init a gpio to read generator output\r\n"); + gpio_config_t gen_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(gen_gpio), + }; + TEST_ESP_OK(gpio_config(&gen_gpio_conf)); + // The operator can even work without the timer printf("create operator and generator\r\n"); mcpwm_oper_handle_t oper = NULL; @@ -55,10 +65,8 @@ TEST_CASE("mcpwm_generator_force_level_hold_on", "[mcpwm]") TEST_ESP_OK(mcpwm_new_operator(&operator_config, &oper)); mcpwm_gen_handle_t generator = NULL; - const int gen_gpio = TEST_PWMA_GPIO; mcpwm_generator_config_t generator_config = { .gen_gpio_num = gen_gpio, - .flags.io_loop_back = true, // loop back for test }; TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &generator)); @@ -78,12 +86,22 @@ TEST_CASE("mcpwm_generator_force_level_hold_on", "[mcpwm]") printf("delete generator and operator\r\n"); TEST_ESP_OK(mcpwm_del_generator(generator)); TEST_ESP_OK(mcpwm_del_operator(oper)); + TEST_ESP_OK(gpio_reset_pin(gen_gpio)); } // mcpwm_generator_set_force_level acts before the dead time module // so the value output on the generator is a combined result TEST_CASE("mcpwm_force_level_and_dead_time", "[mcpwm]") { + const int gen_a_gpio = TEST_PWMA_GPIO; + const int gen_b_gpio = TEST_PWMB_GPIO; + printf("init gpios to read generator output\r\n"); + gpio_config_t gen_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(gen_a_gpio) | BIT(gen_b_gpio), + }; + TEST_ESP_OK(gpio_config(&gen_gpio_conf)); + printf("create operator and generators\r\n"); mcpwm_oper_handle_t oper = NULL; mcpwm_operator_config_t operator_config = { @@ -93,11 +111,8 @@ TEST_CASE("mcpwm_force_level_and_dead_time", "[mcpwm]") mcpwm_gen_handle_t gen_a = NULL; mcpwm_gen_handle_t gen_b = NULL; - const int gen_a_gpio = TEST_PWMA_GPIO; - const int gen_b_gpio = TEST_PWMB_GPIO; mcpwm_generator_config_t generator_config = { .gen_gpio_num = gen_a_gpio, - .flags.io_loop_back = true, // loop back for test }; TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &gen_a)); generator_config.gen_gpio_num = gen_b_gpio; @@ -128,10 +143,20 @@ TEST_CASE("mcpwm_force_level_and_dead_time", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(gen_a)); TEST_ESP_OK(mcpwm_del_generator(gen_b)); TEST_ESP_OK(mcpwm_del_operator(oper)); + TEST_ESP_OK(gpio_reset_pin(gen_a_gpio)); + TEST_ESP_OK(gpio_reset_pin(gen_b_gpio)); } TEST_CASE("mcpwm_generator_force_level_recovery", "[mcpwm]") { + const int gen_gpio = TEST_PWMA_GPIO; + printf("init a gpio to read generator output\r\n"); + gpio_config_t gen_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(gen_gpio), + }; + TEST_ESP_OK(gpio_config(&gen_gpio_conf)); + printf("create mcpwm timer\r\n"); mcpwm_timer_config_t timer_config = { .group_id = 0, @@ -155,10 +180,8 @@ TEST_CASE("mcpwm_generator_force_level_recovery", "[mcpwm]") printf("create generator\r\n"); mcpwm_gen_handle_t generator = NULL; - const int gen_gpio = TEST_PWMA_GPIO; mcpwm_generator_config_t generator_config = { .gen_gpio_num = gen_gpio, - .flags.io_loop_back = true, // loop back for test }; TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &generator)); @@ -195,11 +218,19 @@ TEST_CASE("mcpwm_generator_force_level_recovery", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(generator)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(gen_gpio)); } TEST_CASE("mcpwm_generator_action_on_timer_event", "[mcpwm]") { const int generator_gpio = TEST_PWMA_GPIO; + printf("init a gpio to read generator output\r\n"); + gpio_config_t gen_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(generator_gpio), + }; + TEST_ESP_OK(gpio_config(&gen_gpio_conf)); + printf("create timer and operator\r\n"); mcpwm_timer_config_t timer_config = { .group_id = 0, @@ -224,7 +255,6 @@ TEST_CASE("mcpwm_generator_action_on_timer_event", "[mcpwm]") printf("create generator\r\n"); mcpwm_generator_config_t gen_config = { .gen_gpio_num = generator_gpio, - .flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver }; mcpwm_gen_handle_t gen = NULL; TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen)); @@ -258,12 +288,26 @@ TEST_CASE("mcpwm_generator_action_on_timer_event", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(gen)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(generator_gpio)); +} + +TEST_MCPWM_CALLBACK_ATTR +static bool test_capture_callback(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_data_t *edata, void *user_data) +{ + uint32_t *cap_value = (uint32_t *)user_data; + if (edata->cap_edge == MCPWM_CAP_EDGE_NEG) { + cap_value[1] = edata->cap_value; + } else { + cap_value[0] = edata->cap_value; + } + return false; } typedef void (*set_gen_actions_cb_t)(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb); static void mcpwm_gen_action_test_template(uint32_t timer_resolution, uint32_t period, mcpwm_timer_count_mode_t count_mode, - uint32_t cmpa, uint32_t cmpb, int gpioa, int gpiob, set_gen_actions_cb_t set_generator_actions) + uint32_t cmpa, uint32_t cmpb, int gpioa, int gpiob, set_gen_actions_cb_t set_generator_actions, + uint32_t *ret_capa, uint32_t *ret_capb) { mcpwm_timer_config_t timer_config = { .group_id = 0, @@ -305,10 +349,72 @@ static void mcpwm_gen_action_test_template(uint32_t timer_resolution, uint32_t p set_generator_actions(generator_a, generator_b, comparator_a, comparator_b); + // install mcpwm capture timer + mcpwm_cap_timer_handle_t cap_timer = NULL; + uint32_t clk_src_freq_hz; + esp_clk_tree_src_get_freq_hz(MCPWM_CAPTURE_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz); + mcpwm_capture_timer_config_t cap_timer_config = { + .clk_src = MCPWM_CAPTURE_CLK_SRC_DEFAULT, + .group_id = 0, + .resolution_hz = clk_src_freq_hz / 2, + }; + TEST_ESP_OK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer)); + + // install mcpwm capture channel + mcpwm_cap_channel_handle_t cap_channel_a; + mcpwm_cap_channel_handle_t cap_channel_b; + mcpwm_capture_channel_config_t cap_chan_config = { + .gpio_num = gpioa, + .prescale = 1, + .flags.pos_edge = true, + .flags.neg_edge = true, + }; + TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &cap_channel_a)); + cap_chan_config.gpio_num = gpiob; + TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &cap_channel_b)); + + // install callback for capture channel + mcpwm_capture_event_callbacks_t cbs = { + .on_cap = test_capture_callback, + }; + uint32_t cap_value_a[2] = {0}; + uint32_t cap_value_b[2] = {0}; + TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(cap_channel_a, &cbs, cap_value_a)); + TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(cap_channel_b, &cbs, cap_value_b)); + + // enable capture channel and timer + TEST_ESP_OK(mcpwm_capture_channel_enable(cap_channel_a)); + TEST_ESP_OK(mcpwm_capture_channel_enable(cap_channel_b)); + TEST_ESP_OK(mcpwm_capture_timer_enable(cap_timer)); + + // start timer and capture timer TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP)); + TEST_ESP_OK(mcpwm_capture_timer_start(cap_timer)); vTaskDelay(pdMS_TO_TICKS(100)); TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_STOP_EMPTY)); vTaskDelay(pdMS_TO_TICKS(10)); + TEST_ESP_OK(mcpwm_capture_timer_stop(cap_timer)); + + // calculate the actual capture time + uint32_t clk_src_res; + TEST_ESP_OK(mcpwm_capture_timer_get_resolution(cap_timer, &clk_src_res)); + clk_src_res /= 1000; // convert to kHz + + if (cap_value_a[1] > cap_value_a[0]) { + // generator end with low level, calculate the high level time + *ret_capa = (cap_value_a[1] - cap_value_a[0]) * 1000 / clk_src_res; + } else { + // generator end with high level, calculate the low level time + *ret_capa = (cap_value_a[0] - cap_value_a[1]) * 1000 / clk_src_res; + } + + if (cap_value_b[1] > cap_value_b[0]) { + // generator end with low level, calculate the high level time + *ret_capb = (cap_value_b[1] - cap_value_b[0]) * 1000 / clk_src_res; + } else { + // generator end with high level, calculate the low level time + *ret_capb = (cap_value_b[0] - cap_value_b[1]) * 1000 / clk_src_res; + } TEST_ESP_OK(mcpwm_timer_disable(timer)); TEST_ESP_OK(mcpwm_del_generator(generator_a)); @@ -317,6 +423,12 @@ static void mcpwm_gen_action_test_template(uint32_t timer_resolution, uint32_t p TEST_ESP_OK(mcpwm_del_comparator(comparator_b)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(mcpwm_capture_channel_disable(cap_channel_a)); + TEST_ESP_OK(mcpwm_del_capture_channel(cap_channel_a)); + TEST_ESP_OK(mcpwm_capture_channel_disable(cap_channel_b)); + TEST_ESP_OK(mcpwm_del_capture_channel(cap_channel_b)); + TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer)); + TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer)); } static void single_edge_active_high(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb) @@ -392,41 +504,55 @@ static void dual_edge_complementary(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t TEST_CASE("mcpwm_generator_action_on_compare_event", "[mcpwm]") { + uint32_t capa, capb; printf("[Asymmetric, SingleEdge, ActiveHigh]\r\n"); // PWMA: high = [1->350], low = [351->499,0] // PWMB: high = [1->200], low = [201->499,0] - mcpwm_gen_action_test_template(1000000, 500, MCPWM_TIMER_COUNT_MODE_UP, 350, 200, TEST_PWMA_GPIO, TEST_PWMB_GPIO, single_edge_active_high); + mcpwm_gen_action_test_template(1000000, 500, MCPWM_TIMER_COUNT_MODE_UP, 350, 200, TEST_PWMA_GPIO, TEST_PWMB_GPIO, single_edge_active_high, &capa, &capb); + TEST_ASSERT_UINT_WITHIN(2, 150, capa); + TEST_ASSERT_UINT_WITHIN(2, 300, capb); printf("[Asymmetric, SingleEdge, ActiveLow]\r\n"); // PWMA: low = [0->300], high = [301->499] // PWMB: low = [0->150], high = [151->499] - mcpwm_gen_action_test_template(1000000, 500, MCPWM_TIMER_COUNT_MODE_UP, 300, 150, TEST_PWMA_GPIO, TEST_PWMB_GPIO, single_edge_active_low); + mcpwm_gen_action_test_template(1000000, 500, MCPWM_TIMER_COUNT_MODE_UP, 300, 150, TEST_PWMA_GPIO, TEST_PWMB_GPIO, single_edge_active_low, &capa, &capb); + TEST_ASSERT_UINT_WITHIN(2, 200, capa); + TEST_ASSERT_UINT_WITHIN(2, 350, capb); printf("[Asymmetric, PulsePlacement]\r\n"); // PWMA: low = [0->200], high = [201->400], low = [401->599] // PWMB: high = [0->599], low = [0->599] - mcpwm_gen_action_test_template(1000000, 600, MCPWM_TIMER_COUNT_MODE_UP, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, pulse_placement); + mcpwm_gen_action_test_template(1000000, 600, MCPWM_TIMER_COUNT_MODE_UP, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, pulse_placement, &capa, &capb); + TEST_ASSERT_UINT_WITHIN(2, 200, capa); + TEST_ASSERT_UINT_WITHIN(2, 600, capb); printf("[Asymmetric, DualEdge, ActiveLow]\r\n"); // PWMA: low = [0->250], high = [251->599, 600->450], low = [451->1] // PWMB: low = [0->599], low = [600->1] - mcpwm_gen_action_test_template(1000000, 1200, MCPWM_TIMER_COUNT_MODE_UP_DOWN, 250, 450, TEST_PWMA_GPIO, TEST_PWMB_GPIO, dual_edge_active_low_asym); + mcpwm_gen_action_test_template(1000000, 1200, MCPWM_TIMER_COUNT_MODE_UP_DOWN, 250, 450, TEST_PWMA_GPIO, TEST_PWMB_GPIO, dual_edge_active_low_asym, &capa, &capb); + TEST_ASSERT_UINT_WITHIN(2, 500, capa); + TEST_ASSERT_UINT_WITHIN(2, 600, capb); printf("[Symmetric, DualEdge, ActiveLow]\r\n"); // PWMA: low = [0->400], high = [401->599, 600->400], low = [399->1] // PWMB: low = [0->500], high = [501->599, 600->500], low = [499->1] - mcpwm_gen_action_test_template(1000000, 1200, MCPWM_TIMER_COUNT_MODE_UP_DOWN, 400, 500, TEST_PWMA_GPIO, TEST_PWMB_GPIO, dual_edge_active_low_sym); + mcpwm_gen_action_test_template(1000000, 1200, MCPWM_TIMER_COUNT_MODE_UP_DOWN, 400, 500, TEST_PWMA_GPIO, TEST_PWMB_GPIO, dual_edge_active_low_sym, &capa, &capb); + TEST_ASSERT_UINT_WITHIN(2, 400, capa); + TEST_ASSERT_UINT_WITHIN(2, 200, capb); printf("[Symmetric, DualEdge, Complementary]\r\n"); // PWMA: low = [0->350], high = [351->599, 600->350], low = [349->1] // PWMB: low = [0->400], high = [401->599, 600->400], low = [399->1] - mcpwm_gen_action_test_template(1000000, 1200, MCPWM_TIMER_COUNT_MODE_UP_DOWN, 350, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, dual_edge_complementary); + mcpwm_gen_action_test_template(1000000, 1200, MCPWM_TIMER_COUNT_MODE_UP_DOWN, 350, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, dual_edge_complementary, &capa, &capb); + TEST_ASSERT_UINT_WITHIN(2, 500, capa); + TEST_ASSERT_UINT_WITHIN(2, 400, capb); } typedef void (*set_dead_time_cb_t)(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb); static void mcpwm_deadtime_test_template(uint32_t timer_resolution, uint32_t period, uint32_t cmpa, uint32_t cmpb, int gpioa, int gpiob, - set_gen_actions_cb_t set_generator_actions, set_dead_time_cb_t set_dead_time) + set_gen_actions_cb_t set_generator_actions, set_dead_time_cb_t set_dead_time, + uint32_t ret_capa[2], uint32_t ret_capb[2]) { mcpwm_timer_config_t timer_config = { .group_id = 0, @@ -469,10 +595,61 @@ static void mcpwm_deadtime_test_template(uint32_t timer_resolution, uint32_t per set_generator_actions(generator_a, generator_b, comparator_a, comparator_b); set_dead_time(generator_a, generator_b); + // install mcpwm capture timer + mcpwm_cap_timer_handle_t cap_timer = NULL; + uint32_t clk_src_freq_hz; + esp_clk_tree_src_get_freq_hz(MCPWM_CAPTURE_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz); + mcpwm_capture_timer_config_t cap_timer_config = { + .clk_src = MCPWM_CAPTURE_CLK_SRC_DEFAULT, + .group_id = 0, + .resolution_hz = clk_src_freq_hz / 2, + }; + TEST_ESP_OK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer)); + + // install mcpwm capture channel + mcpwm_cap_channel_handle_t cap_channel_a; + mcpwm_cap_channel_handle_t cap_channel_b; + mcpwm_capture_channel_config_t cap_chan_config = { + .gpio_num = gpioa, + .prescale = 1, + .flags.pos_edge = true, + .flags.neg_edge = true, + }; + TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &cap_channel_a)); + cap_chan_config.gpio_num = gpiob; + TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &cap_channel_b)); + + // install callback for capture channel + mcpwm_capture_event_callbacks_t cbs = { + .on_cap = test_capture_callback, + }; + uint32_t cap_value_a[2] = {0}; + uint32_t cap_value_b[2] = {0}; + TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(cap_channel_a, &cbs, cap_value_a)); + TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(cap_channel_b, &cbs, cap_value_b)); + + // enable capture channel and timer + TEST_ESP_OK(mcpwm_capture_channel_enable(cap_channel_a)); + TEST_ESP_OK(mcpwm_capture_channel_enable(cap_channel_b)); + TEST_ESP_OK(mcpwm_capture_timer_enable(cap_timer)); + + // start timer and capture timer TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP)); + TEST_ESP_OK(mcpwm_capture_timer_start(cap_timer)); vTaskDelay(pdMS_TO_TICKS(100)); - TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_STOP_EMPTY)); + TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_STOP_FULL)); vTaskDelay(pdMS_TO_TICKS(10)); + TEST_ESP_OK(mcpwm_capture_timer_stop(cap_timer)); + + // calculate the actual capture time + uint32_t clk_src_res; + TEST_ESP_OK(mcpwm_capture_timer_get_resolution(cap_timer, &clk_src_res)); + clk_src_res /= 1000; // convert to kHz + + ret_capa[0] = cap_value_a[0] * 1000 / clk_src_res; + ret_capa[1] = cap_value_a[1] * 1000 / clk_src_res; + ret_capb[0] = cap_value_b[0] * 1000 / clk_src_res; + ret_capb[1] = cap_value_b[1] * 1000 / clk_src_res; TEST_ESP_OK(mcpwm_timer_disable(timer)); TEST_ESP_OK(mcpwm_del_generator(generator_a)); @@ -481,6 +658,12 @@ static void mcpwm_deadtime_test_template(uint32_t timer_resolution, uint32_t per TEST_ESP_OK(mcpwm_del_comparator(comparator_b)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(mcpwm_capture_channel_disable(cap_channel_a)); + TEST_ESP_OK(mcpwm_del_capture_channel(cap_channel_a)); + TEST_ESP_OK(mcpwm_capture_channel_disable(cap_channel_b)); + TEST_ESP_OK(mcpwm_del_capture_channel(cap_channel_b)); + TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer)); + TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer)); } static void ahc_set_generator_actions(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb) @@ -663,34 +846,58 @@ static void invalid_reda_redb_set_dead_time(mcpwm_gen_handle_t gena, mcpwm_gen_h TEST_CASE("mcpwm_generator_deadtime_classical_configuration", "[mcpwm]") { + uint32_t capa[2], capb[2]; printf("Active High Complementary\r\n"); - mcpwm_deadtime_test_template(1000000, 600, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, ahc_set_generator_actions, ahc_set_dead_time); + mcpwm_deadtime_test_template(1000000, 600, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, ahc_set_generator_actions, ahc_set_dead_time, capa, capb); + TEST_ASSERT_UINT_WITHIN(2, 50, capa[0] - capb[1]); + TEST_ASSERT_UINT_WITHIN(2, 100, capb[0] - capa[1]); printf("Active Low Complementary\r\n"); - mcpwm_deadtime_test_template(1000000, 600, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, alc_set_generator_actions, alc_set_dead_time); + mcpwm_deadtime_test_template(1000000, 600, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, alc_set_generator_actions, alc_set_dead_time, capa, capb); + TEST_ASSERT_UINT_WITHIN(2, 50, capa[1] - capb[0]); + TEST_ASSERT_UINT_WITHIN(2, 100, capb[1] - capa[0]); printf("Active High\r\n"); - mcpwm_deadtime_test_template(1000000, 600, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, ah_set_generator_actions, ah_set_dead_time); + mcpwm_deadtime_test_template(1000000, 600, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, ah_set_generator_actions, ah_set_dead_time, capa, capb); + TEST_ASSERT_UINT_WITHIN(2, 50, capa[0] - capb[0]); + TEST_ASSERT_UINT_WITHIN(2, 100, capb[1] - capa[1]); printf("Active Low\r\n"); - mcpwm_deadtime_test_template(1000000, 600, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, al_set_generator_actions, al_set_dead_time); + mcpwm_deadtime_test_template(1000000, 600, 200, 400, TEST_PWMA_GPIO, TEST_PWMB_GPIO, al_set_generator_actions, al_set_dead_time, capa, capb); + TEST_ASSERT_UINT_WITHIN(2, 50, capa[1] - capb[1]); + TEST_ASSERT_UINT_WITHIN(2, 100, capb[0] - capa[0]); printf("RED on A, Bypass B\r\n"); - mcpwm_deadtime_test_template(1000000, 500, 350, 350, TEST_PWMA_GPIO, TEST_PWMB_GPIO, reda_only_set_generator_actions, reda_only_set_dead_time); + mcpwm_deadtime_test_template(1000000, 500, 350, 350, TEST_PWMA_GPIO, TEST_PWMB_GPIO, reda_only_set_generator_actions, reda_only_set_dead_time, capa, capb); + TEST_ASSERT_UINT_WITHIN(2, 50, capa[0] - capb[0]); + TEST_ASSERT_UINT_WITHIN(2, 0, capb[1] - capa[1]); printf("Bypass A, FED on B\r\n"); - mcpwm_deadtime_test_template(1000000, 500, 350, 350, TEST_PWMA_GPIO, TEST_PWMB_GPIO, fedb_only_set_generator_actions, fedb_only_set_dead_time); + mcpwm_deadtime_test_template(1000000, 500, 350, 350, TEST_PWMA_GPIO, TEST_PWMB_GPIO, fedb_only_set_generator_actions, fedb_only_set_dead_time, capa, capb); + TEST_ASSERT_UINT_WITHIN(2, 50, capb[1] - capa[1]); + TEST_ASSERT_UINT_WITHIN(2, 0, capb[0] - capa[0]); printf("Bypass A, RED + FED on B\r\n"); - mcpwm_deadtime_test_template(1000000, 500, 350, 350, TEST_PWMA_GPIO, TEST_PWMB_GPIO, redfedb_only_set_generator_actions, redfedb_only_set_dead_time); + mcpwm_deadtime_test_template(1000000, 500, 350, 350, TEST_PWMA_GPIO, TEST_PWMB_GPIO, redfedb_only_set_generator_actions, redfedb_only_set_dead_time, capa, capb); + TEST_ASSERT_UINT_WITHIN(2, 50, capb[0] - capa[0]); + TEST_ASSERT_UINT_WITHIN(2, 50, capb[1] - capa[1]); printf("Can't apply one delay module to multiple generators\r\n"); - mcpwm_deadtime_test_template(1000000, 500, 350, 350, TEST_PWMA_GPIO, TEST_PWMB_GPIO, redfedb_only_set_generator_actions, invalid_reda_redb_set_dead_time); + mcpwm_deadtime_test_template(1000000, 500, 350, 350, TEST_PWMA_GPIO, TEST_PWMB_GPIO, redfedb_only_set_generator_actions, invalid_reda_redb_set_dead_time, capa, capb); + TEST_ASSERT_UINT_WITHIN(2, 0, capa[0] - capb[0]); + TEST_ASSERT_UINT_WITHIN(2, 0, capa[1] - capb[1]); } TEST_CASE("mcpwm_duty_empty_full", "[mcpwm]") { const int gen_gpio_num = TEST_PWMA_GPIO; + printf("init a gpio to read generator output\r\n"); + gpio_config_t gen_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(gen_gpio_num), + }; + TEST_ESP_OK(gpio_config(&gen_gpio_conf)); + mcpwm_timer_handle_t timer; mcpwm_oper_handle_t oper; mcpwm_cmpr_handle_t comparator; @@ -722,7 +929,6 @@ TEST_CASE("mcpwm_duty_empty_full", "[mcpwm]") printf("install MCPWM generator\r\n"); mcpwm_generator_config_t gen_config = { .gen_gpio_num = gen_gpio_num, - .flags.io_loop_back = true, // we want to read the output level as well }; TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen)); @@ -763,12 +969,30 @@ TEST_CASE("mcpwm_duty_empty_full", "[mcpwm]") TEST_ESP_OK(mcpwm_del_comparator(comparator)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(gen_gpio_num)); } TEST_CASE("mcpwm_generator_action_on_fault_trigger_event", "[mcpwm]") { const int generator_gpio = TEST_PWMA_GPIO; const int fault_gpio_num[3] = {TEST_FAULT_GPIO0, TEST_FAULT_GPIO1, TEST_FAULT_GPIO2}; + + printf("init a gpio to read generator output and simulate fault signal\r\n"); + gpio_config_t generator_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(generator_gpio), + }; + TEST_ESP_OK(gpio_config(&generator_gpio_conf)); + + gpio_config_t fault_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 0, + }; + for (int i = 0; i < 3; i++) { + fault_gpio_conf.pin_bit_mask |= BIT(fault_gpio_num[i]); + } + TEST_ESP_OK(gpio_config(&fault_gpio_conf)); + printf("create timer and operator\r\n"); mcpwm_timer_config_t timer_config = { .group_id = 0, @@ -796,7 +1020,6 @@ TEST_CASE("mcpwm_generator_action_on_fault_trigger_event", "[mcpwm]") .flags.active_level = 1, .flags.pull_down = 1, .flags.pull_up = 0, - .flags.io_loop_back = 1, // so that we can write the GPIO value by GPIO driver }; for (int i = 0 ; i < 3; i++) { gpio_trigger_config.gpio_num = fault_gpio_num[i]; @@ -806,7 +1029,6 @@ TEST_CASE("mcpwm_generator_action_on_fault_trigger_event", "[mcpwm]") printf("create generator\r\n"); mcpwm_generator_config_t gen_config = { .gen_gpio_num = generator_gpio, - .flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver }; mcpwm_gen_handle_t gen = NULL; TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen)); @@ -839,11 +1061,22 @@ TEST_CASE("mcpwm_generator_action_on_fault_trigger_event", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(gen)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(generator_gpio)); + for (int i = 0; i < 3; i++) { + TEST_ESP_OK(gpio_reset_pin(fault_gpio_num[i])); + } } TEST_CASE("mcpwm_generator_action_on_soft_sync_trigger_event", "[mcpwm]") { const int generator_gpio = TEST_PWMA_GPIO; + printf("init a gpio to read generator output\r\n"); + gpio_config_t generator_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(generator_gpio), + }; + TEST_ESP_OK(gpio_config(&generator_gpio_conf)); + printf("create timer and operator\r\n"); mcpwm_timer_config_t timer_config = { .group_id = 0, @@ -879,7 +1112,6 @@ TEST_CASE("mcpwm_generator_action_on_soft_sync_trigger_event", "[mcpwm]") printf("create generator\r\n"); mcpwm_generator_config_t gen_config = { .gen_gpio_num = generator_gpio, - .flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver }; mcpwm_gen_handle_t gen = NULL; TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen)); @@ -905,11 +1137,19 @@ TEST_CASE("mcpwm_generator_action_on_soft_sync_trigger_event", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(gen)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(generator_gpio)); } TEST_CASE("mcpwm_generator_action_on_timer_sync_trigger_event", "[mcpwm]") { const int generator_gpio = TEST_PWMA_GPIO; + printf("init a gpio to read generator output\r\n"); + gpio_config_t generator_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(generator_gpio), + }; + TEST_ESP_OK(gpio_config(&generator_gpio_conf)); + printf("create timer and operator\r\n"); mcpwm_timer_config_t timer_config = { .group_id = 0, @@ -948,7 +1188,6 @@ TEST_CASE("mcpwm_generator_action_on_timer_sync_trigger_event", "[mcpwm]") printf("create generator\r\n"); mcpwm_generator_config_t gen_config = { .gen_gpio_num = generator_gpio, - .flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver }; mcpwm_gen_handle_t gen = NULL; TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen)); @@ -970,11 +1209,25 @@ TEST_CASE("mcpwm_generator_action_on_timer_sync_trigger_event", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(gen)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(generator_gpio)); } TEST_CASE("mcpwm_generator_action_on_gpio_sync_trigger_event", "[mcpwm]") { const int generator_gpio = TEST_PWMA_GPIO; + const int sync_gpio = TEST_SYNC_GPIO; + printf("init a gpio to read generator output and simulate sync signal\r\n"); + gpio_config_t generator_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(generator_gpio), + }; + TEST_ESP_OK(gpio_config(&generator_gpio_conf)); + gpio_config_t sync_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT(sync_gpio), + }; + TEST_ESP_OK(gpio_config(&sync_gpio_conf)); + printf("create timer and operator\r\n"); mcpwm_timer_config_t timer_config = { .group_id = 0, @@ -999,14 +1252,13 @@ TEST_CASE("mcpwm_generator_action_on_gpio_sync_trigger_event", "[mcpwm]") mcpwm_sync_handle_t gpio_sync = NULL; mcpwm_gpio_sync_src_config_t gpio_sync_config = { .group_id = 0, - .gpio_num = TEST_SYNC_GPIO, - .flags.io_loop_back = true, // so that we can use gpio driver to simulate the sync signal + .gpio_num = sync_gpio, .flags.pull_down = true, // internally pull down }; TEST_ESP_OK(mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync)); // put the GPIO into initial state - gpio_set_level(gpio_sync_config.gpio_num, 0); + gpio_set_level(sync_gpio, 0); mcpwm_timer_sync_phase_config_t sync_phase_config = { .count_value = 0, @@ -1018,7 +1270,6 @@ TEST_CASE("mcpwm_generator_action_on_gpio_sync_trigger_event", "[mcpwm]") printf("create generator\r\n"); mcpwm_generator_config_t gen_config = { .gen_gpio_num = generator_gpio, - .flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver }; mcpwm_gen_handle_t gen = NULL; TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen)); @@ -1028,8 +1279,8 @@ TEST_CASE("mcpwm_generator_action_on_gpio_sync_trigger_event", "[mcpwm]") MCPWM_GEN_SYNC_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, gpio_sync, MCPWM_GEN_ACTION_HIGH))); TEST_ASSERT_EQUAL(0, gpio_get_level(generator_gpio)); - gpio_set_level(gpio_sync_config.gpio_num, 1); - gpio_set_level(gpio_sync_config.gpio_num, 0); + gpio_set_level(sync_gpio, 1); + gpio_set_level(sync_gpio, 0); TEST_ASSERT_EQUAL(1, gpio_get_level(generator_gpio)); vTaskDelay(pdMS_TO_TICKS(10)); @@ -1038,4 +1289,6 @@ TEST_CASE("mcpwm_generator_action_on_gpio_sync_trigger_event", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(gen)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(generator_gpio)); + TEST_ESP_OK(gpio_reset_pin(sync_gpio)); } diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_iram.c b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_iram.c index fa53482c5692..24744463babc 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_iram.c +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_iram.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -46,6 +46,13 @@ TEST_CASE("mcpwm_capture_iram_safe", "[mcpwm]") TEST_ESP_OK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer)); const int cap_gpio = TEST_CAP_GPIO; + printf("init a gpio to simulate the external capture signal\r\n"); + gpio_config_t cap_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT(cap_gpio), + }; + TEST_ESP_OK(gpio_config(&cap_gpio_conf)); + // put the GPIO into a preset state gpio_set_level(cap_gpio, 0); @@ -56,7 +63,6 @@ TEST_CASE("mcpwm_capture_iram_safe", "[mcpwm]") .prescale = 1, .flags.pos_edge = true, .flags.neg_edge = true, - .flags.io_loop_back = true, // so we can use GPIO functions to simulate the external capture signal .flags.pull_up = true, }; TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &pps_channel)); @@ -89,6 +95,7 @@ TEST_CASE("mcpwm_capture_iram_safe", "[mcpwm]") TEST_ESP_OK(mcpwm_del_capture_channel(pps_channel)); TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer)); TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer)); + TEST_ESP_OK(gpio_reset_pin(cap_gpio)); } static bool IRAM_ATTR test_compare_on_reach(mcpwm_cmpr_handle_t cmpr, const mcpwm_compare_event_data_t *ev_data, void *user_data) diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_oper.c b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_oper.c index 76f977a268c7..ce2523d7fbea 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_oper.c +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_oper.c @@ -121,6 +121,22 @@ static bool IRAM_ATTR test_ost_brake_on_gpio_fault_callback(mcpwm_oper_handle_t TEST_CASE("mcpwm_operator_brake_on_gpio_fault", "[mcpwm]") { + const int cbc_fault_gpio = TEST_FAULT_GPIO1; + const int ost_fault_gpio = TEST_FAULT_GPIO2; + const int gen_a_gpio = TEST_PWMA_GPIO; + const int gen_b_gpio = TEST_PWMB_GPIO; + printf("init gpios to read generator output and simulate fault signal\r\n"); + gpio_config_t fault_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT(cbc_fault_gpio) | BIT(ost_fault_gpio), + }; + TEST_ESP_OK(gpio_config(&fault_gpio_conf)); + gpio_config_t gen_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(gen_a_gpio) | BIT(gen_b_gpio), + }; + TEST_ESP_OK(gpio_config(&gen_gpio_conf)); + printf("install timer\r\n"); mcpwm_timer_config_t timer_config = { .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT, @@ -151,13 +167,10 @@ TEST_CASE("mcpwm_operator_brake_on_gpio_fault", "[mcpwm]") mcpwm_gpio_fault_config_t gpio_fault_config = { .group_id = 0, .flags.active_level = 1, - .flags.io_loop_back = true, .flags.pull_down = true, }; mcpwm_fault_handle_t gpio_cbc_fault = NULL; mcpwm_fault_handle_t gpio_ost_fault = NULL; - const int cbc_fault_gpio = TEST_FAULT_GPIO1; - const int ost_fault_gpio = TEST_FAULT_GPIO2; gpio_fault_config.gpio_num = cbc_fault_gpio; TEST_ESP_OK(mcpwm_new_gpio_fault(&gpio_fault_config, &gpio_cbc_fault)); @@ -180,14 +193,12 @@ TEST_CASE("mcpwm_operator_brake_on_gpio_fault", "[mcpwm]") TEST_ESP_OK(mcpwm_operator_set_brake_on_fault(oper, &brake_config)); printf("create generators\r\n"); - const int gen_a_gpio = TEST_PWMA_GPIO; - const int gen_b_gpio = TEST_PWMB_GPIO; + mcpwm_gen_handle_t gen_a = NULL; mcpwm_gen_handle_t gen_b = NULL; mcpwm_generator_config_t generator_config = { - .flags.io_loop_back = true, + .gen_gpio_num = gen_a_gpio, }; - generator_config.gen_gpio_num = gen_a_gpio; TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &gen_a)); generator_config.gen_gpio_num = gen_b_gpio; TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &gen_b)); @@ -249,10 +260,23 @@ TEST_CASE("mcpwm_operator_brake_on_gpio_fault", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(gen_b)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(cbc_fault_gpio)); + TEST_ESP_OK(gpio_reset_pin(ost_fault_gpio)); + TEST_ESP_OK(gpio_reset_pin(gen_a_gpio)); + TEST_ESP_OK(gpio_reset_pin(gen_b_gpio)); } TEST_CASE("mcpwm_operator_brake_on_soft_fault", "[mcpwm]") { + const int gen_a_gpio = TEST_PWMA_GPIO; + const int gen_b_gpio = TEST_PWMB_GPIO; + printf("init gpios to read generator output\r\n"); + gpio_config_t gen_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT(gen_a_gpio) | BIT(gen_b_gpio), + }; + TEST_ESP_OK(gpio_config(&gen_gpio_conf)); + printf("install timer\r\n"); mcpwm_timer_config_t timer_config = { .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT, @@ -286,14 +310,11 @@ TEST_CASE("mcpwm_operator_brake_on_soft_fault", "[mcpwm]") TEST_ESP_OK(mcpwm_operator_set_brake_on_fault(oper, &brake_config)); printf("create generators\r\n"); - const int gen_a_gpio = TEST_PWMA_GPIO; - const int gen_b_gpio = TEST_PWMB_GPIO; mcpwm_gen_handle_t gen_a = NULL; mcpwm_gen_handle_t gen_b = NULL; mcpwm_generator_config_t generator_config = { - .flags.io_loop_back = true, + .gen_gpio_num = gen_a_gpio, }; - generator_config.gen_gpio_num = gen_a_gpio; TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &gen_a)); generator_config.gen_gpio_num = gen_b_gpio; TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &gen_b)); @@ -360,4 +381,6 @@ TEST_CASE("mcpwm_operator_brake_on_soft_fault", "[mcpwm]") TEST_ESP_OK(mcpwm_del_generator(gen_b)); TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_timer(timer)); + TEST_ESP_OK(gpio_reset_pin(gen_a_gpio)); + TEST_ESP_OK(gpio_reset_pin(gen_b_gpio)); } diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_sync.c b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_sync.c index 7fb5328cfad3..d8bc8e4aaf79 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_sync.c +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_sync.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -106,6 +106,13 @@ TEST_CASE("mcpwm_gpio_sync_timer_phase_lock", "[mcpwm]") // | // v // timer0-->timer1-->timer2 + const int gpio_num = TEST_SYNC_GPIO; + gpio_config_t sync_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT(gpio_num), + }; + TEST_ESP_OK(gpio_config(&sync_gpio_conf)); + mcpwm_timer_config_t timer_config = { .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT, .group_id = 0, @@ -127,11 +134,9 @@ TEST_CASE("mcpwm_gpio_sync_timer_phase_lock", "[mcpwm]") .direction = MCPWM_TIMER_DIRECTION_UP, }; mcpwm_sync_handle_t gpio_sync_src; - const int gpio_num = TEST_SYNC_GPIO; mcpwm_gpio_sync_src_config_t gpio_sync_config = { .group_id = 0, .gpio_num = gpio_num, - .flags.io_loop_back = true, // so that we can use gpio driver to simulate the sync signal .flags.pull_down = true, // internally pull down }; TEST_ESP_OK(mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync_src)); @@ -154,6 +159,7 @@ TEST_CASE("mcpwm_gpio_sync_timer_phase_lock", "[mcpwm]") TEST_ESP_OK(mcpwm_del_sync_src(sync_srcs[i])); TEST_ESP_OK(mcpwm_del_timer(timers[i])); } + TEST_ESP_OK(gpio_reset_pin(gpio_num)); } TEST_CASE("mcpwm_timer_sync_timer_phase_lock", "[mcpwm]") diff --git a/components/esp_driver_parlio/include/driver/parlio_rx.h b/components/esp_driver_parlio/include/driver/parlio_rx.h index 400b10beabe6..9774d871b40c 100644 --- a/components/esp_driver_parlio/include/driver/parlio_rx.h +++ b/components/esp_driver_parlio/include/driver/parlio_rx.h @@ -40,8 +40,10 @@ typedef struct { the output clock will be controlled by the valid gpio, 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; /*!< Set to skip initializing the GPIO, but only attach the pralio rx signals to those GPIOs via IO Matrix. - So that the signals that have attached to those GPIO won't be overwritten. Mainly used for self communication or self monitoring */ + 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; diff --git a/components/esp_driver_parlio/include/driver/parlio_tx.h b/components/esp_driver_parlio/include/driver/parlio_tx.h index b2cb66a24365..0bd9442ced67 100644 --- a/components/esp_driver_parlio/include/driver/parlio_tx.h +++ b/components/esp_driver_parlio/include/driver/parlio_tx.h @@ -40,6 +40,9 @@ 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; diff --git a/components/esp_driver_parlio/src/parlio_common.c b/components/esp_driver_parlio/src/parlio_common.c index 48518ddb0cca..585cea006f51 100644 --- a/components/esp_driver_parlio/src/parlio_common.c +++ b/components/esp_driver_parlio/src/parlio_common.c @@ -18,6 +18,7 @@ #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"; @@ -46,6 +47,23 @@ 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); @@ -87,6 +105,16 @@ 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); } @@ -147,3 +175,32 @@ 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 diff --git a/components/esp_driver_parlio/src/parlio_private.h b/components/esp_driver_parlio/src/parlio_private.h index d728359b09eb..b76ec8ba834e 100644 --- a/components/esp_driver_parlio/src/parlio_private.h +++ b/components/esp_driver_parlio/src/parlio_private.h @@ -24,6 +24,7 @@ #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) @@ -44,6 +45,9 @@ #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; @@ -149,6 +153,11 @@ 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 diff --git a/components/esp_driver_parlio/src/parlio_rx.c b/components/esp_driver_parlio/src/parlio_rx.c index 411ed2aea0d5..97acef19734d 100644 --- a/components/esp_driver_parlio/src/parlio_rx.c +++ b/components/esp_driver_parlio/src/parlio_rx.c @@ -25,7 +25,6 @@ #include "soc/parlio_periph.h" #include "soc/soc_caps.h" #include "hal/parlio_ll.h" -#include "hal/gpio_hal.h" #include "hal/dma_types.h" #include "hal/hal_utils.h" #include "driver/gpio.h" @@ -252,24 +251,19 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons { int group_id = rx_unit->base.group->group_id; int unit_id = rx_unit->base.unit_id; - /* Default GPIO configuration */ - gpio_config_t gpio_conf = { - .intr_type = GPIO_INTR_DISABLE, - .pull_down_en = false, - .pull_up_en = true, - }; /* When the source clock comes from external, enable the gpio input direction and connect to the clock input signal */ if (config->clk_src == PARLIO_CLK_SRC_EXTERNAL) { ESP_RETURN_ON_FALSE(config->clk_in_gpio_num >= 0, ESP_ERR_INVALID_ARG, TAG, "clk_in_gpio_num must be set while the clock input from external"); /* Connect the clock in signal to the GPIO matrix if it is set */ - if (!config->flags.io_no_init) { - gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT; - gpio_conf.pin_bit_mask = BIT64(config->clk_in_gpio_num); - ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk in GPIO failed"); - } else { - gpio_ll_input_enable(&GPIO, config->clk_in_gpio_num); + gpio_func_sel(config->clk_in_gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(config->clk_in_gpio_num); + + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_output_enable(config->clk_in_gpio_num); } + esp_rom_gpio_connect_in_signal(config->clk_in_gpio_num, parlio_periph_signals.groups[group_id].rx_units[unit_id].clk_in_sig, false); } @@ -277,9 +271,14 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons * enable the gpio output direction and connect to the clock output signal */ if (config->clk_out_gpio_num >= 0) { #if SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT - gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_OUTPUT; - gpio_conf.pin_bit_mask = BIT64(config->clk_out_gpio_num); - ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk out GPIO failed"); + gpio_func_sel(config->clk_out_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->clk_out_gpio_num); + } + + // connect the signal to the GPIO by matrix, it will also enable the output path properly esp_rom_gpio_connect_out_signal(config->clk_out_gpio_num, parlio_periph_signals.groups[group_id].rx_units[unit_id].clk_out_sig, false, false); #else @@ -287,15 +286,16 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons #endif // SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT } - gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT; /* Initialize the valid GPIO as input */ if (config->valid_gpio_num >= 0) { - if (!config->flags.io_no_init) { - gpio_conf.pin_bit_mask = BIT64(config->valid_gpio_num); - ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed"); - } else { - gpio_ll_input_enable(&GPIO, config->valid_gpio_num); + gpio_func_sel(config->valid_gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(config->valid_gpio_num); + + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_output_enable(config->valid_gpio_num); } + /* Not connect the signal here, the signal is lazy connected until the delimiter takes effect */ } @@ -303,12 +303,14 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons for (int i = 0; i < config->data_width; i++) { /* Loop the data_gpio_nums to connect data and valid signals via GPIO matrix */ if (config->data_gpio_nums[i] >= 0) { - if (!config->flags.io_no_init) { - gpio_conf.pin_bit_mask = BIT64(config->data_gpio_nums[i]); - ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed"); - } else { - gpio_ll_input_enable(&GPIO, config->data_gpio_nums[i]); + gpio_func_sel(config->data_gpio_nums[i], PIN_FUNC_GPIO); + gpio_input_enable(config->data_gpio_nums[i]); + + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_output_enable(config->data_gpio_nums[i]); } + esp_rom_gpio_connect_in_signal(config->data_gpio_nums[i], parlio_periph_signals.groups[group_id].rx_units[unit_id].data_sigs[i], false); } else { @@ -618,6 +620,10 @@ 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"); @@ -674,6 +680,12 @@ 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; diff --git a/components/esp_driver_parlio/src/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c index dcf073ed264e..b7493b73cb89 100644 --- a/components/esp_driver_parlio/src/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.c @@ -138,46 +138,59 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const { int group_id = tx_unit->base.group->group_id; int unit_id = tx_unit->base.unit_id; - gpio_config_t gpio_conf = { - .intr_type = GPIO_INTR_DISABLE, - .mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_OUTPUT, - .pull_down_en = false, - .pull_up_en = true, - }; // connect peripheral signals via GPIO matrix for (size_t i = 0; i < config->data_width; i++) { if (config->data_gpio_nums[i] >= 0) { - gpio_conf.pin_bit_mask = BIT64(config->data_gpio_nums[i]); - ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed"); + gpio_func_sel(config->data_gpio_nums[i], PIN_FUNC_GPIO); + + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_input_enable(config->data_gpio_nums[i]); + } + + // connect the signal to the GPIO by matrix, it will also enable the output path properly esp_rom_gpio_connect_out_signal(config->data_gpio_nums[i], parlio_periph_signals.groups[group_id].tx_units[unit_id].data_sigs[i], false, false); - gpio_func_sel(config->data_gpio_nums[i], PIN_FUNC_GPIO); } } // Note: the valid signal will override TXD[PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG] if (config->valid_gpio_num >= 0) { - gpio_conf.pin_bit_mask = BIT64(config->valid_gpio_num); - ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config valid GPIO failed"); + gpio_func_sel(config->valid_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->valid_gpio_num); + } + + // connect the signal to the GPIO by matrix, it will also enable the output path properly esp_rom_gpio_connect_out_signal(config->valid_gpio_num, parlio_periph_signals.groups[group_id].tx_units[unit_id].data_sigs[PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG], false, false); - gpio_func_sel(config->valid_gpio_num, PIN_FUNC_GPIO); } if (config->clk_out_gpio_num >= 0) { - gpio_conf.pin_bit_mask = BIT64(config->clk_out_gpio_num); - ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk out GPIO failed"); + gpio_func_sel(config->clk_out_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->clk_out_gpio_num); + } + + // connect the signal to the GPIO by matrix, it will also enable the output path properly esp_rom_gpio_connect_out_signal(config->clk_out_gpio_num, parlio_periph_signals.groups[group_id].tx_units[unit_id].clk_out_sig, false, false); - gpio_func_sel(config->clk_out_gpio_num, PIN_FUNC_GPIO); } if (config->clk_in_gpio_num >= 0) { - gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT; - gpio_conf.pin_bit_mask = BIT64(config->clk_in_gpio_num); - ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk in GPIO failed"); + gpio_func_sel(config->clk_in_gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(config->clk_in_gpio_num); + + // deprecated, to be removed in in esp-idf v6.0 + if (config->flags.io_loop_back) { + gpio_output_enable(config->clk_in_gpio_num); + } + esp_rom_gpio_connect_in_signal(config->clk_in_gpio_num, parlio_periph_signals.groups[group_id].tx_units[unit_id].clk_in_sig, false); - gpio_func_sel(config->clk_in_gpio_num, PIN_FUNC_GPIO); } return ESP_OK; } @@ -257,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 register configuration to the module + // turn on the tx module clock to sync the clock divider configuration because of the CDC (Cross Domain Crossing) parlio_ll_tx_enable_clock(hal->regs, true); parlio_ll_tx_set_clock_source(hal->regs, clk_src); // set clock division @@ -296,6 +309,10 @@ 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); @@ -368,6 +385,12 @@ 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 @@ -455,13 +478,11 @@ 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)) { @@ -476,6 +497,11 @@ 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; @@ -518,6 +544,10 @@ 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); @@ -608,9 +638,6 @@ 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; diff --git a/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt b/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt index 3ee6db54cecc..6d465c10d474 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt +++ b/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt @@ -7,6 +7,10 @@ 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} diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_board.h b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h index da22296e39dc..36c4931acb9a 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_board.h +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h @@ -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 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 +#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 #else #error "Unsupported target" #endif diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c index cf5f0befcb2a..cc454aa7b448 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c @@ -52,7 +52,6 @@ }, \ .flags = { \ .clk_gate_en = false, \ - .io_loop_back = true, \ } \ } @@ -369,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_POS, + .sample_edge = PARLIO_SAMPLE_EDGE_NEG, .bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB, .eof_data_len = TEST_EOF_DATA_LEN, .timeout_ticks = 0, @@ -528,6 +527,13 @@ TEST_CASE("parallel_rx_unit_receive_transaction_test", "[parlio_rx]") TEST_CASE("parallel_rx_unit_receive_timeout_test", "[parlio_rx]") { + printf("init a gpio to simulate valid signal\r\n"); + gpio_config_t test_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT64(TEST_VALID_GPIO), + }; + TEST_ESP_OK(gpio_config(&test_gpio_conf)); + parlio_rx_unit_handle_t rx_unit = NULL; parlio_rx_delimiter_handle_t timeout_deli = NULL; @@ -583,5 +589,6 @@ TEST_CASE("parallel_rx_unit_receive_timeout_test", "[parlio_rx]") TEST_ESP_OK(parlio_rx_unit_disable(rx_unit)); TEST_ESP_OK(parlio_del_rx_delimiter(timeout_deli)); TEST_ESP_OK(parlio_del_rx_unit(rx_unit)); + TEST_ESP_OK(gpio_reset_pin(TEST_VALID_GPIO)); free(payload); } diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_sleep.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_sleep.c new file mode 100644 index 000000000000..047a19ca4c7b --- /dev/null +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_sleep.c @@ -0,0 +1,168 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#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 +} diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c index a1fd71d8883c..a556c8a407ad 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c @@ -178,6 +178,13 @@ TEST_CASE("parallel_tx_unit_enable_disable", "[parlio_tx]") TEST_CASE("parallel_tx_unit_idle_value", "[parlio_tx]") { + printf("init a gpio to read parlio_tx output\r\n"); + gpio_config_t test_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT64(TEST_DATA0_GPIO), + }; + TEST_ESP_OK(gpio_config(&test_gpio_conf)); + printf("install parlio tx unit\r\n"); parlio_tx_unit_handle_t tx_unit = NULL; parlio_tx_unit_config_t config = { @@ -201,7 +208,6 @@ TEST_CASE("parallel_tx_unit_idle_value", "[parlio_tx]") .max_transfer_size = 64, .bit_pack_order = PARLIO_BIT_PACK_ORDER_LSB, .sample_edge = PARLIO_SAMPLE_EDGE_POS, - .flags.io_loop_back = 1, // enable loop back by GPIO matrix, so that we can read the level of the data line by gpio driver }; TEST_ESP_OK(parlio_new_tx_unit(&config, &tx_unit)); TEST_ESP_OK(parlio_tx_unit_enable(tx_unit)); @@ -224,11 +230,19 @@ TEST_CASE("parallel_tx_unit_idle_value", "[parlio_tx]") TEST_ESP_OK(parlio_tx_unit_disable(tx_unit)); TEST_ESP_OK(parlio_del_tx_unit(tx_unit)); + TEST_ESP_OK(gpio_reset_pin(TEST_DATA0_GPIO)); } #if SOC_PARLIO_TX_CLK_SUPPORT_GATING TEST_CASE("parallel_tx_clock_gating", "[paralio_tx]") { + printf("init a gpio to read parlio_tx clk output\r\n"); + gpio_config_t test_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT64(TEST_CLK_GPIO), + }; + TEST_ESP_OK(gpio_config(&test_gpio_conf)); + printf("install parlio tx unit\r\n"); parlio_tx_unit_handle_t tx_unit = NULL; parlio_tx_unit_config_t config = { @@ -247,7 +261,6 @@ TEST_CASE("parallel_tx_clock_gating", "[paralio_tx]") .bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB, .sample_edge = PARLIO_SAMPLE_EDGE_POS, .flags.clk_gate_en = true, // enable clock gating, controlled by the level of TEST_DATA7_GPIO - .flags.io_loop_back = true, // for reading the level of the clock line in IDLE state }; TEST_ESP_OK(parlio_new_tx_unit(&config, &tx_unit)); TEST_ESP_OK(parlio_tx_unit_enable(tx_unit)); @@ -272,5 +285,6 @@ TEST_CASE("parallel_tx_clock_gating", "[paralio_tx]") TEST_ESP_OK(parlio_tx_unit_disable(tx_unit)); TEST_ESP_OK(parlio_del_tx_unit(tx_unit)); + TEST_ESP_OK(gpio_reset_pin(TEST_CLK_GPIO)); } #endif // SOC_PARLIO_TX_CLK_SUPPORT_GATING diff --git a/components/esp_driver_parlio/test_apps/parlio/sdkconfig.ci.release b/components/esp_driver_parlio/test_apps/parlio/sdkconfig.ci.release index 91d93f163e62..17aaee1e8ece 100644 --- a/components/esp_driver_parlio/test_apps/parlio/sdkconfig.ci.release +++ b/components/esp_driver_parlio/test_apps/parlio/sdkconfig.ci.release @@ -1,5 +1,6 @@ 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 diff --git a/components/esp_driver_parlio/test_apps/parlio/sdkconfig.defaults b/components/esp_driver_parlio/test_apps/parlio/sdkconfig.defaults index 448bb50f824b..e8b3e421f0ab 100644 --- a/components/esp_driver_parlio/test_apps/parlio/sdkconfig.defaults +++ b/components/esp_driver_parlio/test_apps/parlio/sdkconfig.defaults @@ -3,3 +3,6 @@ # CONFIG_ESP_TASK_WDT_INIT=n CONFIG_FREERTOS_HZ=1000 + +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/esp_driver_pcnt/src/pulse_cnt.c b/components/esp_driver_pcnt/src/pulse_cnt.c index 5f50e39acff6..6be76876c196 100644 --- a/components/esp_driver_pcnt/src/pulse_cnt.c +++ b/components/esp_driver_pcnt/src/pulse_cnt.c @@ -28,6 +28,7 @@ #include "hal/gpio_hal.h" #include "esp_private/esp_clk.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/sleep_retention.h" #include "driver/gpio.h" #include "esp_private/gpio.h" #include "hal/gpio_ll.h" // for io_loop_back flag only @@ -65,6 +66,13 @@ typedef struct pcnt_group_t pcnt_group_t; typedef struct pcnt_unit_t pcnt_unit_t; typedef struct pcnt_chan_t pcnt_chan_t; +// Use retention link only when the target supports sleep retention +#define PCNT_USE_RETENTION_LINK (SOC_PCNT_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + +#if PCNT_USE_RETENTION_LINK +static esp_err_t pcnt_create_sleep_retention_link_cb(void *arg); +#endif + struct pcnt_platform_t { _lock_t mutex; // platform level mutex lock pcnt_group_t *groups[SOC_PCNT_GROUPS]; // pcnt group pool @@ -246,6 +254,14 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re TAG, "install interrupt service failed"); } + // PCNT uses the APB as its function clock, + // and its filter module is sensitive to the clock frequency +#if CONFIG_PM_ENABLE + sprintf(unit->pm_lock_name, "pcnt_%d_%d", group_id, unit_id); // e.g. pcnt_0_0 + ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, unit->pm_lock_name, &unit->pm_lock), err, TAG, "install pm lock failed"); + ESP_LOGD(TAG, "install APB_FREQ_MAX lock for unit (%d,%d)", group_id, unit_id); +#endif + // some events are enabled by default, disable them all pcnt_ll_disable_all_events(group->hal.dev, unit_id); // disable filter by default @@ -375,15 +391,6 @@ esp_err_t pcnt_unit_set_glitch_filter(pcnt_unit_handle_t unit, const pcnt_glitch if (config) { glitch_filter_thres = esp_clk_apb_freq() / 1000000 * config->max_glitch_ns / 1000; ESP_RETURN_ON_FALSE(glitch_filter_thres <= PCNT_LL_MAX_GLITCH_WIDTH, ESP_ERR_INVALID_ARG, TAG, "glitch width out of range"); - - // The filter module is working against APB clock, so lazy install PM lock -#if CONFIG_PM_ENABLE - if (!unit->pm_lock) { - sprintf(unit->pm_lock_name, "pcnt_%d_%d", group->group_id, unit->unit_id); // e.g. pcnt_0_0 - ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, unit->pm_lock_name, &unit->pm_lock), TAG, "install pm lock failed"); - ESP_LOGD(TAG, "install APB_FREQ_MAX lock for unit (%d,%d)", group->group_id, unit->unit_id); - } -#endif } // filter control bit is mixed with other PCNT control bits in the same register @@ -865,6 +872,23 @@ static pcnt_group_t *pcnt_acquire_group_handle(int group_id) pcnt_ll_enable_bus_clock(group_id, true); pcnt_ll_reset_register(group_id); } +#if PCNT_USE_RETENTION_LINK + sleep_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module; + sleep_retention_module_init_param_t init_param = { + .cbs = { + .create = { + .handle = pcnt_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, PCNT 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 // PCNT_USE_RETENTION_LINK // initialize HAL context pcnt_hal_init(&group->hal, group_id); } @@ -902,6 +926,12 @@ static void pcnt_release_group_handle(pcnt_group_t *group) _lock_release(&s_platform.mutex); if (do_deinitialize) { +#if PCNT_USE_RETENTION_LINK + const periph_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module; + if (sleep_retention_get_inited_modules() & BIT(module_id)) { + sleep_retention_module_deinit(module_id); + } +#endif // PCNT_USE_RETENTION_LINK free(group); ESP_LOGD(TAG, "del group (%d)", group_id); } @@ -999,3 +1029,17 @@ IRAM_ATTR static void pcnt_default_isr(void *args) portYIELD_FROM_ISR(); } } + +#if PCNT_USE_RETENTION_LINK +static esp_err_t pcnt_create_sleep_retention_link_cb(void *arg) +{ + pcnt_group_t *group = (pcnt_group_t *)arg; + int group_id = group->group_id; + sleep_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module; + esp_err_t err = sleep_retention_entries_create(pcnt_reg_retention_info[group_id].regdma_entry_array, + pcnt_reg_retention_info[group_id].array_size, + REGDMA_LINK_PRI_PCNT, module_id); + ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed"); + return ESP_OK; +} +#endif // PCNT_USE_RETENTION_LINK diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/main/CMakeLists.txt b/components/esp_driver_pcnt/test_apps/pulse_cnt/main/CMakeLists.txt index 67bb690c46b1..1fc04aa4b80c 100644 --- a/components/esp_driver_pcnt/test_apps/pulse_cnt/main/CMakeLists.txt +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/main/CMakeLists.txt @@ -6,6 +6,11 @@ if(CONFIG_PCNT_ISR_IRAM_SAFE) list(APPEND srcs "test_pulse_cnt_iram.c") endif() +# TODO: IDF-9907 support ESP32P4 +if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED AND CONFIG_PM_ENABLE AND NOT CONFIG_IDF_TARGET_ESP32P4) + list(APPEND srcs "test_pulse_cnt_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} diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_sleep.c b/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_sleep.c new file mode 100644 index 000000000000..2ac2dc406289 --- /dev/null +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_sleep.c @@ -0,0 +1,141 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "unity.h" +#include "unity_test_utils.h" +#include "driver/pulse_cnt.h" +#include "driver/gpio.h" +#include "spi_flash_mmap.h" +#include "esp_attr.h" +#include "esp_sleep.h" +#include "soc/soc_caps.h" +#include "soc/pcnt_struct.h" +#include "hal/pcnt_ll.h" +#include "test_pulse_cnt_board.h" +#include "esp_private/sleep_cpu.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" + +/** + * @brief Test the PCNT driver can still work after light sleep + */ +static void test_pcnt_sleep_retention(void) +{ + test_gpio_init_for_simulation(TEST_PCNT_GPIO_A); + test_gpio_init_for_simulation(TEST_PCNT_GPIO_B); + + printf("install pcnt units\r\n"); + pcnt_unit_config_t unit_config = { + .low_limit = -100, + .high_limit = 100, + }; + pcnt_unit_handle_t units[2]; + for (int i = 0; i < 2; i++) { + TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i])); + } + + printf("install pcnt channels\r\n"); + const int channel_gpios[] = {TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B}; + pcnt_chan_config_t chan_config = { + .level_gpio_num = -1, + }; + pcnt_channel_handle_t chans[2]; + for (int i = 0; i < 2; i++) { + chan_config.edge_gpio_num = channel_gpios[i]; + TEST_ESP_OK(pcnt_new_channel(units[i], &chan_config, &chans[i])); + TEST_ESP_OK(pcnt_channel_set_edge_action(chans[i], PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD)); + TEST_ESP_OK(pcnt_channel_set_level_action(chans[i], PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP)); + } + + printf("enable and start unit\r\n"); + for (int i = 0; i < 2; i++) { + TEST_ESP_OK(pcnt_unit_enable(units[i])); + TEST_ESP_OK(pcnt_unit_start(units[i])); + } + + // trigger 10 rising edge on GPIO + test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10); + test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_B, 10); + + int count_value = 0; + for (int i = 0; i < 2; i++) { + TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value)); + TEST_ASSERT_EQUAL(10, count_value); + } + + // hold GPIO to avoid trigger PCNT counter during GPIO power down + gpio_hold_en(TEST_PCNT_GPIO_A); + gpio_hold_en(TEST_PCNT_GPIO_B); + + printf("stop and disable unit before sleep\r\n"); + for (int i = 0; i < 2; i++) { + TEST_ESP_OK(pcnt_unit_stop(units[i])); + TEST_ESP_OK(pcnt_unit_disable(units[i])); + } + + // go to sleep + esp_sleep_context_t sleep_ctx; + esp_sleep_set_sleep_context(&sleep_ctx); + printf("go to light sleep for 1 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(1 * 1000 * 1000)); + TEST_ESP_OK(esp_light_sleep_start()); + + printf("Waked up! Let's see if PCNT 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_PCNT_SUPPORT_SLEEP_RETENTION + // check if the power domain also is powered down + TEST_ASSERT_EQUAL(0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); +#endif + esp_sleep_set_sleep_context(NULL); + + gpio_hold_dis(TEST_PCNT_GPIO_A); + gpio_hold_dis(TEST_PCNT_GPIO_B); + + printf("enable and start unit after sleep\r\n"); + for (int i = 0; i < 2; i++) { + TEST_ESP_OK(pcnt_unit_enable(units[i])); + TEST_ESP_OK(pcnt_unit_start(units[i])); + } + + // Verify the counter still holds the value + test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10); + test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_B, 10); + + int reg_value = 0; + for (int i = 0; i < 2; i++) { + // check the counter value (include accum value and register value) + TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value)); + TEST_ASSERT_EQUAL(20, count_value); + // check the register value + reg_value = pcnt_ll_get_count(&PCNT, i); + TEST_ASSERT_EQUAL(20, reg_value); + } + + for (int i = 0; i < 2; i++) { + TEST_ESP_OK(pcnt_unit_stop(units[i])); + TEST_ESP_OK(pcnt_unit_disable(units[i])); + TEST_ESP_OK(pcnt_del_channel(chans[i])); + TEST_ESP_OK(pcnt_del_unit(units[i])); + } +} + +TEST_CASE("pcnt light sleep", "[pcnt]") +{ + test_pcnt_sleep_retention(); +} diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/sdkconfig.ci.release b/components/esp_driver_pcnt/test_apps/pulse_cnt/sdkconfig.ci.release index 91d93f163e62..17aaee1e8ece 100644 --- a/components/esp_driver_pcnt/test_apps/pulse_cnt/sdkconfig.ci.release +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/sdkconfig.ci.release @@ -1,5 +1,6 @@ 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 diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/sdkconfig.defaults b/components/esp_driver_pcnt/test_apps/pulse_cnt/sdkconfig.defaults index fa8ac618b948..488ad46859a8 100644 --- a/components/esp_driver_pcnt/test_apps/pulse_cnt/sdkconfig.defaults +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/sdkconfig.defaults @@ -1,2 +1,5 @@ CONFIG_FREERTOS_HZ=1000 CONFIG_ESP_TASK_WDT_EN=n + +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/esp_driver_ppa/src/ppa_blend.c b/components/esp_driver_ppa/src/ppa_blend.c index b5ebaa7f6923..f8ffab01ee57 100644 --- a/components/esp_driver_ppa/src/ppa_blend.c +++ b/components/esp_driver_ppa/src/ppa_blend.c @@ -234,16 +234,22 @@ 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, in_bg_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + 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); 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, in_fg_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + 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); // 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); diff --git a/components/esp_driver_ppa/src/ppa_srm.c b/components/esp_driver_ppa/src/ppa_srm.c index f59746e8662f..0242ef37eed9 100644 --- a/components/esp_driver_ppa/src/ppa_srm.c +++ b/components/esp_driver_ppa/src/ppa_srm.c @@ -194,14 +194,17 @@ 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 + 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_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_ERR_INVALID_ARG, TAG, "invalid scale"); uint32_t new_block_w = 0; uint32_t new_block_h = 0; @@ -243,7 +246,8 @@ 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 * config->in.block_h * out_pixel_depth / 8; + 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); 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; @@ -256,9 +260,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 + 1)) & PPA_LL_SRM_SCALING_FRAG_MAX; + 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_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 + 1)) & PPA_LL_SRM_SCALING_FRAG_MAX; + 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->alpha_value = new_alpha_value; srm_trans_desc->data_burst_length = ppa_client->data_burst_length; diff --git a/components/esp_driver_rmt/src/rmt_common.c b/components/esp_driver_rmt/src/rmt_common.c index d2b6f856f6ff..7a3cf11ca3d9 100644 --- a/components/esp_driver_rmt/src/rmt_common.c +++ b/components/esp_driver_rmt/src/rmt_common.c @@ -75,7 +75,7 @@ rmt_group_t *rmt_acquire_group_handle(int group_id) rmt_ll_reset_register(group_id); } #if RMT_USE_RETENTION_LINK - sleep_retention_module_t module = RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id); + sleep_retention_module_t module = rmt_reg_retention_info[group_id].module; sleep_retention_module_init_param_t init_param = { .cbs = { .create = { @@ -85,9 +85,7 @@ rmt_group_t *rmt_acquire_group_handle(int group_id) }, .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) }; - if (sleep_retention_module_init(module, &init_param) == ESP_OK) { - group->sleep_retention_module = module; - } else { + if (sleep_retention_module_init(module, &init_param) != ESP_OK) { // even though the sleep retention module init failed, RMT 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); } @@ -147,11 +145,12 @@ void rmt_release_group_handle(rmt_group_t *group) if (do_deinitialize) { #if RMT_USE_RETENTION_LINK - if (group->sleep_retention_module) { - if (group->retention_link_created) { - sleep_retention_module_free(group->sleep_retention_module); - } - sleep_retention_module_deinit(group->sleep_retention_module); + sleep_retention_module_t module = rmt_reg_retention_info[group_id].module; + if (sleep_retention_get_created_modules() & BIT(module)) { + sleep_retention_module_free(module); + } + if (sleep_retention_get_inited_modules() & BIT(module)) { + sleep_retention_module_deinit(module); } #endif free(group); @@ -303,24 +302,21 @@ static esp_err_t rmt_create_sleep_retention_link_cb(void *arg) { rmt_group_t *group = (rmt_group_t *)arg; int group_id = group->group_id; - sleep_retention_module_t module = group->sleep_retention_module; esp_err_t err = sleep_retention_entries_create(rmt_reg_retention_info[group_id].regdma_entry_array, rmt_reg_retention_info[group_id].array_size, - REGDMA_LINK_PRI_RMT, module); + REGDMA_LINK_PRI_RMT, rmt_reg_retention_info[group_id].module); return err; } void rmt_create_retention_module(rmt_group_t *group) { - sleep_retention_module_t module = group->sleep_retention_module; - + int group_id = group->group_id; + sleep_retention_module_t module = rmt_reg_retention_info[group_id].module; _lock_acquire(&s_platform.mutex); - if (group->retention_link_created == false) { + if ((sleep_retention_get_inited_modules() & BIT(module)) && !(sleep_retention_get_created_modules() & BIT(module))) { if (sleep_retention_module_allocate(module) != ESP_OK) { // even though the sleep retention module create failed, RMT driver should still work, so just warning here - ESP_LOGW(TAG, "create retention link failed, power domain can't be turned off"); - } else { - group->retention_link_created = true; + ESP_LOGW(TAG, "create retention link failed, power domain won't be turned off during sleep"); } } _lock_release(&s_platform.mutex); diff --git a/components/esp_driver_rmt/src/rmt_private.h b/components/esp_driver_rmt/src/rmt_private.h index 017ed9d9ab6d..16efc8ca9eba 100644 --- a/components/esp_driver_rmt/src/rmt_private.h +++ b/components/esp_driver_rmt/src/rmt_private.h @@ -119,10 +119,6 @@ struct rmt_group_t { rmt_rx_channel_t *rx_channels[SOC_RMT_RX_CANDIDATES_PER_GROUP]; // array of RMT RX channels rmt_sync_manager_t *sync_manager; // sync manager, this can be extended into an array if there're more sync controllers in one RMT group int intr_priority; // RMT interrupt priority -#if RMT_USE_RETENTION_LINK - sleep_retention_module_t sleep_retention_module; // sleep retention module - bool retention_link_created; // mark if the retention link is created -#endif }; struct rmt_channel_t { diff --git a/components/esp_driver_sdio/src/sdio_slave.c b/components/esp_driver_sdio/src/sdio_slave.c index ccc56d9ae934..71b6084645b1 100644 --- a/components/esp_driver_sdio/src/sdio_slave.c +++ b/components/esp_driver_sdio/src/sdio_slave.c @@ -76,20 +76,24 @@ The driver of FIFOs works as below: */ #include -#include "driver/sdio_slave.h" -#include "soc/sdio_slave_periph.h" -#include "esp_log.h" -#include "esp_intr_alloc.h" -#include "freertos/FreeRTOS.h" + #include "soc/soc_memory_layout.h" #include "soc/gpio_periph.h" #include "soc/soc_caps.h" +#include "soc/sdio_slave_periph.h" #include "esp_cpu.h" +#include "esp_intr_alloc.h" +#include "esp_log.h" +#include "hal/sdio_slave_hal.h" +#include "hal/gpio_hal.h" +#include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "esp_private/periph_ctrl.h" +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP +#include "esp_private/sleep_retention.h" +#endif #include "driver/gpio.h" -#include "hal/sdio_slave_hal.h" -#include "hal/gpio_hal.h" +#include "driver/sdio_slave.h" #define SDIO_SLAVE_CHECK(res, str, ret_val) do { if(!(res)){\ SDIO_SLAVE_LOGE("%s", str);\ @@ -365,6 +369,13 @@ esp_err_t sdio_slave_initialize(sdio_slave_config_t *config) } context.intr_handle = intr_handle; +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + r = sleep_retention_power_lock_acquire(); + if (r != ESP_OK) { + return r; + } +#endif + r = sdio_slave_hw_init(config); if (r != ESP_OK) { return r; @@ -378,6 +389,11 @@ void sdio_slave_deinit(void) { sdio_slave_hw_deinit(); +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + esp_err_t r = sleep_retention_power_lock_release(); + assert(r == ESP_OK); +#endif + //unregister all buffers registered but returned (not loaded) recv_desc_t *temp_desc; recv_desc_t *desc; diff --git a/components/esp_driver_sdio/test_apps/.build-test-rules.yml b/components/esp_driver_sdio/test_apps/.build-test-rules.yml index df1d2c4828f7..25d6c046aec8 100644 --- a/components/esp_driver_sdio/test_apps/.build-test-rules.yml +++ b/components/esp_driver_sdio/test_apps/.build-test-rules.yml @@ -1,7 +1,6 @@ components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc: enable: - if: IDF_TARGET == "esp32" - temporary: false reason: always use ESP32 SDMMC as host depends_components: - sdmmc @@ -9,6 +8,10 @@ components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc: - esp_driver_sdio components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio: + enable: + # There is no retention support for SDIO slave, just build and test if driver can forbid from auto light sleep. + - if: CONFIG_NAME == "sleep_retention" and SOC_PAU_SUPPORTED == 1 + - if: CONFIG_NAME != "sleep_retention" disable: - if: SOC_SDIO_SLAVE_SUPPORTED != 1 depends_components: diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c index 8a63f2b9b6ad..c358a2d8a7be 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c @@ -418,6 +418,20 @@ TEST_CASE("SDIO_SDMMC: test to host", "[sdio]") test_to_host(true); } +TEST_CASE("SDIO_SDMMC: test sleep retention", "[sdio_retention]") +{ + essl_handle_t handle = NULL; + test_sdio_param_t test_param = { + .host_flags = SDMMC_HOST_FLAG_4BIT | SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF, + .max_freq_khz = SDMMC_FREQ_HIGHSPEED, + }; + //essl init and sdmmc init + s_master_init(&test_param, &handle, NULL); + + s_send_finish_test(handle); + s_master_deinit(); +} + TEST_CASE("SDIO_SDMMC: test to host (Performance)", "[sdio_speed]") { test_to_host(false); diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/pytest_sdio.py b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/pytest_sdio.py index e0e6f3ebf731..1e123bd929ad 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/pytest_sdio.py +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/pytest_sdio.py @@ -1,13 +1,30 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import os.path +from typing import List from typing import Tuple import pytest from pytest_embedded_idf import IdfDut +def parameter_expand(existing_parameters: List[List[str]], value_list: List[str]) -> List[List[str]]: + ret = [] + for param in existing_parameters: + ret.extend([param + [value] for value in value_list]) + + return ret + + +esp32_32_param = [[f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', 'esp32|esp32']] +esp32_c6_param = [[f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', 'esp32|esp32c6']] + +esp32_param_default = [pytest.param(*param) for param in parameter_expand(esp32_32_param, ['default|default'])] +c6_param_default = [pytest.param(*param) for param in parameter_expand(esp32_c6_param, ['default|default'])] + +c6_param_retention = [pytest.param(*param) for param in parameter_expand(esp32_c6_param, ['default|sleep_retention'])] + + # Normal tests def test_sdio_flow(dut:Tuple[IdfDut, IdfDut]) -> None: dut[1].expect('Press ENTER to see the list of tests') @@ -24,11 +41,7 @@ def test_sdio_flow(dut:Tuple[IdfDut, IdfDut]) -> None: @pytest.mark.esp32c6 @pytest.mark.sdio_multidev_32_c6 @pytest.mark.parametrize('count', [2,], indirect=True) -@pytest.mark.parametrize('app_path, target', [ - pytest.param( - f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', - 'esp32|esp32c6'), -], indirect=True) +@pytest.mark.parametrize('app_path, target, config', c6_param_default, indirect=True) def test_sdio_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: test_sdio_flow(dut) @@ -36,11 +49,7 @@ def test_sdio_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: @pytest.mark.esp32 @pytest.mark.sdio_master_slave @pytest.mark.parametrize('count', [2,], indirect=True) -@pytest.mark.parametrize('app_path, target', [ - pytest.param( - f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', - 'esp32|esp32'), -], indirect=True) +@pytest.mark.parametrize('app_path, target, config', esp32_param_default, indirect=True) def test_sdio_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None: test_sdio_flow(dut) @@ -68,11 +77,7 @@ def test_sdio_speed_frhost_flow(dut:Tuple[IdfDut, IdfDut], expected_4b_speed:int @pytest.mark.esp32c6 @pytest.mark.sdio_multidev_32_c6 @pytest.mark.parametrize('count', [2,], indirect=True) -@pytest.mark.parametrize('app_path, target', [ - pytest.param( - f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', - 'esp32|esp32c6'), -], indirect=True) +@pytest.mark.parametrize('app_path, target, config', c6_param_default, indirect=True) def test_sdio_speed_frhost_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: test_sdio_speed_frhost_flow(dut, 10000, 4000) @@ -80,11 +85,7 @@ def test_sdio_speed_frhost_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: @pytest.mark.esp32 @pytest.mark.sdio_master_slave @pytest.mark.parametrize('count', [2,], indirect=True) -@pytest.mark.parametrize('app_path, target', [ - pytest.param( - f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', - 'esp32|esp32'), -], indirect=True) +@pytest.mark.parametrize('app_path, target, config', esp32_param_default, indirect=True) def test_sdio_speed_frhost_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None: test_sdio_speed_frhost_flow(dut, 12200, 4000) @@ -112,11 +113,7 @@ def test_sdio_speed_tohost_flow(dut:Tuple[IdfDut, IdfDut], expected_4b_speed:int @pytest.mark.esp32c6 @pytest.mark.sdio_multidev_32_c6 @pytest.mark.parametrize('count', [2,], indirect=True) -@pytest.mark.parametrize('app_path, target', [ - pytest.param( - f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', - 'esp32|esp32c6'), -], indirect=True) +@pytest.mark.parametrize('app_path, target, config', c6_param_default, indirect=True) def test_sdio_speed_tohost_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: test_sdio_speed_tohost_flow(dut, 9000, 4000) @@ -124,10 +121,27 @@ def test_sdio_speed_tohost_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: @pytest.mark.esp32 @pytest.mark.sdio_master_slave @pytest.mark.parametrize('count', [2,], indirect=True) -@pytest.mark.parametrize('app_path, target', [ - pytest.param( - f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}', - 'esp32|esp32'), -], indirect=True) +@pytest.mark.parametrize('app_path, target, config', esp32_param_default, indirect=True) def test_sdio_speed_tohost_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None: test_sdio_speed_tohost_flow(dut, 12200, 4000) + + +# Retention tests +def test_sdio_retention(dut:Tuple[IdfDut, IdfDut]) -> None: + dut[1].expect('Press ENTER to see the list of tests') + dut[1].write('[sdio_retention]') + dut[1].expect('test_sdio: slave ready') + + dut[0].expect('Press ENTER to see the list of tests') + dut[0].write('[sdio_retention]') + + dut[1].expect_unity_test_output() + dut[0].expect_unity_test_output() + + +@pytest.mark.esp32c6 +@pytest.mark.sdio_multidev_32_c6 +@pytest.mark.parametrize('count', [2,], indirect=True) +@pytest.mark.parametrize('app_path, target, config', c6_param_retention, indirect=True) +def test_sdio_retention_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None: + test_sdio_retention(dut) diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/CMakeLists.txt b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/CMakeLists.txt index 94e0034a58bb..0822f3336aed 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/CMakeLists.txt +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/CMakeLists.txt @@ -2,5 +2,5 @@ set(srcs "test_app_main.c" "test_sdio_slave.c") idf_component_register(SRCS ${srcs} - PRIV_REQUIRES test_driver_utils driver + PRIV_REQUIRES test_driver_utils driver esp_hw_support WHOLE_ARCHIVE) diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c index d91e19dd7ce5..6be681697dc6 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c @@ -305,6 +305,31 @@ TEST_CASE("SDIO_Slave: test to host", "[sdio]") test_to_host(); } +#if SOC_PAU_SUPPORTED +#include "esp_private/sleep_sys_periph.h" +#include "esp_private/sleep_retention.h" + +TEST_CASE("SDIO_Slave: test sleep retention", "[sdio_retention]") +{ + TEST_ASSERT_EQUAL_INT32(true, peripheral_domain_pd_allowed()); + sleep_retention_dump_modules(stdout); + + s_slave_init(SDIO_SLAVE_SEND_STREAM); + TEST_ESP_OK(sdio_slave_start()); + ESP_LOGI(TAG, "slave ready"); + + TEST_ASSERT_EQUAL_INT32(false, peripheral_domain_pd_allowed()); + sleep_retention_dump_modules(stdout); + + wait_for_finish(&s_test_slv_ctx); + + sdio_slave_stop(); + sdio_slave_deinit(); + + TEST_ASSERT_EQUAL_INT32(true, peripheral_domain_pd_allowed()); +} +#endif + TEST_CASE("SDIO_Slave: test to host (Performance)", "[sdio_speed]") { test_to_host(); diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.sleep_retention b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/sdkconfig.ci.sleep_retention similarity index 61% rename from components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.sleep_retention rename to components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/sdkconfig.ci.sleep_retention index 219e27e6b932..b9e39a383369 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.sleep_retention +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/sdkconfig.ci.sleep_retention @@ -1,5 +1,4 @@ CONFIG_PM_ENABLE=y CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y CONFIG_FREERTOS_USE_TICKLESS_IDLE=y -CONFIG_IEEE802154_ENABLED=y -CONFIG_IEEE802154_SLEEP_ENABLE=y diff --git a/components/esp_driver_sdm/src/sdm.c b/components/esp_driver_sdm/src/sdm.c index d5300a48ece8..9675e504b61a 100644 --- a/components/esp_driver_sdm/src/sdm.c +++ b/components/esp_driver_sdm/src/sdm.c @@ -29,6 +29,7 @@ #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) @@ -229,16 +230,12 @@ 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 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"); + 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 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; @@ -283,6 +280,7 @@ 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"); diff --git a/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py b/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py index a9b13fcfbb29..723b9b08abe0 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py +++ b/components/esp_driver_sdspi/test_apps/sdspi/pytest_sdspi.py @@ -4,6 +4,7 @@ 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 diff --git a/components/esp_driver_spi/include/driver/spi_common.h b/components/esp_driver_spi/include/driver/spi_common.h index c0c1918afdbc..2f4de6a121ae 100644 --- a/components/esp_driver_spi/include/driver/spi_common.h +++ b/components/esp_driver_spi/include/driver/spi_common.h @@ -64,6 +64,7 @@ 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 diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 7724af5a1cf5..1b51593d5728 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -21,6 +21,7 @@ #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" @@ -49,6 +50,7 @@ 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; @@ -587,7 +589,8 @@ 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_MASTER; //don't check this flag + missing_flag &= ~SPICOMMON_BUSFLAG_SLP_ALLOW_PD; if (missing_flag != 0) { //check pins existence @@ -778,6 +781,16 @@ 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) { @@ -846,6 +859,34 @@ 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); @@ -927,9 +968,24 @@ 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); diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index bc2ce1967f56..7237a0edebcf 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -345,8 +345,7 @@ 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); - int x; - for (x = 0; x < DEV_NUM_MAX; x++) { + for (int x = 0; x < DEV_NUM_MAX; x++) { SPI_CHECK(host->device[x] == NULL, "not all CSses freed", ESP_ERR_INVALID_STATE); } diff --git a/components/esp_driver_spi/test_apps/.build-test-rules.yml b/components/esp_driver_spi/test_apps/.build-test-rules.yml index 81f1c69c5cfb..9b605ff85528 100644 --- a/components/esp_driver_spi/test_apps/.build-test-rules.yml +++ b/components/esp_driver_spi/test_apps/.build-test-rules.yml @@ -9,19 +9,11 @@ components/esp_driver_spi/test_apps/master: disable: - if: SOC_GPSPI_SUPPORTED != 1 - disable_test: - - if: IDF_TARGET in ["esp32c61"] - temporary: true - reason: no multi-dev runner # TODO: [ESP32C61] IDF-10949 <<: *spi_depends_default components/esp_driver_spi/test_apps/param: disable: - if: SOC_GPSPI_SUPPORTED != 1 - disable_test: - - if: IDF_TARGET == "esp32p4" - temporary: true - reason: no multi-dev runner # TODO: [ESP32P4] IDF-9517 <<: *spi_depends_default components/esp_driver_spi/test_apps/slave: diff --git a/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h b/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h index 5dcb6f690f3e..2b68f9d04060 100644 --- a/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h +++ b/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h @@ -84,7 +84,7 @@ #elif CONFIG_IDF_TARGET_ESP32C61 #define IDF_PERFORMANCE_MAX_SPI_CLK_FREQ 40*1000*1000 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 32 -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 17 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 19 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 29 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 14 diff --git a/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt b/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt index 6af72ca6623a..cc99e1467afa 100644 --- a/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt +++ b/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt @@ -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 NOT CONFIG_COMPILER_DUMP_RTL_FILES) +if(CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2 AND CONFIG_SOC_SPI_SCT_SUPPORTED AND NOT CONFIG_COMPILER_DUMP_RTL_FILES) list(APPEND srcs "test_spi_master_sct.c") endif() diff --git a/components/esp_driver_spi/test_apps/master/main/test_spi_master.c b/components/esp_driver_spi/test_apps/master/main/test_spi_master.c index 4298dcdd222e..d08e8996bd71 100644 --- a/components/esp_driver_spi/test_apps/master/main/test_spi_master.c +++ b/components/esp_driver_spi/test_apps/master/main/test_spi_master.c @@ -19,6 +19,9 @@ #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" @@ -1251,6 +1254,7 @@ static void slave_only_tx_trans(uint8_t *slv_send_buf, uint32_t length) { ESP_LOGI(SLAVE_TAG, "FD DMA, Only TX"); spi_slave_transaction_t trans = {0}; + trans.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO; trans.tx_buffer = slv_send_buf; trans.length = length * 8; unity_send_signal("Slave ready"); @@ -1262,6 +1266,7 @@ static void slave_only_rx_trans(uint8_t *slv_recv_buf, uint8_t *mst_send_buf, ui { ESP_LOGI(SLAVE_TAG, "FD DMA, Only RX"); spi_slave_transaction_t trans = {}; + trans.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO; trans.tx_buffer = NULL; trans.rx_buffer = slv_recv_buf; trans.length = length * 8; @@ -1276,6 +1281,7 @@ static void slave_both_trans(uint8_t *slv_send_buf, uint8_t *slv_recv_buf, uint8 { ESP_LOGI(SLAVE_TAG, "FD DMA, Both TX and RX:"); spi_slave_transaction_t trans = {0}; + trans.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO; trans.tx_buffer = slv_send_buf; trans.rx_buffer = slv_recv_buf; trans.length = length * 8; @@ -1492,6 +1498,8 @@ TEST_CASE("spi_speed", "[spi]") #define DUMMY_CS_PINS() {25, 26, 27} #elif CONFIG_IDF_TARGET_ESP32H2 #define DUMMY_CS_PINS() {9, 10, 11, 12, 22, 25} +#elif CONFIG_IDF_TARGET_ESP32P4 +#define DUMMY_CS_PINS() {20, 21, 22, 23, 24, 25} #else #define DUMMY_CS_PINS() {0, 1, 4, 5, 8, 9} #endif //CONFIG_IDF_TARGET_ESP32 @@ -1575,6 +1583,7 @@ void test_add_device_slave(void) slave_trans.length = sizeof(slave_sendbuf) * 8; slave_trans.tx_buffer = slave_sendbuf; slave_trans.rx_buffer = slave_recvbuf; + slave_trans.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO; for (uint8_t i = 0; i < SOC_SPI_MAX_CS_NUM; i++) { memset(slave_recvbuf, 0, sizeof(slave_recvbuf)); @@ -1697,7 +1706,6 @@ static IRAM_ATTR void test_master_iram(void) spi_flash_enable_interrupts_caches_and_other_cpu(); ESP_LOG_BUFFER_HEX("master tx", ret_trans->tx_buffer, TEST_MASTER_IRAM_TRANS_LEN); - ESP_LOG_BUFFER_HEX("master rx", ret_trans->rx_buffer, TEST_MASTER_IRAM_TRANS_LEN); spitest_cmp_or_dump(master_exp, trans_cfg.rx_buffer, TEST_MASTER_IRAM_TRANS_LEN); // Test polling trans api once ------------------------------- @@ -1709,13 +1717,12 @@ static IRAM_ATTR void test_master_iram(void) spi_flash_enable_interrupts_caches_and_other_cpu(); ESP_LOG_BUFFER_HEX("master tx", ret_trans->tx_buffer, TEST_MASTER_IRAM_TRANS_LEN); - ESP_LOG_BUFFER_HEX("master rx", ret_trans->rx_buffer, TEST_MASTER_IRAM_TRANS_LEN); spitest_cmp_or_dump(master_exp, trans_cfg.rx_buffer, TEST_MASTER_IRAM_TRANS_LEN); free(master_send); free(master_recv); free(master_exp); - spi_bus_remove_device(dev_handle); + TEST_ESP_OK(spi_bus_remove_device(dev_handle)); spi_bus_free(TEST_SPI_HOST); } @@ -1733,20 +1740,19 @@ static void test_iram_slave_normal(void) slave_trans.length = TEST_MASTER_IRAM_TRANS_LEN * 8; slave_trans.tx_buffer = slave_sendbuf; slave_trans.rx_buffer = slave_recvbuf; + slave_trans.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO; test_fill_random_to_buffers_dualboard(211, slave_expect, slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN); unity_wait_for_signal("Master ready"); unity_send_signal("Slave ready"); - spi_slave_transmit(TEST_SPI_HOST, &slave_trans, portMAX_DELAY); + TEST_ESP_OK(spi_slave_transmit(TEST_SPI_HOST, &slave_trans, portMAX_DELAY)); ESP_LOG_BUFFER_HEX("slave tx", slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN); - ESP_LOG_BUFFER_HEX("slave rx", slave_recvbuf, TEST_MASTER_IRAM_TRANS_LEN); spitest_cmp_or_dump(slave_expect, slave_recvbuf, TEST_MASTER_IRAM_TRANS_LEN); unity_send_signal("Slave ready"); test_fill_random_to_buffers_dualboard(119, slave_expect, slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN); - spi_slave_transmit(TEST_SPI_HOST, &slave_trans, portMAX_DELAY); + TEST_ESP_OK(spi_slave_transmit(TEST_SPI_HOST, &slave_trans, portMAX_DELAY)); ESP_LOG_BUFFER_HEX("slave tx", slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN); - ESP_LOG_BUFFER_HEX("slave rx", slave_recvbuf, TEST_MASTER_IRAM_TRANS_LEN); spitest_cmp_or_dump(slave_expect, slave_recvbuf, TEST_MASTER_IRAM_TRANS_LEN); free(slave_sendbuf); @@ -1785,3 +1791,135 @@ 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 diff --git a/components/esp_driver_spi/test_apps/master/main/test_spi_master_sct.c b/components/esp_driver_spi/test_apps/master/main/test_spi_master_sct.c index 2efb4184d91a..d0e203704d35 100644 --- a/components/esp_driver_spi/test_apps/master/main/test_spi_master_sct.c +++ b/components/esp_driver_spi/test_apps/master/main/test_spi_master_sct.c @@ -15,6 +15,9 @@ #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" @@ -22,7 +25,6 @@ __attribute__((unused)) static const char *TAG = "SCT"; -#if (SOC_SPI_SUPPORT_SLAVE_HD_VER2 && SOC_SPI_SCT_SUPPORTED) /*----------------------------------------------------------- * HD SCT Functional Test *-----------------------------------------------------------*/ @@ -230,7 +232,6 @@ 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; @@ -291,4 +292,127 @@ TEST_CASE("spi_master: test_sct_dma_desc_oob_on_tail", "[spi]") TEST_ESP_OK(spi_bus_free(SPI2_HOST)); } -#endif //#if (SOC_SPI_SUPPORT_SLAVE_HD_VER2 && SOC_SPI_SCT_SUPPORTED) +/*----------------------------------------------------------- + * 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); diff --git a/components/esp_driver_spi/test_apps/master/pytest_spi_master.py b/components/esp_driver_spi/test_apps/master/pytest_spi_master.py index 1ac833a84ded..691929a135a2 100644 --- a/components/esp_driver_spi/test_apps/master/pytest_spi_master.py +++ b/components/esp_driver_spi/test_apps/master/pytest_spi_master.py @@ -5,7 +5,6 @@ # If `test_env` is define, should not run on generic runner @pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='test case fail') # TODO: [ESP32C61] IDF-10949 @pytest.mark.generic @pytest.mark.parametrize('config', ['defaults', 'release', 'freertos_compliance', 'freertos_flash',], indirect=True) def test_master_single_dev(case_tester) -> None: # type: ignore @@ -27,8 +26,8 @@ def test_master_esp_flash(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default -# TODO: [ESP32P4] IDF-9517 [ESP32C5] IDF-10322 [ESP32C61] IDF-10949 -@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5', 'esp32c61'], reason='no multi-dev runner') +# TODO: [ESP32C61] IDF-10949 +@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='no multi-dev runner') @pytest.mark.supported_targets @pytest.mark.generic_multi_device @pytest.mark.parametrize( diff --git a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.defaults b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.defaults deleted file mode 100644 index 250a29bc45bd..000000000000 --- a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.defaults +++ /dev/null @@ -1,2 +0,0 @@ -# don't delete. -# used for CI to compile a default config when 'sdkconfig.ci.xxxx' is exist diff --git a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.freertos_compliance b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.freertos_compliance index c3eaa50fa4b9..272fdd428529 100644 --- a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.freertos_compliance +++ b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.freertos_compliance @@ -1 +1,3 @@ +CONFIG_PM_ENABLE=y +CONFIG_FREERTOS_USE_TICKLESS_IDLE=y CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE=y diff --git a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release index 3cff15d49e20..ee9acb0df404 100644 --- a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release +++ b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release @@ -1,3 +1,4 @@ +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 diff --git a/components/esp_driver_spi/test_apps/master/sdkconfig.defaults b/components/esp_driver_spi/test_apps/master/sdkconfig.defaults index b308cb2ddda0..fff8c78591b1 100644 --- a/components/esp_driver_spi/test_apps/master/sdkconfig.defaults +++ b/components/esp_driver_spi/test_apps/master/sdkconfig.defaults @@ -1,2 +1,4 @@ CONFIG_FREERTOS_HZ=1000 -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_INIT=n +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/esp_driver_spi/test_apps/param/main/test_spi_param.c b/components/esp_driver_spi/test_apps/param/main/test_spi_param.c index 627f4ad492a3..71506acb752e 100644 --- a/components/esp_driver_spi/test_apps/param/main/test_spi_param.c +++ b/components/esp_driver_spi/test_apps/param/main/test_spi_param.c @@ -109,6 +109,10 @@ static void local_test_start(spi_device_handle_t *spi, int freq, const spitest_p devcfg.flags |= SPI_DEVICE_NO_DUMMY; } +#if CONFIG_IDF_TARGET_ESP32P4 //TODO: IDF-8313, update P4 defaulte clock source + devcfg.clock_source = SPI_CLK_SRC_SPLL; +#endif + //slave config slvcfg.mode = pset->mode; slave_pull_up(&buscfg, slvcfg.spics_io_num); @@ -192,6 +196,7 @@ static void local_test_loop(const void *arg1, void *arg2) .tx_buffer = txdata->start, .rx_buffer = recvbuf, .length = txdata->len, + .flags = SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, }; esp_err_t err = spi_slave_queue_trans(TEST_SLAVE_HOST, &slave_trans, portMAX_DELAY); TEST_ESP_OK(err); @@ -247,8 +252,7 @@ static void local_test_loop(const void *arg1, void *arg2) /************ Timing Test ***********************************************/ //TODO: esp32s2 has better timing performance static spitest_param_set_t timing_pgroup[] = { -//signals are not fed to peripherals through iomux if the functions are not selected to iomux -#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) +#if (SLAVE_IOMUX_PIN_MISO != -1) //SPI3 slave has iomux pin { .pset_name = "FULL_DUP, MASTER IOMUX", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, @@ -277,8 +281,7 @@ static spitest_param_set_t timing_pgroup[] = { .slave_iomux = false, .slave_tv_ns = TV_INT_CONNECT_GPIO, }, -//signals are not fed to peripherals through iomux if the functions are not selected to iomux -#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) +#if (SLAVE_IOMUX_PIN_MISO != -1) //SPI3 slave has iomux pin { .pset_name = "MISO_DUP, MASTER IOMUX", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, @@ -307,8 +310,7 @@ static spitest_param_set_t timing_pgroup[] = { .slave_iomux = false, .slave_tv_ns = TV_INT_CONNECT_GPIO, }, -//signals are not fed to peripherals through iomux if the functions are not selected to iomux -#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) +#if (SLAVE_IOMUX_PIN_MISO != -1) //SPI3 slave has iomux pin { .pset_name = "MOSI_DUP, MASTER IOMUX", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, @@ -616,7 +618,8 @@ TEST_CASE("Slave receive correct data", "[spi]") spi_slave_transaction_t slave_trans = { .length = slave_trans_len * 8, .tx_buffer = slave_sendbuf, - .rx_buffer = slave_recvbuf + .rx_buffer = slave_recvbuf, + .flags = SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, }; esp_err_t ret = spi_slave_queue_trans(TEST_SLAVE_HOST, &slave_trans, portMAX_DELAY); TEST_ESP_OK(ret); @@ -1270,7 +1273,9 @@ static int s_spi_bus_freq[] = { IDF_PERFORMANCE_MAX_SPI_CLK_FREQ / 7, IDF_PERFORMANCE_MAX_SPI_CLK_FREQ / 4, IDF_PERFORMANCE_MAX_SPI_CLK_FREQ / 2, +#if !CONFIG_IDF_TARGET_ESP32P4 //TODO: IDF-8313, update P4 defaulte clock source IDF_PERFORMANCE_MAX_SPI_CLK_FREQ, +#endif }; //------------------------------------------- Full Duplex with DMA Freq test -------------------------------------- @@ -1483,6 +1488,7 @@ static void test_slave_fd_no_dma(void) .tx_buffer = slave_send, .rx_buffer = slave_receive, .length = test_trans_len * 8, + .flags = SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, }; unity_send_signal("Slave ready"); TEST_ESP_OK(spi_slave_transmit(TEST_SPI_HOST, &trans_cfg, portMAX_DELAY)); @@ -1587,6 +1593,7 @@ static void test_slave_hd_dma(void) TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &slave_trans, portMAX_DELAY)); slave_trans.data = slave_receive; TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &slave_trans, portMAX_DELAY)); + TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY)); TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY)); ESP_LOG_BUFFER_HEX("slave tx", slave_send, test_trans_len); @@ -1688,6 +1695,7 @@ static void test_slave_hd_no_dma(void) TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &slave_trans, portMAX_DELAY)); slave_trans.data = slave_receive; TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &slave_trans, portMAX_DELAY)); + TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY)); TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY)); ESP_LOG_BUFFER_HEX("slave tx", slave_send, test_trans_len); @@ -1951,6 +1959,7 @@ static void test_slave_sio_no_dma(void) .length = SOC_SPI_MAXIMUM_BUFFER_SIZE * 8, .tx_buffer = slave_send, .rx_buffer = slave_receive, + .flags = SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, }; unity_send_signal("Slave ready"); TEST_ESP_OK(spi_slave_transmit(TEST_SPI_HOST, &trans, portMAX_DELAY)); diff --git a/components/esp_driver_spi/test_apps/param/pytest_spi_param.py b/components/esp_driver_spi/test_apps/param/pytest_spi_param.py index d565235e9c8c..d7df69641062 100644 --- a/components/esp_driver_spi/test_apps/param/pytest_spi_param.py +++ b/components/esp_driver_spi/test_apps/param/pytest_spi_param.py @@ -4,9 +4,7 @@ # If `test_env` is define, should not run on generic runner -@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942 @pytest.mark.supported_targets -@pytest.mark.esp32h2 @pytest.mark.generic def test_param_single_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: @@ -16,10 +14,9 @@ def test_param_single_dev(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default -# TODO: [ESP32P4] IDF-8942 [ESP32C5] IDF-10322 [ESP32C61] IDF-10949 -@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5', 'esp32c61'], reason='no multi-dev runner') +# TODO: [ESP32C61] IDF-10949 +@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='no multi-dev runner') @pytest.mark.supported_targets -@pytest.mark.esp32h2 @pytest.mark.generic_multi_device @pytest.mark.parametrize('count', [2,], indirect=True) def test_param_multi_dev(case_tester) -> None: # type: ignore diff --git a/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c b/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c index 8a27902e716d..46537168210b 100644 --- a/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c +++ b/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c @@ -562,6 +562,7 @@ static IRAM_ATTR void test_slave_isr_iram(void) } TEST_CASE_MULTIPLE_DEVICES("SPI_Slave: Test_ISR_IRAM_disable_cache", "[spi_ms]", test_slave_iram_master_normal, test_slave_isr_iram); +#if !SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE //isr option is not supported in this condition static uint32_t isr_trans_cnt, isr_trans_test_fail; static IRAM_ATTR void test_trans_in_isr_post_trans_cbk(spi_slave_transaction_t *curr_trans) { @@ -725,6 +726,7 @@ static IRAM_ATTR void spi_queue_reset_in_isr(void) spi_slave_free(TEST_SPI_HOST); } TEST_CASE_MULTIPLE_DEVICES("SPI_Slave: Test_Queue_Reset_in_ISR", "[spi_ms]", test_slave_iram_master_normal, spi_queue_reset_in_isr); +#endif // SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE #endif // CONFIG_SPI_SLAVE_ISR_IN_IRAM #if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE) diff --git a/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py b/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py index b39e7f948471..5b9f8823dc2d 100644 --- a/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py +++ b/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py @@ -15,8 +15,8 @@ def test_slave_single_dev(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default -# TODO: [ESP32P4] IDF-9517 [ESP32C5] IDF-10322 [ESP32C61] IDF-10949 -@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5', 'esp32c61'], reason='no multi-dev runner') +# TODO: [ESP32C61] IDF-10949 +@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='no multi-dev runner') @pytest.mark.supported_targets @pytest.mark.generic_multi_device @pytest.mark.parametrize('count, config', [(2, 'defaults'), (2, 'iram_safe')], indirect=True) diff --git a/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c b/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c index 397a30f4a1a6..eea77e52c339 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c +++ b/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -855,19 +855,23 @@ static void hd_slave_quad(void) { .data = slave_recv_buf, .len = (trans_len + 3) & (~3), + .flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, }, { .data = slave_recv_buf + BUF_SIZE / 2, .len = (trans_len + 3) & (~3), + .flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, }, //send { .data = slave_send_buf, .len = (trans_len + 3) & (~3), + .flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, }, { .data = slave_send_buf + BUF_SIZE / 2, .len = (trans_len + 3) & (~3), + .flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, }, }; @@ -901,7 +905,7 @@ static void hd_slave_quad(void) spi_slave_hd_deinit(TEST_SLAVE_HOST); } -TEST_CASE_MULTIPLE_DEVICES("SPI quad hd test ", "[spi_ms][test_env=generic_multi_device]", hd_master_quad, hd_slave_quad); +TEST_CASE_MULTIPLE_DEVICES("SPI quad hd test", "[spi_ms][test_env=generic_multi_device]", hd_master_quad, hd_slave_quad); #endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) @@ -941,6 +945,7 @@ void slave_run_append(void) slave_rx_trans[append_idx].data = heap_caps_aligned_calloc(4, 1, TEST_TRANS_LEN, MALLOC_CAP_DMA); TEST_ASSERT_NOT_NULL(slave_rx_trans[append_idx].data); slave_rx_trans[append_idx].len = trans_len; + slave_rx_trans[append_idx].flags |= SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO; TEST_ESP_OK(spi_slave_hd_append_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &slave_rx_trans[append_idx], portMAX_DELAY)); } @@ -982,6 +987,7 @@ void slave_run_append(void) } slave_tx_trans[append_idx].data = slave_rx_trans[append_idx].data; slave_tx_trans[append_idx].len = trans_len; + slave_tx_trans[append_idx].flags |= SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO; prepare_data(slave_tx_trans[append_idx].data, trans_len, -3); TEST_ESP_OK(spi_slave_hd_append_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &slave_tx_trans[append_idx], portMAX_DELAY)); } diff --git a/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py b/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py index d84705884604..5d09b75f069d 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py +++ b/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py @@ -26,8 +26,10 @@ def test_slave_hd_single_dev(case_tester) -> None: # type: ignore @pytest.mark.esp32s3 @pytest.mark.esp32c2 @pytest.mark.esp32c3 +@pytest.mark.esp32c5 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic_multi_device @pytest.mark.parametrize('count', [2,], indirect=True) def test_slave_hd_multi_dev(case_tester) -> None: # type: ignore diff --git a/components/esp_driver_touch_sens/hw_ver3/touch_version_specific.c b/components/esp_driver_touch_sens/hw_ver3/touch_version_specific.c index ebf9acecdd6a..e9335d39652b 100644 --- a/components/esp_driver_touch_sens/hw_ver3/touch_version_specific.c +++ b/components/esp_driver_touch_sens/hw_ver3/touch_version_specific.c @@ -331,8 +331,9 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co ESP_ERR_INVALID_ARG, err, TAG, "Invalid sleep level"); /* Enabled touch sensor as wake-up source */ ESP_GOTO_ON_ERROR(esp_sleep_enable_touchpad_wakeup(), err, TAG, "Failed to enable touch sensor wakeup"); -#if SOC_PM_SUPPORT_RC_FAST_PD - ESP_GOTO_ON_ERROR(esp_sleep_pd_config(ESP_PD_DOMAIN_RC_FAST, ESP_PD_OPTION_ON), err, TAG, "Failed to keep touch sensor module clock during the sleep"); +#if SOC_PM_SUPPORT_RTC_PERIPH_PD + // Keep ESP_PD_DOMAIN_RTC_PERIPH power domain on during the light/deep sleep, so that to keep the touch sensor working + ESP_GOTO_ON_ERROR(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON), err, TAG, "Failed to keep touch sensor module clock during the sleep"); #endif /* If set the deep sleep channel (i.e., enable deep sleep wake-up), @@ -360,10 +361,10 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co } else { /* Disable the touch sensor as wake-up source */ esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TOUCHPAD); -#if SOC_PM_SUPPORT_RC_FAST_PD - esp_sleep_pd_config(ESP_PD_DOMAIN_RC_FAST, ESP_PD_OPTION_AUTO); +#if SOC_PM_SUPPORT_RTC_PERIPH_PD + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO); #endif - + sens_handle->deep_slp_chan = NULL; sens_handle->sleep_en = false; } diff --git a/components/esp_driver_tsens/include/driver/temperature_sensor.h b/components/esp_driver_tsens/include/driver/temperature_sensor.h index 3c2c18dc1c5f..fc968dfb0fa0 100644 --- a/components/esp_driver_tsens/include/driver/temperature_sensor.h +++ b/components/esp_driver_tsens/include/driver/temperature_sensor.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,12 @@ typedef struct { int range_min; /**< the minimum value of the temperature you want to test */ int range_max; /**< the maximum value of the temperature you want to test */ temperature_sensor_clk_src_t clk_src; /**< the clock source of the temperature sensor. */ + struct { + uint32_t allow_pd; /**< If set, the driver will backup/restore the temperature sensor registers before/after entering/exist sleep mode. + By this approach, the system can power off temperature sensor's power domain. + This can save power, but at the expense of more RAM being consumed */ + } flags; /**< Temperature sensor config flags */ + } temperature_sensor_config_t; /** diff --git a/components/esp_driver_tsens/src/temperature_sensor.c b/components/esp_driver_tsens/src/temperature_sensor.c index 2bf39ca9bf28..39e44afb9b57 100644 --- a/components/esp_driver_tsens/src/temperature_sensor.c +++ b/components/esp_driver_tsens/src/temperature_sensor.c @@ -29,6 +29,9 @@ #include "soc/temperature_sensor_periph.h" #include "esp_memory_utils.h" #include "esp_private/sar_periph_ctrl.h" +#if TEMPERATURE_SENSOR_USE_RETENTION_LINK +#include "esp_private/sleep_retention.h" +#endif static const char *TAG = "temperature_sensor"; @@ -93,6 +96,26 @@ static void IRAM_ATTR temperature_sensor_isr(void *arg) } #endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT +#if TEMPERATURE_SENSOR_USE_RETENTION_LINK +static esp_err_t s_temperature_sensor_sleep_retention_init(void *arg) +{ + esp_err_t ret = sleep_retention_entries_create(temperature_sensor_regs_retention.link_list, temperature_sensor_regs_retention.link_num, REGDMA_LINK_PRI_TEMPERATURE_SENSOR, temperature_sensor_regs_retention.module_id); + ESP_RETURN_ON_ERROR(ret, TAG, "failed to allocate mem for sleep retention"); + return ret; +} + +void temperature_sensor_create_retention_module(temperature_sensor_handle_t tsens) +{ + sleep_retention_module_t module_id = temperature_sensor_regs_retention.module_id; + 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_id create failed, temperature sensor driver should still work, so just warning here + ESP_LOGW(TAG, "create retention link failed, power domain won't be turned off during sleep"); + } + } +} +#endif // TEMPERATURE_SENSOR_USE_RETENTION_LINK + esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_config, temperature_sensor_handle_t *ret_tsens) { #if CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG @@ -110,6 +133,24 @@ esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_co tsens->clk_src = tsens_config->clk_src; } +#if !SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + ESP_RETURN_ON_FALSE(tsens_config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep"); +#endif // SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + +#if TEMPERATURE_SENSOR_USE_RETENTION_LINK + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = s_temperature_sensor_sleep_retention_init, .arg = (void *)tsens } } + }; + ret = sleep_retention_module_init(temperature_sensor_regs_retention.module_id, &init_param); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "init sleep retention failed, power domain may be turned off during sleep"); + } + + if (tsens_config->flags.allow_pd != 0) { + temperature_sensor_create_retention_module(tsens); + } +#endif // TEMPERATURE_SENSOR_USE_RETENTION_LINK + temperature_sensor_power_acquire(); temperature_sensor_ll_clk_sel(tsens->clk_src); @@ -147,6 +188,17 @@ esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens) ESP_RETURN_ON_ERROR(esp_intr_free(tsens->temp_sensor_isr_handle), TAG, "uninstall interrupt service failed"); } #endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT + +#if TEMPERATURE_SENSOR_USE_RETENTION_LINK + sleep_retention_module_t module_id = temperature_sensor_regs_retention.module_id; + if (sleep_retention_get_created_modules() & BIT(module_id)) { + sleep_retention_module_free(temperature_sensor_regs_retention.module_id); + } + if (sleep_retention_get_inited_modules() & BIT(module_id)) { + sleep_retention_module_deinit(temperature_sensor_regs_retention.module_id); + } +#endif // TEMPERATURE_SENSOR_USE_RETENTION_LINK + temperature_sensor_power_release(); free(tsens); diff --git a/components/esp_driver_tsens/src/temperature_sensor_private.h b/components/esp_driver_tsens/src/temperature_sensor_private.h index b511505ffba8..28b84be5f8e0 100644 --- a/components/esp_driver_tsens/src/temperature_sensor_private.h +++ b/components/esp_driver_tsens/src/temperature_sensor_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,9 @@ typedef enum { #define TEMPERATURE_SENSOR_MEM_ALLOC_CAPS (MALLOC_CAP_DEFAULT) #endif +// Use retention link only when the target supports sleep retention and PM is enabled +#define TEMPERATURE_SENSOR_USE_RETENTION_LINK (SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN) + typedef struct temperature_sensor_obj_t temperature_sensor_obj_t; struct temperature_sensor_obj_t { diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/main/CMakeLists.txt b/components/esp_driver_tsens/test_apps/temperature_sensor/main/CMakeLists.txt index 5d45e0615adc..57b6fd425c69 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/main/CMakeLists.txt +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/main/CMakeLists.txt @@ -9,5 +9,5 @@ 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} - PRIV_REQUIRES unity esp_wifi test_utils nvs_flash esp_driver_tsens esp_driver_gpio + PRIV_REQUIRES unity esp_wifi test_utils nvs_flash esp_driver_tsens esp_driver_gpio esp_pm WHOLE_ARCHIVE) diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.c b/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.c index 6bc7fe4e86ea..15b38613c8b6 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.c +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,11 @@ #include "freertos/task.h" #include "soc/soc_caps.h" #include "unity_test_utils_cache.h" +#include "esp_sleep.h" +#include "esp_private/sleep_cpu.h" +#include "esp_pm.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" TEST_CASE("Temperature_sensor_driver_workflow_test", "[temperature_sensor]") { @@ -146,3 +151,59 @@ TEST_CASE("Temperature sensor callback test", "[temperature_sensor]") } #endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT + +#if SOC_LIGHT_SLEEP_SUPPORTED && CONFIG_PM_ENABLE +static void test_temperature_sensor_sleep_retention(bool allow_pd) +{ + printf("Initializing Temperature sensor\n"); + float tsens_result0; + float tsens_result1; + temperature_sensor_config_t temp_sensor = { + .range_min = 10, + .range_max = 50, + .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT, + .flags.allow_pd = allow_pd, + }; + temperature_sensor_handle_t temp_handle = NULL; + TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_OK(temperature_sensor_enable(temp_handle)); + printf("Temperature sensor started\n"); + TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_result0)); + printf("Temperature out celsius %f°C\n", tsens_result0); + + 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)); + TEST_ESP_OK(esp_light_sleep_start()); +#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_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN + // 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); +#elif CONFIG_IDF_TARGET_ESP32P4 + TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); +#endif + + TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_result1)); + printf("Temperature out celsius %f°C\n", tsens_result1); + TEST_ASSERT_FLOAT_WITHIN(6.0, tsens_result0, tsens_result1); + + TEST_ESP_OK(temperature_sensor_disable(temp_handle)); + TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); +} + +TEST_CASE("temperature sensor sleep retention test", "[temperature_sensor]") +{ + test_temperature_sensor_sleep_retention(false); +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + test_temperature_sensor_sleep_retention(true); +#endif +} +#endif diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.ci.release b/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.ci.release index 91d93f163e62..eb643d4d06bc 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.ci.release +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.ci.release @@ -1,4 +1,5 @@ CONFIG_PM_ENABLE=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y CONFIG_FREERTOS_USE_TICKLESS_IDLE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.defaults b/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.defaults index e4bfc208a55b..a89cab2af3bf 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.defaults +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.defaults @@ -1 +1,3 @@ CONFIG_ESP_TASK_WDT_EN=n +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/esp_driver_uart/include/driver/uart.h b/components/esp_driver_uart/include/driver/uart.h index aeb0176bfd1f..2d090ba10a76 100644 --- a/components/esp_driver_uart/include/driver/uart.h +++ b/components/esp_driver_uart/include/driver/uart.h @@ -47,9 +47,9 @@ typedef struct { #endif }; struct { - 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 */ + 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 */ } flags; /*!< Configuration flags */ } uart_config_t; diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index c8f5436ad2d0..0008bdbc96b9 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -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_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + sleep_retention_module_t module = uart_reg_retention_info[uart_num].module; 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_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + sleep_retention_module_t module = uart_reg_retention_info[uart_num].module; 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,8 +856,9 @@ 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(uart_config->flags.backup_before_sleep == 0, ESP_ERR_NOT_SUPPORTED, UART_TAG, "register back up is not supported"); + ESP_RETURN_ON_FALSE(allow_pd == 0, ESP_ERR_NOT_SUPPORTED, UART_TAG, "not able to power down in light sleep"); #endif uart_module_enable(uart_num); @@ -866,8 +867,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_LL_SLEEP_RETENTION_MODULE_ID(uart_num); - if (uart_config->flags.backup_before_sleep && !uart_context[uart_num].retention_link_created) { + sleep_retention_module_t module = uart_reg_retention_info[uart_num].module; + if (allow_pd && !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; @@ -878,7 +879,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 (!uart_config->flags.backup_before_sleep && uart_context[uart_num].retention_link_created) { + } else if (!allow_pd && 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; @@ -1805,7 +1806,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_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + sleep_retention_module_t module = uart_reg_retention_info[uart_num].module; _lock_acquire(&(uart_context[uart_num].mutex)); if (uart_context[uart_num].retention_link_created) { assert(uart_context[uart_num].retention_link_inited); @@ -1979,7 +1980,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_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + sleep_retention_module_t module = uart_reg_retention_info[uart_num].module; 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); diff --git a/components/esp_driver_uart/test_apps/uart/main/test_uart_retention.c b/components/esp_driver_uart/test_apps/uart/main/test_uart_retention.c index 692d24f72f84..d230a84987ae 100644 --- a/components/esp_driver_uart/test_apps/uart/main/test_uart_retention.c +++ b/components/esp_driver_uart/test_apps/uart/main/test_uart_retention.c @@ -17,7 +17,7 @@ static const uart_port_t uart_num = UART_NUM_1; -static void uart_init(bool backup_before_sleep) +static void uart_init(bool allow_pd) { uart_config_t uart_config = { .baud_rate = 115200, @@ -26,7 +26,7 @@ static void uart_init(bool backup_before_sleep) .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .source_clk = UART_SCLK_DEFAULT, - .flags.backup_before_sleep = backup_before_sleep, + .flags.allow_pd = allow_pd, }; 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); // backup_before_sleep set to false, sleep retention module will be inited, but not created + uart_init(false); // allow_pd 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)); diff --git a/components/esp_eth/CMakeLists.txt b/components/esp_eth/CMakeLists.txt index b432f557810f..696ed432420b 100644 --- a/components/esp_eth/CMakeLists.txt +++ b/components/esp_eth/CMakeLists.txt @@ -30,6 +30,7 @@ if(CONFIG_ETH_ENABLED) list(APPEND srcs "src/mac/esp_eth_mac_esp.c" "src/mac/esp_eth_mac_esp_dma.c" "src/mac/esp_eth_mac_esp_gpio.c" + "src/phy/esp_eth_phy_generic.c" "src/phy/esp_eth_phy_dp83848.c" "src/phy/esp_eth_phy_ip101.c" "src/phy/esp_eth_phy_ksz80xx.c" diff --git a/components/esp_eth/include/esp_eth_phy.h b/components/esp_eth/include/esp_eth_phy.h index 5613b8749744..d551c6270a3c 100644 --- a/components/esp_eth/include/esp_eth_phy.h +++ b/components/esp_eth/include/esp_eth_phy.h @@ -13,7 +13,8 @@ extern "C" { #endif -#define ESP_ETH_PHY_ADDR_AUTO (-1) +#define ESP_ETH_PHY_ADDR_AUTO (-1) +#define ESP_ETH_NO_POST_HW_RESET_DELAY (-1) /** * @brief Auto-negotiation control commands @@ -273,24 +274,45 @@ struct esp_eth_phy_s { * */ typedef struct { - int32_t phy_addr; /*!< PHY address, set -1 to enable PHY address detection at initialization stage */ - uint32_t reset_timeout_ms; /*!< Reset timeout value (Unit: ms) */ - uint32_t autonego_timeout_ms; /*!< Auto-negotiation timeout value (Unit: ms) */ - int reset_gpio_num; /*!< Reset GPIO number, -1 means no hardware reset */ + int32_t phy_addr; /*!< PHY address, set -1 to enable PHY address detection at initialization stage */ + uint32_t reset_timeout_ms; /*!< Reset timeout value (Unit: ms) */ + uint32_t autonego_timeout_ms; /*!< Auto-negotiation timeout value (Unit: ms) */ + int reset_gpio_num; /*!< Reset GPIO number, -1 means no hardware reset */ + int32_t hw_reset_assert_time_us; /*!< Time the reset pin is asserted (Unit: us), 0 to use chip specific default */ + int32_t post_hw_reset_delay_ms; /*!< Time to wait after the HW reset (Unit: ms), 0 to use chip specific default, -1 means no wait */ } eth_phy_config_t; /** * @brief Default configuration for Ethernet PHY object * */ -#define ETH_PHY_DEFAULT_CONFIG() \ - { \ - .phy_addr = ESP_ETH_PHY_ADDR_AUTO, \ - .reset_timeout_ms = 100, \ - .autonego_timeout_ms = 4000, \ - .reset_gpio_num = 5, \ +#define ETH_PHY_DEFAULT_CONFIG() \ + { \ + .phy_addr = ESP_ETH_PHY_ADDR_AUTO, \ + .reset_timeout_ms = 100, \ + .autonego_timeout_ms = 4000, \ + .reset_gpio_num = 5, \ + .hw_reset_assert_time_us = 0, \ + .post_hw_reset_delay_ms = 0 \ } +/** +* @brief Create a PHY instance of generic chip which conforms with IEEE 802.3 +* +* @note Default reset timing configuration is set conservatively( @c DEFAULT_PHY_RESET_ASSERTION_TIME_US ). +* If you need faster response and your chip supports it, configure it via @c config parameter. +* +* @warning While basic functionality should always work, some specific features might be limited, +* even if the PHY meets IEEE 802.3 standard. A typical example is loopback functionality, +* where certain PHYs may require setting a specific speed mode to operate correctly. +* +* @param[in] config configuration of PHY +* @return +* - instance: create PHY instance successfully +* - NULL: create PHY instance failed because some error occurred + */ +esp_eth_phy_t *esp_eth_phy_new_generic(const eth_phy_config_t *config); + /** * @brief Create a PHY instance of IP101 * diff --git a/components/esp_eth/include/esp_eth_phy_802_3.h b/components/esp_eth/include/esp_eth_phy_802_3.h index 0cc83ed1390c..e90646bd37d8 100644 --- a/components/esp_eth/include/esp_eth_phy_802_3.h +++ b/components/esp_eth/include/esp_eth_phy_802_3.h @@ -19,13 +19,15 @@ extern "C" { * */ typedef struct { - esp_eth_phy_t parent; /*!< Parent Ethernet PHY instance */ - esp_eth_mediator_t *eth; /*!< Mediator of Ethernet driver */ - int addr; /*!< PHY address */ - uint32_t reset_timeout_ms; /*!< Reset timeout value (Unit: ms) */ - uint32_t autonego_timeout_ms; /*!< Auto-negotiation timeout value (Unit: ms) */ - eth_link_t link_status; /*!< Current Link status */ - int reset_gpio_num; /*!< Reset GPIO number, -1 means no hardware reset */ + esp_eth_phy_t parent; /*!< Parent Ethernet PHY instance */ + esp_eth_mediator_t *eth; /*!< Mediator of Ethernet driver */ + int addr; /*!< PHY address */ + uint32_t reset_timeout_ms; /*!< Reset timeout value (Unit: ms) */ + uint32_t autonego_timeout_ms; /*!< Auto-negotiation timeout value (Unit: ms) */ + eth_link_t link_status; /*!< Current Link status */ + int reset_gpio_num; /*!< Reset GPIO number, -1 means no hardware reset */ + int32_t hw_reset_assert_time_us; /*!< Time the reset pin is asserted (Unit: us) */ + int32_t post_hw_reset_delay_ms; /*!< Time to wait after the HW reset (Unit: ms) */ } phy_802_3_t; /** @@ -73,6 +75,16 @@ esp_err_t esp_eth_phy_802_3_reset(phy_802_3_t *phy_802_3); */ esp_err_t esp_eth_phy_802_3_autonego_ctrl(phy_802_3_t *phy_802_3, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat); +/** + * @brief Retrieve link status and propagate the status to higher layers if the status changed + * + * @param phy_802_3 IEEE 802.3 PHY object infostructure + * @return + * - ESP_OK: Ethernet PHY link status retrieved successfully + * - ESP_FAIL: Error occurred during reading registry + */ +esp_err_t esp_eth_phy_802_3_updt_link_dup_spd(phy_802_3_t *phy_802_3); + /** * @brief Power control of Ethernet PHY * @@ -183,7 +195,7 @@ esp_err_t esp_eth_phy_802_3_deinit(phy_802_3_t *phy_802_3); * * @param phy_802_3 IEEE 802.3 PHY object infostructure * @return - * - ESP_OK: Ethrnet PHY infostructure deleted + * - ESP_OK: Ethernet PHY infostructure deleted */ esp_err_t esp_eth_phy_802_3_del(phy_802_3_t *phy_802_3); @@ -194,6 +206,7 @@ esp_err_t esp_eth_phy_802_3_del(phy_802_3_t *phy_802_3); * @param reset_assert_us Hardware reset pin assertion time * @return * - ESP_OK: reset Ethernet PHY successfully + * - ESP_ERR_NOT_ALLOWED: reset GPIO not defined */ esp_err_t esp_eth_phy_802_3_reset_hw(phy_802_3_t *phy_802_3, uint32_t reset_assert_us); diff --git a/components/esp_eth/src/phy/esp_eth_phy_802_3.c b/components/esp_eth/src/phy/esp_eth_phy_802_3.c index f120821187f1..b0c22cb53f46 100644 --- a/components/esp_eth/src/phy/esp_eth_phy_802_3.c +++ b/components/esp_eth/src/phy/esp_eth_phy_802_3.c @@ -16,11 +16,14 @@ #include "esp_rom_sys.h" #include "esp_eth_phy_802_3.h" -// Default reset assertion time is selected to be 100us as it is most commonly used value among PHY chips. +// Default reset assertion time is selected to be 100us as it is most commonly used value among ESP-IDF supported PHY chips. #define PHY_RESET_ASSERTION_TIME_US 100 static const char *TAG = "eth_phy_802_3"; +// TODO: IDF-11362 (should be renamed to esp_eth_phy_802_3_reset_hw with the next major release) +static esp_err_t esp_eth_phy_802_3_reset_hw_internal(phy_802_3_t *phy_802_3); + static esp_err_t set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth) { phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); @@ -33,10 +36,10 @@ static esp_err_t reset(esp_eth_phy_t *phy) return esp_eth_phy_802_3_reset(phy_802_3); } -static esp_err_t reset_hw_default(esp_eth_phy_t *phy) +static esp_err_t reset_hw(esp_eth_phy_t *phy) { phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); - return esp_eth_phy_802_3_reset_hw(phy_802_3, PHY_RESET_ASSERTION_TIME_US); + return esp_eth_phy_802_3_reset_hw_internal(phy_802_3); } static esp_err_t autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat) @@ -93,6 +96,14 @@ static esp_err_t set_link(esp_eth_phy_t *phy, eth_link_t link) return esp_eth_phy_802_3_set_link(phy_802_3, link); } +static esp_err_t get_link(esp_eth_phy_t *phy) +{ + phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); + + /* Update information about link, speed, duplex */ + return esp_eth_phy_802_3_updt_link_dup_spd(phy_802_3); +} + static esp_err_t init(esp_eth_phy_t *phy) { phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); @@ -143,21 +154,6 @@ esp_err_t esp_eth_phy_802_3_reset(phy_802_3_t *phy_802_3) return ret; } -/** - * @brief PHY hardware reset with default assert time - * - * @note Default reset assertion time is selected to be 100us as it is most commonly used value among PHY chips. - * If your PHY chip requires different value, redefine the `reset_hw` function in derived PHY specific driver structure. - * - * @param phy Ethernet PHY instance - * @return - * - ESP_OK on success - */ -esp_err_t esp_eth_phy_802_3_reset_hw_default(phy_802_3_t *phy_802_3) -{ - return esp_eth_phy_802_3_reset_hw(phy_802_3, PHY_RESET_ASSERTION_TIME_US); -} - esp_err_t esp_eth_phy_802_3_autonego_ctrl(phy_802_3_t *phy_802_3, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat) { esp_err_t ret = ESP_OK; @@ -220,6 +216,67 @@ esp_err_t esp_eth_phy_802_3_autonego_ctrl(phy_802_3_t *phy_802_3, eth_phy_autone return ret; } +esp_err_t esp_eth_phy_802_3_updt_link_dup_spd(phy_802_3_t *phy_802_3) +{ + esp_err_t ret = ESP_OK; + esp_eth_mediator_t *eth = phy_802_3->eth; + uint32_t addr = phy_802_3->addr; + eth_speed_t speed = ETH_SPEED_10M; + eth_duplex_t duplex = ETH_DUPLEX_HALF; + uint32_t peer_pause_ability = false; + bmcr_reg_t bmcr; + bmsr_reg_t bmsr; + anar_reg_t anar; + anlpar_reg_t anlpar; + + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed"); + eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN; + /* check if link status changed */ + if (phy_802_3->link_status != link) { + /* when link up, read negotiation result */ + if (link == ETH_LINK_UP) { + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANAR_REG_ADDR, &(anar.val)), err, TAG, "read ANAR failed"); + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed"); + if (bmcr.en_auto_nego) { + if (anar.base100_tx_fd && anlpar.base100_tx_fd) { + speed = ETH_SPEED_100M; + duplex = ETH_DUPLEX_FULL; + } else if (anar.base100_tx && anlpar.base100_tx) { + speed = ETH_SPEED_100M; + duplex = ETH_DUPLEX_HALF; + } else if (anar.base10_t_fd && anlpar.base10_t_fd) { + speed = ETH_SPEED_10M; + duplex = ETH_DUPLEX_FULL; + } else if (anar.base10_t && anlpar.base10_t) { + speed = ETH_SPEED_10M; + duplex = ETH_DUPLEX_HALF; + } else { + ESP_GOTO_ON_FALSE(false, ESP_FAIL, err, TAG, "invalid auto-nego speed/duplex advertising"); + } + } else { + speed = bmcr.speed_select ? ETH_SPEED_100M : ETH_SPEED_10M; + duplex = bmcr.duplex_mode ? ETH_DUPLEX_FULL : ETH_DUPLEX_HALF; + } + + ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed"); + ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed"); + /* if we're in duplex mode, and peer has the flow control ability */ + if (duplex == ETH_DUPLEX_FULL && anlpar.symmetric_pause) { + peer_pause_ability = 1; + } else { + peer_pause_ability = 0; + } + ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_PAUSE, (void *)peer_pause_ability), err, TAG, "change pause ability failed"); + } + ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed"); + phy_802_3->link_status = link; + } + return ESP_OK; +err: + return ret; +} + esp_err_t esp_eth_phy_802_3_pwrctl(phy_802_3_t *phy_802_3, bool enable) { esp_err_t ret = ESP_OK; @@ -392,8 +449,28 @@ esp_err_t esp_eth_phy_802_3_reset_hw(phy_802_3_t *phy_802_3, uint32_t reset_asse vTaskDelay(pdMS_TO_TICKS(reset_assert_us/1000)); } gpio_set_level(phy_802_3->reset_gpio_num, 1); + return ESP_OK; } - return ESP_OK; + return ESP_ERR_NOT_ALLOWED; +} + +/** + * @brief Hardware reset with internal timing configuration defined during initialization + * + * @param phy_802_3 IEEE 802.3 PHY object infostructure + * @return + * - ESP_OK: reset Ethernet PHY successfully + * - ESP_ERR_NOT_ALLOWED: reset GPIO not defined + */ +static esp_err_t esp_eth_phy_802_3_reset_hw_internal(phy_802_3_t *phy_802_3) +{ + esp_err_t ret = ESP_OK; + if ((ret = esp_eth_phy_802_3_reset_hw(phy_802_3, phy_802_3->hw_reset_assert_time_us)) == ESP_OK) { + if (phy_802_3->post_hw_reset_delay_ms > 0) { + vTaskDelay(pdMS_TO_TICKS(phy_802_3->post_hw_reset_delay_ms)); + } + } + return ret; } esp_err_t esp_eth_phy_802_3_detect_phy_addr(esp_eth_mediator_t *eth, int *detected_addr) @@ -601,9 +678,19 @@ esp_err_t esp_eth_phy_802_3_obj_config_init(phy_802_3_t *phy_802_3, const eth_ph phy_802_3->reset_timeout_ms = config->reset_timeout_ms; phy_802_3->reset_gpio_num = config->reset_gpio_num; phy_802_3->autonego_timeout_ms = config->autonego_timeout_ms; + if (config->hw_reset_assert_time_us > 0) { + phy_802_3->hw_reset_assert_time_us = config->hw_reset_assert_time_us; + } else { + phy_802_3->hw_reset_assert_time_us = PHY_RESET_ASSERTION_TIME_US; + } + if (config->post_hw_reset_delay_ms > 0) { + phy_802_3->post_hw_reset_delay_ms = config->post_hw_reset_delay_ms; + } else { + phy_802_3->post_hw_reset_delay_ms = ESP_ETH_NO_POST_HW_RESET_DELAY; + } phy_802_3->parent.reset = reset; - phy_802_3->parent.reset_hw = reset_hw_default; + phy_802_3->parent.reset_hw = reset_hw; phy_802_3->parent.init = init; phy_802_3->parent.deinit = deinit; phy_802_3->parent.set_mediator = set_mediator; @@ -617,7 +704,7 @@ esp_err_t esp_eth_phy_802_3_obj_config_init(phy_802_3_t *phy_802_3, const eth_ph phy_802_3->parent.set_duplex = set_duplex; phy_802_3->parent.del = del; phy_802_3->parent.set_link = set_link; - phy_802_3->parent.get_link = NULL; + phy_802_3->parent.get_link = get_link; phy_802_3->parent.custom_ioctl = NULL; err: diff --git a/components/esp_eth/src/phy/esp_eth_phy_generic.c b/components/esp_eth/src/phy/esp_eth_phy_generic.c new file mode 100644 index 000000000000..0003758bf866 --- /dev/null +++ b/components/esp_eth/src/phy/esp_eth_phy_generic.c @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "esp_check.h" +#include "esp_eth.h" +#include "esp_eth_phy_802_3.h" + +static const char *TAG = "eth_phy_generic"; + +// Default reset timing is intentionally conservative +#define DEFAULT_PHY_GENERIC_RESET_ASSERTION_TIME_US 10000 +#define DEFAULT_PHY_GENERIC_POST_RESET_DELAY_MS 500 + +esp_eth_phy_t *esp_eth_phy_new_generic(const eth_phy_config_t *config) +{ + esp_eth_phy_t *ret = NULL; + phy_802_3_t *phy_802_3 = calloc(1, sizeof(phy_802_3_t)); + eth_phy_config_t phy_802_3_config = *config; + // default chip specific configuration if not defined by user + if (config->hw_reset_assert_time_us == 0) { + phy_802_3_config.hw_reset_assert_time_us = DEFAULT_PHY_GENERIC_RESET_ASSERTION_TIME_US; + } + if (config->post_hw_reset_delay_ms == 0) { + phy_802_3_config.post_hw_reset_delay_ms = DEFAULT_PHY_GENERIC_POST_RESET_DELAY_MS; + } + ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(phy_802_3, &phy_802_3_config) == ESP_OK, + NULL, err, TAG, "configuration initialization of PHY 802.3 failed"); + + return &phy_802_3->parent; +err: + return ret; +} diff --git a/components/esp_eth/src/phy/esp_eth_phy_ip101.c b/components/esp_eth/src/phy/esp_eth_phy_ip101.c index e66fb78b93e5..42fce95b3177 100644 --- a/components/esp_eth/src/phy/esp_eth_phy_ip101.c +++ b/components/esp_eth/src/phy/esp_eth_phy_ip101.c @@ -173,14 +173,6 @@ static esp_err_t ip101_get_link(esp_eth_phy_t *phy) return ret; } -static esp_err_t ip101_reset_hw(esp_eth_phy_t *phy) -{ - phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); - esp_err_t ret = esp_eth_phy_802_3_reset_hw(phy_802_3, IP101_PHY_RESET_ASSERTION_TIME_US); - vTaskDelay(pdMS_TO_TICKS(IP101_PHY_POST_RESET_INIT_TIME_MS)); - return ret; -} - static esp_err_t ip101_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -206,13 +198,20 @@ esp_eth_phy_t *esp_eth_phy_new_ip101(const eth_phy_config_t *config) esp_eth_phy_t *ret = NULL; phy_ip101_t *ip101 = calloc(1, sizeof(phy_ip101_t)); ESP_GOTO_ON_FALSE(ip101, NULL, err, TAG, "calloc ip101 failed"); - ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&ip101->phy_802_3, config) == ESP_OK, + eth_phy_config_t ip101_config = *config; + // default chip specific configuration + if (config->hw_reset_assert_time_us == 0) { + ip101_config.hw_reset_assert_time_us = IP101_PHY_RESET_ASSERTION_TIME_US; + } + if (config->post_hw_reset_delay_ms == 0) { + ip101_config.post_hw_reset_delay_ms = IP101_PHY_POST_RESET_INIT_TIME_MS; + } + ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&ip101->phy_802_3, &ip101_config) == ESP_OK, NULL, err, TAG, "configuration initialization of PHY 802.3 failed"); // redefine functions which need to be customized for sake of IP101 ip101->phy_802_3.parent.init = ip101_init; ip101->phy_802_3.parent.get_link = ip101_get_link; - ip101->phy_802_3.parent.reset_hw = ip101_reset_hw; return &ip101->phy_802_3.parent; err: diff --git a/components/esp_eth/src/phy/esp_eth_phy_lan87xx.c b/components/esp_eth/src/phy/esp_eth_phy_lan87xx.c index d6f8e148fd1d..1d9f666f9a7a 100644 --- a/components/esp_eth/src/phy/esp_eth_phy_lan87xx.c +++ b/components/esp_eth/src/phy/esp_eth_phy_lan87xx.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,9 @@ static const char *TAG = "lan87xx"; +/* It was observed that assert nRST signal on LAN87xx needs to be a little longer than the minimum specified in datasheet */ +#define LAN87XX_PHY_RESET_ASSERTION_TIME_US 150 + /***************List of Supported Models***************/ // See Microchip's Application Note AN25.3 summarizing differences among below models @@ -287,12 +290,6 @@ static esp_err_t lan87xx_get_link(esp_eth_phy_t *phy) return ret; } -static esp_err_t lan87xx_reset_hw(esp_eth_phy_t *phy) -{ - /* It was observed that assert nRST signal on LAN87xx needs to be a little longer than the minimum specified in datasheet */ - return esp_eth_phy_802_3_reset_hw(esp_eth_phy_into_phy_802_3(phy), 150); -} - static esp_err_t lan87xx_autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat) { esp_err_t ret = ESP_OK; @@ -366,11 +363,18 @@ esp_eth_phy_t *esp_eth_phy_new_lan87xx(const eth_phy_config_t *config) esp_eth_phy_t *ret = NULL; phy_lan87xx_t *lan87xx = calloc(1, sizeof(phy_lan87xx_t)); ESP_GOTO_ON_FALSE(lan87xx, NULL, err, TAG, "calloc lan87xx failed"); - ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&lan87xx->phy_802_3, config) == ESP_OK, + eth_phy_config_t lan87xx_config = *config; + // default chip specific configuration + if (config->hw_reset_assert_time_us == 0) { + lan87xx_config.hw_reset_assert_time_us = LAN87XX_PHY_RESET_ASSERTION_TIME_US; + } + if (config->post_hw_reset_delay_ms == 0) { + lan87xx_config.post_hw_reset_delay_ms = ESP_ETH_NO_POST_HW_RESET_DELAY; + } + ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&lan87xx->phy_802_3, &lan87xx_config) == ESP_OK, NULL, err, TAG, "configuration initialization of PHY 802.3 failed"); // redefine functions which need to be customized for sake of LAN87xx - lan87xx->phy_802_3.parent.reset_hw = lan87xx_reset_hw; lan87xx->phy_802_3.parent.init = lan87xx_init; lan87xx->phy_802_3.parent.get_link = lan87xx_get_link; lan87xx->phy_802_3.parent.autonego_ctrl = lan87xx_autonego_ctrl; diff --git a/components/esp_eth/src/phy/esp_eth_phy_rtl8201.c b/components/esp_eth/src/phy/esp_eth_phy_rtl8201.c index 4f3a9337b4fa..c2bf0900e3a5 100644 --- a/components/esp_eth/src/phy/esp_eth_phy_rtl8201.c +++ b/components/esp_eth/src/phy/esp_eth_phy_rtl8201.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -149,15 +149,6 @@ static esp_err_t rtl8201_loopback(esp_eth_phy_t *phy, bool enable) return ret; } -static esp_err_t rtl8201_reset_hw(esp_eth_phy_t *phy) -{ - phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); - esp_err_t ret = esp_eth_phy_802_3_reset_hw(phy_802_3, RTL8201_PHY_RESET_ASSERTION_TIME_US); - vTaskDelay(pdMS_TO_TICKS(RTL8201_PHY_POST_RESET_INIT_TIME_MS)); - return ret; -} - - static esp_err_t rtl8201_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -183,7 +174,15 @@ esp_eth_phy_t *esp_eth_phy_new_rtl8201(const eth_phy_config_t *config) esp_eth_phy_t *ret = NULL; phy_rtl8201_t *rtl8201 = calloc(1, sizeof(phy_rtl8201_t)); ESP_GOTO_ON_FALSE(rtl8201, NULL, err, TAG, "calloc rtl8201 failed"); - ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&rtl8201->phy_802_3, config) == ESP_OK, + eth_phy_config_t rtl8201_config = *config; + // default chip specific configuration + if (config->hw_reset_assert_time_us == 0) { + rtl8201_config.hw_reset_assert_time_us = RTL8201_PHY_RESET_ASSERTION_TIME_US; + } + if (config->post_hw_reset_delay_ms == 0) { + rtl8201_config.post_hw_reset_delay_ms = RTL8201_PHY_POST_RESET_INIT_TIME_MS; + } + ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&rtl8201->phy_802_3, &rtl8201_config) == ESP_OK, NULL, err, TAG, "configuration initialization of PHY 802.3 failed"); // redefine functions which need to be customized for sake of RTL8201 @@ -191,7 +190,6 @@ esp_eth_phy_t *esp_eth_phy_new_rtl8201(const eth_phy_config_t *config) rtl8201->phy_802_3.parent.get_link = rtl8201_get_link; rtl8201->phy_802_3.parent.autonego_ctrl = rtl8201_autonego_ctrl; rtl8201->phy_802_3.parent.loopback = rtl8201_loopback; - rtl8201->phy_802_3.parent.reset_hw = rtl8201_reset_hw; return &rtl8201->phy_802_3.parent; err: diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 1e642d63dacc..c7d2c28ffaf8 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -1247,15 +1247,15 @@ int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len) ESP_LOGD(TAG, "need_read=%d, byte_to_read=%d, rlen=%d, ridx=%d", need_read, byte_to_read, rlen, ridx); if (rlen <= 0) { + esp_log_level_t sev = ESP_LOG_WARN; + /* Check for cleanly closed connection */ + if (rlen == ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN && client->response->is_chunked) { + /* Explicit call to parser for invoking `message_complete` callback */ + http_parser_execute(client->parser, client->parser_settings, res_buffer->data, 0); + /* ...and lowering the message severity, as closed connection from server side is expected in chunked transport */ + sev = ESP_LOG_DEBUG; + } if (errno != 0) { - esp_log_level_t sev = ESP_LOG_WARN; - /* Check for cleanly closed connection */ - if (rlen == ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN && client->response->is_chunked) { - /* Explicit call to parser for invoking `message_complete` callback */ - http_parser_execute(client->parser, client->parser_settings, res_buffer->data, 0); - /* ...and lowering the message severity, as closed connection from server side is expected in chunked transport */ - sev = ESP_LOG_DEBUG; - } ESP_LOG_LEVEL(sev, TAG, "esp_transport_read returned:%d and errno:%d ", rlen, errno); } diff --git a/components/esp_http_server/src/httpd_parse.c b/components/esp_http_server/src/httpd_parse.c index 3d76380a8b47..2fbc37f3eb82 100644 --- a/components/esp_http_server/src/httpd_parse.c +++ b/components/esp_http_server/src/httpd_parse.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2024 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 ATLEAST once every packet + * Will be invoked AT LEAST 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 ATLEAST once every header field + * May be invoked AT LEAST 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 ATLEAST once every header value + * May be invoked AT LEAST once every header value */ static esp_err_t cb_header_value(http_parser *parser, const char *at, size_t length) { diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index e1b6efc00db4..1d3585ac91ae 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -1,4 +1,5 @@ idf_build_get_property(target IDF_TARGET) +idf_build_get_property(non_os_build NON_OS_BUILD) # On Linux, we only support a few features, hence this simple component registration if(${target} STREQUAL "linux") @@ -22,7 +23,7 @@ if(CONFIG_RTC_CLK_SRC_INT_RC32K) endif() set(srcs "cpu.c" "port/${IDF_TARGET}/esp_cpu_intr.c" "esp_memory_utils.c" "port/${IDF_TARGET}/cpu_region_protect.c") -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) list(APPEND srcs "esp_clk.c" "clk_ctrl_os.c" "hw_random.c" @@ -163,15 +164,11 @@ idf_build_get_property(target IDF_TARGET) add_subdirectory(port/${target}) add_subdirectory(lowpower) -if(CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU") # TODO IDF-10229 - target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-analyzer") -endif() - if(CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND OR CONFIG_PM_SLP_DISABLE_GPIO) target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_sleep_gpio_include") endif() -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) if(CONFIG_SPIRAM) idf_component_optional_requires(PRIVATE esp_psram) endif() diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 167d828de281..e29c37b24226 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -69,8 +69,9 @@ menu "Hardware Settings" # This is here since this option affect behavior of esp_light_sleep_start # regardless of power management configuration. config ESP_SLEEP_POWER_DOWN_FLASH - bool "Power down flash in light sleep when there is no SPIRAM" - depends on !SPIRAM + bool "Power down flash in light sleep when there is no SPIRAM or SPIRAM has independent power supply" + depends on !SPIRAM || ESP_LDO_RESERVE_PSRAM + depends on !(IDF_TARGET_ESP32P4 && (ESP32P4_REV_MIN_FULL < 100)) default n help If enabled, chip will try to power down flash as part of esp_light_sleep_start(), which costs diff --git a/components/esp_hw_support/dma/Kconfig.dma b/components/esp_hw_support/dma/Kconfig.dma index fa43dd6ea8ee..5620926e3ee4 100644 --- a/components/esp_hw_support/dma/Kconfig.dma +++ b/components/esp_hw_support/dma/Kconfig.dma @@ -29,6 +29,7 @@ menu "DW_GDMA Configurations" config DW_GDMA_CTRL_FUNC_IN_IRAM bool default n + select DW_GDMA_OBJ_DRAM_SAFE help Place DW_GDMA control functions (e.g. dw_gdma_channel_continue) into IRAM, so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context. @@ -36,6 +37,7 @@ menu "DW_GDMA Configurations" config DW_GDMA_SETTER_FUNC_IN_IRAM bool default n + select DW_GDMA_OBJ_DRAM_SAFE help Place DW_GDMA setter functions (e.g. dw_gdma_channel_set_block_markers) into IRAM, so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context. @@ -43,6 +45,7 @@ menu "DW_GDMA Configurations" config DW_GDMA_GETTER_FUNC_IN_IRAM bool default n + select DW_GDMA_OBJ_DRAM_SAFE help Place DW_GDMA getter functions (e.g. dw_gdma_link_list_get_item) into IRAM, so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context. @@ -50,11 +53,19 @@ menu "DW_GDMA Configurations" config DW_GDMA_ISR_IRAM_SAFE bool default n + select DW_GDMA_OBJ_DRAM_SAFE help This will ensure the DW_GDMA interrupt handler is IRAM-Safe, allow to avoid flash cache misses, and also be able to run whilst the cache is disabled. (e.g. SPI Flash write). + config DW_GDMA_OBJ_DRAM_SAFE + bool + default n + help + This will ensure the DW_GDMA object is DRAM-Safe, allow to avoid external memory + cache misses, and also be accessible whilst the cache is disabled. + config DW_GDMA_ENABLE_DEBUG_LOG bool "Enable debug log" default n diff --git a/components/esp_hw_support/dma/dw_gdma.c b/components/esp_hw_support/dma/dw_gdma.c index f76f1245eb5c..fc4aaf4078e2 100644 --- a/components/esp_hw_support/dma/dw_gdma.c +++ b/components/esp_hw_support/dma/dw_gdma.c @@ -48,7 +48,7 @@ static const char *TAG = "dw-gdma"; #define DW_GDMA_GET_CACHE_ADDRESS(nc_addr) (nc_addr) #endif -#if CONFIG_DW_GDMA_ISR_IRAM_SAFE || CONFIG_DW_GDMA_CTRL_FUNC_IN_IRAM || DW_GDMA_SETTER_FUNC_IN_IRAM +#if CONFIG_DW_GDMA_OBJ_DRAM_SAFE #define DW_GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else #define DW_GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT diff --git a/components/esp_hw_support/dma/gdma_link.c b/components/esp_hw_support/dma/gdma_link.c index d13b62e64d24..45923f57a956 100644 --- a/components/esp_hw_support/dma/gdma_link.c +++ b/components/esp_hw_support/dma/gdma_link.c @@ -13,6 +13,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "soc/soc_caps.h" +#include "soc/ext_mem_defs.h" #include "esp_log.h" #include "esp_check.h" #include "esp_memory_utils.h" @@ -227,11 +228,20 @@ uintptr_t gdma_link_get_head_addr(gdma_link_list_handle_t list) return (uintptr_t)(list->items); } +esp_err_t gdma_link_concat(gdma_link_list_handle_t first_link, int first_link_item_index, gdma_link_list_handle_t second_link, int second_link_item_index) +{ + ESP_RETURN_ON_FALSE(first_link && second_link, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + gdma_link_list_item_t *lli_nc = NULL; + lli_nc = (gdma_link_list_item_t *)(first_link->items_nc + (first_link->num_items + first_link_item_index) % first_link->num_items * first_link->item_size); + lli_nc->next = (gdma_link_list_item_t *)(second_link->items + (second_link->num_items + second_link_item_index) % second_link->num_items * second_link->item_size); + return ESP_OK; +} + esp_err_t gdma_link_set_owner(gdma_link_list_handle_t list, int item_index, gdma_lli_owner_t owner) { ESP_RETURN_ON_FALSE_ISR(list, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE_ISR(item_index < list->num_items, ESP_ERR_INVALID_ARG, TAG, "invalid item index"); - gdma_link_list_item_t *lli = (gdma_link_list_item_t *)(list->items_nc + item_index * list->item_size); + gdma_link_list_item_t *lli = (gdma_link_list_item_t *)(list->items_nc + (list->num_items + item_index) % list->num_items * list->item_size); lli->dw0.owner = owner; return ESP_OK; } @@ -240,7 +250,7 @@ esp_err_t gdma_link_get_owner(gdma_link_list_handle_t list, int item_index, gdma { ESP_RETURN_ON_FALSE_ISR(list && owner, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE_ISR(item_index < list->num_items, ESP_ERR_INVALID_ARG, TAG, "invalid item index"); - gdma_link_list_item_t *lli = (gdma_link_list_item_t *)(list->items_nc + item_index * list->item_size); + gdma_link_list_item_t *lli = (gdma_link_list_item_t *)(list->items_nc + (list->num_items + item_index) % list->num_items * list->item_size); *owner = lli->dw0.owner; return ESP_OK; } diff --git a/components/esp_hw_support/dma/include/esp_private/gdma_link.h b/components/esp_hw_support/dma/include/esp_private/gdma_link.h index 94a13651c4ee..fa350e792a6f 100644 --- a/components/esp_hw_support/dma/include/esp_private/gdma_link.h +++ b/components/esp_hw_support/dma/include/esp_private/gdma_link.h @@ -71,7 +71,7 @@ typedef struct { uint32_t mark_final: 1; /*!< Whether to terminate the DMA link list at this item. Note, DMA engine will stop at this item and trigger an interrupt. If `mark_final` is not set, this list item will point to the next item, and - wrap around to the head item if it's the one in the list. */ + wrap around to the head item if it's the last one in the list. */ } flags; //!< Flags for buffer mount configurations } gdma_buffer_mount_config_t; @@ -105,6 +105,31 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, uint32_t start_i */ uintptr_t gdma_link_get_head_addr(gdma_link_list_handle_t list); +/** + * @brief Concatenate two link lists as follows: + * + * Link A: A1 --> A2 --> A3 --> A4 + * | item_index + * +-----+ + * | + * v item_index + * Link B: B1 --> B2 --> B3 --> B4 + * + * After concatenation: + * Link A: A1 --> B3 --> B4 + * Link B: B1 --> B2 --> B3 --> B4 + * + * @param[in] first_link First link list handle, allocated by `gdma_new_link_list` + * @param[in] first_link_item_index Index of the item in the first link list (-1 means the last item) + * @param[in] second_link Second link list handle, allocated by `gdma_new_link_list` + * @param[in] second_link_item_index Index of the item in the second link list (-1 means the last item) + * @return + * - ESP_OK: Concatenate the link lists successfully + * - ESP_ERR_INVALID_ARG: Concatenate the link lists failed because of invalid argument + * - ESP_FAIL: Concatenate the link lists failed because of other error + */ +esp_err_t gdma_link_concat(gdma_link_list_handle_t first_link, int first_link_item_index, gdma_link_list_handle_t second_link, int second_link_item_index); + /** * @brief GDMA link list item owner */ @@ -117,7 +142,7 @@ typedef enum { * @brief Set the ownership for a DMA link list item * * @param[in] list Link list handle, allocated by `gdma_new_link_list` - * @param[in] item_index Index of the link list item + * @param[in] item_index Index of the link list item (-1 means the last item) * @param[in] owner Ownership * @return * - ESP_OK: Set the ownership successfully @@ -130,7 +155,7 @@ esp_err_t gdma_link_set_owner(gdma_link_list_handle_t list, int item_index, gdma * @brief Get the ownership of a DMA link list item * * @param[in] list Link list handle, allocated by `gdma_new_link_list` - * @param[in] item_index Index of the link list item + * @param[in] item_index Index of the link list item (-1 means the last item) * @param[out] owner Ownership * @return * - ESP_OK: Get the ownership successfully diff --git a/components/esp_hw_support/esp_etm.c b/components/esp_hw_support/esp_etm.c index 9dfbfc6cb40e..b8ae6349b7c1 100644 --- a/components/esp_hw_support/esp_etm.c +++ b/components/esp_hw_support/esp_etm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,7 +16,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "soc/soc_caps.h" -#include "soc/periph_defs.h" +#include "soc/etm_periph.h" #include "esp_log.h" #include "esp_check.h" #include "esp_heap_caps.h" @@ -25,10 +25,13 @@ #include "hal/etm_ll.h" #include "esp_private/periph_ctrl.h" #include "esp_private/etm_interface.h" +#include "esp_private/sleep_retention.h" #define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT -#if CONFIG_IDF_TARGET_ESP32P4 +#define ETM_USE_RETENTION_LINK (SOC_ETM_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + +#if !SOC_RCC_IS_INDEPENDENT // Reset and Clock Control registers are mixing with other peripherals, so we need to use a critical section #define ETM_RCC_ATOMIC() PERIPH_RCC_ATOMIC() #else @@ -70,6 +73,32 @@ struct esp_etm_channel_t { // ETM driver platform, it's always a singleton static etm_platform_t s_platform; +#if ETM_USE_RETENTION_LINK +static esp_err_t etm_create_sleep_retention_link_cb(void *arg) +{ + etm_group_t *group = (etm_group_t *)arg; + int group_id = group->group_id; + esp_err_t err = sleep_retention_entries_create(etm_reg_retention_info[group_id].regdma_entry_array, + etm_reg_retention_info[group_id].array_size, + REGDMA_LINK_PRI_ETM, etm_reg_retention_info[group_id].module); + return err; +} + +static void etm_create_retention_module(etm_group_t *group) +{ + int group_id = group->group_id; + sleep_retention_module_t module = etm_reg_retention_info[group_id].module; + _lock_acquire(&s_platform.mutex); + if ((sleep_retention_get_inited_modules() & BIT(module)) && !(sleep_retention_get_created_modules() & BIT(module))) { + if (sleep_retention_module_allocate(module) != ESP_OK) { + // even though the sleep retention module create failed, ETM driver should still work, so just warning here + ESP_LOGW(TAG, "create retention link failed %d, power domain won't be turned off during sleep", group_id); + } + } + _lock_release(&s_platform.mutex); +} +#endif // ETM_USE_RETENTION_LINK + static etm_group_t *etm_acquire_group_handle(int group_id) { bool new_group = false; @@ -90,7 +119,22 @@ static etm_group_t *etm_acquire_group_handle(int group_id) etm_ll_enable_bus_clock(group_id, true); etm_ll_reset_register(group_id); } - +#if ETM_USE_RETENTION_LINK + sleep_retention_module_t module = etm_reg_retention_info[group_id].module; + sleep_retention_module_init_param_t init_param = { + .cbs = { + .create = { + .handle = etm_create_sleep_retention_link_cb, + .arg = group, + }, + }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) + }; + if (sleep_retention_module_init(module, &init_param) != ESP_OK) { + // even though the sleep retention module init failed, ETM driver may 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 // ETM_USE_RETENTION_LINK // initialize HAL context etm_hal_init(&group->hal); } @@ -129,6 +173,15 @@ static void etm_release_group_handle(etm_group_t *group) _lock_release(&s_platform.mutex); if (do_deinitialize) { +#if ETM_USE_RETENTION_LINK + sleep_retention_module_t module = etm_reg_retention_info[group_id].module; + if (sleep_retention_get_created_modules() & BIT(module)) { + sleep_retention_module_free(module); + } + if (sleep_retention_get_inited_modules() & BIT(module)) { + sleep_retention_module_deinit(module); + } +#endif free(group); ESP_LOGD(TAG, "del group (%d)", group_id); } @@ -192,6 +245,9 @@ esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_ch esp_err_t ret = ESP_OK; esp_etm_channel_t *chan = NULL; ESP_GOTO_ON_FALSE(config && ret_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid args"); +#if !SOC_ETM_SUPPORT_SLEEP_RETENTION + ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep"); +#endif // SOC_ETM_SUPPORT_SLEEP_RETENTION chan = heap_caps_calloc(1, sizeof(esp_etm_channel_t), ETM_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(chan, ESP_ERR_NO_MEM, err, TAG, "no mem for channel"); @@ -201,6 +257,12 @@ esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_ch int group_id = group->group_id; int chan_id = chan->chan_id; +#if ETM_USE_RETENTION_LINK + if (config->flags.allow_pd != 0) { + etm_create_retention_module(group); + } +#endif // ETM_USE_RETENTION_LINK + chan->fsm = ETM_CHAN_FSM_INIT; ESP_LOGD(TAG, "new etm channel (%d,%d) at %p", group_id, chan_id, chan); *ret_chan = chan; diff --git a/components/esp_hw_support/esp_memory_utils.c b/components/esp_hw_support/esp_memory_utils.c index 766ca5a2c183..62627cbcb970 100644 --- a/components/esp_hw_support/esp_memory_utils.c +++ b/components/esp_hw_support/esp_memory_utils.c @@ -67,7 +67,7 @@ bool esp_ptr_external_ram(const void *p) #endif //CONFIG_SPIRAM } -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM bool esp_stack_ptr_in_extram(uint32_t sp) { //Check if stack ptr is on PSRAM, and 16 byte aligned. diff --git a/components/esp_hw_support/include/esp_etm.h b/components/esp_hw_support/include/esp_etm.h index c0757abf8aba..daa97d76c32c 100644 --- a/components/esp_hw_support/include/esp_etm.h +++ b/components/esp_hw_support/include/esp_etm.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,7 +32,11 @@ typedef struct esp_etm_task_t *esp_etm_task_handle_t; * @brief ETM channel configuration */ typedef struct { - + /// Extra configuration flags for ETM channel + struct etm_chan_flags { + 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. */ + } flags; /*!< ETM channel flags */ } esp_etm_channel_config_t; /** diff --git a/components/esp_hw_support/include/esp_memory_utils.h b/components/esp_hw_support/include/esp_memory_utils.h index 427dc4912eaf..d17d6f269655 100644 --- a/components/esp_hw_support/include/esp_memory_utils.h +++ b/components/esp_hw_support/include/esp_memory_utils.h @@ -352,7 +352,7 @@ inline static bool esp_stack_ptr_in_dram(uint32_t sp) return !(sp < SOC_DRAM_LOW + 0x10 || sp > SOC_DRAM_HIGH - 0x10 || ((sp & 0xF) != 0)); } -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM /** * @brief Check if the stack pointer is in external ram * @@ -374,7 +374,7 @@ __attribute__((always_inline)) inline static bool esp_stack_ptr_is_sane(uint32_t sp) { return esp_stack_ptr_in_dram(sp) -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM || esp_stack_ptr_in_extram(sp) #endif #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 5b4819460743..6d347788a241 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -50,6 +50,7 @@ typedef enum { #define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17) #define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature #define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19) +#define RTC_SLEEP_LP_PERIPH_USE_XTAL BIT(20) #if SOC_PM_SUPPORT_EXT0_WAKEUP #define RTC_EXT0_TRIG_EN PMU_EXT0_WAKEUP_EN //!< EXT0 wakeup @@ -109,6 +110,12 @@ typedef enum { #define RTC_LP_CORE_TRIG_EN 0 #endif //SOC_LP_CORE_SUPPORTED +#if SOC_LP_VAD_SUPPORTED +#define RTC_LP_VAD_TRIG_EN PMU_LP_I2S_WAKEUP_EN //!< LP VAD wakeup +#else +#define RTC_LP_VAD_TRIG_EN 0 +#endif //SOC_LP_VAD_SUPPORTED + #define RTC_XTAL32K_DEAD_TRIG_EN 0 // TODO #define RTC_BROWNOUT_DET_TRIG_EN 0 // TODO @@ -127,6 +134,7 @@ typedef enum { RTC_TOUCH_TRIG_EN | \ RTC_XTAL32K_DEAD_TRIG_EN | \ RTC_USB_TRIG_EN | \ + RTC_LP_VAD_TRIG_EN | \ RTC_BROWNOUT_DET_TRIG_EN) diff --git a/components/esp_hw_support/include/esp_private/esp_regdma.h b/components/esp_hw_support/include/esp_private/esp_regdma.h index 9e904997f70a..1a082408fd7a 100644 --- a/components/esp_hw_support/include/esp_private/esp_regdma.h +++ b/components/esp_hw_support/include/esp_private/esp_regdma.h @@ -396,9 +396,9 @@ void *regdma_find_prev_module_link_tail(void *link, void *tail, int entry, uint3 */ void *regdma_find_next_module_link_head(void *link, void *tail, int entry, uint32_t module); -#define regdma_link_init_safe(pcfg, branch, module, ...) regdma_link_init((pcfg), (branch), (module), __VA_NARG__(__VA_ARGS__), ##__VA_ARGS__) +#define regdma_link_init_safe(pcfg, branch, module, ...) regdma_link_init((pcfg), (branch), (module), ESP_VA_NARG(__VA_ARGS__), ##__VA_ARGS__) -#define regdma_link_update_next_safe(link, ...) regdma_link_update_next((link), __VA_NARG__(__VA_ARGS__), ##__VA_ARGS__) +#define regdma_link_update_next_safe(link, ...) regdma_link_update_next((link), ESP_VA_NARG(__VA_ARGS__), ##__VA_ARGS__) #endif // SOC_PAU_SUPPORTED diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index df9c2a79e29b..747d426cd9c7 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -38,6 +38,7 @@ typedef enum { ESP_SLEEP_ULTRA_LOW_MODE, //!< In ultra low mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. ESP_SLEEP_RTC_FAST_USE_XTAL_MODE, //!< The mode in which the crystal is used as the RTC_FAST clock source, need keep XTAL on in HP_SLEEP mode when ULP is working. ESP_SLEEP_DIG_USE_XTAL_MODE, //!< The mode requested by digital peripherals to keep XTAL clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the XTAL domain config by esp_sleep_pd_config) + ESP_SLEEP_LP_USE_XTAL_MODE, //!< The mode requested by lp peripherals to keep XTAL clock on during sleep. Only valid for lightsleep. ESP_SLEEP_MODE_MAX, } esp_sleep_sub_mode_t; @@ -107,6 +108,22 @@ esp_err_t esp_deep_sleep_register_phy_hook(esp_deep_sleep_cb_t new_dslp_cb); void esp_deep_sleep_deregister_phy_hook(esp_deep_sleep_cb_t old_dslp_cb); #endif +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD +/** + * @brief Backup or restore the MMU when the top domain is powered down. + * @param backup_or_restore decide to backup mmu or restore mmu + */ +void esp_sleep_mmu_retention(bool backup_or_restore); + +/** + * @brief Whether to allow the top domain to be powered off due to mmu domain requiring retention. + * + * In light sleep mode, only when the system can provide enough memory + * for mmu retention, the top power domain can be powered off. + */ +bool mmu_domain_pd_allowed(void); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h index def755d81560..e77322677f80 100644 --- a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h +++ b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -70,6 +70,13 @@ void regi2c_analog_cali_reg_read(void); void regi2c_analog_cali_reg_write(void); #endif //#if ADC_CALI_PD_WORKAROUND +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION +// regi2c would be powered down in light sleep, but measure range is recorded +// in regi2c, so this function is used for record. +void regi2c_tsens_reg_read(void); +void regi2c_tsens_reg_write(void); +#endif + /* Enable/Disable regi2c_saradc with calling these two functions. With reference count protection inside. Internal use only. diff --git a/components/esp_hw_support/include/esp_private/rtc_clk.h b/components/esp_hw_support/include/esp_private/rtc_clk.h index 52610fa0d1ce..4480780217f4 100644 --- a/components/esp_hw_support/include/esp_private/rtc_clk.h +++ b/components/esp_hw_support/include/esp_private/rtc_clk.h @@ -18,11 +18,12 @@ extern "C" { * @brief Switch CPU clock source to XTAL, and let cpu frequency equal to main XTAL frequency. * * This function does not disable CPU's source PLL. If the PLL requires to be disabled to save power, please call - * `rtc_clk_cpu_freq_set_xtal` instead. It does one extra check (if necessary) to see whether can disable the - * corresponding PLL after switching the CPU clock source to XTAL. + * `rtc_clk_cpu_freq_set_xtal` instead. It will always disable the corresponding PLL after switching the CPU clock + * source to XTAL (except for S2). * - * Currently, this function should only be called in `esp_restart_noos` and `esp_restart_noos_dig` to switch the CPU - * clock source back to XTAL (by default) before reset. + * Currently, this function is only called in `esp_restart_noos` and `esp_restart_noos_dig` to switch the CPU + * clock source back to XTAL (by default) before reset, and in `esp_sleep_start` to switch CPU clock source to XTAL + * before entering sleep for PMU supported chips. */ void rtc_clk_cpu_set_to_default_config(void); @@ -32,12 +33,6 @@ void rtc_clk_cpu_set_to_default_config(void); * Currently, this function is only used for tracking whether USB Serial/JTAG is using the 48MHz PHY clock * * Note: Calling this function only helps to not disable the BBPLL clock in `rtc_clk_cpu_freq_set_config`. - * For light and deep sleep, whether to disable the BBPLL in the internal call to `rtc_clk_cpu_freq_set_xtal` - * varies for targets. - * On ESP32C3/S3, USB CDC device can not function properly during sleep due to the lack of APB clock. Therefore. - * `rtc_clk_cpu_freq_set_xtal` will always disable BBPLL, no matter whether BBPLL has any consumer. - * On ESP32C6/H2, USB CDC device can maintain the minimum connection with the host during sleep, so - * `rtc_clk_cpu_freq_set_xtal` will check for BBPLL consumers, and keep BBPLL if USB Serial/JTAG is in use. */ void rtc_clk_bbpll_add_consumer(void); diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_retention.h index 076373c8f4f9..5b4e95e33823 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -59,6 +59,11 @@ typedef enum { */ esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module); +/** + * @brief Dump the initialization status of all modules. +*/ +void sleep_retention_dump_modules(FILE *out); + /** * @brief Dump all runtime sleep retention linked lists */ @@ -139,6 +144,23 @@ esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module); */ esp_err_t sleep_retention_module_free(sleep_retention_module_t module); +/** + * @brief Force take the power lock so that during sleep the power domain won't be powered off. + * + * @return + * - ESP_OK if success + * - other value when the internal `sleep_retention_module_init` fails. +*/ +esp_err_t sleep_retention_power_lock_acquire(void); + +/** + * @brief Release the power lock so that the peripherals' power domain can be powered off. + * Please note that there is an internal reference counter and the power domain will be kept on until same number + * of `sleep_retention_power_lock_release` is called as `sleep_retention_power_lock_acquire`. + * @return always ESP_OK +*/ +esp_err_t sleep_retention_power_lock_release(void); + /** * @brief Get all initialized modules that require sleep retention * diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index de25aeb26839..7b9be75b0f55 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -118,6 +118,7 @@ typedef enum { ESP_SLEEP_WAKEUP_COCPU, //!< Wakeup caused by COCPU int ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG, //!< Wakeup caused by COCPU crash ESP_SLEEP_WAKEUP_BT, //!< Wakeup caused by BT (light sleep only) + ESP_SLEEP_WAKEUP_VAD, //!< Wakeup caused by VAD } esp_sleep_source_t; /** @@ -179,6 +180,16 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void); */ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us); +#if SOC_LP_VAD_SUPPORTED +/** + * @brief Enable wakeup by VAD + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_sleep_enable_vad_wakeup(void); +#endif + #if SOC_TOUCH_SENSOR_SUPPORTED /** * @brief Enable wakeup by touch sensor @@ -759,41 +770,6 @@ esp_err_t esp_sleep_cpu_retention_init(void); esp_err_t esp_sleep_cpu_retention_deinit(void); #endif // ESP_SLEEP_POWER_DOWN_CPU -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD -/** - * @brief Backup or restore the MMU when the top domain is powered down. - * @param backup_or_restore decide to backup mmu or restore mmu - */ -void esp_sleep_mmu_retention(bool backup_or_restore); - -/** - * @brief Mmu backup initialize when power down TOP domain - * - * @return - * - ESP_OK on success - * - ESP_ERR_NO_MEM not enough retention memory - */ -esp_err_t esp_sleep_mmu_retention_init(void); - -/** - * @brief Mmu backup de-initialize when power down TOP domain - * - * @return - * - ESP_OK on success - * - * Release system retention memory. - */ -esp_err_t esp_sleep_mmu_retention_deinit(void); - -/** - * @brief Whether to allow the top domain to be powered off due to mmu domain requiring retention. - * - * In light sleep mode, only when the system can provide enough memory - * for mmu retention, the top power domain can be powered off. - */ -bool mmu_domain_pd_allowed(void); -#endif - /** * @brief Configure to isolate all GPIO pins in sleep state */ diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c index ac2f45da7bac..3a1cad172840 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c @@ -112,7 +112,7 @@ IRAM_ATTR void esp_sleep_mmu_retention(bool backup_or_restore) } } -static esp_err_t esp_sleep_mmu_retention_deinit_impl(void) +static esp_err_t esp_sleep_mmu_retention_deinit(void) { if (s_mmu_retention.retent.mmu_table_frame) { heap_caps_free((void *)s_mmu_retention.retent.mmu_table_frame); @@ -121,7 +121,7 @@ static esp_err_t esp_sleep_mmu_retention_deinit_impl(void) return ESP_OK; } -static esp_err_t esp_sleep_mmu_retention_init_impl(void) +static esp_err_t esp_sleep_mmu_retention_init(void) { if (s_mmu_retention.retent.mmu_table_frame == NULL) { void *frame = mmu_domain_mmu_table_sleep_frame_alloc_and_init(); @@ -136,16 +136,6 @@ static esp_err_t esp_sleep_mmu_retention_init_impl(void) return ESP_ERR_NO_MEM; } -esp_err_t esp_sleep_mmu_retention_init(void) -{ - return esp_sleep_mmu_retention_init_impl(); -} - -esp_err_t esp_sleep_mmu_retention_deinit(void) -{ - return esp_sleep_mmu_retention_deinit_impl(); -} - bool mmu_domain_pd_allowed(void) { return (s_mmu_retention.retent.mmu_table_frame != NULL); diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c index ac2f45da7bac..3a1cad172840 100644 --- a/components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c @@ -112,7 +112,7 @@ IRAM_ATTR void esp_sleep_mmu_retention(bool backup_or_restore) } } -static esp_err_t esp_sleep_mmu_retention_deinit_impl(void) +static esp_err_t esp_sleep_mmu_retention_deinit(void) { if (s_mmu_retention.retent.mmu_table_frame) { heap_caps_free((void *)s_mmu_retention.retent.mmu_table_frame); @@ -121,7 +121,7 @@ static esp_err_t esp_sleep_mmu_retention_deinit_impl(void) return ESP_OK; } -static esp_err_t esp_sleep_mmu_retention_init_impl(void) +static esp_err_t esp_sleep_mmu_retention_init(void) { if (s_mmu_retention.retent.mmu_table_frame == NULL) { void *frame = mmu_domain_mmu_table_sleep_frame_alloc_and_init(); @@ -136,16 +136,6 @@ static esp_err_t esp_sleep_mmu_retention_init_impl(void) return ESP_ERR_NO_MEM; } -esp_err_t esp_sleep_mmu_retention_init(void) -{ - return esp_sleep_mmu_retention_init_impl(); -} - -esp_err_t esp_sleep_mmu_retention_deinit(void) -{ - return esp_sleep_mmu_retention_deinit_impl(); -} - bool mmu_domain_pd_allowed(void) { return (s_mmu_retention.retent.mmu_table_frame != NULL); diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 63066d6302f1..cd3f68a3e11e 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -108,7 +108,7 @@ static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, boo static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) { - modem_clock_hal_enable_modem_adc_common_fe_clock(ctx->hal, enable); + modem_clock_hal_enable_modem_common_fe_clock(ctx->hal, enable); } static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) diff --git a/components/esp_hw_support/port/esp32c5/include/soc/rtc.h b/components/esp_hw_support/port/esp32c5/include/soc/rtc.h index 92a2c4f5c255..a11d201f20cf 100644 --- a/components/esp_hw_support/port/esp32c5/include/soc/rtc.h +++ b/components/esp_hw_support/port/esp32c5/include/soc/rtc.h @@ -307,8 +307,9 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. * - * @note On ESP32C5, this function will check whether BBPLL can be disabled. If there is no consumer, then BBPLL will be - * turned off. The behaviour is the same as using rtc_clk_cpu_freq_set_config to switch cpu clock source to XTAL. + * @note This function always disables BBPLL after switching the CPU clock source to XTAL for power saving purpose. + * If this is unwanted, please use rtc_clk_cpu_freq_set_config. It helps to check whether USB Serial JTAG is in use, + * if so, then BBPLL will not be turned off. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/esp_hw_support/port/esp32c5/pmu_param.c b/components/esp_hw_support/port/esp32c5/pmu_param.c index c9b691c71966..6f44a1b4e17d 100644 --- a/components/esp_hw_support/port/esp32c5/pmu_param.c +++ b/components/esp_hw_support/port/esp32c5/pmu_param.c @@ -291,17 +291,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2active_backup_en = 0, \ .hp_modem2active_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \ @@ -313,17 +303,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \ .hp_sleep2modem_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \ @@ -340,17 +320,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_modem2sleep_backup_en = 0, \ .hp_active2sleep_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) diff --git a/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h index 8e9909749b81..bbcc0c8e70f9 100644 --- a/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h @@ -87,7 +87,7 @@ const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mo typedef struct { pmu_hp_backup_reg_t retention; - uint32_t backup_clk; + uint32_t backup_clk; // icg_func } pmu_hp_system_retention_param_t; const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode); diff --git a/components/esp_hw_support/port/esp32c5/rtc_clk.c b/components/esp_hw_support/port/esp32c5/rtc_clk.c index e3d1052c4b07..23a3941c9d2b 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c5/rtc_clk.c @@ -383,10 +383,7 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { rtc_clk_cpu_set_to_default_config(); - // We don't turn off the bbpll if some consumers depend on bbpll - if (!s_bbpll_digi_consumers_ref_count) { - rtc_clk_bbpll_disable(); - } + rtc_clk_bbpll_disable(); } void rtc_clk_cpu_set_to_default_config(void) @@ -394,6 +391,7 @@ void rtc_clk_cpu_set_to_default_config(void) int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); + s_cur_pll_freq = 0; // no disable PLL, but set freq to 0 to trigger a PLL calibration after wake-up from sleep } void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz) diff --git a/components/esp_hw_support/port/esp32c6/include/soc/rtc.h b/components/esp_hw_support/port/esp32c6/include/soc/rtc.h index 8d508d5df39b..3880b325e5b7 100644 --- a/components/esp_hw_support/port/esp32c6/include/soc/rtc.h +++ b/components/esp_hw_support/port/esp32c6/include/soc/rtc.h @@ -338,8 +338,9 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. * - * @note On ESP32C6, this function will check whether BBPLL can be disabled. If there is no consumer, then BBPLL will be - * turned off. The behaviour is the same as using rtc_clk_cpu_freq_set_config to switch cpu clock source to XTAL. + * @note This function always disables BBPLL after switching the CPU clock source to XTAL for power saving purpose. + * If this is unwanted, please use rtc_clk_cpu_freq_set_config. It helps to check whether USB Serial JTAG is in use, + * if so, then BBPLL will not be turned off. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/esp_hw_support/port/esp32c6/pmu_param.c b/components/esp_hw_support/port/esp32c6/pmu_param.c index 044c300688e5..6b24a4c4d907 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_param.c +++ b/components/esp_hw_support/port/esp32c6/pmu_param.c @@ -291,18 +291,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2active_backup_en = 0, \ .hp_modem2active_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_GDMA) | \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \ @@ -314,17 +303,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \ .hp_sleep2modem_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \ @@ -341,18 +320,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_modem2sleep_backup_en = 0, \ .hp_active2sleep_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_GDMA) | \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) @@ -368,21 +336,14 @@ const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pm /** LP system default parameter */ - -#if CONFIG_ESP_SYSTEM_RTC_EXT_XTAL -# define PMU_SLOW_CLK_USE_EXT_XTAL (1) -#else -# define PMU_SLOW_CLK_USE_EXT_XTAL (0) -#endif - #define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \ .dig_power = { \ .mem_dslp = 0, \ .peri_pd_en = 0, \ }, \ .clk_power = { \ - .xpd_xtal32k = PMU_SLOW_CLK_USE_EXT_XTAL, \ - .xpd_rc32k = 0, \ + .xpd_xtal32k = 1, \ + .xpd_rc32k = 1, \ .xpd_fosc = 1, \ .pd_osc = 0 \ } \ diff --git a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h index fdef78b3300b..155c3e810f4a 100644 --- a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h @@ -92,7 +92,7 @@ const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mo typedef struct { pmu_hp_backup_reg_t retention; - uint32_t backup_clk; + uint32_t backup_clk; // icg_func } pmu_hp_system_retention_param_t; const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode); diff --git a/components/esp_hw_support/port/esp32c6/rtc_clk.c b/components/esp_hw_support/port/esp32c6/rtc_clk.c index 521e2fd03f54..c36c48d85934 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c6/rtc_clk.c @@ -333,10 +333,7 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { rtc_clk_cpu_set_to_default_config(); - // We don't turn off the bbpll if some consumers depend on bbpll - if (!s_bbpll_digi_consumers_ref_count) { - rtc_clk_bbpll_disable(); - } + rtc_clk_bbpll_disable(); } void rtc_clk_cpu_set_to_default_config(void) @@ -344,6 +341,7 @@ void rtc_clk_cpu_set_to_default_config(void) int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); + s_cur_pll_freq = 0; // no disable PLL, but set freq to 0 to trigger a PLL calibration after wake-up from sleep } void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz) diff --git a/components/esp_hw_support/port/esp32c61/esp_clk_tree.c b/components/esp_hw_support/port/esp32c61/esp_clk_tree.c index 78352f59f3e1..7915de98ec57 100644 --- a/components/esp_hw_support/port/esp32c61/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c61/esp_clk_tree.c @@ -33,6 +33,9 @@ uint32_t *freq_value) case SOC_MOD_CLK_PLL_F80M: clk_src_freq = CLK_LL_PLL_80M_FREQ_MHZ * MHZ; break; + case SOC_MOD_CLK_PLL_F120M: + clk_src_freq = CLK_LL_PLL_120M_FREQ_MHZ * MHZ; + break; case SOC_MOD_CLK_PLL_F160M: clk_src_freq = CLK_LL_PLL_160M_FREQ_MHZ * MHZ; break; diff --git a/components/esp_hw_support/port/esp32c61/include/soc/rtc.h b/components/esp_hw_support/port/esp32c61/include/soc/rtc.h index 12c15bc101d4..b04132733988 100644 --- a/components/esp_hw_support/port/esp32c61/include/soc/rtc.h +++ b/components/esp_hw_support/port/esp32c61/include/soc/rtc.h @@ -307,8 +307,9 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. * - * @note On ESP32C61, this function will check whether BBPLL can be disabled. If there is no consumer, then BBPLL will be - * turned off. The behaviour is the same as using rtc_clk_cpu_freq_set_config to switch cpu clock source to XTAL. + * @note This function always disables BBPLL after switching the CPU clock source to XTAL for power saving purpose. + * If this is unwanted, please use rtc_clk_cpu_freq_set_config. It helps to check whether USB Serial JTAG is in use, + * if so, then BBPLL will not be turned off. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/esp_hw_support/port/esp32c61/pmu_param.c b/components/esp_hw_support/port/esp32c61/pmu_param.c index 5343316f8ad0..4883b9067723 100644 --- a/components/esp_hw_support/port/esp32c61/pmu_param.c +++ b/components/esp_hw_support/port/esp32c61/pmu_param.c @@ -290,17 +290,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2active_backup_en = 0, \ .hp_modem2active_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \ @@ -312,17 +302,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \ .hp_sleep2modem_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \ @@ -339,17 +319,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_modem2sleep_backup_en = 0, \ .hp_active2sleep_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_TG0) | \ - BIT(PMU_ICG_FUNC_ENA_TG1) | \ - BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ - BIT(PMU_ICG_FUNC_ENA_MSPI) | \ - BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ - BIT(PMU_ICG_FUNC_ENA_SPI2) | \ - BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - ) \ + .backup_clk = 0xffffffff, \ } const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) diff --git a/components/esp_hw_support/port/esp32c61/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c61/private_include/pmu_param.h index 80aaac61ee96..4a7516a4f932 100644 --- a/components/esp_hw_support/port/esp32c61/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c61/private_include/pmu_param.h @@ -90,7 +90,7 @@ const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mo typedef struct { pmu_hp_backup_reg_t retention; - uint32_t backup_clk; + uint32_t backup_clk; // icg_func } pmu_hp_system_retention_param_t; const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode); diff --git a/components/esp_hw_support/port/esp32c61/rtc_clk.c b/components/esp_hw_support/port/esp32c61/rtc_clk.c index e46cdbe1c480..5c32d173585a 100644 --- a/components/esp_hw_support/port/esp32c61/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c61/rtc_clk.c @@ -327,10 +327,7 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { rtc_clk_cpu_set_to_default_config(); - // We don't turn off the bbpll if some consumers depend on bbpll - if (!s_bbpll_digi_consumers_ref_count) { - rtc_clk_bbpll_disable(); - } + rtc_clk_bbpll_disable(); } void rtc_clk_cpu_set_to_default_config(void) @@ -338,6 +335,7 @@ void rtc_clk_cpu_set_to_default_config(void) int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); + s_cur_pll_freq = 0; // no disable PLL, but set freq to 0 to trigger a PLL calibration after wake-up from sleep } void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz) diff --git a/components/esp_hw_support/port/esp32h2/include/soc/rtc.h b/components/esp_hw_support/port/esp32h2/include/soc/rtc.h index dfd1f96f0197..fa820b48d82b 100644 --- a/components/esp_hw_support/port/esp32h2/include/soc/rtc.h +++ b/components/esp_hw_support/port/esp32h2/include/soc/rtc.h @@ -354,8 +354,9 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. * - * @note On ESP32H2, this function will check whether BBPLL can be disabled. If there is no consumer, then BBPLL will be - * turned off. The behaviour is the same as using rtc_clk_cpu_freq_set_config to switch cpu clock source to XTAL. + * @note This function always disables BBPLL after switching the CPU clock source to XTAL for power saving purpose. + * If this is unwanted, please use rtc_clk_cpu_freq_set_config. It helps to check whether USB Serial JTAG is in use, + * if so, then BBPLL will not be turned off. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/esp_hw_support/port/esp32h2/pmu_param.c b/components/esp_hw_support/port/esp32h2/pmu_param.c index 036792a6faae..f9de2ca5aebe 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_param.c +++ b/components/esp_hw_support/port/esp32h2/pmu_param.c @@ -290,18 +290,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2active_backup_en = 0, \ .hp_modem2active_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_GDMA) \ - | BIT(PMU_ICG_FUNC_ENA_REGDMA) \ - | BIT(PMU_ICG_FUNC_ENA_TG0) \ - | BIT(PMU_ICG_FUNC_ENA_HPBUS) \ - | BIT(PMU_ICG_FUNC_ENA_MSPI) \ - | BIT(PMU_ICG_FUNC_ENA_IOMUX) \ - | BIT(PMU_ICG_FUNC_ENA_SPI2) \ - | BIT(PMU_ICG_FUNC_ENA_SEC) \ - | BIT(PMU_ICG_FUNC_ENA_PWM) \ - | BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - | BIT(PMU_ICG_FUNC_ENA_UART0)), \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \ @@ -313,16 +302,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \ .hp_sleep2modem_backup_en = 0, \ }, \ - .backup_clk = (BIT(PMU_ICG_FUNC_ENA_REGDMA) \ - | BIT(PMU_ICG_FUNC_ENA_TG0) \ - | BIT(PMU_ICG_FUNC_ENA_HPBUS) \ - | BIT(PMU_ICG_FUNC_ENA_MSPI) \ - | BIT(PMU_ICG_FUNC_ENA_IOMUX) \ - | BIT(PMU_ICG_FUNC_ENA_SPI2) \ - | BIT(PMU_ICG_FUNC_ENA_SEC) \ - | BIT(PMU_ICG_FUNC_ENA_PWM) \ - | BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - | BIT(PMU_ICG_FUNC_ENA_UART0)), \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \ @@ -339,18 +319,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_modem2sleep_backup_en = 0, \ .hp_active2sleep_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_GDMA) \ - | BIT(PMU_ICG_FUNC_ENA_REGDMA) \ - | BIT(PMU_ICG_FUNC_ENA_TG0) \ - | BIT(PMU_ICG_FUNC_ENA_HPBUS) \ - | BIT(PMU_ICG_FUNC_ENA_MSPI) \ - | BIT(PMU_ICG_FUNC_ENA_IOMUX) \ - | BIT(PMU_ICG_FUNC_ENA_SPI2) \ - | BIT(PMU_ICG_FUNC_ENA_SEC) \ - | BIT(PMU_ICG_FUNC_ENA_PWM) \ - | BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - | BIT(PMU_ICG_FUNC_ENA_UART0)), \ + .backup_clk = 0xffffffff, \ } const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) @@ -366,21 +335,14 @@ const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pm /** LP system default parameter */ - -#if CONFIG_ESP_SYSTEM_RTC_EXT_XTAL -# define PMU_SLOW_CLK_USE_EXT_XTAL (1) -#else -# define PMU_SLOW_CLK_USE_EXT_XTAL (0) -#endif - #define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \ .dig_power = { \ .mem_dslp = 0, \ .peri_pd_en = 0, \ }, \ .clk_power = { \ - .xpd_xtal32k = PMU_SLOW_CLK_USE_EXT_XTAL, \ - .xpd_rc32k = 0, \ + .xpd_xtal32k = 1, \ + .xpd_rc32k = 1, \ .xpd_fosc = 1, \ .pd_osc = 0 \ } \ diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index ab32613ab59d..60492aa4de1f 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -20,6 +20,8 @@ #include "hal/efuse_ll.h" #include "hal/efuse_hal.h" #include "esp_hw_log.h" +#include "soc/regi2c_bias.h" +#include "regi2c_ctrl.h" static __attribute__((unused)) const char *TAG = "pmu_sleep"; @@ -264,6 +266,8 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp bool pmu_sleep_finish(bool dslp) { (void)dslp; + // Restore registers lost during sleep + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_0P8, 8); // fix low temp issue, need to increase this internal voltage return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev); } diff --git a/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h index 58fbf97ff48b..bb89da8b001c 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h @@ -85,7 +85,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m typedef struct { pmu_hp_backup_reg_t retention; - uint32_t backup_clk; + uint32_t backup_clk; // icg_func } pmu_hp_system_retention_param_t; const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode); @@ -340,7 +340,7 @@ typedef struct { }, \ .lp_sys[PMU_MODE_LP_SLEEP] = { \ .analog = { \ - .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .drv_b = PMU_LP_DRVB_LIGHTSLEEP, \ .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ @@ -407,7 +407,7 @@ typedef struct { typedef struct pmu_sleep_machine_constant { struct { - uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */ + uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */ uint8_t reserved0; uint16_t reserved1; uint16_t analog_wait_time_us; /* LP LDO power up wait time (unit: microsecond) */ @@ -418,7 +418,7 @@ typedef struct pmu_sleep_machine_constant { uint16_t power_up_wait_time_us; /* (unit: microsecond) */ } lp; struct { - uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */ + uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */ uint16_t analog_wait_time_us; /* HP LDO power up wait time (unit: microsecond) */ uint16_t power_supply_wait_time_us; /* (unit: microsecond) */ uint16_t power_up_wait_time_us; /* (unit: microsecond) */ diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk.c b/components/esp_hw_support/port/esp32h2/rtc_clk.c index 0c6664fdce84..7a8a82ef5948 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk.c @@ -393,10 +393,7 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { rtc_clk_cpu_set_to_default_config(); - // We don't turn off the bbpll if some consumers only depends on bbpll - if (!s_bbpll_digi_consumers_ref_count) { - rtc_clk_bbpll_disable(); - } + rtc_clk_bbpll_disable(); } void rtc_clk_cpu_set_to_default_config(void) @@ -404,6 +401,7 @@ void rtc_clk_cpu_set_to_default_config(void) int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); + s_cur_pll_freq = 0; // no disable PLL, but set freq to 0 to trigger a PLL calibration after wake-up from sleep } soc_xtal_freq_t rtc_clk_xtal_freq_get(void) diff --git a/components/esp_hw_support/port/esp32p4/Kconfig.hw_support b/components/esp_hw_support/port/esp32p4/Kconfig.hw_support index fe31a3aebef1..46f9a88f302c 100644 --- a/components/esp_hw_support/port/esp32p4/Kconfig.hw_support +++ b/components/esp_hw_support/port/esp32p4/Kconfig.hw_support @@ -13,12 +13,15 @@ choice ESP32P4_REV_MIN bool "Rev v0.0" config ESP32P4_REV_MIN_1 bool "Rev v0.1" + config ESP32P4_REV_MIN_100 + bool "Rev v1.0" endchoice config ESP32P4_REV_MIN_FULL int default 0 if ESP32P4_REV_MIN_0 default 1 if ESP32P4_REV_MIN_1 + default 100 if ESP32P4_REV_MIN_100 config ESP_REV_MIN_FULL int @@ -28,7 +31,7 @@ config ESP_REV_MIN_FULL # MAX Revision # - comment "Maximum Supported ESP32-P4 Revision (Rev v0.99)" + comment "Maximum Supported ESP32-P4 Revision (Rev v1.99)" # Maximum revision that IDF supports. # It can not be changed by user. # Only Espressif can change it when a new version will be supported in IDF. @@ -36,7 +39,7 @@ config ESP_REV_MIN_FULL config ESP32P4_REV_MAX_FULL int - default 99 + default 199 # keep in sync the "Maximum Supported Revision" description with this value config ESP_REV_MAX_FULL diff --git a/components/esp_hw_support/port/esp32p4/include/soc/rtc.h b/components/esp_hw_support/port/esp32p4/include/soc/rtc.h index 183f8a79fe60..43acaa253faf 100644 --- a/components/esp_hw_support/port/esp32p4/include/soc/rtc.h +++ b/components/esp_hw_support/port/esp32p4/include/soc/rtc.h @@ -350,8 +350,8 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. * - * @note On ESP32C6, this function will check whether BBPLL can be disabled. If there is no consumer, then BBPLL will be - * turned off. The behaviour is the same as using rtc_clk_cpu_freq_set_config to switch cpu clock source to XTAL. + * @note On ESP32P4, this function always disables CPLL after switching the CPU clock source to XTAL, + * since there is no peripheral relies on CPLL clock (except Flash/PSRAM if their clock source selects CPLL). */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/esp_hw_support/port/esp32p4/pmu_init.c b/components/esp_hw_support/port/esp32p4/pmu_init.c index 92d67002fdf9..ffebc6a0e22c 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_init.c +++ b/components/esp_hw_support/port/esp32p4/pmu_init.c @@ -9,8 +9,10 @@ #include #include "sdkconfig.h" #include "esp_attr.h" +#include "soc/chip_revision.h" #include "soc/soc.h" #include "soc/pmu_struct.h" +#include "hal/efuse_hal.h" #include "hal/pmu_hal.h" #include "pmu_param.h" #include "esp_private/esp_pmu.h" @@ -84,7 +86,9 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep); pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd); pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd); - pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias); + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100) && (mode == PMU_MODE_HP_SLEEP)) { + pmu_ll_hp_enable_sleep_flash_ldo_channel(ctx->hal->dev, anlg->regulator0.xpd_0p1a); + } pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias); pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b); diff --git a/components/esp_hw_support/port/esp32p4/pmu_param.c b/components/esp_hw_support/port/esp32p4/pmu_param.c index 0905a1268a4a..44b73bd6a1b4 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_param.c +++ b/components/esp_hw_support/port/esp32p4/pmu_param.c @@ -153,8 +153,8 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .dbias_init = 1, \ .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ - .slp_mem_dbias = 0, \ - .slp_logic_dbias = 0, \ + .slp_mem_dbias = 1, /* slp_mem_dbias bit[3] controls ext_ldo_1 xpd for rev1.0*/ \ + .slp_logic_dbias = 0, \ }, \ .regulator1 = { \ .drv_b = 0x0 \ @@ -173,8 +173,8 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .regulator0 = { \ .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ - .slp_mem_dbias = 0, \ - .slp_logic_dbias = 0, \ + .slp_mem_dbias = 1, /* slp_mem_dbias bit[3] controls ext_ldo_1 xpd for rev1.0*/ \ + .slp_logic_dbias = 0, \ }, \ .regulator1 = { \ .drv_b = 0x0 \ @@ -208,18 +208,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2active_backup_en = 0, \ .hp_modem2active_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_L2MEM_MEM) | \ - BIT(PMU_ICG_FUNC_ENA_L2MEM_SYS) | \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_HP_CLKRST) | \ - BIT(PMU_ICG_FUNC_ENA_SYSREG_APB) | \ - BIT(PMU_ICG_FUNC_ENA_ICM_CPU) | \ - BIT(PMU_ICG_FUNC_ENA_ICM_APB) | \ - BIT(PMU_ICG_FUNC_ENA_ICM_SYS) | \ - BIT(PMU_ICG_FUNC_ENA_ICM_MEM) | \ - BIT(PMU_ICG_FUNC_ENA_INTRMTX_APB) \ - ) \ + .backup_clk = 0xffffffff, \ } #define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \ @@ -236,18 +225,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_modem2sleep_backup_en = 0, \ .hp_active2sleep_backup_en = 0, \ }, \ - .backup_clk = ( \ - BIT(PMU_ICG_FUNC_ENA_L2MEM_MEM) | \ - BIT(PMU_ICG_FUNC_ENA_L2MEM_SYS) | \ - BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ - BIT(PMU_ICG_FUNC_ENA_HP_CLKRST) | \ - BIT(PMU_ICG_FUNC_ENA_SYSREG_APB) | \ - BIT(PMU_ICG_FUNC_ENA_ICM_CPU) | \ - BIT(PMU_ICG_FUNC_ENA_ICM_APB) | \ - BIT(PMU_ICG_FUNC_ENA_ICM_SYS) | \ - BIT(PMU_ICG_FUNC_ENA_ICM_MEM) | \ - BIT(PMU_ICG_FUNC_ENA_INTRMTX_APB) \ - ) \ + .backup_clk = 0xffffffff, \ } const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index 97c112aa6b52..64ea630d3232 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -29,11 +29,15 @@ #include "hal/pmu_hal.h" #include "hal/psram_ctrlr_ll.h" #include "hal/lp_sys_ll.h" +#include "hal/clk_gate_ll.h" #include "esp_private/esp_pmu.h" #include "pmu_param.h" #include "esp_rom_sys.h" #include "esp_rom_uart.h" #include "hal/efuse_hal.h" +#if CONFIG_SPIRAM +#include "hal/ldo_ll.h" +#endif #define HP(state) (PMU_MODE_HP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state) @@ -154,6 +158,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->digital = digital_default; pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags); + analog_default.hp_sys.analog.xpd_0p1a = 0; config->analog = analog_default; } else { // Get light sleep digital_default @@ -164,6 +169,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags); #if CONFIG_SPIRAM + // Adjust analog parameters to keep EXT_LDO PSRAM channel volt outputting during light-sleep. analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON; analog_default.lp_sys[PMU_MODE_LP_SLEEP].analog.pd_cur = PMU_PD_CUR_SLEEP_ON; #endif @@ -190,6 +196,11 @@ const pmu_sleep_config_t* pmu_sleep_config_default( analog_default.hp_sys.analog.dcm_vset = CONFIG_ESP_SLEEP_DCM_VSET_VAL_IN_SLEEP; analog_default.hp_sys.analog.dcm_mode = 1; #endif + if (sleep_flags & PMU_SLEEP_PD_VDDSDIO) { + analog_default.hp_sys.analog.xpd_0p1a = 0; + } else { + analog_default.hp_sys.analog.xpd_0p1a = 1; + } config->analog = analog_default; } @@ -202,6 +213,10 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->analog.hp_sys.analog.dbias = HP_CALI_ACTIVE_DBIAS_DEFAULT; } + if (sleep_flags & RTC_SLEEP_LP_PERIPH_USE_XTAL) { + _clk_gate_ll_xtal_to_lp_periph_en(true); + } + config->power = power_default; pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags); config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period); @@ -239,7 +254,9 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd); pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd); pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd); - pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_dbias); + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) { + pmu_ll_hp_enable_sleep_flash_ldo_channel(ctx->hal->dev, analog->hp_sys.analog.xpd_0p1a); + } pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias); pmu_ll_hp_set_dbg_atten (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbg_atten); pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); @@ -351,6 +368,14 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, rtc_clk_mpll_disable(); } + +#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM + // Disable PSRAM chip power supply + if (dslp) { + ldo_ll_enable(LDO_ID2UNIT(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN), false); + } +#endif + /* Start entry into sleep mode */ pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev); @@ -359,6 +384,13 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, ; } +#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM + // Enable PSRAM chip power supply after deepsleep request rejected + if (dslp) { + ldo_ll_enable(LDO_ID2UNIT(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN), true); + } +#endif + return pmu_sleep_finish(dslp); } diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h index 9c8be63ac555..4ad678bd334e 100644 --- a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h @@ -86,7 +86,7 @@ const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mo typedef struct { pmu_hp_backup_reg_t retention; - uint32_t backup_clk; + uint32_t backup_clk; // icg_func } pmu_hp_system_retention_param_t; const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode); @@ -173,7 +173,7 @@ typedef struct { uint32_t slp_mem_xpd : 1; uint32_t slp_logic_xpd : 1; uint32_t xpd : 1; - uint32_t slp_mem_dbias : 4; + uint32_t xpd_0p1a : 1; // Should map to slp_mem_dbias bit[3] on hardware. uint32_t slp_logic_dbias: 4; uint32_t dbias : 5; }; diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk.c b/components/esp_hw_support/port/esp32p4/rtc_clk.c index aa3bfd967505..f9e19ce08c44 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk.c @@ -426,6 +426,7 @@ void rtc_clk_cpu_set_to_default_config(void) int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, true); + s_cur_cpll_freq = 0; // no disable PLL, but set freq to 0 to trigger a PLL calibration after wake-up from sleep } soc_xtal_freq_t rtc_clk_xtal_freq_get(void) diff --git a/components/esp_hw_support/port/regdma_link.c b/components/esp_hw_support/port/regdma_link.c index a090ea0b25d4..69db06f5e08f 100644 --- a/components/esp_hw_support/port/regdma_link.c +++ b/components/esp_hw_support/port/regdma_link.c @@ -15,6 +15,7 @@ #include "esp_heap_caps.h" #include "esp_log.h" #include "esp_regdma.h" +#include "esp_compiler.h" @@ -419,6 +420,7 @@ static void * regdma_link_get_instance(void *link) return container_memaddr[it]; } +ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-null-dereference") // TODO IDF-11384 static regdma_link_stats_t * regdma_link_get_stats(void *link) { const static size_t stats_offset[] = { @@ -437,6 +439,7 @@ static regdma_link_stats_t * regdma_link_get_stats(void *link) return (regdma_link_stats_t *)(regdma_link_get_instance(link) + stats_offset[it]); } +ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-null-dereference") static void regdma_link_update_stats_wrapper(void *link, int entry, int depth) { diff --git a/components/esp_hw_support/regi2c_ctrl.c b/components/esp_hw_support/regi2c_ctrl.c index 1d63f6668643..14c8e4034518 100644 --- a/components/esp_hw_support/regi2c_ctrl.c +++ b/components/esp_hw_support/regi2c_ctrl.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,6 +12,7 @@ #include "hal/regi2c_ctrl.h" #include "hal/regi2c_ctrl_ll.h" #include "esp_hw_log.h" +#include "soc/soc_caps.h" static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; @@ -109,3 +110,21 @@ void regi2c_saradc_disable(void) regi2c_exit_critical(); } + +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + +#include "soc/regi2c_saradc.h" + +static DRAM_ATTR uint8_t dac_offset_regi2c; + +void IRAM_ATTR regi2c_tsens_reg_read(void) +{ + dac_offset_regi2c = REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC); +} + +void IRAM_ATTR regi2c_tsens_reg_write(void) +{ + REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, dac_offset_regi2c); +} + +#endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index ed81134542d6..297c9db14de9 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -12,6 +12,7 @@ #include "esp_attr.h" #include "esp_rom_caps.h" +#include "esp_macros.h" #include "esp_memory_utils.h" #include "esp_sleep.h" #include "esp_private/esp_sleep_internal.h" @@ -222,7 +223,7 @@ typedef struct { } domain[ESP_PD_DOMAIN_MAX]; portMUX_TYPE lock; uint64_t sleep_duration; - uint32_t wakeup_triggers : 15; + uint32_t wakeup_triggers : 20; #if SOC_PM_SUPPORT_EXT1_WAKEUP uint32_t ext1_trigger_mode : 22; // 22 is the maximum RTCIO number in all chips uint32_t ext1_rtc_gpio_mask : 22; @@ -679,6 +680,9 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_s #endif #if REGI2C_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_read(); +#endif +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + regi2c_tsens_reg_read(); #endif } @@ -724,6 +728,9 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags) #if REGI2C_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_write(); #endif +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + regi2c_tsens_reg_write(); +#endif } static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp) @@ -803,7 +810,16 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m // Save current frequency and switch to XTAL rtc_cpu_freq_config_t cpu_freq_config; rtc_clk_cpu_freq_get_config(&cpu_freq_config); +#if SOC_PMU_SUPPORTED + // For PMU supported chips, CPU's PLL power can be turned off by PMU, so no need to disable the PLL at here. + // Leaving PLL on at this stage also helps USJ keep connection and retention operation (if they rely on this PLL). + rtc_clk_cpu_set_to_default_config(); +#else + // For earlier chips, there is no PMU module that can turn off the CPU's PLL, so it has to be disabled at here to save the power consumption. + // Though ESP32C3/S3 has USB CDC device, it can not function properly during sleep due to the lack of APB clock (before C6, USJ relies on APB clock to work). + // Therefore, we will always disable CPU's PLL (i.e. BBPLL). rtc_clk_cpu_freq_set_xtal(); +#endif #if SOC_PM_SUPPORT_EXT0_WAKEUP // Configure pins for external wakeup @@ -901,7 +917,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m uint32_t sleep_flags = pd_flags; if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_RC_FAST_MODE] && !deep_sleep) { - pd_flags &= ~RTC_SLEEP_PD_INT_8M; + sleep_flags &= ~RTC_SLEEP_PD_INT_8M; sleep_flags |= RTC_SLEEP_DIG_USE_8M; } @@ -917,6 +933,12 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m sleep_flags |= RTC_SLEEP_XTAL_AS_RTC_FAST; } +#if SOC_LP_VAD_SUPPORTED + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_LP_USE_XTAL_MODE] && !deep_sleep) { + sleep_flags |= RTC_SLEEP_LP_PERIPH_USE_XTAL; + } +#endif + #if CONFIG_ESP_SLEEP_DEBUG if (s_sleep_ctx != NULL) { s_sleep_ctx->sleep_flags = sleep_flags; @@ -1106,12 +1128,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CLK_READY, (void *)0); if (!deep_sleep) { - s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); + if (result == ESP_OK) { + s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); #if SOC_PM_RETENTION_SW_TRIGGER_REGDMA - if (pd_flags & PMU_SLEEP_PD_TOP) { - sleep_retention_do_system_retention(false); - } + if (pd_flags & PMU_SLEEP_PD_TOP) { + sleep_retention_do_system_retention(false); + } #endif + } misc_modules_wake_prepare(pd_flags); } @@ -1215,9 +1239,7 @@ static esp_err_t IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection) } else { // Because RTC is in a slower clock domain than the CPU, it // can take several CPU cycles for the sleep mode to start. - while (1) { - ; - } + ESP_INFINITE_LOOP(); } // Never returns here, except that the sleep is rejected. esp_ipc_isr_stall_resume(); @@ -1266,7 +1288,7 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, #endif // If SPI flash was powered down, wait for it to become ready - if (pd_flags & RTC_SLEEP_PD_VDDSDIO) { + if (!reject && (pd_flags & RTC_SLEEP_PD_VDDSDIO)) { #if SOC_PM_SUPPORT_TOP_PD if (pd_flags & PMU_SLEEP_PD_TOP) { uint32_t flash_ready_hw_waited_time_us = pmu_sleep_get_wakup_retention_cost(); @@ -1492,33 +1514,28 @@ esp_err_t esp_light_sleep_start(void) // Enter sleep, then wait for flash to be ready on wakeup err = esp_light_sleep_inner(pd_flags, flash_enable_time_us); } -#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW - if (err != ESP_OK) { - esp_sleep_cpu_skip_retention(); - } -#endif // light sleep wakeup flag only makes sense after a successful light sleep s_light_sleep_wakeup = (err == ESP_OK); // System timer has been stopped for the duration of the sleep, correct for that. uint64_t rtc_ticks_at_end = rtc_time_get(); - uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period); -#if CONFIG_ESP_SLEEP_DEBUG - if (s_sleep_ctx != NULL) { - s_sleep_ctx->sleep_out_rtc_time_stamp = rtc_ticks_at_end; - } + if (s_light_sleep_wakeup) { + uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period); + /** + * If sleep duration is too small(less than 1 rtc_slow_clk cycle), rtc_time_diff will be zero. + * In this case, just ignore the time compensation and keep esp_timer monotonic. + */ + if (rtc_time_diff > 0) { + esp_timer_private_set(high_res_time_at_start + rtc_time_diff); + } + esp_set_time_from_rtc(); + } else { +#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW + esp_sleep_cpu_skip_retention(); #endif - - /** - * If sleep duration is too small(less than 1 rtc_slow_clk cycle), rtc_time_diff will be zero. - * In this case, just ignore the time compensation and keep esp_timer monotonic. - */ - if (rtc_time_diff > 0) { - esp_timer_private_set(high_res_time_at_start + rtc_time_diff); } - esp_set_time_from_rtc(); esp_clk_private_unlock(); esp_timer_private_unlock(); @@ -1553,14 +1570,18 @@ esp_err_t esp_light_sleep_start(void) #endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_EXIT_SLEEP, (void *)0); - s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); #if CONFIG_ESP_SLEEP_DEBUG if (s_sleep_ctx != NULL) { + s_sleep_ctx->sleep_out_rtc_time_stamp = rtc_ticks_at_end; s_sleep_ctx->sleep_request_result = err; } #endif + if (s_light_sleep_wakeup) { + s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); + } + portEXIT_CRITICAL(&s_config.lock); return err; } @@ -1645,6 +1666,14 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us) return ESP_OK; } +#if SOC_LP_VAD_SUPPORTED +esp_err_t esp_sleep_enable_vad_wakeup(void) +{ + s_config.wakeup_triggers |= RTC_LP_VAD_TRIG_EN; + return esp_sleep_sub_mode_config(ESP_SLEEP_LP_USE_XTAL_MODE, true); +} +#endif + static esp_err_t timer_wakeup_prepare(int64_t sleep_duration) { if (sleep_duration < 0) { @@ -2165,6 +2194,10 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) #if SOC_LP_CORE_SUPPORTED } else if (wakeup_cause & RTC_LP_CORE_TRIG_EN) { return ESP_SLEEP_WAKEUP_ULP; +#endif +#if SOC_LP_VAD_SUPPORTED + } else if (wakeup_cause & RTC_LP_VAD_TRIG_EN) { + return ESP_SLEEP_WAKEUP_VAD; #endif } else { return ESP_SLEEP_WAKEUP_UNDEFINED; @@ -2229,6 +2262,7 @@ int32_t* esp_sleep_sub_mode_dump_config(FILE *stream) { [ESP_SLEEP_ULTRA_LOW_MODE] = "ESP_SLEEP_ULTRA_LOW_MODE", [ESP_SLEEP_RTC_FAST_USE_XTAL_MODE] = "ESP_SLEEP_RTC_FAST_USE_XTAL_MODE", [ESP_SLEEP_DIG_USE_XTAL_MODE] = "ESP_SLEEP_DIG_USE_XTAL_MODE", + [ESP_SLEEP_LP_USE_XTAL_MODE] = "ESP_SLEEP_LP_USE_XTAL_MODE", }[mode], s_sleep_sub_mode_ref_cnt[mode] ? "ENABLED" : "DISABLED", s_sleep_sub_mode_ref_cnt[mode]); @@ -2339,6 +2373,11 @@ static uint32_t get_power_down_flags(void) if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option == ESP_PD_OPTION_AUTO) { #ifndef CONFIG_ESP_SLEEP_POWER_DOWN_FLASH s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON; +#endif +#if CONFIG_IDF_TARGET_ESP32P4 + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) { + s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON; + } #endif } #endif @@ -2427,6 +2466,13 @@ static uint32_t get_power_down_flags(void) } #endif +#if CONFIG_IDF_TARGET_ESP32P4 + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) { + if (pd_flags & RTC_SLEEP_PD_VDDSDIO) { + ESP_LOGE(TAG, "ESP32P4 chips lower than v1.0 are not allowed to power down the Flash"); + } + } +#endif return pd_flags; } diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index e437a6fe5813..7e01204a6edf 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -29,6 +29,8 @@ #endif static __attribute__((unused)) const char *TAG = "sleep"; +static int acquire_cnt; //for the force acquire lock + struct sleep_retention_module_object { sleep_retention_module_callbacks_t cbs; /* A callback list that can extend more sleep retention event callbacks */ @@ -319,6 +321,23 @@ static void sleep_retention_entries_stats(void) _lock_release_recursive(&s_retention.lock); } +void sleep_retention_dump_modules(FILE *out) +{ + uint32_t inited_modules = sleep_retention_get_inited_modules(); + uint32_t created_modules = sleep_retention_get_created_modules(); + for (int i = SLEEP_RETENTION_MODULE_MIN; i <= SLEEP_RETENTION_MODULE_MAX; i++) { + bool inited = (inited_modules & BIT(i)) != 0; + bool created = (created_modules & BIT(i)) != 0; + bool is_top = (TOP_DOMAIN_PERIPHERALS_BM & BIT(i)) != 0; + + const char* status = !inited? "-": + created? "CREATED": + "INITED"; + const char* domain = is_top? "TOP": "-"; + fprintf(out, "%2d: %4s %8s\n", i, domain, status); + } +} + void sleep_retention_dump_entries(FILE *out) { _lock_acquire_recursive(&s_retention.lock); @@ -820,6 +839,42 @@ esp_err_t sleep_retention_module_free(sleep_retention_module_t module) return err; } +static esp_err_t empty_create(void *args) +{ + return ESP_OK; +} + +esp_err_t sleep_retention_power_lock_acquire(void) +{ + _lock_acquire_recursive(&s_retention.lock); + if (acquire_cnt == 0) { + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = {.handle = empty_create},}, + }; + esp_err_t ret = sleep_retention_module_init(SLEEP_RETENTION_MODULE_NULL, &init_param); + if (ret != ESP_OK) { + _lock_release_recursive(&s_retention.lock); + return ret; + } + } + acquire_cnt++; + _lock_release_recursive(&s_retention.lock); + return ESP_OK; +} + +esp_err_t sleep_retention_power_lock_release(void) +{ + esp_err_t ret = ESP_OK; + _lock_acquire_recursive(&s_retention.lock); + acquire_cnt--; + assert(acquire_cnt >= 0); + if (acquire_cnt == 0) { + ret = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_NULL); + } + _lock_release_recursive(&s_retention.lock); + return ret; +} + void IRAM_ATTR sleep_retention_do_extra_retention(bool backup_or_restore) { if (s_retention.highpri < SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY || diff --git a/components/esp_hw_support/test_apps/.build-test-rules.yml b/components/esp_hw_support/test_apps/.build-test-rules.yml index b61d8878c6c9..0585429ebae6 100644 --- a/components/esp_hw_support/test_apps/.build-test-rules.yml +++ b/components/esp_hw_support/test_apps/.build-test-rules.yml @@ -42,6 +42,15 @@ components/esp_hw_support/test_apps/rtc_power_modes: temporary: true reason: the other targets are not tested yet +components/esp_hw_support/test_apps/sleep_retention: + enable: + - if: SOC_PAU_SUPPORTED == 1 and CONFIG_NAME != "xip_psram" + - if: SOC_PAU_SUPPORTED == 1 and (SOC_SPIRAM_XIP_SUPPORTED == 1 and CONFIG_NAME == "xip_psram") + +components/esp_hw_support/test_apps/vad_wakeup: + disable: + - if: SOC_LP_VAD_SUPPORTED != 1 + components/esp_hw_support/test_apps/wakeup_tests: disable: - if: IDF_TARGET in ["esp32c5", "esp32p4", "linux", "esp32c61"] diff --git a/components/esp_hw_support/test_apps/dma/main/test_dw_gdma.c b/components/esp_hw_support/test_apps/dma/main/test_dw_gdma.c index eb927a04b6a1..45eeb11c320f 100644 --- a/components/esp_hw_support/test_apps/dma/main/test_dw_gdma.c +++ b/components/esp_hw_support/test_apps/dma/main/test_dw_gdma.c @@ -380,6 +380,7 @@ static bool test_dw_gdma_list_mode_invalid_block_cb(dw_gdma_channel_handle_t cha udata->count++; // clear the destination buffer memset(udata->dst_buffer_addr, 0, udata->dst_buffer_size); + esp_cache_msync(udata->dst_buffer_addr, udata->dst_buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); dw_gdma_block_markers_t markers = { .is_last = true, // mark the next block as the last one .is_valid = true, // mark the block as valid so that the DMA can continue the transfer diff --git a/components/esp_hw_support/test_apps/dma/pytest_dma.py b/components/esp_hw_support/test_apps/dma/pytest_dma.py index 3d78de4a8493..1d741f14fb12 100644 --- a/components/esp_hw_support/test_apps/dma/pytest_dma.py +++ b/components/esp_hw_support/test_apps/dma/pytest_dma.py @@ -21,7 +21,7 @@ indirect=True, ) def test_dma(dut: Dut) -> None: - dut.run_all_single_board_cases() + dut.run_all_single_board_cases(reset=True) @pytest.mark.esp32s3 @@ -34,4 +34,4 @@ def test_dma(dut: Dut) -> None: indirect=True, ) def test_dma_psram(dut: Dut) -> None: - dut.run_all_single_board_cases() + dut.run_all_single_board_cases(reset=True) diff --git a/components/esp_hw_support/test_apps/sleep_retention/CMakeLists.txt b/components/esp_hw_support/test_apps/sleep_retention/CMakeLists.txt new file mode 100644 index 000000000000..47e7d817bd33 --- /dev/null +++ b/components/esp_hw_support/test_apps/sleep_retention/CMakeLists.txt @@ -0,0 +1,10 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. We also depend on esp_psram +# as we set CONFIG_SPIRAM_... options. +set(COMPONENTS main esp_psram) + +project(test_retention) diff --git a/components/esp_hw_support/test_apps/sleep_retention/README.md b/components/esp_hw_support/test_apps/sleep_retention/README.md new file mode 100644 index 000000000000..77eda1867c07 --- /dev/null +++ b/components/esp_hw_support/test_apps/sleep_retention/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | diff --git a/components/esp_hw_support/test_apps/sleep_retention/main/CMakeLists.txt b/components/esp_hw_support/test_apps/sleep_retention/main/CMakeLists.txt new file mode 100644 index 000000000000..d285f1b55256 --- /dev/null +++ b/components/esp_hw_support/test_apps/sleep_retention/main/CMakeLists.txt @@ -0,0 +1,7 @@ +set(srcs "test_app_main.c" "test_retention.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 +idf_component_register(SRCS ${srcs} + PRIV_REQUIRES unity esp_mm esp_psram + WHOLE_ARCHIVE) diff --git a/components/esp_hw_support/test_apps/sleep_retention/main/test_app_main.c b/components/esp_hw_support/test_apps/sleep_retention/main/test_app_main.c new file mode 100644 index 000000000000..027d2b69c056 --- /dev/null +++ b/components/esp_hw_support/test_apps/sleep_retention/main/test_app_main.c @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "esp_heap_caps.h" + +#define TEST_MEMORY_LEAK_THRESHOLD (-300) + +static size_t before_free_8bit; +static size_t before_free_32bit; + +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); + TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak"); +} + +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); +} + +void app_main(void) +{ + unity_run_menu(); +} diff --git a/components/esp_hw_support/test_apps/sleep_retention/main/test_retention.c b/components/esp_hw_support/test_apps/sleep_retention/main/test_retention.c new file mode 100644 index 000000000000..72a4e5b3e801 --- /dev/null +++ b/components/esp_hw_support/test_apps/sleep_retention/main/test_retention.c @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "sdkconfig.h" +#include "unity.h" +#include "esp_private/sleep_sys_periph.h" +#include "esp_private/sleep_retention.h" +#include "esp_sleep.h" +#include "esp_private/sleep_cpu.h" + +const char TAG[] = "retention"; + +TEST_CASE("retention: can go to retention", "[retention]") +{ + // Prepare a TOP PD sleep + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000)); + sleep_cpu_configure(true); + + TEST_ASSERT_EQUAL_INT32(true, peripheral_domain_pd_allowed()); + sleep_retention_dump_modules(stdout); + vTaskDelay(1000/portTICK_PERIOD_MS); + + ESP_LOGI(TAG, "Going to sleep..."); + esp_light_sleep_start(); + + ESP_LOGI(TAG, "After wakeup"); + TEST_ASSERT_EQUAL_INT32(true, peripheral_domain_pd_allowed()); + sleep_retention_dump_modules(stdout); + + sleep_cpu_configure(false); +} diff --git a/components/esp_hw_support/test_apps/sleep_retention/pytest_retention.py b/components/esp_hw_support/test_apps/sleep_retention/pytest_retention.py new file mode 100644 index 000000000000..3a4ca50f1eed --- /dev/null +++ b/components/esp_hw_support/test_apps/sleep_retention/pytest_retention.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import functools +from typing import Callable +from typing import Dict +from typing import List + +import pytest +from pytest_embedded import Dut + + +def target_list(targets: List[str]) -> Callable: + + def decorator(func: Callable) -> Callable: + + @functools.wraps(func) + def wrapper(*args: List, **kwargs: Dict) -> Callable: + return func(*args, **kwargs) # type: ignore + + for target in targets: + wrapper = pytest.mark.__getattr__(target)(wrapper) + + return wrapper + + return decorator + + +# SOC_PAU_SUPPORTED == 1 +retention_targets = ['esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'] + + +@target_list(retention_targets) +@pytest.mark.generic +def test_sleep_retention(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/soc/esp32c2/register/soc/.gitkeep b/components/esp_hw_support/test_apps/sleep_retention/sdkconfig.ci.defaults similarity index 100% rename from components/soc/esp32c2/register/soc/.gitkeep rename to components/esp_hw_support/test_apps/sleep_retention/sdkconfig.ci.defaults diff --git a/components/esp_hw_support/test_apps/sleep_retention/sdkconfig.ci.xip_psram b/components/esp_hw_support/test_apps/sleep_retention/sdkconfig.ci.xip_psram new file mode 100644 index 000000000000..358f51460be7 --- /dev/null +++ b/components/esp_hw_support/test_apps/sleep_retention/sdkconfig.ci.xip_psram @@ -0,0 +1,2 @@ +CONFIG_SPIRAM=y +CONFIG_SPIRAM_XIP_FROM_PSRAM=y diff --git a/components/esp_hw_support/test_apps/sleep_retention/sdkconfig.defaults b/components/esp_hw_support/test_apps/sleep_retention/sdkconfig.defaults new file mode 100644 index 000000000000..6cefbfaaf53a --- /dev/null +++ b/components/esp_hw_support/test_apps/sleep_retention/sdkconfig.defaults @@ -0,0 +1,6 @@ +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESP_TASK_WDT=n + +CONFIG_PM_ENABLE=y +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y diff --git a/components/esp_hw_support/test_apps/vad_wakeup/CMakeLists.txt b/components/esp_hw_support/test_apps/vad_wakeup/CMakeLists.txt new file mode 100644 index 000000000000..503656001154 --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/CMakeLists.txt @@ -0,0 +1,8 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(vad_wakeup) diff --git a/components/esp_hw_support/test_apps/vad_wakeup/README.md b/components/esp_hw_support/test_apps/vad_wakeup/README.md new file mode 100644 index 000000000000..f8ea707124d7 --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/README.md @@ -0,0 +1,3 @@ +| Supported Targets | ESP32-P4 | +| ----------------- | -------- | + diff --git a/components/esp_hw_support/test_apps/vad_wakeup/main/CMakeLists.txt b/components/esp_hw_support/test_apps/vad_wakeup/main/CMakeLists.txt new file mode 100644 index 000000000000..3a92a5d2bd7c --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/main/CMakeLists.txt @@ -0,0 +1,7 @@ +set(srcs "test_app_main.c" + "test_vad_wakeup.c") + +idf_component_register(SRCS ${srcs} + REQUIRES unity esp_driver_i2s esp_driver_uart ulp esp_timer + WHOLE_ARCHIVE + EMBED_FILES "test_vad_8k.pcm") diff --git a/components/esp_hw_support/test_apps/vad_wakeup/main/test_app_main.c b/components/esp_hw_support/test_apps/vad_wakeup/main/test_app_main.c new file mode 100644 index 000000000000..1d34b63e4462 --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/main/test_app_main.c @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "unity_test_utils.h" + +#define LEAKS (400) + + +void setUp(void) +{ + unity_utils_record_free_mem(); +} + +void tearDown(void) +{ + unity_utils_evaluate_leaks_direct(LEAKS); +} + +void app_main(void) +{ + unity_run_menu(); +} diff --git a/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_8k.pcm b/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_8k.pcm new file mode 100644 index 000000000000..5b6c32a03731 Binary files /dev/null and b/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_8k.pcm differ diff --git a/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_wakeup.c b/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_wakeup.c new file mode 100644 index 000000000000..2a245bfc6f37 --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/main/test_vad_wakeup.c @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "driver/uart.h" +#include "driver/lp_i2s.h" +#include "driver/lp_i2s_std.h" +#include "driver/i2s_std.h" +#include "ulp_lp_core_lp_vad_shared.h" +#include "unity.h" +#include "esp_timer.h" + +#define TEST_I2S_FRAME_SIZE (128) // Frame numbers in every writing / reading +#define TEST_I2S_TRANS_SIZE (4096) // Trans size +#define TEST_LP_I2S_PIN_BCK 4 +#define TEST_LP_I2S_PIN_WS 5 +#define TEST_LP_I2S_PIN_DIN 6 + + +extern const uint8_t test_vad_pcm_start[] asm("_binary_test_vad_8k_pcm_start"); +extern const uint8_t test_vad_pcm_end[] asm("_binary_test_vad_8k_pcm_end"); +static const char *TAG = "TEST_VAD"; + +static void s_hp_i2s_config(void) +{ + esp_err_t ret = ESP_FAIL; + int pcm_size = test_vad_pcm_end - test_vad_pcm_start; + printf("pcm_size: %d\n", pcm_size); + + i2s_chan_handle_t tx_handle = NULL; + i2s_chan_config_t i2s_channel_config = { + .id = I2S_NUM_0, + .role = I2S_ROLE_MASTER, + .dma_desc_num = 16, + .dma_frame_num = TEST_I2S_FRAME_SIZE, + .auto_clear = false, + }; + TEST_ESP_OK(i2s_new_channel(&i2s_channel_config, &tx_handle, NULL)); + + + i2s_std_config_t i2s_std_config = { + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = GPIO_NUM_7, + .ws = GPIO_NUM_8, + .dout = GPIO_NUM_21, + .din = -1, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + i2s_std_config.clk_cfg = (i2s_std_clk_config_t)I2S_STD_CLK_DEFAULT_CONFIG(16000); + i2s_std_config.slot_cfg = (i2s_std_slot_config_t)I2S_STD_PCM_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &i2s_std_config)); + + + uint8_t *txbuf = (uint8_t *)heap_caps_calloc(1, TEST_I2S_TRANS_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(txbuf); + + uint8_t *prebuf = (uint8_t *)heap_caps_calloc(1, TEST_I2S_TRANS_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(prebuf); + + memcpy(prebuf, test_vad_pcm_start, TEST_I2S_TRANS_SIZE); + memcpy(txbuf, test_vad_pcm_start, TEST_I2S_TRANS_SIZE); + + for (int i = 0; i < TEST_I2S_TRANS_SIZE; i++) { + ESP_LOGD(TAG, "prebuf[%d]: %d", i, prebuf[i]); + ESP_LOGD(TAG, "txbuf[%d]: %d", i, txbuf[i]); + } + + size_t bytes_written = 0; + TEST_ESP_OK(i2s_channel_preload_data(tx_handle, prebuf, TEST_I2S_TRANS_SIZE, &bytes_written)); + + TEST_ESP_OK(i2s_channel_enable(tx_handle)); + + while (1) { + ret = i2s_channel_write(tx_handle, txbuf, TEST_I2S_TRANS_SIZE, &bytes_written, 0); + if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) { + TEST_ESP_OK(ret); + } + ESP_LOGD(TAG, "bytes_written: %d", bytes_written); + vTaskDelay(1); + } +} + +static void s_lp_vad_config(void) +{ + ESP_ERROR_CHECK(esp_sleep_enable_vad_wakeup()); + ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)); + ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON)); + + lp_i2s_chan_handle_t rx_handle = NULL; + lp_i2s_chan_config_t config = { + .id = 0, + .role = I2S_ROLE_SLAVE, + .threshold = 512, + }; + TEST_ESP_OK(lp_i2s_new_channel(&config, NULL, &rx_handle)); + + lp_i2s_std_config_t lp_std_cfg = { + .pin_cfg = { + .bck = TEST_LP_I2S_PIN_BCK, + .ws = TEST_LP_I2S_PIN_WS, + .din = TEST_LP_I2S_PIN_DIN, + }, + }; + lp_std_cfg.slot_cfg = (lp_i2s_std_slot_config_t)LP_I2S_STD_PCM_SHORT_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + TEST_ESP_OK(lp_i2s_channel_init_std_mode(rx_handle, &lp_std_cfg)); + + // LP VAD Init + lp_vad_init_config_t init_config = { + .lp_i2s_chan = rx_handle, + .vad_config = { + .init_frame_num = 100, + .min_energy_thresh = 100, + .speak_activity_thresh = 10, + .non_speak_activity_thresh = 30, + .min_speak_activity_thresh = 3, + .max_speak_activity_thresh = 100, + }, + }; + TEST_ESP_OK(lp_core_lp_vad_init(0, &init_config)); + TEST_ESP_OK(lp_i2s_channel_enable(rx_handle)); + TEST_ESP_OK(lp_core_lp_vad_enable(0)); + + printf("Entering light sleep\n"); + /* To make sure the complete line is printed before entering sleep mode, + * need to wait until UART TX FIFO is empty: + */ + uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); + + /* Enter sleep mode */ + esp_light_sleep_start(); + + /* Determine wake up reason */ + const char* wakeup_reason; + switch (esp_sleep_get_wakeup_cause()) { + case ESP_SLEEP_WAKEUP_VAD: + wakeup_reason = "vad"; + break; + default: + wakeup_reason = "other"; + TEST_ASSERT(false); + break; + } + + ESP_LOGI(TAG, "wakeup, reason: %s", wakeup_reason); +} + +TEST_CASE_MULTIPLE_DEVICES("test LP VAD wakeup", "[vad][ignore][manual]", s_hp_i2s_config, s_lp_vad_config); diff --git a/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py b/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py new file mode 100644 index 000000000000..b4d9f85affd9 --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/pytest_wakeup_vad.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32p4 +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='lack of runners for now') +@pytest.mark.lp_i2s +def test_efuse(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_hw_support/test_apps/vad_wakeup/sdkconfig.defaults b/components/esp_hw_support/test_apps/vad_wakeup/sdkconfig.defaults new file mode 100644 index 000000000000..cac3f9a01f9a --- /dev/null +++ b/components/esp_hw_support/test_apps/vad_wakeup/sdkconfig.defaults @@ -0,0 +1,8 @@ +CONFIG_ESP_TASK_WDT_INIT=n + +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_TYPE_LP_CORE=y +CONFIG_ULP_COPROC_RESERVE_MEM=12000 +CONFIG_ULP_PANIC_OUTPUT_ENABLE=y + +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y diff --git a/components/esp_lcd/Kconfig b/components/esp_lcd/Kconfig index 1e6ee9407cb1..c247c58637e6 100644 --- a/components/esp_lcd/Kconfig +++ b/components/esp_lcd/Kconfig @@ -1,47 +1,40 @@ -menu "LCD and Touch Panel" - comment "LCD Touch Drivers are maintained in the ESP Component Registry" +menu "ESP-Driver:LCD Controller Configurations" + config LCD_ENABLE_DEBUG_LOG + bool "Enable debug log" + default n + help + whether to enable the debug log message for LCD driver. + Note that, this option only controls the LCD driver log, won't affect other drivers. - menu "LCD Peripheral Configuration" - config LCD_ENABLE_DEBUG_LOG - bool "Enable debug log" + if SOC_LCD_RGB_SUPPORTED + config LCD_RGB_ISR_IRAM_SAFE + bool "RGB LCD ISR IRAM-Safe" + select GDMA_ISR_IRAM_SAFE # bounce buffer mode relies on GDMA EOF interrupt default n help - whether to enable the debug log message for LCD driver. - Note that, this option only controls the LCD driver log, won't affect other drivers. + Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be + executable when the cache is disabled (e.g. SPI Flash write). + If you want the LCD driver to keep flushing the screen even when cache ops disabled, + you can enable this option. Note, this will also increase the IRAM usage. - if SOC_LCD_RGB_SUPPORTED - config LCD_RGB_ISR_IRAM_SAFE - bool "RGB LCD ISR IRAM-Safe" - default n - help - Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be - executable when the cache is disabled (e.g. SPI Flash write). - If you want the LCD driver to keep flushing the screen even when cache ops disabled, - you can enable this option. Note, this will also increase the IRAM usage. - - config LCD_RGB_RESTART_IN_VSYNC - bool "Restart transmission in VSYNC" - default n - select GDMA_CTRL_FUNC_IN_IRAM # need to restart GDMA in the LCD ISR - help - Reset the GDMA channel every VBlank to stop permanent desyncs from happening. - Only need to enable it when in your application, the DMA can't deliver data - as fast as the LCD consumes it. - endif # SOC_LCD_RGB_SUPPORTED + config LCD_RGB_RESTART_IN_VSYNC + bool "Always restart RGB LCD transmission in VSYNC" + default n + help + Reset the GDMA channel every VBlank to stop permanent desyncs from happening. + Only need to enable it when in your application, the DMA can't deliver data + as fast as the LCD consumes it. + endif # SOC_LCD_RGB_SUPPORTED - if SOC_MIPI_DSI_SUPPORTED - config LCD_DSI_ISR_IRAM_SAFE - bool "DSI LCD ISR IRAM-Safe" - default n - select DW_GDMA_ISR_IRAM_SAFE - select DW_GDMA_CTRL_FUNC_IN_IRAM - select DW_GDMA_SETTER_FUNC_IN_IRAM - select DW_GDMA_GETTER_FUNC_IN_IRAM - help - Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be - executable when the cache is disabled (e.g. SPI Flash write). - If you want the LCD driver to keep flushing the screen even when cache ops disabled, - you can enable this option. Note, this will also increase the IRAM usage. - endif # SOC_MIPI_DSI_SUPPORTED - endmenu + if SOC_MIPI_DSI_SUPPORTED + config LCD_DSI_ISR_IRAM_SAFE + bool "DSI LCD ISR IRAM-Safe" + default n + select DW_GDMA_ISR_IRAM_SAFE # relies on DW_GDMA Full trans done interrupt + help + Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be + executable when the cache is disabled (e.g. SPI Flash write). + If you want the LCD driver to keep flushing the screen even when cache ops disabled, + you can enable this option. Note, this will also increase the IRAM usage. + endif # SOC_MIPI_DSI_SUPPORTED endmenu diff --git a/components/esp_lcd/dsi/esp_lcd_panel_dpi.c b/components/esp_lcd/dsi/esp_lcd_panel_dpi.c index c41a8d7d6f9f..5a74f4376c2f 100644 --- a/components/esp_lcd/dsi/esp_lcd_panel_dpi.c +++ b/components/esp_lcd/dsi/esp_lcd_panel_dpi.c @@ -20,6 +20,7 @@ #include "esp_private/esp_clk_tree_common.h" #include "hal/cache_hal.h" #include "hal/cache_ll.h" +#include "hal/color_hal.h" static const char *TAG = "lcd.dsi.dpi"; @@ -40,7 +41,8 @@ struct esp_lcd_dpi_panel_t { uint32_t v_pixels; // Vertical pixels size_t fb_size; // Frame buffer size, in bytes size_t bits_per_pixel; // Bits per pixel - lcd_color_rgb_pixel_format_t pixel_format; // RGB Pixel format + lcd_color_format_t in_color_format; // Input color format + lcd_color_format_t out_color_format; // Output color format dw_gdma_channel_handle_t dma_chan; // DMA channel dw_gdma_link_list_handle_t link_lists[DPI_PANEL_MAX_FB_NUM]; // DMA link list esp_async_fbcpy_handle_t fbcpy_handle; // Use DMA2D to do frame buffer copy @@ -175,6 +177,19 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ bits_per_pixel = 24; break; } + lcd_color_format_t in_color_format = COLOR_TYPE_ID(COLOR_SPACE_RGB, panel_config->pixel_format); + // if user sets the in_color_format, it can override the pixel format setting + if (panel_config->in_color_format) { + color_space_pixel_format_t in_color_id = { + .color_type_id = panel_config->in_color_format, + }; + bits_per_pixel = color_hal_pixel_format_get_bit_depth(in_color_id); + in_color_format = panel_config->in_color_format; + } + lcd_color_format_t out_color_format = in_color_format; + if (panel_config->out_color_format) { + out_color_format = panel_config->out_color_format; + } ESP_RETURN_ON_FALSE(panel_config->video_timing.h_size * panel_config->video_timing.v_size * bits_per_pixel % 8 == 0, ESP_ERR_INVALID_ARG, TAG, "frame buffer size not aligned to byte boundary"); @@ -184,7 +199,8 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ dpi_panel = heap_caps_calloc(1, sizeof(esp_lcd_dpi_panel_t), DSI_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(dpi_panel, ESP_ERR_NO_MEM, err, TAG, "no memory for DPI panel"); dpi_panel->virtual_channel = panel_config->virtual_channel; - dpi_panel->pixel_format = panel_config->pixel_format; + dpi_panel->in_color_format = in_color_format; + dpi_panel->out_color_format = out_color_format; dpi_panel->bus = bus; dpi_panel->num_fbs = num_fbs; @@ -253,16 +269,25 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ ESP_GOTO_ON_ERROR(dpi_panel_create_dma_link(dpi_panel), err, TAG, "initialize DMA link failed"); mipi_dsi_host_ll_dpi_set_vcid(hal->host, panel_config->virtual_channel); - mipi_dsi_hal_host_dpi_set_color_coding(hal, panel_config->pixel_format, 0); + mipi_dsi_hal_host_dpi_set_color_coding(hal, out_color_format, 0); // these signals define how the DPI interface interacts with the controller mipi_dsi_host_ll_dpi_set_timing_polarity(hal->host, false, false, false, false, false); - // configure the low-power transitions: defines the video periods which are permitted to goto low-power if the time available to do so - mipi_dsi_host_ll_dpi_enable_lp_horizontal_timing(hal->host, true, true); - mipi_dsi_host_ll_dpi_enable_lp_vertical_timing(hal->host, true, true, true, true); + + if (panel_config->flags.disable_lp) { + // configure the low-power transitions: defines the video periods which are NOT permitted to goto low-power + mipi_dsi_host_ll_dpi_enable_lp_horizontal_timing(hal->host, false, false); + mipi_dsi_host_ll_dpi_enable_lp_vertical_timing(hal->host, false, false, false, false); + // commands are NOT transmitted in low-power mode + mipi_dsi_host_ll_dpi_enable_lp_command(hal->host, false); + } else { + // configure the low-power transitions: defines the video periods which are permitted to goto low-power if the time available to do so + mipi_dsi_host_ll_dpi_enable_lp_horizontal_timing(hal->host, true, true); + mipi_dsi_host_ll_dpi_enable_lp_vertical_timing(hal->host, true, true, true, true); + // commands are transmitted in low-power mode + mipi_dsi_host_ll_dpi_enable_lp_command(hal->host, true); + } // after sending a frame, the DSI device should return an ack mipi_dsi_host_ll_dpi_enable_frame_ack(hal->host, true); - // commands are transmitted in low-power mode - mipi_dsi_host_ll_dpi_enable_lp_command(hal->host, true); // using the burst mode because it's energy-efficient mipi_dsi_host_ll_dpi_set_video_burst_type(hal->host, MIPI_DSI_LL_VIDEO_BURST_WITH_SYNC_PULSES); // configure the size of the active lin period, measured in pixels @@ -282,6 +307,8 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ panel_config->video_timing.vsync_front_porch); mipi_dsi_brg_ll_set_num_pixel_bits(hal->bridge, panel_config->video_timing.h_size * panel_config->video_timing.v_size * bits_per_pixel); mipi_dsi_brg_ll_set_underrun_discard_count(hal->bridge, panel_config->video_timing.h_size); + // set input color space + mipi_dsi_brg_ll_set_input_color_space(hal->bridge, COLOR_SPACE_TYPE(in_color_format)); // use the DW_GDMA as the flow controller mipi_dsi_brg_ll_set_flow_controller(hal->bridge, MIPI_DSI_LL_FLOW_CONTROLLER_DMA); mipi_dsi_brg_ll_set_multi_block_number(hal->bridge, DPI_PANEL_MIN_DMA_NODES_PER_LINK); @@ -334,7 +361,7 @@ static esp_err_t dpi_panel_del(esp_lcd_panel_t *panel) esp_async_fbcpy_uninstall(dpi_panel->fbcpy_handle); } if (dpi_panel->draw_sem) { - vSemaphoreDelete(dpi_panel->draw_sem); + vSemaphoreDeleteWithCaps(dpi_panel->draw_sem); } if (dpi_panel->pm_lock) { esp_pm_lock_release(dpi_panel->pm_lock); @@ -506,9 +533,8 @@ static esp_err_t dpi_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int .copy_size_x = x_end - x_start, .copy_size_y = y_end - y_start, .pixel_format_unique_id = { - .color_space = COLOR_SPACE_RGB, - .pixel_format = dpi_panel->pixel_format, - }, + .color_type_id = dpi_panel->in_color_format, + } }; ESP_RETURN_ON_ERROR(esp_async_fbcpy(dpi_panel->fbcpy_handle, &fbcpy_trans_config, async_fbcpy_done_cb, dpi_panel), TAG, "async memcpy failed"); } @@ -516,6 +542,24 @@ static esp_err_t dpi_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int return ESP_OK; } +esp_err_t esp_lcd_dpi_panel_set_color_conversion(esp_lcd_panel_handle_t panel, const esp_lcd_color_conv_config_t *config) +{ + ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + esp_lcd_dpi_panel_t *dpi_panel = __containerof(panel, esp_lcd_dpi_panel_t, base); + esp_lcd_dsi_bus_handle_t bus = dpi_panel->bus; + mipi_dsi_hal_context_t *hal = &bus->hal; + + if (dpi_panel->in_color_format == COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422) + && COLOR_SPACE_TYPE(dpi_panel->out_color_format) == LCD_COLOR_SPACE_RGB) { + // YUV422->RGB + mipi_dsi_brg_ll_set_yuv_convert_std(hal->bridge, config->spec.yuv.conv_std); + mipi_dsi_brg_ll_set_yuv422_pack_order(hal->bridge, config->spec.yuv.yuv422.in_pack_order); + } else { + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported conversion mode"); + } + return ESP_OK; +} + esp_err_t esp_lcd_dpi_panel_set_pattern(esp_lcd_panel_handle_t panel, mipi_dsi_pattern_type_t pattern) { ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); diff --git a/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h b/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h index 657f71583db3..497b4329bb0b 100644 --- a/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h +++ b/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h @@ -84,12 +84,17 @@ typedef struct { mipi_dsi_dpi_clock_source_t dpi_clk_src; /*!< MIPI DSI DPI clock source */ uint32_t dpi_clock_freq_mhz; /*!< DPI clock frequency in MHz */ lcd_color_rgb_pixel_format_t pixel_format; /*!< Pixel format that used by the MIPI LCD device */ + lcd_color_format_t in_color_format; /*!< Format of the input data (color space and pixel format), + which is the format stored in the frame buffer */ + lcd_color_format_t out_color_format; /*!< Format of the output data (color space and pixel format), + which is the format that the panel can accept */ uint8_t num_fbs; /*!< Number of screen-sized frame buffers that allocated by the driver By default (set to either 0 or 1) only one frame buffer will be created */ esp_lcd_video_timing_t video_timing; /*!< Video timing */ /// Extra configuration flags for MIPI DSI DPI panel struct extra_dpi_panel_flags { uint32_t use_dma2d: 1; /*!< Use DMA2D to copy user buffer to the frame buffer when necessary */ + uint32_t disable_lp: 1;/*!< Disable low-power for DPI */ } flags; /*!< Extra configuration flags */ } esp_lcd_dpi_panel_config_t; @@ -133,6 +138,18 @@ esp_err_t esp_lcd_dpi_panel_get_frame_buffer(esp_lcd_panel_handle_t dpi_panel, u */ esp_err_t esp_lcd_dpi_panel_set_pattern(esp_lcd_panel_handle_t dpi_panel, mipi_dsi_pattern_type_t pattern); +/** + * @brief Set color conversion configuration for DPI panel + * + * @param[in] dpi_panel MIPI DPI panel handle, returned from esp_lcd_new_panel_dpi() + * @param[in] config Color conversion configuration + * @return + * - ESP_OK: Set color conversion configuration successfully + * - ESP_ERR_INVALID_ARG: Set color conversion configuration failed because of invalid argument + * - ESP_FAIL: Set color conversion configuration failed because of other error + */ +esp_err_t esp_lcd_dpi_panel_set_color_conversion(esp_lcd_panel_handle_t dpi_panel, const esp_lcd_color_conv_config_t *config); + /** * @brief Type of LCD DPI panel event data */ diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c index 0851381033e4..4c30053ced97 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c @@ -39,14 +39,12 @@ #include "esp_private/periph_ctrl.h" #include "esp_private/i2s_platform.h" #include "esp_private/gdma_link.h" +#include "esp_private/gpio.h" #include "soc/lcd_periph.h" #include "hal/i2s_hal.h" #include "hal/i2s_ll.h" #include "hal/i2s_types.h" -// the DMA descriptor used by esp32 and esp32s2, each descriptor can carry 4095 bytes at most -#define LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE 4095 - static const char *TAG = "lcd_panel.io.i80"; typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t; @@ -61,7 +59,7 @@ static esp_err_t i2s_lcd_init_dma_link(esp_lcd_i80_bus_handle_t bus); static esp_err_t i2s_lcd_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_lcd_i80_bus_config_t *bus_config); static void i2s_lcd_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t bus); static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_i80_t *next_device); -static void lcd_default_isr_handler(void *args); +static void i2s_lcd_default_isr_handler(void *args); static esp_err_t panel_io_i80_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx); struct esp_lcd_i80_bus_t { @@ -188,7 +186,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED; ret = esp_intr_alloc_intrstatus(lcd_periph_i2s_signals.buses[bus->bus_id].irq_id, isr_flags, (uint32_t)i2s_ll_get_intr_status_reg(bus->hal.dev), - I2S_LL_EVENT_TX_EOF, lcd_default_isr_handler, bus, &bus->intr); + I2S_LL_EVENT_TX_EOF, i2s_lcd_default_isr_handler, bus, &bus->intr); ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed"); i2s_ll_enable_intr(bus->hal.dev, I2S_LL_EVENT_TX_EOF, false); // disable interrupt temporarily i2s_ll_clear_intr_status(bus->hal.dev, I2S_LL_EVENT_TX_EOF); // clear pending interrupt @@ -317,8 +315,8 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p if (io_config->cs_gpio_num >= 0) { // CS signal is controlled by software gpio_set_level(io_config->cs_gpio_num, !io_config->flags.cs_active_high); // de-assert by default - gpio_set_direction(io_config->cs_gpio_num, GPIO_MODE_OUTPUT); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[io_config->cs_gpio_num], PIN_FUNC_GPIO); + gpio_func_sel(io_config->cs_gpio_num, PIN_FUNC_GPIO); + gpio_output_enable(io_config->cs_gpio_num); } *ret_io = &(i80_device->base); ESP_LOGD(TAG, "new i80 lcd panel io @%p on bus(%d), pclk=%"PRIu32"Hz", i80_device, bus->bus_id, i80_device->pclk_hz); @@ -362,9 +360,8 @@ static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io) LIST_REMOVE(i80_device, device_list_entry); portEXIT_CRITICAL(&bus->spinlock); - // reset CS GPIO if (i80_device->cs_gpio_num >= 0) { - gpio_reset_pin(i80_device->cs_gpio_num); + gpio_output_disable(i80_device->cs_gpio_num); } ESP_LOGD(TAG, "del i80 lcd panel io @%p", i80_device); @@ -648,7 +645,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons xQueueSend(next_device->trans_queue, &trans_desc, portMAX_DELAY); next_device->num_trans_inflight++; // enable interrupt and go into isr handler, where we fetch the transactions from trans_queue and start it - // we will go into `lcd_default_isr_handler` almost at once, because the "trans done" event is active at the moment + // we will go into `i2s_lcd_default_isr_handler` almost at once, because the "trans done" event is active at the moment esp_intr_enable(bus->intr); return ESP_OK; } @@ -669,7 +666,7 @@ static esp_err_t i2s_lcd_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_c // create pm lock based on different clock source // clock sources like PLL and XTAL will be turned off in light sleep #if CONFIG_PM_ENABLE - ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i80_bus_lcd", &bus->pm_lock), TAG, "create pm lock failed"); + ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i80_bus_lcd", &bus->pm_lock), TAG, "create pm lock failed"); #endif return ESP_OK; } @@ -698,21 +695,20 @@ static esp_err_t i2s_lcd_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_ // connect peripheral signals via GPIO matrix // data line for (size_t i = 0; i < bus_config->bus_width; i++) { - gpio_set_direction(bus_config->data_gpio_nums[i], GPIO_MODE_OUTPUT); + gpio_func_sel(bus_config->data_gpio_nums[i], PIN_FUNC_GPIO); + // the esp_rom_gpio_connect_out_signal function will also help enable the output path properly #if SOC_I2S_TRANS_SIZE_ALIGN_WORD esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i2s_signals.buses[bus_id].data_sigs[i + 8], false, false); #else esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i2s_signals.buses[bus_id].data_sigs[i + SOC_I2S_MAX_DATA_WIDTH - bus_config->bus_width], false, false); #endif - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->data_gpio_nums[i]], PIN_FUNC_GPIO); } // WR signal (pclk) - gpio_set_direction(bus_config->wr_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(bus_config->wr_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_i2s_signals.buses[bus_id].wr_sig, true, false); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->wr_gpio_num], PIN_FUNC_GPIO); // DC signal is controlled by software, set as general purpose IO - gpio_set_direction(bus_config->dc_gpio_num, GPIO_MODE_OUTPUT); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->dc_gpio_num], PIN_FUNC_GPIO); + gpio_func_sel(bus_config->dc_gpio_num, PIN_FUNC_GPIO); + gpio_output_enable(bus_config->dc_gpio_num); return ESP_OK; } @@ -756,7 +752,7 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_ bus->cur_device = next_device; } -static IRAM_ATTR void lcd_default_isr_handler(void *args) +static IRAM_ATTR void i2s_lcd_default_isr_handler(void *args) { esp_lcd_i80_bus_t *bus = (esp_lcd_i80_bus_t *)args; lcd_i80_trans_descriptor_t *trans_desc = NULL; diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c index 96b8fb4ca8b5..d7a29f445041 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c @@ -43,8 +43,6 @@ #include "hal/cache_ll.h" #include "hal/cache_hal.h" -#define LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE 4095 - #if defined(SOC_GDMA_TRIG_PERIPH_LCD0_BUS) && (SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AHB) #define LCD_GDMA_NEW_CHANNEL gdma_new_ahb_channel #define LCD_GDMA_DESCRIPTOR_ALIGN 4 @@ -76,7 +74,7 @@ static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_c static esp_err_t lcd_i80_bus_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_lcd_i80_bus_config_t *bus_config); static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_i80_t *next_device); static void lcd_start_transaction(esp_lcd_i80_bus_t *bus, lcd_i80_trans_descriptor_t *trans_desc); -static void lcd_default_isr_handler(void *args); +static void i80_lcd_default_isr_handler(void *args); static esp_err_t panel_io_i80_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx); struct esp_lcd_i80_bus_t { @@ -157,18 +155,6 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc // allocate i80 bus memory bus = heap_caps_calloc(1, sizeof(esp_lcd_i80_bus_t), LCD_I80_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(bus, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 bus"); - size_t num_dma_nodes = bus_config->max_transfer_bytes / LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; - // create DMA link list - gdma_link_list_config_t dma_link_config = { - .buffer_alignment = 1, // no special buffer alignment for LCD TX buffer - .item_alignment = LCD_GDMA_DESCRIPTOR_ALIGN, - .num_items = num_dma_nodes, - .flags = { - .check_owner = true, - }, - }; - ESP_GOTO_ON_ERROR(gdma_new_link_list(&dma_link_config, &bus->dma_link), err, TAG, "create DMA link list failed"); - bus->num_dma_nodes = num_dma_nodes; bus->bus_width = bus_config->bus_width; bus->bus_id = -1; // allocate the format buffer from internal memory, with DMA capability @@ -208,7 +194,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED; ret = esp_intr_alloc_intrstatus(lcd_periph_i80_signals.buses[bus_id].irq_id, isr_flags, (uint32_t)lcd_ll_get_interrupt_status_reg(bus->hal.dev), - LCD_LL_EVENT_TRANS_DONE, lcd_default_isr_handler, bus, &bus->intr); + LCD_LL_EVENT_TRANS_DONE, i80_lcd_default_isr_handler, bus, &bus->intr); ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed"); lcd_ll_enable_interrupt(bus->hal.dev, LCD_LL_EVENT_TRANS_DONE, false); // disable all interrupts lcd_ll_clear_interrupt_status(bus->hal.dev, UINT32_MAX); // clear pending interrupt @@ -355,9 +341,10 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p // we only configure the CS GPIO as output, don't connect to the peripheral signal at the moment // we will connect the CS GPIO to peripheral signal when switching devices in lcd_i80_switch_devices() if (io_config->cs_gpio_num >= 0) { - gpio_set_level(io_config->cs_gpio_num, !io_config->flags.cs_active_high); - gpio_set_direction(io_config->cs_gpio_num, GPIO_MODE_OUTPUT); + // CS signal is controlled by software + gpio_set_level(io_config->cs_gpio_num, !io_config->flags.cs_active_high); // de-assert by default gpio_func_sel(io_config->cs_gpio_num, PIN_FUNC_GPIO); + gpio_output_enable(io_config->cs_gpio_num); } *ret_io = &(i80_device->base); ESP_LOGD(TAG, "new i80 lcd panel io @%p on bus(%d)", i80_device, bus->bus_id); @@ -393,9 +380,8 @@ static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io) LIST_REMOVE(i80_device, device_list_entry); portEXIT_CRITICAL(&bus->spinlock); - // reset CS to normal GPIO if (i80_device->cs_gpio_num >= 0) { - gpio_reset_pin(i80_device->cs_gpio_num); + gpio_output_disable(i80_device->cs_gpio_num); } ESP_LOGD(TAG, "del i80 lcd panel io @%p", i80_device); @@ -572,7 +558,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons xQueueSend(i80_device->trans_queue, &trans_desc, portMAX_DELAY); i80_device->num_trans_inflight++; // enable interrupt and go into isr handler, where we fetch the transactions from trans_queue and start it - // we will go into `lcd_default_isr_handler` almost at once, because the "trans done" event is active at the moment + // we will go into `i80_lcd_default_isr_handler` almost at once, because the "trans done" event is active at the moment esp_intr_enable(bus->intr); return ESP_OK; } @@ -609,7 +595,7 @@ static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus, const esp_l .direction = GDMA_CHANNEL_DIRECTION_TX, }; ret = LCD_GDMA_NEW_CHANNEL(&dma_chan_config, &bus->dma_chan); - ESP_GOTO_ON_ERROR(ret, err, TAG, "alloc DMA channel failed"); + ESP_RETURN_ON_ERROR(ret, TAG, "alloc DMA channel failed"); gdma_connect(bus->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0)); gdma_strategy_config_t strategy_config = { .auto_update_desc = true, @@ -621,14 +607,23 @@ static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus, const esp_l .max_data_burst_size = bus_config->dma_burst_size ? bus_config->dma_burst_size : 16, // Enable DMA burst transfer for better performance .access_ext_mem = true, // the LCD can carry pixel buffer from the external memory }; - ESP_GOTO_ON_ERROR(gdma_config_transfer(bus->dma_chan, &trans_cfg), err, TAG, "config DMA transfer failed"); + ESP_RETURN_ON_ERROR(gdma_config_transfer(bus->dma_chan, &trans_cfg), TAG, "config DMA transfer failed"); gdma_get_alignment_constraints(bus->dma_chan, &bus->int_mem_align, &bus->ext_mem_align); + + size_t num_dma_nodes = bus_config->max_transfer_bytes / LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; + // create DMA link list + gdma_link_list_config_t dma_link_config = { + .buffer_alignment = MAX(bus->int_mem_align, bus->ext_mem_align), + .item_alignment = LCD_GDMA_DESCRIPTOR_ALIGN, + .num_items = num_dma_nodes, + .flags = { + .check_owner = true, + }, + }; + ESP_RETURN_ON_ERROR(gdma_new_link_list(&dma_link_config, &bus->dma_link), TAG, "create DMA link list failed"); + bus->num_dma_nodes = num_dma_nodes; + return ESP_OK; -err: - if (bus->dma_chan) { - gdma_del_channel(bus->dma_chan); - } - return ret; } void *esp_lcd_i80_alloc_draw_buffer(esp_lcd_panel_io_handle_t io, size_t size, uint32_t caps) @@ -660,17 +655,18 @@ static esp_err_t lcd_i80_bus_configure_gpio(esp_lcd_i80_bus_handle_t bus, const // Set the number of output data lines lcd_ll_set_data_wire_width(bus->hal.dev, bus_config->bus_width); // connect peripheral signals via GPIO matrix + // data lines for (size_t i = 0; i < bus_config->bus_width; i++) { - gpio_set_direction(bus_config->data_gpio_nums[i], GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i80_signals.buses[bus_id].data_sigs[i], false, false); gpio_func_sel(bus_config->data_gpio_nums[i], PIN_FUNC_GPIO); + // the esp_rom_gpio_connect_out_signal function will also help enable the output path properly + esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i80_signals.buses[bus_id].data_sigs[i], false, false); } - gpio_set_direction(bus_config->dc_gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(bus_config->dc_gpio_num, lcd_periph_i80_signals.buses[bus_id].dc_sig, false, false); + // D/C signal gpio_func_sel(bus_config->dc_gpio_num, PIN_FUNC_GPIO); - gpio_set_direction(bus_config->wr_gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_i80_signals.buses[bus_id].wr_sig, false, false); + esp_rom_gpio_connect_out_signal(bus_config->dc_gpio_num, lcd_periph_i80_signals.buses[bus_id].dc_sig, false, false); + // WR signal (PCLK) gpio_func_sel(bus_config->wr_gpio_num, PIN_FUNC_GPIO); + esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_i80_signals.buses[bus_id].wr_sig, false, false); return ESP_OK; } @@ -722,8 +718,7 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_ lcd_ll_set_dc_level(bus->hal.dev, next_device->dc_levels.dc_idle_level, next_device->dc_levels.dc_cmd_level, next_device->dc_levels.dc_dummy_level, next_device->dc_levels.dc_data_level); if (cur_device && cur_device->cs_gpio_num >= 0) { - // disconnect current CS GPIO from peripheral signal - esp_rom_gpio_connect_out_signal(cur_device->cs_gpio_num, SIG_GPIO_OUT_IDX, false, false); + gpio_output_disable(cur_device->cs_gpio_num); } if (next_device->cs_gpio_num >= 0) { // connect CS signal to the new device @@ -733,7 +728,7 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_ } } -IRAM_ATTR static void lcd_default_isr_handler(void *args) +IRAM_ATTR static void i80_lcd_default_isr_handler(void *args) { esp_lcd_i80_bus_t *bus = (esp_lcd_i80_bus_t *)args; lcd_i80_trans_descriptor_t *trans_desc = NULL; diff --git a/components/esp_lcd/include/esp_lcd_io_i2c.h b/components/esp_lcd/include/esp_lcd_io_i2c.h index 7d1b0fc02c95..e98f18acbd74 100644 --- a/components/esp_lcd/include/esp_lcd_io_i2c.h +++ b/components/esp_lcd/include/esp_lcd_io_i2c.h @@ -83,9 +83,9 @@ esp_err_t esp_lcd_new_panel_io_i2c_v2(i2c_master_bus_handle_t bus, const esp_lcd * - ESP_ERR_NO_MEM if out of memory * - ESP_OK on success */ -static inline void esp_lcd_new_panel_io_i2c(uint32_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io) +static inline esp_err_t esp_lcd_new_panel_io_i2c(uint32_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io) { - esp_lcd_new_panel_io_i2c_v1(bus, io_config, ret_io); + return esp_lcd_new_panel_io_i2c_v1(bus, io_config, ret_io); } /** @@ -99,9 +99,9 @@ static inline void esp_lcd_new_panel_io_i2c(uint32_t bus, const esp_lcd_panel_io * - ESP_ERR_NO_MEM if out of memory * - ESP_OK on success */ -static inline void esp_lcd_new_panel_io_i2c(i2c_master_bus_handle_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io) +static inline esp_err_t esp_lcd_new_panel_io_i2c(i2c_master_bus_handle_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io) { - esp_lcd_new_panel_io_i2c_v2(bus, io_config, ret_io); + return esp_lcd_new_panel_io_i2c_v2(bus, io_config, ret_io); } #else /** diff --git a/components/esp_lcd/include/esp_lcd_io_i80.h b/components/esp_lcd/include/esp_lcd_io_i80.h index 7b6bd90422f1..f2885390f5fe 100644 --- a/components/esp_lcd/include/esp_lcd_io_i80.h +++ b/components/esp_lcd/include/esp_lcd_io_i80.h @@ -30,7 +30,7 @@ typedef struct { size_t bus_width; /*!< Number of data lines, 8 or 16 */ size_t max_transfer_bytes; /*!< Maximum transfer size, this determines the length of internal DMA link */ union { - size_t psram_trans_align; /*!< DMA transfer alignment for data allocated from PSRAM */ + size_t psram_trans_align __attribute__((deprecated)); /*!< DMA transfer alignment for data allocated from PSRAM */ size_t dma_burst_size; /*!< DMA burst size, in bytes */ }; size_t sram_trans_align __attribute__((deprecated)); /*!< DMA transfer alignment for data allocated from SRAM */ diff --git a/components/esp_lcd/include/esp_lcd_types.h b/components/esp_lcd/include/esp_lcd_types.h index ca15370b93d7..2de4306ba2a6 100644 --- a/components/esp_lcd/include/esp_lcd_types.h +++ b/components/esp_lcd/include/esp_lcd_types.h @@ -75,6 +75,22 @@ typedef struct { esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; /*!< Callback invoked when color data transfer has finished */ } esp_lcd_panel_io_callbacks_t; +/** + * @brief Configuration of LCD color conversion + */ +typedef struct { + lcd_color_range_t in_color_range; /*!< Color range of the input color */ + lcd_color_range_t out_color_range; /*!< Color range of the output color */ + union { + struct { + lcd_yuv_conv_std_t conv_std; /*!< YUV conversion standard: BT601, BT709 */ + struct { + lcd_yuv422_pack_order_t in_pack_order; /*!< YUV422 packing order of the input color */ + } yuv422; /*!< YUV422 specific */ + } yuv; /*!< YUV specific */ + } spec; /*!< Extra configuration for specific color conversion */ +} esp_lcd_color_conv_config_t; + #ifdef __cplusplus } #endif diff --git a/components/esp_lcd/interface/esp_lcd_panel_io_interface.h b/components/esp_lcd/interface/esp_lcd_panel_io_interface.h index 781eb1dd3f45..0a4334f6fade 100644 --- a/components/esp_lcd/interface/esp_lcd_panel_io_interface.h +++ b/components/esp_lcd/interface/esp_lcd_panel_io_interface.h @@ -7,7 +7,7 @@ #include #include "esp_err.h" -#include "esp_lcd_panel_io.h" +#include "esp_lcd_types.h" #ifdef __cplusplus extern "C" { diff --git a/components/esp_lcd/linker.lf b/components/esp_lcd/linker.lf index 6e3aa0d3cda7..f66d088f22d6 100644 --- a/components/esp_lcd/linker.lf +++ b/components/esp_lcd/linker.lf @@ -1,8 +1,15 @@ -[mapping:esp_lcd_driver] -archive: libesp_lcd.a +[mapping:esp_lcd_gdma] +archive: libesp_hw_support.a entries: if LCD_RGB_ISR_IRAM_SAFE = y: - esp_lcd_common: lcd_com_mount_dma_data (noflash) + gdma: gdma_reset (noflash) + gdma: gdma_start (noflash) + gdma_link: gdma_link_get_head_addr (noflash) + if LCD_DSI_ISR_IRAM_SAFE = y: + dw_gdma: dw_gdma_link_list_get_item (noflash) + dw_gdma: dw_gdma_lli_set_block_markers (noflash) + dw_gdma: dw_gdma_channel_use_link_list (noflash) + dw_gdma: dw_gdma_channel_enable_ctrl (noflash) [mapping:esp_lcd_hal] archive: libhal.a diff --git a/components/esp_lcd/priv_include/esp_lcd_common.h b/components/esp_lcd/priv_include/esp_lcd_common.h index a7b8ae6161ef..64546727ef3b 100644 --- a/components/esp_lcd/priv_include/esp_lcd_common.h +++ b/components/esp_lcd/priv_include/esp_lcd_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,6 +33,8 @@ extern "C" { #define LCD_CLOCK_SRC_ATOMIC() #endif +#define LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE 4095 + #if SOC_LCDCAM_SUPPORTED typedef enum { @@ -58,15 +60,6 @@ int lcd_com_register_device(lcd_com_device_type_t device_type, void *device_obj) void lcd_com_remove_device(lcd_com_device_type_t device_type, int member_id); #endif // SOC_LCDCAM_SUPPORTED -/** - * @brief Mount data to DMA descriptors - * - * @param desc_head Point to the head of DMA descriptor chain - * @param buffer Data buffer - * @param len Size of the data buffer, in bytes - */ -void lcd_com_mount_dma_data(dma_descriptor_t *desc_head, const void *buffer, size_t len); - /** * @brief Reverse the bytes in the buffer * diff --git a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c index 60165fc1c532..25cb52db2895 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -17,7 +17,6 @@ #endif #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" #include "esp_attr.h" #include "esp_check.h" #include "esp_pm.h" @@ -28,43 +27,50 @@ #include "soc/soc_caps.h" #include "esp_clk_tree.h" #include "hal/dma_types.h" -#include "hal/gpio_hal.h" -#include "esp_private/gdma.h" #include "driver/gpio.h" #include "esp_bit_defs.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/gdma.h" +#include "esp_private/gdma_link.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/gpio.h" #include "esp_psram.h" #include "esp_lcd_common.h" +#include "esp_cache.h" #include "esp_memory_utils.h" #include "soc/lcd_periph.h" -#include "soc/soc_caps.h" +#include "soc/io_mux_reg.h" #include "hal/lcd_hal.h" #include "hal/lcd_ll.h" #include "hal/cache_hal.h" #include "hal/cache_ll.h" -#include "rom/cache.h" -#include "esp_cache.h" +#include "rgb_lcd_rotation_sw.h" + +// hardware issue workaround +#if CONFIG_IDF_TARGET_ESP32S3 +#define RGB_LCD_NEEDS_SEPARATE_RESTART_LINK 1 +#endif #if CONFIG_LCD_RGB_ISR_IRAM_SAFE #define LCD_RGB_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED) +#define LCD_RGB_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else #define LCD_RGB_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED +#define LCD_RGB_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT +#endif + +#if defined(SOC_GDMA_TRIG_PERIPH_LCD0_BUS) && (SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AHB) +#define LCD_GDMA_NEW_CHANNEL gdma_new_ahb_channel +#define LCD_GDMA_DESCRIPTOR_ALIGN 4 +#elif defined(SOC_GDMA_TRIG_PERIPH_LCD0_BUS) && (SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AXI) +#define LCD_GDMA_NEW_CHANNEL gdma_new_axi_channel +#define LCD_GDMA_DESCRIPTOR_ALIGN 8 +#else +#error "Unsupported GDMA bus type for RGB LCD" #endif #define RGB_LCD_PANEL_MAX_FB_NUM 3 // maximum supported frame buffer number #define RGB_LCD_PANEL_BOUNCE_BUF_NUM 2 // bounce buffer number -#define RGB_LCD_PANEL_DMA_LINKS_REPLICA MAX(RGB_LCD_PANEL_MAX_FB_NUM, RGB_LCD_PANEL_BOUNCE_BUF_NUM) - -#define RGB_PANEL_SWAP_XY 0 -#define RGB_PANEL_MIRROR_Y 1 -#define RGB_PANEL_MIRROR_X 2 - -typedef enum { - ROTATE_MASK_SWAP_XY = BIT(RGB_PANEL_SWAP_XY), - ROTATE_MASK_MIRROR_Y = BIT(RGB_PANEL_MIRROR_Y), - ROTATE_MASK_MIRROR_X = BIT(RGB_PANEL_MIRROR_X), -} panel_rotate_mask_t; static const char *TAG = "lcd_panel.rgb"; @@ -79,12 +85,12 @@ static esp_err_t rgb_panel_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mi static esp_err_t rgb_panel_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); static esp_err_t rgb_panel_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); static esp_err_t rgb_panel_disp_on_off(esp_lcd_panel_t *panel, bool off); -static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *panel, lcd_clock_source_t clk_src); -static esp_err_t lcd_rgb_create_dma_channel(esp_rgb_panel_t *panel); -static void lcd_rgb_panel_init_trans_link(esp_rgb_panel_t *panel); -static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_lcd_rgb_panel_config_t *panel_config); +static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *rgb_panel, lcd_clock_source_t clk_src); +static esp_err_t lcd_rgb_create_dma_channel(esp_rgb_panel_t *rgb_panel); +static esp_err_t lcd_rgb_panel_init_trans_link(esp_rgb_panel_t *rgb_panel); +static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *rgb_panel, const esp_lcd_rgb_panel_config_t *panel_config); static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel); -static void lcd_default_isr_handler(void *args); +static void rgb_lcd_default_isr_handler(void *args); struct esp_rgb_panel_t { esp_lcd_panel_t base; // Base class of generic lcd panel @@ -99,22 +105,30 @@ struct esp_rgb_panel_t { intr_handle_t intr; // LCD peripheral interrupt handle esp_pm_lock_handle_t pm_lock; // Power management lock size_t num_dma_nodes; // Number of DMA descriptors that used to carry the frame buffer + gdma_channel_handle_t dma_chan; // DMA channel handle + gdma_link_list_handle_t dma_fb_links[RGB_LCD_PANEL_MAX_FB_NUM]; // DMA link lists for multiple frame buffers + gdma_link_list_handle_t dma_bb_link; // DMA link list for bounce buffer +#if RGB_LCD_NEEDS_SEPARATE_RESTART_LINK + gdma_link_list_handle_t dma_restart_link; // DMA link list for restarting the DMA +#endif uint8_t *fbs[RGB_LCD_PANEL_MAX_FB_NUM]; // Frame buffers + uint8_t *bounce_buffer[RGB_LCD_PANEL_BOUNCE_BUF_NUM]; // Pointer to the bounce buffers + size_t fb_size; // Size of frame buffer, in bytes + size_t bb_size; // Size of the bounce buffer, in bytes. If not-zero, the driver uses two bounce buffers allocated from internal memory uint8_t cur_fb_index; // Current frame buffer index uint8_t bb_fb_index; // Current frame buffer index which used by bounce buffer - size_t fb_size; // Size of frame buffer, in bytes - int data_gpio_nums[SOC_LCD_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color" + size_t int_mem_align; // DMA buffer alignment for internal memory + size_t ext_mem_align; // DMA buffer alignment for external memory + int data_gpio_nums[SOC_LCDCAM_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color" uint32_t src_clk_hz; // Peripheral source clock resolution esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width) - size_t bb_size; // Size of the bounce buffer, in bytes. If not-zero, the driver uses two bounce buffers allocated from internal memory int bounce_pos_px; // Position in whatever source material is used for the bounce buffer, in pixels - uint8_t *bounce_buffer[RGB_LCD_PANEL_BOUNCE_BUF_NUM]; // Pointer to the bounce buffers size_t bb_eof_count; // record the number we received the DMA EOF event, compare with `expect_eof_count` in the VSYNC_END ISR size_t expect_eof_count; // record the number of DMA EOF event we expected to receive - gdma_channel_handle_t dma_chan; // DMA channel handle + esp_lcd_rgb_panel_draw_buf_complete_cb_t on_color_trans_done; // draw buffer completes + esp_lcd_rgb_panel_frame_buf_complete_cb_t on_frame_buf_complete; // callback used to notify when the bounce buffer finish copying the entire frame esp_lcd_rgb_panel_vsync_cb_t on_vsync; // VSYNC event callback esp_lcd_rgb_panel_bounce_buf_fill_cb_t on_bounce_empty; // callback used to fill a bounce buffer rather than copying from the frame buffer - esp_lcd_rgb_panel_bounce_buf_finish_cb_t on_bounce_frame_finish; // callback used to notify when the bounce buffer finish copying the entire frame void *user_ctx; // Reserved user's data of callback functions int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window @@ -127,67 +141,55 @@ struct esp_rgb_panel_t { uint32_t fb_in_psram: 1; // Whether the frame buffer is in PSRAM uint32_t need_update_pclk: 1; // Whether to update the PCLK before start a new transaction uint32_t need_restart: 1; // Whether to restart the LCD controller and the DMA - uint32_t bb_invalidate_cache: 1; // Whether to do cache invalidation in bounce buffer mode + uint32_t fb_behind_cache: 1; // Whether the frame buffer is behind the cache + uint32_t bb_behind_cache: 1; // Whether the bounce buffer is behind the cache } flags; - dma_descriptor_t *dma_links[RGB_LCD_PANEL_DMA_LINKS_REPLICA]; // fbs[0] <-> dma_links[0], fbs[1] <-> dma_links[1], etc - dma_descriptor_t dma_restart_node; // DMA descriptor used to restart the transfer - dma_descriptor_t dma_nodes[]; // DMA descriptors pool }; -static esp_err_t lcd_rgb_panel_alloc_frame_buffers(const esp_lcd_rgb_panel_config_t *rgb_panel_config, esp_rgb_panel_t *rgb_panel) +static esp_err_t lcd_rgb_panel_alloc_frame_buffers(esp_rgb_panel_t *rgb_panel) { - bool fb_in_psram = false; - size_t ext_mem_align = 0; - size_t int_mem_align = 0; - gdma_get_alignment_constraints(rgb_panel->dma_chan, &int_mem_align, &ext_mem_align); + bool fb_in_psram = rgb_panel->flags.fb_in_psram; - // also take the cache line size into account when allocating the frame buffer - uint32_t ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); + // read the cache line size of internal and external memory, we use this information to check if the allocated memory is behind the cache uint32_t int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); - // The buffer must be aligned to the cache line size - if (ext_mem_cache_line_size) { - ext_mem_align = MAX(ext_mem_align, ext_mem_cache_line_size); - } - if (int_mem_cache_line_size) { - int_mem_align = MAX(int_mem_align, int_mem_cache_line_size); - } + uint32_t ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); // alloc frame buffer - if (rgb_panel->num_fbs > 0) { - // fb_in_psram is only an option, if there's no PSRAM on board, we fallback to alloc from SRAM - if (rgb_panel_config->flags.fb_in_psram) { -#if CONFIG_SPIRAM_USE_MALLOC || CONFIG_SPIRAM_USE_CAPS_ALLOC - if (esp_psram_is_initialized()) { - fb_in_psram = true; - } -#endif + for (int i = 0; i < rgb_panel->num_fbs; i++) { + if (fb_in_psram) { + // the allocated buffer is also aligned to the cache line size + rgb_panel->fbs[i] = heap_caps_aligned_calloc(rgb_panel->ext_mem_align, 1, rgb_panel->fb_size, + MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT); + ESP_RETURN_ON_FALSE(rgb_panel->fbs[i], ESP_ERR_NO_MEM, TAG, "no mem for frame buffer"); + rgb_panel->flags.fb_behind_cache = ext_mem_cache_line_size > 0; + } else { + rgb_panel->fbs[i] = heap_caps_aligned_calloc(rgb_panel->int_mem_align, 1, rgb_panel->fb_size, + MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT); + ESP_RETURN_ON_FALSE(rgb_panel->fbs[i], ESP_ERR_NO_MEM, TAG, "no mem for frame buffer"); + rgb_panel->flags.fb_behind_cache = int_mem_cache_line_size > 0; } - for (int i = 0; i < rgb_panel->num_fbs; i++) { - if (fb_in_psram) { - // the low level malloc function will help check the validation of alignment - rgb_panel->fbs[i] = heap_caps_aligned_calloc(ext_mem_align, 1, rgb_panel->fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - ESP_RETURN_ON_FALSE(rgb_panel->fbs[i], ESP_ERR_NO_MEM, TAG, "no mem for frame buffer"); - // calloc not only allocates but also zero's the buffer. We have to make sure this is - // properly committed to the PSRAM, otherwise all sorts of visual corruption will happen. - ESP_RETURN_ON_ERROR(esp_cache_msync(rgb_panel->fbs[i], rgb_panel->fb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M), TAG, "cache write back failed"); - } else { - rgb_panel->fbs[i] = heap_caps_aligned_calloc(int_mem_align, 1, rgb_panel->fb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); - ESP_RETURN_ON_FALSE(rgb_panel->fbs[i], ESP_ERR_NO_MEM, TAG, "no mem for frame buffer"); - } + // flush data from cache to the physical memory + if (rgb_panel->flags.fb_behind_cache) { + esp_cache_msync(rgb_panel->fbs[i], rgb_panel->fb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); } } // alloc bounce buffer if (rgb_panel->bb_size) { for (int i = 0; i < RGB_LCD_PANEL_BOUNCE_BUF_NUM; i++) { - // bounce buffer must come from SRAM - rgb_panel->bounce_buffer[i] = heap_caps_aligned_calloc(int_mem_align, 1, rgb_panel->bb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + // bounce buffer must be allocated from internal memory for performance + rgb_panel->bounce_buffer[i] = heap_caps_aligned_calloc(rgb_panel->int_mem_align, 1, rgb_panel->bb_size, + MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT); ESP_RETURN_ON_FALSE(rgb_panel->bounce_buffer[i], ESP_ERR_NO_MEM, TAG, "no mem for bounce buffer"); + if (int_mem_cache_line_size > 0) { + // flush data from cache to the physical memory + esp_cache_msync(rgb_panel->bounce_buffer[i], rgb_panel->bb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + rgb_panel->flags.bb_behind_cache = true; + } } } rgb_panel->cur_fb_index = 0; rgb_panel->bb_fb_index = 0; - rgb_panel->flags.fb_in_psram = fb_in_psram; return ESP_OK; } @@ -205,21 +207,31 @@ static esp_err_t lcd_rgb_panel_destroy(esp_rgb_panel_t *rgb_panel) } lcd_com_remove_device(LCD_COM_DEVICE_TYPE_RGB, rgb_panel->panel_id); } - for (size_t i = 0; i < rgb_panel->num_fbs; i++) { + if (rgb_panel->dma_chan) { + gdma_disconnect(rgb_panel->dma_chan); + gdma_del_channel(rgb_panel->dma_chan); + } + for (size_t i = 0; i < RGB_LCD_PANEL_MAX_FB_NUM; i++) { if (rgb_panel->fbs[i]) { free(rgb_panel->fbs[i]); } + if (rgb_panel->dma_fb_links[i]) { + gdma_del_link_list(rgb_panel->dma_fb_links[i]); + } } - if (rgb_panel->bounce_buffer[0]) { - free(rgb_panel->bounce_buffer[0]); + for (int i = 0; i < RGB_LCD_PANEL_BOUNCE_BUF_NUM; i++) { + if (rgb_panel->bounce_buffer[i]) { + free(rgb_panel->bounce_buffer[i]); + } } - if (rgb_panel->bounce_buffer[1]) { - free(rgb_panel->bounce_buffer[1]); + if (rgb_panel->dma_bb_link) { + gdma_del_link_list(rgb_panel->dma_bb_link); } - if (rgb_panel->dma_chan) { - gdma_disconnect(rgb_panel->dma_chan); - gdma_del_channel(rgb_panel->dma_chan); +#if RGB_LCD_NEEDS_SEPARATE_RESTART_LINK + if (rgb_panel->dma_restart_link) { + gdma_del_link_list(rgb_panel->dma_restart_link); } +#endif if (rgb_panel->intr) { esp_intr_free(rgb_panel->intr); } @@ -240,7 +252,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf esp_rgb_panel_t *rgb_panel = NULL; ESP_RETURN_ON_FALSE(rgb_panel_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid parameter"); size_t data_width = rgb_panel_config->data_width; - ESP_RETURN_ON_FALSE((data_width >= 8) && (data_width <= SOC_LCD_RGB_DATA_WIDTH) && ((data_width & (data_width - 1)) == 0), ESP_ERR_INVALID_ARG, + ESP_RETURN_ON_FALSE((data_width > 0) && (data_width <= SOC_LCDCAM_RGB_DATA_WIDTH) && ((data_width % 8) == 0), ESP_ERR_INVALID_ARG, TAG, "unsupported data width %d", data_width); ESP_RETURN_ON_FALSE(!(rgb_panel_config->flags.double_fb && rgb_panel_config->flags.no_fb), ESP_ERR_INVALID_ARG, TAG, "double_fb conflicts with no_fb"); @@ -250,8 +262,6 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf ESP_ERR_INVALID_ARG, TAG, "num_fbs conflicts with no_fb"); ESP_RETURN_ON_FALSE(!(rgb_panel_config->flags.no_fb && rgb_panel_config->bounce_buffer_size_px == 0), ESP_ERR_INVALID_ARG, TAG, "must set bounce buffer if there's no frame buffer"); - ESP_RETURN_ON_FALSE(!(rgb_panel_config->flags.refresh_on_demand && rgb_panel_config->bounce_buffer_size_px), - ESP_ERR_INVALID_ARG, TAG, "refresh on demand is not supported under bounce buffer mode"); // determine number of framebuffers size_t num_fbs = 1; @@ -275,33 +285,22 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf size_t bb_size = rgb_panel_config->bounce_buffer_size_px * fb_bits_per_pixel / 8; size_t expect_bb_eof_count = 0; if (bb_size) { - // we want the bounce can always end in the second buffer - ESP_RETURN_ON_FALSE(fb_size % (2 * bb_size) == 0, ESP_ERR_INVALID_ARG, TAG, - "fb size must be even multiple of bounce buffer size"); + ESP_RETURN_ON_FALSE(fb_size % bb_size == 0, ESP_ERR_INVALID_ARG, TAG, "frame buffer size must be multiple of bounce buffer size"); expect_bb_eof_count = fb_size / bb_size; } // calculate the number of DMA descriptors size_t num_dma_nodes = 0; - if (bb_size) { - // in bounce buffer mode, DMA is used to convey the bounce buffer, not the frame buffer. - // frame buffer is copied to bounce buffer by CPU - num_dma_nodes = (bb_size + DMA_DESCRIPTOR_BUFFER_MAX_SIZE - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - } else { - // Not bounce buffer mode, DMA descriptors need to fit the entire frame buffer - num_dma_nodes = (fb_size + DMA_DESCRIPTOR_BUFFER_MAX_SIZE - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - } - - // DMA descriptors must be placed in internal SRAM (requested by DMA) - rgb_panel = heap_caps_calloc(1, sizeof(esp_rgb_panel_t) + num_dma_nodes * sizeof(dma_descriptor_t) * RGB_LCD_PANEL_DMA_LINKS_REPLICA, - MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + // allocate memory for rgb panel + rgb_panel = heap_caps_calloc(1, sizeof(esp_rgb_panel_t), LCD_RGB_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(rgb_panel, ESP_ERR_NO_MEM, err, TAG, "no mem for rgb panel"); + rgb_panel->panel_id = -1; rgb_panel->num_dma_nodes = num_dma_nodes; rgb_panel->num_fbs = num_fbs; rgb_panel->fb_size = fb_size; rgb_panel->bb_size = bb_size; + rgb_panel->fb_bits_per_pixel = fb_bits_per_pixel; rgb_panel->expect_eof_count = expect_bb_eof_count; - rgb_panel->panel_id = -1; // register to platform int panel_id = lcd_com_register_device(LCD_COM_DEVICE_TYPE_RGB, rgb_panel); ESP_GOTO_ON_FALSE(panel_id >= 0, ESP_ERR_NOT_FOUND, err, TAG, "no free rgb panel slot"); @@ -336,20 +335,20 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED; ret = esp_intr_alloc_intrstatus(lcd_periph_rgb_signals.panels[panel_id].irq_id, isr_flags, (uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev), - LCD_LL_EVENT_VSYNC_END, lcd_default_isr_handler, rgb_panel, &rgb_panel->intr); + LCD_LL_EVENT_VSYNC_END, rgb_lcd_default_isr_handler, rgb_panel, &rgb_panel->intr); ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed"); lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_VSYNC_END, false); // disable all interrupts lcd_ll_clear_interrupt_status(rgb_panel->hal.dev, UINT32_MAX); // clear pending interrupt // install DMA service rgb_panel->flags.stream_mode = !rgb_panel_config->flags.refresh_on_demand; - rgb_panel->fb_bits_per_pixel = fb_bits_per_pixel; rgb_panel->dma_burst_size = rgb_panel_config->dma_burst_size ? rgb_panel_config->dma_burst_size : 64; + rgb_panel->flags.fb_in_psram = rgb_panel_config->flags.fb_in_psram; ESP_GOTO_ON_ERROR(lcd_rgb_create_dma_channel(rgb_panel), err, TAG, "install DMA failed"); // allocate frame buffers + bounce buffers - ESP_GOTO_ON_ERROR(lcd_rgb_panel_alloc_frame_buffers(rgb_panel_config, rgb_panel), err, TAG, "alloc frame buffers failed"); + ESP_GOTO_ON_ERROR(lcd_rgb_panel_alloc_frame_buffers(rgb_panel), err, TAG, "alloc frame buffers failed"); // initialize DMA descriptor link - lcd_rgb_panel_init_trans_link(rgb_panel); + ESP_GOTO_ON_ERROR(lcd_rgb_panel_init_trans_link(rgb_panel), err, TAG, "init DMA link failed"); // configure GPIO ret = lcd_rgb_panel_configure_gpio(rgb_panel, rgb_panel_config); @@ -361,7 +360,6 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf rgb_panel->output_bits_per_pixel = fb_bits_per_pixel; // by default, the output bpp is the same as the frame buffer bpp rgb_panel->disp_gpio_num = rgb_panel_config->disp_gpio_num; rgb_panel->flags.disp_en_level = !rgb_panel_config->flags.disp_active_low; - rgb_panel->flags.bb_invalidate_cache = rgb_panel_config->flags.bb_invalidate_cache; rgb_panel->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; // fill function table rgb_panel->base.del = rgb_panel_del; @@ -398,19 +396,23 @@ esp_err_t esp_lcd_rgb_panel_register_event_callbacks(esp_lcd_panel_handle_t pane if (callbacks->on_vsync) { ESP_RETURN_ON_FALSE(esp_ptr_in_iram(callbacks->on_vsync), ESP_ERR_INVALID_ARG, TAG, "on_vsync callback not in IRAM"); } + if (callbacks->on_color_trans_done) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(callbacks->on_color_trans_done), ESP_ERR_INVALID_ARG, TAG, "on_color_trans_done callback not in IRAM"); + } + if (callbacks->on_frame_buf_complete) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(callbacks->on_frame_buf_complete), ESP_ERR_INVALID_ARG, TAG, "on_frame_buf_complete callback not in IRAM"); + } if (callbacks->on_bounce_empty) { ESP_RETURN_ON_FALSE(esp_ptr_in_iram(callbacks->on_bounce_empty), ESP_ERR_INVALID_ARG, TAG, "on_bounce_empty callback not in IRAM"); } - if (callbacks->on_bounce_frame_finish) { - ESP_RETURN_ON_FALSE(esp_ptr_in_iram(callbacks->on_bounce_frame_finish), ESP_ERR_INVALID_ARG, TAG, "on_bounce_frame_finish callback not in IRAM"); - } if (user_ctx) { ESP_RETURN_ON_FALSE(esp_ptr_internal(user_ctx), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM"); } #endif // CONFIG_LCD_RGB_ISR_IRAM_SAFE rgb_panel->on_vsync = callbacks->on_vsync; + rgb_panel->on_color_trans_done = callbacks->on_color_trans_done; + rgb_panel->on_frame_buf_complete = callbacks->on_frame_buf_complete; rgb_panel->on_bounce_empty = callbacks->on_bounce_empty; - rgb_panel->on_bounce_frame_finish = callbacks->on_bounce_frame_finish; rgb_panel->user_ctx = user_ctx; return ESP_OK; } @@ -488,8 +490,7 @@ esp_err_t esp_lcd_rgb_panel_set_yuv_conversion(esp_lcd_panel_handle_t panel, con if (config->src.color_space == LCD_COLOR_SPACE_YUV && config->dst.color_space == LCD_COLOR_SPACE_RGB) { // YUV->RGB lcd_ll_set_convert_mode_yuv_to_rgb(hal->dev, config->src.yuv_sample); - // Note, the RGB->YUV conversion only support RGB565 - rgb_panel->output_bits_per_pixel = 16; + rgb_panel->output_bits_per_pixel = rgb_panel->fb_bits_per_pixel; } else if (config->src.color_space == LCD_COLOR_SPACE_RGB && config->dst.color_space == LCD_COLOR_SPACE_YUV) { // RGB->YUV lcd_ll_set_convert_mode_rgb_to_yuv(hal->dev, config->dst.yuv_sample); rgb_panel->output_bits_per_pixel = bpp_yuv[config->dst.yuv_sample]; @@ -551,7 +552,8 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel) // enable RGB mode and set data width lcd_ll_enable_rgb_mode(rgb_panel->hal.dev, true); lcd_ll_set_dma_read_stride(rgb_panel->hal.dev, rgb_panel->data_width); - lcd_ll_set_phase_cycles(rgb_panel->hal.dev, 0, 0, 1); // enable data phase only + // enable data phase only + lcd_ll_set_phase_cycles(rgb_panel->hal.dev, 0, 0, 1); // number of data cycles is controlled by DMA buffer size lcd_ll_enable_output_always_on(rgb_panel->hal.dev, true); // configure HSYNC, VSYNC, DE signal idle state level @@ -569,7 +571,8 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel) lcd_ll_enable_output_hsync_in_porch_region(rgb_panel->hal.dev, true); // generate the hsync at the very beginning of line lcd_ll_set_hsync_position(rgb_panel->hal.dev, 0); - // send next frame automatically in stream mode + // in stream mode, after finish one frame, the LCD controller will ask for data automatically from the DMA + // DMA should prepare the next frame data within porch region lcd_ll_enable_auto_next_frame(rgb_panel->hal.dev, rgb_panel->flags.stream_mode); // trigger interrupt on the end of frame lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_VSYNC_END, true); @@ -583,157 +586,18 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel) return ret; } -__attribute__((always_inline)) -static inline void copy_pixel_8bpp(uint8_t *to, const uint8_t *from) -{ - *to++ = *from++; -} - -__attribute__((always_inline)) -static inline void copy_pixel_16bpp(uint8_t *to, const uint8_t *from) -{ - *to++ = *from++; - *to++ = *from++; -} - -__attribute__((always_inline)) -static inline void copy_pixel_24bpp(uint8_t *to, const uint8_t *from) -{ - *to++ = *from++; - *to++ = *from++; - *to++ = *from++; -} - -#define COPY_PIXEL_CODE_BLOCK(_bpp) \ - switch (rgb_panel->rotate_mask) \ - { \ - case 0: \ - { \ - uint8_t *to = fb + (y_start * h_res + x_start) * bytes_per_pixel; \ - for (int y = y_start; y < y_end; y++) \ - { \ - memcpy(to, from, copy_bytes_per_line); \ - to += bytes_per_line; \ - from += copy_bytes_per_line; \ - } \ - bytes_to_flush = (y_end - y_start) * bytes_per_line; \ - flush_ptr = fb + y_start * bytes_per_line; \ - } \ - break; \ - case ROTATE_MASK_MIRROR_X: \ - for (int y = y_start; y < y_end; y++) \ - { \ - uint32_t index = (y * h_res + (h_res - 1 - x_start)) * bytes_per_pixel; \ - for (size_t x = x_start; x < x_end; x++) \ - { \ - copy_pixel_##_bpp##bpp(to + index, from); \ - index -= bytes_per_pixel; \ - from += bytes_per_pixel; \ - } \ - } \ - bytes_to_flush = (y_end - y_start) * bytes_per_line; \ - flush_ptr = fb + y_start * bytes_per_line; \ - break; \ - case ROTATE_MASK_MIRROR_Y: \ - { \ - uint8_t *to = fb + ((v_res - 1 - y_start) * h_res + x_start) * bytes_per_pixel; \ - for (int y = y_start; y < y_end; y++) \ - { \ - memcpy(to, from, copy_bytes_per_line); \ - to -= bytes_per_line; \ - from += copy_bytes_per_line; \ - } \ - bytes_to_flush = (y_end - y_start) * bytes_per_line; \ - flush_ptr = fb + (v_res - y_end) * bytes_per_line; \ - } \ - break; \ - case ROTATE_MASK_MIRROR_X | ROTATE_MASK_MIRROR_Y: \ - for (int y = y_start; y < y_end; y++) \ - { \ - uint32_t index = ((v_res - 1 - y) * h_res + (h_res - 1 - x_start)) * bytes_per_pixel; \ - for (size_t x = x_start; x < x_end; x++) \ - { \ - copy_pixel_##_bpp##bpp(to + index, from); \ - index -= bytes_per_pixel; \ - from += bytes_per_pixel; \ - } \ - } \ - bytes_to_flush = (y_end - y_start) * bytes_per_line; \ - flush_ptr = fb + (v_res - y_end) * bytes_per_line; \ - break; \ - case ROTATE_MASK_SWAP_XY: \ - for (int y = y_start; y < y_end; y++) \ - { \ - for (int x = x_start; x < x_end; x++) \ - { \ - uint32_t j = y * copy_bytes_per_line + x * bytes_per_pixel - offset; \ - uint32_t i = (x * h_res + y) * bytes_per_pixel; \ - copy_pixel_##_bpp##bpp(to + i, from + j); \ - } \ - } \ - bytes_to_flush = (x_end - x_start) * bytes_per_line; \ - flush_ptr = fb + x_start * bytes_per_line; \ - break; \ - case ROTATE_MASK_SWAP_XY | ROTATE_MASK_MIRROR_X: \ - for (int y = y_start; y < y_end; y++) \ - { \ - for (int x = x_start; x < x_end; x++) \ - { \ - uint32_t j = y * copy_bytes_per_line + x * bytes_per_pixel - offset; \ - uint32_t i = (x * h_res + h_res - 1 - y) * bytes_per_pixel; \ - copy_pixel_##_bpp##bpp(to + i, from + j); \ - } \ - } \ - bytes_to_flush = (x_end - x_start) * bytes_per_line; \ - flush_ptr = fb + x_start * bytes_per_line; \ - break; \ - case ROTATE_MASK_SWAP_XY | ROTATE_MASK_MIRROR_Y: \ - for (int y = y_start; y < y_end; y++) \ - { \ - for (int x = x_start; x < x_end; x++) \ - { \ - uint32_t j = y * copy_bytes_per_line + x * bytes_per_pixel - offset; \ - uint32_t i = ((v_res - 1 - x) * h_res + y) * bytes_per_pixel; \ - copy_pixel_##_bpp##bpp(to + i, from + j); \ - } \ - } \ - bytes_to_flush = (x_end - x_start) * bytes_per_line; \ - flush_ptr = fb + (v_res - x_end) * bytes_per_line; \ - break; \ - case ROTATE_MASK_SWAP_XY | ROTATE_MASK_MIRROR_X | ROTATE_MASK_MIRROR_Y: \ - for (int y = y_start; y < y_end; y++) \ - { \ - for (int x = x_start; x < x_end; x++) \ - { \ - uint32_t j = y * copy_bytes_per_line + x * bytes_per_pixel - offset; \ - uint32_t i = ((v_res - 1 - x) * h_res + h_res - 1 - y) * bytes_per_pixel; \ - copy_pixel_##_bpp##bpp(to + i, from + j); \ - } \ - } \ - bytes_to_flush = (x_end - x_start) * bytes_per_line; \ - flush_ptr = fb + (v_res - x_end) * bytes_per_line; \ - break; \ - default: \ - break; \ - } - static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data) { esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base); ESP_RETURN_ON_FALSE(rgb_panel->num_fbs > 0, ESP_ERR_NOT_SUPPORTED, TAG, "no frame buffer installed"); + esp_lcd_rgb_panel_draw_buf_complete_cb_t cb = rgb_panel->on_color_trans_done; - // check if we need to copy the draw buffer (pointed by the color_data) to the driver's frame buffer - bool do_copy = false; - if (color_data == rgb_panel->fbs[0]) { - rgb_panel->cur_fb_index = 0; - } else if (color_data == rgb_panel->fbs[1]) { - rgb_panel->cur_fb_index = 1; - } else if (color_data == rgb_panel->fbs[2]) { - rgb_panel->cur_fb_index = 2; - } else { - // we do the copy only if the color_data is different from either frame buffer - do_copy = true; - } + uint8_t *draw_buffer = (uint8_t *)color_data; + size_t fb_size = rgb_panel->fb_size; + int h_res = rgb_panel->timings.h_res; + int v_res = rgb_panel->timings.v_res; + int bytes_per_pixel = rgb_panel->fb_bits_per_pixel / 8; + uint32_t bytes_per_line = bytes_per_pixel * h_res; // adjust the flush window by adding extra gap x_start += rgb_panel->x_gap; @@ -742,8 +606,6 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_end += rgb_panel->y_gap; // clip to boundaries - int h_res = rgb_panel->timings.h_res; - int v_res = rgb_panel->timings.v_res; if (rgb_panel->rotate_mask & ROTATE_MASK_SWAP_XY) { x_start = MAX(x_start, 0); x_end = MIN(x_end, v_res); @@ -756,15 +618,24 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_end = MIN(y_end, v_res); } - int bytes_per_pixel = rgb_panel->fb_bits_per_pixel / 8; - int pixels_per_line = rgb_panel->timings.h_res; - uint32_t bytes_per_line = bytes_per_pixel * pixels_per_line; - uint8_t *fb = rgb_panel->fbs[rgb_panel->cur_fb_index]; - size_t bytes_to_flush = v_res * h_res * bytes_per_pixel; - uint8_t *flush_ptr = fb; - - if (do_copy) { - // copy the UI draw buffer into internal frame buffer + // check if we want to copy the draw buffer to the internal frame buffer + bool draw_buf_copy_to_fb = true; + uint8_t draw_buf_fb_index = 0; + for (int i = 0; i < rgb_panel->num_fbs; i++) { + if (draw_buffer >= rgb_panel->fbs[i] && draw_buffer < rgb_panel->fbs[i] + fb_size) { + draw_buf_fb_index = i; + draw_buf_copy_to_fb = false; + break; + } + } + + if (draw_buf_copy_to_fb) { + // sync the draw buffer with the frame buffer by CPU copy + ESP_LOGV(TAG, "copy draw buffer to frame buffer by CPU"); + uint8_t *fb = rgb_panel->fbs[rgb_panel->cur_fb_index]; + size_t bytes_to_flush = v_res * bytes_per_line; + uint8_t *flush_ptr = fb; + const uint8_t *from = (const uint8_t *)color_data; uint32_t copy_bytes_per_line = (x_end - x_start) * bytes_per_pixel; size_t offset = y_start * copy_bytes_per_line + x_start * bytes_per_pixel; @@ -776,23 +647,41 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int } else if (3 == bytes_per_pixel) { COPY_PIXEL_CODE_BLOCK(24) } - } - - // Note that if we use a bounce buffer, the data gets read by the CPU as well so no need to write back - if (rgb_panel->flags.fb_in_psram && !rgb_panel->bb_size) { - // CPU writes data to PSRAM through DCache, data in PSRAM might not get updated, so write back - ESP_RETURN_ON_ERROR(esp_cache_msync(flush_ptr, bytes_to_flush, 0), TAG, "flush cache buffer failed"); + // do memory sync only when the frame buffer is mounted to the DMA link list and behind the cache + if (!rgb_panel->bb_size && rgb_panel->flags.fb_behind_cache) { + esp_cache_msync(flush_ptr, bytes_to_flush, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + } + // after the draw buffer finished copying, notify the user to recycle the draw buffer + if (cb) { + cb(&rgb_panel->base, NULL, rgb_panel->user_ctx); + } + } else { + ESP_LOGV(TAG, "draw buffer is part of the frame buffer"); + // the new frame buffer index is changed + rgb_panel->cur_fb_index = draw_buf_fb_index; + // when this function is called, the frame buffer already reflects the draw buffer changes + // if the frame buffer is also mounted to the DMA, we need to do the sync between them + if (!rgb_panel->bb_size && rgb_panel->flags.fb_behind_cache) { + uint8_t *cache_sync_start = rgb_panel->fbs[draw_buf_fb_index] + (y_start * h_res) * bytes_per_pixel; + size_t cache_sync_size = (y_end - y_start) * bytes_per_line; + esp_cache_msync(cache_sync_start, cache_sync_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + } + // after the draw buffer finished copying, notify the user to recycle the draw buffer + if (cb) { + cb(&rgb_panel->base, NULL, rgb_panel->user_ctx); + } } if (!rgb_panel->bb_size) { if (rgb_panel->flags.stream_mode) { - // the DMA will convey the new frame buffer next time - for (int i = 0; i < RGB_LCD_PANEL_DMA_LINKS_REPLICA; i++) { - rgb_panel->dma_nodes[rgb_panel->num_dma_nodes * (i + 1) - 1].next = rgb_panel->dma_links[rgb_panel->cur_fb_index]; + for (int i = 0; i < rgb_panel->num_fbs; i++) { + // Note, because of DMA prefetch, there's possibility that the old frame buffer might be sent out again + // it's hard to know the time when the new frame buffer starts + gdma_link_concat(rgb_panel->dma_fb_links[i], -1, rgb_panel->dma_fb_links[rgb_panel->cur_fb_index], 0); } + } } - return ESP_OK; } @@ -848,73 +737,67 @@ static esp_err_t rgb_panel_disp_on_off(esp_lcd_panel_t *panel, bool on_off) return ESP_OK; } -static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_lcd_rgb_panel_config_t *panel_config) +static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *rgb_panel, const esp_lcd_rgb_panel_config_t *panel_config) { - int panel_id = panel->panel_id; + int panel_id = rgb_panel->panel_id; // Set the number of output data lines - lcd_ll_set_data_wire_width(panel->hal.dev, panel_config->data_width); + lcd_ll_set_data_wire_width(rgb_panel->hal.dev, panel_config->data_width); // connect peripheral signals via GPIO matrix for (size_t i = 0; i < panel_config->data_width; i++) { if (panel_config->data_gpio_nums[i] >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->data_gpio_nums[i]], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->data_gpio_nums[i], GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->data_gpio_nums[i], PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->data_gpio_nums[i], lcd_periph_rgb_signals.panels[panel_id].data_sigs[i], false, false); } } if (panel_config->hsync_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->hsync_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->hsync_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->hsync_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->hsync_gpio_num, lcd_periph_rgb_signals.panels[panel_id].hsync_sig, false, false); } if (panel_config->vsync_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->vsync_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->vsync_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->vsync_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->vsync_gpio_num, lcd_periph_rgb_signals.panels[panel_id].vsync_sig, false, false); } // PCLK may not be necessary in some cases (i.e. VGA output) if (panel_config->pclk_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->pclk_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->pclk_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->pclk_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->pclk_gpio_num, lcd_periph_rgb_signals.panels[panel_id].pclk_sig, false, false); } // DE signal might not be necessary for some RGB LCD if (panel_config->de_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->de_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->de_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->de_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->de_gpio_num, lcd_periph_rgb_signals.panels[panel_id].de_sig, false, false); } - // disp enable GPIO is optional + // disp enable GPIO is optional, it is a general purpose output GPIO if (panel_config->disp_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->disp_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->disp_gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(panel_config->disp_gpio_num, SIG_GPIO_OUT_IDX, false, false); + gpio_func_sel(panel_config->disp_gpio_num, PIN_FUNC_GPIO); + gpio_output_enable(panel_config->disp_gpio_num); } return ESP_OK; } -static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *panel, lcd_clock_source_t clk_src) +static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *rgb_panel, lcd_clock_source_t clk_src) { // get clock source frequency uint32_t src_clk_hz = 0; ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_hz), TAG, "get clock source frequency failed"); - panel->src_clk_hz = src_clk_hz; + rgb_panel->src_clk_hz = src_clk_hz; esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); LCD_CLOCK_SRC_ATOMIC() { - lcd_ll_select_clk_src(panel->hal.dev, clk_src); + lcd_ll_select_clk_src(rgb_panel->hal.dev, clk_src); } // create pm lock based on different clock source // clock sources like PLL and XTAL will be turned off in light sleep #if CONFIG_PM_ENABLE - ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "rgb_panel", &panel->pm_lock), TAG, "create pm lock failed"); + ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "rgb_panel", &rgb_panel->pm_lock), TAG, "create pm lock failed"); // hold the lock during the whole lifecycle of RGB panel - esp_pm_lock_acquire(panel->pm_lock); + esp_pm_lock_acquire(rgb_panel->pm_lock); ESP_LOGD(TAG, "installed pm lock and hold the lock during the whole panel lifecycle"); #endif @@ -925,135 +808,211 @@ static IRAM_ATTR bool lcd_rgb_panel_fill_bounce_buffer(esp_rgb_panel_t *panel, u { bool need_yield = false; int bytes_per_pixel = panel->fb_bits_per_pixel / 8; - if (panel->num_fbs == 0) { + if (unlikely(panel->num_fbs == 0)) { + // driver doesn't maintain a frame buffer, so ask the user to fill the bounce buffer if (panel->on_bounce_empty) { - // We don't have a frame buffer here; we need to call a callback to refill the bounce buffer if (panel->on_bounce_empty(&panel->base, buffer, panel->bounce_pos_px, panel->bb_size, panel->user_ctx)) { need_yield = true; } } } else { - // We do have frame buffer; copy from there. - // Note: if the cache is disabled, and accessing the PSRAM by DCACHE will crash. + // copy partial frame buffer to the bounce buffer + // Note: if the frame buffer is behind a cache, and the cache is disabled, crash would happen here when auto write back happens memcpy(buffer, &panel->fbs[panel->bb_fb_index][panel->bounce_pos_px * bytes_per_pixel], panel->bb_size); - if (panel->flags.bb_invalidate_cache) { - // We don't need the bytes we copied from the psram anymore - // Make sure that if anything happened to have changed (because the line already was in cache) we write the data back. - esp_cache_msync(&panel->fbs[panel->bb_fb_index][panel->bounce_pos_px * bytes_per_pixel], (size_t)panel->bb_size, ESP_CACHE_MSYNC_FLAG_INVALIDATE); - } } + // do memory sync if the bounce buffer is behind the cache + if (panel->flags.bb_behind_cache) { + esp_cache_msync(buffer, panel->bb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + } + panel->bounce_pos_px += panel->bb_size / bytes_per_pixel; // If the bounce pos is larger than the frame buffer size, wrap around so the next isr starts pre-loading the next frame. if (panel->bounce_pos_px >= panel->fb_size / bytes_per_pixel) { panel->bounce_pos_px = 0; panel->bb_fb_index = panel->cur_fb_index; - if (panel->on_bounce_frame_finish) { - if (panel->on_bounce_frame_finish(&panel->base, NULL, panel->user_ctx)) { + esp_lcd_rgb_panel_frame_buf_complete_cb_t cb = panel->on_frame_buf_complete; + if (cb) { + if (cb(&panel->base, NULL, panel->user_ctx)) { need_yield = true; } } } - if (panel->num_fbs > 0) { - // Preload the next bit of buffer from psram + + // Preload the next bit of buffer to the cache memory, this can improve the performance + if (panel->num_fbs > 0 && panel->flags.fb_behind_cache) { +#if CONFIG_IDF_TARGET_ESP32S3 Cache_Start_DCache_Preload((uint32_t)&panel->fbs[panel->bb_fb_index][panel->bounce_pos_px * bytes_per_pixel], panel->bb_size, 0); +#elif CONFIG_IDF_TARGET_ESP32P4 + Cache_Start_L2_Cache_Preload((uint32_t)&panel->fbs[panel->bb_fb_index][panel->bounce_pos_px * bytes_per_pixel], + panel->bb_size, 0); +#else +#error "Unsupported target" +#endif } return need_yield; } -// This is called in bounce buffer mode, when one bounce buffer has been fully sent to the LCD peripheral. static IRAM_ATTR bool lcd_rgb_panel_eof_handler(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) { - esp_rgb_panel_t *panel = (esp_rgb_panel_t *)user_data; - dma_descriptor_t *desc = (dma_descriptor_t *)event_data->tx_eof_desc_addr; - // Figure out which bounce buffer to write to. - // Note: what we receive is the *last* descriptor of this bounce buffer. - int bb = (desc == &panel->dma_nodes[panel->num_dma_nodes - 1]) ? 0 : 1; - portENTER_CRITICAL_ISR(&panel->spinlock); - panel->bb_eof_count++; - portEXIT_CRITICAL_ISR(&panel->spinlock); - return lcd_rgb_panel_fill_bounce_buffer(panel, panel->bounce_buffer[bb]); + bool need_yield = false; + esp_rgb_panel_t *rgb_panel = (esp_rgb_panel_t *)user_data; + + if (rgb_panel->bb_size) { + // in bounce buffer mode, the DMA EOF means time to fill the finished bounce buffer + // Figure out which bounce buffer to write to + portENTER_CRITICAL_ISR(&rgb_panel->spinlock); + int bb = rgb_panel->bb_eof_count % RGB_LCD_PANEL_BOUNCE_BUF_NUM; + rgb_panel->bb_eof_count++; + portEXIT_CRITICAL_ISR(&rgb_panel->spinlock); + need_yield = lcd_rgb_panel_fill_bounce_buffer(rgb_panel, rgb_panel->bounce_buffer[bb]); + } else { + // if not bounce buffer, the DMA EOF event means the end of a frame has been sent out to the LCD controller + if (rgb_panel->on_frame_buf_complete) { + if (rgb_panel->on_frame_buf_complete(&rgb_panel->base, NULL, rgb_panel->user_ctx)) { + need_yield = true; + } + } + } + return need_yield; } -static esp_err_t lcd_rgb_create_dma_channel(esp_rgb_panel_t *panel) +static esp_err_t lcd_rgb_create_dma_channel(esp_rgb_panel_t *rgb_panel) { // alloc DMA channel and connect to LCD peripheral gdma_channel_alloc_config_t dma_chan_config = { .direction = GDMA_CHANNEL_DIRECTION_TX, }; -#if SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AHB - ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_chan_config, &panel->dma_chan), TAG, "alloc DMA channel failed"); -#elif SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AXI - ESP_RETURN_ON_ERROR(gdma_new_axi_channel(&dma_chan_config, &panel->dma_chan), TAG, "alloc DMA channel failed"); -#endif - gdma_connect(panel->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0)); + ESP_RETURN_ON_ERROR(LCD_GDMA_NEW_CHANNEL(&dma_chan_config, &rgb_panel->dma_chan), TAG, "alloc DMA channel failed"); + gdma_connect(rgb_panel->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0)); - // configure DMA transfer parameters + // configure DMA strategy + gdma_strategy_config_t dma_strategy = { + .eof_till_data_popped = false, + }; + gdma_apply_strategy(rgb_panel->dma_chan, &dma_strategy); + + // configure DMA transfer gdma_transfer_config_t trans_cfg = { - .max_data_burst_size = panel->dma_burst_size, - .access_ext_mem = true, // frame buffer was allocated from external memory + .max_data_burst_size = rgb_panel->dma_burst_size, + .access_ext_mem = rgb_panel->flags.fb_in_psram, }; - ESP_RETURN_ON_ERROR(gdma_config_transfer(panel->dma_chan, &trans_cfg), TAG, "config DMA transfer failed"); + ESP_RETURN_ON_ERROR(gdma_config_transfer(rgb_panel->dma_chan, &trans_cfg), TAG, "config DMA transfer failed"); + // get the memory alignment required by the DMA + gdma_get_alignment_constraints(rgb_panel->dma_chan, &rgb_panel->int_mem_align, &rgb_panel->ext_mem_align); - // we need to refill the bounce buffer in the DMA EOF interrupt, so only register the callback for bounce buffer mode - if (panel->bb_size) { - gdma_tx_event_callbacks_t cbs = { - .on_trans_eof = lcd_rgb_panel_eof_handler, - }; - gdma_register_tx_event_callbacks(panel->dma_chan, &cbs, panel); - } + // register DMA EOF callback + gdma_tx_event_callbacks_t cbs = { + .on_trans_eof = lcd_rgb_panel_eof_handler, + }; + ESP_RETURN_ON_ERROR(gdma_register_tx_event_callbacks(rgb_panel->dma_chan, &cbs, rgb_panel), TAG, "register DMA EOF callback failed"); return ESP_OK; } -// If we restart GDMA, many pixels already have been transferred to the LCD peripheral. -// Looks like that has 16 pixels of FIFO plus one holding register. +#if RGB_LCD_NEEDS_SEPARATE_RESTART_LINK +// If we restart GDMA, the data sent to the LCD peripheral needs to start LCD_FIFO_PRESERVE_SIZE_PX pixels after the FB start +// so we use a dedicated DMA link (called restart link) to restart the transaction #define LCD_FIFO_PRESERVE_SIZE_PX (LCD_LL_FIFO_DEPTH + 1) +#endif -static void lcd_rgb_panel_init_trans_link(esp_rgb_panel_t *panel) +static esp_err_t lcd_rgb_panel_init_trans_link(esp_rgb_panel_t *rgb_panel) { - for (int i = 0; i < RGB_LCD_PANEL_DMA_LINKS_REPLICA; i++) { - panel->dma_links[i] = &panel->dma_nodes[panel->num_dma_nodes * i]; - } - // chain DMA descriptors - for (int i = 0; i < panel->num_dma_nodes * RGB_LCD_PANEL_DMA_LINKS_REPLICA; i++) { - panel->dma_nodes[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_CPU; - panel->dma_nodes[i].next = &panel->dma_nodes[i + 1]; - } - - if (panel->bb_size) { - // loop end back to start - panel->dma_nodes[panel->num_dma_nodes * RGB_LCD_PANEL_BOUNCE_BUF_NUM - 1].next = &panel->dma_nodes[0]; - // mount the bounce buffers to the DMA descriptors - lcd_com_mount_dma_data(panel->dma_links[0], panel->bounce_buffer[0], panel->bb_size); - lcd_com_mount_dma_data(panel->dma_links[1], panel->bounce_buffer[1], panel->bb_size); - } else { - if (panel->flags.stream_mode) { - // circle DMA descriptors chain for each frame buffer - for (int i = 0; i < RGB_LCD_PANEL_DMA_LINKS_REPLICA; i++) { - panel->dma_nodes[panel->num_dma_nodes * (i + 1) - 1].next = &panel->dma_nodes[panel->num_dma_nodes * i]; - } - } else { - // one-off DMA descriptors chain - for (int i = 0; i < RGB_LCD_PANEL_DMA_LINKS_REPLICA; i++) { - panel->dma_nodes[panel->num_dma_nodes * (i + 1) - 1].next = NULL; +#if RGB_LCD_NEEDS_SEPARATE_RESTART_LINK + // the restart link shares the same buffer with the frame/bounce buffer but start from a different offset + int restart_skip_bytes = LCD_FIFO_PRESERVE_SIZE_PX * (rgb_panel->fb_bits_per_pixel / 8); +#endif + if (rgb_panel->bb_size) { + // DMA is used to convey the bounce buffer + size_t num_dma_nodes_per_bounce_buffer = (rgb_panel->bb_size + LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE - 1) / LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE; + gdma_link_list_config_t link_cfg = { + .buffer_alignment = rgb_panel->int_mem_align, + .item_alignment = LCD_GDMA_DESCRIPTOR_ALIGN, + .num_items = num_dma_nodes_per_bounce_buffer * RGB_LCD_PANEL_BOUNCE_BUF_NUM, + .flags = { + .check_owner = true, } + }; + ESP_RETURN_ON_ERROR(gdma_new_link_list(&link_cfg, &rgb_panel->dma_bb_link), TAG, "create bounce buffer DMA link failed"); + // mount bounce buffers to the DMA link list + gdma_buffer_mount_config_t mount_cfgs[RGB_LCD_PANEL_BOUNCE_BUF_NUM] = {0}; + for (int i = 0; i < RGB_LCD_PANEL_BOUNCE_BUF_NUM; i++) { + mount_cfgs[i].buffer = rgb_panel->bounce_buffer[i]; + mount_cfgs[i].length = rgb_panel->bb_size; + mount_cfgs[i].flags.mark_eof = true; // we use the DMA EOF interrupt to copy the frame buffer (partially) to the bounce buffer } - // mount the frame buffer to the DMA descriptors - for (size_t i = 0; i < panel->num_fbs; i++) { - lcd_com_mount_dma_data(panel->dma_links[i], panel->fbs[i], panel->fb_size); + ESP_RETURN_ON_ERROR(gdma_link_mount_buffers(rgb_panel->dma_bb_link, 0, mount_cfgs, RGB_LCD_PANEL_BOUNCE_BUF_NUM, NULL), + TAG, "mount DMA bounce buffers failed"); +#if RGB_LCD_NEEDS_SEPARATE_RESTART_LINK + // create restart link + gdma_link_list_config_t restart_link_cfg = { + .buffer_alignment = rgb_panel->int_mem_align, + .item_alignment = LCD_GDMA_DESCRIPTOR_ALIGN, + .num_items = 1, // the restart link only contains one node + .flags = { + .check_owner = true, + } + }; + ESP_RETURN_ON_ERROR(gdma_new_link_list(&restart_link_cfg, &rgb_panel->dma_restart_link), TAG, "create DMA restart link list failed"); + gdma_buffer_mount_config_t restart_buffer_mount_cfg = { + .buffer = rgb_panel->bounce_buffer[0] + restart_skip_bytes, + .length = MIN(LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE, rgb_panel->bb_size) - restart_skip_bytes, + }; + ESP_RETURN_ON_ERROR(gdma_link_mount_buffers(rgb_panel->dma_restart_link, 0, &restart_buffer_mount_cfg, 1, NULL), + TAG, "mount DMA restart buffer failed"); + + // Magic here: we use the restart link to restart the bounce buffer link list, so concat them + gdma_link_concat(rgb_panel->dma_restart_link, 0, rgb_panel->dma_bb_link, 1); +#endif + } else { + // DMA is used to convey the frame buffer + size_t num_dma_nodes = (rgb_panel->fb_size + LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE - 1) / LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE; + gdma_link_list_config_t link_cfg = { + .buffer_alignment = rgb_panel->flags.fb_in_psram ? rgb_panel->ext_mem_align : rgb_panel->int_mem_align, + .item_alignment = LCD_GDMA_DESCRIPTOR_ALIGN, + .num_items = num_dma_nodes, + .flags = { + .check_owner = true, + }, + }; + gdma_buffer_mount_config_t mount_cfg = { + .length = rgb_panel->fb_size, + .flags = { + .mark_final = rgb_panel->flags.stream_mode ? false : true, + .mark_eof = true, + }, + }; + for (size_t i = 0; i < rgb_panel->num_fbs; i++) { + ESP_RETURN_ON_ERROR(gdma_new_link_list(&link_cfg, &rgb_panel->dma_fb_links[i]), TAG, "create frame buffer DMA link failed"); + // mount bounce buffers to the DMA link list + mount_cfg.buffer = rgb_panel->fbs[i]; + ESP_RETURN_ON_ERROR(gdma_link_mount_buffers(rgb_panel->dma_fb_links[i], 0, &mount_cfg, 1, NULL), + TAG, "mount DMA frame buffer failed"); } +#if RGB_LCD_NEEDS_SEPARATE_RESTART_LINK + // create restart link + gdma_link_list_config_t restart_link_cfg = { + .buffer_alignment = rgb_panel->flags.fb_in_psram ? rgb_panel->ext_mem_align : rgb_panel->int_mem_align, + .item_alignment = LCD_GDMA_DESCRIPTOR_ALIGN, + .num_items = 1, // the restart link only contains one node + .flags = { + .check_owner = true, + } + }; + ESP_RETURN_ON_ERROR(gdma_new_link_list(&restart_link_cfg, &rgb_panel->dma_restart_link), TAG, "create DMA restart link list failed"); + gdma_buffer_mount_config_t restart_buffer_mount_cfg = { + .buffer = rgb_panel->fbs[0] + restart_skip_bytes, + .length = MIN(LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE, rgb_panel->fb_size) - restart_skip_bytes, + }; + ESP_RETURN_ON_ERROR(gdma_link_mount_buffers(rgb_panel->dma_restart_link, 0, &restart_buffer_mount_cfg, 1, NULL), + TAG, "mount DMA restart buffer failed"); + + // Magic here: we use the restart link to restart the frame buffer link list, so concat them + gdma_link_concat(rgb_panel->dma_restart_link, 0, rgb_panel->dma_fb_links[0], 1); +#endif } - // On restart, the data sent to the LCD peripheral needs to start LCD_FIFO_PRESERVE_SIZE_PX pixels after the FB start - // so we use a dedicated DMA node to restart the DMA transaction - // see also `lcd_rgb_panel_try_restart_transmission` - memcpy(&panel->dma_restart_node, &panel->dma_nodes[0], sizeof(panel->dma_restart_node)); - int restart_skip_bytes = LCD_FIFO_PRESERVE_SIZE_PX * (panel->fb_bits_per_pixel / 8); - uint8_t *p = (uint8_t *)panel->dma_restart_node.buffer; - panel->dma_restart_node.buffer = &p[restart_skip_bytes]; - panel->dma_restart_node.dw0.length -= restart_skip_bytes; - panel->dma_restart_node.dw0.size -= restart_skip_bytes; + return ESP_OK; } // reset the GDMA channel every VBlank to stop permanent desyncs from happening. @@ -1098,8 +1057,17 @@ static IRAM_ATTR void lcd_rgb_panel_try_restart_transmission(esp_rgb_panel_t *pa } gdma_reset(panel->dma_chan); + lcd_ll_fifo_reset(panel->hal.dev); +#if RGB_LCD_NEEDS_SEPARATE_RESTART_LINK // restart the DMA by a special DMA node - gdma_start(panel->dma_chan, (intptr_t)&panel->dma_restart_node); + gdma_start(panel->dma_chan, gdma_link_get_head_addr(panel->dma_restart_link)); +#else + if (panel->bb_size) { + gdma_start(panel->dma_chan, gdma_link_get_head_addr(panel->dma_bb_link)); + } else { + gdma_start(panel->dma_chan, gdma_link_get_head_addr(panel->dma_fb_links[panel->cur_fb_index])); + } +#endif if (panel->bb_size) { // Fill 2nd bounce buffer while 1st is being sent out, if needed. @@ -1115,6 +1083,7 @@ static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel) // reset FIFO of DMA and LCD, in case there remains old frame data gdma_reset(rgb_panel->dma_chan); lcd_ll_stop(rgb_panel->hal.dev); + lcd_ll_reset(rgb_panel->hal.dev); lcd_ll_fifo_reset(rgb_panel->hal.dev); // pre-fill bounce buffers if needed @@ -1125,7 +1094,11 @@ static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel) } // the start of DMA should be prior to the start of LCD engine - gdma_start(rgb_panel->dma_chan, (intptr_t)rgb_panel->dma_links[rgb_panel->cur_fb_index]); + if (rgb_panel->bb_size) { + gdma_start(rgb_panel->dma_chan, gdma_link_get_head_addr(rgb_panel->dma_bb_link)); + } else { + gdma_start(rgb_panel->dma_chan, gdma_link_get_head_addr(rgb_panel->dma_fb_links[rgb_panel->cur_fb_index])); + } // delay 1us is sufficient for DMA to pass data to LCD FIFO // in fact, this is only needed when LCD pixel clock is set too high esp_rom_delay_us(1); @@ -1147,13 +1120,16 @@ IRAM_ATTR static void lcd_rgb_panel_try_update_pclk(esp_rgb_panel_t *rgb_panel) portEXIT_CRITICAL_ISR(&rgb_panel->spinlock); } -IRAM_ATTR static void lcd_default_isr_handler(void *args) +IRAM_ATTR static void rgb_lcd_default_isr_handler(void *args) { esp_rgb_panel_t *rgb_panel = (esp_rgb_panel_t *)args; bool need_yield = false; + // clear the interrupt status uint32_t intr_status = lcd_ll_get_interrupt_status(rgb_panel->hal.dev); lcd_ll_clear_interrupt_status(rgb_panel->hal.dev, intr_status); + + // VSYNC event happened if (intr_status & LCD_LL_EVENT_VSYNC_END) { // call user registered callback if (rgb_panel->on_vsync) { @@ -1171,6 +1147,7 @@ IRAM_ATTR static void lcd_default_isr_handler(void *args) } } + // yield if needed if (need_yield) { portYIELD_FROM_ISR(); } diff --git a/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h b/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h index 2e9e5a95a6e3..389d49ef2f84 100644 --- a/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h +++ b/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -77,14 +77,32 @@ typedef struct { } esp_lcd_rgb_panel_event_data_t; /** - * @brief RGB LCD VSYNC event callback prototype + * @brief A general function callback prototype for RGB panel driver * - * @param[in] panel LCD panel handle, returned from `esp_lcd_new_rgb_panel` - * @param[in] edata Panel event data, fed by driver + * @param[in] panel LCD panel handle, which is created by factory API like `esp_lcd_new_rgb_panel` + * @param[in] edata RGB panel event data, provided by driver * @param[in] user_ctx User data, passed from `esp_lcd_rgb_panel_register_event_callbacks()` * @return Whether a high priority task has been waken up by this function */ -typedef bool (*esp_lcd_rgb_panel_vsync_cb_t)(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx); +typedef bool (*esp_lcd_rgb_panel_general_cb_t)(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx); + +/** + * @brief Declare the prototype of the function that will be invoked when the user draw buffer is complete. + * The draw buffer can be recycled after this event. + */ +typedef esp_lcd_rgb_panel_general_cb_t esp_lcd_rgb_panel_draw_buf_complete_cb_t; + +/** + * @brief Declare the prototype of the function that will be invoked when a whole frame buffer is sent to the LCD DMA. + * The LCD hardware may still need some blank time to finish the refresh. + */ +typedef esp_lcd_rgb_panel_general_cb_t esp_lcd_rgb_panel_frame_buf_complete_cb_t; + +/** + * @brief Declare the prototype of the function that will be invoked when the LCD controller sends the VSYNC signal. + * It means, the LCD hardware should be ready, and after some blank time, the next frame will be flushed to the LCD controller. + */ +typedef esp_lcd_rgb_panel_general_cb_t esp_lcd_rgb_panel_vsync_cb_t; /** * @brief Prototype for function to re-fill a bounce buffer, rather than copying from the frame buffer @@ -99,15 +117,10 @@ typedef bool (*esp_lcd_rgb_panel_vsync_cb_t)(esp_lcd_panel_handle_t panel, const */ typedef bool (*esp_lcd_rgb_panel_bounce_buf_fill_cb_t)(esp_lcd_panel_handle_t panel, void *bounce_buf, int pos_px, int len_bytes, void *user_ctx); -/** - * @brief Prototype for the function to be called when the bounce buffer finish copying the entire frame. - * - * @param[in] panel LCD panel handle, returned from `esp_lcd_new_rgb_panel` - * @param[in] edata Panel event data, fed by driver - * @param[in] user_ctx User data, passed from `esp_lcd_rgb_panel_register_event_callbacks()` - * @return Whether a high priority task has been waken up by this function - */ -typedef bool (*esp_lcd_rgb_panel_bounce_buf_finish_cb_t)(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx); +/** @cond */ +/// for backward compatible +typedef esp_lcd_rgb_panel_frame_buf_complete_cb_t esp_lcd_rgb_panel_bounce_buf_finish_cb_t __attribute__((deprecated("esp_lcd_rgb_panel_bounce_buf_finish_cb_t is deprecated, use esp_lcd_rgb_panel_frame_buf_complete_cb_t instead"))); +/** @endcond */ /** * @brief Group of supported RGB LCD panel callbacks @@ -115,9 +128,15 @@ typedef bool (*esp_lcd_rgb_panel_bounce_buf_finish_cb_t)(esp_lcd_panel_handle_t * @note When CONFIG_LCD_RGB_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM. */ typedef struct { - esp_lcd_rgb_panel_vsync_cb_t on_vsync; /*!< VSYNC event callback */ - esp_lcd_rgb_panel_bounce_buf_fill_cb_t on_bounce_empty; /*!< Bounce buffer empty callback. */ - esp_lcd_rgb_panel_bounce_buf_finish_cb_t on_bounce_frame_finish; /*!< Bounce buffer finish callback. */ + esp_lcd_rgb_panel_draw_buf_complete_cb_t on_color_trans_done; /*!< Invoked when user's color buffer copied to the internal frame buffer. + This is an indicator that the draw buffer can be recycled safely. + But doesn't mean the draw buffer finishes the refreshing to the screen. */ + esp_lcd_rgb_panel_vsync_cb_t on_vsync; /*!< VSYNC event callback */ + esp_lcd_rgb_panel_bounce_buf_fill_cb_t on_bounce_empty; /*!< Bounce buffer empty callback. */ + union { + esp_lcd_rgb_panel_frame_buf_complete_cb_t on_bounce_frame_finish __attribute__((deprecated)); /*!< Bounce buffer finish callback. */ + esp_lcd_rgb_panel_frame_buf_complete_cb_t on_frame_buf_complete; /*!< A whole frame buffer was just sent to the LCD DMA */ + }; } esp_lcd_rgb_panel_event_callbacks_t; /** @@ -134,7 +153,7 @@ typedef struct { DMA fetching from DRAM bounce buffer is much faster than PSRAM frame buffer. */ size_t sram_trans_align __attribute__((deprecated)); /*!< Alignment of buffers (frame buffer or bounce buffer) that allocated in SRAM */ union { - size_t psram_trans_align; /*!< Alignment of buffers (frame buffer) that allocated in PSRAM */ + size_t psram_trans_align __attribute__((deprecated)); /*!< Alignment of buffers (frame buffer) that allocated in PSRAM */ size_t dma_burst_size; /*!< DMA burst size, in bytes */ }; int hsync_gpio_num; /*!< GPIO used for HSYNC signal */ @@ -142,11 +161,10 @@ typedef struct { int de_gpio_num; /*!< GPIO used for DE signal, set to -1 if it's not used */ int pclk_gpio_num; /*!< GPIO used for PCLK signal, set to -1 if it's not used */ int disp_gpio_num; /*!< GPIO used for display control signal, set to -1 if it's not used */ - int data_gpio_nums[SOC_LCD_RGB_DATA_WIDTH]; /*!< GPIOs used for data lines */ + int data_gpio_nums[SOC_LCDCAM_RGB_DATA_WIDTH]; /*!< GPIOs used for data lines */ struct { uint32_t disp_active_low: 1; /*!< If this flag is enabled, a low level of display control signal can turn the screen on; vice versa */ - uint32_t refresh_on_demand: 1; /*!< If this flag is enabled, the host only refresh the frame buffer when `esp_lcd_panel_draw_bitmap` is called. - This is useful when the LCD screen has a GRAM and can refresh the LCD by itself. */ + uint32_t refresh_on_demand: 1; /*!< If this flag is enabled, the host only refresh the frame buffer in `esp_lcd_panel_draw_bitmap` and `esp_lcd_rgb_panel_refresh`. */ uint32_t fb_in_psram: 1; /*!< If this flag is enabled, the frame buffer will be allocated from PSRAM, preferentially */ uint32_t double_fb: 1; /*!< If this flag is enabled, the driver will allocate two screen sized frame buffer, same as num_fbs=2 */ uint32_t no_fb: 1; /*!< If this flag is enabled, the driver won't allocate frame buffer. diff --git a/components/esp_lcd/rgb/rgb_lcd_rotation_sw.h b/components/esp_lcd/rgb/rgb_lcd_rotation_sw.h new file mode 100644 index 000000000000..401786cbcbd3 --- /dev/null +++ b/components/esp_lcd/rgb/rgb_lcd_rotation_sw.h @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "esp_bit_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define RGB_PANEL_SWAP_XY 0 +#define RGB_PANEL_MIRROR_Y 1 +#define RGB_PANEL_MIRROR_X 2 + +typedef enum { + ROTATE_MASK_SWAP_XY = BIT(RGB_PANEL_SWAP_XY), + ROTATE_MASK_MIRROR_Y = BIT(RGB_PANEL_MIRROR_Y), + ROTATE_MASK_MIRROR_X = BIT(RGB_PANEL_MIRROR_X), +} panel_rotate_mask_t; + +__attribute__((always_inline)) +static inline void copy_pixel_8bpp(uint8_t *to, const uint8_t *from) +{ + *to++ = *from++; +} + +__attribute__((always_inline)) +static inline void copy_pixel_16bpp(uint8_t *to, const uint8_t *from) +{ + *to++ = *from++; + *to++ = *from++; +} + +__attribute__((always_inline)) +static inline void copy_pixel_24bpp(uint8_t *to, const uint8_t *from) +{ + *to++ = *from++; + *to++ = *from++; + *to++ = *from++; +} + +#define COPY_PIXEL_CODE_BLOCK(_bpp) \ + switch (rgb_panel->rotate_mask) \ + { \ + case 0: \ + { \ + uint8_t *to = fb + (y_start * h_res + x_start) * bytes_per_pixel; \ + for (int y = y_start; y < y_end; y++) \ + { \ + memcpy(to, from, copy_bytes_per_line); \ + to += bytes_per_line; \ + from += copy_bytes_per_line; \ + } \ + bytes_to_flush = (y_end - y_start) * bytes_per_line; \ + flush_ptr = fb + y_start * bytes_per_line; \ + } \ + break; \ + case ROTATE_MASK_MIRROR_X: \ + for (int y = y_start; y < y_end; y++) \ + { \ + uint32_t index = (y * h_res + (h_res - 1 - x_start)) * bytes_per_pixel; \ + for (size_t x = x_start; x < x_end; x++) \ + { \ + copy_pixel_##_bpp##bpp(to + index, from); \ + index -= bytes_per_pixel; \ + from += bytes_per_pixel; \ + } \ + } \ + bytes_to_flush = (y_end - y_start) * bytes_per_line; \ + flush_ptr = fb + y_start * bytes_per_line; \ + break; \ + case ROTATE_MASK_MIRROR_Y: \ + { \ + uint8_t *to = fb + ((v_res - 1 - y_start) * h_res + x_start) * bytes_per_pixel; \ + for (int y = y_start; y < y_end; y++) \ + { \ + memcpy(to, from, copy_bytes_per_line); \ + to -= bytes_per_line; \ + from += copy_bytes_per_line; \ + } \ + bytes_to_flush = (y_end - y_start) * bytes_per_line; \ + flush_ptr = fb + (v_res - y_end) * bytes_per_line; \ + } \ + break; \ + case ROTATE_MASK_MIRROR_X | ROTATE_MASK_MIRROR_Y: \ + for (int y = y_start; y < y_end; y++) \ + { \ + uint32_t index = ((v_res - 1 - y) * h_res + (h_res - 1 - x_start)) * bytes_per_pixel; \ + for (size_t x = x_start; x < x_end; x++) \ + { \ + copy_pixel_##_bpp##bpp(to + index, from); \ + index -= bytes_per_pixel; \ + from += bytes_per_pixel; \ + } \ + } \ + bytes_to_flush = (y_end - y_start) * bytes_per_line; \ + flush_ptr = fb + (v_res - y_end) * bytes_per_line; \ + break; \ + case ROTATE_MASK_SWAP_XY: \ + for (int y = y_start; y < y_end; y++) \ + { \ + for (int x = x_start; x < x_end; x++) \ + { \ + uint32_t j = y * copy_bytes_per_line + x * bytes_per_pixel - offset; \ + uint32_t i = (x * h_res + y) * bytes_per_pixel; \ + copy_pixel_##_bpp##bpp(to + i, from + j); \ + } \ + } \ + bytes_to_flush = (x_end - x_start) * bytes_per_line; \ + flush_ptr = fb + x_start * bytes_per_line; \ + break; \ + case ROTATE_MASK_SWAP_XY | ROTATE_MASK_MIRROR_X: \ + for (int y = y_start; y < y_end; y++) \ + { \ + for (int x = x_start; x < x_end; x++) \ + { \ + uint32_t j = y * copy_bytes_per_line + x * bytes_per_pixel - offset; \ + uint32_t i = (x * h_res + h_res - 1 - y) * bytes_per_pixel; \ + copy_pixel_##_bpp##bpp(to + i, from + j); \ + } \ + } \ + bytes_to_flush = (x_end - x_start) * bytes_per_line; \ + flush_ptr = fb + x_start * bytes_per_line; \ + break; \ + case ROTATE_MASK_SWAP_XY | ROTATE_MASK_MIRROR_Y: \ + for (int y = y_start; y < y_end; y++) \ + { \ + for (int x = x_start; x < x_end; x++) \ + { \ + uint32_t j = y * copy_bytes_per_line + x * bytes_per_pixel - offset; \ + uint32_t i = ((v_res - 1 - x) * h_res + y) * bytes_per_pixel; \ + copy_pixel_##_bpp##bpp(to + i, from + j); \ + } \ + } \ + bytes_to_flush = (x_end - x_start) * bytes_per_line; \ + flush_ptr = fb + (v_res - x_end) * bytes_per_line; \ + break; \ + case ROTATE_MASK_SWAP_XY | ROTATE_MASK_MIRROR_X | ROTATE_MASK_MIRROR_Y: \ + for (int y = y_start; y < y_end; y++) \ + { \ + for (int x = x_start; x < x_end; x++) \ + { \ + uint32_t j = y * copy_bytes_per_line + x * bytes_per_pixel - offset; \ + uint32_t i = ((v_res - 1 - x) * h_res + h_res - 1 - y) * bytes_per_pixel; \ + copy_pixel_##_bpp##bpp(to + i, from + j); \ + } \ + } \ + bytes_to_flush = (x_end - x_start) * bytes_per_line; \ + flush_ptr = fb + (v_res - x_end) * bytes_per_line; \ + break; \ + default: \ + break; \ + } + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_lcd/src/esp_lcd_common.c b/components/esp_lcd/src/esp_lcd_common.c index 07ee21a98e23..7b739188bba5 100644 --- a/components/esp_lcd/src/esp_lcd_common.c +++ b/components/esp_lcd/src/esp_lcd_common.c @@ -78,29 +78,3 @@ void lcd_com_remove_device(lcd_com_device_type_t device_type, int member_id) } } #endif // SOC_LCDCAM_SUPPORTED - -void lcd_com_mount_dma_data(dma_descriptor_t *desc_head, const void *buffer, size_t len) -{ - size_t prepared_length = 0; - uint8_t *data = (uint8_t *)buffer; - dma_descriptor_t *desc = desc_head; - while (len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE) { - desc->dw0.suc_eof = 0; // not the end of the transaction - desc->dw0.size = DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - desc->dw0.length = DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; - desc->buffer = &data[prepared_length]; - desc = desc->next; // move to next descriptor - prepared_length += DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - len -= DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - } - if (len) { - desc->dw0.suc_eof = 1; // end of the transaction - desc->dw0.size = len; - desc->dw0.length = len; - desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; - desc->buffer = &data[prepared_length]; - desc = desc->next; // move to next descriptor - prepared_length += len; - } -} diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt b/components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt index 30d912b096cf..e895a0deedaf 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt @@ -7,6 +7,9 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mipi_dsi_lcd_panel_test) +target_add_binary_data(mipi_dsi_lcd_panel_test.elf "resources/pictures/hello.yuv" BINARY) +target_add_binary_data(mipi_dsi_lcd_panel_test.elf "resources/pictures/world.yuv" BINARY) + if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/idf_component.yml b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/idf_component.yml index 27d4953b96c4..2187eb1048b3 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/idf_component.yml +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/idf_component.yml @@ -1,2 +1,2 @@ dependencies: - esp_lcd_ili9881c: "~0.2.0" + esp_lcd_ek79007: "^1.0.0" diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_board.h b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_board.h index d1e57d9a47fc..069e4369842a 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_board.h +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_board.h @@ -9,16 +9,16 @@ extern "C" { #endif -// FPS = 80000000/(40+140+40+800)/(4+16+16+1280) = 60Hz -#define MIPI_DSI_DPI_CLK_MHZ 80 -#define MIPI_DSI_LCD_H_RES 800 -#define MIPI_DSI_LCD_V_RES 1280 -#define MIPI_DSI_LCD_HSYNC 40 -#define MIPI_DSI_LCD_HBP 140 -#define MIPI_DSI_LCD_HFP 40 -#define MIPI_DSI_LCD_VSYNC 4 -#define MIPI_DSI_LCD_VBP 16 -#define MIPI_DSI_LCD_VFP 16 +// Refresh Rate = 48000000/(10+120+120+1024)/(1+20+10+600) = 60Hz +#define MIPI_DSI_DPI_CLK_MHZ 48 +#define MIPI_DSI_LCD_H_RES 1024 +#define MIPI_DSI_LCD_V_RES 600 +#define MIPI_DSI_LCD_HSYNC 10 +#define MIPI_DSI_LCD_HBP 120 +#define MIPI_DSI_LCD_HFP 120 +#define MIPI_DSI_LCD_VSYNC 1 +#define MIPI_DSI_LCD_VBP 20 +#define MIPI_DSI_LCD_VFP 20 #define TEST_MIPI_DSI_PHY_PWR_LDO_CHAN 3 #define TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500 diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_iram.c b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_iram.c index 85cef15288ff..51299acb8c99 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_iram.c +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_iram.c @@ -16,7 +16,7 @@ #include "esp_random.h" #include "esp_attr.h" #include "test_mipi_dsi_board.h" -#include "esp_lcd_ili9881c.h" +#include "esp_lcd_ek79007.h" IRAM_ATTR static bool test_rgb_panel_count_in_callback(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx) { @@ -32,12 +32,11 @@ static void IRAM_ATTR test_delay_post_cache_disable(void *args) #define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t)) -TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]") +TEST_CASE("MIPI DSI draw bitmap (EK79007) IRAM Safe", "[mipi_dsi]") { esp_lcd_dsi_bus_handle_t mipi_dsi_bus; esp_lcd_panel_io_handle_t mipi_dbi_io; esp_lcd_panel_handle_t mipi_dpi_panel; - esp_lcd_panel_handle_t ili9881c_ctrl_panel; test_bsp_enable_dsi_phy_power(); @@ -59,22 +58,11 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]") }; TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io)); - esp_lcd_panel_dev_config_t lcd_dev_config = { - .bits_per_pixel = 16, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .reset_gpio_num = -1, - }; - TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel)); - TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel)); - TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel)); - // turn on display - TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true)); - esp_lcd_dpi_panel_config_t dpi_config = { .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ, .virtual_channel = 0, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, + .in_color_format = LCD_COLOR_FMT_RGB565, .video_timing = { .h_size = MIPI_DSI_LCD_H_RES, .v_size = MIPI_DSI_LCD_V_RES, @@ -86,8 +74,22 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]") .vsync_front_porch = MIPI_DSI_LCD_VFP, }, }; - TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel)); + ek79007_vendor_config_t vendor_config = { + .mipi_config = { + .dsi_bus = mipi_dsi_bus, + .dpi_config = &dpi_config, + }, + }; + esp_lcd_panel_dev_config_t lcd_dev_config = { + .reset_gpio_num = -1, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, + .bits_per_pixel = 16, + .vendor_config = &vendor_config, + }; + TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel)); + TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel)); TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel)); + uint32_t callback_calls = 0; esp_lcd_dpi_panel_event_callbacks_t cbs = { .on_refresh_done = test_rgb_panel_count_in_callback, @@ -110,7 +112,6 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]") TEST_ASSERT(callback_calls > 2); TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel)); - TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel)); TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io)); TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus)); free(img); diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c index a31d26e01fdd..aa5579c0d349 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c @@ -15,14 +15,13 @@ #include "esp_random.h" #include "esp_attr.h" #include "test_mipi_dsi_board.h" -#include "esp_lcd_ili9881c.h" +#include "esp_lcd_ek79007.h" -TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]") +TEST_CASE("MIPI DSI Pattern Generator (EK79007)", "[mipi_dsi]") { esp_lcd_dsi_bus_handle_t mipi_dsi_bus; esp_lcd_panel_io_handle_t mipi_dbi_io; esp_lcd_panel_handle_t mipi_dpi_panel; - esp_lcd_panel_handle_t ili9881c_ctrl_panel; test_bsp_enable_dsi_phy_power(); @@ -41,22 +40,11 @@ TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]") }; TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io)); - esp_lcd_panel_dev_config_t lcd_dev_config = { - .bits_per_pixel = 16, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .reset_gpio_num = -1, - }; - TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel)); - TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel)); - TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel)); - // turn on display - TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true)); - esp_lcd_dpi_panel_config_t dpi_config = { .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ, .virtual_channel = 0, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, + .in_color_format = LCD_COLOR_FMT_RGB888, .video_timing = { .h_size = MIPI_DSI_LCD_H_RES, .v_size = MIPI_DSI_LCD_V_RES, @@ -68,7 +56,20 @@ TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]") .vsync_front_porch = MIPI_DSI_LCD_VFP, }, }; - TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel)); + ek79007_vendor_config_t vendor_config = { + .mipi_config = { + .dsi_bus = mipi_dsi_bus, + .dpi_config = &dpi_config, + }, + }; + esp_lcd_panel_dev_config_t lcd_dev_config = { + .reset_gpio_num = -1, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, + .bits_per_pixel = 24, + .vendor_config = &vendor_config, + }; + TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel)); + TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel)); TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel)); TEST_ESP_OK(esp_lcd_dpi_panel_set_pattern(mipi_dpi_panel, MIPI_DSI_PATTERN_BAR_HORIZONTAL)); @@ -80,7 +81,6 @@ TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]") TEST_ESP_OK(esp_lcd_dpi_panel_set_pattern(mipi_dpi_panel, MIPI_DSI_PATTERN_NONE)); TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel)); - TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel)); TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io)); TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus)); @@ -89,12 +89,11 @@ TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]") #define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t)) -TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]") +TEST_CASE("MIPI DSI draw bitmap (EK79007)", "[mipi_dsi]") { esp_lcd_dsi_bus_handle_t mipi_dsi_bus; esp_lcd_panel_io_handle_t mipi_dbi_io; esp_lcd_panel_handle_t mipi_dpi_panel; - esp_lcd_panel_handle_t ili9881c_ctrl_panel; test_bsp_enable_dsi_phy_power(); @@ -116,22 +115,11 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]") }; TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io)); - esp_lcd_panel_dev_config_t lcd_dev_config = { - .bits_per_pixel = 16, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .reset_gpio_num = -1, - }; - TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel)); - TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel)); - TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel)); - // turn on display - TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true)); - esp_lcd_dpi_panel_config_t dpi_config = { .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ, .virtual_channel = 0, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, + .in_color_format = LCD_COLOR_FMT_RGB565, .video_timing = { .h_size = MIPI_DSI_LCD_H_RES, .v_size = MIPI_DSI_LCD_V_RES, @@ -143,7 +131,20 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]") .vsync_front_porch = MIPI_DSI_LCD_VFP, }, }; - TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel)); + ek79007_vendor_config_t vendor_config = { + .mipi_config = { + .dsi_bus = mipi_dsi_bus, + .dpi_config = &dpi_config, + }, + }; + esp_lcd_panel_dev_config_t lcd_dev_config = { + .reset_gpio_num = -1, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, + .bits_per_pixel = 16, + .vendor_config = &vendor_config, + }; + TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel)); + TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel)); TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel)); for (int i = 0; i < 100; i++) { @@ -156,7 +157,6 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]") } TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel)); - TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel)); TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io)); TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus)); free(img); @@ -164,12 +164,11 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]") test_bsp_disable_dsi_phy_power(); } -TEST_CASE("MIPI DSI with multiple frame buffers (ILI9881C)", "[mipi_dsi]") +TEST_CASE("MIPI DSI with multiple frame buffers (EK79007)", "[mipi_dsi]") { esp_lcd_dsi_bus_handle_t mipi_dsi_bus; esp_lcd_panel_io_handle_t mipi_dbi_io; esp_lcd_panel_handle_t mipi_dpi_panel; - esp_lcd_panel_handle_t ili9881c_ctrl_panel; test_bsp_enable_dsi_phy_power(); @@ -188,22 +187,11 @@ TEST_CASE("MIPI DSI with multiple frame buffers (ILI9881C)", "[mipi_dsi]") }; TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io)); - esp_lcd_panel_dev_config_t lcd_dev_config = { - .bits_per_pixel = 16, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .reset_gpio_num = -1, - }; - TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel)); - TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel)); - TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel)); - // turn on display - TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true)); - esp_lcd_dpi_panel_config_t dpi_config = { .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ, .virtual_channel = 0, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, + .in_color_format = LCD_COLOR_FMT_RGB565, .num_fbs = 3, // the driver will allocate and maintain 3 frame buffers .video_timing = { .h_size = MIPI_DSI_LCD_H_RES, @@ -216,7 +204,21 @@ TEST_CASE("MIPI DSI with multiple frame buffers (ILI9881C)", "[mipi_dsi]") .vsync_front_porch = MIPI_DSI_LCD_VFP, }, }; - TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel)); + + ek79007_vendor_config_t vendor_config = { + .mipi_config = { + .dsi_bus = mipi_dsi_bus, + .dpi_config = &dpi_config, + }, + }; + esp_lcd_panel_dev_config_t lcd_dev_config = { + .reset_gpio_num = -1, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, + .bits_per_pixel = 16, + .vendor_config = &vendor_config, + }; + TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel)); + TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel)); TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel)); uint16_t *fbs[3]; @@ -236,9 +238,106 @@ TEST_CASE("MIPI DSI with multiple frame buffers (ILI9881C)", "[mipi_dsi]") } TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel)); - TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel)); TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io)); TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus)); test_bsp_disable_dsi_phy_power(); } + +TEST_CASE("MIPI DSI draw YUV422 (EK79007)", "[mipi_dsi]") +{ + esp_lcd_dsi_bus_handle_t mipi_dsi_bus; + esp_lcd_panel_io_handle_t mipi_dbi_io; + esp_lcd_panel_handle_t mipi_dpi_panel; + + test_bsp_enable_dsi_phy_power(); + + uint8_t *img = malloc(TEST_IMG_SIZE); + TEST_ASSERT_NOT_NULL(img); + + esp_lcd_dsi_bus_config_t bus_config = { + .bus_id = 0, + .num_data_lanes = 2, + .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, + .lane_bit_rate_mbps = 1000, // 1000 Mbps + }; + TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); + + esp_lcd_dbi_io_config_t dbi_config = { + .virtual_channel = 0, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + }; + TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io)); + + esp_lcd_dpi_panel_config_t dpi_config = { + .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, + .dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ, + .virtual_channel = 0, + + // YUV422 -> RGB888 + .in_color_format = LCD_COLOR_FMT_YUV422, + .out_color_format = LCD_COLOR_FMT_RGB888, + + .video_timing = { + .h_size = MIPI_DSI_LCD_H_RES, + .v_size = MIPI_DSI_LCD_V_RES, + .hsync_back_porch = MIPI_DSI_LCD_HBP, + .hsync_pulse_width = MIPI_DSI_LCD_HSYNC, + .hsync_front_porch = MIPI_DSI_LCD_HFP, + .vsync_back_porch = MIPI_DSI_LCD_VBP, + .vsync_pulse_width = MIPI_DSI_LCD_VSYNC, + .vsync_front_porch = MIPI_DSI_LCD_VFP, + }, + + .flags = { + .use_dma2d = true, + } + }; + ek79007_vendor_config_t vendor_config = { + .mipi_config = { + .dsi_bus = mipi_dsi_bus, + .dpi_config = &dpi_config, + }, + }; + esp_lcd_panel_dev_config_t lcd_dev_config = { + .reset_gpio_num = -1, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, + .bits_per_pixel = 24, + .vendor_config = &vendor_config, + }; + TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel)); + + // Set color conversion configuration + esp_lcd_color_conv_config_t convert_config = { + .in_color_range = LCD_COLOR_RANGE_FULL, + .out_color_range = LCD_COLOR_RANGE_FULL, + .spec.yuv = { + .conv_std = LCD_YUV_CONV_STD_BT601, + .yuv422.in_pack_order = LCD_YUV422_PACK_ORDER_YUYV, + } + }; + TEST_ESP_OK(esp_lcd_dpi_panel_set_color_conversion(mipi_dpi_panel, &convert_config)); + + TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel)); + TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel)); + + // YUV images are embedded in the firmware binary + extern const uint8_t image_hello_yuv_start[] asm("_binary_hello_yuv_start"); + extern const uint8_t image_world_yuv_start[] asm("_binary_world_yuv_start"); + + printf("Draw YUV images\r\n"); + for (int i = 0; i < 4; i++) { + TEST_ESP_OK(esp_lcd_panel_draw_bitmap(mipi_dpi_panel, 0, 0, 320, 320, image_hello_yuv_start)); + vTaskDelay(pdMS_TO_TICKS(1000)); + TEST_ESP_OK(esp_lcd_panel_draw_bitmap(mipi_dpi_panel, 0, 0, 320, 320, image_world_yuv_start)); + vTaskDelay(pdMS_TO_TICKS(1000)); + } + + TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel)); + TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io)); + TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus)); + free(img); + + test_bsp_disable_dsi_phy_power(); +} diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/README.md b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/README.md new file mode 100644 index 000000000000..5822bbd7732d --- /dev/null +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/README.md @@ -0,0 +1,13 @@ +# How to generate the YUV image from the PNG image + +```bash +ffmpeg -i hello.png -pix_fmt yuyv422 hello.yuv +``` + +## Supported YUV422 packing order + +| NAME | NB_COMPONENTS | BITS_PER_PIXEL | BIT_DEPTHS | +|----------|----------------|----------------|------------| +| yuyv422 | 3 | 16 | 8-8-8 | +| yvyu422 | 3 | 16 | 8-8-8 | +| uyvy422 | 3 | 16 | 8-8-8 | diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/hello.png b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/hello.png new file mode 100644 index 000000000000..b1172c410a8e Binary files /dev/null and b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/hello.png differ diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/hello.yuv b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/hello.yuv new file mode 100644 index 000000000000..5dd8b5fd94ea --- /dev/null +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/hello.yuv @@ -0,0 +1 @@ +ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ikPlhffgiilnlmQii?ii?ii?iiAiiAii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?qKUQpiBii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?illumcqgfsffvggxgmfqpgo]miAii?ii?iiAiiBihAii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@ipBRTSoJii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ikts}jogioiinjjnknogirhfwhi|gimijfqiBii?ii?iiAiiCjjCklCllCllClkCkkBji@ii?ii@jiAii?ii?ii@jGSUSQii?ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?imptopdfpefpffpfepfgohjnklnlhpigygjkfmshiliEii?ii?ii?ii?ii?ii?ii?ii?kkBji@ii@ii@ii?ii@jJTUURii?ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iirtqlcogfoffoffpffpfepffqffofinllnpiqinygiilhxvupqruxpaxmJii?iiGojUiiAii?ii@jJSUTRii?ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iettsygoffoffoffoffoffoffoffpffpffqffoggnjlnoung|bĚXHţ=̕>Jfczmd|sii@iiAii@jJSUURii?ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ifs{tsrpbgoffoffoffoffoffoffoffoffoffpffqefqfepfbt^]xVbgCB@ž>əBlvqiYiiAii@jGSUTPii?ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ifststxqegoffoffoffoffoffoffoffoffoffoffoffoffpffohioen_@AABARtqhiAii@ipBRRSnJii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ifsutsrsdogfoffoffoffoffoffoffoffoffoffoffoffoffofgq_zS@@@@@\tvuq_ji@ii?oIROniBii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ifstssszdogfoffoffoffoffoffoffoffoffoffoffoffoffogcnoɝH@@@@@`ttlkKii?ii?ii?ii?ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?igsir…ssspefoffoffoffoffoffoffoffoffoffoffoffofgofgd?@@@@@etsrdniFii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?igsir…ss~qgfoffoffoffoffoffoffoffoffoffoffoffofiqa˂U@@@@@Aku~t]Frvij@ji@ii@ii?ii?ii?ij@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?igserąssrreoffoffoffoffoffoffoffoffoffoffoffni_nwɬG£A@@@@B}s[KDAžFiWikAii?ii?ii?ii?ii?jj@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?igscrąsss~hoffoffoffoffoffoffoffoffoffoffofhoax\@@@@@@AOC=Ĝ?@@ŝ\oiCki@ii?ih@ii?wUii?ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?igrdryŃsssrpfeoffoffoffoffoffoffoffoffoffohdokʣHĥ@@@@@@@<Û?A@@A@ufikAii?ii@irDgizmLij@ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iqAPbɉsiHii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?qHYkەdii?ii?ii?ii?ii?ii?iqAPbɉsiHii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ifueqtǀsss~qheoffoffoffoffoffoffoffoffofgpdl`@A@@@@@@AA@@@@ARviGki@ii@ixHdhoexiHii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?Wn}riBii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iFeχvsbii?ii?ii?ii?Wn}siBii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?igmerwƂsssrpgoefoffoffoffoffoffoffoffofcnmʙJ@@@@@@@@@@@@@@A@Ɯrdij@ii@iyIcj^l}w^niCii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?t{ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iT؝i[ii?ii?ii?ii?t{ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii_erttsss}ioefoffoffoffoffoffoffogfpcl`?@@@@@@@@@@@@@@@AZniBii@iL`l`l^miNii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?؃{뉽tii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?i[뀽iTii?ii?ii?ii?؃{뉽tii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iibfqj{ssssppffoffoffoffoffoffoffofcnlʗJ@@@@@@@@@@@@@@@@ACiWii@iL`l`maliNii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?irB뎠mii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?rb뀡iMii?ii?ii?irB뎡mii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ihbfqk{ssss|qjeogfoffoffoffoffofgpcma@@@@@@@@@@@@@@@@@@AŜpxii?iR^k`leiji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iH딄fii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?h뀆iGii?ii?ii?iH딆gii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ihbgqfyssssrpfoffoffoffoffoffogcnlʘJ@@@@@@@@@@@@@@@@@@AGoiEiR_l_lnVii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iOl`ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?omi@ii?ii?ii?iOm`ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iiagqgrrssss{joegoffoffoffofhodl`@@@@@@@@@@@@@@@@@@@A@j^iS_kcjziIii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iVϟiYii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ćvyii?ii?ii?ii?iVПiYii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ihcgqgqr„ssssqpegoffoffoffoiaok˚J@@@@@@@@@@@@@@@@@@@@@žnyx\_lpckiAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?i]뀳iRii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?߂}늵rii?ii?ii?ii?i]뀵iRii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ijVgrhrrsssszqjeogfoffofjp_x]@žA@@@@@@@@@@@@@@@@@@@@R|^`lnPij@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?zd뀘iKii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iyD됚kii?ii?ii?ii?yd뀚iKii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ilOgrjkr|ąssssrrdogfofgnh^nuɨHģ@@@@@@@@@@@@@@@@@@@@@@BnghfmiBji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?k|iDii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iJ~eii?ii?ii?ii?j~iEii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ikQfrjfqxƆssssszipegogera}Y@@@@@@@@@@@@@@@@@@@@@@@@]orWij@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?q}ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iQj^ii?ii?ii?ii?q~ji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ilPfrjeqyŇsssssrpegoehk~ķCàA@@@@@@@@@@@@@@@@@@@@@@@efriFii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ͅxwii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iXɠiWii?ii?ii?ii?̆xwii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ilRfrkbptDžsssss{qicoiˋQ@@@@@@@@@@@@@@@@@@@@@@@@@insjDji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ik@댪pii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?j_뀮iPii?ii?ii?ij@~댮pii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ikNgskdpossssssqjdA@@@@@@@@@@@@@@@@@@@@@@@@@IiLkiAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iF뒏iii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?e뀑iIii?ii?ii?iE둑jii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ftldposssssqHĦ@@@@@@@@@@@@@@@@@@@@@@@@@@@ɚiVji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iMtbii?ii?ivCNtHii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?nIgֆx}ًrwRii?ii?ii?ii?ii?lviCii?ii?ii?iLvcii?ii?ii?ii?ii?ii?ii?ii?ii?xNi͉tҋq[li@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ftldpossssu~U@@@@@@@@@@@@@@@@@@@@@@@@@@@@Ý}zmik@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iTٝi[ii?~W؃{ؐkviCii?ii?ii?ii?ii?ii?ii?ii?ii?ii?{V}kRii?ii?ii?ii?s|ii?ii?ii?ii?iSݜi\ii?ii?ii?ii?ii?ii?ii?inAdݓgii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@ftlfpgwsssr{nA@@@@@@@@@@@@@@AAIPvpQKAƜ@A@@@@Aj}ikAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iZ뀾iTuU㒖iii?ii?ii?ii?ii?ii?ii?ii?ii?oRvii@ii?ii?ii?Ԅzuii?ii?ii?ii?iZiUii?ii?ii?ii?ii?ii?ii@h뀵iSii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?dtkgocsrsrsL?@@@@@@@@@@@@@AA}Ua\YVR[NL\PTZX\WhH@@@@@A`ikAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?qa뀢U߂}iJii?ii?ii?ii?ii?ii?ii?iF܃|뀝iLii?ii?ioA덦oii?ii?ii?ii?o`뀦iNii?ii?ii?ii?ii?ii?v[댯qii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?i}Ivnmfpcsrsv~[>ÝA@@@@@@@@@@@@AC~ScN_DF_IK]MN\LI^HEaETYcG@@@@AVojCii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?h뀩ntaii?ii?ii?ii?ii?ii?ii?jyXхyםiZii?ii?iH듊hii?ii?ii?ii?h뀊iHii?ii?ii?ii?ii?iGނ|iFii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iSjmepdqq„ueC¡@@@@@@@AAA@@@@?PgJ`CL\PQ[PK^HH^JN[PQ[OI_EPR@@@@AOwiHji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?o닰qii?ii?ii?ii?ii?ii?iK뀬jPii?{drbii?ii?iNpaii?ii?ii?ii?npiAii?ii?ii?ii?ii?fXoHքzšiVii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?i\ikfohjssƀnH?@@@@@@@Ý@ś@ś@Ü@@@@DV^CN[PN]IDaFUY_cXXJ_DD_KP[RFYA@@@AHiNki@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?Çv{ii?ii?ii?ii?ii?ii?i닱qii?ii?i\딂fii?ii?iU՞iZii?ii?ii?ii?uzii?ii?ii?ii?ii?iG~璑iii?ii?etbii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?idigbr_cm}ƝS?@@@@@@@œCFFE@Þ@@@L_C^RN]JG\WiSyJIQudYQD`GIXA@@@ABiSkiAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ނ|wiCii?ii?ii?ii?iwC~ʠjXii?ii?iZ둒jii?ii?i\뀺iTii?ii?ii?ii?ۃ|뉺tii?ii?ii?ii?ii?r^뀕iJii?ii?iZ돝lii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ihghllrƂU=A@@@@@AGRkVYZYYYdUpG@@@JlD`IH^LeQ?ƞ@œ@Ý?ĚH`X[tKA@@@AAiVkiAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ixC~wQtP뀄iFii?ii?ii?ii?iW}iDii?ii?i\뒌hii?ii?uc뀞iLii?ii?ii?iuC돞lii?ii?ii?ii?ii?u뉻tii?ii?ii?iU늷sii?ii?ii?ii?ii?ii?Oii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?izoWP@A@@@@@@JW]HH^KM\LL\LK]L?\pA@@EbZPUWxAžAA@A@C@A@@@@@͘i[liAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iJ唈fii?ii?p뀎iIii?ii?ii?ii?m댮qii?ii?ii?j`}dii?ii?i뀂iFii?ii?ii?iI딂fii?ii?ii?ii?iKܛq^ii?ii?ii?iTyii?ii?ii?ii?ii?tV뉻tii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?izo@@@@@@@@@HX\JL\MM\LL\LL\LL\NHZgC@@@žHE@@@@@@@@@@@@@@̙iZliAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iQiHii?ii?}d뀋iHii?ii?ii?i{D~saii?ii?ii?enaii?ii?pki@ii?ii?ii?iPk_ii?ii?ii?ii?yb뀖iJii?ii?ij@u|ii?ii?ii?ii?sS~wii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?izo@@@@@@@@ChXNK]LL\MM\LL]KK]KL\NG[fC@@@@@@@@@@@@@@@@@@@̙iZliAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iX늵rii?ii?ii?m`뀂iFii?ii?ii?iT뀲iRii?ii?ii?o՞iZii?ii?Ȇwxii?ii?ii?ii?iW͟iXii?ii?ii?ii?t{ji@ii?ii?iM~ii?ii?ii?W~¡nWii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?izo@@@@@@@AžMhL]KL\NN]JG]WsQ~}Q~bW\fOA@@@@@@@@@@@@@@@@@@@̙iZliAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?j_s`ii?ii?ii?j_wiCii?ii?ii?ycziDii?ii?ii?Ѕy뀦iNii?ii@~닲rii?ii?ii?ii?i^뀲iRii?ii?ii?izD됚kii?ii?ii?iYkj@yLk錯qji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?izo@@@@@@@BjYKL]LP]JNWsGCBDB@@@@@@@@@@@@@@@@@@BA̘iZliAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?e뀯iQii?ii?ii?rb~ii@ii?ii?ii?rxii?ii?ii?iHyiCii?i}D됖kii?ii?ii?ii?}d뀖iJii?ii?ii?iRޜk]ii?ii?ii?i^~wiFii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?izo@@@@@@@J|H^MM\PE\aG@Ŝ@@@ě@@@@@@@@@@@@@@@@@AB=AʘiYliAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?l뀀iEii?ii?ii?eyii?ii?ii?irB~됙kii?ii?ii?iXvii?ii?iK{dii?ii?ii?ii?k{iDii?ii?ii?ua뀰iQii?ii?ii?i^yiJii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?izo@@@@@@@ƜTPM\NM^EhQ@ĜA@@AA@@@@@@@@@BA@@@@A?>WDДhYliAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?s|ii?ii?ii?ii?j뉹sii?ii?ii?iNraii?ii?ii?nybii?ii?iRi]ii?ii?ii?ii?r}ii?ii?ii?ii?p뀁iEii?ii?ii?iX፳oiFii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iyn@@@@@@@ǜVFO\LH\fEÚA@@@@@@@@@@@@@@CA@@@@@It{izuiSii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?Ԅzuii?ii?ii?ii?o됛lii?ii?ii?iYϟiYii?ii?iF뀤iNii?ii?iYơiWii?ii?ii?ii?υywii?ii?ii?ii?׃{zii?ii?ii?ii?iG~uWli@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?i}m@@@@@@@ÝLhH_H^Q@A@@@@@@@@@@@@@AAB@@@A?yxnoSstWqpTtsNliAii?ii?ii?ii?ii?ii?ii?ii?ii?ioA덦oii?ii?ii?ii?Çv~eii?ii?ii?vc뀭iPii?ii?dvji@ii?ii?l`뀪iOii?ii?ii?il@댪pii?ii?ii?i~E댫pii?ii?ii?ii?ii?t`wji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ifBA@@@@@BrSrD@@@@@@@@@@@@@@@BAAA@@?UvuXyx[ww[xx[{|XsmLii?ii?ii?ii?ii?ii?ii?ii?ii?iG듋hii?ii?ii?ii?}i]ii?ii?ii?l뀊iHii?iJ~ʟmYii?ii?ii?f뀏iIii?ii?ii?iF뒏iii?ii?ii?iO듈gii?ii?ii?ii?ii?pa늵rii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ibBA@@@@@A@Ĝ@@@@@@@@@@@@@@@AAAA@@@@xmww[vvYvvYvvYvwYyrUji@ii?ii?ii?ii?ii?ii?ii?ii?iNpaii?ii?ii?i{DáiVii?ii?ii?ćv~li@ixCtxpiAii?ii?ii?mtiBii?ii?ii?iMtbii?ii?ii?iYk_ii?ii?ii?ii?ii?g뎡mii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iVDÚ@@@@@@@@@@@@@@@@@@@@@@@AABA@@@cxv[vvZvvYvvYvvYvvZzvWviCii?ii?ii?ii?ii?ii?ii?ii?iU՞iZii?ii?ii?iK뀦iNii?ii?ik@~w~PukQii?ii?ii?ii?t{ii?ii?ii?ii?iTڝi[ii?ii?ii?rbơiVii?ii?ii?ii?ii?l뒎iii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iOEęA@@@@@@@@@@@@@@@@@@@@@@BAA@@@EpavuZuvYwvZvvYvvYvvZxuYsiIii?ii?ii?ii?ii?ii?ii?ii?i\뀺iSii?ii?ii?iR뀇iGii?ii?iEܕeii?ii?ii?ii?ii?׃{눾uii?ii?ii?ii?i[뀾iUii?ii?ii?h뀫iPii?ii?ii?ii?ii?t{dii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?imBGƖA@@@@@@@@@@@@@@@@@ĝ@ś@@@@AA@Ÿ@@@h]_]swYwvYvvYvvYvvZviLii?ii?ii?ii?ii?ii?ii?ii?vc뀞iLii?ii?ii?iY~li@ii?ii?iKޑjli@ii?ii?ii?ii?irB뎢nii?ii?ii?ii?ra뀢iNii?ii?ii?n뀔iJii?ii?ii?ii?ii?ނ|j^ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?OÑCG@@@@@@@AAB@@@@@KweXewLA@@AAAž@@Fe``_q\svYvvYvvYvvYxiLii?ii?ii?ii?ii?ii?ii?ii?j뀂iFii?ii?ii?o`wii?ii?ii?iQØbmi@ii?ii?ii?ii?ii?iH듇gii?ii?ii?ii?h뀇iGii?ii?ii?t~iDii?ii?ii?ii?iE¢iVii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?[CW?@@@@@AAABAž@@@Bd[KAcAJYa@CCCB@@@[]`_`_x[vwYvvYvvYviLii?ii?ii?ii?ii?ii?ii?ii?p~ki@ii?ii?ii?g덩oii?ii?ii?iVxcoKii?ii?ii?ii?ii?ii?ii?iOn`ii?ii?ii?ii?oniAii?ii?ii?ӄzki@ii?ii?ii?ii?iO뀝iLii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@zuvHj>@@@@@AAAAA@@@IsBgX^v^~^sKU;:=CCB@r}_s_y{__`z\swYvvYvvZwiMii?ii?ii?ii?ii?ii?ii?ii?ʆwxii?ii?ii?ii?o듊gii?ii?ii?iZi]ii?ii?ii?ii?ii?ii?ii?ii?ii?iVҞiYii?ii?ii?ii?Çvyii?ii?ii?ii?}}ii?ii?ii?ii?ii?i[xiCii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ij@ieNwtF@@@@@@AAAAA@AǜSUeomsr^ulb|lq}dR=9Þ=?q^cN^US^a^_^uvYvvYvvYviLii?ii?ii?ii?ii?ii?ii?ij@~닱qii?ii?ii?ii?Çvn`ii?ii?ii?i\ڝi[ii?ii?ii?ii?ii?ii?ii?ii?ii?w`뀷iSii?ii?ii?ii?߂}늷sii?ii?ii?ii?{ii?ii?ii?ii?ii?fzii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ij@iVZuOŧ@@@@@@AAAAA@AțfWwSwwYvyXupVonRp}Zmi^OGn\^]]]^^VX^__sZxvYyvYpiGii?ii?ii?ii?ii?ii?ii?iE둕jii?ii?ii?ii?߂}֞iZii?ii?ii?i^ԞiZii?ii?ii?ii?ii?ii?ii?ii?iwCۃ{뀛iLii?ii?ii?ivC됛lii?ii?ii?ipAyii?ii?ii?ii?ii?u덧oii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@ivDsv~T@@@@@@@@žBAA@@u^}zu[vvZvvZwx[xy[xvZssWssSnvUnr}k]`X][[^\[^c^`oZxxY~vUii?ii?ii?ii?ii?ii?ii?ii?iLydii?ii?ii?ivC뀿iUii?ii?ii?k`ӞiYii?ii?ii?ii?ii?ii?ii?ii?s]뀀iEii?ii?ii?iI땀eii?ii?ii?iwCzii?ii?ii?ii?i~Dr`ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?jiAy}ub@@@@@@@@@AA@?t]|vYvvYvvYvvYvvYvvZwwZwx[xy[pY^^_jU^\[^[Y^\]`qZxzYurLii?ii?ii?ii?ii?ii?ii?ii?iSi]ii?ii?ii?iH뀱iQii?ii?ii?j`؝i[ii?ii?ii?ii?ii?ii?ii?ioAυyli@ii?ii?ii?iWl`ii?ii?ii?ipA{ii?ii?ii?ii?iU뀳iRii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@iiJ|ytr?@@@@@@@@AAA@Ɯr\{vYvvYvvYvvYvvYvvYvvYvvYwuY}\```[_Z[^[Y^\]`|\zvVmiAhi@ii?ii?ii?ii?ii?ii?ii?iYġiVii?ii?ii?iL뀨iOii?ii?ii?kj_ii?ii?ii?ii?ii?ii?ii?w]΅y|ii?ii?ii?ii?mޜi\ii?ii?ii?iMii@ii?ii?ii?jziDii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@iq\usrE@@@@@@@@AAAAƝUhox\vvZvvZwwZwvZvvZvvYvvYwuY}\```u_R^^[Z^\]`\tnLii?ii?ii?ii?ii?ii?ii?ii?ii?n`뀨iOii?ii?ii?iO뀳iRii?ii?irB߂}eii?ii?ii?ii?ii?ii?iGނ|~s~ii?ii?ii?iFi^ii?ii?ii?e뀁iEii?ii?i}D}늷sii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@i~ptssP@@@@@@@@AAAAEMyi}ppfyuUrrUrsVuuXwvZxx[yv[~]```_Y^TS^e_`qVoiBii@ii?ii?ii?ii?ii?ii?ii?ii?g뀍iHii?ii?ii?iQٝk\ii?ii?u[댬pii?ii?ii?ii?ii?ii@kꐖjs~iDii?ii?h~eii?ii?iJ}뀶iSii?ii?z`ۛp]ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@i~tst[@@@@@@@@AAA@@UVFiEZb\mq}}_qoRrnTyY_`aa`__^{iHii?hi@ii?ii?ii?ii?ii?ii?ii?ii?nriBii?ii?ii?iPvnGtMۃ|~iGii?ii?ii?ij@b뀢iNqӘbqnCZzqInHt뉺spGzR~iHii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ruuvc@@@@@@@@AAA@@CE>=CLX`p~rh^Z\]`_~Tji@ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?u{ii?ii?ii?ii?iM銶rxKlqB{Nm댮qii?n|ۃ{닳rii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?zsŽsÐofA@@@@@@@AAA@@@ƜAșA›B@=;9ANZdp~uj]WzjDij?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ۃ{뉼tii?ii?ii?ii?iF늷sЅy뀧iOii?g䕇e~Y뀾jUii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?iqDw}x{|vrPA@@@@@@@AAA@@@A@@ABBCA>;8əAAA@@@@@@@@@AB@ĝAzpliBjjAii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@i~DSRQii?hi@ii?ij@ki@iLcBǚ?AAA@@@@@AAA?ǛHnxqiDikAii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@}MPiEii?ii?ii?ii?ij@ji@iqDj}H?ƛ?Ü@@@@@@@?ś?Mzoii?ik@ii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii@ii?ii?ij?ii?ii?ii?ii?ii?ij@kiAii?zeWJD@@@@AEK]mYii?jjAii@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ij@ij@ii@ii?ii?ii?ii?ii?ii?ii@ij@ii?imBf]CA@@Id{]ii?ii@ji@ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?ii?jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@jj@ \ No newline at end of file diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/world.png b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/world.png new file mode 100644 index 000000000000..3a111fac8f0e Binary files /dev/null and b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/world.png differ diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/world.yuv b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/world.yuv new file mode 100644 index 000000000000..ad4535676f5f --- /dev/null +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/resources/pictures/world.yuv @@ -0,0 +1 @@ +WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKXWLWWKW_LtT[__`__[tT_WLWWKWXLXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXYKXWLWXKqT\^_`````_^\qTXWKWXLYXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKVWLWgNZ_^^_`````_^^_YiWMWXKYXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXLWWL^zPY^__```````_`___Zu[OWXKYWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLWWLW`Qqycfga_`_````````_`^[qWNWXLXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWLW`Ofoqc|\vnmZmpo\spd``a`_```__``___YjWNWYKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWYLdvq_|`ynucvmwcxnyarn~f_duigc___``___`__vW[WLXXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKWWKZiV{bwnubunvbvnvbvnwaunypkdjuls^sor\qpril`adf}hd`_____`RWWKXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW]Omg|itbunvbvnvbvnvbvnvbvnv`tor^rouawnwbwnwcwnvawngo{ks^sos_sot_tos_uo{hcaa`_\hXMWXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLasq`{aunvbvnvbvnvbvnvbvnvbvnvbvnwbvnvbvnvbvnvbvnvbvnvaunvbvnvbvnvbvnvbvnvbvnvaunu`uoud|nrk~hb_sWXWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXLWcSscylvavnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvavnvavnvbvnvbvnvbvnvbvnvavnvauouavovbvnwbwnunk`^|WPXWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWKdoscyavnvbvovbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvauouaunufma_}YWXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWcSsczlvbunvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnwcxnxdxnwbvnvbvnwcvnsok`_^}WPWXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLWWLarrayavnvbvovbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnt]pooZops`vovbwnubxnd___sXWXKWWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWK`tR`nمiWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXiO~]kЃqWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXXKW\Ordykvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnxifkvlv`ro}wi_``_]gWMXXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWvQj́xbgWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW]Let냖qWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWKZ{mY{avnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnu`soa_gtjla````__TWXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW\ֆWbWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWRwkWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLWXLgj|fubvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnucyo``be_````_Z[WLXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWb뀷W\WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWX[fWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLXbRxbunvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvaunvqk_`__``````_vYOYXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKag뀗WWWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW]͇W`WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWL]wp\ybunvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvatowyibb_```````_iUWXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKmwWQWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWc뀭W[WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWLgk{eubvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvauowim{ctn}{h_````````ZWXLXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKr\WLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKfh뀎WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWXLW_Pqdykubvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvauo{yi````````_^pWNYWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKxzWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKnoWOWWKWWKWWKWWKWWKWWKWWKWWKWWKXWK[mW}aumvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvcvn}{h_````````_[SXXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKހ}낮uWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKs~XWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWLeut`zaunvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnwatnt^poe`````````_tXXYKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWjO냎oWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKÁxyWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLli}gubvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnuhmsja`````````_[WXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWTojWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXK~낤sWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKX]Opc~kubvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvatn~gc_`````````_]iXMWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWZXdWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWlO냅nWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLWiVwbvmubvovbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbuntfmbf_`````````__WQXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW_ćW_WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWUfhWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKYzpZ}aumvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvavn|hbqnk_``````````_\TXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKYe뀥WYWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWZۆWcWWKWWKWWKWWKWWKWWKWWKWWKWWKWWK_rs`zavnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnucznbetsj_``````````_qWWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW`MwZ_TWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKrj뀅WTWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW_뀻W]WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKhltfwaunvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbwntd{ncex{h```````````_ZWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW[Lr~WTWWKWWKWWKWWKWWKWWKWWKWWKWhNcrՁw„m[TWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKpfWNWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKYe뀜WWWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKngyjvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvatodcf````````````]WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKn͂u͂u͂u͂u̓rWWKWWKWWKWWKs͂u͂u͂u͂ǘmWWKWWKWZ鄆nWWKWWKWWKWWKWWKWWKWWK\Vʁz}WUWWKWWKWWKWWKWWKWWKw{WWKWWK[Vr|k`WWKWWKWWKu}WWKWWKWWKWWKWWKWWKWWKWWKWWKp[sހ}ہwzbWWKsj}WRWWKWWKWWKWWKWWKWWKWWKWWKWWKWZMrc}lnktawnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnw`so~g`|kl```````````_]_WLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKӀ{낺wWWKWWKWWKWdN냘qWWKWWKbg|WWKWWKWWKWWKWWKWWKXUۀ}낮uXWKWWKWWKWWKWWKWWKـ|낵vWWKZX݀}~WSWWKWWKЁ{끻wWWKWWKWWKWWKWWKWWKWWKWXKhZ^p_WMWWKWWKWWKWWKWWKWWKWWKWWKWWKWaQsfk~gq`wovbvnvbvnvbvnvbvnvbwnwcwnwcwnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnwatnzwidw]lpb```````````^tWNWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW_M냛rWWKWWKWWKWSxkWWKWWK}lzWQWWKWWKWWKWWKWeNƁy뀦WYWWKWWKWWKWWKWdN냖pWnÓzdgWWKW]L냜rWWKWWKWWKWWKWWKWWKWWKse납tu{WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWgTsglfq`wovbvnvbvnvbvnvbwnu_roq\ppp^uovbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnwatn{vig|h````````````^WPWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW}R|lWWKWWKWWKWY\fWWKWWK}l뀜WXWWKWWKWWKWWKxisjWWKWWKWWKWWKWSvkn낭uWWKW{R}lWWKWWKWWKWWKWWKWWKWT|ρ{낳vWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW}lWubxmel]wovbvnvbvnvavnwatn}tje|huauovbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnwasofba````````````_WRWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWX_fWWKWWKWWKW^·W`WWKWWKcg뀪WZWWKWWKWWKW}Rꂯup]QxgxWWKWWKWWKWWKWY肨s|WWKWW_gWWKWWKWWKWWKWWKWWKq냔pWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW{pYv_rnckzlvbvnvbvnvbxnqdmb_a~eumvbvnvbvnvbvnvbwnvbvnvbvnvbvnvbvnvbvnvbvnvbwnraznb__````````````_WTWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW]цWaWWKWWKWWKWc뀯W[WWKWWKW\뀷W\WWKWWKWWKxjWSWWKWpPdWNWWKWWKWWKW^\WLW]҆WaWWKWWKWWKWWKWWKXZ낹wz\RaV߀~ukWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWxs\w`sodfsawovbvnwasoywi_`_qxkuavnvbvnvbvnu_rovbwnvbvnvbvnvbvnvbvnvbvnwbunvqk```````````````_WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWc뀲W\WWKWWKWWKli뀏WUWWKWWKW\Luكr~뀱W[WWKWWKWaMڀ}냉nWWKWWKWWKЀ{뀓WVWWKWWKWWKXd~ƒn؀|\WLWb뀳W\WWKWWKWWKWWKWWKrWTWWKWWKzkZeWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWvw]wbun}{hbt_tovbwntbync```{|ht`wovbvnvavnximvatovbvnvbvnvbvnvbvnvbvnt^rod````````````````WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKfh뀓WVWWKWWKWWKopWPWWKWWKWWKWWKWXK뀩WZWWKWWKW]뀴W\WWKWWKWWKw뀯W[WWKWWKWWKmia[WWKsj|WWKeh뀓WVWWKWWKWWKWWKWyQ鄀lWWKWWKWWKWaʇW`WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWwv]vbwnsqk`pzkt_soxvj````~gr`wovbvnvbwneoxkubvnvbvnvbvnvavntawnzmka````````````````WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKnsWPWWKWWKWWKt~XWLWWKWWKWWKWWKW`M뀠WXWWKWWKo}`WMWWKWWKWWKvˇW`WWKWWKWWKoޅyiWWKWWKWc낥sWWKmtWQWWKWWKWWKWWKad뀡WYWWKWWKWWKWc뀪WZWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWvv]vbwnshmabhzmc````er`wovbwntc{nacwaunvbvnvbvnvbvn~pkb_````````````````WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKsZWLWWKWWKWWKʁzyWWKWWKWWKWWKWWKWkO뀗WWWWKWjO~냋nWWKWWKWWKX]ۆWcWWKWWKWWKu~kWOWWKWWKW]ކ_eWWKsZWLWWKWWKWWKWWKwyXWLWWKWWKWWKgh뀋WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWvv]vbvnwaunf`a`````cybunvbwnsc|n_`jtlwbvnvavnvgm```````````````````WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKāyyWWKWWKWWKWZL낦sWWKWWKWWKWWKWWKWS뀍WUWWKW\ՆYbWWKWWKWWKpWdWWKWWKWqṔz끻wWWKWWKWWKW{R{pWPWWKÁyzWWKWWKWWKWWKWSojWWKWWKWWKWWKnlWOWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWvv]vbvnvbwnud{nbae````afrmwcwnsc|n_`gs`wovaunwwi_``````````````````WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXK~낪tWWKWWKWWKWtQ냇nWWKWWKWWKWWKWWKWWyWQWWKjh뀎WUWWKWWKWWḰzZfXiO}_Ԁ{냜rWWKWWKWWKWWKfςt]YWWKWXK~낪tWWKWWKWWKWWKW`뀶W\WWKWWKWWKWWKs~WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWvv]vbvnvbvnuauoyf}m|g{mwml````_mtkwcxnsc|n_`a~eunwatnxg_``````````````````WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWnO냋nWWKWWKWWKWVhhWWKWWKWWKWWKWWKW\aWMWWKu}YWLWWKWWKWWK~~lWWKWWKWWKWWKWWKWWKWWKWWKWmO냋nWWKWWKWWKWWKmmWOWWKWWKWWKWWKƁyxWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWwv]vbvnvbvnvbvnt_ros^soue~ma````et`toue}n```jplzcunyg_``````````````````WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWUkiWWKWWKWWKW\݆WcWWKWWKWWKWWKWWKWa}WWKWdN남tWWKWWKWWKWWK~`gWWKWWKWWKWWKWWKWWKWWKWWKWUkiWWKWWKWWKWWKˁz끼wWWKWWKWWKWWKWYL~낢sWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWvw]vbvnvbvnvbvnvbwnwcxntema`````}hn^woa``yzhp]rpu~g_``````````````````WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWZWcWWKWWKWWKWa뀽W]WWKWWKWWKWWKWWKagyWWKWYrjWWKWWKWWKWWKȁy~kӆWaWWKWWKWWKWWKWWKWWKWWKWWKWZWcWWKWWKWWKW}R냅nWWKWWKWWKWWKWrP넂mWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWxs\ubvnvbvnvbvnvbvnw`so}xh`````_a{h``_bsje_`````````````````_WUWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW`W^WWKWWKWWK_f뀞WXWWKWWKWWKWWKWWKn낪tWWKWbЇWaWWKWWKWWKWWKzk~k|ZRWb뀴W\WWKWWKWWKWWKWWKWWKWWKWWKW`W^WWKWWKWWKW[ZdWWKWWKWWKWWKWVdhWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWzoYtbwnvbvnvbvnvbvnsfmb_`````_`_``_ba``````````````````_WTWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWK[e뀡WYWWKWWKWWK}l~WRWWKWWKWWKWWKWWKv냏pWWKoj뀢WYWWKWWKWWKWWKWcN~ƇX_WWKWWKag뀕WVWWKWWKWWKWWKWWKWWKWWKWWK[e뀡WYWWKWWKWWKYd뀮W[WWKWWKWWKWWKW[؆WbWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW~mWubxnvbvnvbvnu_sog_```````````a____````````````````_WRWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKwk뀂WSWWKWWKWWKr`WMWWKWWKWWKWWKWXK܀}hhWWKrzWRWWKWWKWWKWWKW_M뀭W[WWKWWKmvWQWWKWWKWWKWWKWWKWWKWWKWWKwk뀂WSWWKWWKWWKm뀃WSWWKWWKWWKWWKWa뀹W]WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWjTtcymubvnvauntfma_```````````f__ba_```````````````^WPWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKqcWNWWKWWKWWKw{WWKWWKWWKWWKWWKWtQ҆WaWWḰz~ZWLWWKWWKWWKWWKWxQ뀗WWWWKWWKrZWLWWKWWKWWKWWKWWKWWKWWKWWKqcWNWWKWWKWWKv_WMWWKWWKWWKWWK^f뀙WWWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWaQsc{lubvnubwnf_````````````ll``gqm|wi`__`````````````^tWNWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKv|WWKWWKWWKWWKڀ}낵vWWKWWKWWKWWKWWKWZ뀩WZWaMxWWKWWKWWKWWKWWKWV뀁WSWWKWWKxzWWKWWKWWKWWKWWKWWKWWKWWKWWKv|WWKWWKWWKWWKۀ}zWWKWWKWWKWWKWWK|lzWRWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWZMrc|lubwnskl_````````````bzil`bxbtnwatnf``_```````````_]_WLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKՀ|낸wWWKWWKWWKWeN냖pWWKWWKWWKWWKWWKZdWRW}R낢sWWKWWKWWKWWKWWKW\kWOWWKWWKހ}났uWWKWWKWWKWWKWWKWWKWWKWWKWWKՀ|낸wWWKWWKWWKWeN낧sWWKWWKWWKWWKWWKr]WLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKnfyjvbunxrj_````````````bxeymdbwasovbwnsencf_````````````]WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW`M냙qWWKWWKWWKWSvkWWKWWKWWKWWKWWKn\WLWW냈nWWKWWKWWKWWKWWKWc~YWLWWKWiO냍oWWKWWKWWKWWKWWKWWKWWKWWKWaM냘qWWKWWKWWKWS냍oWWKWWKWWKWWKWWKw{WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKknvexaunzuj`````````````afumyg|mee}dtnvllbue}nea``````````_ZWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWRzkWWKWWKWWKWY[eWWKWWKWWKWWKWWKx끼wWWKW\njWWKWWKWWKWWKWWKpj끽xWWKWWKWTmiWWKWWKWWKWWKWWKWWKWWKWWKWRykWWKWWKWWKWYtkWWKWWKWWKWWKWWKۀ}낰uWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWK`ss`zaunxsj_````````````_orkr]qptgm`fd`{cunzhm|rj`_````````_qWWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWX]fWWKWWKWWKW_ˇW`WWKWWKWWKWWKWrPmWWKWaYfWWKWWKWWKWWKWWKr냓pWWKWWKWZXdWWKWWKWWKWWKWWKWWKWWKWWKWX]fWWKWWKWWKW^]fWWKWWKWWKWWKWgN냑pWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKXzrZatnxrj_`````````````cvivj`a``ktlr]qpq`xo|ge````````_\TXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW]φW`WWKWWKWWKXd뀬WZWWKWWKWWKWWKW]ՆXbWWKWcWdWWKWWKWWKWWKWWKՀ|hhWWKWWKW_ÇW_WWKWWKWWKWWKWWKWWKWWKWWKW]φW`WWKWWKWWKW`WdWWKWWKWWKWWKWTrjWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLWlUycumwsj_`````````````_aa`_``~gmly`qop\qorbznf_`````__WQXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWc뀯W[WWKWWKWWKmi뀍WUWWKWWKWWKWWKvk뀗WWWWKWe׆WbWWKWWKWWKWWKWwQцWaWWKWWKYe뀤WYWWKWWKWWKWWKWWKWWKWWKWWKWc뀯W[WWKWWKWWKWbنWbWWKWWKWWKWWKWYYeWWKWWKWWKWXKmmSm_QWWKWWKWWKWWKWWKWWKWWKX^Oqd}kvsj_``````````````__`ezib`b}gujujsd~mc`````_]iXMWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKeh뀐WUWWKWWKWWKqmWOWWKWWKWWKWWKÁy~`WMWWK_gφW`WWKWWKWWKWWKW]뀞WXWWKWWKrj뀅WSWWKWWKWWKWWKWWKWWKWWKWWKeh뀏WUWWKWWKWWKWdІWaWWKWWKWWKWWKW^LJW_WWKWWKWWKW{RhhWWKWWKWWKWWKWWKWWKWWKWWLlh|gwsj_```````````````af}crnq\pp}hbb_a`v~i~yi`````_[WXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWK~lsWPWWKWWKWWKӀ{~XWKWWKWWKWWKWU낮uWWKWWKghІWaWWKWWKWWKWWKni~aWMWWKWWKpfWNWWKWWKWWKWWKWWKWWKWWKWWKmrWPWWKWWKWWKYfцWaWWKWWKWWKWWKfh뀩WZWWKWWKWWKW\W^WWKWWKWWKWWKWWKWWKWWKXXKfut`|rj_`````````````_`}hu_soubwnwcwnve}mn}k{nkb_`ae`````_tXXYKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKq`WMWWKWWKWzQyWWKWWKWWKWWKohhgWWKWWK_g؆WbWWKWWKWWKWWKw낫tWWKWWKWWKu}WWKWWKWWKWWKWWKWWKWWKWWKWWKqZWLWWKWWKWWKYfچWcWWKWWKWWKWWKr뀎WUWWKWWKWWK`f뀃WSWWKWWKWWKWWKWWKWWKWWKXWK]nW~qi_``````````````~gs_uowbwnvbvnvbvnvbvnuavnvatozui``__`````_[SXXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKsWWKWWKWWKX`낳vWWKWWKWWKW\LЁ{뀘WWWWKWWKWeXeWWKWWKWWKWTjiWWKWWKWWKЁ{끻wWWKWWKWWKWWKWWKWWKWWKWWKWWKs}WWKWWKWWKWWKp_fWWKWWKWWKWdN܀}~WRWWKWWKWWKu{XWKWWKWWKWWKWWKWWKWWKWWKWXLW_Qrvg_````````````_cuawnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbwnd```````_^pWNYWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKu]WLWWKWWKq낭uWWKWWKWWK[^{YWLWWKWWKWcrjWWKWWKWWKmg뀯W[WWKWWKW]L냜rWWKWWKWWKWWKWWKWWKWWKWWKWWKu~WWKWWKWWKWuQ넂mWWKWWKWWKZ`뀂WSWWKWWKWxQ넆nWWKWWKWWKWWKWWKWWKWWKWWKWXKXWLr^_`````````````jslvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnwqj_```````ZWXLXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKu뀅WSWWKWUzWWKWWKWhNƁyvkWWKWWKWWKW]낯uWWKWWKWkOـ||_WMWWKWWKW{R}lWWKWWKWWKWWKWWKWWKWWKWWKWWKunWOWWKWWKlyXWKWWKWbMw뀢WYWWKWWKzj‡W^WWKWWKWWKWWKWWKWWKWWKWWKWWKXWLiU^````````````ft`uovbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbwntd|nb``````_iUWXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKtمxh]qQu뀦h\]rQr뀬WZWWKWWKWWKWV뀲r`_kPp~lWWKWWKWWKWW_gWWKWWKWWKWWKWWKWWKWWKWWKWWKtυ}g`]Nwa뀽rb[nPn僓oeZOk\mWOWWKWWKWWKWWKWWKWWKWWKWWKWWKXXLYwO_````````````fq`xovavnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnwatn}yh``````_vYOYXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKqz]WLWWKWWKWWKWhN뀬WZWWKWWKWWKW]҆WaWWKWWKWWKWWKWWKWWKWWKWWKWWKq|{냟rWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKWZLZ_```````````beunwbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvbvnvaunvok_````_Z[WLXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKxk|uڅeeWWKWWKWWKWWKWWKu낸vYWLWWKWWKWWKWb뀳W\WWKWWKWWKWWKWWKWWKWWKWWKWWKxksi؀|뀯wa뀹X]WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWL_T_````````````gtmwbvnvbvnwcwnvbvnvbvnvbvnvbvnvbvnvbvnvaunztj_````__TWXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKZdsjnj|nWOWWKWWKWWKWWKWWKgg뀹Y]WWKWWKWWKWWKdh뀔WVWWKWWKWWKWWKWWKWWKWWKWWKWWKZdWSp{[XL܀}z\WLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXXKWgM]_``````````b|dunwbvnvbwnt_roubwnvbvnvbvnvbvnvbvnvbvnwatnzvi_```_]gWMXXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWYWTW_҆gdWWKWWKWWKWWKWWKWWKW|R낱uYWLWWKWWKWWKWWKmuWQWWKWWKWWKWWKWWKWWKWWKWWKWWKWY烎oWWK\bцgdWWKq`_WWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLXWKsX__`````````ctawnvbvnv`ro{jlxasnvbvnvbvnvbvnvbvnvbvnwatn{xi_``__sXWXKWWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKW`M؀|儇mWWKWnOހ}내v`WMWWKWWKWWKWWKWWKWWKWWKk}WSWWKWWKWWKWWKWWKsZWLWWKWWKWWKWWKWWKWWKWWKWWKWWKW`M؀|}zWQWWKWkO~y`WMWWKW]邤sXWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWLW}P^_`````````eq_xovauntd}ndoxkuavnvbvnvbvnvbvnvbvnw`ro}~g```_^}WPWXLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKrh|sWPWWKWWKph|WSWWKWWKWWKWWKWWKWWKWWKWWKWeNv~`[WWKWWKWWKWWKWWKWWKÁxzWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKrhꀸg_WWKWWKWWKpf[[WWKWWKW]LtꁻwnWOWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWK}Y__```````_gs`vnu`uoz|h_b{dunvbvnvbvnvbvnvbvnv_rof``__}YWXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWhNx{ZXWWKWWKWWKWgNryXTWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWfNk~؂tZTWWKWWKWWKWWKWWKWWKWXK~났tWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWhNxvbWWKWWKWWKWWKW`Mrj_WWKWWKWWKWWKWlOnڀ|zhgWNWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXLW|P^````````_v{iuavnxklc`_wzivbvnvbvnvbvnvbwntd|nb```^|WPXWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWpPiăqhrWPWWKWWKWWKWWKWWKW^MannbaWMWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWaMjrTgXNWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWpPiărj_UWWKWWKWWKWWKWWKWWKW`McpmhYWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXLsW_```````_qvkxnka```cq`wovbvnvbvnwaun{vj_``_sWXWLWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXWKXhM\```````_cb_```avaunwbwnwbxnuc{nc```\hXMWXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKWWK`R__``````__`````gs^rpt^royvi``__`RWWKXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXXKW[LvW^_```````````_afwib`_^vW[WLXXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKYWKWjNY___``````````__a___YjWNWYKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKXWLWqN[^`__`````````___^[qWNWXLXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWYKXWK[uOZ___`_`````_`___Zu[OWXKYWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXYKXWKWiMY_^^_`````_^^_YiWMWXKYXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKXYKXWLWXKqT\^_`````_^\qTXWKWXLYXKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWXKXWLWWKW_LtT[__`__[tT_WLWWKWXLXWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWKWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWLWWL \ No newline at end of file diff --git a/components/esp_lcd/test_apps/rgb_lcd/README.md b/components/esp_lcd/test_apps/rgb_lcd/README.md index 47ecb029fc44..c9ab66b2b9b4 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/README.md +++ b/components/esp_lcd/test_apps/rgb_lcd/README.md @@ -1,4 +1,4 @@ -| Supported Targets | ESP32-S3 | -| ----------------- | -------- | +| Supported Targets | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | This test app is used to test RGB565 interfaced LCDs. diff --git a/components/esp_lcd/test_apps/rgb_lcd/main/test_app_main.c b/components/esp_lcd/test_apps/rgb_lcd/main/test_app_main.c index 7b7ff5c86876..59989d90b117 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/main/test_app_main.c +++ b/components/esp_lcd/test_apps/rgb_lcd/main/test_app_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ diff --git a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_board.h b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_board.h index 180c519e5614..3e65925a1533 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_board.h +++ b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_board.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,16 @@ extern "C" { #define TEST_LCD_H_RES 800 #define TEST_LCD_V_RES 480 +#define TEST_LCD_HSYNC 1 +#define TEST_LCD_HBP 40 +#define TEST_LCD_HFP 20 +#define TEST_LCD_VSYNC 1 +#define TEST_LCD_VBP 10 +#define TEST_LCD_VFP 5 + +#define TEST_LCD_PIXEL_CLOCK_HZ (18 * 1000 * 1000) + +#if CONFIG_IDF_TARGET_ESP32S3 #define TEST_LCD_VSYNC_GPIO 3 #define TEST_LCD_HSYNC_GPIO 46 @@ -34,7 +44,33 @@ extern "C" { #define TEST_LCD_DATA15_GPIO 40 // R4 #define TEST_LCD_DISP_EN_GPIO -1 -#define TEST_LCD_PIXEL_CLOCK_HZ (10 * 1000 * 1000) +#elif CONFIG_IDF_TARGET_ESP32P4 + +#define TEST_LCD_VSYNC_GPIO 41 +#define TEST_LCD_HSYNC_GPIO 39 +#define TEST_LCD_DE_GPIO 43 +#define TEST_LCD_PCLK_GPIO 33 +#define TEST_LCD_DATA0_GPIO 40 // B0 +#define TEST_LCD_DATA1_GPIO 42 // B1 +#define TEST_LCD_DATA2_GPIO 27 // B2 +#define TEST_LCD_DATA3_GPIO 29 // B3 +#define TEST_LCD_DATA4_GPIO 31 // B4 +#define TEST_LCD_DATA5_GPIO 21 // G0 +#define TEST_LCD_DATA6_GPIO 23 // G1 +#define TEST_LCD_DATA7_GPIO 26 // G2 +#define TEST_LCD_DATA8_GPIO 28 // G3 +#define TEST_LCD_DATA9_GPIO 30 // G4 +#define TEST_LCD_DATA10_GPIO 32 // G5 +#define TEST_LCD_DATA11_GPIO 6 // R0 +#define TEST_LCD_DATA12_GPIO 0 // R1 +#define TEST_LCD_DATA13_GPIO 15 // R2 +#define TEST_LCD_DATA14_GPIO 17 // R3 +#define TEST_LCD_DATA15_GPIO 19 // R4 +#define TEST_LCD_DISP_EN_GPIO -1 + +#else +#error "Unsupported target" +#endif #ifdef __cplusplus } diff --git a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c index 8c39c32121f4..0de40e884ccf 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c +++ b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -62,12 +62,12 @@ static esp_lcd_panel_handle_t test_rgb_panel_initialization(size_t data_width, s .pclk_hz = TEST_LCD_PIXEL_CLOCK_HZ, .h_res = TEST_LCD_H_RES, .v_res = TEST_LCD_V_RES, - .hsync_back_porch = 68, - .hsync_front_porch = 20, - .hsync_pulse_width = 5, - .vsync_back_porch = 18, - .vsync_front_porch = 4, - .vsync_pulse_width = 1, + .hsync_back_porch = TEST_LCD_HBP, + .hsync_front_porch = TEST_LCD_HFP, + .hsync_pulse_width = TEST_LCD_HSYNC, + .vsync_back_porch = TEST_LCD_VBP, + .vsync_front_porch = TEST_LCD_VFP, + .vsync_pulse_width = TEST_LCD_VSYNC, }, .flags.fb_in_psram = 1, // allocate frame buffer in PSRAM .flags.refresh_on_demand = refresh_on_demand, @@ -99,6 +99,7 @@ TEST_CASE("lcd_rgb_panel_stream_mode", "[lcd]") int y_start = esp_random() % (TEST_LCD_V_RES - 100); memset(img, color_byte, TEST_IMG_SIZE); esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img); + vTaskDelay(pdMS_TO_TICKS(10)); } printf("delete RGB panel\r\n"); TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); diff --git a/components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py b/components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py index 497ca91e4d2e..a9d77166a45f 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py +++ b/components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py @@ -1,6 +1,5 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut @@ -15,5 +14,19 @@ ], indirect=True, ) -def test_rgb_lcd(dut: Dut) -> None: +def test_rgb_lcd_esp32s3(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32p4 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'iram_safe', + 'release', + ], + indirect=True, +) +def test_rgb_lcd_esp32p4(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.iram_safe b/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.iram_safe index 0643ce8884a5..a0efad79df16 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.iram_safe +++ b/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.iram_safe @@ -1,8 +1,5 @@ CONFIG_COMPILER_DUMP_RTL_FILES=y CONFIG_LCD_RGB_ISR_IRAM_SAFE=y -CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y -# bounce buffer mode relies on GDMA EOF interrupt to be service-able -CONFIG_GDMA_ISR_IRAM_SAFE=y CONFIG_COMPILER_OPTIMIZATION_NONE=y # silent the error check, as the error string are stored in rodata, causing RTL check failure CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y diff --git a/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.defaults.esp32p4 b/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.defaults.esp32p4 new file mode 100644 index 000000000000..a27acf6f087a --- /dev/null +++ b/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.defaults.esp32p4 @@ -0,0 +1,5 @@ +CONFIG_IDF_EXPERIMENTAL_FEATURES=y + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_HEX=y +CONFIG_SPIRAM_SPEED_200M=y diff --git a/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test_lwip.c b/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test_lwip.c index 6fe84750b4bd..66974fab137a 100644 --- a/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test_lwip.c +++ b/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test_lwip.c @@ -315,6 +315,17 @@ TEST(esp_netif, dhcp_server_state_transitions_mesh) #endif // CONFIG_ESP_WIFI_ENABLED && CONFIG_ESP_WIFI_SOFTAP_SUPPORT #ifdef CONFIG_ESP_WIFI_ENABLED +/* + * This checks some semi-public API for null dereference + */ +TEST(esp_netif, wifi_netif_api_null_deref) +{ + esp_wifi_destroy_if_driver(NULL); // returns void: just checking if won't crash + TEST_ASSERT_NOT_EQUAL(ESP_OK, esp_wifi_get_if_mac(NULL, NULL)); + TEST_ASSERT_NOT_EQUAL(true, esp_wifi_is_if_ready_when_started(NULL)); + TEST_ASSERT_NOT_EQUAL(ESP_OK, esp_wifi_register_if_rxcb(NULL, NULL, NULL)); +} + /* * This test validates convenience API esp_netif_create_wifi() which creates WiFi station * or API with the specified inherent network config. @@ -582,6 +593,7 @@ TEST_GROUP_RUNNER(esp_netif) RUN_TEST_CASE(esp_netif, create_delete_multiple_netifs) RUN_TEST_CASE(esp_netif, find_netifs) #ifdef CONFIG_ESP_WIFI_ENABLED + RUN_TEST_CASE(esp_netif, wifi_netif_api_null_deref) RUN_TEST_CASE(esp_netif, create_custom_wifi_interfaces) RUN_TEST_CASE(esp_netif, create_destroy_default_wifi) #endif diff --git a/components/esp_partition/host_test/partition_api_test/main/partition_api_test.c b/components/esp_partition/host_test/partition_api_test/main/partition_api_test.c index ca780fb06a3f..8d57d5d09f1a 100644 --- a/components/esp_partition/host_test/partition_api_test/main/partition_api_test.c +++ b/components/esp_partition/host_test/partition_api_test/main/partition_api_test.c @@ -722,6 +722,48 @@ TEST(partition_api, test_partition_power_off_emulation) free(test_data_ptr); } +TEST(partition_api, test_partition_copy) +{ + const esp_partition_t *factory_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); + TEST_ASSERT_NOT_NULL(factory_part); + + const esp_partition_t *ota0_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL); + TEST_ASSERT_NOT_NULL(ota0_part); + + TEST_ESP_OK(esp_partition_copy(ota0_part, 0, factory_part, 0, factory_part->size)); + TEST_ESP_OK(esp_partition_copy(ota0_part, 0, factory_part, 0, SIZE_MAX)); + + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_partition_copy(ota0_part, 0x1000000, factory_part, 0, SIZE_MAX)); + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_partition_copy(ota0_part, 0, factory_part, 0x1000000, SIZE_MAX)); + + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_partition_copy(ota0_part, 0, factory_part, 0, SIZE_MAX - 1)); + + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_partition_copy(ota0_part, UINT32_MAX - 1, factory_part, 0, 0x10000)); + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_partition_copy(ota0_part, 0, factory_part, UINT32_MAX - 1, 0x10000)); + + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_partition_copy(ota0_part, UINT32_MAX - 1, factory_part, 0, SIZE_MAX)); + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_partition_copy(ota0_part, 0, factory_part, UINT32_MAX - 1, SIZE_MAX)); +} + +TEST(partition_api, test_partition_register_external) +{ + esp_err_t error; + const esp_partition_t *ota1_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL); + TEST_ASSERT_NULL(ota1_part); + const esp_partition_t *storage_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_UNDEFINED, NULL); + error = esp_partition_register_external(NULL, + storage_part->address + storage_part->size, // place this new partition after the storage (the last part in the table) + 1 * 1024 * 1024, + "ota_1", + ESP_PARTITION_TYPE_APP, + ESP_PARTITION_SUBTYPE_APP_OTA_1, + &ota1_part); + TEST_ESP_OK(error); + ota1_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL); + TEST_ASSERT_NOT_NULL(ota1_part); + TEST_ESP_OK(esp_partition_deregister_external(ota1_part)); +} + TEST_GROUP_RUNNER(partition_api) { RUN_TEST_CASE(partition_api, test_partition_find_basic); @@ -741,6 +783,8 @@ TEST_GROUP_RUNNER(partition_api) RUN_TEST_CASE(partition_api, test_partition_mmap_size_too_small); RUN_TEST_CASE(partition_api, test_partition_stats); RUN_TEST_CASE(partition_api, test_partition_power_off_emulation); + RUN_TEST_CASE(partition_api, test_partition_copy); + RUN_TEST_CASE(partition_api, test_partition_register_external); } static void run_all_tests(void) diff --git a/components/esp_partition/host_test/partition_api_test/partition_table.csv b/components/esp_partition/host_test/partition_api_test/partition_table.csv index a70efe6a7544..6ee9489a6271 100644 --- a/components/esp_partition/host_test/partition_api_test/partition_table.csv +++ b/components/esp_partition/host_test/partition_api_test/partition_table.csv @@ -3,4 +3,5 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, +ota_0, app, ota_0, 0x120000, 1M, storage, data, , , 0x40000, diff --git a/components/esp_partition/include/esp_partition.h b/components/esp_partition/include/esp_partition.h index 972fbded9ea9..2a108ac0ac32 100644 --- a/components/esp_partition/include/esp_partition.h +++ b/components/esp_partition/include/esp_partition.h @@ -29,8 +29,8 @@ typedef struct esp_flash_t esp_flash_t; * @brief Enumeration which specifies memory space requested in an mmap call */ typedef enum { - ESP_PARTITION_MMAP_DATA, /**< map to data memory (Vaddr0), allows byte-aligned access, 4 MB total */ - ESP_PARTITION_MMAP_INST, /**< map to instruction memory (Vaddr1-3), allows only 4-byte-aligned access, 11 MB total */ + ESP_PARTITION_MMAP_DATA, /**< map to data memory (Vaddr0), allows byte-aligned access, (4 MB total - only for esp32) */ + ESP_PARTITION_MMAP_INST, /**< map to instruction memory (Vaddr1-3), allows only 4-byte-aligned access, (11 MB total - only for esp32) */ } esp_partition_mmap_memory_t; /** @@ -50,6 +50,8 @@ typedef uint32_t esp_partition_mmap_handle_t; typedef enum { ESP_PARTITION_TYPE_APP = 0x00, //!< Application partition type ESP_PARTITION_TYPE_DATA = 0x01, //!< Data partition type + ESP_PARTITION_TYPE_BOOTLOADER = 0x02, //!< Bootloader partition type + ESP_PARTITION_TYPE_PARTITION_TABLE = 0x03, //!< Partition table type ESP_PARTITION_TYPE_ANY = 0xff, //!< Used to search for partitions with any type } esp_partition_type_t; @@ -65,6 +67,12 @@ typedef enum { * @internal Keep this enum in sync with PartitionDefinition class gen_esp32part.py @endinternal */ typedef enum { + ESP_PARTITION_SUBTYPE_BOOTLOADER_PRIMARY = 0x00, //!< Primary Bootloader + ESP_PARTITION_SUBTYPE_BOOTLOADER_OTA = 0x01, //!< Temporary OTA storage for Bootloader, where the OTA uploads a new Bootloader image + + ESP_PARTITION_SUBTYPE_PARTITION_TABLE_PRIMARY = 0x00, //!< Primary Partition table + ESP_PARTITION_SUBTYPE_PARTITION_TABLE_OTA = 0x01, //!< Temporary OTA storage for Partition table, where the OTA uploads a new Partition table image + ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00, //!< Factory application partition ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10, //!< Base for OTA partition subtypes ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0, //!< OTA partition 0 @@ -429,7 +437,7 @@ bool esp_partition_check_identity(const esp_partition_t* partition_1, const esp_ * This API allows designating certain areas of external flash chips (identified by the esp_flash_t structure) * as partitions. This allows using them with components which access SPI flash through the esp_partition API. * - * @param flash_chip Pointer to the structure identifying the flash chip + * @param flash_chip Pointer to the structure identifying the flash chip. If NULL then the internal flash chip is used (esp_flash_default_chip). * @param offset Address in bytes, where the partition starts * @param size Size of the partition in bytes * @param label Partition name @@ -472,6 +480,35 @@ void esp_partition_unload_all(void); */ uint32_t esp_partition_get_main_flash_sector_size(void); +/** + * @brief Copy data from a source partition at a specific offset to a destination partition at a specific offset. + * + * The destination offset must be aligned to the flash sector size (SPI_FLASH_SEC_SIZE = 0x1000). + * If "size" is SIZE_MAX, the entire destination partition (from dest_offset onward) will be erased, + * and the function will copy all of the source partition starting from src_offset into the destination. + * The function ensures that the destination partition is erased on sector boundaries (erase size is aligned up SPI_FLASH_SEC_SIZE). + * + * This function does the following: + * - erases the destination partition from dest_offset to the specified size (or the whole partition if "size" == SIZE_MAX), + * - maps data from the source partition in chunks, + * - writes the source data into the destination partition in corresponding chunks. + * + * @param dest_part Pointer to a destination partition. + * @param dest_offset Offset in the destination partition where the data should be written (must be aligned to SPI_FLASH_SEC_SIZE = 0x1000). + * @param src_part Pointer to a source partition (must be located on internal flash). + * @param src_offset Offset in the source partition where the data should be read from. + * @param size Number of bytes to copy from the source partition to the destination partition. If "size" is SIZE_MAX, + * the function copies from src_offset to the end of the source partition and erases + * the entire destination partition (from dest_offset onward). + * + * @return ESP_OK, if the source partition was copied successfully to the destination partition; + * ESP_ERR_INVALID_ARG, if src_part or dest_part are incorrect, or if dest_offset is not sector aligned; + * ESP_ERR_INVALID_SIZE, if the copy would go out of bounds of the source or destination partition; + * ESP_ERR_NOT_ALLOWED, if the destination partition is read-only; + * or one of the error codes from the lower-level flash driver. + */ +esp_err_t esp_partition_copy(const esp_partition_t* dest_part, uint32_t dest_offset, const esp_partition_t* src_part, uint32_t src_offset, size_t size); + #ifdef __cplusplus } #endif diff --git a/components/esp_partition/partition.c b/components/esp_partition/partition.c index bb61203e61ea..d1ab54c08637 100644 --- a/components/esp_partition/partition.c +++ b/components/esp_partition/partition.c @@ -9,6 +9,7 @@ #include #include #include +#include /* interim to enable test_wl_host and test_fatfs_on_host compilation (both use IDF_TARGET_ESP32) * should go back to #include "sys/queue.h" once the tests are switched to CMake @@ -24,11 +25,11 @@ #include "esp_flash_partitions.h" #include "esp_attr.h" #include "esp_partition.h" -#if !CONFIG_IDF_TARGET_LINUX #include "esp_flash.h" +#if !CONFIG_IDF_TARGET_LINUX #include "esp_flash_encrypt.h" -#include "spi_flash_mmap.h" #endif +#include "spi_flash_mmap.h" #include "esp_log.h" #include "esp_rom_md5.h" #include "bootloader_util.h" @@ -49,6 +50,8 @@ #define INVARIANTS #endif +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + typedef struct partition_list_item_ { esp_partition_t info; bool user_registered; @@ -68,6 +71,31 @@ static _lock_t s_partition_list_lock; static const char *TAG = "partition"; +static bool is_partition_encrypted(bool encryption_config, esp_partition_type_t type, esp_partition_subtype_t subtype) +{ +#if CONFIG_IDF_TARGET_LINUX + (void) type; + (void) subtype; + (void) encryption_config; + return false; +#else + bool ret_encrypted = encryption_config; + if (!esp_flash_encryption_enabled()) { + /* If flash encryption is not turned on, no partitions should be treated as encrypted */ + ret_encrypted = false; + } else if (type == ESP_PARTITION_TYPE_APP + || (type == ESP_PARTITION_TYPE_BOOTLOADER) + || (type == ESP_PARTITION_TYPE_PARTITION_TABLE) + || (type == ESP_PARTITION_TYPE_DATA && subtype == ESP_PARTITION_SUBTYPE_DATA_OTA) + || (type == ESP_PARTITION_TYPE_DATA && subtype == ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS)) { + /* If encryption is turned on, all app partitions and OTA data + are always encrypted */ + ret_encrypted = true; + } + return ret_encrypted; +#endif +} + // Create linked list of partition_list_item_t structures. // This function is called only once, with s_partition_list_lock taken. static esp_err_t load_partitions(void) @@ -151,25 +179,10 @@ static esp_err_t load_partitions(void) #endif item->info.type = entry.type; item->info.subtype = entry.subtype; - item->info.encrypted = entry.flags & PART_FLAG_ENCRYPTED; + item->info.encrypted = is_partition_encrypted(entry.flags & PART_FLAG_ENCRYPTED, entry.type, entry.subtype); item->info.readonly = entry.flags & PART_FLAG_READONLY; item->user_registered = false; -#if CONFIG_IDF_TARGET_LINUX - item->info.encrypted = false; -#else - if (!esp_flash_encryption_enabled()) { - /* If flash encryption is not turned on, no partitions should be treated as encrypted */ - item->info.encrypted = false; - } else if (entry.type == ESP_PARTITION_TYPE_APP - || (entry.type == ESP_PARTITION_TYPE_DATA && entry.subtype == ESP_PARTITION_SUBTYPE_DATA_OTA) - || (entry.type == ESP_PARTITION_TYPE_DATA && entry.subtype == ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS)) { - /* If encryption is turned on, all app partitions and OTA data - are always encrypted */ - item->info.encrypted = true; - } -#endif - #if CONFIG_NVS_COMPATIBLE_PRE_V4_3_ENCRYPTION_FLAG if (entry.type == ESP_PARTITION_TYPE_DATA && entry.subtype == ESP_PARTITION_SUBTYPE_DATA_NVS && @@ -392,10 +405,10 @@ esp_err_t esp_partition_register_external(esp_flash_t *flash_chip, size_t offset *out_partition = NULL; } -#if CONFIG_IDF_TARGET_LINUX - return ESP_ERR_NOT_SUPPORTED; - -#else +#if !CONFIG_IDF_TARGET_LINUX + if (flash_chip == NULL) { + flash_chip = esp_flash_default_chip; + } if (offset + size > flash_chip->size) { return ESP_ERR_INVALID_SIZE; } @@ -415,7 +428,14 @@ esp_err_t esp_partition_register_external(esp_flash_t *flash_chip, size_t offset item->info.size = size; item->info.type = type; item->info.subtype = subtype; +#if CONFIG_IDF_TARGET_LINUX + item->info.erase_size = ESP_PARTITION_EMULATED_SECTOR_SIZE; item->info.encrypted = false; +#else + item->info.erase_size = SPI_FLASH_SEC_SIZE; + item->info.encrypted = (flash_chip == esp_flash_default_chip) ? is_partition_encrypted(false, type, subtype) : false; +#endif // CONFIG_IDF_TARGET_LINUX + item->info.readonly = false; item->user_registered = true; strlcpy(item->info.label, label, sizeof(item->info.label)); @@ -466,3 +486,75 @@ esp_err_t esp_partition_deregister_external(const esp_partition_t *partition) _lock_release(&s_partition_list_lock); return result; } + +esp_err_t esp_partition_copy(const esp_partition_t* dest_part, uint32_t dest_offset, const esp_partition_t* src_part, uint32_t src_offset, size_t size) +{ + if (src_part == NULL || dest_part == NULL || src_part == dest_part) { + return ESP_ERR_INVALID_ARG; + } + + if (src_offset > src_part->size || dest_offset > dest_part->size) { + return ESP_ERR_INVALID_SIZE; + } + + // Check if the source partition is on external flash and return error +#if !CONFIG_IDF_TARGET_LINUX + if (src_part->flash_chip != esp_flash_default_chip) { + ESP_LOGE(TAG, "Source partition is on external flash. Operation not supported."); + return ESP_ERR_NOT_SUPPORTED; + } +#endif + + size_t dest_erase_size = size; + if (size == SIZE_MAX) { + size = src_part->size - src_offset; + dest_erase_size = dest_part->size - dest_offset; // Erase the whole destination partition + } + + uint32_t src_end_offset; + uint32_t dest_end_offset; + if ((__builtin_add_overflow(src_offset, size, &src_end_offset) || (src_end_offset > src_part->size)) + || (__builtin_add_overflow(dest_offset, size, &dest_end_offset) || (dest_end_offset > dest_part->size))) { // with overflow checks + return ESP_ERR_INVALID_SIZE; + } + + esp_err_t error = esp_partition_erase_range(dest_part, dest_offset, ALIGN_UP(dest_erase_size, SPI_FLASH_SEC_SIZE)); + if (error) { + ESP_LOGE(TAG, "Erasing destination partition range failed (err=0x%x)", error); + return error; + } + + uint32_t src_current_offset = src_offset; + uint32_t dest_current_offset = dest_offset; + size_t remaining_size = size; + /* Read the portion that fits in the free MMU pages */ + uint32_t mmu_free_pages_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); + int attempts_for_mmap = 0; + while (remaining_size > 0) { + uint32_t chunk_size = MIN(remaining_size, mmu_free_pages_count * SPI_FLASH_MMU_PAGE_SIZE); + esp_partition_mmap_handle_t src_part_map; + const void *src_data = NULL; + error = esp_partition_mmap(src_part, src_current_offset, chunk_size, ESP_PARTITION_MMAP_DATA, &src_data, &src_part_map); + if (error == ESP_OK) { + attempts_for_mmap = 0; + error = esp_partition_write(dest_part, dest_current_offset, src_data, chunk_size); + if (error != ESP_OK) { + ESP_LOGE(TAG, "Writing to destination partition failed (err=0x%x)", error); + esp_partition_munmap(src_part_map); + break; + } + esp_partition_munmap(src_part_map); + } else { + mmu_free_pages_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); + chunk_size = 0; + if (++attempts_for_mmap >= 3) { + ESP_LOGE(TAG, "Failed to mmap source partition after a few attempts, mmu_free_pages = %" PRIu32 " (err=0x%x)", mmu_free_pages_count, error); + break; + } + } + src_current_offset += chunk_size; + dest_current_offset += chunk_size; + remaining_size -= chunk_size; + } + return error; +} diff --git a/components/esp_partition/partition_linux.c b/components/esp_partition/partition_linux.c index c85ac0ced8eb..daeba669312a 100644 --- a/components/esp_partition/partition_linux.c +++ b/components/esp_partition/partition_linux.c @@ -67,6 +67,8 @@ const char *esp_partition_type_to_str(const uint32_t type) switch (type) { case PART_TYPE_APP: return "app"; case PART_TYPE_DATA: return "data"; + case PART_TYPE_BOOTLOADER: return "bootloader"; + case PART_TYPE_PARTITION_TABLE: return "partition_table"; default: return "unknown"; } } @@ -74,6 +76,18 @@ const char *esp_partition_type_to_str(const uint32_t type) const char *esp_partition_subtype_to_str(const uint32_t type, const uint32_t subtype) { switch (type) { + case PART_TYPE_BOOTLOADER: + switch (subtype) { + case PART_SUBTYPE_BOOTLOADER_PRIMARY: return "primary"; + case PART_SUBTYPE_BOOTLOADER_OTA: return "ota"; + default: return "unknown"; + } + case PART_TYPE_PARTITION_TABLE: + switch (subtype) { + case PART_SUBTYPE_PARTITION_TABLE_PRIMARY: return "primary"; + case PART_SUBTYPE_PARTITION_TABLE_OTA: return "ota"; + default: return "unknown"; + } case PART_TYPE_APP: switch (subtype) { case PART_SUBTYPE_FACTORY: return "factory"; diff --git a/components/esp_phy/Kconfig b/components/esp_phy/Kconfig index c0837398e2ad..75b5be45cd4e 100644 --- a/components/esp_phy/Kconfig +++ b/components/esp_phy/Kconfig @@ -172,5 +172,10 @@ menu "PHY" help If enabled, there will be some logs while pll tracking + config ESP_PHY_RECORD_USED_TIME + bool "Record PHY used time" + default n + help + Select to support record and query phy used time. endif endmenu # PHY diff --git a/components/esp_phy/esp32c6/phy_init_data.c b/components/esp_phy/esp32c6/phy_init_data.c index f60ba8f7e398..499b60d6609b 100644 --- a/components/esp_phy/esp32c6/phy_init_data.c +++ b/components/esp_phy/esp32c6/phy_init_data.c @@ -13,8 +13,8 @@ const char __attribute__((section(".rodata"))) phy_init_magic_pre[] = PHY_INIT_M * @brief Structure containing default recommended PHY initialization parameters. */ const esp_phy_init_data_t phy_init_data= { { - 0x01, - 0x00, + 0xa, + 0x0, LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x54), LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x54), LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x50), @@ -29,62 +29,62 @@ const esp_phy_init_data_t phy_init_data= { { LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x3C), LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x3C), LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x3C), + LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x4c), + LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x4c), + LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x4c), + LIMIT(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + 0x0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, 0x00, 0x00, 0x00, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0, - 0, 0, 0, 0, @@ -140,7 +140,7 @@ const esp_phy_init_data_t phy_init_data= { { 0, 0, 0, - 0x70 + 0x51 } }; const char __attribute__((section(".rodata"))) phy_init_magic_post[] = PHY_INIT_MAGIC; diff --git a/components/esp_phy/include/esp_phy_init.h b/components/esp_phy/include/esp_phy_init.h index 95756568b48b..2e194f707b38 100644 --- a/components/esp_phy/include/esp_phy_init.h +++ b/components/esp_phy/include/esp_phy_init.h @@ -38,6 +38,7 @@ typedef enum { PHY_MODEM_WIFI = 1, /*!< PHY modem WIFI */ PHY_MODEM_BT = 2, /*!< PHY modem BT */ PHY_MODEM_IEEE802154 = 4, /*!< PHY modem IEEE802154 */ + PHY_MODEM_MAX, /*!< Don't use it. Used by ESP_PHY_MODEM_COUNT_MAX */ } esp_phy_modem_t; /** @@ -286,6 +287,23 @@ void phy_init_param_set(uint8_t param); */ void phy_wifi_enable_set(uint8_t enable); +#if CONFIG_ESP_PHY_RECORD_USED_TIME +/** + * @brief Get phy used time from different modem + * @param used_time pointer of variable to get used time, in microseconds + * @param modem modem type + * @return ESP_ERR_INVALID_ARG on incorrect modem type. + */ +esp_err_t phy_query_used_time(uint64_t *used_time, esp_phy_modem_t modem); + +/** + * @brief Clear phy used time for different modem + * @param modem modem type + * @return ESP_ERR_INVALID_ARG on incorrect modem type. + */ +esp_err_t phy_clear_used_time(esp_phy_modem_t modem); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_phy/lib b/components/esp_phy/lib index 6bd4ea98abf8..f5f852b53c90 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit 6bd4ea98abf865ee8ee3598f58d7260bf06ff03e +Subproject commit f5f852b53c90c2a23bfbd6b9c4897c25f0ae6155 diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index bc495b303168..86f1cbb5e00d 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -161,6 +161,60 @@ static phy_country_to_bin_type_t s_country_code_map_type_table[] = { {"US", ESP_PHY_INIT_DATA_TYPE_FCC}, }; #endif + +#if CONFIG_ESP_PHY_RECORD_USED_TIME +#define ESP_PHY_MODEM_COUNT_MAX (__builtin_ffs(PHY_MODEM_MAX - 1)) +#define ESP_PHY_IS_VALID_MODEM(modem) (__builtin_popcount(modem) == 1 && __builtin_ctz(modem) < ESP_PHY_MODEM_COUNT_MAX) + +static DRAM_ATTR struct { + uint64_t used_time; + uint64_t enabled_time; + uint64_t disabled_time; +} s_phy_rf_used_info[ESP_PHY_MODEM_COUNT_MAX]; + +static IRAM_ATTR void phy_record_time(bool enabled, esp_phy_modem_t modem) { + uint8_t index = __builtin_ctz(modem); + if (enabled) { + s_phy_rf_used_info[index].enabled_time = esp_timer_get_time(); + } else { + s_phy_rf_used_info[index].disabled_time = esp_timer_get_time(); + s_phy_rf_used_info[index].used_time += s_phy_rf_used_info[index].disabled_time - s_phy_rf_used_info[index].enabled_time; + } +} + +esp_err_t phy_query_used_time(uint64_t *used_time, esp_phy_modem_t modem) { + if (!ESP_PHY_IS_VALID_MODEM(modem)) { + return ESP_ERR_INVALID_ARG; + } + uint8_t index = __builtin_ctz(modem); + _lock_acquire(&s_phy_access_lock); + *used_time = s_phy_rf_used_info[index].used_time; + if (s_phy_rf_used_info[index].disabled_time < s_phy_rf_used_info[index].enabled_time) { + // phy is being used + *used_time += esp_timer_get_time() - s_phy_rf_used_info[index].enabled_time; + } + _lock_release(&s_phy_access_lock); + return ESP_OK; +} + +esp_err_t phy_clear_used_time(esp_phy_modem_t modem) { + if (!ESP_PHY_IS_VALID_MODEM(modem)) { + return ESP_ERR_INVALID_ARG; + } + uint8_t index = __builtin_ctz(modem); + _lock_acquire(&s_phy_access_lock); + if (s_phy_rf_used_info[index].enabled_time > s_phy_rf_used_info[index].disabled_time) { + // phy is being used + s_phy_rf_used_info[index].enabled_time = esp_timer_get_time(); + } else { + s_phy_rf_used_info[index].enabled_time = s_phy_rf_used_info[index].disabled_time; + } + s_phy_rf_used_info[index].used_time = 0; + _lock_release(&s_phy_access_lock); + return ESP_OK; +} +#endif + uint32_t IRAM_ATTR phy_enter_critical(void) { if (xPortInIsrContext()) { @@ -293,13 +347,18 @@ void esp_phy_enable(esp_phy_modem_t modem) phy_track_pll(); #endif +#if CONFIG_ESP_PHY_RECORD_USED_TIME + phy_record_time(true, modem); +#endif _lock_release(&s_phy_access_lock); } void esp_phy_disable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); - +#if CONFIG_ESP_PHY_RECORD_USED_TIME + phy_record_time(false, modem); +#endif phy_clr_modem_flag(modem); if (phy_get_modem_flag() == 0) { // ESP32 will track pll in the wifi/BT modem interrupt handler. diff --git a/components/esp_phy/src/phy_init_esp32hxx.c b/components/esp_phy/src/phy_init_esp32hxx.c index d0d3e2a20b98..9ff88d452fee 100644 --- a/components/esp_phy/src/phy_init_esp32hxx.c +++ b/components/esp_phy/src/phy_init_esp32hxx.c @@ -8,6 +8,7 @@ #include "freertos/portmacro.h" #include "esp_phy_init.h" #include "esp_private/phy.h" +#include "esp_timer.h" #if SOC_MODEM_CLOCK_IS_INDEPENDENT #include "esp_private/esp_modem_clock.h" @@ -23,6 +24,59 @@ static _lock_t s_phy_access_lock; /* Reference count of enabling PHY */ static bool s_phy_is_enabled = false; +#if CONFIG_ESP_PHY_RECORD_USED_TIME +#define ESP_PHY_MODEM_COUNT_MAX (__builtin_ffs(PHY_MODEM_MAX - 1)) +#define ESP_PHY_IS_VALID_MODEM(modem) (__builtin_popcount(modem) == 1 && __builtin_ctz(modem) < ESP_PHY_MODEM_COUNT_MAX) + +static DRAM_ATTR struct { + uint64_t used_time; + uint64_t enabled_time; + uint64_t disabled_time; +} s_phy_rf_used_info[ESP_PHY_MODEM_COUNT_MAX]; + +static IRAM_ATTR void phy_record_time(bool enabled, esp_phy_modem_t modem) { + uint8_t index = __builtin_ctz(modem); + if (enabled) { + s_phy_rf_used_info[index].enabled_time = esp_timer_get_time(); + } else { + s_phy_rf_used_info[index].disabled_time = esp_timer_get_time(); + s_phy_rf_used_info[index].used_time += s_phy_rf_used_info[index].disabled_time - s_phy_rf_used_info[index].enabled_time; + } +} + +esp_err_t phy_query_used_time(uint64_t *used_time, esp_phy_modem_t modem) { + if (!ESP_PHY_IS_VALID_MODEM(modem)) { + return ESP_ERR_INVALID_ARG; + } + uint8_t index = __builtin_ctz(modem); + _lock_acquire(&s_phy_access_lock); + *used_time = s_phy_rf_used_info[index].used_time; + if (s_phy_rf_used_info[index].disabled_time < s_phy_rf_used_info[index].enabled_time) { + // phy is being used + *used_time += esp_timer_get_time() - s_phy_rf_used_info[index].enabled_time; + } + _lock_release(&s_phy_access_lock); + return ESP_OK; +} + +esp_err_t phy_clear_used_time(esp_phy_modem_t modem) { + if (!ESP_PHY_IS_VALID_MODEM(modem)) { + return ESP_ERR_INVALID_ARG; + } + uint8_t index = __builtin_ctz(modem); + _lock_acquire(&s_phy_access_lock); + if (s_phy_rf_used_info[index].enabled_time > s_phy_rf_used_info[index].disabled_time) { + // phy is being used + s_phy_rf_used_info[index].enabled_time = esp_timer_get_time(); + } else { + s_phy_rf_used_info[index].enabled_time = s_phy_rf_used_info[index].disabled_time; + } + s_phy_rf_used_info[index].used_time = 0; + _lock_release(&s_phy_access_lock); + return ESP_OK; +} +#endif + uint32_t IRAM_ATTR phy_enter_critical(void) { if (xPortInIsrContext()) { @@ -64,13 +118,18 @@ void esp_phy_enable(esp_phy_modem_t modem) phy_set_modem_flag(modem); // Immediately track pll when phy enabled. phy_track_pll(); +#if CONFIG_ESP_PHY_RECORD_USED_TIME + phy_record_time(true, modem); +#endif _lock_release(&s_phy_access_lock); } void esp_phy_disable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); - +#if CONFIG_ESP_PHY_RECORD_USED_TIME + phy_record_time(false, modem); +#endif phy_clr_modem_flag(modem); if (phy_get_modem_flag() == 0) { diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index 6fe90c1ff36a..2399e0690a4e 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -34,6 +34,8 @@ entries: if SOC_PM_SUPPORT_TOP_PD = y: sleep_clock:clock_domain_pd_allowed (noflash) sleep_system_peripheral:peripheral_domain_pd_allowed (noflash) + if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP = y: + sleep_mmu:mmu_domain_pd_allowed (noflash) sleep_modem:modem_domain_pd_allowed (noflash) sleep_modem:periph_inform_out_light_sleep_overhead (noflash) if IDF_TARGET_ESP32P4 = n && IDF_TARGET_ESP32C61 = n : # TODO: IDF-6496, IDF-9304 diff --git a/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_xip_psram_esp32s2 b/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_xip_psram_esp32s2 index 51f7a5a04519..8345d72b95f7 100644 --- a/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_xip_psram_esp32s2 +++ b/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_xip_psram_esp32s2 @@ -1,6 +1,6 @@ CONFIG_IDF_TARGET="esp32s2" CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y CONFIG_SPIRAM_RODATA=y diff --git a/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_xip_psram_esp32s3 b/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_xip_psram_esp32s3 index 31f93b587662..7669b3050c80 100644 --- a/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_xip_psram_esp32s3 +++ b/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_xip_psram_esp32s3 @@ -1,6 +1,6 @@ CONFIG_IDF_TARGET="esp32s3" CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y CONFIG_SPIRAM_RODATA=y diff --git a/components/esp_psram/Kconfig.spiram.common b/components/esp_psram/Kconfig.spiram.common index cbff587ffc18..2832f1e67789 100644 --- a/components/esp_psram/Kconfig.spiram.common +++ b/components/esp_psram/Kconfig.spiram.common @@ -17,16 +17,12 @@ config SPIRAM_IGNORE_NOTFOUND help Normally, if psram initialization is enabled during compile time but not found at runtime, it is seen as an error making the CPU panic. If this is enabled, booting will complete - but no PSRAM will be available. If PSRAM failed to initialize, the following configs may be affected - and may need to be corrected manually. SPIRAM_TRY_ALLOCATE_WIFI_LWIP will affect some LWIP and WiFi buffer - default values and range values. Enable SPIRAM_TRY_ALLOCATE_WIFI_LWIP, ESP_WIFI_AMSDU_TX_ENABLED, - ESP_WIFI_CACHE_TX_BUFFER_NUM and use static WiFi Tx buffer may cause potential memory exhaustion issues. - Suggest disable SPIRAM_TRY_ALLOCATE_WIFI_LWIP. - Suggest disable ESP_WIFI_AMSDU_TX_ENABLED. - Suggest disable ESP_WIFI_CACHE_TX_BUFFER_NUM, - need clear CONFIG_FEATURE_CACHE_TX_BUF_BIT of config->feature_caps. - Suggest change ESP_WIFI_TX_BUFFER from static to dynamic. Also suggest to adjust some buffer numbers to the - values used without PSRAM case. Such as, ESP_WIFI_STATIC_TX_BUFFER_NUM, ESP_WIFI_DYNAMIC_TX_BUFFER_NUM. + but no PSRAM will be available. In particular, it is important to note that when SPIRAM_IGNORE_NOTFOUND + is enabled, some WIFI related configs will be set to the default value used when SPIRAM is disabled. + It can be assumed that by enabling this config, WIFI and LWIP will assume that the current chip does not + have SPIRAM. SPIRAM_TRY_ALLOCATE_WIFI_LWIP will not work, buffers in WIFI and LWIP will be set to smaller + ranges and default values. WIFI_CACHE_TX_BUFFER_NUM and ESP_WIFI_AMSDU_TX_ENABLED will be disabled, + ESP_WIFI_TX_BUFFER will be set to ESP_WIFI_DYNAMIC_TX_BUFFER. choice SPIRAM_USE prompt "SPI RAM access method" diff --git a/components/esp_psram/esp32/Kconfig.spiram b/components/esp_psram/esp32/Kconfig.spiram index f7eb1725a45e..04c32ff5faf1 100644 --- a/components/esp_psram/esp32/Kconfig.spiram +++ b/components/esp_psram/esp32/Kconfig.spiram @@ -259,19 +259,6 @@ menu "SPI RAM config" any himem calls, the reservation is not done and the original amount of memory will be available to malloc/esp_heap_alloc_caps. - config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY - bool "Allow external memory as an argument to xTaskCreateStatic" - default n - depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC - help - Because some bits of the ESP32 code environment cannot be recompiled with the cache workaround, - normally tasks cannot be safely run with their stack residing in external memory; for this reason - xTaskCreate (and related task creaton functions) always allocate stack in internal memory and - xTaskCreateStatic will check if the memory passed to it is in internal memory. If you have a task that - needs a large amount of stack and does not call on ROM code in any way (no direct calls, but also no - Bluetooth/WiFi), you can try enable this to cause xTaskCreateStatic to allow tasks stack in external - memory. - choice SPIRAM_OCCUPY_SPI_HOST prompt "SPI host to use for 32MBit PSRAM" default SPIRAM_OCCUPY_VSPI_HOST diff --git a/components/esp_psram/esp32c5/Kconfig.spiram b/components/esp_psram/esp32c5/Kconfig.spiram index 75e0ec8da9df..ca941e8f1d55 100644 --- a/components/esp_psram/esp32c5/Kconfig.spiram +++ b/components/esp_psram/esp32c5/Kconfig.spiram @@ -17,16 +17,6 @@ menu "SPI RAM config" endchoice - config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY - bool "Allow external memory as an argument to xTaskCreateStatic" - default y - help - Accessing memory in SPIRAM has certain restrictions, so task stacks allocated by xTaskCreate - are by default allocated from internal RAM. - - This option allows for passing memory allocated from SPIRAM to be passed to xTaskCreateStatic. - This should only be used for tasks where the stack is never accessed while the cache is disabled. - choice SPIRAM_SPEED prompt "Set RAM clock speed" default SPIRAM_SPEED_40M diff --git a/components/esp_psram/esp32c61/Kconfig.spiram b/components/esp_psram/esp32c61/Kconfig.spiram index 0ef577983fd9..fefbd96463cb 100644 --- a/components/esp_psram/esp32c61/Kconfig.spiram +++ b/components/esp_psram/esp32c61/Kconfig.spiram @@ -17,16 +17,6 @@ menu "SPI RAM config" endchoice - config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY - bool "Allow external memory as an argument to xTaskCreateStatic" - default y - help - Accessing memory in SPIRAM has certain restrictions, so task stacks allocated by xTaskCreate - are by default allocated from internal RAM. - - This option allows for passing memory allocated from SPIRAM to be passed to xTaskCreateStatic. - This should only be used for tasks where the stack is never accessed while the cache is disabled. - choice SPIRAM_SPEED prompt "Set RAM clock speed" default SPIRAM_SPEED_40M diff --git a/components/esp_psram/esp32p4/Kconfig.spiram b/components/esp_psram/esp32p4/Kconfig.spiram index f17fb795eeca..821188d2f3ff 100644 --- a/components/esp_psram/esp32p4/Kconfig.spiram +++ b/components/esp_psram/esp32p4/Kconfig.spiram @@ -91,17 +91,6 @@ menu "PSRAM config" If enabled, 1/8 of the PSRAM total size will be reserved for error-correcting code. - config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY - bool "Allow external memory as an argument to xTaskCreateStatic" - default y - help - Accessing memory in PSRAM has certain restrictions, so task stacks allocated by xTaskCreate - are by default allocated from internal RAM. - - This option allows for passing memory allocated from PSRAM to be passed to xTaskCreateStatic. - This should only be used for tasks where the stack is never accessed while the L2Cache is - disabled, e.g. during SPI Flash operations - source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here endmenu diff --git a/components/esp_psram/esp32s2/Kconfig.spiram b/components/esp_psram/esp32s2/Kconfig.spiram index 1af865756aaf..6135222a5af4 100644 --- a/components/esp_psram/esp32s2/Kconfig.spiram +++ b/components/esp_psram/esp32s2/Kconfig.spiram @@ -29,16 +29,6 @@ menu "SPI RAM config" bool "ESP-PSRAM64 or LY68L6400" endchoice - config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY - bool "Allow external memory as an argument to xTaskCreateStatic" - default y - help - Accessing memory in SPIRAM has certain restrictions, so task stacks allocated by xTaskCreate - are by default allocated from internal RAM. - - This option allows for passing memory allocated from SPIRAM to be passed to xTaskCreateStatic. - This should only be used for tasks where the stack is never accessed while the cache is disabled. - config SPIRAM_CLK_IO int default 30 diff --git a/components/esp_psram/esp32s3/Kconfig.spiram b/components/esp_psram/esp32s3/Kconfig.spiram index 466343762973..1bf74912d0c7 100644 --- a/components/esp_psram/esp32s3/Kconfig.spiram +++ b/components/esp_psram/esp32s3/Kconfig.spiram @@ -38,16 +38,6 @@ menu "SPI RAM config" bool "ESP-PSRAM64 , LY68L6400 or APS6408" endchoice - config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY - bool "Allow external memory as an argument to xTaskCreateStatic" - default y - help - Accessing memory in SPIRAM has certain restrictions, so task stacks allocated by xTaskCreate - are by default allocated from internal RAM. - - This option allows for passing memory allocated from SPIRAM to be passed to xTaskCreateStatic. - This should only be used for tasks where the stack is never accessed while the cache is disabled. - config SPIRAM_CLK_IO int default 30 diff --git a/components/esp_psram/esp_psram.c b/components/esp_psram/esp_psram.c index 59176e7c74e4..80a9cdeb5f4c 100644 --- a/components/esp_psram/esp_psram.c +++ b/components/esp_psram/esp_psram.c @@ -325,6 +325,7 @@ static void s_psram_mapping(uint32_t psram_available_size, uint32_t start_page) #if CONFIG_IDF_TARGET_ESP32 s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].size -= esp_himem_reserved_area_size() - 1; + s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].vaddr_end -= esp_himem_reserved_area_size(); #endif } diff --git a/components/esp_psram/test_apps/.build-test-rules.yml b/components/esp_psram/test_apps/.build-test-rules.yml index 88e270873461..c9b865f3012b 100644 --- a/components/esp_psram/test_apps/.build-test-rules.yml +++ b/components/esp_psram/test_apps/.build-test-rules.yml @@ -9,11 +9,3 @@ components/esp_psram/test_apps/psram: - esp_driver_gpio - esp_driver_spi - spi_flash - - -components/esp_psram/test_apps/psram_no_malloc_task_stack: - enable: - - if: IDF_TARGET in ["esp32", "esp32p4"] - depends_components: - - esp_psram - - freertos diff --git a/components/esp_psram/test_apps/psram/main/test_himem.c b/components/esp_psram/test_apps/psram/main/test_himem.c index cfb4372d201a..7e048c3af34a 100644 --- a/components/esp_psram/test_apps/psram/main/test_himem.c +++ b/components/esp_psram/test_apps/psram/main/test_himem.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ #include #include #include +#include #include "inttypes.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -106,6 +107,60 @@ TEST_CASE("high psram memory test", "[himem]") vTaskDelay(100); } +#define CACHE_BLOCKSIZE (32*1024) +#define ALLOCATIONS_SIZE (CACHE_BLOCKSIZE / 2) +#define MAX_ALLOCATIONS ((4*1024*1024) / ALLOCATIONS_SIZE) + +TEST_CASE("psram heap doesn't affect himem", "[himem]") +{ + esp_himem_handle_t mh; + esp_himem_rangehandle_t rh; + uint32_t *ptr = NULL; + /* Array containing all the areas from the heap */ + void* allocs[MAX_ALLOCATIONS] = { 0 }; + int allocs_idx = 0; + + /* Allocate a physical block from the PSRAM */ + ESP_ERROR_CHECK(esp_himem_alloc(CACHE_BLOCKSIZE, &mh)); + /* Allocate a range of virtual memory where we can map the allocated block */ + ESP_ERROR_CHECK(esp_himem_alloc_map_range(ESP_HIMEM_BLKSZ, &rh)); + /* Map that physical block in the allocated virtual memory */ + ESP_ERROR_CHECK(esp_himem_map(mh, rh, 0, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr)); + /* Memset that part of the memory with an arbitrary pattern */ + memset(ptr, 0x42, CACHE_BLOCKSIZE); + + /* Allocate heap memory in PSRAM until there is no more memory */ + while (1) { + uint8_t* data = heap_caps_malloc(ALLOCATIONS_SIZE, MALLOC_CAP_SPIRAM); + /* If the allocation failed, there is no more memory, we can break */ + if (data == NULL) { + break; + } + assert(allocs_idx < MAX_ALLOCATIONS); + allocs[allocs_idx++] = data; + /* Set the allocated memory to another pattern */ + memset(data, 0xAB, ALLOCATIONS_SIZE); + } + + /* Make sure we allocated more than 127 blocks */ + printf("Allocated %d blocks\n", allocs_idx); + TEST_ASSERT_GREATER_THAN_INT(127, allocs_idx); + + /* Check if the himem block has been altered by the heap */ + TEST_ASSERT_EACH_EQUAL_INT8(0x42, ptr, CACHE_BLOCKSIZE); + + /* Free all the allocated memories */ + for (int i = 0; i < allocs_idx; i++) { + heap_caps_free(allocs[i]); + } + + ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ)); + ESP_ERROR_CHECK(esp_himem_free(mh)); + ESP_ERROR_CHECK(esp_himem_free_map_range(rh)); + + printf("Success!\n"); +} + #endif #endif // CONFIG_IDF_TARGET_ESP32 diff --git a/components/esp_psram/test_apps/psram_no_malloc_task_stack/CMakeLists.txt b/components/esp_psram/test_apps/psram_no_malloc_task_stack/CMakeLists.txt deleted file mode 100644 index 9debb1681bd8..000000000000 --- a/components/esp_psram/test_apps/psram_no_malloc_task_stack/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.16) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set(COMPONENTS main) -project(psram_no_malloc_task_stack) diff --git a/components/esp_psram/test_apps/psram_no_malloc_task_stack/README.md b/components/esp_psram/test_apps/psram_no_malloc_task_stack/README.md deleted file mode 100644 index 4873c15b15b5..000000000000 --- a/components/esp_psram/test_apps/psram_no_malloc_task_stack/README.md +++ /dev/null @@ -1,2 +0,0 @@ -| Supported Targets | ESP32 | ESP32-P4 | -| ----------------- | ----- | -------- | diff --git a/components/esp_psram/test_apps/psram_no_malloc_task_stack/main/CMakeLists.txt b/components/esp_psram/test_apps/psram_no_malloc_task_stack/main/CMakeLists.txt deleted file mode 100644 index 90939ebf279b..000000000000 --- a/components/esp_psram/test_apps/psram_no_malloc_task_stack/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "test_psram_no_malloc_task_stack.c" - INCLUDE_DIRS "." - PRIV_REQUIRES unity esp_psram freertos heap) diff --git a/components/esp_psram/test_apps/psram_no_malloc_task_stack/main/test_psram_no_malloc_task_stack.c b/components/esp_psram/test_apps/psram_no_malloc_task_stack/main/test_psram_no_malloc_task_stack.c deleted file mode 100644 index d0c48c608d25..000000000000 --- a/components/esp_psram/test_apps/psram_no_malloc_task_stack/main/test_psram_no_malloc_task_stack.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include -#include "esp_log.h" -#include "unity.h" -#include "unity_test_runner.h" -#include "unity_test_utils_memory.h" -#include "unity_test_utils.h" -#include "esp_heap_caps.h" -#include "esp_memory_utils.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -static const char* TAG = "psram_no_malloc_task_stack_test"; - -#define STACK_SIZE 4096 -#define WAIT_TICKS 2 -#define TEST_TASK_PRIORITY 6 // relatively high priority to let task finish quickly - -void setUp(void) -{ - unity_utils_set_leak_level(0); - unity_utils_record_free_mem(); -} - -void tearDown(void) -{ - unity_utils_evaluate_leaks(); -} - -static uint8_t *stack_memory; -static StaticTask_t *tcb_memory; -static bool is_external; -static SemaphoreHandle_t task_waiter; - -static void test_task(void *arg) -{ - int dummy = 47; - is_external = esp_ptr_external_ram(&dummy); - xSemaphoreGive(task_waiter); - vTaskDelay(portMAX_DELAY); -} - -TEST_CASE("FreeRTOS task with stack on SPIRAM works", "[psram]") -{ - stack_memory = heap_caps_malloc(STACK_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - TEST_ASSERT_NOT_NULL(stack_memory); - tcb_memory = heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_8BIT); - TEST_ASSERT_NOT_NULL(tcb_memory); - task_waiter = xSemaphoreCreateBinary(); - TEST_ASSERT_NOT_NULL(task_waiter); - - TaskHandle_t task = xTaskCreateStatic(test_task, - "heap caps static", - STACK_SIZE, - NULL, - TEST_TASK_PRIORITY, - stack_memory, - tcb_memory); - TEST_ASSERT_NOT_NULL(task); - - TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(task_waiter, WAIT_TICKS)); - - TEST_ASSERT_EQUAL(true, is_external); - - // use unity_utils_task_delete() to avoid deleting stack of a still running task - unity_utils_task_delete(task); - - vSemaphoreDelete(task_waiter); - heap_caps_free(tcb_memory); - heap_caps_free(stack_memory); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "Running PSRAM task stack test app with SPIRAM_USE_CAPS_ALLOC"); - - unity_run_menu(); -} diff --git a/components/esp_psram/test_apps/psram_no_malloc_task_stack/pytest_psram_no_malloc_task_stack.py b/components/esp_psram/test_apps/psram_no_malloc_task_stack/pytest_psram_no_malloc_task_stack.py deleted file mode 100644 index 298f6f93c872..000000000000 --- a/components/esp_psram/test_apps/psram_no_malloc_task_stack/pytest_psram_no_malloc_task_stack.py +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: CC0-1.0 -import pytest -from pytest_embedded import Dut - - -@pytest.mark.esp32 -@pytest.mark.esp32p4 -@pytest.mark.generic -def test_psram_no_malloc_task_stack(dut: Dut) -> None: - dut.run_all_single_board_cases() diff --git a/components/esp_psram/test_apps/psram_no_malloc_task_stack/sdkconfig.defaults b/components/esp_psram/test_apps/psram_no_malloc_task_stack/sdkconfig.defaults deleted file mode 100644 index 5e67e04b0c44..000000000000 --- a/components/esp_psram/test_apps/psram_no_malloc_task_stack/sdkconfig.defaults +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_ESP_TASK_WDT_EN=n -CONFIG_SPIRAM=y -CONFIG_SPIRAM_USE_CAPS_ALLOC=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index e344d4dffcf6..a2a86ed786da 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -99,6 +99,11 @@ if(target STREQUAL "linux") else() target_linker_script(${COMPONENT_LIB} INTERFACE "${target_folder}/${ld_folder}/${target}.rom.ld") rom_linker_script("api") + if(NOT CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + if(target STREQUAL "esp32s3" OR target STREQUAL "esp32c3") + rom_linker_script("bt_funcs") + endif() + endif() if(CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB) rom_linker_script("libgcc") @@ -176,15 +181,67 @@ else() # Regular app build endif() elseif(target STREQUAL "esp32c3") + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + if(NOT CONFIG_BT_CTRL_BLE_MASTER) + rom_linker_script("ble_master") + endif() + if(NOT CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT AND NOT CONFIG_BT_BLE_50_FEATURES_SUPPORTED) + rom_linker_script("ble_50") + endif() + if(CONFIG_BT_BLE_CCA_MODE_NONE) + rom_linker_script("ble_cca") + endif() + if(NOT CONFIG_BT_NIMBLE_SECURITY_ENABLE AND NOT CONFIG_BT_BLE_SMP_ENABLE) + rom_linker_script("ble_smp") + endif() + if(NOT CONFIG_BT_CTRL_DTM_ENABLE) + rom_linker_script("ble_dtm") + endif() + if(NOT CONFIG_BT_CTRL_BLE_TEST) + rom_linker_script("ble_test") + endif() + if(NOT CONFIG_BT_CTRL_BLE_SCAN) + rom_linker_script("ble_scan") + endif() + endif() if(CONFIG_ESP32C3_REV_MIN_FULL GREATER_EQUAL 3) rom_linker_script("eco3") + if(NOT CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + rom_linker_script("eco3_bt_funcs") + endif() endif() if(CONFIG_ESP32C3_REV_MIN_FULL GREATER_EQUAL 101) rom_linker_script("eco7") + if(NOT CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + rom_linker_script("eco7_bt_funcs") + endif() + endif() + elseif(target STREQUAL "esp32s3") + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + if(NOT CONFIG_BT_CTRL_BLE_MASTER) + rom_linker_script("ble_master") + endif() + if(NOT CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT AND NOT CONFIG_BT_BLE_50_FEATURES_SUPPORTED) + rom_linker_script("ble_50") + endif() + if(CONFIG_BT_BLE_CCA_MODE_NONE) + rom_linker_script("ble_cca") + endif() + if(NOT CONFIG_BT_NIMBLE_SECURITY_ENABLE AND NOT CONFIG_BT_BLE_SMP_ENABLE) + rom_linker_script("ble_smp") + endif() + if(NOT CONFIG_BT_CTRL_DTM_ENABLE) + rom_linker_script("ble_dtm") + endif() + if(NOT CONFIG_BT_CTRL_BLE_TEST) + rom_linker_script("ble_test") + endif() + if(NOT CONFIG_BT_CTRL_BLE_SCAN) + rom_linker_script("ble_scan") + endif() endif() - elseif(target STREQUAL "esp32c6") # esp32c6.rom.api.ld has been split to several lds by components. # esp32c6.rom.api.ld is still reserved to map the APIs diff --git a/components/esp_rom/esp32/ld/esp32.rom.ld b/components/esp_rom/esp32/ld/esp32.rom.ld index b47c3140b894..a24ff27f0712 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.ld @@ -1368,6 +1368,7 @@ PROVIDE ( esp_rom_spiflash_config_clk = 0x40062bc8 ); PROVIDE ( g_rom_spiflash_chip = 0x3ffae270 ); PROVIDE ( SPI_write_enable = 0x40062320 ); PROVIDE ( hci_le_rd_rem_used_feats_cmd_handler = 0x400417b4 ); +PROVIDE ( hci_per_inq_mode_cmd_handler = 0x400519b0 ); PROVIDE ( llcp_length_req_handler = 0x40043808 ); PROVIDE ( llcp_unknown_rsp_handler = 0x40043ba8 ); PROVIDE ( llcp_channel_map_req_handler = 0x4004291c ); diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.eco4.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.eco4.ld index 22130d601e41..4cbcc4849386 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.eco4.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.eco4.ld @@ -1201,7 +1201,7 @@ ieee80211_send_mgmt = 0x40002038; //ieee80211_auth_construct = 0x4000203c; ieee80211_deauth_construct = 0x40002040; ieee80211_disassoc_construct = 0x40002044; -ieee80211_add_xrates = 0x40002058; +//ieee80211_add_xrates = 0x40002058; //ieee80211_assoc_req_construct = 0x40002060; ieee80211_assoc_resp_construct = 0x40002064; ieee80211_timer_process = 0x4000208c; @@ -1226,7 +1226,7 @@ sta_send_sa_query_req = 0x40002138; sta_send_sa_query_resp = 0x4000213c; sta_recv_sa_query_req = 0x40002140; sta_recv_sa_query_resp = 0x40002144; -ieee80211_parse_beacon = 0x40002148; +//ieee80211_parse_beacon = 0x40002148; ieee80211_match_security = 0x40002154; //ieee80211_parse_rsn = 0x4000215c; /* Data (.data, .bss, .rodata) */ diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld index 166dadf4ee7d..2abe48222a5f 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld @@ -361,8 +361,8 @@ ets_get_xtal_freq = 0x40000784; gpio_input_get = 0x40000788; gpio_matrix_in = 0x4000078c; gpio_matrix_out = 0x40000790; -gpio_output_disable = 0x40000794; -gpio_output_enable = 0x40000798; +/* gpio_output_disable = 0x40000794; */ +/* gpio_output_enable = 0x40000798; */ gpio_output_set = 0x4000079c; gpio_pad_hold = 0x400007a0; gpio_pad_input_disable = 0x400007a4; @@ -1457,7 +1457,7 @@ ppGetTxframe = 0x40001bf8; ppMapTxQueue = 0x40001bfc; ppProcTxSecFrame = 0x40001c00; ppProcessRxPktHdr = 0x40001c04; -ppProcessTxQ = 0x40001c08; +/*ppProcessTxQ = 0x40001c08;*/ ppRecordBarRRC = 0x40001c0c; lmacRequestTxopQueue = 0x40001c10; lmacReleaseTxopQueue = 0x40001c14; @@ -1623,7 +1623,7 @@ dbg_lmac_rxtx_statis_dump = 0x40001e90; dbg_lmac_hw_statis_dump = 0x40001e94; dbg_lmac_diag_statis_dump = 0x40001e98; dbg_lmac_ps_statis_dump = 0x40001e9c; -pp_timer_do_process = 0x40001ea0; +/*pp_timer_do_process = 0x40001ea0;*/ rcUpdateAMPDUParam = 0x40001ea4; rcUpdatePhyMode = 0x40001ea8; rcGetHighestRateIdx = 0x40001eac; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_50.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_50.ld new file mode 100644 index 000000000000..cf9e0c3e1278 --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_50.ld @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32c3.rom.ld for esp32c3 + * + * + * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* extend adv */ +f_hci_le_set_ext_adv_param_cmd_handler = 0; +f_hci_le_set_adv_set_rand_addr_cmd_handler = 0; +f_hci_le_set_ext_adv_data_cmd_handler = 0; +f_hci_le_set_ext_scan_rsp_data_cmd_handler = 0; +f_hci_le_set_ext_adv_en_cmd_handler = 0; +f_hci_le_rd_max_adv_data_len_cmd_handler = 0; +f_hci_le_rd_nb_supp_adv_sets_cmd_handler = 0; +f_hci_le_rmv_adv_set_cmd_handler = 0; +f_hci_le_clear_adv_sets_cmd_handler = 0; +r_lld_adv_sync_info_set = 0; + +r_lld_ext_adv_dynamic_pti_process = 0; +r_lld_adv_ext_chain_construct = 0; +r_lld_adv_aux_evt_canceled_cbk = 0; +r_lld_adv_aux_evt_start_cbk = 0; +r_lld_adv_aux_ch_idx_set = 0; + +/* periodic adv */ +f_hci_le_set_per_adv_param_cmd_handler = 0; +f_hci_le_set_per_adv_data_cmd_handler = 0; +f_hci_le_set_per_adv_en_cmd_handler = 0; +r_lld_per_adv_ch_map_update = 0; +r_lld_per_adv_init = 0; + +/* PA list */ +f_hci_le_add_dev_to_per_adv_list_cmd_handler = 0; +f_hci_le_rmv_dev_from_per_adv_list_cmd_handler = 0; +f_hci_le_clear_per_adv_list_cmd_handler = 0; +f_hci_le_rd_per_adv_list_size_cmd_handler = 0; + +/* extend scan */ +f_hci_le_set_ext_scan_param_cmd_handler = 0; +f_hci_le_set_ext_scan_en_cmd_handler = 0; +r_lld_scan_process_pkt_rx_ext_adv = 0; +r_lld_scan_trunc_ind = 0; + +/* extend con */ +f_hci_le_ext_create_con_cmd_handler = 0; +r_lld_init_process_pkt_rx_adv_ext_ind = 0; +r_lld_init_process_pkt_rx_aux_connect_rsp = 0; + +/* PA sync */ +f_hci_le_per_adv_create_sync_cmd_handler = 0; +f_hci_le_per_adv_create_sync_cancel_cmd_handler = 0; +f_hci_le_per_adv_term_sync_cmd_handler = 0; +f_lld_per_adv_rx_end_ind_handler_hack = 0; +f_lld_sync_start_req_handler = 0; +f_lld_per_adv_rep_ind_handler = 0; +r_lld_sync_init = 0; + +/* phy update*/ +r_phy_upd_proc_start = 0; +f_llc_op_phy_upd_ind_handler = 0; +f_ll_phy_req_handler = 0; +f_ll_phy_rsp_handler = 0; +f_ll_phy_update_ind_handler = 0; +f_lld_phy_upd_cfm_handler = 0; +f_hci_le_set_phy_cmd_handler = 0; +llc_llcp_phy_update_ind_ack = 0; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_cca.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_cca.ld new file mode 100644 index 000000000000..3bb147647223 --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_cca.ld @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32c3.rom.ld for esp32c3 + * + * + * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* SW CCA */ +r_lld_cca_con_evt_start_handle = 0; +r_lld_hw_cca_end_isr = 0; +r_lld_hw_cca_isr_eco = 0; +r_lld_cca_bb_sync_found_handle = 0; +r_lld_cca_data_reset = 0; +r_lld_cca_sw_init = 0; +r_lld_cca_con_evt_end_handle = 0; +r_lld_cca_alloc = 0; +r_lld_cca_sw_alloc = 0; +r_lld_cca_sw_free = 0; +r_lld_cca_free = 0; +r_cca_init = 0; +r_lld_hw_cca_evt_handler = 0; +r_lld_sw_cca_evt_handler = 0; +r_ble_sw_cca_check_isr = 0; +bt_bb_tx_cca_set = 0; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_dtm.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_dtm.ld new file mode 100644 index 000000000000..aeede90250df --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_dtm.ld @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32c3.rom.ld for esp32c3 + * + * + * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* DTM */ +f_hci_le_rx_test_cmd_handler = 0; +f_hci_le_tx_test_cmd_handler = 0; +f_hci_le_enh_rx_test_cmd_handler = 0; +f_hci_le_enh_tx_test_cmd_handler = 0; +f_hci_le_test_end_cmd_handler = 0; +r_lld_test_init = 0; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_master.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_master.ld new file mode 100644 index 000000000000..e7d2db0cbff1 --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_master.ld @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32c3.rom.ld for esp32c3 + * + * + * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* master */ +f_hci_le_create_con_cmd_handler = 0; +f_hci_le_create_con_cancel_cmd_handler = 0; +lld_init_end_ind_handler = 0; +r_lld_init_init = 0; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_scan.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_scan.ld new file mode 100644 index 000000000000..eda6c721a1bf --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_scan.ld @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32c3.rom.ld for esp32c3 + * + * + * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + + +/* BLE scan */ +f_hci_le_set_scan_param_cmd_handler = 0; +f_hci_le_set_scan_en_cmd_handler = 0; +f_llm_scan_period_to_handler_hack = 0; +f_lld_adv_rep_ind_handler_hack = 0; +r_lld_scan_init = 0; +r_lld_scan_restart = 0; +f_lld_scan_end_ind_handler_hack = 0; +r_llm_env_adv_dup_filt_deinit_eco = 0; +llm_exception_list_init = 0; +llm_duplicate_list_init = 0; +f_hci_vendor_ble_update_duplicate_exceptional_list_cmd_handler = 0; +f_hci_vendor_ble_init_adv_flow_control_cmd_handler = 0; +f_hci_vendor_ble_update_adv_report_flow_control_cmd_handler = 0; +coex_schm_ble_scan_stop = 0; + +f_hci_le_set_ext_scan_param_cmd_handler = 0; +f_hci_le_set_ext_scan_en_cmd_handler = 0; +r_lld_scan_process_pkt_rx_ext_adv = 0; +r_lld_scan_trunc_ind = 0; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_smp.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_smp.ld new file mode 100644 index 000000000000..15436088d77f --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_smp.ld @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32c3.rom.ld for esp32c3 + * + * + * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* SMP */ +f_ll_pause_enc_req_handler = 0; +f_ll_pause_enc_rsp_handler = 0; +f_ll_enc_req_handler = 0; +f_ll_enc_rsp_handler = 0; +f_ll_start_enc_req_handler = 0; +f_ll_start_enc_rsp_handler = 0; +f_hci_le_start_enc_cmd_handler = 0; +f_hci_le_ltk_req_reply_cmd_handler = 0; +f_hci_le_ltk_req_neg_reply_cmd_handler = 0; +f_llc_encrypt_ind_handler = 0; +f_llc_op_encrypt_ind_handler = 0; +f_hci_le_rd_local_p256_public_key_cmd_handler = 0; +f_hci_le_generate_dhkey_cmd_handler = 0; +f_hci_le_enc_cmd_handler = 0; +r_rwip_crypt_evt_handler = 0; + +/* LE ping */ +f_ll_ping_req_handler = 0; +f_ll_ping_rsp_handler = 0; +r_llc_le_ping_set = 0; +r_llc_le_ping_restart = 0; +f_llc_op_le_ping_ind_handler = 0; +f_llc_auth_payl_nearly_op_handler = 0; +f_llc_auth_payl_real_to_handler = 0; +f_llc_auth_payl_nearly_to_handler = 0; + +/* ecc */ +r_ecc_init = 0; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_test.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_test.ld new file mode 100644 index 000000000000..0c821cf5ba89 --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ble_test.ld @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32c3.rom.ld for esp32c3 + * + * + * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + + +/* overwrite */ +lld_acl_rx_ind_handler = 0; +lld_con_estab_ind_handler = 0; +lld_adv_rep_ind_handler = 0; +llm_rpa_renew_to_handler = 0; +lld_scan_end_ind_handler = 0; +llm_scan_period_to_handler = 0; + +/* nvds */ +r_nvds_init = 0; +f_nvds_get = 0; +f_nvds_del = 0; +f_nvds_put = 0; + +/* controller flash */ +r_flash_init = 0; +r_flash_env_init = 0; +r_flash_env_deinit = 0; + +/* QA test */ +f_hci_vendor_ble_qa_test_cmd_handler = 0; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.bt_funcs.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.bt_funcs.ld new file mode 100644 index 000000000000..89ea7c532ce8 --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.bt_funcs.ld @@ -0,0 +1,844 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32c3.rom.ld for esp32c3 + * + * + * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/*************************************** + Group bluetooth + ***************************************/ + +/* Functions */ +bt_rf_coex_get_dft_cfg = 0x400008dc; +bt_rf_coex_hooks_p_set = 0x400008e0; +btdm_con_maxevtime_cal_impl = 0x400008e4; +btdm_controller_get_compile_version_impl = 0x400008e8; +btdm_controller_rom_data_init = 0x400008ec; +btdm_dis_privacy_err_report_impl = 0x400008f0; +btdm_disable_adv_delay_impl = 0x400008f4; +btdm_enable_scan_continue_impl = 0x400008f8; +btdm_enable_scan_forever_impl = 0x400008fc; +btdm_get_power_state_impl = 0x40000900; +btdm_get_prevent_sleep_flag_impl = 0x40000904; +btdm_power_state_active_impl = 0x40000908; +btdm_switch_phy_coded_impl = 0x4000090c; +hci_acl_data_handler = 0x40000910; +hci_disconnect_cmd_handler = 0x40000914; +hci_le_con_upd_cmd_handler = 0x40000918; +hci_le_ltk_req_neg_reply_cmd_handler = 0x4000091c; +hci_le_ltk_req_reply_cmd_handler = 0x40000920; +hci_le_rd_chnl_map_cmd_handler = 0x40000924; +hci_le_rd_phy_cmd_handler = 0x40000928; +hci_le_rd_rem_feats_cmd_handler = 0x4000092c; +hci_le_rem_con_param_req_neg_reply_cmd_handler = 0x40000930; +hci_le_rem_con_param_req_reply_cmd_handler = 0x40000934; +hci_le_set_data_len_cmd_handler = 0x40000938; +hci_le_set_phy_cmd_handler = 0x4000093c; +hci_le_start_enc_cmd_handler = 0x40000940; +hci_rd_auth_payl_to_cmd_handler = 0x40000944; +hci_rd_rem_ver_info_cmd_handler = 0x40000948; +hci_rd_rssi_cmd_handler = 0x4000094c; +hci_rd_tx_pwr_lvl_cmd_handler = 0x40000950; +hci_vs_set_pref_slave_evt_dur_cmd_handler = 0x40000954; +hci_vs_set_pref_slave_latency_cmd_handler = 0x40000958; +hci_wr_auth_payl_to_cmd_handler = 0x4000095c; +ll_channel_map_ind_handler = 0x40000960; +ll_connection_param_req_handler = 0x40000964; +ll_connection_param_rsp_handler = 0x40000968; +ll_connection_update_ind_handler = 0x4000096c; +ll_enc_req_handler = 0x40000970; +ll_enc_rsp_handler = 0x40000974; +ll_feature_req_handler = 0x40000978; +ll_feature_rsp_handler = 0x4000097c; +ll_length_req_handler = 0x40000980; +ll_length_rsp_handler = 0x40000984; +ll_min_used_channels_ind_handler = 0x40000988; +ll_pause_enc_req_handler = 0x4000098c; +ll_pause_enc_rsp_handler = 0x40000990; +ll_phy_req_handler = 0x40000994; +ll_phy_rsp_handler = 0x40000998; +ll_phy_update_ind_handler = 0x4000099c; +ll_ping_req_handler = 0x400009a0; +ll_ping_rsp_handler = 0x400009a4; +ll_slave_feature_req_handler = 0x400009a8; +ll_start_enc_req_handler = 0x400009ac; +ll_start_enc_rsp_handler = 0x400009b0; +ll_terminate_ind_handler = 0x400009b4; +ll_version_ind_handler = 0x400009b8; +llc_auth_payl_nearly_to_handler = 0x400009bc; +llc_auth_payl_real_to_handler = 0x400009c0; +llc_encrypt_ind_handler = 0x400009c4; +llc_hci_command_handler_wrapper = 0x400009c8; +llc_ll_connection_param_req_pdu_send = 0x400009cc; +llc_ll_connection_param_rsp_pdu_send = 0x400009d0; +llc_ll_connection_update_ind_pdu_send = 0x400009d4; +llc_ll_enc_req_pdu_send = 0x400009d8; +llc_ll_enc_rsp_pdu_send = 0x400009dc; +llc_ll_feature_req_pdu_send = 0x400009e0; +llc_ll_feature_rsp_pdu_send = 0x400009e4; +llc_ll_length_req_pdu_send = 0x400009e8; +llc_ll_length_rsp_pdu_send = 0x400009ec; +llc_ll_pause_enc_req_pdu_send = 0x400009f0; +llc_ll_pause_enc_rsp_pdu_send = 0x400009f4; +llc_ll_phy_req_pdu_send = 0x400009f8; +llc_ll_phy_rsp_pdu_send = 0x400009fc; +llc_ll_ping_req_pdu_send = 0x40000a00; +llc_ll_ping_rsp_pdu_send = 0x40000a04; +llc_ll_start_enc_req_pdu_send = 0x40000a08; +llc_ll_start_enc_rsp_pdu_send = 0x40000a0c; +llc_ll_terminate_ind_pdu_send = 0x40000a10; +llc_ll_unknown_rsp_pdu_send = 0x40000a14; +llc_llcp_ch_map_update_ind_pdu_send = 0x40000a18; +llc_llcp_phy_upd_ind_pdu_send = 0x40000a1c; +llc_llcp_version_ind_pdu_send = 0x40000a20; +llc_op_ch_map_upd_ind_handler = 0x40000a24; +llc_op_con_upd_ind_handler = 0x40000a28; +llc_op_disconnect_ind_handler = 0x40000a2c; +llc_op_dl_upd_ind_handler = 0x40000a30; +llc_op_encrypt_ind_handler = 0x40000a34; +llc_op_feats_exch_ind_handler = 0x40000a38; +llc_op_le_ping_ind_handler = 0x40000a3c; +llc_op_phy_upd_ind_handler = 0x40000a40; +llc_op_ver_exch_ind_handler = 0x40000a44; +llc_stopped_ind_handler = 0x40000a48; +lld_acl_rx_ind_handler = 0x40000a4c; +lld_acl_tx_cfm_handler = 0x40000a50; +lld_adv_end_ind_handler = 0x40000a54; +lld_adv_rep_ind_handler = 0x40000a58; +lld_ch_map_upd_cfm_handler = 0x40000a5c; +lld_con_estab_ind_handler = 0x40000a60; +lld_con_evt_sd_evt_time_set = 0x40000a64; +lld_con_offset_upd_ind_handler = 0x40000a68; +lld_con_param_upd_cfm_handler = 0x40000a6c; +lld_disc_ind_handler = 0x40000a70; +lld_init_end_ind_handler = 0x40000a74; +lld_llcp_rx_ind_handler_wrapper = 0x40000a78; +lld_llcp_tx_cfm_handler = 0x40000a7c; +lld_per_adv_end_ind_handler = 0x40000a80; +lld_per_adv_rep_ind_handler = 0x40000a84; +lld_per_adv_rx_end_ind_handler = 0x40000a88; +lld_phy_coded_500k_get = 0x40000a8c; +lld_phy_upd_cfm_handler = 0x40000a90; +lld_scan_end_ind_handler = 0x40000a94; +lld_scan_req_ind_handler = 0x40000a98; +lld_sync_start_req_handler = 0x40000a9c; +lld_test_end_ind_handler = 0x40000aa0; +lld_update_rxbuf_handler = 0x40000aa4; +llm_ch_map_update_ind_handler = 0x40000aa8; +llm_hci_command_handler_wrapper = 0x40000aac; +llm_scan_period_to_handler = 0x40000ab0; +r_Add2SelfBigHex256 = 0x40000ab4; +r_AddBigHex256 = 0x40000ab8; +r_AddBigHexModP256 = 0x40000abc; +r_AddP256 = 0x40000ac0; +r_AddPdiv2_256 = 0x40000ac4; +r_GF_Jacobian_Point_Addition256 = 0x40000ac8; +r_GF_Jacobian_Point_Double256 = 0x40000acc; +r_GF_Point_Jacobian_To_Affine256 = 0x40000ad0; +r_MultiplyBigHexByUint32_256 = 0x40000ad4; +r_MultiplyBigHexModP256 = 0x40000ad8; +r_MultiplyByU16ModP256 = 0x40000adc; +r_SubtractBigHex256 = 0x40000ae0; +r_SubtractBigHexMod256 = 0x40000ae4; +r_SubtractBigHexUint32_256 = 0x40000ae8; +r_SubtractFromSelfBigHex256 = 0x40000aec; +r_SubtractFromSelfBigHexSign256 = 0x40000af0; +r_aes_alloc = 0x40000af4; +r_aes_ccm_continue = 0x40000af8; +r_aes_ccm_process_e = 0x40000afc; +r_aes_ccm_xor_128_lsb = 0x40000b00; +r_aes_ccm_xor_128_msb = 0x40000b04; +r_aes_cmac_continue = 0x40000b08; +r_aes_cmac_start = 0x40000b0c; +r_aes_k1_continue = 0x40000b10; +r_aes_k2_continue = 0x40000b14; +r_aes_k3_continue = 0x40000b18; +r_aes_k4_continue = 0x40000b1c; +r_aes_shift_left_128 = 0x40000b20; +r_aes_start = 0x40000b24; +r_aes_xor_128 = 0x40000b28; +r_assert_err = 0x40000b2c; +r_assert_param = 0x40000b30; +r_assert_warn = 0x40000b34; +r_bigHexInversion256 = 0x40000b38; +r_ble_sw_cca_check_isr = 0x40000b3c; +r_ble_util_buf_acl_tx_alloc = 0x40000b40; +r_ble_util_buf_acl_tx_elt_get = 0x40000b44; +r_ble_util_buf_acl_tx_free = 0x40000b48; +r_ble_util_buf_acl_tx_free_in_isr = 0x40000b4c; +r_ble_util_buf_adv_tx_alloc = 0x40000b50; +r_ble_util_buf_adv_tx_free = 0x40000b54; +r_ble_util_buf_adv_tx_free_in_isr = 0x40000b58; +r_ble_util_buf_env_deinit = 0x40000b5c; +r_ble_util_buf_env_init = 0x40000b60; +r_ble_util_buf_get_rx_buf_nb = 0x40000b64; +r_ble_util_buf_get_rx_buf_size = 0x40000b68; +r_ble_util_buf_llcp_tx_alloc = 0x40000b6c; +r_ble_util_buf_llcp_tx_free = 0x40000b70; +r_ble_util_buf_rx_alloc = 0x40000b74; +r_ble_util_buf_rx_alloc_in_isr = 0x40000b78; +r_ble_util_buf_rx_free = 0x40000b7c; +r_ble_util_buf_rx_free_in_isr = 0x40000b80; +r_ble_util_buf_set_rx_buf_nb = 0x40000b84; +r_ble_util_buf_set_rx_buf_size = 0x40000b88; +r_ble_util_data_rx_buf_reset = 0x40000b8c; +r_bt_bb_get_intr_mask = 0x40000b90; +r_bt_bb_intr_clear = 0x40000b94; +r_bt_bb_intr_mask_set = 0x40000b98; +r_bt_rf_coex_cfg_set = 0x40000ba0; +r_bt_rf_coex_conn_dynamic_pti_en_get = 0x40000ba4; +r_bt_rf_coex_ext_adv_dynamic_pti_en_get = 0x40000bac; +r_bt_rf_coex_ext_scan_dynamic_pti_en_get = 0x40000bb0; +r_bt_rf_coex_legacy_adv_dynamic_pti_en_get = 0x40000bb4; +r_bt_rf_coex_per_adv_dynamic_pti_en_get = 0x40000bb8; +r_bt_rf_coex_pti_table_get = 0x40000bbc; +r_bt_rf_coex_st_param_get = 0x40000bc0; +r_bt_rf_coex_st_param_set = 0x40000bc4; +r_bt_rf_coex_sync_scan_dynamic_pti_en_get = 0x40000bc8; +r_bt_rma_apply_rule_cs_fmt = 0x40000bcc; +r_bt_rma_apply_rule_cs_idx = 0x40000bd0; +r_bt_rma_configure = 0x40000bd4; +r_bt_rma_deregister_rule_cs_fmt = 0x40000bd8; +r_bt_rma_deregister_rule_cs_idx = 0x40000bdc; +r_bt_rma_get_ant_by_act = 0x40000be0; +r_bt_rma_init = 0x40000be4; +r_bt_rma_register_rule_cs_fmt = 0x40000be8; +r_bt_rma_register_rule_cs_idx = 0x40000bec; +r_bt_rtp_apply_rule_cs_fmt = 0x40000bf0; +r_bt_rtp_apply_rule_cs_idx = 0x40000bf4; +r_bt_rtp_deregister_rule_cs_fmt = 0x40000bf8; +r_bt_rtp_deregister_rule_cs_idx = 0x40000bfc; +r_bt_rtp_init = 0x40000c04; +r_bt_rtp_register_rule_cs_fmt = 0x40000c08; +r_bt_rtp_register_rule_cs_idx = 0x40000c0c; +r_btdm_isr = 0x40000c10; +r_cali_phase_match_p = 0x40000c20; +r_cmp_abs_time = 0x40000c24; +r_cmp_dest_id = 0x40000c28; +r_cmp_timer_id = 0x40000c2c; +r_co_bdaddr_compare = 0x40000c30; +r_co_ble_pkt_dur_in_us = 0x40000c34; +r_co_list_extract = 0x40000c38; +r_co_list_extract_after = 0x40000c3c; +r_co_list_extract_sublist = 0x40000c40; +r_co_list_find = 0x40000c44; +r_co_list_init = 0x40000c48; +r_co_list_insert_after = 0x40000c4c; +r_co_list_insert_before = 0x40000c50; +r_co_list_merge = 0x40000c54; +r_co_list_pool_init = 0x40000c58; +r_co_list_pop_front = 0x40000c5c; +r_co_list_push_back = 0x40000c60; +r_co_list_push_back_sublist = 0x40000c64; +r_co_list_push_front = 0x40000c68; +r_co_list_size = 0x40000c6c; +r_co_nb_good_le_channels = 0x40000c70; +r_co_util_pack = 0x40000c74; +r_co_util_read_array_size = 0x40000c78; +r_co_util_unpack = 0x40000c7c; +r_dbg_env_deinit = 0x40000c80; +r_dbg_env_init = 0x40000c84; +r_dbg_platform_reset_complete = 0x40000c88; +r_dl_upd_proc_start = 0x40000c8c; +r_dump_data = 0x40000c90; +r_ecc_abort_key256_generation = 0x40000c94; +r_ecc_gen_new_public_key = 0x40000c98; +r_ecc_gen_new_secret_key = 0x40000c9c; +r_ecc_generate_key256 = 0x40000ca0; +r_ecc_get_debug_Keys = 0x40000ca4; +r_ecc_init = 0x40000ca8; +r_ecc_is_valid_point = 0x40000cac; +r_ecc_multiplication_event_handler = 0x40000cb0; +r_ecc_point_multiplication_win_256 = 0x40000cb4; +r_emi_alloc_em_mapping_by_offset = 0x40000cb8; +r_emi_base_reg_lut_show = 0x40000cbc; +r_emi_em_base_reg_show = 0x40000cc0; +r_emi_free_em_mapping_by_offset = 0x40000cc4; +r_emi_get_em_mapping_idx_by_offset = 0x40000cc8; +r_emi_get_mem_addr_by_offset = 0x40000ccc; +r_emi_overwrite_em_mapping_by_offset = 0x40000cd0; +r_esp_vendor_hci_command_handler = 0x40000cd4; +r_get_stack_usage = 0x40000cd8; +r_h4tl_acl_hdr_rx_evt_handler = 0x40000cdc; +r_h4tl_cmd_hdr_rx_evt_handler = 0x40000ce0; +r_h4tl_cmd_pld_rx_evt_handler = 0x40000ce4; +r_h4tl_eif_io_event_post = 0x40000ce8; +r_h4tl_eif_register = 0x40000cec; +r_h4tl_init = 0x40000cf0; +r_h4tl_out_of_sync = 0x40000cf4; +r_h4tl_out_of_sync_check = 0x40000cf8; +r_h4tl_read_hdr = 0x40000cfc; +r_h4tl_read_next_out_of_sync = 0x40000d00; +r_h4tl_read_payl = 0x40000d04; +r_h4tl_read_start = 0x40000d08; +r_h4tl_rx_acl_hdr_extract = 0x40000d0c; +r_h4tl_rx_cmd_hdr_extract = 0x40000d10; +r_h4tl_rx_done = 0x40000d14; +r_h4tl_start = 0x40000d18; +r_h4tl_stop = 0x40000d1c; +r_h4tl_tx_done = 0x40000d20; +r_h4tl_tx_evt_handler = 0x40000d24; +r_h4tl_write = 0x40000d28; +r_hci_acl_tx_data_alloc = 0x40000d2c; +r_hci_acl_tx_data_received = 0x40000d30; +r_hci_basic_cmd_send_2_controller = 0x40000d34; +r_hci_ble_adv_report_filter_check = 0x40000d38; +r_hci_ble_adv_report_tx_check = 0x40000d3c; +r_hci_ble_conhdl_register = 0x40000d40; +r_hci_ble_conhdl_unregister = 0x40000d44; +r_hci_build_acl_data = 0x40000d48; +r_hci_build_cc_evt = 0x40000d4c; +r_hci_build_cs_evt = 0x40000d50; +r_hci_build_evt = 0x40000d54; +r_hci_build_le_evt = 0x40000d58; +r_hci_cmd_get_max_param_size = 0x40000d5c; +r_hci_cmd_received = 0x40000d60; +r_hci_cmd_reject = 0x40000d64; +r_hci_evt_mask_check = 0x40000d68; +r_hci_evt_mask_set = 0x40000d6c; +r_hci_fc_acl_buf_size_set = 0x40000d70; +r_hci_fc_acl_en = 0x40000d74; +r_hci_fc_acl_packet_sent = 0x40000d78; +r_hci_fc_check_host_available_nb_acl_packets = 0x40000d7c; +r_hci_fc_host_nb_acl_pkts_complete = 0x40000d80; +r_hci_fc_init = 0x40000d84; +r_hci_look_for_cmd_desc = 0x40000d88; +r_hci_look_for_evt_desc = 0x40000d8c; +r_hci_look_for_le_evt_desc = 0x40000d90; +r_hci_look_for_le_evt_desc_esp = 0x40000d94; +r_hci_pack_bytes = 0x40000d98; +r_hci_send_2_controller = 0x40000da0; +r_hci_send_2_host = 0x40000da4; +r_hci_tl_c2h_data_flow_on = 0x40000da8; +r_hci_tl_cmd_hdr_rx_evt_handler = 0x40000dac; +r_hci_tl_cmd_pld_rx_evt_handler = 0x40000db0; +r_hci_tl_get_pkt = 0x40000db4; +r_hci_tl_hci_pkt_handler = 0x40000db8; +r_hci_tl_hci_tx_done_evt_handler = 0x40000dbc; +r_hci_tl_inc_nb_h2c_cmd_pkts = 0x40000dc0; +r_hci_tl_save_pkt = 0x40000dc4; +r_hci_tl_send = 0x40000dc8; +r_hci_tx_done = 0x40000dcc; +r_hci_tx_start = 0x40000dd0; +r_hci_tx_trigger = 0x40000dd4; +r_isValidSecretKey_256 = 0x40000dd8; +r_ke_check_malloc = 0x40000ddc; +r_ke_event_callback_set = 0x40000de0; +r_ke_event_clear = 0x40000de4; +r_ke_event_flush = 0x40000de8; +r_ke_event_get = 0x40000dec; +r_ke_event_get_all = 0x40000df0; +r_ke_event_init = 0x40000df4; +r_ke_event_schedule = 0x40000df8; +r_ke_event_set = 0x40000dfc; +r_ke_flush = 0x40000e00; +r_ke_free = 0x40000e04; +r_ke_handler_search = 0x40000e08; +r_ke_init = 0x40000e0c; +r_ke_is_free = 0x40000e10; +r_ke_malloc = 0x40000e14; +r_ke_mem_init = 0x40000e18; +r_ke_mem_is_empty = 0x40000e1c; +r_ke_mem_is_in_heap = 0x40000e20; +r_ke_msg_alloc = 0x40000e24; +r_ke_msg_dest_id_get = 0x40000e28; +r_ke_msg_discard = 0x40000e2c; +r_ke_msg_forward = 0x40000e30; +r_ke_msg_forward_new_id = 0x40000e34; +r_ke_msg_free = 0x40000e38; +r_ke_msg_in_queue = 0x40000e3c; +r_ke_msg_save = 0x40000e40; +r_ke_msg_send = 0x40000e44; +r_ke_msg_send_basic = 0x40000e48; +r_ke_msg_src_id_get = 0x40000e4c; +r_ke_queue_extract = 0x40000e50; +r_ke_queue_insert = 0x40000e54; +r_ke_sleep_check = 0x40000e58; +r_ke_state_get = 0x40000e5c; +r_ke_state_set = 0x40000e60; +r_ke_task_check = 0x40000e64; +r_ke_task_create = 0x40000e68; +r_ke_task_delete = 0x40000e6c; +r_ke_task_handler_get = 0x40000e70; +r_ke_task_init = 0x40000e74; +r_ke_task_msg_flush = 0x40000e78; +r_ke_task_saved_update = 0x40000e7c; +r_ke_time = 0x40000e84; +r_ke_time_cmp = 0x40000e88; +r_ke_time_past = 0x40000e8c; +r_ke_timer_active = 0x40000e90; +r_ke_timer_adjust_all = 0x40000e94; +r_ke_timer_clear = 0x40000e98; +r_ke_timer_init = 0x40000e9c; +r_ke_timer_schedule = 0x40000ea0; +r_ke_timer_set = 0x40000ea4; +r_led_init = 0x40000ea8; +r_led_set_all = 0x40000eac; +r_llc_aes_res_cb = 0x40000eb0; +r_llc_ch_map_up_proc_err_cb = 0x40000eb4; +r_llc_cleanup = 0x40000eb8; +r_llc_cmd_cmp_send = 0x40000ebc; +r_llc_cmd_stat_send = 0x40000ec0; +r_llc_con_move_cbk = 0x40000ec4; +r_llc_con_plan_set_update = 0x40000ec8; +r_llc_con_upd_param_in_range = 0x40000ecc; +r_llc_disconnect = 0x40000ed0; +r_llc_disconnect_end = 0x40000ed4; +r_llc_disconnect_proc_continue = 0x40000ed8; +r_llc_disconnect_proc_err_cb = 0x40000edc; +r_llc_dl_chg_check = 0x40000ee0; +r_llc_dle_proc_err_cb = 0x40000ee4; +r_llc_feats_exch_proc_err_cb = 0x40000ee8; +r_llc_hci_cmd_handler_tab_p_get = 0x40000eec; +r_llc_hci_con_param_req_evt_send = 0x40000ef4; +r_llc_hci_con_upd_info_send = 0x40000ef8; +r_llc_hci_disconnected_dis = 0x40000efc; +r_llc_hci_dl_upd_info_send = 0x40000f00; +r_llc_hci_enc_evt_send = 0x40000f04; +r_llc_hci_feats_info_send = 0x40000f08; +r_llc_hci_le_phy_upd_cmp_evt_send = 0x40000f0c; +r_llc_hci_ltk_request_evt_send = 0x40000f10; +r_llc_hci_nb_cmp_pkts_evt_send = 0x40000f14; +r_llc_hci_version_info_send = 0x40000f18; +r_llc_init_term_proc = 0x40000f1c; +r_llc_iv_skd_rand_gen = 0x40000f20; +r_llc_le_ping_proc_continue = 0x40000f24; +r_llc_le_ping_proc_err_cb = 0x40000f28; +/* r_llc_le_ping_restart = 0x40000f2c; */ +r_llc_le_ping_set = 0x40000f30; +r_llc_ll_pause_enc_rsp_ack_handler = 0x40000f34; +r_llc_ll_reject_ind_ack_handler = 0x40000f38; +r_llc_ll_reject_ind_pdu_send = 0x40000f3c; +r_llc_ll_start_enc_rsp_ack_handler = 0x40000f40; +r_llc_ll_terminate_ind_ack = 0x40000f44; +r_llc_ll_unknown_ind_handler = 0x40000f48; +r_llc_llcp_send = 0x40000f4c; +r_llc_llcp_state_set = 0x40000f50; +r_llc_llcp_trans_timer_set = 0x40000f54; +r_llc_llcp_tx_check = 0x40000f58; +r_llc_loc_con_upd_proc_err_cb = 0x40000f64; +r_llc_loc_dl_upd_proc_continue = 0x40000f68; +r_llc_loc_encrypt_proc_continue = 0x40000f6c; +r_llc_loc_encrypt_proc_err_cb = 0x40000f70; +r_llc_loc_feats_exch_proc_continue = 0x40000f74; +r_llc_loc_phy_upd_proc_err_cb = 0x40000f7c; +r_llc_msg_handler_tab_p_get = 0x40000f80; +r_llc_pref_param_compute = 0x40000f84; +r_llc_proc_collision_check = 0x40000f88; +r_llc_proc_err_ind = 0x40000f8c; +r_llc_proc_get = 0x40000f90; +r_llc_proc_id_get = 0x40000f94; +r_llc_proc_reg = 0x40000f98; +r_llc_proc_state_get = 0x40000f9c; +r_llc_proc_state_set = 0x40000fa0; +r_llc_proc_timer_pause_set = 0x40000fa4; +r_llc_proc_timer_set = 0x40000fa8; +r_llc_proc_unreg = 0x40000fac; +r_llc_rem_ch_map_proc_continue = 0x40000fb0; +r_llc_rem_con_upd_proc_err_cb = 0x40000fb8; +r_llc_rem_dl_upd_proc = 0x40000fbc; +r_llc_rem_encrypt_proc_continue = 0x40000fc0; +r_llc_rem_encrypt_proc_err_cb = 0x40000fc4; +r_llc_rem_phy_upd_proc_continue = 0x40000fc8; +r_llc_rem_phy_upd_proc_err_cb = 0x40000fcc; +r_llc_role_get = 0x40000fd0; +r_llc_sk_gen = 0x40000fd4; +r_llc_start = 0x40000fd8; +r_llc_stop = 0x40000fdc; +r_llc_ver_exch_loc_proc_continue = 0x40000fe0; +r_llc_ver_proc_err_cb = 0x40000fe4; +r_llcp_pdu_handler_tab_p_get = 0x40000fe8; +r_lld_aa_gen = 0x40000fec; +r_lld_adv_adv_data_set = 0x40000ff0; +r_lld_adv_adv_data_update = 0x40000ff4; +r_lld_adv_aux_ch_idx_set = 0x40000ff8; +r_lld_adv_aux_evt_canceled_cbk = 0x40000ffc; +r_lld_adv_aux_evt_start_cbk = 0x40001000; +r_lld_adv_coex_check_ext_adv_synced = 0x40001004; +r_lld_adv_coex_env_reset = 0x40001008; +r_lld_adv_duration_update = 0x4000100c; +r_lld_adv_dynamic_pti_process = 0x40001010; +r_lld_adv_end = 0x40001014; +r_lld_adv_evt_canceled_cbk = 0x40001018; +r_lld_adv_evt_start_cbk = 0x4000101c; +r_lld_adv_ext_chain_construct = 0x40001020; +r_lld_adv_ext_pkt_prepare = 0x40001024; +r_lld_adv_frm_cbk = 0x40001028; +r_lld_adv_frm_isr = 0x4000102c; +r_lld_adv_frm_skip_isr = 0x40001030; +r_lld_adv_init = 0x40001034; +r_lld_adv_pkt_rx = 0x40001038; +r_lld_adv_pkt_rx_connect_ind = 0x4000103c; +r_lld_adv_pkt_rx_send_scan_req_evt = 0x40001040; +r_lld_adv_rand_addr_update = 0x40001044; +r_lld_adv_restart = 0x40001048; +r_lld_adv_scan_rsp_data_set = 0x4000104c; +r_lld_adv_scan_rsp_data_update = 0x40001050; +r_lld_adv_set_tx_power = 0x40001054; +r_lld_adv_start = 0x40001058; +r_lld_adv_stop = 0x4000105c; +r_lld_adv_sync_info_set = 0x40001060; +r_lld_adv_sync_info_update = 0x40001064; +r_lld_calc_aux_rx = 0x40001068; +r_lld_cca_alloc = 0x4000106c; +r_lld_cca_data_reset = 0x40001070; +r_lld_cca_free = 0x40001074; +r_lld_ch_assess_data_get = 0x40001078; +r_lld_ch_idx_get = 0x4000107c; +r_lld_ch_map_set = 0x40001080; +r_lld_channel_assess = 0x40001084; +r_lld_con_activity_act_offset_compute = 0x40001088; +r_lld_con_activity_offset_compute = 0x4000108c; +r_lld_con_ch_map_update = 0x40001090; +r_lld_con_cleanup = 0x40001094; +r_lld_con_current_tx_power_get = 0x40001098; +r_lld_con_data_flow_set = 0x4000109c; +r_lld_con_data_len_update = 0x400010a0; +r_lld_con_data_tx = 0x400010a4; +r_lld_con_enc_key_load = 0x400010a8; +r_lld_con_event_counter_get = 0x400010ac; +r_lld_con_evt_canceled_cbk = 0x400010b0; +r_lld_con_evt_duration_min_get = 0x400010b4; +r_lld_con_evt_max_eff_time_cal = 0x400010b8; +r_lld_con_evt_sd_evt_time_get = 0x400010bc; +r_lld_con_evt_start_cbk = 0x400010c0; +r_lld_con_evt_time_update = 0x400010c4; +r_lld_con_free_all_tx_buf = 0x400010c8; +r_lld_con_frm_cbk = 0x400010cc; +r_lld_con_frm_isr = 0x400010d0; +r_lld_con_frm_skip_isr = 0x400010d4; +r_lld_con_init = 0x400010d8; +r_lld_con_llcp_tx = 0x400010dc; +r_lld_con_max_lat_calc = 0x400010e0; +r_lld_con_offset_get = 0x400010e4; +r_lld_con_param_update = 0x400010e8; +r_lld_con_phys_update = 0x400010ec; +r_lld_con_pref_slave_evt_dur_set = 0x400010f0; +r_lld_con_pref_slave_latency_set = 0x400010f4; +r_lld_con_rssi_get = 0x400010f8; +r_lld_con_rx = 0x400010fc; +/* r_lld_con_rx_channel_assess = 0x40001100; */ +r_lld_con_rx_enc = 0x40001104; +r_lld_con_rx_isr = 0x40001108; +r_lld_con_rx_link_info_check = 0x4000110c; +r_lld_con_rx_llcp_check = 0x40001110; +r_lld_con_rx_sync_time_update = 0x40001114; +r_lld_con_set_tx_power = 0x4000111c; +r_lld_con_start = 0x40001120; +r_lld_con_tx = 0x40001128; +r_lld_con_tx_enc = 0x4000112c; +r_lld_con_tx_isr = 0x40001130; +r_lld_con_tx_len_update = 0x40001134; +r_lld_con_tx_len_update_for_intv = 0x40001138; +r_lld_con_tx_len_update_for_rate = 0x4000113c; +r_lld_con_tx_prog = 0x40001140; +r_lld_conn_dynamic_pti_process = 0x40001144; +r_lld_continue_scan_rx_isr_end_process = 0x40001148; +r_lld_ext_scan_dynamic_pti_process = 0x4000114c; +r_lld_hw_cca_end_isr = 0x40001150; +r_lld_hw_cca_evt_handler = 0x40001154; +r_lld_hw_cca_isr = 0x40001158; +r_lld_init_cal_anchor_point = 0x4000115c; +r_lld_init_compute_winoffset = 0x40001160; +r_lld_init_connect_req_pack = 0x40001164; +r_lld_init_end = 0x40001168; +r_lld_init_evt_canceled_cbk = 0x4000116c; +r_lld_init_evt_start_cbk = 0x40001170; +r_lld_init_frm_cbk = 0x40001174; +r_lld_init_frm_eof_isr = 0x40001178; +r_lld_init_frm_skip_isr = 0x4000117c; +r_lld_init_init = 0x40001180; +r_lld_init_process_pkt_rx = 0x40001184; +r_lld_init_process_pkt_rx_adv_ext_ind = 0x40001188; +r_lld_init_process_pkt_rx_adv_ind_or_direct_ind = 0x4000118c; +r_lld_init_process_pkt_rx_aux_connect_rsp = 0x40001190; +r_lld_init_process_pkt_tx = 0x40001194; +r_lld_init_process_pkt_tx_cal_con_timestamp = 0x40001198; +r_lld_init_sched = 0x4000119c; +r_lld_init_set_tx_power = 0x400011a0; +r_lld_init_start = 0x400011a4; +r_lld_init_stop = 0x400011a8; +r_lld_instant_proc_end = 0x400011ac; +r_lld_per_adv_ch_map_update = 0x400011b4; +r_lld_per_adv_chain_construct = 0x400011b8; +r_lld_per_adv_cleanup = 0x400011bc; +r_lld_per_adv_coex_env_reset = 0x400011c0; +r_lld_per_adv_data_set = 0x400011c4; +r_lld_per_adv_data_update = 0x400011c8; +r_lld_per_adv_dynamic_pti_process = 0x400011cc; +r_lld_per_adv_evt_canceled_cbk = 0x400011d0; +r_lld_per_adv_evt_start_cbk = 0x400011d4; +r_lld_per_adv_ext_pkt_prepare = 0x400011d8; +r_lld_per_adv_frm_cbk = 0x400011dc; +r_lld_per_adv_frm_isr = 0x400011e0; +r_lld_per_adv_frm_skip_isr = 0x400011e4; +r_lld_per_adv_init = 0x400011e8; +r_lld_per_adv_init_info_get = 0x400011ec; +r_lld_per_adv_list_add = 0x400011f0; +r_lld_per_adv_list_rem = 0x400011f4; +r_lld_per_adv_set_tx_power = 0x400011fc; +r_lld_per_adv_start = 0x40001200; +r_lld_per_adv_stop = 0x40001204; +r_lld_per_adv_sync_info_get = 0x40001208; +r_lld_process_cca_data = 0x4000120c; +r_lld_ral_search = 0x40001210; +r_lld_read_clock = 0x40001214; +r_lld_res_list_add = 0x40001218; +r_lld_res_list_is_empty = 0x40001220; +r_lld_res_list_local_rpa_get = 0x40001224; +r_lld_res_list_peer_rpa_get = 0x40001228; +r_lld_res_list_peer_update = 0x4000122c; +/* r_lld_res_list_priv_mode_update = 0x40001230; */ +r_lld_reset_reg = 0x40001238; +r_lld_rpa_renew = 0x4000123c; +r_lld_rpa_renew_evt_canceled_cbk = 0x40001240; +r_lld_rpa_renew_evt_start_cbk = 0x40001244; +r_lld_rpa_renew_instant_cbk = 0x40001248; +r_lld_rxdesc_check = 0x4000124c; +r_lld_rxdesc_free = 0x40001250; +r_lld_scan_create_sync = 0x40001254; +r_lld_scan_create_sync_cancel = 0x40001258; +r_lld_scan_end = 0x4000125c; +r_lld_scan_evt_canceled_cbk = 0x40001260; +r_lld_scan_evt_start_cbk = 0x40001264; +r_lld_scan_frm_cbk = 0x40001268; +r_lld_scan_frm_eof_isr = 0x4000126c; +r_lld_scan_frm_rx_isr = 0x40001270; +r_lld_scan_frm_skip_isr = 0x40001274; +r_lld_scan_init = 0x40001278; +r_lld_scan_params_update = 0x4000127c; +r_lld_scan_process_pkt_rx_aux_adv_ind = 0x40001288; +r_lld_scan_process_pkt_rx_aux_chain_ind = 0x4000128c; +r_lld_scan_process_pkt_rx_aux_scan_rsp = 0x40001290; +r_lld_scan_process_pkt_rx_ext_adv = 0x40001294; +r_lld_scan_process_pkt_rx_ext_adv_ind = 0x40001298; +r_lld_scan_process_pkt_rx_legacy_adv = 0x4000129c; +r_lld_scan_restart = 0x400012a0; +r_lld_scan_sched = 0x400012a4; +r_lld_scan_set_tx_power = 0x400012a8; +r_lld_scan_start = 0x400012ac; +r_lld_scan_stop = 0x400012b0; +r_lld_scan_sync_accept = 0x400012b4; +r_lld_scan_sync_info_unpack = 0x400012b8; +r_lld_scan_trunc_ind = 0x400012bc; +r_lld_sw_cca_evt_handler = 0x400012c0; +r_lld_sw_cca_isr = 0x400012c4; +r_lld_sync_ch_map_update = 0x400012c8; +r_lld_sync_cleanup = 0x400012cc; +r_lld_sync_evt_canceled_cbk = 0x400012d0; +r_lld_sync_evt_start_cbk = 0x400012d4; +r_lld_sync_frm_cbk = 0x400012d8; +r_lld_sync_frm_eof_isr = 0x400012dc; +r_lld_sync_frm_rx_isr = 0x400012e0; +r_lld_sync_frm_skip_isr = 0x400012e4; +r_lld_sync_init = 0x400012e8; +r_lld_sync_process_pkt_rx = 0x400012ec; +r_lld_sync_process_pkt_rx_aux_sync_ind = 0x400012f0; +r_lld_sync_process_pkt_rx_pkt_check = 0x400012f4; +r_lld_sync_scan_dynamic_pti_process = 0x400012f8; +r_lld_sync_sched = 0x400012fc; +r_lld_sync_start = 0x40001300; +r_lld_sync_stop = 0x40001304; +r_lld_sync_trunc_ind = 0x40001308; +r_lld_test_cleanup = 0x4000130c; +r_lld_test_evt_canceled_cbk = 0x40001310; +r_lld_test_evt_start_cbk = 0x40001314; +r_lld_test_freq2chnl = 0x40001318; +r_lld_test_frm_cbk = 0x4000131c; +r_lld_test_frm_isr = 0x40001320; +r_lld_test_init = 0x40001324; +r_lld_test_rx_isr = 0x40001328; +r_lld_test_set_tx_power = 0x4000132c; +r_lld_test_start = 0x40001330; +/* r_lld_test_stop = 0x40001334; */ +r_lld_update_rxbuf = 0x40001338; +r_lld_update_rxbuf_isr = 0x4000133c; +r_lld_white_list_add = 0x40001340; +r_lld_white_list_rem = 0x40001344; +r_llm_activity_free_get = 0x40001348; +r_llm_activity_free_set = 0x4000134c; +r_llm_activity_syncing_get = 0x40001350; +r_llm_adv_con_len_check = 0x40001354; +r_llm_adv_hdl_to_id = 0x40001358; +r_llm_adv_rep_flow_control_check = 0x4000135c; +r_llm_adv_rep_flow_control_update = 0x40001360; +r_llm_adv_reports_list_check = 0x40001364; +r_llm_adv_set_all_release = 0x40001368; +r_llm_adv_set_dft_params = 0x4000136c; +r_llm_adv_set_release = 0x40001370; +r_llm_aes_res_cb = 0x40001374; +r_llm_ble_update_adv_flow_control = 0x40001378; +r_llm_ch_map_update = 0x4000137c; +r_llm_cmd_cmp_send = 0x40001380; +r_llm_cmd_stat_send = 0x40001384; +r_llm_dev_list_empty_entry = 0x40001388; +r_llm_dev_list_search = 0x4000138c; +r_llm_env_adv_dup_filt_deinit = 0x40001390; +r_llm_env_adv_dup_filt_init = 0x40001394; +r_llm_init_ble_adv_report_flow_contol = 0x40001398; +r_llm_is_dev_connected = 0x4000139c; +r_llm_is_dev_synced = 0x400013a0; +r_llm_is_non_con_act_ongoing_check = 0x400013a4; +r_llm_is_wl_accessible = 0x400013a8; +r_llm_le_evt_mask_check = 0x400013ac; +r_llm_link_disc = 0x400013b4; +r_llm_master_ch_map_get = 0x400013b8; +r_llm_msg_handler_tab_p_get = 0x400013bc; +r_llm_no_activity = 0x400013c0; +r_llm_per_adv_slot_dur = 0x400013c4; +r_llm_plan_elt_get = 0x400013c8; +r_llm_rx_path_comp_get = 0x400013cc; +r_llm_scan_start = 0x400013d0; +r_llm_scan_sync_acad_attach = 0x400013d4; +r_llm_scan_sync_acad_detach = 0x400013d8; +r_llm_send_adv_lost_event_to_host = 0x400013dc; +r_llm_tx_path_comp_get = 0x400013e0; +r_misc_deinit = 0x400013e4; +r_misc_free_em_buf_in_isr = 0x400013e8; +r_misc_init = 0x400013ec; +r_misc_msg_handler_tab_p_get = 0x400013f0; +r_notEqual256 = 0x400013f4; +r_phy_upd_proc_start = 0x400013f8; +r_platform_reset = 0x400013fc; +r_rf_em_init = 0x40001404; +r_rf_force_agc_enable = 0x40001408; +r_rf_reg_rd = 0x4000140c; +r_rf_reg_wr = 0x40001410; +r_rf_reset = 0x40001414; +r_rf_rssi_convert = 0x40001418; +r_rf_rw_v9_le_disable = 0x4000141c; +r_rf_rw_v9_le_enable = 0x40001420; +r_rf_sleep = 0x40001424; +r_rf_util_cs_fmt_convert = 0x40001430; +r_rw_crypto_aes_ccm = 0x40001434; +r_rw_crypto_aes_encrypt = 0x40001438; +r_rw_crypto_aes_init = 0x4000143c; +r_rw_crypto_aes_k1 = 0x40001440; +r_rw_crypto_aes_k2 = 0x40001444; +r_rw_crypto_aes_k3 = 0x40001448; +r_rw_crypto_aes_k4 = 0x4000144c; +r_rw_crypto_aes_rand = 0x40001450; +r_rw_crypto_aes_result_handler = 0x40001454; +r_rw_crypto_aes_s1 = 0x40001458; +r_rw_cryto_aes_cmac = 0x4000145c; +r_rw_v9_init_em_radio_table = 0x40001460; +r_rwble_sleep_enter = 0x40001468; +r_rwble_sleep_wakeup_end = 0x4000146c; +/* r_rwbtdm_isr_wrapper = 0x40001470; */ +r_rwip_active_check = 0x40001474; +r_rwip_aes_encrypt = 0x40001478; +/* r_rwip_assert = 0x4000147c; */ +r_rwip_crypt_evt_handler = 0x40001480; +r_rwip_crypt_isr_handler = 0x40001484; +r_rwip_eif_get = 0x40001488; +r_rwip_half_slot_2_lpcycles = 0x4000148c; +r_rwip_hus_2_lpcycles = 0x40001490; +r_rwip_isr = 0x40001494; +r_rwip_lpcycles_2_hus = 0x40001498; +r_rwip_prevent_sleep_clear = 0x4000149c; +r_rwip_prevent_sleep_set = 0x400014a0; +r_rwip_schedule = 0x400014a4; +r_rwip_sleep = 0x400014a8; +r_rwip_sw_int_handler = 0x400014ac; +r_rwip_sw_int_req = 0x400014b0; +r_rwip_time_get = 0x400014b4; +r_rwip_timer_10ms_handler = 0x400014b8; +r_rwip_timer_10ms_set = 0x400014bc; +r_rwip_timer_hs_handler = 0x400014c0; +r_rwip_timer_hs_set = 0x400014c4; +r_rwip_timer_hus_handler = 0x400014c8; +r_rwip_timer_hus_set = 0x400014cc; +r_rwip_wakeup = 0x400014d0; +/* r_rwip_wakeup_end = 0x400014d4; */ +r_rwip_wlcoex_set = 0x400014d8; +r_sch_alarm_clear = 0x400014dc; +r_sch_alarm_init = 0x400014e0; +r_sch_alarm_prog = 0x400014e4; +r_sch_alarm_set = 0x400014e8; +r_sch_alarm_timer_isr = 0x400014ec; +r_sch_arb_conflict_check = 0x400014f0; +r_sch_arb_elt_cancel = 0x400014f4; +r_sch_arb_init = 0x400014fc; +r_sch_arb_insert = 0x40001500; +r_sch_arb_prog_timer = 0x40001504; +r_sch_arb_remove = 0x40001508; +r_sch_arb_sw_isr = 0x4000150c; +r_sch_plan_chk = 0x40001510; +r_sch_plan_clock_wrap_offset_update = 0x40001514; +r_sch_plan_init = 0x40001518; +r_sch_plan_interval_req = 0x4000151c; +r_sch_plan_offset_max_calc = 0x40001520; +r_sch_plan_offset_req = 0x40001524; +r_sch_plan_position_range_compute = 0x40001528; +r_sch_plan_rem = 0x4000152c; +r_sch_plan_req = 0x40001530; +r_sch_prog_init = 0x4000153c; +r_sch_prog_push = 0x40001540; +r_sch_prog_rx_isr = 0x40001544; +r_sch_prog_skip_isr = 0x40001548; +r_sch_prog_tx_isr = 0x4000154c; +r_sch_slice_bg_add = 0x40001550; +r_sch_slice_bg_remove = 0x40001554; +r_sch_slice_compute = 0x40001558; +r_sch_slice_fg_add = 0x4000155c; +r_sch_slice_fg_remove = 0x40001560; +r_sch_slice_init = 0x40001564; +r_sch_slice_per_add = 0x40001568; +r_sch_slice_per_remove = 0x4000156c; +r_sdk_config_get_bt_sleep_enable = 0x40001570; +r_sdk_config_get_hl_derived_opts = 0x40001574; +r_sdk_config_get_opts = 0x40001578; +r_sdk_config_get_priv_opts = 0x4000157c; +r_sdk_config_set_bt_sleep_enable = 0x40001580; +r_sdk_config_set_hl_derived_opts = 0x40001584; +r_sdk_config_set_opts = 0x40001588; +r_specialModP256 = 0x4000158c; +r_unloaded_area_init = 0x40001590; +r_vhci_flow_off = 0x40001594; +r_vhci_flow_on = 0x40001598; +r_vhci_notify_host_send_available = 0x4000159c; +r_vhci_send_to_host = 0x400015a0; +r_vnd_hci_command_handler = 0x400015a4; +r_vshci_init = 0x400015a8; +vnd_hci_command_handler_wrapper = 0x400015ac; + +/* bluetooth hook funcs */ +r_llc_loc_encrypt_proc_continue_hook = 0x40001c60; +r_llc_loc_phy_upd_proc_continue_hook = 0x40001c64; +r_llc_rem_phy_upd_proc_continue_hook = 0x40001c68; +r_lld_scan_frm_eof_isr_hook = 0x40001c6c; +r_lld_scan_evt_start_cbk_hook = 0x40001c70; +r_lld_scan_process_pkt_rx_ext_adv_hook = 0x40001c78; +r_lld_scan_sched_hook = 0x40001c7c; +r_lld_adv_evt_start_cbk_hook = 0x40001c84; +r_lld_adv_aux_evt_start_cbk_hook = 0x40001c88; +r_lld_adv_frm_isr_hook = 0x40001c8c; +r_lld_adv_start_init_evt_param_hook = 0x40001c90; +r_lld_con_evt_canceled_cbk_hook = 0x40001c94; +r_lld_con_frm_isr_hook = 0x40001c98; +r_lld_con_tx_hook = 0x40001c9c; +r_lld_con_rx_hook = 0x40001ca0; +r_lld_con_evt_start_cbk_hook = 0x40001ca4; +r_lld_con_tx_prog_new_packet_hook = 0x40001cac; +r_lld_init_frm_eof_isr_hook = 0x40001cb0; +r_lld_init_evt_start_cbk_hook = 0x40001cb4; +r_lld_init_sched_hook = 0x40001cbc; +r_lld_init_process_pkt_tx_hook = 0x40001cc0; +r_lld_per_adv_evt_start_cbk_hook = 0x40001cc4; +r_lld_per_adv_frm_isr_hook = 0x40001cc8; +r_lld_per_adv_start_hook = 0x40001ccc; +r_lld_sync_frm_eof_isr_hook = 0x40001cd0; +r_lld_sync_evt_start_cbk_hook = 0x40001cd4; +r_lld_sync_start_hook = 0x40001cd8; +r_lld_sync_process_pkt_rx_pkt_check_hook = 0x40001cdc; +r_sch_arb_insert_hook = 0x40001ce0; +r_sch_plan_offset_req_hook = 0x40001ce4; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.eco3.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.eco3.ld index 3568b2d6e8da..edad2237dc73 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.eco3.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.eco3.ld @@ -44,38 +44,6 @@ ppProcTxCallback = 0x40001b30; ieee80211_gettid = 0x40001b34; -/*************************************** - Group eco3_bluetooth - ***************************************/ - -/* Functions */ -r_lld_legacy_adv_dynamic_pti_get = 0x40001b38; -r_lld_legacy_adv_dynamic_pti_process = 0x40001b3c; -r_lld_ext_adv_dynamic_pti_get = 0x40001b40; -r_lld_ext_adv_dynamic_aux_pti_process = 0x40001b44; -r_lld_ext_adv_dynamic_pti_process = 0x40001b48; -r_lld_adv_ext_pkt_prepare_set = 0x40001b4c; -r_lld_adv_ext_chain_connectable_construct = 0x40001b54; -r_lld_adv_pkt_rx_connect_post = 0x40001b5c; -r_lld_adv_start_init_evt_param = 0x40001b60; -r_lld_adv_start_set_cs = 0x40001b64; -/* r_lld_adv_start_update_filter_policy = 0x40001b68; */ -r_lld_adv_start_schedule_asap = 0x40001b6c; -r_lld_con_tx_prog_new_packet_coex = 0x40001b70; -r_lld_per_adv_dynamic_pti_get = 0x40001b78; -r_lld_per_adv_evt_start_chm_upd = 0x40001b7c; -r_lld_ext_scan_dynamic_pti_get = 0x40001b80; -r_lld_sync_insert = 0x40001b88; -r_sch_prog_ble_push = 0x40001b8c; -r_sch_prog_bt_push = 0x40001b90; -r_lld_init_evt_end_type_set = 0x40001b94; -r_lld_init_evt_end_type_get = 0x40001b98; -r_lld_adv_direct_adv_use_rpa_addr_state_set = 0x40001b9c; -r_lld_adv_direct_adv_use_rpa_addr_state_get = 0x40001ba0; -r_lld_init_evt_end_type_check_state_set = 0x40001ba4; -r_lld_init_evt_end_type_check_state_get = 0x40001ba8; - - /*************************************** Group eco3_phy ***************************************/ diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.eco3_bt_funcs.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.eco3_bt_funcs.ld new file mode 100644 index 000000000000..6f67b8ddc33c --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.eco3_bt_funcs.ld @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* +ESP32C3 ECO3 ROM address table +Version 3 API's imported from the ROM +*/ + + +/*************************************** + Group eco3_bluetooth + ***************************************/ + +/* Functions */ +r_lld_legacy_adv_dynamic_pti_get = 0x40001b38; +r_lld_legacy_adv_dynamic_pti_process = 0x40001b3c; +r_lld_ext_adv_dynamic_pti_get = 0x40001b40; +r_lld_ext_adv_dynamic_aux_pti_process = 0x40001b44; +r_lld_ext_adv_dynamic_pti_process = 0x40001b48; +/* +r_lld_adv_ext_pkt_prepare_set = 0x40001b4c; +*/ +r_lld_adv_ext_chain_connectable_construct = 0x40001b54; +r_lld_adv_pkt_rx_connect_post = 0x40001b5c; +r_lld_adv_start_init_evt_param = 0x40001b60; +r_lld_adv_start_set_cs = 0x40001b64; +/* r_lld_adv_start_update_filter_policy = 0x40001b68; */ +r_lld_adv_start_schedule_asap = 0x40001b6c; +r_lld_con_tx_prog_new_packet_coex = 0x40001b70; +r_lld_per_adv_dynamic_pti_get = 0x40001b78; +r_lld_per_adv_evt_start_chm_upd = 0x40001b7c; +r_lld_ext_scan_dynamic_pti_get = 0x40001b80; +r_lld_sync_insert = 0x40001b88; +/* +r_sch_prog_ble_push = 0x40001b8c; +*/ +r_sch_prog_bt_push = 0x40001b90; +r_lld_init_evt_end_type_set = 0x40001b94; +r_lld_init_evt_end_type_get = 0x40001b98; +r_lld_adv_direct_adv_use_rpa_addr_state_set = 0x40001b9c; +r_lld_adv_direct_adv_use_rpa_addr_state_get = 0x40001ba0; +r_lld_init_evt_end_type_check_state_set = 0x40001ba4; +r_lld_init_evt_end_type_check_state_get = 0x40001ba8; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.eco7.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.eco7.ld index 69df558be7ec..41445a1b5431 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.eco7.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.eco7.ld @@ -93,132 +93,6 @@ rom1_phy_close_rf = 0x40001c18; uart_tx_switch = 0x40001c44; -/*************************************** - Group eco7_bluetooth - ***************************************/ - -/* Functions */ -r_lld_con_count_get = 0x40001c48; -r_lld_update_con_offset = 0x40001c4c; -r_lld_con_update_last_clock = 0x40001c50; -r_lld_con_llcp_ind_info_clear = 0x40001c54; -r_lld_con_update_terminte_info_init = 0x40001c58; -r_lld_con_terminate_max_evt_update = 0x40001c5c; -r_llc_pref_param_compute_eco = 0x40001ce8; -r_llc_hci_con_upd_info_send_eco = 0x40001cec; -r_llc_rem_encrypt_proc_continue_eco = 0x40001cf0; -r_llc_start_eco = 0x40001cf8; -r_lld_ext_adv_dynamic_aux_pti_process_eco = 0x40001cfc; -r_lld_adv_start_eco = 0x40001d04; -r_lld_con_evt_canceled_cbk_eco = 0x40001d08; -r_lld_con_evt_time_update_eco = 0x40001d0c; -r_lld_con_start_eco = 0x40001d10; -r_lld_con_frm_isr_eco = 0x40001d14; -r_lld_con_tx_eco = 0x40001d18; -r_lld_ext_scan_dynamic_pti_process_eco = 0x40001d28; -r_lld_scan_frm_eof_isr_eco = 0x40001d2c; -r_lld_sync_start_eco = 0x40001d30; -r_lld_sync_insert_eco = 0x40001d34; -r_llm_adv_rep_flow_control_update_eco = 0x40001d38; -r_llm_env_adv_dup_filt_init_eco = 0x40001d3c; -r_llm_env_adv_dup_filt_deinit_eco = 0x40001d40; -r_llm_adv_rep_flow_control_check_eco = 0x40001d44; -r_llm_scan_start_eco = 0x40001d48; -r_llm_update_duplicate_scan_count = 0x40001d4c; -r_llc_hci_command_handler_pre = 0x40001d50; -r_llc_hci_command_handler_get = 0x40001d54; -r_llc_hci_command_handler_search = 0x40001d58; -r_llc_llcp_pdu_handler_get_overwrite = 0x40001d5c; -r_llc_llcp_pdu_handler_pre = 0x40001d60; -r_llc_llcp_pdu_handler_end = 0x40001d64; -r_llc_con_conflict_check = 0x40001d6c; -r_sch_prog_hw_reset_try = 0x40001d70; -r_sch_prog_et_state_reset = 0x40001d74; -r_sch_prog_end_isr_handler = 0x40001d78; -r_sch_plan_conflict_check = 0x40001d7c; -r_rwble_isr_hw_fixed = 0x40001d80; -r_bt_bb_recorrect_is_dead = 0x40001d84; -r_bt_bb_restart_hw_recorrect = 0x40001d88; -r_ke_task_handler_pre = 0x40001da0; -r_ke_task_handler_end = 0x40001da4; -r_lld_scan_frm_skip_isr_eco = 0x40001db0; -r_lld_ext_scan_dynamic_pti_reset = 0x40001db4; -r_llc_rem_phy_upd_proc_continue_eco = 0x40001db8; -r_llm_get_preferred_phys = 0x40001dbc; -r_lld_hw_cca_isr_eco = 0x40001dc0; -r_lld_sw_cca_isr_eco = 0x40001dc4; -r_lld_cca_chan_prn_e = 0x40001dc8; -r_lld_cca_chan_prn_s = 0x40001dcc; -r_lld_cca_chan_sel_remap = 0x40001dd0; -r_lld_cca_chan_sel_1 = 0x40001dd4; -r_lld_cca_chan_sel_2 = 0x40001dd8; -r_lld_cca_set_thresh = 0x40001ddc; -r_lld_cca_con_start = 0x40001de0; -r_lld_cca_con_end = 0x40001de4; -r_lld_cca_chm_restore = 0x40001de8; -r_lld_cca_chan_unused_check = 0x40001dec; -r_lld_cca_chm_update_check = 0x40001df0; -r_lld_cca_busy_mode_handle = 0x40001df4; -r_lld_cca_lbt_handle = 0x40001df8; -r_lld_cca_scst_timeout_check = 0x40001dfc; -r_lld_cca_chan_avl_timeout_check = 0x40001e00; - -r_lld_con_start_hook = 0x40001ca8; - -/* ble Functions eco */ -r_bt_bb_isr = 0x40000b9c; -r_bt_rf_coex_conn_phy_coded_data_time_limit_en_get = 0x40000ba8; -r_bt_rtp_get_txpwr_idx_by_act = 0x40000c00; -r_btdm_task_post = 0x40000c14; -r_btdm_task_post_from_isr = 0x40000c18; -r_btdm_task_recycle = 0x40000c1c; -r_hci_register_vendor_desc_tab = 0x40000d9c; -r_ke_task_schedule = 0x40000e80; -r_llc_hci_command_handler = 0x40000ef0; -r_llc_loc_ch_map_proc_continue = 0x40000f5c; -r_llc_loc_con_upd_proc_continue = 0x40000f60; -r_llc_loc_phy_upd_proc_continue = 0x40000f78; -r_llc_rem_con_upd_proc_continue = 0x40000fb4; -r_lld_con_sched = 0x40001118; -r_lld_con_stop = 0x40001124; -r_lld_llcp_rx_ind_handler = 0x400011b0; -r_lld_per_adv_sched = 0x400011f8; -r_lld_scan_process_pkt_rx_adv_rep = 0x40001284; -r_register_esp_vendor_cmd_handler = 0x40001400; -r_rf_txpwr_cs_get = 0x40001428; -r_rf_txpwr_dbm_get = 0x4000142c; -r_sch_arb_event_start_isr = 0x400014f8; -r_sch_plan_set = 0x40001534; -r_sch_prog_end_isr = 0x40001538; -r_lld_adv_ext_chain_scannable_construct = 0x40001b58; - -r_lld_scan_process_pkt_rx = 0x40001280; -r_llm_le_features_get = 0x400013b0; - -/* ble functions rename */ -r_lld_init_start_hack = 0x400011a4; - -/* ble functions disable */ -/* -r_lld_adv_frm_isr_eco = 0x40001d00; -r_lld_res_list_clear = 0x40004638; -r_lld_res_list_rem = 0x40004680; -r_lld_adv_start_hook = 0x40001c80; -r_lld_con_evt_start_cbk_eco = 0x40001d1c; -r_lld_con_tx_prog_new_packet = 0x40001b74; -r_lld_adv_ext_chain_none_construct = 0x40001b50; -r_llc_llcp_send_eco = 0x40001cf4; -r_llc_llcp_channel_map_ind_ack = 0x40001d68; -r_rwble_isr = 0x40001464; -r_lld_scan_start_eco = 0x40001d24; -r_lld_scan_try_sched_eco = 0x40001dac; -r_lld_scan_start_hook = 0x40001c74; -r_lld_init_start_hook = 0x40001cb8; -r_lld_scan_evt_start_cbk_eco = 0x40001d20; -r_ke_task_handler_get_overwrite = 0x40001da8; -*/ - - /*************************************** Group eco7_phy ***************************************/ diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.eco7_bt_funcs.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.eco7_bt_funcs.ld new file mode 100644 index 000000000000..33b0ed595d6b --- /dev/null +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.eco7_bt_funcs.ld @@ -0,0 +1,130 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/*************************************** + Group eco7_bluetooth + ***************************************/ + +/* Functions */ +r_lld_con_count_get = 0x40001c48; +r_lld_update_con_offset = 0x40001c4c; +r_lld_con_update_last_clock = 0x40001c50; +r_lld_con_llcp_ind_info_clear = 0x40001c54; +r_lld_con_update_terminte_info_init = 0x40001c58; +r_lld_con_terminate_max_evt_update = 0x40001c5c; +r_llc_pref_param_compute_eco = 0x40001ce8; +r_llc_hci_con_upd_info_send_eco = 0x40001cec; +r_llc_rem_encrypt_proc_continue_eco = 0x40001cf0; +r_llc_start_eco = 0x40001cf8; +r_lld_ext_adv_dynamic_aux_pti_process_eco = 0x40001cfc; +r_lld_adv_start_eco = 0x40001d04; +r_lld_con_evt_canceled_cbk_eco = 0x40001d08; +r_lld_con_evt_time_update_eco = 0x40001d0c; +r_lld_con_start_eco = 0x40001d10; +r_lld_con_frm_isr_eco = 0x40001d14; +r_lld_con_tx_eco = 0x40001d18; +r_lld_ext_scan_dynamic_pti_process_eco = 0x40001d28; +r_lld_scan_frm_eof_isr_eco = 0x40001d2c; +r_lld_sync_start_eco = 0x40001d30; +r_lld_sync_insert_eco = 0x40001d34; +r_llm_adv_rep_flow_control_update_eco = 0x40001d38; +r_llm_env_adv_dup_filt_init_eco = 0x40001d3c; +r_llm_env_adv_dup_filt_deinit_eco = 0x40001d40; +r_llm_adv_rep_flow_control_check_eco = 0x40001d44; +r_llm_scan_start_eco = 0x40001d48; +r_llm_update_duplicate_scan_count = 0x40001d4c; +r_llc_hci_command_handler_pre = 0x40001d50; +r_llc_hci_command_handler_get = 0x40001d54; +r_llc_hci_command_handler_search = 0x40001d58; +r_llc_llcp_pdu_handler_pre = 0x40001d60; +r_llc_llcp_pdu_handler_end = 0x40001d64; +r_llc_con_conflict_check = 0x40001d6c; +r_sch_prog_hw_reset_try = 0x40001d70; +r_sch_prog_et_state_reset = 0x40001d74; +r_sch_prog_end_isr_handler = 0x40001d78; +r_sch_plan_conflict_check = 0x40001d7c; +r_rwble_isr_hw_fixed = 0x40001d80; +r_bt_bb_recorrect_is_dead = 0x40001d84; +r_bt_bb_restart_hw_recorrect = 0x40001d88; +r_ke_task_handler_pre = 0x40001da0; +r_ke_task_handler_end = 0x40001da4; +r_lld_scan_frm_skip_isr_eco = 0x40001db0; +r_lld_ext_scan_dynamic_pti_reset = 0x40001db4; +r_llc_rem_phy_upd_proc_continue_eco = 0x40001db8; +r_llm_get_preferred_phys = 0x40001dbc; +r_lld_hw_cca_isr_eco = 0x40001dc0; +r_lld_sw_cca_isr_eco = 0x40001dc4; +r_lld_cca_chan_prn_e = 0x40001dc8; +r_lld_cca_chan_prn_s = 0x40001dcc; +r_lld_cca_chan_sel_remap = 0x40001dd0; +r_lld_cca_chan_sel_1 = 0x40001dd4; +r_lld_cca_chan_sel_2 = 0x40001dd8; +r_lld_cca_set_thresh = 0x40001ddc; +r_lld_cca_con_start = 0x40001de0; +r_lld_cca_con_end = 0x40001de4; +r_lld_cca_chm_restore = 0x40001de8; +r_lld_cca_chan_unused_check = 0x40001dec; +r_lld_cca_chm_update_check = 0x40001df0; +r_lld_cca_busy_mode_handle = 0x40001df4; +r_lld_cca_lbt_handle = 0x40001df8; +r_lld_cca_scst_timeout_check = 0x40001dfc; +r_lld_cca_chan_avl_timeout_check = 0x40001e00; + +r_lld_con_start_hook = 0x40001ca8; + +/* ble Functions eco */ +r_bt_bb_isr = 0x40000b9c; +r_bt_rf_coex_conn_phy_coded_data_time_limit_en_get = 0x40000ba8; +r_bt_rtp_get_txpwr_idx_by_act = 0x40000c00; +r_btdm_task_post = 0x40000c14; +r_btdm_task_post_from_isr = 0x40000c18; +r_btdm_task_recycle = 0x40000c1c; +r_ke_task_schedule = 0x40000e80; +r_llc_hci_command_handler = 0x40000ef0; +r_llc_loc_ch_map_proc_continue = 0x40000f5c; +r_llc_loc_con_upd_proc_continue = 0x40000f60; +r_llc_loc_phy_upd_proc_continue = 0x40000f78; +r_llc_rem_con_upd_proc_continue = 0x40000fb4; +r_lld_con_sched = 0x40001118; +r_lld_con_stop = 0x40001124; +r_lld_llcp_rx_ind_handler = 0x400011b0; +r_lld_per_adv_sched = 0x400011f8; +r_rf_txpwr_cs_get = 0x40001428; +r_rf_txpwr_dbm_get = 0x4000142c; +r_sch_arb_event_start_isr = 0x400014f8; +r_sch_plan_set = 0x40001534; +r_sch_prog_end_isr = 0x40001538; +r_lld_adv_ext_chain_scannable_construct = 0x40001b58; + +r_lld_scan_process_pkt_rx = 0x40001280; +r_llm_le_features_get = 0x400013b0; + +/* ble functions rename */ +r_lld_init_start_hack = 0x400011a4; + +/* ble functions disable */ +/* +r_lld_adv_frm_isr_eco = 0x40001d00; +r_lld_res_list_clear = 0x40004638; +r_lld_res_list_rem = 0x40004680; +r_lld_adv_start_hook = 0x40001c80; +r_lld_con_evt_start_cbk_eco = 0x40001d1c; +r_lld_con_tx_prog_new_packet = 0x40001b74; +r_lld_adv_ext_chain_none_construct = 0x40001b50; +r_llc_llcp_send_eco = 0x40001cf4; +r_llc_llcp_channel_map_ind_ack = 0x40001d68; +r_rwble_isr = 0x40001464; +r_lld_scan_start_eco = 0x40001d24; +r_lld_scan_try_sched_eco = 0x40001dac; +r_lld_scan_start_hook = 0x40001c74; +r_lld_init_start_hook = 0x40001cb8; +r_lld_scan_evt_start_cbk_eco = 0x40001d20; +r_ke_task_handler_get_overwrite = 0x40001da8; +r_hci_register_vendor_desc_tab = 0x40000d9c; +r_lld_scan_process_pkt_rx_adv_rep = 0x40001284; +r_register_esp_vendor_cmd_handler = 0x40001400; +r_llc_llcp_pdu_handler_get_overwrite = 0x40001d5c; +*/ diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld index 793e7d8d9a36..339442480951 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld @@ -366,8 +366,8 @@ ets_get_xtal_freq = 0x40000598; gpio_input_get = 0x4000059c; gpio_matrix_in = 0x400005a0; gpio_matrix_out = 0x400005a4; -gpio_output_disable = 0x400005a8; -gpio_output_enable = 0x400005ac; +/* gpio_output_disable = 0x400005a8; */ +/* gpio_output_enable = 0x400005ac; */ gpio_output_set = 0x400005b0; gpio_pad_hold = 0x400005b4; gpio_pad_input_disable = 0x400005b8; @@ -525,800 +525,6 @@ PROVIDE( g_usb_print = 0x3fcdffd0 ); /*************************************** Group bluetooth ***************************************/ - -/* Functions */ -bt_rf_coex_get_dft_cfg = 0x400008dc; -bt_rf_coex_hooks_p_set = 0x400008e0; -btdm_con_maxevtime_cal_impl = 0x400008e4; -btdm_controller_get_compile_version_impl = 0x400008e8; -btdm_controller_rom_data_init = 0x400008ec; -btdm_dis_privacy_err_report_impl = 0x400008f0; -btdm_disable_adv_delay_impl = 0x400008f4; -btdm_enable_scan_continue_impl = 0x400008f8; -btdm_enable_scan_forever_impl = 0x400008fc; -btdm_get_power_state_impl = 0x40000900; -btdm_get_prevent_sleep_flag_impl = 0x40000904; -btdm_power_state_active_impl = 0x40000908; -btdm_switch_phy_coded_impl = 0x4000090c; -hci_acl_data_handler = 0x40000910; -hci_disconnect_cmd_handler = 0x40000914; -hci_le_con_upd_cmd_handler = 0x40000918; -hci_le_ltk_req_neg_reply_cmd_handler = 0x4000091c; -hci_le_ltk_req_reply_cmd_handler = 0x40000920; -hci_le_rd_chnl_map_cmd_handler = 0x40000924; -hci_le_rd_phy_cmd_handler = 0x40000928; -hci_le_rd_rem_feats_cmd_handler = 0x4000092c; -hci_le_rem_con_param_req_neg_reply_cmd_handler = 0x40000930; -hci_le_rem_con_param_req_reply_cmd_handler = 0x40000934; -hci_le_set_data_len_cmd_handler = 0x40000938; -hci_le_set_phy_cmd_handler = 0x4000093c; -hci_le_start_enc_cmd_handler = 0x40000940; -hci_rd_auth_payl_to_cmd_handler = 0x40000944; -hci_rd_rem_ver_info_cmd_handler = 0x40000948; -hci_rd_rssi_cmd_handler = 0x4000094c; -hci_rd_tx_pwr_lvl_cmd_handler = 0x40000950; -hci_vs_set_pref_slave_evt_dur_cmd_handler = 0x40000954; -hci_vs_set_pref_slave_latency_cmd_handler = 0x40000958; -hci_wr_auth_payl_to_cmd_handler = 0x4000095c; -ll_channel_map_ind_handler = 0x40000960; -ll_connection_param_req_handler = 0x40000964; -ll_connection_param_rsp_handler = 0x40000968; -ll_connection_update_ind_handler = 0x4000096c; -ll_enc_req_handler = 0x40000970; -ll_enc_rsp_handler = 0x40000974; -ll_feature_req_handler = 0x40000978; -ll_feature_rsp_handler = 0x4000097c; -ll_length_req_handler = 0x40000980; -ll_length_rsp_handler = 0x40000984; -ll_min_used_channels_ind_handler = 0x40000988; -ll_pause_enc_req_handler = 0x4000098c; -ll_pause_enc_rsp_handler = 0x40000990; -ll_phy_req_handler = 0x40000994; -ll_phy_rsp_handler = 0x40000998; -ll_phy_update_ind_handler = 0x4000099c; -ll_ping_req_handler = 0x400009a0; -ll_ping_rsp_handler = 0x400009a4; -ll_slave_feature_req_handler = 0x400009a8; -ll_start_enc_req_handler = 0x400009ac; -ll_start_enc_rsp_handler = 0x400009b0; -ll_terminate_ind_handler = 0x400009b4; -ll_version_ind_handler = 0x400009b8; -llc_auth_payl_nearly_to_handler = 0x400009bc; -llc_auth_payl_real_to_handler = 0x400009c0; -llc_encrypt_ind_handler = 0x400009c4; -llc_hci_command_handler_wrapper = 0x400009c8; -llc_ll_connection_param_req_pdu_send = 0x400009cc; -llc_ll_connection_param_rsp_pdu_send = 0x400009d0; -llc_ll_connection_update_ind_pdu_send = 0x400009d4; -llc_ll_enc_req_pdu_send = 0x400009d8; -llc_ll_enc_rsp_pdu_send = 0x400009dc; -llc_ll_feature_req_pdu_send = 0x400009e0; -llc_ll_feature_rsp_pdu_send = 0x400009e4; -llc_ll_length_req_pdu_send = 0x400009e8; -llc_ll_length_rsp_pdu_send = 0x400009ec; -llc_ll_pause_enc_req_pdu_send = 0x400009f0; -llc_ll_pause_enc_rsp_pdu_send = 0x400009f4; -llc_ll_phy_req_pdu_send = 0x400009f8; -llc_ll_phy_rsp_pdu_send = 0x400009fc; -llc_ll_ping_req_pdu_send = 0x40000a00; -llc_ll_ping_rsp_pdu_send = 0x40000a04; -llc_ll_start_enc_req_pdu_send = 0x40000a08; -llc_ll_start_enc_rsp_pdu_send = 0x40000a0c; -llc_ll_terminate_ind_pdu_send = 0x40000a10; -llc_ll_unknown_rsp_pdu_send = 0x40000a14; -llc_llcp_ch_map_update_ind_pdu_send = 0x40000a18; -llc_llcp_phy_upd_ind_pdu_send = 0x40000a1c; -llc_llcp_version_ind_pdu_send = 0x40000a20; -llc_op_ch_map_upd_ind_handler = 0x40000a24; -llc_op_con_upd_ind_handler = 0x40000a28; -llc_op_disconnect_ind_handler = 0x40000a2c; -llc_op_dl_upd_ind_handler = 0x40000a30; -llc_op_encrypt_ind_handler = 0x40000a34; -llc_op_feats_exch_ind_handler = 0x40000a38; -llc_op_le_ping_ind_handler = 0x40000a3c; -llc_op_phy_upd_ind_handler = 0x40000a40; -llc_op_ver_exch_ind_handler = 0x40000a44; -llc_stopped_ind_handler = 0x40000a48; -lld_acl_rx_ind_handler = 0x40000a4c; -lld_acl_tx_cfm_handler = 0x40000a50; -lld_adv_end_ind_handler = 0x40000a54; -lld_adv_rep_ind_handler = 0x40000a58; -lld_ch_map_upd_cfm_handler = 0x40000a5c; -lld_con_estab_ind_handler = 0x40000a60; -lld_con_evt_sd_evt_time_set = 0x40000a64; -lld_con_offset_upd_ind_handler = 0x40000a68; -lld_con_param_upd_cfm_handler = 0x40000a6c; -lld_disc_ind_handler = 0x40000a70; -lld_init_end_ind_handler = 0x40000a74; -lld_llcp_rx_ind_handler_wrapper = 0x40000a78; -lld_llcp_tx_cfm_handler = 0x40000a7c; -lld_per_adv_end_ind_handler = 0x40000a80; -lld_per_adv_rep_ind_handler = 0x40000a84; -lld_per_adv_rx_end_ind_handler = 0x40000a88; -lld_phy_coded_500k_get = 0x40000a8c; -lld_phy_upd_cfm_handler = 0x40000a90; -lld_scan_end_ind_handler = 0x40000a94; -lld_scan_req_ind_handler = 0x40000a98; -lld_sync_start_req_handler = 0x40000a9c; -lld_test_end_ind_handler = 0x40000aa0; -lld_update_rxbuf_handler = 0x40000aa4; -llm_ch_map_update_ind_handler = 0x40000aa8; -llm_hci_command_handler_wrapper = 0x40000aac; -llm_scan_period_to_handler = 0x40000ab0; -r_Add2SelfBigHex256 = 0x40000ab4; -r_AddBigHex256 = 0x40000ab8; -r_AddBigHexModP256 = 0x40000abc; -r_AddP256 = 0x40000ac0; -r_AddPdiv2_256 = 0x40000ac4; -r_GF_Jacobian_Point_Addition256 = 0x40000ac8; -r_GF_Jacobian_Point_Double256 = 0x40000acc; -r_GF_Point_Jacobian_To_Affine256 = 0x40000ad0; -r_MultiplyBigHexByUint32_256 = 0x40000ad4; -r_MultiplyBigHexModP256 = 0x40000ad8; -r_MultiplyByU16ModP256 = 0x40000adc; -r_SubtractBigHex256 = 0x40000ae0; -r_SubtractBigHexMod256 = 0x40000ae4; -r_SubtractBigHexUint32_256 = 0x40000ae8; -r_SubtractFromSelfBigHex256 = 0x40000aec; -r_SubtractFromSelfBigHexSign256 = 0x40000af0; -r_aes_alloc = 0x40000af4; -r_aes_ccm_continue = 0x40000af8; -r_aes_ccm_process_e = 0x40000afc; -r_aes_ccm_xor_128_lsb = 0x40000b00; -r_aes_ccm_xor_128_msb = 0x40000b04; -r_aes_cmac_continue = 0x40000b08; -r_aes_cmac_start = 0x40000b0c; -r_aes_k1_continue = 0x40000b10; -r_aes_k2_continue = 0x40000b14; -r_aes_k3_continue = 0x40000b18; -r_aes_k4_continue = 0x40000b1c; -r_aes_shift_left_128 = 0x40000b20; -r_aes_start = 0x40000b24; -r_aes_xor_128 = 0x40000b28; -r_assert_err = 0x40000b2c; -r_assert_param = 0x40000b30; -r_assert_warn = 0x40000b34; -r_bigHexInversion256 = 0x40000b38; -r_ble_sw_cca_check_isr = 0x40000b3c; -r_ble_util_buf_acl_tx_alloc = 0x40000b40; -r_ble_util_buf_acl_tx_elt_get = 0x40000b44; -r_ble_util_buf_acl_tx_free = 0x40000b48; -r_ble_util_buf_acl_tx_free_in_isr = 0x40000b4c; -r_ble_util_buf_adv_tx_alloc = 0x40000b50; -r_ble_util_buf_adv_tx_free = 0x40000b54; -r_ble_util_buf_adv_tx_free_in_isr = 0x40000b58; -r_ble_util_buf_env_deinit = 0x40000b5c; -r_ble_util_buf_env_init = 0x40000b60; -r_ble_util_buf_get_rx_buf_nb = 0x40000b64; -r_ble_util_buf_get_rx_buf_size = 0x40000b68; -r_ble_util_buf_llcp_tx_alloc = 0x40000b6c; -r_ble_util_buf_llcp_tx_free = 0x40000b70; -r_ble_util_buf_rx_alloc = 0x40000b74; -r_ble_util_buf_rx_alloc_in_isr = 0x40000b78; -r_ble_util_buf_rx_free = 0x40000b7c; -r_ble_util_buf_rx_free_in_isr = 0x40000b80; -r_ble_util_buf_set_rx_buf_nb = 0x40000b84; -r_ble_util_buf_set_rx_buf_size = 0x40000b88; -r_ble_util_data_rx_buf_reset = 0x40000b8c; -r_bt_bb_get_intr_mask = 0x40000b90; -r_bt_bb_intr_clear = 0x40000b94; -r_bt_bb_intr_mask_set = 0x40000b98; -r_bt_rf_coex_cfg_set = 0x40000ba0; -r_bt_rf_coex_conn_dynamic_pti_en_get = 0x40000ba4; -r_bt_rf_coex_ext_adv_dynamic_pti_en_get = 0x40000bac; -r_bt_rf_coex_ext_scan_dynamic_pti_en_get = 0x40000bb0; -r_bt_rf_coex_legacy_adv_dynamic_pti_en_get = 0x40000bb4; -r_bt_rf_coex_per_adv_dynamic_pti_en_get = 0x40000bb8; -r_bt_rf_coex_pti_table_get = 0x40000bbc; -r_bt_rf_coex_st_param_get = 0x40000bc0; -r_bt_rf_coex_st_param_set = 0x40000bc4; -r_bt_rf_coex_sync_scan_dynamic_pti_en_get = 0x40000bc8; -r_bt_rma_apply_rule_cs_fmt = 0x40000bcc; -r_bt_rma_apply_rule_cs_idx = 0x40000bd0; -r_bt_rma_configure = 0x40000bd4; -r_bt_rma_deregister_rule_cs_fmt = 0x40000bd8; -r_bt_rma_deregister_rule_cs_idx = 0x40000bdc; -r_bt_rma_get_ant_by_act = 0x40000be0; -r_bt_rma_init = 0x40000be4; -r_bt_rma_register_rule_cs_fmt = 0x40000be8; -r_bt_rma_register_rule_cs_idx = 0x40000bec; -r_bt_rtp_apply_rule_cs_fmt = 0x40000bf0; -r_bt_rtp_apply_rule_cs_idx = 0x40000bf4; -r_bt_rtp_deregister_rule_cs_fmt = 0x40000bf8; -r_bt_rtp_deregister_rule_cs_idx = 0x40000bfc; -r_bt_rtp_init = 0x40000c04; -r_bt_rtp_register_rule_cs_fmt = 0x40000c08; -r_bt_rtp_register_rule_cs_idx = 0x40000c0c; -r_btdm_isr = 0x40000c10; -r_cali_phase_match_p = 0x40000c20; -r_cmp_abs_time = 0x40000c24; -r_cmp_dest_id = 0x40000c28; -r_cmp_timer_id = 0x40000c2c; -r_co_bdaddr_compare = 0x40000c30; -r_co_ble_pkt_dur_in_us = 0x40000c34; -r_co_list_extract = 0x40000c38; -r_co_list_extract_after = 0x40000c3c; -r_co_list_extract_sublist = 0x40000c40; -r_co_list_find = 0x40000c44; -r_co_list_init = 0x40000c48; -r_co_list_insert_after = 0x40000c4c; -r_co_list_insert_before = 0x40000c50; -r_co_list_merge = 0x40000c54; -r_co_list_pool_init = 0x40000c58; -r_co_list_pop_front = 0x40000c5c; -r_co_list_push_back = 0x40000c60; -r_co_list_push_back_sublist = 0x40000c64; -r_co_list_push_front = 0x40000c68; -r_co_list_size = 0x40000c6c; -r_co_nb_good_le_channels = 0x40000c70; -r_co_util_pack = 0x40000c74; -r_co_util_read_array_size = 0x40000c78; -r_co_util_unpack = 0x40000c7c; -r_dbg_env_deinit = 0x40000c80; -r_dbg_env_init = 0x40000c84; -r_dbg_platform_reset_complete = 0x40000c88; -r_dl_upd_proc_start = 0x40000c8c; -r_dump_data = 0x40000c90; -r_ecc_abort_key256_generation = 0x40000c94; -r_ecc_gen_new_public_key = 0x40000c98; -r_ecc_gen_new_secret_key = 0x40000c9c; -r_ecc_generate_key256 = 0x40000ca0; -r_ecc_get_debug_Keys = 0x40000ca4; -r_ecc_init = 0x40000ca8; -r_ecc_is_valid_point = 0x40000cac; -r_ecc_multiplication_event_handler = 0x40000cb0; -r_ecc_point_multiplication_win_256 = 0x40000cb4; -r_emi_alloc_em_mapping_by_offset = 0x40000cb8; -r_emi_base_reg_lut_show = 0x40000cbc; -r_emi_em_base_reg_show = 0x40000cc0; -r_emi_free_em_mapping_by_offset = 0x40000cc4; -r_emi_get_em_mapping_idx_by_offset = 0x40000cc8; -r_emi_get_mem_addr_by_offset = 0x40000ccc; -r_emi_overwrite_em_mapping_by_offset = 0x40000cd0; -r_esp_vendor_hci_command_handler = 0x40000cd4; -r_get_stack_usage = 0x40000cd8; -r_h4tl_acl_hdr_rx_evt_handler = 0x40000cdc; -r_h4tl_cmd_hdr_rx_evt_handler = 0x40000ce0; -r_h4tl_cmd_pld_rx_evt_handler = 0x40000ce4; -r_h4tl_eif_io_event_post = 0x40000ce8; -r_h4tl_eif_register = 0x40000cec; -r_h4tl_init = 0x40000cf0; -r_h4tl_out_of_sync = 0x40000cf4; -r_h4tl_out_of_sync_check = 0x40000cf8; -r_h4tl_read_hdr = 0x40000cfc; -r_h4tl_read_next_out_of_sync = 0x40000d00; -r_h4tl_read_payl = 0x40000d04; -r_h4tl_read_start = 0x40000d08; -r_h4tl_rx_acl_hdr_extract = 0x40000d0c; -r_h4tl_rx_cmd_hdr_extract = 0x40000d10; -r_h4tl_rx_done = 0x40000d14; -r_h4tl_start = 0x40000d18; -r_h4tl_stop = 0x40000d1c; -r_h4tl_tx_done = 0x40000d20; -r_h4tl_tx_evt_handler = 0x40000d24; -r_h4tl_write = 0x40000d28; -r_hci_acl_tx_data_alloc = 0x40000d2c; -r_hci_acl_tx_data_received = 0x40000d30; -r_hci_basic_cmd_send_2_controller = 0x40000d34; -r_hci_ble_adv_report_filter_check = 0x40000d38; -r_hci_ble_adv_report_tx_check = 0x40000d3c; -r_hci_ble_conhdl_register = 0x40000d40; -r_hci_ble_conhdl_unregister = 0x40000d44; -r_hci_build_acl_data = 0x40000d48; -r_hci_build_cc_evt = 0x40000d4c; -r_hci_build_cs_evt = 0x40000d50; -r_hci_build_evt = 0x40000d54; -r_hci_build_le_evt = 0x40000d58; -r_hci_cmd_get_max_param_size = 0x40000d5c; -r_hci_cmd_received = 0x40000d60; -r_hci_cmd_reject = 0x40000d64; -r_hci_evt_mask_check = 0x40000d68; -r_hci_evt_mask_set = 0x40000d6c; -r_hci_fc_acl_buf_size_set = 0x40000d70; -r_hci_fc_acl_en = 0x40000d74; -r_hci_fc_acl_packet_sent = 0x40000d78; -r_hci_fc_check_host_available_nb_acl_packets = 0x40000d7c; -r_hci_fc_host_nb_acl_pkts_complete = 0x40000d80; -r_hci_fc_init = 0x40000d84; -r_hci_look_for_cmd_desc = 0x40000d88; -r_hci_look_for_evt_desc = 0x40000d8c; -r_hci_look_for_le_evt_desc = 0x40000d90; -r_hci_look_for_le_evt_desc_esp = 0x40000d94; -r_hci_pack_bytes = 0x40000d98; -r_hci_send_2_controller = 0x40000da0; -r_hci_send_2_host = 0x40000da4; -r_hci_tl_c2h_data_flow_on = 0x40000da8; -r_hci_tl_cmd_hdr_rx_evt_handler = 0x40000dac; -r_hci_tl_cmd_pld_rx_evt_handler = 0x40000db0; -r_hci_tl_get_pkt = 0x40000db4; -r_hci_tl_hci_pkt_handler = 0x40000db8; -r_hci_tl_hci_tx_done_evt_handler = 0x40000dbc; -r_hci_tl_inc_nb_h2c_cmd_pkts = 0x40000dc0; -r_hci_tl_save_pkt = 0x40000dc4; -r_hci_tl_send = 0x40000dc8; -r_hci_tx_done = 0x40000dcc; -r_hci_tx_start = 0x40000dd0; -r_hci_tx_trigger = 0x40000dd4; -r_isValidSecretKey_256 = 0x40000dd8; -r_ke_check_malloc = 0x40000ddc; -r_ke_event_callback_set = 0x40000de0; -r_ke_event_clear = 0x40000de4; -r_ke_event_flush = 0x40000de8; -r_ke_event_get = 0x40000dec; -r_ke_event_get_all = 0x40000df0; -r_ke_event_init = 0x40000df4; -r_ke_event_schedule = 0x40000df8; -r_ke_event_set = 0x40000dfc; -r_ke_flush = 0x40000e00; -r_ke_free = 0x40000e04; -r_ke_handler_search = 0x40000e08; -r_ke_init = 0x40000e0c; -r_ke_is_free = 0x40000e10; -r_ke_malloc = 0x40000e14; -r_ke_mem_init = 0x40000e18; -r_ke_mem_is_empty = 0x40000e1c; -r_ke_mem_is_in_heap = 0x40000e20; -r_ke_msg_alloc = 0x40000e24; -r_ke_msg_dest_id_get = 0x40000e28; -r_ke_msg_discard = 0x40000e2c; -r_ke_msg_forward = 0x40000e30; -r_ke_msg_forward_new_id = 0x40000e34; -r_ke_msg_free = 0x40000e38; -r_ke_msg_in_queue = 0x40000e3c; -r_ke_msg_save = 0x40000e40; -r_ke_msg_send = 0x40000e44; -r_ke_msg_send_basic = 0x40000e48; -r_ke_msg_src_id_get = 0x40000e4c; -r_ke_queue_extract = 0x40000e50; -r_ke_queue_insert = 0x40000e54; -r_ke_sleep_check = 0x40000e58; -r_ke_state_get = 0x40000e5c; -r_ke_state_set = 0x40000e60; -r_ke_task_check = 0x40000e64; -r_ke_task_create = 0x40000e68; -r_ke_task_delete = 0x40000e6c; -r_ke_task_handler_get = 0x40000e70; -r_ke_task_init = 0x40000e74; -r_ke_task_msg_flush = 0x40000e78; -r_ke_task_saved_update = 0x40000e7c; -r_ke_time = 0x40000e84; -r_ke_time_cmp = 0x40000e88; -r_ke_time_past = 0x40000e8c; -r_ke_timer_active = 0x40000e90; -r_ke_timer_adjust_all = 0x40000e94; -r_ke_timer_clear = 0x40000e98; -r_ke_timer_init = 0x40000e9c; -r_ke_timer_schedule = 0x40000ea0; -r_ke_timer_set = 0x40000ea4; -r_led_init = 0x40000ea8; -r_led_set_all = 0x40000eac; -r_llc_aes_res_cb = 0x40000eb0; -r_llc_ch_map_up_proc_err_cb = 0x40000eb4; -r_llc_cleanup = 0x40000eb8; -r_llc_cmd_cmp_send = 0x40000ebc; -r_llc_cmd_stat_send = 0x40000ec0; -r_llc_con_move_cbk = 0x40000ec4; -r_llc_con_plan_set_update = 0x40000ec8; -r_llc_con_upd_param_in_range = 0x40000ecc; -r_llc_disconnect = 0x40000ed0; -r_llc_disconnect_end = 0x40000ed4; -r_llc_disconnect_proc_continue = 0x40000ed8; -r_llc_disconnect_proc_err_cb = 0x40000edc; -r_llc_dl_chg_check = 0x40000ee0; -r_llc_dle_proc_err_cb = 0x40000ee4; -r_llc_feats_exch_proc_err_cb = 0x40000ee8; -r_llc_hci_cmd_handler_tab_p_get = 0x40000eec; -r_llc_hci_con_param_req_evt_send = 0x40000ef4; -r_llc_hci_con_upd_info_send = 0x40000ef8; -r_llc_hci_disconnected_dis = 0x40000efc; -r_llc_hci_dl_upd_info_send = 0x40000f00; -r_llc_hci_enc_evt_send = 0x40000f04; -r_llc_hci_feats_info_send = 0x40000f08; -r_llc_hci_le_phy_upd_cmp_evt_send = 0x40000f0c; -r_llc_hci_ltk_request_evt_send = 0x40000f10; -r_llc_hci_nb_cmp_pkts_evt_send = 0x40000f14; -r_llc_hci_version_info_send = 0x40000f18; -r_llc_init_term_proc = 0x40000f1c; -r_llc_iv_skd_rand_gen = 0x40000f20; -r_llc_le_ping_proc_continue = 0x40000f24; -r_llc_le_ping_proc_err_cb = 0x40000f28; -/* r_llc_le_ping_restart = 0x40000f2c; */ -r_llc_le_ping_set = 0x40000f30; -r_llc_ll_pause_enc_rsp_ack_handler = 0x40000f34; -r_llc_ll_reject_ind_ack_handler = 0x40000f38; -r_llc_ll_reject_ind_pdu_send = 0x40000f3c; -r_llc_ll_start_enc_rsp_ack_handler = 0x40000f40; -r_llc_ll_terminate_ind_ack = 0x40000f44; -r_llc_ll_unknown_ind_handler = 0x40000f48; -r_llc_llcp_send = 0x40000f4c; -r_llc_llcp_state_set = 0x40000f50; -r_llc_llcp_trans_timer_set = 0x40000f54; -r_llc_llcp_tx_check = 0x40000f58; -r_llc_loc_con_upd_proc_err_cb = 0x40000f64; -r_llc_loc_dl_upd_proc_continue = 0x40000f68; -r_llc_loc_encrypt_proc_continue = 0x40000f6c; -r_llc_loc_encrypt_proc_err_cb = 0x40000f70; -r_llc_loc_feats_exch_proc_continue = 0x40000f74; -r_llc_loc_phy_upd_proc_err_cb = 0x40000f7c; -r_llc_msg_handler_tab_p_get = 0x40000f80; -r_llc_pref_param_compute = 0x40000f84; -r_llc_proc_collision_check = 0x40000f88; -r_llc_proc_err_ind = 0x40000f8c; -r_llc_proc_get = 0x40000f90; -r_llc_proc_id_get = 0x40000f94; -r_llc_proc_reg = 0x40000f98; -r_llc_proc_state_get = 0x40000f9c; -r_llc_proc_state_set = 0x40000fa0; -r_llc_proc_timer_pause_set = 0x40000fa4; -r_llc_proc_timer_set = 0x40000fa8; -r_llc_proc_unreg = 0x40000fac; -r_llc_rem_ch_map_proc_continue = 0x40000fb0; -r_llc_rem_con_upd_proc_err_cb = 0x40000fb8; -r_llc_rem_dl_upd_proc = 0x40000fbc; -r_llc_rem_encrypt_proc_continue = 0x40000fc0; -r_llc_rem_encrypt_proc_err_cb = 0x40000fc4; -r_llc_rem_phy_upd_proc_continue = 0x40000fc8; -r_llc_rem_phy_upd_proc_err_cb = 0x40000fcc; -r_llc_role_get = 0x40000fd0; -r_llc_sk_gen = 0x40000fd4; -r_llc_start = 0x40000fd8; -r_llc_stop = 0x40000fdc; -r_llc_ver_exch_loc_proc_continue = 0x40000fe0; -r_llc_ver_proc_err_cb = 0x40000fe4; -r_llcp_pdu_handler_tab_p_get = 0x40000fe8; -r_lld_aa_gen = 0x40000fec; -r_lld_adv_adv_data_set = 0x40000ff0; -r_lld_adv_adv_data_update = 0x40000ff4; -r_lld_adv_aux_ch_idx_set = 0x40000ff8; -r_lld_adv_aux_evt_canceled_cbk = 0x40000ffc; -r_lld_adv_aux_evt_start_cbk = 0x40001000; -r_lld_adv_coex_check_ext_adv_synced = 0x40001004; -r_lld_adv_coex_env_reset = 0x40001008; -r_lld_adv_duration_update = 0x4000100c; -r_lld_adv_dynamic_pti_process = 0x40001010; -r_lld_adv_end = 0x40001014; -r_lld_adv_evt_canceled_cbk = 0x40001018; -r_lld_adv_evt_start_cbk = 0x4000101c; -r_lld_adv_ext_chain_construct = 0x40001020; -r_lld_adv_ext_pkt_prepare = 0x40001024; -r_lld_adv_frm_cbk = 0x40001028; -r_lld_adv_frm_isr = 0x4000102c; -r_lld_adv_frm_skip_isr = 0x40001030; -r_lld_adv_init = 0x40001034; -r_lld_adv_pkt_rx = 0x40001038; -r_lld_adv_pkt_rx_connect_ind = 0x4000103c; -r_lld_adv_pkt_rx_send_scan_req_evt = 0x40001040; -r_lld_adv_rand_addr_update = 0x40001044; -r_lld_adv_restart = 0x40001048; -r_lld_adv_scan_rsp_data_set = 0x4000104c; -r_lld_adv_scan_rsp_data_update = 0x40001050; -r_lld_adv_set_tx_power = 0x40001054; -r_lld_adv_start = 0x40001058; -r_lld_adv_stop = 0x4000105c; -r_lld_adv_sync_info_set = 0x40001060; -r_lld_adv_sync_info_update = 0x40001064; -r_lld_calc_aux_rx = 0x40001068; -r_lld_cca_alloc = 0x4000106c; -r_lld_cca_data_reset = 0x40001070; -r_lld_cca_free = 0x40001074; -r_lld_ch_assess_data_get = 0x40001078; -r_lld_ch_idx_get = 0x4000107c; -r_lld_ch_map_set = 0x40001080; -r_lld_channel_assess = 0x40001084; -r_lld_con_activity_act_offset_compute = 0x40001088; -r_lld_con_activity_offset_compute = 0x4000108c; -r_lld_con_ch_map_update = 0x40001090; -r_lld_con_cleanup = 0x40001094; -r_lld_con_current_tx_power_get = 0x40001098; -r_lld_con_data_flow_set = 0x4000109c; -r_lld_con_data_len_update = 0x400010a0; -r_lld_con_data_tx = 0x400010a4; -r_lld_con_enc_key_load = 0x400010a8; -r_lld_con_event_counter_get = 0x400010ac; -r_lld_con_evt_canceled_cbk = 0x400010b0; -r_lld_con_evt_duration_min_get = 0x400010b4; -r_lld_con_evt_max_eff_time_cal = 0x400010b8; -r_lld_con_evt_sd_evt_time_get = 0x400010bc; -r_lld_con_evt_start_cbk = 0x400010c0; -r_lld_con_evt_time_update = 0x400010c4; -r_lld_con_free_all_tx_buf = 0x400010c8; -r_lld_con_frm_cbk = 0x400010cc; -r_lld_con_frm_isr = 0x400010d0; -r_lld_con_frm_skip_isr = 0x400010d4; -r_lld_con_init = 0x400010d8; -r_lld_con_llcp_tx = 0x400010dc; -r_lld_con_max_lat_calc = 0x400010e0; -r_lld_con_offset_get = 0x400010e4; -r_lld_con_param_update = 0x400010e8; -r_lld_con_phys_update = 0x400010ec; -r_lld_con_pref_slave_evt_dur_set = 0x400010f0; -r_lld_con_pref_slave_latency_set = 0x400010f4; -r_lld_con_rssi_get = 0x400010f8; -r_lld_con_rx = 0x400010fc; -/* r_lld_con_rx_channel_assess = 0x40001100; */ -r_lld_con_rx_enc = 0x40001104; -r_lld_con_rx_isr = 0x40001108; -r_lld_con_rx_link_info_check = 0x4000110c; -r_lld_con_rx_llcp_check = 0x40001110; -r_lld_con_rx_sync_time_update = 0x40001114; -r_lld_con_set_tx_power = 0x4000111c; -r_lld_con_start = 0x40001120; -r_lld_con_tx = 0x40001128; -r_lld_con_tx_enc = 0x4000112c; -r_lld_con_tx_isr = 0x40001130; -r_lld_con_tx_len_update = 0x40001134; -r_lld_con_tx_len_update_for_intv = 0x40001138; -r_lld_con_tx_len_update_for_rate = 0x4000113c; -r_lld_con_tx_prog = 0x40001140; -r_lld_conn_dynamic_pti_process = 0x40001144; -r_lld_continue_scan_rx_isr_end_process = 0x40001148; -r_lld_ext_scan_dynamic_pti_process = 0x4000114c; -r_lld_hw_cca_end_isr = 0x40001150; -r_lld_hw_cca_evt_handler = 0x40001154; -r_lld_hw_cca_isr = 0x40001158; -r_lld_init_cal_anchor_point = 0x4000115c; -r_lld_init_compute_winoffset = 0x40001160; -r_lld_init_connect_req_pack = 0x40001164; -r_lld_init_end = 0x40001168; -r_lld_init_evt_canceled_cbk = 0x4000116c; -r_lld_init_evt_start_cbk = 0x40001170; -r_lld_init_frm_cbk = 0x40001174; -r_lld_init_frm_eof_isr = 0x40001178; -r_lld_init_frm_skip_isr = 0x4000117c; -r_lld_init_init = 0x40001180; -r_lld_init_process_pkt_rx = 0x40001184; -r_lld_init_process_pkt_rx_adv_ext_ind = 0x40001188; -r_lld_init_process_pkt_rx_adv_ind_or_direct_ind = 0x4000118c; -r_lld_init_process_pkt_rx_aux_connect_rsp = 0x40001190; -r_lld_init_process_pkt_tx = 0x40001194; -r_lld_init_process_pkt_tx_cal_con_timestamp = 0x40001198; -r_lld_init_sched = 0x4000119c; -r_lld_init_set_tx_power = 0x400011a0; -r_lld_init_start = 0x400011a4; -r_lld_init_stop = 0x400011a8; -r_lld_instant_proc_end = 0x400011ac; -r_lld_per_adv_ch_map_update = 0x400011b4; -r_lld_per_adv_chain_construct = 0x400011b8; -r_lld_per_adv_cleanup = 0x400011bc; -r_lld_per_adv_coex_env_reset = 0x400011c0; -r_lld_per_adv_data_set = 0x400011c4; -r_lld_per_adv_data_update = 0x400011c8; -r_lld_per_adv_dynamic_pti_process = 0x400011cc; -r_lld_per_adv_evt_canceled_cbk = 0x400011d0; -r_lld_per_adv_evt_start_cbk = 0x400011d4; -r_lld_per_adv_ext_pkt_prepare = 0x400011d8; -r_lld_per_adv_frm_cbk = 0x400011dc; -r_lld_per_adv_frm_isr = 0x400011e0; -r_lld_per_adv_frm_skip_isr = 0x400011e4; -r_lld_per_adv_init = 0x400011e8; -r_lld_per_adv_init_info_get = 0x400011ec; -r_lld_per_adv_list_add = 0x400011f0; -r_lld_per_adv_list_rem = 0x400011f4; -r_lld_per_adv_set_tx_power = 0x400011fc; -r_lld_per_adv_start = 0x40001200; -r_lld_per_adv_stop = 0x40001204; -r_lld_per_adv_sync_info_get = 0x40001208; -r_lld_process_cca_data = 0x4000120c; -r_lld_ral_search = 0x40001210; -r_lld_read_clock = 0x40001214; -r_lld_res_list_add = 0x40001218; -r_lld_res_list_is_empty = 0x40001220; -r_lld_res_list_local_rpa_get = 0x40001224; -r_lld_res_list_peer_rpa_get = 0x40001228; -r_lld_res_list_peer_update = 0x4000122c; -/* r_lld_res_list_priv_mode_update = 0x40001230; */ -r_lld_reset_reg = 0x40001238; -r_lld_rpa_renew = 0x4000123c; -r_lld_rpa_renew_evt_canceled_cbk = 0x40001240; -r_lld_rpa_renew_evt_start_cbk = 0x40001244; -r_lld_rpa_renew_instant_cbk = 0x40001248; -r_lld_rxdesc_check = 0x4000124c; -r_lld_rxdesc_free = 0x40001250; -r_lld_scan_create_sync = 0x40001254; -r_lld_scan_create_sync_cancel = 0x40001258; -r_lld_scan_end = 0x4000125c; -r_lld_scan_evt_canceled_cbk = 0x40001260; -r_lld_scan_evt_start_cbk = 0x40001264; -r_lld_scan_frm_cbk = 0x40001268; -r_lld_scan_frm_eof_isr = 0x4000126c; -r_lld_scan_frm_rx_isr = 0x40001270; -r_lld_scan_frm_skip_isr = 0x40001274; -r_lld_scan_init = 0x40001278; -r_lld_scan_params_update = 0x4000127c; -r_lld_scan_process_pkt_rx_aux_adv_ind = 0x40001288; -r_lld_scan_process_pkt_rx_aux_chain_ind = 0x4000128c; -r_lld_scan_process_pkt_rx_aux_scan_rsp = 0x40001290; -r_lld_scan_process_pkt_rx_ext_adv = 0x40001294; -r_lld_scan_process_pkt_rx_ext_adv_ind = 0x40001298; -r_lld_scan_process_pkt_rx_legacy_adv = 0x4000129c; -r_lld_scan_restart = 0x400012a0; -r_lld_scan_sched = 0x400012a4; -r_lld_scan_set_tx_power = 0x400012a8; -r_lld_scan_start = 0x400012ac; -r_lld_scan_stop = 0x400012b0; -r_lld_scan_sync_accept = 0x400012b4; -r_lld_scan_sync_info_unpack = 0x400012b8; -r_lld_scan_trunc_ind = 0x400012bc; -r_lld_sw_cca_evt_handler = 0x400012c0; -r_lld_sw_cca_isr = 0x400012c4; -r_lld_sync_ch_map_update = 0x400012c8; -r_lld_sync_cleanup = 0x400012cc; -r_lld_sync_evt_canceled_cbk = 0x400012d0; -r_lld_sync_evt_start_cbk = 0x400012d4; -r_lld_sync_frm_cbk = 0x400012d8; -r_lld_sync_frm_eof_isr = 0x400012dc; -r_lld_sync_frm_rx_isr = 0x400012e0; -r_lld_sync_frm_skip_isr = 0x400012e4; -r_lld_sync_init = 0x400012e8; -r_lld_sync_process_pkt_rx = 0x400012ec; -r_lld_sync_process_pkt_rx_aux_sync_ind = 0x400012f0; -r_lld_sync_process_pkt_rx_pkt_check = 0x400012f4; -r_lld_sync_scan_dynamic_pti_process = 0x400012f8; -r_lld_sync_sched = 0x400012fc; -r_lld_sync_start = 0x40001300; -r_lld_sync_stop = 0x40001304; -r_lld_sync_trunc_ind = 0x40001308; -r_lld_test_cleanup = 0x4000130c; -r_lld_test_evt_canceled_cbk = 0x40001310; -r_lld_test_evt_start_cbk = 0x40001314; -r_lld_test_freq2chnl = 0x40001318; -r_lld_test_frm_cbk = 0x4000131c; -r_lld_test_frm_isr = 0x40001320; -r_lld_test_init = 0x40001324; -r_lld_test_rx_isr = 0x40001328; -r_lld_test_set_tx_power = 0x4000132c; -r_lld_test_start = 0x40001330; -/* r_lld_test_stop = 0x40001334; */ -r_lld_update_rxbuf = 0x40001338; -r_lld_update_rxbuf_isr = 0x4000133c; -r_lld_white_list_add = 0x40001340; -r_lld_white_list_rem = 0x40001344; -r_llm_activity_free_get = 0x40001348; -r_llm_activity_free_set = 0x4000134c; -r_llm_activity_syncing_get = 0x40001350; -r_llm_adv_con_len_check = 0x40001354; -r_llm_adv_hdl_to_id = 0x40001358; -r_llm_adv_rep_flow_control_check = 0x4000135c; -r_llm_adv_rep_flow_control_update = 0x40001360; -r_llm_adv_reports_list_check = 0x40001364; -r_llm_adv_set_all_release = 0x40001368; -r_llm_adv_set_dft_params = 0x4000136c; -r_llm_adv_set_release = 0x40001370; -r_llm_aes_res_cb = 0x40001374; -r_llm_ble_update_adv_flow_control = 0x40001378; -r_llm_ch_map_update = 0x4000137c; -r_llm_cmd_cmp_send = 0x40001380; -r_llm_cmd_stat_send = 0x40001384; -r_llm_dev_list_empty_entry = 0x40001388; -r_llm_dev_list_search = 0x4000138c; -r_llm_env_adv_dup_filt_deinit = 0x40001390; -r_llm_env_adv_dup_filt_init = 0x40001394; -r_llm_init_ble_adv_report_flow_contol = 0x40001398; -r_llm_is_dev_connected = 0x4000139c; -r_llm_is_dev_synced = 0x400013a0; -r_llm_is_non_con_act_ongoing_check = 0x400013a4; -r_llm_is_wl_accessible = 0x400013a8; -r_llm_le_evt_mask_check = 0x400013ac; -r_llm_link_disc = 0x400013b4; -r_llm_master_ch_map_get = 0x400013b8; -r_llm_msg_handler_tab_p_get = 0x400013bc; -r_llm_no_activity = 0x400013c0; -r_llm_per_adv_slot_dur = 0x400013c4; -r_llm_plan_elt_get = 0x400013c8; -r_llm_rx_path_comp_get = 0x400013cc; -r_llm_scan_start = 0x400013d0; -r_llm_scan_sync_acad_attach = 0x400013d4; -r_llm_scan_sync_acad_detach = 0x400013d8; -r_llm_send_adv_lost_event_to_host = 0x400013dc; -r_llm_tx_path_comp_get = 0x400013e0; -r_misc_deinit = 0x400013e4; -r_misc_free_em_buf_in_isr = 0x400013e8; -r_misc_init = 0x400013ec; -r_misc_msg_handler_tab_p_get = 0x400013f0; -r_notEqual256 = 0x400013f4; -r_phy_upd_proc_start = 0x400013f8; -r_platform_reset = 0x400013fc; -r_rf_em_init = 0x40001404; -r_rf_force_agc_enable = 0x40001408; -r_rf_reg_rd = 0x4000140c; -r_rf_reg_wr = 0x40001410; -r_rf_reset = 0x40001414; -r_rf_rssi_convert = 0x40001418; -r_rf_rw_v9_le_disable = 0x4000141c; -r_rf_rw_v9_le_enable = 0x40001420; -r_rf_sleep = 0x40001424; -r_rf_util_cs_fmt_convert = 0x40001430; -r_rw_crypto_aes_ccm = 0x40001434; -r_rw_crypto_aes_encrypt = 0x40001438; -r_rw_crypto_aes_init = 0x4000143c; -r_rw_crypto_aes_k1 = 0x40001440; -r_rw_crypto_aes_k2 = 0x40001444; -r_rw_crypto_aes_k3 = 0x40001448; -r_rw_crypto_aes_k4 = 0x4000144c; -r_rw_crypto_aes_rand = 0x40001450; -r_rw_crypto_aes_result_handler = 0x40001454; -r_rw_crypto_aes_s1 = 0x40001458; -r_rw_cryto_aes_cmac = 0x4000145c; -r_rw_v9_init_em_radio_table = 0x40001460; -r_rwble_sleep_enter = 0x40001468; -r_rwble_sleep_wakeup_end = 0x4000146c; -/* r_rwbtdm_isr_wrapper = 0x40001470; */ -r_rwip_active_check = 0x40001474; -r_rwip_aes_encrypt = 0x40001478; -/* r_rwip_assert = 0x4000147c; */ -r_rwip_crypt_evt_handler = 0x40001480; -r_rwip_crypt_isr_handler = 0x40001484; -r_rwip_eif_get = 0x40001488; -r_rwip_half_slot_2_lpcycles = 0x4000148c; -r_rwip_hus_2_lpcycles = 0x40001490; -r_rwip_isr = 0x40001494; -r_rwip_lpcycles_2_hus = 0x40001498; -r_rwip_prevent_sleep_clear = 0x4000149c; -r_rwip_prevent_sleep_set = 0x400014a0; -r_rwip_schedule = 0x400014a4; -r_rwip_sleep = 0x400014a8; -r_rwip_sw_int_handler = 0x400014ac; -r_rwip_sw_int_req = 0x400014b0; -r_rwip_time_get = 0x400014b4; -r_rwip_timer_10ms_handler = 0x400014b8; -r_rwip_timer_10ms_set = 0x400014bc; -r_rwip_timer_hs_handler = 0x400014c0; -r_rwip_timer_hs_set = 0x400014c4; -r_rwip_timer_hus_handler = 0x400014c8; -r_rwip_timer_hus_set = 0x400014cc; -r_rwip_wakeup = 0x400014d0; -/* r_rwip_wakeup_end = 0x400014d4; */ -r_rwip_wlcoex_set = 0x400014d8; -r_sch_alarm_clear = 0x400014dc; -r_sch_alarm_init = 0x400014e0; -r_sch_alarm_prog = 0x400014e4; -r_sch_alarm_set = 0x400014e8; -r_sch_alarm_timer_isr = 0x400014ec; -r_sch_arb_conflict_check = 0x400014f0; -r_sch_arb_elt_cancel = 0x400014f4; -r_sch_arb_init = 0x400014fc; -r_sch_arb_insert = 0x40001500; -r_sch_arb_prog_timer = 0x40001504; -r_sch_arb_remove = 0x40001508; -r_sch_arb_sw_isr = 0x4000150c; -r_sch_plan_chk = 0x40001510; -r_sch_plan_clock_wrap_offset_update = 0x40001514; -r_sch_plan_init = 0x40001518; -r_sch_plan_interval_req = 0x4000151c; -r_sch_plan_offset_max_calc = 0x40001520; -r_sch_plan_offset_req = 0x40001524; -r_sch_plan_position_range_compute = 0x40001528; -r_sch_plan_rem = 0x4000152c; -r_sch_plan_req = 0x40001530; -r_sch_prog_init = 0x4000153c; -r_sch_prog_push = 0x40001540; -r_sch_prog_rx_isr = 0x40001544; -r_sch_prog_skip_isr = 0x40001548; -r_sch_prog_tx_isr = 0x4000154c; -r_sch_slice_bg_add = 0x40001550; -r_sch_slice_bg_remove = 0x40001554; -r_sch_slice_compute = 0x40001558; -r_sch_slice_fg_add = 0x4000155c; -r_sch_slice_fg_remove = 0x40001560; -r_sch_slice_init = 0x40001564; -r_sch_slice_per_add = 0x40001568; -r_sch_slice_per_remove = 0x4000156c; -r_sdk_config_get_bt_sleep_enable = 0x40001570; -r_sdk_config_get_hl_derived_opts = 0x40001574; -r_sdk_config_get_opts = 0x40001578; -r_sdk_config_get_priv_opts = 0x4000157c; -r_sdk_config_set_bt_sleep_enable = 0x40001580; -r_sdk_config_set_hl_derived_opts = 0x40001584; -r_sdk_config_set_opts = 0x40001588; -r_specialModP256 = 0x4000158c; -r_unloaded_area_init = 0x40001590; -r_vhci_flow_off = 0x40001594; -r_vhci_flow_on = 0x40001598; -r_vhci_notify_host_send_available = 0x4000159c; -r_vhci_send_to_host = 0x400015a0; -r_vnd_hci_command_handler = 0x400015a4; -r_vshci_init = 0x400015a8; -vnd_hci_command_handler_wrapper = 0x400015ac; /* Data (.data, .bss, .rodata) */ bt_rf_coex_cfg_p = 0x3fcdffcc; bt_rf_coex_hooks_p = 0x3fcdffc8; @@ -1462,38 +668,6 @@ rwip_coex_cfg = 0x3ff1eeac; rwip_priority = 0x3ff1ee94; veryBigHexP256 = 0x3ff1ee48; -/* bluetooth hook funcs */ -r_llc_loc_encrypt_proc_continue_hook = 0x40001c60; -r_llc_loc_phy_upd_proc_continue_hook = 0x40001c64; -r_llc_rem_phy_upd_proc_continue_hook = 0x40001c68; -r_lld_scan_frm_eof_isr_hook = 0x40001c6c; -r_lld_scan_evt_start_cbk_hook = 0x40001c70; -r_lld_scan_process_pkt_rx_ext_adv_hook = 0x40001c78; -r_lld_scan_sched_hook = 0x40001c7c; -r_lld_adv_evt_start_cbk_hook = 0x40001c84; -r_lld_adv_aux_evt_start_cbk_hook = 0x40001c88; -r_lld_adv_frm_isr_hook = 0x40001c8c; -r_lld_adv_start_init_evt_param_hook = 0x40001c90; -r_lld_con_evt_canceled_cbk_hook = 0x40001c94; -r_lld_con_frm_isr_hook = 0x40001c98; -r_lld_con_tx_hook = 0x40001c9c; -r_lld_con_rx_hook = 0x40001ca0; -r_lld_con_evt_start_cbk_hook = 0x40001ca4; -r_lld_con_tx_prog_new_packet_hook = 0x40001cac; -r_lld_init_frm_eof_isr_hook = 0x40001cb0; -r_lld_init_evt_start_cbk_hook = 0x40001cb4; -r_lld_init_sched_hook = 0x40001cbc; -r_lld_init_process_pkt_tx_hook = 0x40001cc0; -r_lld_per_adv_evt_start_cbk_hook = 0x40001cc4; -r_lld_per_adv_frm_isr_hook = 0x40001cc8; -r_lld_per_adv_start_hook = 0x40001ccc; -r_lld_sync_frm_eof_isr_hook = 0x40001cd0; -r_lld_sync_evt_start_cbk_hook = 0x40001cd4; -r_lld_sync_start_hook = 0x40001cd8; -r_lld_sync_process_pkt_rx_pkt_check_hook = 0x40001cdc; -r_sch_arb_insert_hook = 0x40001ce0; -r_sch_plan_offset_req_hook = 0x40001ce4; - /*************************************** Group rom_pp ***************************************/ @@ -1571,7 +745,7 @@ ppEnqueueTxDone = 0x400016cc; ppGetTxQFirstAvail_Locked = 0x400016d0; ppGetTxframe = 0x400016d4; ppProcessRxPktHdr = 0x400016e0; -ppProcessTxQ = 0x400016e4; +/*ppProcessTxQ = 0x400016e4;*/ ppRecordBarRRC = 0x400016e8; lmacRequestTxopQueue = 0x400016ec; lmacReleaseTxopQueue = 0x400016f0; diff --git a/components/esp_rom/esp32c5/include/esp32c5/rom/km.h b/components/esp_rom/esp32c5/include/esp32c5/rom/km.h new file mode 100644 index 000000000000..2fe74e77a569 --- /dev/null +++ b/components/esp_rom/esp32c5/include/esp32c5/rom/km.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _KM_H +#define _KM_H + +#include "soc/soc_caps.h" +#if SOC_KEY_MANAGER_SUPPORTED + +#include +#include "soc/soc.h" +#include "ets_sys.h" + +#if __cplusplus +extern "C" { +#endif + +/* huk mode type */ +typedef enum { + HUK_MODE_RECOVER = 0, + HUK_MODE_GEN = 1, +} huk_mode_t; + +/** + * @brief Recover efuse key or key manager key if flash encryption is enabled + * + * @param do_log : if km process print log + * + * @return ETS_OK when key is recovered, ETS_FAILED when key not recovered + */ +ETS_STATUS esp_rom_check_recover_key(int do_log); + +/** + * @brief Configure huk mode + * + * @param mode : HUK_MODE_RECOVER or HUK_MODE_GEN + * + * @param huk_info : uint8_t pointer to the buffer which will feed the huk info or + * gain the huk info + * + * @return ETS_OK when huk configuration is done, else ETS_FAILED + */ +ETS_STATUS esp_rom_km_huk_conf(huk_mode_t mode, uint8_t *huk_info); + +/** + * @brief Get huk risk. The risk level of HUK is 0-6: the higher the risk level is, + * the more error bits there are in the PUF SRAM. 7: Error level, HUK is invalid + * + * @param None + * + * @return The huk risk + */ +int esp_rom_km_huk_risk(void); + +#ifdef __cplusplus +} +#endif +#endif /* SOC_KEY_MANAGER_SUPPORTED */ + +#endif /* _KM_H */ diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.ld index 3f5b833a297d..7f5148d682f8 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.ld @@ -258,8 +258,8 @@ gpio_get_input_level = 0x4000070c; gpio_matrix_in = 0x40000710; gpio_matrix_out = 0x40000714; gpio_bypass_matrix_in = 0x40000718; -gpio_output_disable = 0x4000071c; -gpio_output_enable = 0x40000720; +/* gpio_output_disable = 0x4000071c; */ +/* gpio_output_enable = 0x40000720; */ gpio_pad_input_disable = 0x40000724; gpio_pad_input_enable = 0x40000728; gpio_pad_pulldown = 0x4000072c; diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.net80211.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.net80211.ld index bd55f3bb3cb7..1d87aafcb388 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.net80211.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.net80211.ld @@ -60,7 +60,7 @@ ieee80211_find_ext_elem = 0x40000bb0; ieee80211_find_ie = 0x40000bb4; ieee80211_find_ext_ie = 0x40000bb8; ieee80211_merge_mbssid_profile = 0x40000bbc; -ieee80211_encap_esfbuf_htc = 0x40000bc0; +/*ieee80211_encap_esfbuf_htc = 0x40000bc0;*/ /*wifi_get_macaddr = 0x40000bc4;*/ /*wifi_rf_phy_disable = 0x40000bc8;*/ /*wifi_rf_phy_enable = 0x40000bcc;*/ diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.phy.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.phy.ld index 9bd20793bee6..3c61a264b035 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.phy.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.phy.ld @@ -284,10 +284,14 @@ phy_wifi_set_tx_gain = 0x400014f4; phy_bt_get_tx_tab_ = 0x400014f8; phy_bt_set_tx_gain = 0x400014fc; phy_bt_tx_gain_init = 0x40001500; -phy_pbus_xpd_rx_off = 0x40002518; -phy_i2c_writeReg_Mask = 0x4000787e; -phy_pbus_xpd_rx_on = 0x40002628; -phy_pbus_xpd_tx_on = 0x4000274c; +phy_pbus_xpd_rx_off = 0x40001528; +phy_i2c_writeReg_Mask = 0x4000152c; +phy_pbus_xpd_rx_on = 0x40001530; +phy_pbus_xpd_tx_on = 0x40001534; +phy_get_romfuncs = 0x40001538; +phy_chip_set_chan_ana_ = 0x4000153c; +phy_pbus_xpd_tx_off = 0x40001540; /* Data (.data, .bss, .rodata) */ phy_rom_phyFuns = 0x4085fb80; phy_param_rom = 0x4085fc70; +phy_rom_phyFuns_eco1 = 0x4085fc6c; diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.pp.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.pp.ld index a72cb8e5b758..dbe5ab1adf9c 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.pp.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.pp.ld @@ -27,14 +27,14 @@ esf_buf_recycle = 0x40000bfc; GetAccess = 0x40000c00; hal_mac_is_low_rate_enabled = 0x40000c04; hal_mac_tx_get_blockack = 0x40000c08; -hal_mac_tx_set_ppdu = 0x40000c0c; +/*hal_mac_tx_set_ppdu = 0x40000c0c;*/ hal_mac_tx_clr_mplen = 0x40000c10; hal_mac_get_txq_state = 0x40000c14; hal_mac_clr_txq_state = 0x40000c18; hal_mac_get_txq_complete = 0x40000c1c; -/*hal_mac_deinit_twt_tx = 0x40000c20;*/ +hal_mac_deinit_twt_tx = 0x40000c20; hal_mac_is_dma_enable = 0x40000c24; -hal_he_get_bss_color = 0x40000c28; +/*hal_he_get_bss_color = 0x40000c28;*/ hal_he_set_ersu = 0x40000c2c; hal_he_get_mplen_addr_start = 0x40000c30; hal_he_get_mplen_addr_end = 0x40000c34; @@ -62,7 +62,7 @@ ic_get_he_rts_threshold_bytes = 0x40000c88; lmacAdjustTimestamp = 0x40000c8c; lmacDiscardAgedMSDU = 0x40000c90; lmacDiscardMSDU = 0x40000c94; -/*lmacEndFrameExchangeSequence = 0x40000c98;*/ +lmacEndFrameExchangeSequence = 0x40000c98; lmacIsIdle = 0x40000c9c; lmacIsLongFrame = 0x40000ca0; lmacMSDUAged = 0x40000ca4; @@ -74,19 +74,19 @@ lmacReachLongLimit = 0x40000cb8; lmacReachShortLimit = 0x40000cbc; lmacRecycleMPDU = 0x40000cc0; lmacRxDone = 0x40000cc4; -/*lmacSetTxFrame = 0x40000cc8;*/ +lmacSetTxFrame = 0x40000cc8; lmacTxDone = 0x40000ccc; lmacTxFrame = 0x40000cd0; lmacDisableTransmit = 0x40000cd4; lmacDiscardFrameExchangeSequence = 0x40000cd8; lmacProcessCollision = 0x40000cdc; lmacProcessAckTimeout = 0x40000ce0; -/*lmacProcessShortRetryFail = 0x40000ce4;*/ +lmacProcessShortRetryFail = 0x40000ce4; lmacProcessCollisions_task = 0x40000ce8; lmacProcessTxRtsError = 0x40000cec; lmacProcessTxError = 0x40000cf0; lmacProcessCtsTimeout = 0x40000cf4; -/*lmacProcessLongRetryFail = 0x40000cf8;*/ +lmacProcessLongRetryFail = 0x40000cf8; lmacRetryTxFrame = 0x40000cfc; lmacEndRetryAMPDUFail = 0x40000d00; lmacProcessTxSuccess = 0x40000d04; @@ -112,7 +112,7 @@ pm_disable_sleep_delay_timer = 0x40000d50; /*pm_dream = 0x40000d54;*/ pm_mac_wakeup = 0x40000d58; pm_mac_sleep = 0x40000d5c; -pm_enable_active_timer = 0x40000d60; +/*pm_enable_active_timer = 0x40000d60;*/ pm_enable_sleep_delay_timer = 0x40000d64; pm_local_tsf_process = 0x40000d68; pm_set_beacon_filter = 0x40000d6c; @@ -145,13 +145,13 @@ pm_disconnected_wake = 0x40000dd4; /*pm_tx_data_process = 0x40000dd8;*/ pm_is_twt_awake = 0x40000ddc; pm_enable_twt_keep_alive = 0x40000de0; -/*pm_twt_on_tsf_timer = 0x40000de4;*/ +pm_twt_on_tsf_timer = 0x40000de4; pm_twt_process = 0x40000de8; pm_is_twt_start = 0x40000dec; pm_twt_set_target_wdev_time = 0x40000df0; pm_twt_set_target_tsf = 0x40000df4; pm_enable_twt_keep_alive_timer = 0x40000df8; -/*pm_mac_try_enable_modem_state = 0x40000dfc;*/ +pm_mac_try_enable_modem_state = 0x40000dfc; pm_beacon_monitor_tbtt_timeout_process = 0x40000e00; /*pm_update_next_tbtt = 0x40000e04;*/ pm_twt_disallow_tx = 0x40000e08; @@ -180,7 +180,7 @@ ppGetTxframe = 0x40000e60; ppMapTxQueue = 0x40000e64; ppProcTxSecFrame = 0x40000e68; ppProcessRxPktHdr = 0x40000e6c; -ppProcessTxQ = 0x40000e70; +/*ppProcessTxQ = 0x40000e70;*/ ppRecordBarRRC = 0x40000e74; ppRecycleAmpdu = 0x40000e78; ppRecycleRxPkt = 0x40000e7c; @@ -209,11 +209,11 @@ ppDisableQueue = 0x40000ed4; ppCalVHTDeliNum = 0x40000ed8; ppCalTxVHTSMPDULength = 0x40000edc; ppCheckTxRTS = 0x40000ee0; -/*ppProcessLifeTime = 0x40000ee4;*/ +ppProcessLifeTime = 0x40000ee4; ppProcTxCallback = 0x40000ee8; ppCalPreFecPaddingFactor = 0x40000eec; ppCalDeliNum = 0x40000ef0; -/*ppRemoveHTC = 0x40000ef4;*/ +ppRemoveHTC = 0x40000ef4; ppCheckTxHEAMPDUlength = 0x40000ef8; ppCertSetRate = 0x40000efc; ppSelectTxFormat = 0x40000f00; @@ -222,7 +222,7 @@ pp_coex_tx_release = 0x40000f08; ppAdd2AMPDUTail = 0x40000f0c; ppDirectRecycleAmpdu = 0x40000f10; ppRegressAmpdu = 0x40000f14; -pp_timer_do_process = 0x40000f18; +/*pp_timer_do_process = 0x40000f18;*/ rcGetAmpduSched = 0x40000f1c; rcUpdateRxDone = 0x40000f20; rc_get_trc = 0x40000f24; @@ -260,7 +260,7 @@ trcAmpduSetState = 0x40000fa0; trc_set_bf_report_rate = 0x40000fa4; trc_onPPTxDone = 0x40000fa8; wDevCheckBlockError = 0x40000fac; -/*wDev_AppendRxBlocks = 0x40000fb0;*/ +wDev_AppendRxBlocks = 0x40000fb0; wDev_DiscardFrame = 0x40000fb4; wDev_GetNoiseFloor = 0x40000fb8; wDev_IndicateAmpdu = 0x40000fbc; @@ -335,6 +335,12 @@ is_use_muedca = 0x400010cc; pwr_hal_clear_mac_modem_state_wakeup_protect_signal = 0x400010d0; get_estimated_batime = 0x400010d4; get_sublen_offset = 0x400010d8; +pm_coex_schm_overall_period_get = 0x40001504; +ppRemoveHEAMPDUflags = 0x4000150c; +tsf_hal_get_tbtt_interval = 0x40001510; +pm_get_tbtt_count = 0x4000151c; +tsf_hal_get_time = 0x40001520; +tsf_hal_get_counter_value = 0x40001524; /* Data (.data, .bss, .rodata) */ our_instances_ptr = 0x4004ffe0; pTxRx = 0x4085ff74; diff --git a/components/esp_rom/esp32c6/ld/esp32c6.rom.ld b/components/esp_rom/esp32c6/ld/esp32c6.rom.ld index f8ea9d4d3e46..2af963d50873 100644 --- a/components/esp_rom/esp32c6/ld/esp32c6.rom.ld +++ b/components/esp_rom/esp32c6/ld/esp32c6.rom.ld @@ -238,8 +238,8 @@ ets_clk_mspi_apb_wait_ready = 0x400006d0; gpio_input_get = 0x400006d4; gpio_matrix_in = 0x400006d8; gpio_matrix_out = 0x400006dc; -gpio_output_disable = 0x400006e0; -gpio_output_enable = 0x400006e4; +/* gpio_output_disable = 0x400006e0; */ +/* gpio_output_enable = 0x400006e4; */ gpio_output_set = 0x400006e8; gpio_pad_hold = 0x400006ec; gpio_pad_input_disable = 0x400006f0; diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.ld index 7ef283388df1..645b536924c7 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.ld @@ -260,8 +260,8 @@ gpio_get_input_level = 0x400006f0; gpio_matrix_in = 0x400006f4; gpio_matrix_out = 0x400006f8; gpio_bypass_matrix_in = 0x400006fc; -gpio_output_disable = 0x40000700; -gpio_output_enable = 0x40000704; +/* gpio_output_disable = 0x40000700; */ +/* gpio_output_enable = 0x40000704; */ gpio_pad_input_disable = 0x40000708; gpio_pad_input_enable = 0x4000070c; gpio_pad_pulldown = 0x40000710; diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.net80211.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.net80211.ld index 82727daf2414..230c560b3dfe 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.net80211.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.net80211.ld @@ -60,7 +60,7 @@ ieee80211_find_ext_elem = 0x40000b18; ieee80211_find_ie = 0x40000b1c; ieee80211_find_ext_ie = 0x40000b20; ieee80211_merge_mbssid_profile = 0x40000b24; -ieee80211_encap_esfbuf_htc = 0x40000b28; +/*ieee80211_encap_esfbuf_htc = 0x40000b28;*/ wifi_get_macaddr = 0x40000b2c; wifi_rf_phy_disable = 0x40000b30; wifi_rf_phy_enable = 0x40000b34; diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.pp.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.pp.ld index f23dfdec23ea..2bdc202eb758 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.pp.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.pp.ld @@ -27,14 +27,14 @@ esf_buf_recycle = 0x40000b64; GetAccess = 0x40000b68; hal_mac_is_low_rate_enabled = 0x40000b6c; hal_mac_tx_get_blockack = 0x40000b70; -hal_mac_tx_set_ppdu = 0x40000b74; +/*hal_mac_tx_set_ppdu = 0x40000b74;*/ hal_mac_tx_clr_mplen = 0x40000b78; hal_mac_get_txq_state = 0x40000b7c; hal_mac_clr_txq_state = 0x40000b80; hal_mac_get_txq_complete = 0x40000b84; hal_mac_deinit_twt_tx = 0x40000b88; hal_mac_is_dma_enable = 0x40000b8c; -hal_he_get_bss_color = 0x40000b90; +/*hal_he_get_bss_color = 0x40000b90;*/ hal_he_set_ersu = 0x40000b94; hal_he_get_mplen_addr_start = 0x40000b98; hal_he_get_mplen_addr_end = 0x40000b9c; @@ -113,7 +113,7 @@ pm_disable_sleep_delay_timer = 0x40000cbc; pm_dream = 0x40000cc0; pm_mac_wakeup = 0x40000cc4; pm_mac_sleep = 0x40000cc8; -pm_enable_active_timer = 0x40000ccc; +/*pm_enable_active_timer = 0x40000ccc;*/ pm_enable_sleep_delay_timer = 0x40000cd0; pm_local_tsf_process = 0x40000cd4; pm_set_beacon_filter = 0x40000cd8; @@ -184,7 +184,7 @@ ppGetTxframe = 0x40000dd8; ppMapTxQueue = 0x40000ddc; ppProcTxSecFrame = 0x40000de0; ppProcessRxPktHdr = 0x40000de4; -ppProcessTxQ = 0x40000de8; +/*ppProcessTxQ = 0x40000de8;*/ ppRecordBarRRC = 0x40000dec; ppRecycleAmpdu = 0x40000df0; ppRecycleRxPkt = 0x40000df4; @@ -225,7 +225,7 @@ pp_coex_tx_release = 0x40000e7c; ppAdd2AMPDUTail = 0x40000e80; ppDirectRecycleAmpdu = 0x40000e84; ppRegressAmpdu = 0x40000e88; -pp_timer_do_process = 0x40000e8c; +/*pp_timer_do_process = 0x40000e8c;*/ rcGetAmpduSched = 0x40000e90; rcUpdateRxDone = 0x40000e94; rc_get_trc = 0x40000e98; diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.systimer.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.systimer.ld index 7be47b111051..9f260f5ecd4d 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.systimer.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.systimer.ld @@ -9,8 +9,9 @@ ***************************************/ /* Functions */ -systimer_hal_init = 0x400003d0; -systimer_hal_deinit = 0x400003d4; +/* The following ROM functions are commented out because they're patched in the esp_rom_systimer.c */ +/* systimer_hal_init = 0x400003d0; */ +/* systimer_hal_deinit = 0x400003d4; */ systimer_hal_set_tick_rate_ops = 0x400003d8; systimer_hal_get_counter_value = 0x400003dc; systimer_hal_get_time = 0x400003e0; diff --git a/components/esp_rom/esp32h2/ld/esp32h2.rom.ld b/components/esp_rom/esp32h2/ld/esp32h2.rom.ld index 8000e80f1c25..b7b8775614eb 100644 --- a/components/esp_rom/esp32h2/ld/esp32h2.rom.ld +++ b/components/esp_rom/esp32h2/ld/esp32h2.rom.ld @@ -226,8 +226,8 @@ ets_clk_get_cpu_freq = 0x4000069c; gpio_input_get = 0x400006a0; gpio_matrix_in = 0x400006a4; gpio_matrix_out = 0x400006a8; -gpio_output_disable = 0x400006ac; -gpio_output_enable = 0x400006b0; +/* gpio_output_disable = 0x400006ac; */ +/* gpio_output_enable = 0x400006b0; */ gpio_output_set = 0x400006b4; gpio_pad_hold = 0x400006b8; gpio_pad_input_disable = 0x400006bc; diff --git a/components/esp_rom/esp32p4/ld/esp32p4.rom.ld b/components/esp_rom/esp32p4/ld/esp32p4.rom.ld index 6b8f14bf60e7..1ddf2b794516 100644 --- a/components/esp_rom/esp32p4/ld/esp32p4.rom.ld +++ b/components/esp_rom/esp32p4/ld/esp32p4.rom.ld @@ -301,8 +301,8 @@ gpio_get_input_level = 0x4fc00568; gpio_matrix_in = 0x4fc0056c; gpio_matrix_out = 0x4fc00570; gpio_bypass_matrix_in = 0x4fc00574; -gpio_output_disable = 0x4fc00578; -gpio_output_enable = 0x4fc0057c; +/* gpio_output_disable = 0x4fc00578; */ +/* gpio_output_enable = 0x4fc0057c; */ gpio_pad_input_disable = 0x4fc00580; gpio_pad_input_enable = 0x4fc00584; gpio_pad_pulldown = 0x4fc00588; diff --git a/components/esp_rom/esp32p4/ld/esp32p4lp.rom.ld b/components/esp_rom/esp32p4/ld/esp32p4lp.rom.ld index ad9dbf3971be..7fba13bd4bd8 100644 --- a/components/esp_rom/esp32p4/ld/esp32p4lp.rom.ld +++ b/components/esp_rom/esp32p4/ld/esp32p4lp.rom.ld @@ -44,8 +44,8 @@ gpio_matrix_in = 0x501000d4; gpio_matrix_out = 0x501000d8; gpio_bypass_matrix_in = 0x501000dc; gpio_output_disable = 0x501000e0; -gpio_output_enable = 0x501000e4; -gpio_pad_input_disable = 0x501000e8; +/* gpio_output_enable = 0x501000e4; */ +/* gpio_pad_input_disable = 0x501000e8; */ gpio_pad_input_enable = 0x501000ec; gpio_pad_pulldown = 0x501000f0; gpio_pad_pullup = 0x501000f4; diff --git a/components/esp_rom/esp32p4/ld/esp32p4lp.rom.newlib.ld b/components/esp_rom/esp32p4/ld/esp32p4lp.rom.newlib.ld index d4936c7833c1..ab46640b20bc 100644 --- a/components/esp_rom/esp32p4/ld/esp32p4lp.rom.newlib.ld +++ b/components/esp_rom/esp32p4/ld/esp32p4lp.rom.newlib.ld @@ -1,12 +1,12 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ /* ROM function interface esp32p4lp.rom.newlib.ld for esp32p4lp * * - * Generated from ./target/esp32p4lp/interface-esp32p4lp.yml md5sum 0751c805e21bd23f11b74dcc1f7e8007 + * Generated from ./target/esp32p4lp/interface-esp32p4lp.yml md5sum f827caf806e9f4faec384ffbde44b380 * * Compatible with ROM where ECO version equal or greater to 0. * @@ -18,60 +18,60 @@ ***************************************/ /* Functions */ -memset = 0x501000f0; -memcpy = 0x501000f4; -memmove = 0x501000f8; -memcmp = 0x501000fc; -strcpy = 0x50100100; -strncpy = 0x50100104; -strcmp = 0x50100108; -strncmp = 0x5010010c; -strlen = 0x50100110; -strstr = 0x50100114; -bzero = 0x50100118; -isalnum = 0x5010011c; -isalpha = 0x50100120; -isascii = 0x50100124; -isblank = 0x50100128; -iscntrl = 0x5010012c; -isdigit = 0x50100130; -islower = 0x50100134; -isgraph = 0x50100138; -isprint = 0x5010013c; -ispunct = 0x50100140; -isspace = 0x50100144; -isupper = 0x50100148; -toupper = 0x5010014c; -tolower = 0x50100150; -toascii = 0x50100154; -memccpy = 0x50100158; -memchr = 0x5010015c; -memrchr = 0x50100160; -strcasecmp = 0x50100164; -strcasestr = 0x50100168; -strcat = 0x5010016c; -strchr = 0x50100170; -strcspn = 0x50100174; -strcoll = 0x50100178; -strlcat = 0x5010017c; -strlcpy = 0x50100180; -strlwr = 0x50100184; -strncasecmp = 0x50100188; -strncat = 0x5010018c; -strnlen = 0x50100190; -strrchr = 0x50100194; -strsep = 0x50100198; -strspn = 0x5010019c; -strtok_r = 0x501001a0; -strupr = 0x501001a4; -longjmp = 0x501001a8; -setjmp = 0x501001ac; -abs = 0x501001b0; -div = 0x501001b4; -labs = 0x501001b8; -ldiv = 0x501001bc; -qsort = 0x501001c0; -atoi = 0x501001c4; -atol = 0x501001c8; -itoa = 0x501001cc; -utoa = 0x501001d0; +memset = 0x50100134; +memcpy = 0x50100138; +memmove = 0x5010013c; +memcmp = 0x50100140; +strcpy = 0x50100144; +strncpy = 0x50100148; +strcmp = 0x5010014c; +strncmp = 0x50100150; +strlen = 0x50100154; +strstr = 0x50100158; +bzero = 0x5010015c; +isalnum = 0x50100160; +isalpha = 0x50100164; +isascii = 0x50100168; +isblank = 0x5010016c; +iscntrl = 0x50100170; +isdigit = 0x50100174; +islower = 0x50100178; +isgraph = 0x5010017c; +isprint = 0x50100180; +ispunct = 0x50100184; +isspace = 0x50100188; +isupper = 0x5010018c; +toupper = 0x50100190; +tolower = 0x50100194; +toascii = 0x50100198; +memccpy = 0x5010019c; +memchr = 0x501001a0; +memrchr = 0x501001a4; +strcasecmp = 0x501001a8; +strcasestr = 0x501001ac; +strcat = 0x501001b0; +strchr = 0x501001b4; +strcspn = 0x501001b8; +strcoll = 0x501001bc; +strlcat = 0x501001c0; +strlcpy = 0x501001c4; +strlwr = 0x501001c8; +strncasecmp = 0x501001cc; +strncat = 0x501001d0; +strnlen = 0x501001d4; +strrchr = 0x501001d8; +strsep = 0x501001dc; +strspn = 0x501001e0; +strtok_r = 0x501001e4; +strupr = 0x501001e8; +longjmp = 0x501001ec; +setjmp = 0x501001f0; +abs = 0x501001f4; +div = 0x501001f8; +labs = 0x501001fc; +ldiv = 0x50100200; +qsort = 0x50100204; +atoi = 0x50100208; +atol = 0x5010020c; +itoa = 0x50100210; +utoa = 0x50100214; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_50.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_50.ld new file mode 100644 index 000000000000..10cc038cc3bf --- /dev/null +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_50.ld @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32s3.rom.ld for esp32s3 + * + * + * Generated from ./interface-esp32s3.yml md5sum 39c4ce259b11323b9404c192b01b712b + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* extend adv */ +f_hci_le_set_ext_adv_param_cmd_handler = 0x40000000; +f_hci_le_set_adv_set_rand_addr_cmd_handler = 0x40000000; +f_hci_le_set_ext_adv_data_cmd_handler = 0x40000000; +f_hci_le_set_ext_scan_rsp_data_cmd_handler = 0x40000000; +f_hci_le_set_ext_adv_en_cmd_handler = 0x40000000; +f_hci_le_rd_max_adv_data_len_cmd_handler = 0x40000000; +f_hci_le_rd_nb_supp_adv_sets_cmd_handler = 0x40000000; +f_hci_le_rmv_adv_set_cmd_handler = 0x40000000; +f_hci_le_clear_adv_sets_cmd_handler = 0x40000000; +r_lld_adv_sync_info_set = 0x40000000; + +r_lld_ext_adv_dynamic_pti_process = 0x40000000; +r_lld_adv_ext_chain_construct = 0x40000000; +r_lld_adv_aux_evt_canceled_cbk = 0x40000000; +r_lld_adv_aux_evt_start_cbk = 0x40000000; +r_lld_adv_aux_ch_idx_set = 0x40000000; + +/* periodic adv */ +f_hci_le_set_per_adv_param_cmd_handler = 0x40000000; +f_hci_le_set_per_adv_data_cmd_handler = 0x40000000; +f_hci_le_set_per_adv_en_cmd_handler = 0x40000000; +r_lld_per_adv_ch_map_update = 0x40000000; +r_lld_per_adv_init = 0x40000000; + +/* PA list */ +f_hci_le_add_dev_to_per_adv_list_cmd_handler = 0x40000000; +f_hci_le_rmv_dev_from_per_adv_list_cmd_handler = 0x40000000; +f_hci_le_clear_per_adv_list_cmd_handler = 0x40000000; +f_hci_le_rd_per_adv_list_size_cmd_handler = 0x40000000; + +/* extend scan */ +f_hci_le_set_ext_scan_param_cmd_handler = 0x40000000; +f_hci_le_set_ext_scan_en_cmd_handler = 0x40000000; +r_lld_scan_process_pkt_rx_ext_adv = 0x40000000; +r_lld_scan_trunc_ind = 0x40000000; + +/* extend con */ +f_hci_le_ext_create_con_cmd_handler = 0x40000000; +r_lld_init_process_pkt_rx_adv_ext_ind = 0x40000000; +r_lld_init_process_pkt_rx_aux_connect_rsp = 0x40000000; + +/* PA sync */ +f_hci_le_per_adv_create_sync_cmd_handler = 0x40000000; +f_hci_le_per_adv_create_sync_cancel_cmd_handler = 0x40000000; +f_hci_le_per_adv_term_sync_cmd_handler = 0x40000000; +f_lld_per_adv_rx_end_ind_handler_hack = 0x40000000; +f_lld_sync_start_req_handler = 0x40000000; +f_lld_per_adv_rep_ind_handler = 0x40000000; +r_lld_sync_init = 0x40000000; + +/* phy update*/ +r_phy_upd_proc_start = 0x40000000; +f_llc_op_phy_upd_ind_handler = 0x40000000; +f_ll_phy_req_handler = 0x40000000; +f_ll_phy_rsp_handler = 0x40000000; +f_ll_phy_update_ind_handler = 0x40000000; +f_lld_phy_upd_cfm_handler = 0x40000000; +f_hci_le_set_phy_cmd_handler = 0x40000000; +llc_llcp_phy_update_ind_ack = 0x40000000; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_cca.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_cca.ld new file mode 100644 index 000000000000..74d2dca0e301 --- /dev/null +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_cca.ld @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32s3.rom.ld for esp32s3 + * + * + * Generated from ./interface-esp32s3.yml md5sum 39c4ce259b11323b9404c192b01b712b + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* SW CCA */ +r_lld_cca_con_evt_start_handle = 0x40000000; +r_lld_hw_cca_end_isr = 0x40000000; +r_lld_hw_cca_isr_eco = 0x40000000; +r_lld_cca_bb_sync_found_handle = 0x40000000; +r_lld_cca_data_reset = 0x40000000; +r_lld_cca_sw_init = 0x40000000; +r_lld_cca_con_evt_end_handle = 0x40000000; +r_lld_cca_alloc = 0x40000000; +r_lld_cca_sw_alloc = 0x40000000; +r_lld_cca_sw_free = 0x40000000; +r_lld_cca_free = 0x40000000; +r_cca_init = 0x40000000; +r_lld_hw_cca_evt_handler = 0x40000000; +r_lld_sw_cca_evt_handler = 0x40000000; +r_ble_sw_cca_check_isr = 0x40000000; +bt_bb_tx_cca_set = 0x40000000; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_dtm.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_dtm.ld new file mode 100644 index 000000000000..e08545c7179a --- /dev/null +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_dtm.ld @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32s3.rom.ld for esp32s3 + * + * + * Generated from ./interface-esp32s3.yml md5sum 39c4ce259b11323b9404c192b01b712b + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* DTM */ +f_hci_le_rx_test_cmd_handler = 0x40000000; +f_hci_le_tx_test_cmd_handler = 0x40000000; +f_hci_le_enh_rx_test_cmd_handler = 0x40000000; +f_hci_le_enh_tx_test_cmd_handler = 0x40000000; +f_hci_le_test_end_cmd_handler = 0x40000000; +r_lld_test_init = 0x40000000; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_master.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_master.ld new file mode 100644 index 000000000000..498330a68049 --- /dev/null +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_master.ld @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32s3.rom.ld for esp32s3 + * + * + * Generated from ./interface-esp32s3.yml md5sum 39c4ce259b11323b9404c192b01b712b + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* master */ +f_hci_le_create_con_cmd_handler = 0x40000000; +f_hci_le_create_con_cancel_cmd_handler = 0x40000000; +lld_init_end_ind_handler = 0x40000000; +r_lld_init_init = 0x40000000; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_scan.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_scan.ld new file mode 100644 index 000000000000..c3c8414e516b --- /dev/null +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_scan.ld @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32s3.rom.ld for esp32s3 + * + * + * Generated from ./interface-esp32s3.yml md5sum 39c4ce259b11323b9404c192b01b712b + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + + +/* BLE scan */ + +f_hci_le_set_scan_param_cmd_handler = 0x40000000; +f_hci_le_set_scan_en_cmd_handler = 0x40000000; +f_llm_scan_period_to_handler_hack = 0x40000000; +f_lld_adv_rep_ind_handler_hack = 0x40000000; +r_lld_scan_init = 0x40000000; +r_lld_scan_restart = 0x40000000; +f_lld_scan_end_ind_handler_hack = 0x40000000; +r_llm_env_adv_dup_filt_deinit_eco = 0x40000000; +llm_exception_list_init = 0x40000000; +llm_duplicate_list_init = 0x40000000; +f_hci_vendor_ble_update_duplicate_exceptional_list_cmd_handler = 0x40000000; +f_hci_vendor_ble_init_adv_flow_control_cmd_handler = 0x40000000; +f_hci_vendor_ble_update_adv_report_flow_control_cmd_handler = 0x40000000; +coex_schm_ble_scan_stop = 0x40000000; + +f_hci_le_set_ext_scan_param_cmd_handler = 0x40000000; +f_hci_le_set_ext_scan_en_cmd_handler = 0x40000000; +r_lld_scan_process_pkt_rx_ext_adv = 0x40000000; +r_lld_scan_trunc_ind = 0x40000000; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_smp.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_smp.ld new file mode 100644 index 000000000000..78d1fb9784a7 --- /dev/null +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_smp.ld @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32s3.rom.ld for esp32s3 + * + * + * Generated from ./interface-esp32s3.yml md5sum 39c4ce259b11323b9404c192b01b712b + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/* SMP */ +f_ll_pause_enc_req_handler = 0x40000000; +f_ll_pause_enc_rsp_handler = 0x40000000; +f_ll_enc_req_handler = 0x40000000; +f_ll_enc_rsp_handler = 0x40000000; +f_ll_start_enc_req_handler = 0x40000000; +f_ll_start_enc_rsp_handler = 0x40000000; +f_hci_le_start_enc_cmd_handler = 0x40000000; +f_hci_le_ltk_req_reply_cmd_handler = 0x40000000; +f_hci_le_ltk_req_neg_reply_cmd_handler = 0x40000000; +f_llc_encrypt_ind_handler = 0x40000000; +f_llc_op_encrypt_ind_handler = 0x40000000; +f_hci_le_rd_local_p256_public_key_cmd_handler = 0x40000000; +f_hci_le_generate_dhkey_cmd_handler = 0x40000000; +f_hci_le_enc_cmd_handler = 0x40000000; +r_rwip_crypt_evt_handler = 0x40000000; + +/* LE ping */ +f_ll_ping_req_handler = 0x40000000; +f_ll_ping_rsp_handler = 0x40000000; +r_llc_le_ping_set = 0x40000000; +r_llc_le_ping_restart = 0x40000000; +f_llc_op_le_ping_ind_handler = 0x40000000; +f_llc_auth_payl_nearly_op_handler = 0x40000000; +f_llc_auth_payl_real_to_handler = 0x40000000; +f_llc_auth_payl_nearly_to_handler = 0x40000000; + +/* ecc */ +r_ecc_init = 0x40000000; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_test.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_test.ld new file mode 100644 index 000000000000..1c0a6b59f0a3 --- /dev/null +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_test.ld @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32s3.rom.ld for esp32s3 + * + * + * Generated from ./interface-esp32s3.yml md5sum 39c4ce259b11323b9404c192b01b712b + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + + +/* overwrite */ +lld_acl_rx_ind_handler = 0x40000000; +lld_con_estab_ind_handler = 0x40000000; +lld_adv_rep_ind_handler = 0x40000000; +llm_rpa_renew_to_handler = 0x40000000; +lld_scan_end_ind_handler = 0x40000000; +llm_scan_period_to_handler = 0x40000000; + +/* nvds */ +r_nvds_init = 0x40000000; +f_nvds_get = 0x40000000; +f_nvds_del = 0x40000000; +f_nvds_put = 0x40000000; + +/* controller flash */ +r_flash_init = 0x40000000; +r_flash_env_init = 0x40000000; +r_flash_env_deinit = 0x40000000; + +/* QA test */ +f_hci_vendor_ble_qa_test_cmd_handler = 0x40000000; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld new file mode 100644 index 000000000000..de1ad1875332 --- /dev/null +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld @@ -0,0 +1,874 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32s3.rom.ld for esp32s3 + * + * + * Generated from ./interface-esp32s3.yml md5sum 39c4ce259b11323b9404c192b01b712b + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/*************************************** + Group bluetooth + ***************************************/ + +/* Functions */ +bt_rf_coex_get_dft_cfg = 0x40002a78; +bt_rf_coex_hooks_p_set = 0x40002a84; +btdm_con_maxevtime_cal_impl = 0x40002a90; +btdm_controller_get_compile_version_impl = 0x40002a9c; +btdm_controller_rom_data_init = 0x40002aa8; +btdm_dis_privacy_err_report_impl = 0x40002ab4; +btdm_disable_adv_delay_impl = 0x40002ac0; +btdm_enable_scan_continue_impl = 0x40002acc; +btdm_enable_scan_forever_impl = 0x40002ad8; +btdm_get_power_state_impl = 0x40002ae4; +btdm_get_prevent_sleep_flag_impl = 0x40002af0; +btdm_power_state_active_impl = 0x40002afc; +btdm_switch_phy_coded_impl = 0x40002b08; +hci_acl_data_handler = 0x40002b14; +hci_disconnect_cmd_handler = 0x40002b20; +hci_le_con_upd_cmd_handler = 0x40002b2c; +hci_le_ltk_req_neg_reply_cmd_handler = 0x40002b38; +hci_le_ltk_req_reply_cmd_handler = 0x40002b44; +hci_le_rd_chnl_map_cmd_handler = 0x40002b50; +hci_le_rd_phy_cmd_handler = 0x40002b5c; +hci_le_rd_rem_feats_cmd_handler = 0x40002b68; +hci_le_rem_con_param_req_neg_reply_cmd_handler = 0x40002b74; +hci_le_rem_con_param_req_reply_cmd_handler = 0x40002b80; +hci_le_set_data_len_cmd_handler = 0x40002b8c; +hci_le_set_phy_cmd_handler = 0x40002b98; +hci_le_start_enc_cmd_handler = 0x40002ba4; +hci_rd_auth_payl_to_cmd_handler = 0x40002bb0; +hci_rd_rem_ver_info_cmd_handler = 0x40002bbc; +hci_rd_rssi_cmd_handler = 0x40002bc8; +hci_rd_tx_pwr_lvl_cmd_handler = 0x40002bd4; +hci_vs_set_pref_slave_evt_dur_cmd_handler = 0x40002be0; +hci_vs_set_pref_slave_latency_cmd_handler = 0x40002bec; +hci_wr_auth_payl_to_cmd_handler = 0x40002bf8; +ll_channel_map_ind_handler = 0x40002c04; +ll_connection_param_req_handler = 0x40002c10; +ll_connection_param_rsp_handler = 0x40002c1c; +ll_connection_update_ind_handler = 0x40002c28; +ll_enc_req_handler = 0x40002c34; +ll_enc_rsp_handler = 0x40002c40; +ll_feature_req_handler = 0x40002c4c; +ll_feature_rsp_handler = 0x40002c58; +ll_length_req_handler = 0x40002c64; +ll_length_rsp_handler = 0x40002c70; +ll_min_used_channels_ind_handler = 0x40002c7c; +ll_pause_enc_req_handler = 0x40002c88; +ll_pause_enc_rsp_handler = 0x40002c94; +ll_phy_req_handler = 0x40002ca0; +ll_phy_rsp_handler = 0x40002cac; +ll_phy_update_ind_handler = 0x40002cb8; +ll_ping_req_handler = 0x40002cc4; +ll_ping_rsp_handler = 0x40002cd0; +ll_slave_feature_req_handler = 0x40002cdc; +ll_start_enc_req_handler = 0x40002ce8; +ll_start_enc_rsp_handler = 0x40002cf4; +ll_terminate_ind_handler = 0x40002d00; +ll_version_ind_handler = 0x40002d0c; +llc_auth_payl_nearly_to_handler = 0x40002d18; +llc_auth_payl_real_to_handler = 0x40002d24; +llc_encrypt_ind_handler = 0x40002d30; +llc_hci_command_handler_wrapper = 0x40002d3c; +llc_ll_connection_param_req_pdu_send = 0x40002d48; +llc_ll_connection_param_rsp_pdu_send = 0x40002d54; +llc_ll_connection_update_ind_pdu_send = 0x40002d60; +llc_ll_enc_req_pdu_send = 0x40002d6c; +llc_ll_enc_rsp_pdu_send = 0x40002d78; +llc_ll_feature_req_pdu_send = 0x40002d84; +llc_ll_feature_rsp_pdu_send = 0x40002d90; +llc_ll_length_req_pdu_send = 0x40002d9c; +llc_ll_length_rsp_pdu_send = 0x40002da8; +llc_ll_pause_enc_req_pdu_send = 0x40002db4; +llc_ll_pause_enc_rsp_pdu_send = 0x40002dc0; +llc_ll_phy_req_pdu_send = 0x40002dcc; +llc_ll_phy_rsp_pdu_send = 0x40002dd8; +llc_ll_ping_req_pdu_send = 0x40002de4; +llc_ll_ping_rsp_pdu_send = 0x40002df0; +llc_ll_start_enc_req_pdu_send = 0x40002dfc; +llc_ll_start_enc_rsp_pdu_send = 0x40002e08; +llc_ll_terminate_ind_pdu_send = 0x40002e14; +llc_ll_unknown_rsp_pdu_send = 0x40002e20; +llc_llcp_ch_map_update_ind_pdu_send = 0x40002e2c; +llc_llcp_phy_upd_ind_pdu_send = 0x40002e38; +llc_llcp_version_ind_pdu_send = 0x40002e44; +llc_op_ch_map_upd_ind_handler = 0x40002e50; +llc_op_con_upd_ind_handler = 0x40002e5c; +llc_op_disconnect_ind_handler = 0x40002e68; +llc_op_dl_upd_ind_handler = 0x40002e74; +llc_op_encrypt_ind_handler = 0x40002e80; +llc_op_feats_exch_ind_handler = 0x40002e8c; +llc_op_le_ping_ind_handler = 0x40002e98; +llc_op_phy_upd_ind_handler = 0x40002ea4; +llc_op_ver_exch_ind_handler = 0x40002eb0; +llc_stopped_ind_handler = 0x40002ebc; +lld_acl_rx_ind_handler = 0x40002ec8; +lld_acl_tx_cfm_handler = 0x40002ed4; +lld_adv_end_ind_handler = 0x40002ee0; +lld_adv_rep_ind_handler = 0x40002eec; +lld_ch_map_upd_cfm_handler = 0x40002ef8; +lld_con_estab_ind_handler = 0x40002f04; +lld_con_evt_sd_evt_time_set = 0x40002f10; +lld_con_offset_upd_ind_handler = 0x40002f1c; +lld_con_param_upd_cfm_handler = 0x40002f28; +lld_disc_ind_handler = 0x40002f34; +lld_init_end_ind_handler = 0x40002f40; +lld_llcp_rx_ind_handler_wrapper = 0x40002f4c; +lld_llcp_tx_cfm_handler = 0x40002f58; +lld_per_adv_end_ind_handler = 0x40002f64; +lld_per_adv_rep_ind_handler = 0x40002f70; +lld_per_adv_rx_end_ind_handler = 0x40002f7c; +lld_phy_coded_500k_get = 0x40002f88; +lld_phy_upd_cfm_handler = 0x40002f94; +lld_scan_end_ind_handler = 0x40002fa0; +lld_scan_req_ind_handler = 0x40002fac; +lld_sync_start_req_handler = 0x40002fb8; +lld_test_end_ind_handler = 0x40002fc4; +lld_update_rxbuf_handler = 0x40002fd0; +llm_ch_map_update_ind_handler = 0x40002fdc; +llm_hci_command_handler_wrapper = 0x40002fe8; +llm_scan_period_to_handler = 0x40002ff4; +r_Add2SelfBigHex256 = 0x40003000; +r_AddBigHex256 = 0x4000300c; +r_AddBigHexModP256 = 0x40003018; +r_AddP256 = 0x40003024; +r_AddPdiv2_256 = 0x40003030; +r_GF_Jacobian_Point_Addition256 = 0x4000303c; +r_GF_Jacobian_Point_Double256 = 0x40003048; +r_GF_Point_Jacobian_To_Affine256 = 0x40003054; +r_MultiplyBigHexByUint32_256 = 0x40003060; +r_MultiplyBigHexModP256 = 0x4000306c; +r_MultiplyByU16ModP256 = 0x40003078; +r_SubtractBigHex256 = 0x40003084; +r_SubtractBigHexMod256 = 0x40003090; +r_SubtractBigHexUint32_256 = 0x4000309c; +r_SubtractFromSelfBigHex256 = 0x400030a8; +r_SubtractFromSelfBigHexSign256 = 0x400030b4; +r_aes_alloc = 0x400030c0; +r_aes_ccm_continue = 0x400030cc; +r_aes_ccm_process_e = 0x400030d8; +r_aes_ccm_xor_128_lsb = 0x400030e4; +r_aes_ccm_xor_128_msb = 0x400030f0; +r_aes_cmac_continue = 0x400030fc; +r_aes_cmac_start = 0x40003108; +r_aes_k1_continue = 0x40003114; +r_aes_k2_continue = 0x40003120; +r_aes_k3_continue = 0x4000312c; +r_aes_k4_continue = 0x40003138; +r_aes_shift_left_128 = 0x40003144; +r_aes_start = 0x40003150; +r_aes_xor_128 = 0x4000315c; +r_assert_err = 0x40003168; +r_assert_param = 0x40003174; +r_assert_warn = 0x40003180; +r_bigHexInversion256 = 0x4000318c; +r_ble_sw_cca_check_isr = 0x40003198; +r_ble_util_buf_acl_tx_alloc = 0x400031a4; +r_ble_util_buf_acl_tx_elt_get = 0x400031b0; +r_ble_util_buf_acl_tx_free = 0x400031bc; +r_ble_util_buf_acl_tx_free_in_isr = 0x400031c8; +r_ble_util_buf_adv_tx_alloc = 0x400031d4; +r_ble_util_buf_adv_tx_free = 0x400031e0; +r_ble_util_buf_adv_tx_free_in_isr = 0x400031ec; +r_ble_util_buf_env_deinit = 0x400031f8; +r_ble_util_buf_env_init = 0x40003204; +r_ble_util_buf_get_rx_buf_nb = 0x40003210; +r_ble_util_buf_get_rx_buf_size = 0x4000321c; +r_ble_util_buf_llcp_tx_alloc = 0x40003228; +r_ble_util_buf_llcp_tx_free = 0x40003234; +r_ble_util_buf_rx_alloc = 0x40003240; +r_ble_util_buf_rx_alloc_in_isr = 0x4000324c; +r_ble_util_buf_rx_free = 0x40003258; +r_ble_util_buf_rx_free_in_isr = 0x40003264; +r_ble_util_buf_set_rx_buf_nb = 0x40003270; +r_ble_util_buf_set_rx_buf_size = 0x4000327c; +r_ble_util_data_rx_buf_reset = 0x40003288; +r_bt_bb_get_intr_mask = 0x40003294; +r_bt_bb_intr_clear = 0x400032a0; +r_bt_bb_intr_mask_set = 0x400032ac; +r_bt_rf_coex_cfg_set = 0x400032c4; +r_bt_rf_coex_conn_dynamic_pti_en_get = 0x400032d0; +r_bt_rf_coex_ext_adv_dynamic_pti_en_get = 0x400032e8; +r_bt_rf_coex_ext_scan_dynamic_pti_en_get = 0x400032f4; +r_bt_rf_coex_legacy_adv_dynamic_pti_en_get = 0x40003300; +r_bt_rf_coex_per_adv_dynamic_pti_en_get = 0x4000330c; +r_bt_rf_coex_pti_table_get = 0x40003318; +r_bt_rf_coex_st_param_get = 0x40003324; +r_bt_rf_coex_st_param_set = 0x40003330; +r_bt_rf_coex_sync_scan_dynamic_pti_en_get = 0x4000333c; +r_bt_rma_apply_rule_cs_fmt = 0x40003348; +r_bt_rma_apply_rule_cs_idx = 0x40003354; +r_bt_rma_configure = 0x40003360; +r_bt_rma_deregister_rule_cs_fmt = 0x4000336c; +r_bt_rma_deregister_rule_cs_idx = 0x40003378; +r_bt_rma_get_ant_by_act = 0x40003384; +r_bt_rma_init = 0x40003390; +r_bt_rma_register_rule_cs_fmt = 0x4000339c; +r_bt_rma_register_rule_cs_idx = 0x400033a8; +r_bt_rtp_apply_rule_cs_fmt = 0x400033b4; +r_bt_rtp_apply_rule_cs_idx = 0x400033c0; +r_bt_rtp_deregister_rule_cs_fmt = 0x400033cc; +r_bt_rtp_deregister_rule_cs_idx = 0x400033d8; +r_bt_rtp_init = 0x400033f0; +r_bt_rtp_register_rule_cs_fmt = 0x400033fc; +r_bt_rtp_register_rule_cs_idx = 0x40003408; +r_btdm_isr = 0x40003414; +r_cali_phase_match_p = 0x40003444; +r_cmp_abs_time = 0x40003450; +r_cmp_dest_id = 0x4000345c; +r_cmp_timer_id = 0x40003468; +r_co_bdaddr_compare = 0x40003474; +r_co_ble_pkt_dur_in_us = 0x40003480; +r_co_list_extract = 0x4000348c; +r_co_list_extract_after = 0x40003498; +r_co_list_extract_sublist = 0x400034a4; +r_co_list_find = 0x400034b0; +r_co_list_init = 0x400034bc; +r_co_list_insert_after = 0x400034c8; +r_co_list_insert_before = 0x400034d4; +r_co_list_merge = 0x400034e0; +r_co_list_pool_init = 0x400034ec; +r_co_list_pop_front = 0x400034f8; +r_co_list_push_back = 0x40003504; +r_co_list_push_back_sublist = 0x40003510; +r_co_list_push_front = 0x4000351c; +r_co_list_size = 0x40003528; +r_co_nb_good_le_channels = 0x40003534; +r_co_util_pack = 0x40003540; +r_co_util_read_array_size = 0x4000354c; +r_co_util_unpack = 0x40003558; +r_dbg_env_deinit = 0x40003564; +r_dbg_env_init = 0x40003570; +r_dbg_platform_reset_complete = 0x4000357c; +r_dl_upd_proc_start = 0x40003588; +r_dump_data = 0x40003594; +r_ecc_abort_key256_generation = 0x400035a0; +r_ecc_gen_new_public_key = 0x400035ac; +r_ecc_gen_new_secret_key = 0x400035b8; +r_ecc_generate_key256 = 0x400035c4; +r_ecc_get_debug_Keys = 0x400035d0; +r_ecc_init = 0x400035dc; +r_ecc_is_valid_point = 0x400035e8; +r_ecc_multiplication_event_handler = 0x400035f4; +r_ecc_point_multiplication_win_256 = 0x40003600; +r_emi_alloc_em_mapping_by_offset = 0x4000360c; +r_emi_base_reg_lut_show = 0x40003618; +r_emi_em_base_reg_show = 0x40003624; +r_emi_free_em_mapping_by_offset = 0x40003630; +r_emi_get_em_mapping_idx_by_offset = 0x4000363c; +r_emi_get_mem_addr_by_offset = 0x40003648; +r_emi_overwrite_em_mapping_by_offset = 0x40003654; +r_esp_vendor_hci_command_handler = 0x40003660; +r_get_stack_usage = 0x4000366c; +r_h4tl_acl_hdr_rx_evt_handler = 0x40003678; +r_h4tl_cmd_hdr_rx_evt_handler = 0x40003684; +r_h4tl_cmd_pld_rx_evt_handler = 0x40003690; +r_h4tl_eif_io_event_post = 0x4000369c; +r_h4tl_eif_register = 0x400036a8; +r_h4tl_init = 0x400036b4; +r_h4tl_out_of_sync = 0x400036c0; +r_h4tl_out_of_sync_check = 0x400036cc; +r_h4tl_read_hdr = 0x400036d8; +r_h4tl_read_next_out_of_sync = 0x400036e4; +r_h4tl_read_payl = 0x400036f0; +r_h4tl_read_start = 0x400036fc; +r_h4tl_rx_acl_hdr_extract = 0x40003708; +r_h4tl_rx_cmd_hdr_extract = 0x40003714; +r_h4tl_rx_done = 0x40003720; +r_h4tl_start = 0x4000372c; +r_h4tl_stop = 0x40003738; +r_h4tl_tx_done = 0x40003744; +r_h4tl_tx_evt_handler = 0x40003750; +r_h4tl_write = 0x4000375c; +r_hci_acl_tx_data_alloc = 0x40003768; +r_hci_acl_tx_data_received = 0x40003774; +r_hci_basic_cmd_send_2_controller = 0x40003780; +r_hci_ble_adv_report_filter_check = 0x4000378c; +r_hci_ble_adv_report_tx_check = 0x40003798; +r_hci_ble_conhdl_register = 0x400037a4; +r_hci_ble_conhdl_unregister = 0x400037b0; +r_hci_build_acl_data = 0x400037bc; +r_hci_build_cc_evt = 0x400037c8; +r_hci_build_cs_evt = 0x400037d4; +r_hci_build_evt = 0x400037e0; +r_hci_build_le_evt = 0x400037ec; +r_hci_cmd_get_max_param_size = 0x400037f8; +r_hci_cmd_received = 0x40003804; +r_hci_cmd_reject = 0x40003810; +r_hci_evt_mask_check = 0x4000381c; +r_hci_evt_mask_set = 0x40003828; +r_hci_fc_acl_buf_size_set = 0x40003834; +r_hci_fc_acl_en = 0x40003840; +r_hci_fc_acl_packet_sent = 0x4000384c; +r_hci_fc_check_host_available_nb_acl_packets = 0x40003858; +r_hci_fc_host_nb_acl_pkts_complete = 0x40003864; +r_hci_fc_init = 0x40003870; +r_hci_look_for_cmd_desc = 0x4000387c; +r_hci_look_for_evt_desc = 0x40003888; +r_hci_look_for_le_evt_desc = 0x40003894; +r_hci_look_for_le_evt_desc_esp = 0x400038a0; +r_hci_pack_bytes = 0x400038ac; +r_hci_send_2_controller = 0x400038c4; +r_hci_send_2_host = 0x400038d0; +r_hci_tl_c2h_data_flow_on = 0x400038dc; +r_hci_tl_cmd_hdr_rx_evt_handler = 0x400038e8; +r_hci_tl_cmd_pld_rx_evt_handler = 0x400038f4; +r_hci_tl_get_pkt = 0x40003900; +r_hci_tl_hci_pkt_handler = 0x4000390c; +r_hci_tl_hci_tx_done_evt_handler = 0x40003918; +r_hci_tl_inc_nb_h2c_cmd_pkts = 0x40003924; +r_hci_tl_save_pkt = 0x40003930; +r_hci_tl_send = 0x4000393c; +r_hci_tx_done = 0x40003948; +r_hci_tx_start = 0x40003954; +r_hci_tx_trigger = 0x40003960; +r_isValidSecretKey_256 = 0x4000396c; +r_ke_check_malloc = 0x40003978; +r_ke_event_callback_set = 0x40003984; +r_ke_event_clear = 0x40003990; +r_ke_event_flush = 0x4000399c; +r_ke_event_get = 0x400039a8; +r_ke_event_get_all = 0x400039b4; +r_ke_event_init = 0x400039c0; +r_ke_event_schedule = 0x400039cc; +r_ke_event_set = 0x400039d8; +r_ke_flush = 0x400039e4; +r_ke_free = 0x400039f0; +r_ke_handler_search = 0x400039fc; +r_ke_init = 0x40003a08; +r_ke_is_free = 0x40003a14; +r_ke_malloc = 0x40003a20; +r_ke_mem_init = 0x40003a2c; +r_ke_mem_is_empty = 0x40003a38; +r_ke_mem_is_in_heap = 0x40003a44; +r_ke_msg_alloc = 0x40003a50; +r_ke_msg_dest_id_get = 0x40003a5c; +r_ke_msg_discard = 0x40003a68; +r_ke_msg_forward = 0x40003a74; +r_ke_msg_forward_new_id = 0x40003a80; +r_ke_msg_free = 0x40003a8c; +r_ke_msg_in_queue = 0x40003a98; +r_ke_msg_save = 0x40003aa4; +r_ke_msg_send = 0x40003ab0; +r_ke_msg_send_basic = 0x40003abc; +r_ke_msg_src_id_get = 0x40003ac8; +r_ke_queue_extract = 0x40003ad4; +r_ke_queue_insert = 0x40003ae0; +r_ke_sleep_check = 0x40003aec; +r_ke_state_get = 0x40003af8; +r_ke_state_set = 0x40003b04; +r_ke_task_check = 0x40003b10; +r_ke_task_create = 0x40003b1c; +r_ke_task_delete = 0x40003b28; +r_ke_task_handler_get = 0x40003b34; +r_ke_task_init = 0x40003b40; +r_ke_task_msg_flush = 0x40003b4c; +r_ke_task_saved_update = 0x40003b58; +r_ke_time = 0x40003b70; +r_ke_time_cmp = 0x40003b7c; +r_ke_time_past = 0x40003b88; +r_ke_timer_active = 0x40003b94; +r_ke_timer_adjust_all = 0x40003ba0; +r_ke_timer_clear = 0x40003bac; +r_ke_timer_init = 0x40003bb8; +r_ke_timer_schedule = 0x40003bc4; +r_ke_timer_set = 0x40003bd0; +r_led_init = 0x40003bdc; +r_led_set_all = 0x40003be8; +r_llc_aes_res_cb = 0x40003bf4; +r_llc_ch_map_up_proc_err_cb = 0x40003c00; +r_llc_cleanup = 0x40003c0c; +r_llc_cmd_cmp_send = 0x40003c18; +r_llc_cmd_stat_send = 0x40003c24; +r_llc_con_move_cbk = 0x40003c30; +r_llc_con_plan_set_update = 0x40003c3c; +r_llc_con_upd_param_in_range = 0x40003c48; +r_llc_disconnect = 0x40003c54; +r_llc_disconnect_end = 0x40003c60; +r_llc_disconnect_proc_continue = 0x40003c6c; +r_llc_disconnect_proc_err_cb = 0x40003c78; +r_llc_dl_chg_check = 0x40003c84; +r_llc_dle_proc_err_cb = 0x40003c90; +r_llc_feats_exch_proc_err_cb = 0x40003c9c; +r_llc_hci_cmd_handler_tab_p_get = 0x40003ca8; +r_llc_hci_con_param_req_evt_send = 0x40003cc0; +r_llc_hci_con_upd_info_send = 0x40003ccc; +r_llc_hci_disconnected_dis = 0x40003cd8; +r_llc_hci_dl_upd_info_send = 0x40003ce4; +r_llc_hci_enc_evt_send = 0x40003cf0; +r_llc_hci_feats_info_send = 0x40003cfc; +r_llc_hci_le_phy_upd_cmp_evt_send = 0x40003d08; +r_llc_hci_ltk_request_evt_send = 0x40003d14; +r_llc_hci_nb_cmp_pkts_evt_send = 0x40003d20; +r_llc_hci_version_info_send = 0x40003d2c; +r_llc_init_term_proc = 0x40003d38; +r_llc_iv_skd_rand_gen = 0x40003d44; +r_llc_le_ping_proc_continue = 0x40003d50; +r_llc_le_ping_proc_err_cb = 0x40003d5c; +/* r_llc_le_ping_restart = 0x40003d68; */ +r_llc_le_ping_set = 0x40003d74; +r_llc_ll_pause_enc_rsp_ack_handler = 0x40003d80; +r_llc_ll_reject_ind_ack_handler = 0x40003d8c; +r_llc_ll_reject_ind_pdu_send = 0x40003d98; +r_llc_ll_start_enc_rsp_ack_handler = 0x40003da4; +r_llc_ll_terminate_ind_ack = 0x40003db0; +r_llc_ll_unknown_ind_handler = 0x40003dbc; +r_llc_llcp_send = 0x40003dc8; +r_llc_llcp_state_set = 0x40003dd4; +r_llc_llcp_trans_timer_set = 0x40003de0; +r_llc_llcp_tx_check = 0x40003dec; +/* r_llc_loc_ch_map_proc_continue = 0x40003df8; */ +r_llc_loc_con_upd_proc_err_cb = 0x40003e10; +r_llc_loc_dl_upd_proc_continue = 0x40003e1c; +r_llc_loc_encrypt_proc_continue = 0x40003e28; +r_llc_loc_encrypt_proc_err_cb = 0x40003e34; +r_llc_loc_feats_exch_proc_continue = 0x40003e40; +r_llc_loc_phy_upd_proc_err_cb = 0x40003e58; +r_llc_msg_handler_tab_p_get = 0x40003e64; +r_llc_pref_param_compute = 0x40003e70; +r_llc_proc_collision_check = 0x40003e7c; +r_llc_proc_err_ind = 0x40003e88; +r_llc_proc_get = 0x40003e94; +r_llc_proc_id_get = 0x40003ea0; +r_llc_proc_reg = 0x40003eac; +r_llc_proc_state_get = 0x40003eb8; +r_llc_proc_state_set = 0x40003ec4; +r_llc_proc_timer_pause_set = 0x40003ed0; +r_llc_proc_timer_set = 0x40003edc; +r_llc_proc_unreg = 0x40003ee8; +r_llc_rem_ch_map_proc_continue = 0x40003ef4; +r_llc_rem_con_upd_proc_err_cb = 0x40003f0c; +r_llc_rem_dl_upd_proc = 0x40003f18; +r_llc_rem_encrypt_proc_continue = 0x40003f24; +r_llc_rem_encrypt_proc_err_cb = 0x40003f30; +r_llc_rem_phy_upd_proc_continue = 0x40003f3c; +r_llc_rem_phy_upd_proc_err_cb = 0x40003f48; +r_llc_role_get = 0x40003f54; +r_llc_sk_gen = 0x40003f60; +r_llc_start = 0x40003f6c; +r_llc_stop = 0x40003f78; +r_llc_ver_exch_loc_proc_continue = 0x40003f84; +r_llc_ver_proc_err_cb = 0x40003f90; +r_llcp_pdu_handler_tab_p_get = 0x40003f9c; +r_lld_aa_gen = 0x40003fa8; +r_lld_adv_adv_data_set = 0x40003fb4; +r_lld_adv_adv_data_update = 0x40003fc0; +r_lld_adv_aux_ch_idx_set = 0x40003fcc; +r_lld_adv_aux_evt_canceled_cbk = 0x40003fd8; +r_lld_adv_aux_evt_start_cbk = 0x40003fe4; +r_lld_adv_coex_check_ext_adv_synced = 0x40003ff0; +r_lld_adv_coex_env_reset = 0x40003ffc; +r_lld_adv_duration_update = 0x40004008; +r_lld_adv_dynamic_pti_process = 0x40004014; +r_lld_adv_end = 0x40004020; +r_lld_adv_evt_canceled_cbk = 0x4000402c; +r_lld_adv_evt_start_cbk = 0x40004038; +r_lld_adv_ext_chain_construct = 0x40004044; +r_lld_adv_ext_pkt_prepare = 0x40004050; +r_lld_adv_frm_cbk = 0x4000405c; +r_lld_adv_frm_isr = 0x40004068; +r_lld_adv_frm_skip_isr = 0x40004074; +r_lld_adv_init = 0x40004080; +r_lld_adv_pkt_rx = 0x4000408c; +r_lld_adv_pkt_rx_connect_ind = 0x40004098; +r_lld_adv_pkt_rx_send_scan_req_evt = 0x400040a4; +r_lld_adv_rand_addr_update = 0x400040b0; +r_lld_adv_restart = 0x400040bc; +r_lld_adv_scan_rsp_data_set = 0x400040c8; +r_lld_adv_scan_rsp_data_update = 0x400040d4; +r_lld_adv_set_tx_power = 0x400040e0; +r_lld_adv_start = 0x400040ec; +r_lld_adv_stop = 0x400040f8; +r_lld_adv_sync_info_set = 0x40004104; +r_lld_adv_sync_info_update = 0x40004110; +r_lld_calc_aux_rx = 0x4000411c; +r_lld_cca_alloc = 0x40004128; +r_lld_cca_data_reset = 0x40004134; +r_lld_cca_free = 0x40004140; +r_lld_ch_assess_data_get = 0x4000414c; +r_lld_ch_idx_get = 0x40004158; +r_lld_ch_map_set = 0x40004164; +r_lld_channel_assess = 0x40004170; +r_lld_con_activity_act_offset_compute = 0x4000417c; +r_lld_con_activity_offset_compute = 0x40004188; +r_lld_con_ch_map_update = 0x40004194; +r_lld_con_cleanup = 0x400041a0; +r_lld_con_current_tx_power_get = 0x400041ac; +r_lld_con_data_flow_set = 0x400041b8; +r_lld_con_data_len_update = 0x400041c4; +r_lld_con_data_tx = 0x400041d0; +r_lld_con_enc_key_load = 0x400041dc; +r_lld_con_event_counter_get = 0x400041e8; +r_lld_con_evt_canceled_cbk = 0x400041f4; +r_lld_con_evt_duration_min_get = 0x40004200; +r_lld_con_evt_max_eff_time_cal = 0x4000420c; +r_lld_con_evt_sd_evt_time_get = 0x40004218; +r_lld_con_evt_start_cbk = 0x40004224; +r_lld_con_evt_time_update = 0x40004230; +r_lld_con_free_all_tx_buf = 0x4000423c; +r_lld_con_frm_cbk = 0x40004248; +r_lld_con_frm_isr = 0x40004254; +r_lld_con_frm_skip_isr = 0x40004260; +r_lld_con_init = 0x4000426c; +r_lld_con_llcp_tx = 0x40004278; +r_lld_con_max_lat_calc = 0x40004284; +r_lld_con_offset_get = 0x40004290; +r_lld_con_param_update = 0x4000429c; +r_lld_con_phys_update = 0x400042a8; +r_lld_con_pref_slave_evt_dur_set = 0x400042b4; +r_lld_con_pref_slave_latency_set = 0x400042c0; +r_lld_con_rssi_get = 0x400042cc; +r_lld_con_rx = 0x400042d8; +/* r_lld_con_rx_channel_assess = 0x400042e4; */ +r_lld_con_rx_enc = 0x400042f0; +r_lld_con_rx_isr = 0x400042fc; +r_lld_con_rx_link_info_check = 0x40004308; +r_lld_con_rx_llcp_check = 0x40004314; +r_lld_con_rx_sync_time_update = 0x40004320; +r_lld_con_set_tx_power = 0x40004338; +r_lld_con_start = 0x40004344; +r_lld_con_tx = 0x4000435c; +r_lld_con_tx_enc = 0x40004368; +r_lld_con_tx_isr = 0x40004374; +r_lld_con_tx_len_update = 0x40004380; +r_lld_con_tx_len_update_for_intv = 0x4000438c; +r_lld_con_tx_len_update_for_rate = 0x40004398; +r_lld_con_tx_prog = 0x400043a4; +r_lld_conn_dynamic_pti_process = 0x400043b0; +r_lld_continue_scan_rx_isr_end_process = 0x400043bc; +r_lld_ext_scan_dynamic_pti_process = 0x400043c8; +r_lld_hw_cca_end_isr = 0x400043d4; +r_lld_hw_cca_evt_handler = 0x400043e0; +r_lld_hw_cca_isr = 0x400043ec; +r_lld_init_cal_anchor_point = 0x400043f8; +r_lld_init_compute_winoffset = 0x40004404; +r_lld_init_connect_req_pack = 0x40004410; +r_lld_init_end = 0x4000441c; +r_lld_init_evt_canceled_cbk = 0x40004428; +r_lld_init_evt_start_cbk = 0x40004434; +r_lld_init_frm_cbk = 0x40004440; +r_lld_init_frm_eof_isr = 0x4000444c; +r_lld_init_frm_skip_isr = 0x40004458; +r_lld_init_init = 0x40004464; +r_lld_init_process_pkt_rx = 0x40004470; +r_lld_init_process_pkt_rx_adv_ext_ind = 0x4000447c; +r_lld_init_process_pkt_rx_adv_ind_or_direct_ind = 0x40004488; +r_lld_init_process_pkt_rx_aux_connect_rsp = 0x40004494; +r_lld_init_process_pkt_tx = 0x400044a0; +r_lld_init_process_pkt_tx_cal_con_timestamp = 0x400044ac; +r_lld_init_sched = 0x400044b8; +r_lld_init_set_tx_power = 0x400044c4; +r_lld_init_start = 0x400044d0; +r_lld_init_stop = 0x400044dc; +r_lld_instant_proc_end = 0x400044e8; +r_lld_per_adv_ch_map_update = 0x40004500; +r_lld_per_adv_chain_construct = 0x4000450c; +r_lld_per_adv_cleanup = 0x40004518; +r_lld_per_adv_coex_env_reset = 0x40004524; +r_lld_per_adv_data_set = 0x40004530; +r_lld_per_adv_data_update = 0x4000453c; +r_lld_per_adv_dynamic_pti_process = 0x40004548; +r_lld_per_adv_evt_canceled_cbk = 0x40004554; +r_lld_per_adv_evt_start_cbk = 0x40004560; +r_lld_per_adv_ext_pkt_prepare = 0x4000456c; +r_lld_per_adv_frm_cbk = 0x40004578; +r_lld_per_adv_frm_isr = 0x40004584; +r_lld_per_adv_frm_skip_isr = 0x40004590; +r_lld_per_adv_init = 0x4000459c; +r_lld_per_adv_init_info_get = 0x400045a8; +r_lld_per_adv_list_add = 0x400045b4; +r_lld_per_adv_list_rem = 0x400045c0; +r_lld_per_adv_set_tx_power = 0x400045d8; +r_lld_per_adv_start = 0x400045e4; +r_lld_per_adv_stop = 0x400045f0; +r_lld_per_adv_sync_info_get = 0x400045fc; +r_lld_process_cca_data = 0x40004608; +r_lld_ral_search = 0x40004614; +r_lld_read_clock = 0x40004620; +r_lld_res_list_add = 0x4000462c; +r_lld_res_list_is_empty = 0x40004644; +r_lld_res_list_local_rpa_get = 0x40004650; +r_lld_res_list_peer_rpa_get = 0x4000465c; +r_lld_res_list_peer_update = 0x40004668; +/* r_lld_res_list_priv_mode_update = 0x40004674; */ +r_lld_reset_reg = 0x4000468c; +r_lld_rpa_renew = 0x40004698; +r_lld_rpa_renew_evt_canceled_cbk = 0x400046a4; +r_lld_rpa_renew_evt_start_cbk = 0x400046b0; +r_lld_rpa_renew_instant_cbk = 0x400046bc; +r_lld_rxdesc_check = 0x400046c8; +r_lld_rxdesc_free = 0x400046d4; +r_lld_scan_create_sync = 0x400046e0; +r_lld_scan_create_sync_cancel = 0x400046ec; +r_lld_scan_end = 0x400046f8; +r_lld_scan_evt_canceled_cbk = 0x40004704; +r_lld_scan_evt_start_cbk = 0x40004710; +r_lld_scan_frm_cbk = 0x4000471c; +r_lld_scan_frm_eof_isr = 0x40004728; +r_lld_scan_frm_rx_isr = 0x40004734; +r_lld_scan_frm_skip_isr = 0x40004740; +r_lld_scan_init = 0x4000474c; +r_lld_scan_params_update = 0x40004758; +r_lld_scan_process_pkt_rx_aux_adv_ind = 0x4000477c; +r_lld_scan_process_pkt_rx_aux_chain_ind = 0x40004788; +r_lld_scan_process_pkt_rx_aux_scan_rsp = 0x40004794; +r_lld_scan_process_pkt_rx_ext_adv = 0x400047a0; +r_lld_scan_process_pkt_rx_ext_adv_ind = 0x400047ac; +r_lld_scan_process_pkt_rx_legacy_adv = 0x400047b8; +r_lld_scan_restart = 0x400047c4; +r_lld_scan_sched = 0x400047d0; +r_lld_scan_set_tx_power = 0x400047dc; +r_lld_scan_start = 0x400047e8; +r_lld_scan_stop = 0x400047f4; +r_lld_scan_sync_accept = 0x40004800; +r_lld_scan_sync_info_unpack = 0x4000480c; +r_lld_scan_trunc_ind = 0x40004818; +r_lld_sw_cca_evt_handler = 0x40004824; +r_lld_sw_cca_isr = 0x40004830; +r_lld_sync_ch_map_update = 0x4000483c; +r_lld_sync_cleanup = 0x40004848; +r_lld_sync_evt_canceled_cbk = 0x40004854; +r_lld_sync_evt_start_cbk = 0x40004860; +r_lld_sync_frm_cbk = 0x4000486c; +r_lld_sync_frm_eof_isr = 0x40004878; +r_lld_sync_frm_rx_isr = 0x40004884; +r_lld_sync_frm_skip_isr = 0x40004890; +r_lld_sync_init = 0x4000489c; +r_lld_sync_process_pkt_rx = 0x400048a8; +r_lld_sync_process_pkt_rx_aux_sync_ind = 0x400048b4; +r_lld_sync_process_pkt_rx_pkt_check = 0x400048c0; +r_lld_sync_scan_dynamic_pti_process = 0x400048cc; +r_lld_sync_sched = 0x400048d8; +r_lld_sync_start = 0x400048e4; +r_lld_sync_stop = 0x400048f0; +r_lld_sync_trunc_ind = 0x400048fc; +r_lld_test_cleanup = 0x40004908; +r_lld_test_evt_canceled_cbk = 0x40004914; +r_lld_test_evt_start_cbk = 0x40004920; +r_lld_test_freq2chnl = 0x4000492c; +r_lld_test_frm_cbk = 0x40004938; +r_lld_test_frm_isr = 0x40004944; +r_lld_test_init = 0x40004950; +r_lld_test_rx_isr = 0x4000495c; +r_lld_test_set_tx_power = 0x40004968; +r_lld_test_start = 0x40004974; +/* r_lld_test_stop = 0x40004980;*/ +r_lld_update_rxbuf = 0x4000498c; +r_lld_update_rxbuf_isr = 0x40004998; +r_lld_white_list_add = 0x400049a4; +r_lld_white_list_rem = 0x400049b0; +r_llm_activity_free_get = 0x400049bc; +r_llm_activity_free_set = 0x400049c8; +r_llm_activity_syncing_get = 0x400049d4; +r_llm_adv_con_len_check = 0x400049e0; +r_llm_adv_hdl_to_id = 0x400049ec; +r_llm_adv_rep_flow_control_check = 0x400049f8; +r_llm_adv_rep_flow_control_update = 0x40004a04; +r_llm_adv_reports_list_check = 0x40004a10; +r_llm_adv_set_all_release = 0x40004a1c; +r_llm_adv_set_dft_params = 0x40004a28; +r_llm_adv_set_release = 0x40004a34; +r_llm_aes_res_cb = 0x40004a40; +r_llm_ble_update_adv_flow_control = 0x40004a4c; +r_llm_ch_map_update = 0x40004a58; +r_llm_cmd_cmp_send = 0x40004a64; +r_llm_cmd_stat_send = 0x40004a70; +r_llm_dev_list_empty_entry = 0x40004a7c; +r_llm_dev_list_search = 0x40004a88; +r_llm_env_adv_dup_filt_deinit = 0x40004a94; +r_llm_env_adv_dup_filt_init = 0x40004aa0; +r_llm_init_ble_adv_report_flow_contol = 0x40004aac; +r_llm_is_dev_connected = 0x40004ab8; +r_llm_is_dev_synced = 0x40004ac4; +r_llm_is_non_con_act_ongoing_check = 0x40004ad0; +r_llm_is_wl_accessible = 0x40004adc; +r_llm_le_evt_mask_check = 0x40004ae8; +r_llm_link_disc = 0x40004b00; +r_llm_master_ch_map_get = 0x40004b0c; +r_llm_msg_handler_tab_p_get = 0x40004b18; +r_llm_no_activity = 0x40004b24; +r_llm_per_adv_slot_dur = 0x40004b30; +r_llm_plan_elt_get = 0x40004b3c; +r_llm_rx_path_comp_get = 0x40004b48; +r_llm_scan_start = 0x40004b54; +r_llm_scan_sync_acad_attach = 0x40004b60; +r_llm_scan_sync_acad_detach = 0x40004b6c; +r_llm_send_adv_lost_event_to_host = 0x40004b78; +r_llm_tx_path_comp_get = 0x40004b84; +r_misc_deinit = 0x40004b90; +r_misc_free_em_buf_in_isr = 0x40004b9c; +r_misc_init = 0x40004ba8; +r_misc_msg_handler_tab_p_get = 0x40004bb4; +r_notEqual256 = 0x40004bc0; +r_phy_upd_proc_start = 0x40004bcc; +r_platform_reset = 0x40004bd8; +r_rf_em_init = 0x40004bf0; +r_rf_force_agc_enable = 0x40004bfc; +r_rf_reg_rd = 0x40004c08; +r_rf_reg_wr = 0x40004c14; +r_rf_reset = 0x40004c20; +r_rf_rssi_convert = 0x40004c2c; +r_rf_rw_v9_le_disable = 0x40004c38; +r_rf_rw_v9_le_enable = 0x40004c44; +r_rf_sleep = 0x40004c50; +r_rf_util_cs_fmt_convert = 0x40004c74; +r_rw_crypto_aes_ccm = 0x40004c80; +r_rw_crypto_aes_encrypt = 0x40004c8c; +r_rw_crypto_aes_init = 0x40004c98; +r_rw_crypto_aes_k1 = 0x40004ca4; +r_rw_crypto_aes_k2 = 0x40004cb0; +r_rw_crypto_aes_k3 = 0x40004cbc; +r_rw_crypto_aes_k4 = 0x40004cc8; +r_rw_crypto_aes_rand = 0x40004cd4; +r_rw_crypto_aes_result_handler = 0x40004ce0; +r_rw_crypto_aes_s1 = 0x40004cec; +r_rw_cryto_aes_cmac = 0x40004cf8; +r_rw_v9_init_em_radio_table = 0x40004d04; +r_rwble_sleep_enter = 0x40004d1c; +r_rwble_sleep_wakeup_end = 0x40004d28; +/* r_rwbtdm_isr_wrapper = 0x40004d34; */ +r_rwip_active_check = 0x40004d40; +r_rwip_aes_encrypt = 0x40004d4c; +/* r_rwip_assert = 0x40004d58; */ +r_rwip_crypt_evt_handler = 0x40004d64; +r_rwip_crypt_isr_handler = 0x40004d70; +r_rwip_eif_get = 0x40004d7c; +r_rwip_half_slot_2_lpcycles = 0x40004d88; +r_rwip_hus_2_lpcycles = 0x40004d94; +r_rwip_isr = 0x40004da0; +r_rwip_lpcycles_2_hus = 0x40004dac; +r_rwip_prevent_sleep_clear = 0x40004db8; +r_rwip_prevent_sleep_set = 0x40004dc4; +r_rwip_schedule = 0x40004dd0; +r_rwip_sleep = 0x40004ddc; +r_rwip_sw_int_handler = 0x40004de8; +r_rwip_sw_int_req = 0x40004df4; +r_rwip_time_get = 0x40004e00; +r_rwip_timer_10ms_handler = 0x40004e0c; +r_rwip_timer_10ms_set = 0x40004e18; +r_rwip_timer_hs_handler = 0x40004e24; +r_rwip_timer_hs_set = 0x40004e30; +r_rwip_timer_hus_handler = 0x40004e3c; +r_rwip_timer_hus_set = 0x40004e48; +r_rwip_wakeup = 0x40004e54; +/* r_rwip_wakeup_end = 0x40004e60; */ +r_rwip_wlcoex_set = 0x40004e6c; +r_sch_alarm_clear = 0x40004e78; +r_sch_alarm_init = 0x40004e84; +r_sch_alarm_prog = 0x40004e90; +r_sch_alarm_set = 0x40004e9c; +r_sch_alarm_timer_isr = 0x40004ea8; +r_sch_arb_conflict_check = 0x40004eb4; +r_sch_arb_elt_cancel = 0x40004ec0; +r_sch_arb_init = 0x40004ed8; +r_sch_arb_insert = 0x40004ee4; +r_sch_arb_prog_timer = 0x40004ef0; +r_sch_arb_remove = 0x40004efc; +r_sch_arb_sw_isr = 0x40004f08; +r_sch_plan_chk = 0x40004f14; +r_sch_plan_clock_wrap_offset_update = 0x40004f20; +r_sch_plan_init = 0x40004f2c; +r_sch_plan_interval_req = 0x40004f38; +r_sch_plan_offset_max_calc = 0x40004f44; +r_sch_plan_offset_req = 0x40004f50; +r_sch_plan_position_range_compute = 0x40004f5c; +r_sch_plan_rem = 0x40004f68; +r_sch_plan_req = 0x40004f74; +r_sch_prog_init = 0x40004f98; +r_sch_prog_push = 0x40004fa4; +r_sch_prog_rx_isr = 0x40004fb0; +r_sch_prog_skip_isr = 0x40004fbc; +r_sch_prog_tx_isr = 0x40004fc8; +r_sch_slice_bg_add = 0x40004fd4; +r_sch_slice_bg_remove = 0x40004fe0; +r_sch_slice_compute = 0x40004fec; +r_sch_slice_fg_add = 0x40004ff8; +r_sch_slice_fg_remove = 0x40005004; +r_sch_slice_init = 0x40005010; +r_sch_slice_per_add = 0x4000501c; +r_sch_slice_per_remove = 0x40005028; +r_sdk_config_get_bt_sleep_enable = 0x40005034; +r_sdk_config_get_hl_derived_opts = 0x40005040; +r_sdk_config_get_opts = 0x4000504c; +r_sdk_config_get_priv_opts = 0x40005058; +r_sdk_config_set_bt_sleep_enable = 0x40005064; +r_sdk_config_set_hl_derived_opts = 0x40005070; +r_sdk_config_set_opts = 0x4000507c; +r_specialModP256 = 0x40005088; +r_unloaded_area_init = 0x40005094; +r_vhci_flow_off = 0x400050a0; +r_vhci_flow_on = 0x400050ac; +r_vhci_notify_host_send_available = 0x400050b8; +r_vhci_send_to_host = 0x400050c4; +r_vnd_hci_command_handler = 0x400050d0; +r_vshci_init = 0x400050dc; +vnd_hci_command_handler_wrapper = 0x400050e8; +r_lld_legacy_adv_dynamic_pti_get = 0x400050f4; +r_lld_legacy_adv_dynamic_pti_process = 0x40005100; +r_lld_ext_adv_dynamic_pti_get = 0x4000510c; +r_lld_ext_adv_dynamic_aux_pti_process = 0x40005118; +r_lld_ext_adv_dynamic_pti_process = 0x40005124; +/* +r_lld_adv_ext_pkt_prepare_set = 0x40005130; +*/ +r_lld_adv_ext_chain_connectable_construct = 0x40005148; +r_lld_adv_pkt_rx_connect_post = 0x40005160; +r_lld_adv_start_init_evt_param = 0x4000516c; +r_lld_adv_start_set_cs = 0x40005178; +/* r_lld_adv_start_update_filter_policy = 0x40005184; */ +r_lld_adv_start_schedule_asap = 0x40005190; +r_lld_con_tx_prog_new_packet_coex = 0x4000519c; +r_lld_per_adv_dynamic_pti_get = 0x400051b4; +r_lld_per_adv_evt_start_chm_upd = 0x400051c0; +r_lld_ext_scan_dynamic_pti_get = 0x400051cc; +r_lld_sync_insert = 0x400051e4; +/* +r_sch_prog_ble_push = 0x400051f0; +*/ +r_sch_prog_bt_push = 0x400051fc; +r_lld_init_evt_end_type_set = 0x40005208; +r_lld_init_evt_end_type_get = 0x40005214; +r_lld_adv_direct_adv_use_rpa_addr_state_set = 0x40005220; +r_lld_adv_direct_adv_use_rpa_addr_state_get = 0x4000522c; +r_lld_init_evt_end_type_check_state_set = 0x40005238; +r_lld_init_evt_end_type_check_state_get = 0x40005244; + +/* bluetooth hook funcs */ +r_llc_loc_encrypt_proc_continue_hook = 0x40001c60; +r_llc_loc_phy_upd_proc_continue_hook = 0x40001c64; +r_llc_rem_phy_upd_proc_continue_hook = 0x40001c68; +r_lld_scan_frm_eof_isr_hook = 0x40001c6c; +r_lld_scan_evt_start_cbk_hook = 0x40001c70; +r_lld_scan_process_pkt_rx_ext_adv_hook = 0x40001c78; +r_lld_scan_sched_hook = 0x40001c7c; +r_lld_adv_evt_start_cbk_hook = 0x40001c84; +r_lld_adv_aux_evt_start_cbk_hook = 0x40001c88; +r_lld_adv_frm_isr_hook = 0x40001c8c; +r_lld_adv_start_init_evt_param_hook = 0x40001c90; +r_lld_con_evt_canceled_cbk_hook = 0x40001c94; +r_lld_con_frm_isr_hook = 0x40001c98; +r_lld_con_tx_hook = 0x40001c9c; +r_lld_con_rx_hook = 0x40001ca0; +r_lld_con_evt_start_cbk_hook = 0x40001ca4; +r_lld_con_tx_prog_new_packet_hook = 0x40001cac; +r_lld_init_frm_eof_isr_hook = 0x40001cb0; +r_lld_init_evt_start_cbk_hook = 0x40001cb4; +r_lld_init_sched_hook = 0x40001cbc; +r_lld_init_process_pkt_tx_hook = 0x40001cc0; +r_lld_per_adv_evt_start_cbk_hook = 0x40001cc4; +r_lld_per_adv_frm_isr_hook = 0x40001cc8; +r_lld_per_adv_start_hook = 0x40001ccc; +r_lld_sync_frm_eof_isr_hook = 0x40001cd0; +r_lld_sync_evt_start_cbk_hook = 0x40001cd4; +r_lld_sync_start_hook = 0x40001cd8; +r_lld_sync_process_pkt_rx_pkt_check_hook = 0x40001cdc; +r_sch_arb_insert_hook = 0x40001ce0; +r_sch_plan_offset_req_hook = 0x40001ce4; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld index e60065d6b9df..a883ee041624 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld @@ -458,8 +458,8 @@ ets_get_xtal_freq = 0x40001a7c; gpio_input_get = 0x40001a88; gpio_matrix_in = 0x40001a94; gpio_matrix_out = 0x40001aa0; -gpio_output_disable = 0x40001aac; -gpio_output_enable = 0x40001ab8; +/* gpio_output_disable = 0x40001aac; */ +/* gpio_output_enable = 0x40001ab8; */ gpio_output_set = 0x40001ac4; gpio_pad_hold = 0x40001ad0; gpio_pad_input_disable = 0x40001adc; @@ -776,825 +776,6 @@ rom_usb_osglue = 0x3fceffac; Group bluetooth ***************************************/ -/* Functions */ -bt_rf_coex_get_dft_cfg = 0x40002a78; -bt_rf_coex_hooks_p_set = 0x40002a84; -btdm_con_maxevtime_cal_impl = 0x40002a90; -btdm_controller_get_compile_version_impl = 0x40002a9c; -btdm_controller_rom_data_init = 0x40002aa8; -btdm_dis_privacy_err_report_impl = 0x40002ab4; -btdm_disable_adv_delay_impl = 0x40002ac0; -btdm_enable_scan_continue_impl = 0x40002acc; -btdm_enable_scan_forever_impl = 0x40002ad8; -btdm_get_power_state_impl = 0x40002ae4; -btdm_get_prevent_sleep_flag_impl = 0x40002af0; -btdm_power_state_active_impl = 0x40002afc; -btdm_switch_phy_coded_impl = 0x40002b08; -hci_acl_data_handler = 0x40002b14; -hci_disconnect_cmd_handler = 0x40002b20; -hci_le_con_upd_cmd_handler = 0x40002b2c; -hci_le_ltk_req_neg_reply_cmd_handler = 0x40002b38; -hci_le_ltk_req_reply_cmd_handler = 0x40002b44; -hci_le_rd_chnl_map_cmd_handler = 0x40002b50; -hci_le_rd_phy_cmd_handler = 0x40002b5c; -hci_le_rd_rem_feats_cmd_handler = 0x40002b68; -hci_le_rem_con_param_req_neg_reply_cmd_handler = 0x40002b74; -hci_le_rem_con_param_req_reply_cmd_handler = 0x40002b80; -hci_le_set_data_len_cmd_handler = 0x40002b8c; -hci_le_set_phy_cmd_handler = 0x40002b98; -hci_le_start_enc_cmd_handler = 0x40002ba4; -hci_rd_auth_payl_to_cmd_handler = 0x40002bb0; -hci_rd_rem_ver_info_cmd_handler = 0x40002bbc; -hci_rd_rssi_cmd_handler = 0x40002bc8; -hci_rd_tx_pwr_lvl_cmd_handler = 0x40002bd4; -hci_vs_set_pref_slave_evt_dur_cmd_handler = 0x40002be0; -hci_vs_set_pref_slave_latency_cmd_handler = 0x40002bec; -hci_wr_auth_payl_to_cmd_handler = 0x40002bf8; -ll_channel_map_ind_handler = 0x40002c04; -ll_connection_param_req_handler = 0x40002c10; -ll_connection_param_rsp_handler = 0x40002c1c; -ll_connection_update_ind_handler = 0x40002c28; -ll_enc_req_handler = 0x40002c34; -ll_enc_rsp_handler = 0x40002c40; -ll_feature_req_handler = 0x40002c4c; -ll_feature_rsp_handler = 0x40002c58; -ll_length_req_handler = 0x40002c64; -ll_length_rsp_handler = 0x40002c70; -ll_min_used_channels_ind_handler = 0x40002c7c; -ll_pause_enc_req_handler = 0x40002c88; -ll_pause_enc_rsp_handler = 0x40002c94; -ll_phy_req_handler = 0x40002ca0; -ll_phy_rsp_handler = 0x40002cac; -ll_phy_update_ind_handler = 0x40002cb8; -ll_ping_req_handler = 0x40002cc4; -ll_ping_rsp_handler = 0x40002cd0; -ll_slave_feature_req_handler = 0x40002cdc; -ll_start_enc_req_handler = 0x40002ce8; -ll_start_enc_rsp_handler = 0x40002cf4; -ll_terminate_ind_handler = 0x40002d00; -ll_version_ind_handler = 0x40002d0c; -llc_auth_payl_nearly_to_handler = 0x40002d18; -llc_auth_payl_real_to_handler = 0x40002d24; -llc_encrypt_ind_handler = 0x40002d30; -llc_hci_command_handler_wrapper = 0x40002d3c; -llc_ll_connection_param_req_pdu_send = 0x40002d48; -llc_ll_connection_param_rsp_pdu_send = 0x40002d54; -llc_ll_connection_update_ind_pdu_send = 0x40002d60; -llc_ll_enc_req_pdu_send = 0x40002d6c; -llc_ll_enc_rsp_pdu_send = 0x40002d78; -llc_ll_feature_req_pdu_send = 0x40002d84; -llc_ll_feature_rsp_pdu_send = 0x40002d90; -llc_ll_length_req_pdu_send = 0x40002d9c; -llc_ll_length_rsp_pdu_send = 0x40002da8; -llc_ll_pause_enc_req_pdu_send = 0x40002db4; -llc_ll_pause_enc_rsp_pdu_send = 0x40002dc0; -llc_ll_phy_req_pdu_send = 0x40002dcc; -llc_ll_phy_rsp_pdu_send = 0x40002dd8; -llc_ll_ping_req_pdu_send = 0x40002de4; -llc_ll_ping_rsp_pdu_send = 0x40002df0; -llc_ll_start_enc_req_pdu_send = 0x40002dfc; -llc_ll_start_enc_rsp_pdu_send = 0x40002e08; -llc_ll_terminate_ind_pdu_send = 0x40002e14; -llc_ll_unknown_rsp_pdu_send = 0x40002e20; -llc_llcp_ch_map_update_ind_pdu_send = 0x40002e2c; -llc_llcp_phy_upd_ind_pdu_send = 0x40002e38; -llc_llcp_version_ind_pdu_send = 0x40002e44; -llc_op_ch_map_upd_ind_handler = 0x40002e50; -llc_op_con_upd_ind_handler = 0x40002e5c; -llc_op_disconnect_ind_handler = 0x40002e68; -llc_op_dl_upd_ind_handler = 0x40002e74; -llc_op_encrypt_ind_handler = 0x40002e80; -llc_op_feats_exch_ind_handler = 0x40002e8c; -llc_op_le_ping_ind_handler = 0x40002e98; -llc_op_phy_upd_ind_handler = 0x40002ea4; -llc_op_ver_exch_ind_handler = 0x40002eb0; -llc_stopped_ind_handler = 0x40002ebc; -lld_acl_rx_ind_handler = 0x40002ec8; -lld_acl_tx_cfm_handler = 0x40002ed4; -lld_adv_end_ind_handler = 0x40002ee0; -lld_adv_rep_ind_handler = 0x40002eec; -lld_ch_map_upd_cfm_handler = 0x40002ef8; -lld_con_estab_ind_handler = 0x40002f04; -lld_con_evt_sd_evt_time_set = 0x40002f10; -lld_con_offset_upd_ind_handler = 0x40002f1c; -lld_con_param_upd_cfm_handler = 0x40002f28; -lld_disc_ind_handler = 0x40002f34; -lld_init_end_ind_handler = 0x40002f40; -lld_llcp_rx_ind_handler_wrapper = 0x40002f4c; -lld_llcp_tx_cfm_handler = 0x40002f58; -lld_per_adv_end_ind_handler = 0x40002f64; -lld_per_adv_rep_ind_handler = 0x40002f70; -lld_per_adv_rx_end_ind_handler = 0x40002f7c; -lld_phy_coded_500k_get = 0x40002f88; -lld_phy_upd_cfm_handler = 0x40002f94; -lld_scan_end_ind_handler = 0x40002fa0; -lld_scan_req_ind_handler = 0x40002fac; -lld_sync_start_req_handler = 0x40002fb8; -lld_test_end_ind_handler = 0x40002fc4; -lld_update_rxbuf_handler = 0x40002fd0; -llm_ch_map_update_ind_handler = 0x40002fdc; -llm_hci_command_handler_wrapper = 0x40002fe8; -llm_scan_period_to_handler = 0x40002ff4; -r_Add2SelfBigHex256 = 0x40003000; -r_AddBigHex256 = 0x4000300c; -r_AddBigHexModP256 = 0x40003018; -r_AddP256 = 0x40003024; -r_AddPdiv2_256 = 0x40003030; -r_GF_Jacobian_Point_Addition256 = 0x4000303c; -r_GF_Jacobian_Point_Double256 = 0x40003048; -r_GF_Point_Jacobian_To_Affine256 = 0x40003054; -r_MultiplyBigHexByUint32_256 = 0x40003060; -r_MultiplyBigHexModP256 = 0x4000306c; -r_MultiplyByU16ModP256 = 0x40003078; -r_SubtractBigHex256 = 0x40003084; -r_SubtractBigHexMod256 = 0x40003090; -r_SubtractBigHexUint32_256 = 0x4000309c; -r_SubtractFromSelfBigHex256 = 0x400030a8; -r_SubtractFromSelfBigHexSign256 = 0x400030b4; -r_aes_alloc = 0x400030c0; -r_aes_ccm_continue = 0x400030cc; -r_aes_ccm_process_e = 0x400030d8; -r_aes_ccm_xor_128_lsb = 0x400030e4; -r_aes_ccm_xor_128_msb = 0x400030f0; -r_aes_cmac_continue = 0x400030fc; -r_aes_cmac_start = 0x40003108; -r_aes_k1_continue = 0x40003114; -r_aes_k2_continue = 0x40003120; -r_aes_k3_continue = 0x4000312c; -r_aes_k4_continue = 0x40003138; -r_aes_shift_left_128 = 0x40003144; -r_aes_start = 0x40003150; -r_aes_xor_128 = 0x4000315c; -r_assert_err = 0x40003168; -r_assert_param = 0x40003174; -r_assert_warn = 0x40003180; -r_bigHexInversion256 = 0x4000318c; -r_ble_sw_cca_check_isr = 0x40003198; -r_ble_util_buf_acl_tx_alloc = 0x400031a4; -r_ble_util_buf_acl_tx_elt_get = 0x400031b0; -r_ble_util_buf_acl_tx_free = 0x400031bc; -r_ble_util_buf_acl_tx_free_in_isr = 0x400031c8; -r_ble_util_buf_adv_tx_alloc = 0x400031d4; -r_ble_util_buf_adv_tx_free = 0x400031e0; -r_ble_util_buf_adv_tx_free_in_isr = 0x400031ec; -r_ble_util_buf_env_deinit = 0x400031f8; -r_ble_util_buf_env_init = 0x40003204; -r_ble_util_buf_get_rx_buf_nb = 0x40003210; -r_ble_util_buf_get_rx_buf_size = 0x4000321c; -r_ble_util_buf_llcp_tx_alloc = 0x40003228; -r_ble_util_buf_llcp_tx_free = 0x40003234; -r_ble_util_buf_rx_alloc = 0x40003240; -r_ble_util_buf_rx_alloc_in_isr = 0x4000324c; -r_ble_util_buf_rx_free = 0x40003258; -r_ble_util_buf_rx_free_in_isr = 0x40003264; -r_ble_util_buf_set_rx_buf_nb = 0x40003270; -r_ble_util_buf_set_rx_buf_size = 0x4000327c; -r_ble_util_data_rx_buf_reset = 0x40003288; -r_bt_bb_get_intr_mask = 0x40003294; -r_bt_bb_intr_clear = 0x400032a0; -r_bt_bb_intr_mask_set = 0x400032ac; -r_bt_rf_coex_cfg_set = 0x400032c4; -r_bt_rf_coex_conn_dynamic_pti_en_get = 0x400032d0; -r_bt_rf_coex_ext_adv_dynamic_pti_en_get = 0x400032e8; -r_bt_rf_coex_ext_scan_dynamic_pti_en_get = 0x400032f4; -r_bt_rf_coex_legacy_adv_dynamic_pti_en_get = 0x40003300; -r_bt_rf_coex_per_adv_dynamic_pti_en_get = 0x4000330c; -r_bt_rf_coex_pti_table_get = 0x40003318; -r_bt_rf_coex_st_param_get = 0x40003324; -r_bt_rf_coex_st_param_set = 0x40003330; -r_bt_rf_coex_sync_scan_dynamic_pti_en_get = 0x4000333c; -r_bt_rma_apply_rule_cs_fmt = 0x40003348; -r_bt_rma_apply_rule_cs_idx = 0x40003354; -r_bt_rma_configure = 0x40003360; -r_bt_rma_deregister_rule_cs_fmt = 0x4000336c; -r_bt_rma_deregister_rule_cs_idx = 0x40003378; -r_bt_rma_get_ant_by_act = 0x40003384; -r_bt_rma_init = 0x40003390; -r_bt_rma_register_rule_cs_fmt = 0x4000339c; -r_bt_rma_register_rule_cs_idx = 0x400033a8; -r_bt_rtp_apply_rule_cs_fmt = 0x400033b4; -r_bt_rtp_apply_rule_cs_idx = 0x400033c0; -r_bt_rtp_deregister_rule_cs_fmt = 0x400033cc; -r_bt_rtp_deregister_rule_cs_idx = 0x400033d8; -r_bt_rtp_init = 0x400033f0; -r_bt_rtp_register_rule_cs_fmt = 0x400033fc; -r_bt_rtp_register_rule_cs_idx = 0x40003408; -r_btdm_isr = 0x40003414; -r_cali_phase_match_p = 0x40003444; -r_cmp_abs_time = 0x40003450; -r_cmp_dest_id = 0x4000345c; -r_cmp_timer_id = 0x40003468; -r_co_bdaddr_compare = 0x40003474; -r_co_ble_pkt_dur_in_us = 0x40003480; -r_co_list_extract = 0x4000348c; -r_co_list_extract_after = 0x40003498; -r_co_list_extract_sublist = 0x400034a4; -r_co_list_find = 0x400034b0; -r_co_list_init = 0x400034bc; -r_co_list_insert_after = 0x400034c8; -r_co_list_insert_before = 0x400034d4; -r_co_list_merge = 0x400034e0; -r_co_list_pool_init = 0x400034ec; -r_co_list_pop_front = 0x400034f8; -r_co_list_push_back = 0x40003504; -r_co_list_push_back_sublist = 0x40003510; -r_co_list_push_front = 0x4000351c; -r_co_list_size = 0x40003528; -r_co_nb_good_le_channels = 0x40003534; -r_co_util_pack = 0x40003540; -r_co_util_read_array_size = 0x4000354c; -r_co_util_unpack = 0x40003558; -r_dbg_env_deinit = 0x40003564; -r_dbg_env_init = 0x40003570; -r_dbg_platform_reset_complete = 0x4000357c; -r_dl_upd_proc_start = 0x40003588; -r_dump_data = 0x40003594; -r_ecc_abort_key256_generation = 0x400035a0; -r_ecc_gen_new_public_key = 0x400035ac; -r_ecc_gen_new_secret_key = 0x400035b8; -r_ecc_generate_key256 = 0x400035c4; -r_ecc_get_debug_Keys = 0x400035d0; -r_ecc_init = 0x400035dc; -r_ecc_is_valid_point = 0x400035e8; -r_ecc_multiplication_event_handler = 0x400035f4; -r_ecc_point_multiplication_win_256 = 0x40003600; -r_emi_alloc_em_mapping_by_offset = 0x4000360c; -r_emi_base_reg_lut_show = 0x40003618; -r_emi_em_base_reg_show = 0x40003624; -r_emi_free_em_mapping_by_offset = 0x40003630; -r_emi_get_em_mapping_idx_by_offset = 0x4000363c; -r_emi_get_mem_addr_by_offset = 0x40003648; -r_emi_overwrite_em_mapping_by_offset = 0x40003654; -r_esp_vendor_hci_command_handler = 0x40003660; -r_get_stack_usage = 0x4000366c; -r_h4tl_acl_hdr_rx_evt_handler = 0x40003678; -r_h4tl_cmd_hdr_rx_evt_handler = 0x40003684; -r_h4tl_cmd_pld_rx_evt_handler = 0x40003690; -r_h4tl_eif_io_event_post = 0x4000369c; -r_h4tl_eif_register = 0x400036a8; -r_h4tl_init = 0x400036b4; -r_h4tl_out_of_sync = 0x400036c0; -r_h4tl_out_of_sync_check = 0x400036cc; -r_h4tl_read_hdr = 0x400036d8; -r_h4tl_read_next_out_of_sync = 0x400036e4; -r_h4tl_read_payl = 0x400036f0; -r_h4tl_read_start = 0x400036fc; -r_h4tl_rx_acl_hdr_extract = 0x40003708; -r_h4tl_rx_cmd_hdr_extract = 0x40003714; -r_h4tl_rx_done = 0x40003720; -r_h4tl_start = 0x4000372c; -r_h4tl_stop = 0x40003738; -r_h4tl_tx_done = 0x40003744; -r_h4tl_tx_evt_handler = 0x40003750; -r_h4tl_write = 0x4000375c; -r_hci_acl_tx_data_alloc = 0x40003768; -r_hci_acl_tx_data_received = 0x40003774; -r_hci_basic_cmd_send_2_controller = 0x40003780; -r_hci_ble_adv_report_filter_check = 0x4000378c; -r_hci_ble_adv_report_tx_check = 0x40003798; -r_hci_ble_conhdl_register = 0x400037a4; -r_hci_ble_conhdl_unregister = 0x400037b0; -r_hci_build_acl_data = 0x400037bc; -r_hci_build_cc_evt = 0x400037c8; -r_hci_build_cs_evt = 0x400037d4; -r_hci_build_evt = 0x400037e0; -r_hci_build_le_evt = 0x400037ec; -r_hci_cmd_get_max_param_size = 0x400037f8; -r_hci_cmd_received = 0x40003804; -r_hci_cmd_reject = 0x40003810; -r_hci_evt_mask_check = 0x4000381c; -r_hci_evt_mask_set = 0x40003828; -r_hci_fc_acl_buf_size_set = 0x40003834; -r_hci_fc_acl_en = 0x40003840; -r_hci_fc_acl_packet_sent = 0x4000384c; -r_hci_fc_check_host_available_nb_acl_packets = 0x40003858; -r_hci_fc_host_nb_acl_pkts_complete = 0x40003864; -r_hci_fc_init = 0x40003870; -r_hci_look_for_cmd_desc = 0x4000387c; -r_hci_look_for_evt_desc = 0x40003888; -r_hci_look_for_le_evt_desc = 0x40003894; -r_hci_look_for_le_evt_desc_esp = 0x400038a0; -r_hci_pack_bytes = 0x400038ac; -r_hci_send_2_controller = 0x400038c4; -r_hci_send_2_host = 0x400038d0; -r_hci_tl_c2h_data_flow_on = 0x400038dc; -r_hci_tl_cmd_hdr_rx_evt_handler = 0x400038e8; -r_hci_tl_cmd_pld_rx_evt_handler = 0x400038f4; -r_hci_tl_get_pkt = 0x40003900; -r_hci_tl_hci_pkt_handler = 0x4000390c; -r_hci_tl_hci_tx_done_evt_handler = 0x40003918; -r_hci_tl_inc_nb_h2c_cmd_pkts = 0x40003924; -r_hci_tl_save_pkt = 0x40003930; -r_hci_tl_send = 0x4000393c; -r_hci_tx_done = 0x40003948; -r_hci_tx_start = 0x40003954; -r_hci_tx_trigger = 0x40003960; -r_isValidSecretKey_256 = 0x4000396c; -r_ke_check_malloc = 0x40003978; -r_ke_event_callback_set = 0x40003984; -r_ke_event_clear = 0x40003990; -r_ke_event_flush = 0x4000399c; -r_ke_event_get = 0x400039a8; -r_ke_event_get_all = 0x400039b4; -r_ke_event_init = 0x400039c0; -r_ke_event_schedule = 0x400039cc; -r_ke_event_set = 0x400039d8; -r_ke_flush = 0x400039e4; -r_ke_free = 0x400039f0; -r_ke_handler_search = 0x400039fc; -r_ke_init = 0x40003a08; -r_ke_is_free = 0x40003a14; -r_ke_malloc = 0x40003a20; -r_ke_mem_init = 0x40003a2c; -r_ke_mem_is_empty = 0x40003a38; -r_ke_mem_is_in_heap = 0x40003a44; -r_ke_msg_alloc = 0x40003a50; -r_ke_msg_dest_id_get = 0x40003a5c; -r_ke_msg_discard = 0x40003a68; -r_ke_msg_forward = 0x40003a74; -r_ke_msg_forward_new_id = 0x40003a80; -r_ke_msg_free = 0x40003a8c; -r_ke_msg_in_queue = 0x40003a98; -r_ke_msg_save = 0x40003aa4; -r_ke_msg_send = 0x40003ab0; -r_ke_msg_send_basic = 0x40003abc; -r_ke_msg_src_id_get = 0x40003ac8; -r_ke_queue_extract = 0x40003ad4; -r_ke_queue_insert = 0x40003ae0; -r_ke_sleep_check = 0x40003aec; -r_ke_state_get = 0x40003af8; -r_ke_state_set = 0x40003b04; -r_ke_task_check = 0x40003b10; -r_ke_task_create = 0x40003b1c; -r_ke_task_delete = 0x40003b28; -r_ke_task_handler_get = 0x40003b34; -r_ke_task_init = 0x40003b40; -r_ke_task_msg_flush = 0x40003b4c; -r_ke_task_saved_update = 0x40003b58; -r_ke_time = 0x40003b70; -r_ke_time_cmp = 0x40003b7c; -r_ke_time_past = 0x40003b88; -r_ke_timer_active = 0x40003b94; -r_ke_timer_adjust_all = 0x40003ba0; -r_ke_timer_clear = 0x40003bac; -r_ke_timer_init = 0x40003bb8; -r_ke_timer_schedule = 0x40003bc4; -r_ke_timer_set = 0x40003bd0; -r_led_init = 0x40003bdc; -r_led_set_all = 0x40003be8; -r_llc_aes_res_cb = 0x40003bf4; -r_llc_ch_map_up_proc_err_cb = 0x40003c00; -r_llc_cleanup = 0x40003c0c; -r_llc_cmd_cmp_send = 0x40003c18; -r_llc_cmd_stat_send = 0x40003c24; -r_llc_con_move_cbk = 0x40003c30; -r_llc_con_plan_set_update = 0x40003c3c; -r_llc_con_upd_param_in_range = 0x40003c48; -r_llc_disconnect = 0x40003c54; -r_llc_disconnect_end = 0x40003c60; -r_llc_disconnect_proc_continue = 0x40003c6c; -r_llc_disconnect_proc_err_cb = 0x40003c78; -r_llc_dl_chg_check = 0x40003c84; -r_llc_dle_proc_err_cb = 0x40003c90; -r_llc_feats_exch_proc_err_cb = 0x40003c9c; -r_llc_hci_cmd_handler_tab_p_get = 0x40003ca8; -r_llc_hci_con_param_req_evt_send = 0x40003cc0; -r_llc_hci_con_upd_info_send = 0x40003ccc; -r_llc_hci_disconnected_dis = 0x40003cd8; -r_llc_hci_dl_upd_info_send = 0x40003ce4; -r_llc_hci_enc_evt_send = 0x40003cf0; -r_llc_hci_feats_info_send = 0x40003cfc; -r_llc_hci_le_phy_upd_cmp_evt_send = 0x40003d08; -r_llc_hci_ltk_request_evt_send = 0x40003d14; -r_llc_hci_nb_cmp_pkts_evt_send = 0x40003d20; -r_llc_hci_version_info_send = 0x40003d2c; -r_llc_init_term_proc = 0x40003d38; -r_llc_iv_skd_rand_gen = 0x40003d44; -r_llc_le_ping_proc_continue = 0x40003d50; -r_llc_le_ping_proc_err_cb = 0x40003d5c; -/* r_llc_le_ping_restart = 0x40003d68; */ -r_llc_le_ping_set = 0x40003d74; -r_llc_ll_pause_enc_rsp_ack_handler = 0x40003d80; -r_llc_ll_reject_ind_ack_handler = 0x40003d8c; -r_llc_ll_reject_ind_pdu_send = 0x40003d98; -r_llc_ll_start_enc_rsp_ack_handler = 0x40003da4; -r_llc_ll_terminate_ind_ack = 0x40003db0; -r_llc_ll_unknown_ind_handler = 0x40003dbc; -r_llc_llcp_send = 0x40003dc8; -r_llc_llcp_state_set = 0x40003dd4; -r_llc_llcp_trans_timer_set = 0x40003de0; -r_llc_llcp_tx_check = 0x40003dec; -/* r_llc_loc_ch_map_proc_continue = 0x40003df8; */ -r_llc_loc_con_upd_proc_err_cb = 0x40003e10; -r_llc_loc_dl_upd_proc_continue = 0x40003e1c; -r_llc_loc_encrypt_proc_continue = 0x40003e28; -r_llc_loc_encrypt_proc_err_cb = 0x40003e34; -r_llc_loc_feats_exch_proc_continue = 0x40003e40; -r_llc_loc_phy_upd_proc_err_cb = 0x40003e58; -r_llc_msg_handler_tab_p_get = 0x40003e64; -r_llc_pref_param_compute = 0x40003e70; -r_llc_proc_collision_check = 0x40003e7c; -r_llc_proc_err_ind = 0x40003e88; -r_llc_proc_get = 0x40003e94; -r_llc_proc_id_get = 0x40003ea0; -r_llc_proc_reg = 0x40003eac; -r_llc_proc_state_get = 0x40003eb8; -r_llc_proc_state_set = 0x40003ec4; -r_llc_proc_timer_pause_set = 0x40003ed0; -r_llc_proc_timer_set = 0x40003edc; -r_llc_proc_unreg = 0x40003ee8; -r_llc_rem_ch_map_proc_continue = 0x40003ef4; -r_llc_rem_con_upd_proc_err_cb = 0x40003f0c; -r_llc_rem_dl_upd_proc = 0x40003f18; -r_llc_rem_encrypt_proc_continue = 0x40003f24; -r_llc_rem_encrypt_proc_err_cb = 0x40003f30; -r_llc_rem_phy_upd_proc_continue = 0x40003f3c; -r_llc_rem_phy_upd_proc_err_cb = 0x40003f48; -r_llc_role_get = 0x40003f54; -r_llc_sk_gen = 0x40003f60; -r_llc_start = 0x40003f6c; -r_llc_stop = 0x40003f78; -r_llc_ver_exch_loc_proc_continue = 0x40003f84; -r_llc_ver_proc_err_cb = 0x40003f90; -r_llcp_pdu_handler_tab_p_get = 0x40003f9c; -r_lld_aa_gen = 0x40003fa8; -r_lld_adv_adv_data_set = 0x40003fb4; -r_lld_adv_adv_data_update = 0x40003fc0; -r_lld_adv_aux_ch_idx_set = 0x40003fcc; -r_lld_adv_aux_evt_canceled_cbk = 0x40003fd8; -r_lld_adv_aux_evt_start_cbk = 0x40003fe4; -r_lld_adv_coex_check_ext_adv_synced = 0x40003ff0; -r_lld_adv_coex_env_reset = 0x40003ffc; -r_lld_adv_duration_update = 0x40004008; -r_lld_adv_dynamic_pti_process = 0x40004014; -r_lld_adv_end = 0x40004020; -r_lld_adv_evt_canceled_cbk = 0x4000402c; -r_lld_adv_evt_start_cbk = 0x40004038; -r_lld_adv_ext_chain_construct = 0x40004044; -r_lld_adv_ext_pkt_prepare = 0x40004050; -r_lld_adv_frm_cbk = 0x4000405c; -r_lld_adv_frm_isr = 0x40004068; -r_lld_adv_frm_skip_isr = 0x40004074; -r_lld_adv_init = 0x40004080; -r_lld_adv_pkt_rx = 0x4000408c; -r_lld_adv_pkt_rx_connect_ind = 0x40004098; -r_lld_adv_pkt_rx_send_scan_req_evt = 0x400040a4; -r_lld_adv_rand_addr_update = 0x400040b0; -r_lld_adv_restart = 0x400040bc; -r_lld_adv_scan_rsp_data_set = 0x400040c8; -r_lld_adv_scan_rsp_data_update = 0x400040d4; -r_lld_adv_set_tx_power = 0x400040e0; -r_lld_adv_start = 0x400040ec; -r_lld_adv_stop = 0x400040f8; -r_lld_adv_sync_info_set = 0x40004104; -r_lld_adv_sync_info_update = 0x40004110; -r_lld_calc_aux_rx = 0x4000411c; -r_lld_cca_alloc = 0x40004128; -r_lld_cca_data_reset = 0x40004134; -r_lld_cca_free = 0x40004140; -r_lld_ch_assess_data_get = 0x4000414c; -r_lld_ch_idx_get = 0x40004158; -r_lld_ch_map_set = 0x40004164; -r_lld_channel_assess = 0x40004170; -r_lld_con_activity_act_offset_compute = 0x4000417c; -r_lld_con_activity_offset_compute = 0x40004188; -r_lld_con_ch_map_update = 0x40004194; -r_lld_con_cleanup = 0x400041a0; -r_lld_con_current_tx_power_get = 0x400041ac; -r_lld_con_data_flow_set = 0x400041b8; -r_lld_con_data_len_update = 0x400041c4; -r_lld_con_data_tx = 0x400041d0; -r_lld_con_enc_key_load = 0x400041dc; -r_lld_con_event_counter_get = 0x400041e8; -r_lld_con_evt_canceled_cbk = 0x400041f4; -r_lld_con_evt_duration_min_get = 0x40004200; -r_lld_con_evt_max_eff_time_cal = 0x4000420c; -r_lld_con_evt_sd_evt_time_get = 0x40004218; -r_lld_con_evt_start_cbk = 0x40004224; -r_lld_con_evt_time_update = 0x40004230; -r_lld_con_free_all_tx_buf = 0x4000423c; -r_lld_con_frm_cbk = 0x40004248; -r_lld_con_frm_isr = 0x40004254; -r_lld_con_frm_skip_isr = 0x40004260; -r_lld_con_init = 0x4000426c; -r_lld_con_llcp_tx = 0x40004278; -r_lld_con_max_lat_calc = 0x40004284; -r_lld_con_offset_get = 0x40004290; -r_lld_con_param_update = 0x4000429c; -r_lld_con_phys_update = 0x400042a8; -r_lld_con_pref_slave_evt_dur_set = 0x400042b4; -r_lld_con_pref_slave_latency_set = 0x400042c0; -r_lld_con_rssi_get = 0x400042cc; -r_lld_con_rx = 0x400042d8; -/* r_lld_con_rx_channel_assess = 0x400042e4; */ -r_lld_con_rx_enc = 0x400042f0; -r_lld_con_rx_isr = 0x400042fc; -r_lld_con_rx_link_info_check = 0x40004308; -r_lld_con_rx_llcp_check = 0x40004314; -r_lld_con_rx_sync_time_update = 0x40004320; -r_lld_con_set_tx_power = 0x40004338; -r_lld_con_start = 0x40004344; -r_lld_con_tx = 0x4000435c; -r_lld_con_tx_enc = 0x40004368; -r_lld_con_tx_isr = 0x40004374; -r_lld_con_tx_len_update = 0x40004380; -r_lld_con_tx_len_update_for_intv = 0x4000438c; -r_lld_con_tx_len_update_for_rate = 0x40004398; -r_lld_con_tx_prog = 0x400043a4; -r_lld_conn_dynamic_pti_process = 0x400043b0; -r_lld_continue_scan_rx_isr_end_process = 0x400043bc; -r_lld_ext_scan_dynamic_pti_process = 0x400043c8; -r_lld_hw_cca_end_isr = 0x400043d4; -r_lld_hw_cca_evt_handler = 0x400043e0; -r_lld_hw_cca_isr = 0x400043ec; -r_lld_init_cal_anchor_point = 0x400043f8; -r_lld_init_compute_winoffset = 0x40004404; -r_lld_init_connect_req_pack = 0x40004410; -r_lld_init_end = 0x4000441c; -r_lld_init_evt_canceled_cbk = 0x40004428; -r_lld_init_evt_start_cbk = 0x40004434; -r_lld_init_frm_cbk = 0x40004440; -r_lld_init_frm_eof_isr = 0x4000444c; -r_lld_init_frm_skip_isr = 0x40004458; -r_lld_init_init = 0x40004464; -r_lld_init_process_pkt_rx = 0x40004470; -r_lld_init_process_pkt_rx_adv_ext_ind = 0x4000447c; -r_lld_init_process_pkt_rx_adv_ind_or_direct_ind = 0x40004488; -r_lld_init_process_pkt_rx_aux_connect_rsp = 0x40004494; -r_lld_init_process_pkt_tx = 0x400044a0; -r_lld_init_process_pkt_tx_cal_con_timestamp = 0x400044ac; -r_lld_init_sched = 0x400044b8; -r_lld_init_set_tx_power = 0x400044c4; -r_lld_init_start = 0x400044d0; -r_lld_init_stop = 0x400044dc; -r_lld_instant_proc_end = 0x400044e8; -r_lld_per_adv_ch_map_update = 0x40004500; -r_lld_per_adv_chain_construct = 0x4000450c; -r_lld_per_adv_cleanup = 0x40004518; -r_lld_per_adv_coex_env_reset = 0x40004524; -r_lld_per_adv_data_set = 0x40004530; -r_lld_per_adv_data_update = 0x4000453c; -r_lld_per_adv_dynamic_pti_process = 0x40004548; -r_lld_per_adv_evt_canceled_cbk = 0x40004554; -r_lld_per_adv_evt_start_cbk = 0x40004560; -r_lld_per_adv_ext_pkt_prepare = 0x4000456c; -r_lld_per_adv_frm_cbk = 0x40004578; -r_lld_per_adv_frm_isr = 0x40004584; -r_lld_per_adv_frm_skip_isr = 0x40004590; -r_lld_per_adv_init = 0x4000459c; -r_lld_per_adv_init_info_get = 0x400045a8; -r_lld_per_adv_list_add = 0x400045b4; -r_lld_per_adv_list_rem = 0x400045c0; -r_lld_per_adv_set_tx_power = 0x400045d8; -r_lld_per_adv_start = 0x400045e4; -r_lld_per_adv_stop = 0x400045f0; -r_lld_per_adv_sync_info_get = 0x400045fc; -r_lld_process_cca_data = 0x40004608; -r_lld_ral_search = 0x40004614; -r_lld_read_clock = 0x40004620; -r_lld_res_list_add = 0x4000462c; -r_lld_res_list_is_empty = 0x40004644; -r_lld_res_list_local_rpa_get = 0x40004650; -r_lld_res_list_peer_rpa_get = 0x4000465c; -r_lld_res_list_peer_update = 0x40004668; -/* r_lld_res_list_priv_mode_update = 0x40004674; */ -r_lld_reset_reg = 0x4000468c; -r_lld_rpa_renew = 0x40004698; -r_lld_rpa_renew_evt_canceled_cbk = 0x400046a4; -r_lld_rpa_renew_evt_start_cbk = 0x400046b0; -r_lld_rpa_renew_instant_cbk = 0x400046bc; -r_lld_rxdesc_check = 0x400046c8; -r_lld_rxdesc_free = 0x400046d4; -r_lld_scan_create_sync = 0x400046e0; -r_lld_scan_create_sync_cancel = 0x400046ec; -r_lld_scan_end = 0x400046f8; -r_lld_scan_evt_canceled_cbk = 0x40004704; -r_lld_scan_evt_start_cbk = 0x40004710; -r_lld_scan_frm_cbk = 0x4000471c; -r_lld_scan_frm_eof_isr = 0x40004728; -r_lld_scan_frm_rx_isr = 0x40004734; -r_lld_scan_frm_skip_isr = 0x40004740; -r_lld_scan_init = 0x4000474c; -r_lld_scan_params_update = 0x40004758; -r_lld_scan_process_pkt_rx_aux_adv_ind = 0x4000477c; -r_lld_scan_process_pkt_rx_aux_chain_ind = 0x40004788; -r_lld_scan_process_pkt_rx_aux_scan_rsp = 0x40004794; -r_lld_scan_process_pkt_rx_ext_adv = 0x400047a0; -r_lld_scan_process_pkt_rx_ext_adv_ind = 0x400047ac; -r_lld_scan_process_pkt_rx_legacy_adv = 0x400047b8; -r_lld_scan_restart = 0x400047c4; -r_lld_scan_sched = 0x400047d0; -r_lld_scan_set_tx_power = 0x400047dc; -r_lld_scan_start = 0x400047e8; -r_lld_scan_stop = 0x400047f4; -r_lld_scan_sync_accept = 0x40004800; -r_lld_scan_sync_info_unpack = 0x4000480c; -r_lld_scan_trunc_ind = 0x40004818; -r_lld_sw_cca_evt_handler = 0x40004824; -r_lld_sw_cca_isr = 0x40004830; -r_lld_sync_ch_map_update = 0x4000483c; -r_lld_sync_cleanup = 0x40004848; -r_lld_sync_evt_canceled_cbk = 0x40004854; -r_lld_sync_evt_start_cbk = 0x40004860; -r_lld_sync_frm_cbk = 0x4000486c; -r_lld_sync_frm_eof_isr = 0x40004878; -r_lld_sync_frm_rx_isr = 0x40004884; -r_lld_sync_frm_skip_isr = 0x40004890; -r_lld_sync_init = 0x4000489c; -r_lld_sync_process_pkt_rx = 0x400048a8; -r_lld_sync_process_pkt_rx_aux_sync_ind = 0x400048b4; -r_lld_sync_process_pkt_rx_pkt_check = 0x400048c0; -r_lld_sync_scan_dynamic_pti_process = 0x400048cc; -r_lld_sync_sched = 0x400048d8; -r_lld_sync_start = 0x400048e4; -r_lld_sync_stop = 0x400048f0; -r_lld_sync_trunc_ind = 0x400048fc; -r_lld_test_cleanup = 0x40004908; -r_lld_test_evt_canceled_cbk = 0x40004914; -r_lld_test_evt_start_cbk = 0x40004920; -r_lld_test_freq2chnl = 0x4000492c; -r_lld_test_frm_cbk = 0x40004938; -r_lld_test_frm_isr = 0x40004944; -r_lld_test_init = 0x40004950; -r_lld_test_rx_isr = 0x4000495c; -r_lld_test_set_tx_power = 0x40004968; -r_lld_test_start = 0x40004974; -/* r_lld_test_stop = 0x40004980;*/ -r_lld_update_rxbuf = 0x4000498c; -r_lld_update_rxbuf_isr = 0x40004998; -r_lld_white_list_add = 0x400049a4; -r_lld_white_list_rem = 0x400049b0; -r_llm_activity_free_get = 0x400049bc; -r_llm_activity_free_set = 0x400049c8; -r_llm_activity_syncing_get = 0x400049d4; -r_llm_adv_con_len_check = 0x400049e0; -r_llm_adv_hdl_to_id = 0x400049ec; -r_llm_adv_rep_flow_control_check = 0x400049f8; -r_llm_adv_rep_flow_control_update = 0x40004a04; -r_llm_adv_reports_list_check = 0x40004a10; -r_llm_adv_set_all_release = 0x40004a1c; -r_llm_adv_set_dft_params = 0x40004a28; -r_llm_adv_set_release = 0x40004a34; -r_llm_aes_res_cb = 0x40004a40; -r_llm_ble_update_adv_flow_control = 0x40004a4c; -r_llm_ch_map_update = 0x40004a58; -r_llm_cmd_cmp_send = 0x40004a64; -r_llm_cmd_stat_send = 0x40004a70; -r_llm_dev_list_empty_entry = 0x40004a7c; -r_llm_dev_list_search = 0x40004a88; -r_llm_env_adv_dup_filt_deinit = 0x40004a94; -r_llm_env_adv_dup_filt_init = 0x40004aa0; -r_llm_init_ble_adv_report_flow_contol = 0x40004aac; -r_llm_is_dev_connected = 0x40004ab8; -r_llm_is_dev_synced = 0x40004ac4; -r_llm_is_non_con_act_ongoing_check = 0x40004ad0; -r_llm_is_wl_accessible = 0x40004adc; -r_llm_le_evt_mask_check = 0x40004ae8; -r_llm_link_disc = 0x40004b00; -r_llm_master_ch_map_get = 0x40004b0c; -r_llm_msg_handler_tab_p_get = 0x40004b18; -r_llm_no_activity = 0x40004b24; -r_llm_per_adv_slot_dur = 0x40004b30; -r_llm_plan_elt_get = 0x40004b3c; -r_llm_rx_path_comp_get = 0x40004b48; -r_llm_scan_start = 0x40004b54; -r_llm_scan_sync_acad_attach = 0x40004b60; -r_llm_scan_sync_acad_detach = 0x40004b6c; -r_llm_send_adv_lost_event_to_host = 0x40004b78; -r_llm_tx_path_comp_get = 0x40004b84; -r_misc_deinit = 0x40004b90; -r_misc_free_em_buf_in_isr = 0x40004b9c; -r_misc_init = 0x40004ba8; -r_misc_msg_handler_tab_p_get = 0x40004bb4; -r_notEqual256 = 0x40004bc0; -r_phy_upd_proc_start = 0x40004bcc; -r_platform_reset = 0x40004bd8; -r_rf_em_init = 0x40004bf0; -r_rf_force_agc_enable = 0x40004bfc; -r_rf_reg_rd = 0x40004c08; -r_rf_reg_wr = 0x40004c14; -r_rf_reset = 0x40004c20; -r_rf_rssi_convert = 0x40004c2c; -r_rf_rw_v9_le_disable = 0x40004c38; -r_rf_rw_v9_le_enable = 0x40004c44; -r_rf_sleep = 0x40004c50; -r_rf_util_cs_fmt_convert = 0x40004c74; -r_rw_crypto_aes_ccm = 0x40004c80; -r_rw_crypto_aes_encrypt = 0x40004c8c; -r_rw_crypto_aes_init = 0x40004c98; -r_rw_crypto_aes_k1 = 0x40004ca4; -r_rw_crypto_aes_k2 = 0x40004cb0; -r_rw_crypto_aes_k3 = 0x40004cbc; -r_rw_crypto_aes_k4 = 0x40004cc8; -r_rw_crypto_aes_rand = 0x40004cd4; -r_rw_crypto_aes_result_handler = 0x40004ce0; -r_rw_crypto_aes_s1 = 0x40004cec; -r_rw_cryto_aes_cmac = 0x40004cf8; -r_rw_v9_init_em_radio_table = 0x40004d04; -r_rwble_sleep_enter = 0x40004d1c; -r_rwble_sleep_wakeup_end = 0x40004d28; -/* r_rwbtdm_isr_wrapper = 0x40004d34; */ -r_rwip_active_check = 0x40004d40; -r_rwip_aes_encrypt = 0x40004d4c; -/* r_rwip_assert = 0x40004d58; */ -r_rwip_crypt_evt_handler = 0x40004d64; -r_rwip_crypt_isr_handler = 0x40004d70; -r_rwip_eif_get = 0x40004d7c; -r_rwip_half_slot_2_lpcycles = 0x40004d88; -r_rwip_hus_2_lpcycles = 0x40004d94; -r_rwip_isr = 0x40004da0; -r_rwip_lpcycles_2_hus = 0x40004dac; -r_rwip_prevent_sleep_clear = 0x40004db8; -r_rwip_prevent_sleep_set = 0x40004dc4; -r_rwip_schedule = 0x40004dd0; -r_rwip_sleep = 0x40004ddc; -r_rwip_sw_int_handler = 0x40004de8; -r_rwip_sw_int_req = 0x40004df4; -r_rwip_time_get = 0x40004e00; -r_rwip_timer_10ms_handler = 0x40004e0c; -r_rwip_timer_10ms_set = 0x40004e18; -r_rwip_timer_hs_handler = 0x40004e24; -r_rwip_timer_hs_set = 0x40004e30; -r_rwip_timer_hus_handler = 0x40004e3c; -r_rwip_timer_hus_set = 0x40004e48; -r_rwip_wakeup = 0x40004e54; -/* r_rwip_wakeup_end = 0x40004e60; */ -r_rwip_wlcoex_set = 0x40004e6c; -r_sch_alarm_clear = 0x40004e78; -r_sch_alarm_init = 0x40004e84; -r_sch_alarm_prog = 0x40004e90; -r_sch_alarm_set = 0x40004e9c; -r_sch_alarm_timer_isr = 0x40004ea8; -r_sch_arb_conflict_check = 0x40004eb4; -r_sch_arb_elt_cancel = 0x40004ec0; -r_sch_arb_init = 0x40004ed8; -r_sch_arb_insert = 0x40004ee4; -r_sch_arb_prog_timer = 0x40004ef0; -r_sch_arb_remove = 0x40004efc; -r_sch_arb_sw_isr = 0x40004f08; -r_sch_plan_chk = 0x40004f14; -r_sch_plan_clock_wrap_offset_update = 0x40004f20; -r_sch_plan_init = 0x40004f2c; -r_sch_plan_interval_req = 0x40004f38; -r_sch_plan_offset_max_calc = 0x40004f44; -r_sch_plan_offset_req = 0x40004f50; -r_sch_plan_position_range_compute = 0x40004f5c; -r_sch_plan_rem = 0x40004f68; -r_sch_plan_req = 0x40004f74; -r_sch_prog_init = 0x40004f98; -r_sch_prog_push = 0x40004fa4; -r_sch_prog_rx_isr = 0x40004fb0; -r_sch_prog_skip_isr = 0x40004fbc; -r_sch_prog_tx_isr = 0x40004fc8; -r_sch_slice_bg_add = 0x40004fd4; -r_sch_slice_bg_remove = 0x40004fe0; -r_sch_slice_compute = 0x40004fec; -r_sch_slice_fg_add = 0x40004ff8; -r_sch_slice_fg_remove = 0x40005004; -r_sch_slice_init = 0x40005010; -r_sch_slice_per_add = 0x4000501c; -r_sch_slice_per_remove = 0x40005028; -r_sdk_config_get_bt_sleep_enable = 0x40005034; -r_sdk_config_get_hl_derived_opts = 0x40005040; -r_sdk_config_get_opts = 0x4000504c; -r_sdk_config_get_priv_opts = 0x40005058; -r_sdk_config_set_bt_sleep_enable = 0x40005064; -r_sdk_config_set_hl_derived_opts = 0x40005070; -r_sdk_config_set_opts = 0x4000507c; -r_specialModP256 = 0x40005088; -r_unloaded_area_init = 0x40005094; -r_vhci_flow_off = 0x400050a0; -r_vhci_flow_on = 0x400050ac; -r_vhci_notify_host_send_available = 0x400050b8; -r_vhci_send_to_host = 0x400050c4; -r_vnd_hci_command_handler = 0x400050d0; -r_vshci_init = 0x400050dc; -vnd_hci_command_handler_wrapper = 0x400050e8; -r_lld_legacy_adv_dynamic_pti_get = 0x400050f4; -r_lld_legacy_adv_dynamic_pti_process = 0x40005100; -r_lld_ext_adv_dynamic_pti_get = 0x4000510c; -r_lld_ext_adv_dynamic_aux_pti_process = 0x40005118; -r_lld_ext_adv_dynamic_pti_process = 0x40005124; -r_lld_adv_ext_pkt_prepare_set = 0x40005130; -r_lld_adv_ext_chain_connectable_construct = 0x40005148; -r_lld_adv_pkt_rx_connect_post = 0x40005160; -r_lld_adv_start_init_evt_param = 0x4000516c; -r_lld_adv_start_set_cs = 0x40005178; -/* r_lld_adv_start_update_filter_policy = 0x40005184; */ -r_lld_adv_start_schedule_asap = 0x40005190; -r_lld_con_tx_prog_new_packet_coex = 0x4000519c; -r_lld_per_adv_dynamic_pti_get = 0x400051b4; -r_lld_per_adv_evt_start_chm_upd = 0x400051c0; -r_lld_ext_scan_dynamic_pti_get = 0x400051cc; -r_lld_sync_insert = 0x400051e4; -r_sch_prog_ble_push = 0x400051f0; -r_sch_prog_bt_push = 0x400051fc; -r_lld_init_evt_end_type_set = 0x40005208; -r_lld_init_evt_end_type_get = 0x40005214; -r_lld_adv_direct_adv_use_rpa_addr_state_set = 0x40005220; -r_lld_adv_direct_adv_use_rpa_addr_state_get = 0x4000522c; -r_lld_init_evt_end_type_check_state_set = 0x40005238; -r_lld_init_evt_end_type_check_state_get = 0x40005244; /* Data (.data, .bss, .rodata) */ bt_rf_coex_cfg_p = 0x3fceffa8; bt_rf_coex_hooks_p = 0x3fceffa4; @@ -1738,38 +919,6 @@ rwip_coex_cfg = 0x3ff1eebe; rwip_priority = 0x3ff1eea8; veryBigHexP256 = 0x3ff1ee5c; -/* bluetooth hook funcs */ -r_llc_loc_encrypt_proc_continue_hook = 0x40001c60; -r_llc_loc_phy_upd_proc_continue_hook = 0x40001c64; -r_llc_rem_phy_upd_proc_continue_hook = 0x40001c68; -r_lld_scan_frm_eof_isr_hook = 0x40001c6c; -r_lld_scan_evt_start_cbk_hook = 0x40001c70; -r_lld_scan_process_pkt_rx_ext_adv_hook = 0x40001c78; -r_lld_scan_sched_hook = 0x40001c7c; -r_lld_adv_evt_start_cbk_hook = 0x40001c84; -r_lld_adv_aux_evt_start_cbk_hook = 0x40001c88; -r_lld_adv_frm_isr_hook = 0x40001c8c; -r_lld_adv_start_init_evt_param_hook = 0x40001c90; -r_lld_con_evt_canceled_cbk_hook = 0x40001c94; -r_lld_con_frm_isr_hook = 0x40001c98; -r_lld_con_tx_hook = 0x40001c9c; -r_lld_con_rx_hook = 0x40001ca0; -r_lld_con_evt_start_cbk_hook = 0x40001ca4; -r_lld_con_tx_prog_new_packet_hook = 0x40001cac; -r_lld_init_frm_eof_isr_hook = 0x40001cb0; -r_lld_init_evt_start_cbk_hook = 0x40001cb4; -r_lld_init_sched_hook = 0x40001cbc; -r_lld_init_process_pkt_tx_hook = 0x40001cc0; -r_lld_per_adv_evt_start_cbk_hook = 0x40001cc4; -r_lld_per_adv_frm_isr_hook = 0x40001cc8; -r_lld_per_adv_start_hook = 0x40001ccc; -r_lld_sync_frm_eof_isr_hook = 0x40001cd0; -r_lld_sync_evt_start_cbk_hook = 0x40001cd4; -r_lld_sync_start_hook = 0x40001cd8; -r_lld_sync_process_pkt_rx_pkt_check_hook = 0x40001cdc; -r_sch_arb_insert_hook = 0x40001ce0; -r_sch_plan_offset_req_hook = 0x40001ce4; - /*************************************** Group rom_pp ***************************************/ @@ -1851,7 +1000,7 @@ ppGetTxQFirstAvail_Locked = 0x400055b0; ppGetTxframe = 0x400055bc; /*ppMapTxQueue = 0x400055c8;*/ ppProcessRxPktHdr = 0x400055e0; -ppProcessTxQ = 0x400055ec; +/*ppProcessTxQ = 0x400055ec;*/ ppRecordBarRRC = 0x400055f8; lmacRequestTxopQueue = 0x40005604; lmacReleaseTxopQueue = 0x40005610; diff --git a/components/esp_rom/patches/esp_rom_systimer.c b/components/esp_rom/patches/esp_rom_systimer.c index 0b8b20e180d6..7de32f09e6ae 100644 --- a/components/esp_rom/patches/esp_rom_systimer.c +++ b/components/esp_rom/patches/esp_rom_systimer.c @@ -64,7 +64,7 @@ void systimer_hal_counter_value_advance(systimer_hal_context_t *hal, uint32_t co } #endif // CONFIG_IDF_TARGET_ESP32C2 && (CONFIG_ESP32C2_REV_MIN_FULL < 200) -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 void systimer_hal_init(systimer_hal_context_t *hal) { hal->dev = &SYSTIMER; @@ -78,6 +78,6 @@ void systimer_hal_deinit(systimer_hal_context_t *hal) systimer_ll_enable_clock(hal->dev, false); hal->dev = NULL; } -#endif // CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 +#endif // CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 #endif // CONFIG_HAL_SYSTIMER_USE_ROM_IMPL diff --git a/components/esp_security/CMakeLists.txt b/components/esp_security/CMakeLists.txt index d9c054b15ec4..da2fb0125bba 100644 --- a/components/esp_security/CMakeLists.txt +++ b/components/esp_security/CMakeLists.txt @@ -1,4 +1,5 @@ idf_build_get_property(target IDF_TARGET) +idf_build_get_property(non_os_build NON_OS_BUILD) if(${target} STREQUAL "linux") return() # This component is not supported by the POSIX/Linux simulator @@ -8,7 +9,7 @@ set(srcs "") set(priv_requires "") set(priv_includes "") -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) list(APPEND srcs "src/init.c") list(APPEND priv_includes "src/${IDF_TARGET}") @@ -37,6 +38,6 @@ idf_component_register(SRCS ${srcs} PRIV_INCLUDE_DIRS ${priv_includes} PRIV_REQUIRES ${priv_requires}) -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) target_link_libraries(${COMPONENT_LIB} PRIVATE "-u esp_security_init_include_impl") endif() diff --git a/components/esp_security/src/init.c b/components/esp_security/src/init.c index d00d0e9647f9..d12e1fe3265d 100644 --- a/components/esp_security/src/init.c +++ b/components/esp_security/src/init.c @@ -20,23 +20,15 @@ __attribute__((unused)) static const char *TAG = "esp_security"; static void esp_key_mgr_init(void) { - // The following operation makes the Key Manager to use eFuse key for ECDSA and XTS-AES operation by default - // This is to keep the default behavior same as the other chips - // If the Key Manager configuration is already locked then following operation does not have any effect + // The following code initializes the key manager. #if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY || SOC_KEY_MANAGER_FE_KEY_DEPLOY // Enable key manager clock // Using ll APIs which do not require critical section _key_mgr_ll_enable_bus_clock(true); _key_mgr_ll_enable_peripheral_clock(true); - + _key_mgr_ll_reset_register(); while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) { }; -#if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY - key_mgr_ll_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); -#endif -#if SOC_KEY_MANAGER_FE_KEY_DEPLOY - key_mgr_ll_set_key_usage(ESP_KEY_MGR_XTS_AES_128_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); -#endif #endif /* SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY || SOC_KEY_MANAGER_FE_KEY_DEPLOY */ } diff --git a/components/esp_security/test_apps/.build-test-rules.yml b/components/esp_security/test_apps/.build-test-rules.yml index abfc86a2c5da..6802faf7539e 100644 --- a/components/esp_security/test_apps/.build-test-rules.yml +++ b/components/esp_security/test_apps/.build-test-rules.yml @@ -1,7 +1,7 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps components/esp_security/test_apps/crypto_drivers: - disable: - - if: IDF_TARGET in ["esp32c61"] - temporary: true - reason: Support for ESP32C61 is yet to be added. + enable: + - if: ((SOC_HMAC_SUPPORTED == 1) or (SOC_DIG_SIGN_SUPPORTED == 1)) or (SOC_KEY_MANAGER_SUPPORTED == 1) + depends_components: + - esp_security diff --git a/components/esp_security/test_apps/crypto_drivers/README.md b/components/esp_security/test_apps/crypto_drivers/README.md index 351f5fdebc72..1dfe1331b41a 100644 --- a/components/esp_security/test_apps/crypto_drivers/README.md +++ b/components/esp_security/test_apps/crypto_drivers/README.md @@ -1,3 +1,3 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_security/test_apps/crypto_drivers/main/CMakeLists.txt b/components/esp_security/test_apps/crypto_drivers/main/CMakeLists.txt index 674856755475..b6ae16ae0a92 100644 --- a/components/esp_security/test_apps/crypto_drivers/main/CMakeLists.txt +++ b/components/esp_security/test_apps/crypto_drivers/main/CMakeLists.txt @@ -1,7 +1,16 @@ -set(srcs "test_app_main.c" - "test_ds.c" - "test_hmac.c" - "test_key_mgr.c") +set(srcs "test_app_main.c") + +if(CONFIG_SOC_HMAC_SUPPORTED) + list(APPEND srcs "test_hmac.c") +endif() + +if(CONFIG_SOC_DIG_SIGN_SUPPORTED) + list(APPEND srcs "test_ds.c") +endif() + +if(CONFIG_SOC_KEY_MANAGER_SUPPORTED) + list(APPEND srcs "test_key_mgr.c") +endif() idf_component_register(SRCS ${srcs} REQUIRES unity efuse test_utils spi_flash esp_security diff --git a/components/esp_security/test_apps/crypto_drivers/main/Kconfig.projbuild b/components/esp_security/test_apps/crypto_drivers/main/Kconfig.projbuild new file mode 100644 index 000000000000..7cdf8c00fa6f --- /dev/null +++ b/components/esp_security/test_apps/crypto_drivers/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "ESP Security Tests" + config ESP_SECURITY_ENABLE_FPGA_TESTS + bool "Allow enabling the esp_security tests that require burning efuses" + default y if IDF_ENV_FPGA + default n + help + This includes the esp_security tests that actually require burning some efuses. + It is better to run these tests on an FPGA to avoid mistakenly burning eFuses. +endmenu diff --git a/components/esp_security/test_apps/crypto_drivers/main/test_ds.c b/components/esp_security/test_apps/crypto_drivers/main/test_ds.c index d631c7dd3580..13d53308be69 100644 --- a/components/esp_security/test_apps/crypto_drivers/main/test_ds.c +++ b/components/esp_security/test_apps/crypto_drivers/main/test_ds.c @@ -8,8 +8,6 @@ #include "unity.h" #include "soc/soc_caps.h" - -#if SOC_DIG_SIGN_SUPPORTED #include "rom/efuse.h" #if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/digital_signature.h" @@ -257,7 +255,7 @@ TEST_CASE("Digital Signature Blocking HMAC key out of range", "[hw_crypto] [ds]" TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY0 - 1, signature_data)); } -#if CONFIG_IDF_ENV_FPGA +#if CONFIG_ESP_SECURITY_ENABLE_FPGA_TESTS static void burn_hmac_keys(void) { @@ -437,5 +435,4 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]") } } -#endif // CONFIG_IDF_ENV_FPGA -#endif // SOC_DIG_SIGN_SUPPORTED +#endif // CONFIG_ESP_SECURITY_ENABLE_FPGA_TESTS diff --git a/components/esp_security/test_apps/crypto_drivers/main/test_hmac.c b/components/esp_security/test_apps/crypto_drivers/main/test_hmac.c index 9c20debc5299..8f8ccf39ef4b 100644 --- a/components/esp_security/test_apps/crypto_drivers/main/test_hmac.c +++ b/components/esp_security/test_apps/crypto_drivers/main/test_hmac.c @@ -8,11 +8,9 @@ #include "esp_efuse.h" #include "esp_efuse_table.h" #include "esp_log.h" - -#if SOC_HMAC_SUPPORTED #include "esp_hmac.h" -#if CONFIG_IDF_ENV_FPGA +#if CONFIG_ESP_SECURITY_ENABLE_FPGA_TESTS /* Allow testing varying message lengths (truncating the same message) for various results */ @@ -1299,7 +1297,7 @@ TEST_CASE("HMAC 'upstream' wait lock", "[hw_crypto]") } } -#endif // CONFIG_IDF_ENV_FPGA +#endif // CONFIG_ESP_SECURITY_ENABLE_FPGA_TESTS /** * This test is just a parameter test and does not write any keys to efuse. @@ -1315,5 +1313,3 @@ TEST_CASE("HMAC key out of range", "[hw_crypto]") TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_hmac_calculate(HMAC_KEY0 - 1, message, 47, hmac)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_hmac_calculate(HMAC_KEY5 + 1, message, 47, hmac)); } - -#endif // SOC_HMAC_SUPPORTED diff --git a/components/esp_security/test_apps/crypto_drivers/main/test_key_mgr.c b/components/esp_security/test_apps/crypto_drivers/main/test_key_mgr.c index 4484a9fde5e0..1fdb5b28f198 100644 --- a/components/esp_security/test_apps/crypto_drivers/main/test_key_mgr.c +++ b/components/esp_security/test_apps/crypto_drivers/main/test_key_mgr.c @@ -7,7 +7,6 @@ #include "unity.h" #include "soc/soc_caps.h" -#if SOC_KEY_MANAGER_SUPPORTED #include "esp_partition.h" #include "esp_flash.h" #include "esp_log.h" @@ -143,4 +142,3 @@ TEST_CASE("Key Manager random mode: ECDSA key deployment", "[hw_crypto] [key_mgr esp_ret = esp_key_mgr_deploy_key_in_random_mode(&key_config, &key_info); TEST_ASSERT_EQUAL(ESP_OK, esp_ret); } -#endif diff --git a/components/esp_security/test_apps/crypto_drivers/pytest_crypto_drivers.py b/components/esp_security/test_apps/crypto_drivers/pytest_crypto_drivers.py index e0709970c50b..44435595f06c 100644 --- a/components/esp_security/test_apps/crypto_drivers/pytest_crypto_drivers.py +++ b/components/esp_security/test_apps/crypto_drivers/pytest_crypto_drivers.py @@ -1,17 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32h2 +@pytest.mark.esp32p4 +@pytest.mark.esp32c5 @pytest.mark.generic -@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='Support for ESP32C61 is yet to be added.') # TODO: [ESP32C61] IDF-10987 -@pytest.mark.parametrize( - 'config', - [ - pytest.param('default', marks=[pytest.mark.supported_targets]), - ], - indirect=True, -) def test_crypto_drivers(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=180) diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index d2f97850eceb..1443e619d4bb 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -147,3 +147,7 @@ endif() if(CONFIG_SOC_MEM_NON_CONTIGUOUS_SRAM) target_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--enable-non-contiguous-regions") endif() + +if(CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS) + add_subdirectory(openocd_stub_bins) +endif() diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index e597eac88faa..8e606c8f1976 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -92,14 +92,8 @@ menu "ESP System Settings" config ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK bool - default y if IDF_TARGET_ESP32 && ESP_SYSTEM_SINGLE_CORE_MODE - default y if IDF_TARGET_ESP32S2 - default y if IDF_TARGET_ESP32C3 - default y if IDF_TARGET_ESP32S3 - default y if IDF_TARGET_ESP32C6 - default n if IDF_TARGET_ESP32H2 # IDF-5667 - default y if IDF_TARGET_ESP32P4 - default y if IDF_TARGET_ESP32C5 + default n if IDF_TARGET_ESP32 && !ESP_SYSTEM_SINGLE_CORE_MODE + default y depends on SOC_RTC_FAST_MEM_SUPPORTED config ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP @@ -108,9 +102,8 @@ menu "ESP System Settings" depends on ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK help This config option allows to add RTC fast memory region to system heap with capability - similar to that of DRAM region but without DMA. This memory will be consumed first per - heap initialization order by early startup services and scheduler related code. Speed - wise RTC fast memory operates on APB clock and hence does not have much performance impact. + similar to that of DRAM region but without DMA. Speed wise RTC fast memory operates on + APB clock and hence does not have much performance impact. config ESP_SYSTEM_USE_EH_FRAME bool "Generate and use eh_frame for backtracing" @@ -542,6 +535,19 @@ menu "ESP System Settings" Debug stubs are used by OpenOCD to execute pre-compiled onboard code which does some useful debugging stuff, e.g. GCOV data dump. + config ESP_DEBUG_INCLUDE_OCD_STUB_BINS + bool "Preload OpenOCD stub binaries to speed up debugging. 8K memory will be reserved" + default y + depends on SOC_DEBUG_HAVE_OCD_STUB_BINS + help + OpenOCD uses stub code to access flash during programming or when inserting and removing + SW flash breakpoints. + To execute stub code, OpenOCD allocates memory on the target device, backs up the existing memory, + loads the stub binary, runs the binary, and then restores the original memory. + This process can be time-consuming, especially when using USB serial JTAG. + By enabling this option, 8K of memory in RAM will be preallocated with the stub code, + eliminating the need to back up and restore the memory region. + config ESP_DEBUG_OCDAWARE bool "Make exception and panic handlers JTAG/OCD aware" default y diff --git a/components/esp_system/ld/esp32c6/sections.ld.in b/components/esp_system/ld/esp32c6/sections.ld.in index 98b23613d328..da8a695be4af 100644 --- a/components/esp_system/ld/esp32c6/sections.ld.in +++ b/components/esp_system/ld/esp32c6/sections.ld.in @@ -156,6 +156,21 @@ SECTIONS .iram0.text : { _iram_start = ABSOLUTE(.); + +#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS + /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ + KEEP(*(.ocd_stub.code)); + KEEP(*(.ocd_stub.tramp)); + . = ALIGN(0x800); + KEEP(*(.ocd_stub.data)); + KEEP(*(.ocd_stub.bss)); + KEEP(*(.ocd_stub.stack)); + KEEP(*(.ocd_stub.params)); + . = ALIGN(0x1000); + KEEP(*(.ocd_stub.scratchmem)); + ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); +#endif + /* Vectors go to start of IRAM */ ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index 5ffe1de81d63..5fb84f6b3b0b 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -156,6 +156,21 @@ SECTIONS .iram0.text : { _iram_start = ABSOLUTE(.); + +#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS + /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ + KEEP(*(.ocd_stub.code)); + KEEP(*(.ocd_stub.tramp)); + . = ALIGN(0x800); + KEEP(*(.ocd_stub.data)); + KEEP(*(.ocd_stub.bss)); + KEEP(*(.ocd_stub.stack)); + KEEP(*(.ocd_stub.params)); + . = ALIGN(0x1000); + KEEP(*(.ocd_stub.scratchmem)); + ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); +#endif + /* Vectors go to start of IRAM */ ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); diff --git a/components/esp_system/openocd_stub_bins/CMakeLists.txt b/components/esp_system/openocd_stub_bins/CMakeLists.txt new file mode 100644 index 000000000000..ebd73f430aa9 --- /dev/null +++ b/components/esp_system/openocd_stub_bins/CMakeLists.txt @@ -0,0 +1,48 @@ +idf_build_get_property(target IDF_TARGET) + +# Function to add custom commands for copying stub files +function(add_copy_command src dest) + add_custom_command( + OUTPUT ${dest} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dest} + DEPENDS ${src} + COMMENT "Copying ${src} to ${dest}" + VERBATIM + ) +endfunction() + +set(openocd_path $ENV{OPENOCD_SCRIPTS}) + +if(openocd_path) + set(stub_bin_path ${openocd_path}/../espressif/stub_bins) + if(IS_DIRECTORY ${stub_bin_path} AND IS_DIRECTORY ${stub_bin_path}/${target}) + set(code_bin "${stub_bin_path}/${target}/stub_flash_idf_binary_code.inc") + set(data_bin "${stub_bin_path}/${target}/stub_flash_idf_binary_data.inc") + set(img_header "${stub_bin_path}/${target}/stub_flash_idf_image.h") + if(EXISTS ${code_bin} AND EXISTS ${data_bin} AND EXISTS ${img_header}) + set(dest_dir "${CMAKE_BINARY_DIR}/openocd_stub_bins") + set(output_code_bin "${dest_dir}/stub_flash_idf_binary_code.inc") + set(output_data_bin "${dest_dir}/stub_flash_idf_binary_data.inc") + set(output_img_header "${dest_dir}/stub_flash_idf_image.h") + add_copy_command(${code_bin} ${output_code_bin}) + add_copy_command(${data_bin} ${output_data_bin}) + add_copy_command(${img_header} ${output_img_header}) + add_custom_target(copy_stub_bins ALL + DEPENDS ${output_code_bin} ${output_data_bin} ${output_img_header} + COMMENT "Copying OpenOCD stub binaries and image header" + ) + add_dependencies(${COMPONENT_LIB} copy_stub_bins) + endif() + else() + message(FATAL_ERROR + "OpenOCD stub binary files couldn't be found! " + "To bypass this error, disable the CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS option") + endif() + + set(srcs "openocd_stub_flasher.c") + add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") + target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) + target_include_directories(${COMPONENT_LIB} PRIVATE ${dest_dir}) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_system_include_openocd_stub_binaries") + +endif() diff --git a/components/esp_system/openocd_stub_bins/esp_riscv_stub_tramp.inc b/components/esp_system/openocd_stub_bins/esp_riscv_stub_tramp.inc new file mode 100644 index 000000000000..22c0b530f609 --- /dev/null +++ b/components/esp_system/openocd_stub_bins/esp_riscv_stub_tramp.inc @@ -0,0 +1 @@ + 0x82, 0x98, 0x02, 0x90 diff --git a/components/esp_system/openocd_stub_bins/openocd_stub_flasher.c b/components/esp_system/openocd_stub_bins/openocd_stub_flasher.c new file mode 100644 index 000000000000..52331ec67c19 --- /dev/null +++ b/components/esp_system/openocd_stub_bins/openocd_stub_flasher.c @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "stub_flash_idf_image.h" + +/* Copied from openocd-esp32/contrib/loaders/flash/espressif/${target}/inc/stub_flash_idf_binary_code.inc */ +static const uint8_t s_flasher_stub_code[] __attribute__((used, section(".ocd_stub.code"))) = { +#include "stub_flash_idf_binary_code.inc" +}; + +/* Copied from openocd-esp32/src/target/espressif/esp_riscv_stub_tramp.inc */ +static const uint8_t s_flasher_stub_tramp[] __attribute__((used, section(".ocd_stub.tramp"))) = { +#include "esp_riscv_stub_tramp.inc" +}; + +/* Copied from openocd-esp32/contrib/loaders/flash/espressif/${target}/inc/stub_flash_idf_binary_data.inc */ +static const uint8_t s_flasher_stub_data[] __attribute__((used, section(".ocd_stub.data"))) = { +#include "stub_flash_idf_binary_data.inc" +}; + +static uint8_t s_flasher_stub_bss[OPENOCD_STUB_BSS_SIZE] __attribute__((used, section(".ocd_stub.bss"))); +static uint8_t s_flasher_stub_stack[OPENOCD_STUB_STACK_SIZE] __attribute__((used, section(".ocd_stub.stack"))); +static uint8_t s_flasher_stub_params[OPENOCD_STUB_PARAM_SIZE] __attribute__((used, section(".ocd_stub.params"))); +static uint8_t s_flasher_stub_bp_sectors[OPENOCD_STUB_BP_SECTOR_SIZE] __attribute__((used, section(".ocd_stub.scratchmem"))); + +// Hook to force the linker to include this file +void esp_system_include_openocd_stub_binaries(void) +{ +} diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 0911e8abd557..340f89ee0538 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -13,6 +13,7 @@ #include "esp_log.h" #include "esp_chip_info.h" +#include "esp_app_format.h" #include "esp_private/cache_err_int.h" #include "esp_clk_internal.h" @@ -787,9 +788,13 @@ void IRAM_ATTR call_start_cpu0(void) // Read the application binary image header. This will also decrypt the header if the image is encrypted. __attribute__((unused)) esp_image_header_t fhdr = {0}; - // This assumes that DROM is the first segment in the application binary, i.e. that we can read - // the binary header through cache by accessing SOC_DROM_LOW address. - hal_memcpy(&fhdr, (void *) SOC_DROM_LOW, sizeof(fhdr)); + // We can access the image header through the cache by reading from the memory-mapped virtual DROM start offset + uint32_t fhdr_src_addr = (uint32_t)(&_rodata_reserved_start) - sizeof(esp_image_header_t) - sizeof(esp_image_segment_header_t); + hal_memcpy(&fhdr, (void *) fhdr_src_addr, sizeof(fhdr)); + if (fhdr.magic != ESP_IMAGE_HEADER_MAGIC) { + ESP_EARLY_LOGE(TAG, "Invalid app image header"); + abort(); + } #if CONFIG_IDF_TARGET_ESP32 #if !CONFIG_SPIRAM_BOOT_INIT diff --git a/components/esp_system/port/soc/esp32/system_internal.c b/components/esp_system/port/soc/esp32/system_internal.c index 75cae925114a..da76aa90d1a6 100644 --- a/components/esp_system/port/soc/esp32/system_internal.c +++ b/components/esp_system/port/soc/esp32/system_internal.c @@ -97,9 +97,9 @@ void IRAM_ATTR esp_restart_noos(void) wdt_hal_disable(&wdt1_context); wdt_hal_write_protect_enable(&wdt1_context); -#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#ifdef CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM if (esp_ptr_external_ram(esp_cpu_get_sp())) { - // If stack_addr is from External Memory (CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY is used) + // If stack_addr is from External Memory (CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM is used) // then need to switch SP to Internal Memory otherwise // we will get the "Cache disabled but cached memory region accessed" error after Cache_Read_Disable. uint32_t new_sp = SOC_DRAM_LOW + (SOC_DRAM_HIGH - SOC_DRAM_LOW) / 2; diff --git a/components/esp_system/port/soc/esp32c3/clk.c b/components/esp_system/port/soc/esp32c3/clk.c index ece3d4c732fc..ecb5d083856f 100644 --- a/components/esp_system/port/soc/esp32c3/clk.c +++ b/components/esp_system/port/soc/esp32c3/clk.c @@ -235,7 +235,7 @@ __attribute__((weak)) void esp_perip_clk_init(void) SYSTEM_SPI3_CLK_EN | SYSTEM_SPI4_CLK_EN | SYSTEM_TWAI_CLK_EN | - SYSTEM_I2S1_CLK_EN | + SYSTEM_I2S0_CLK_EN | SYSTEM_SPI2_DMA_CLK_EN | SYSTEM_SPI3_DMA_CLK_EN; @@ -274,7 +274,7 @@ __attribute__((weak)) void esp_perip_clk_init(void) SYSTEM_SPI3_CLK_EN | SYSTEM_SPI4_CLK_EN | SYSTEM_I2C_EXT1_CLK_EN | - SYSTEM_I2S1_CLK_EN | + SYSTEM_I2S0_CLK_EN | SYSTEM_SPI2_DMA_CLK_EN | SYSTEM_SPI3_DMA_CLK_EN; common_perip_clk1 = 0; diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index 7bf484cab4ee..6e62a960edde 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -164,6 +164,12 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) } rtc_clk_slow_src_set(rtc_slow_clk_src); + // Disable unused clock sources after clock source switching is complete. + // Regardless of the clock source selection, the internal 136K clock source will always keep on. + if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_XTAL32K && rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + rtc_clk_32k_enable(false); + } + if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. * Improve calibration routine to wait until the frequency is stable. @@ -242,7 +248,7 @@ __attribute__((weak)) void esp_perip_clk_init(void) SYSTEM_SPI3_CLK_EN | SYSTEM_SPI4_CLK_EN | SYSTEM_TWAI_CLK_EN | - SYSTEM_I2S1_CLK_EN | + SYSTEM_I2S0_CLK_EN | SYSTEM_SPI2_DMA_CLK_EN | SYSTEM_SPI3_DMA_CLK_EN; @@ -272,7 +278,7 @@ __attribute__((weak)) void esp_perip_clk_init(void) SYSTEM_SPI3_CLK_EN | SYSTEM_SPI4_CLK_EN | SYSTEM_I2C_EXT1_CLK_EN | - SYSTEM_I2S1_CLK_EN | + SYSTEM_I2S0_CLK_EN | SYSTEM_SPI2_DMA_CLK_EN | SYSTEM_SPI3_DMA_CLK_EN; common_perip_clk1 = 0; diff --git a/components/esp_system/port/soc/esp32c6/clk.c b/components/esp_system/port/soc/esp32c6/clk.c index 23a8ddab32f9..36e023cd561d 100644 --- a/components/esp_system/port/soc/esp32c6/clk.c +++ b/components/esp_system/port/soc/esp32c6/clk.c @@ -185,6 +185,15 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) } rtc_clk_slow_src_set(rtc_slow_clk_src); + // Disable unused clock sources after clock source switching is complete. + // Regardless of the clock source selection, the internal 136K clock source will always keep on. + if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_XTAL32K && rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + rtc_clk_32k_enable(false); + } + if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_RC32K) { + rtc_clk_rc32k_enable(false); + } + if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. * Improve calibration routine to wait until the frequency is stable. diff --git a/components/esp_system/port/soc/esp32c61/clk.c b/components/esp_system/port/soc/esp32c61/clk.c index 035cc1c87f3b..7e865037ab64 100644 --- a/components/esp_system/port/soc/esp32c61/clk.c +++ b/components/esp_system/port/soc/esp32c61/clk.c @@ -148,6 +148,12 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) } rtc_clk_slow_src_set(rtc_slow_clk_src); + // Disable unused clock sources after clock source switching is complete. + // Regardless of the clock source selection, the internal 136K clock source will always keep on. + if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_XTAL32K && rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + rtc_clk_32k_enable(false); + } + if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. * Improve calibration routine to wait until the frequency is stable. diff --git a/components/esp_system/port/soc/esp32h2/clk.c b/components/esp_system/port/soc/esp32h2/clk.c index 02aa13411a0f..026fd5c19ea1 100644 --- a/components/esp_system/port/soc/esp32h2/clk.c +++ b/components/esp_system/port/soc/esp32h2/clk.c @@ -184,6 +184,15 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) } rtc_clk_slow_src_set(rtc_slow_clk_src); + // Disable unused clock sources after clock source switching is complete. + // Regardless of the clock source selection, the internal 136K clock source will always keep on. + if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_XTAL32K && rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + rtc_clk_32k_enable(false); + } + if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_RC32K) { + rtc_clk_rc32k_enable(false); + } + if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. * Improve calibration routine to wait until the frequency is stable. diff --git a/components/esp_system/port/soc/esp32p4/Kconfig.system b/components/esp_system/port/soc/esp32p4/Kconfig.system index 5ffec7fe769b..2e1d235b6874 100644 --- a/components/esp_system/port/soc/esp32p4/Kconfig.system +++ b/components/esp_system/port/soc/esp32p4/Kconfig.system @@ -10,7 +10,7 @@ menu "Brownout Detector" choice ESP_BROWNOUT_DET_LVL_SEL prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET + depends on ESP_BROWNOUT_DET && (ESP32P4_REV_MIN_FULL <= 1) default ESP_BROWNOUT_DET_LVL_SEL_7 help The brownout detector will reset the chip when the supply voltage is approximately @@ -33,13 +33,32 @@ menu "Brownout Detector" bool "3.27V" endchoice + choice ESP_BROWNOUT_DET_LVL_SEL_V2 + prompt "Brownout voltage level" + default ESP_BROWNOUT_DET_LVL_SEL_7_V2 + depends on ESP_BROWNOUT_DET && (ESP32P4_REV_MIN_FULL >= 100) + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7_V2 + bool "2.6V" + config ESP_BROWNOUT_DET_LVL_SEL_6_V2 + bool "2.52V" + config ESP_BROWNOUT_DET_LVL_SEL_5_V2 + bool "2.42V" + endchoice + config ESP_BROWNOUT_DET_LVL int default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 || ESP_BROWNOUT_DET_LVL_SEL_5_V2 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 || ESP_BROWNOUT_DET_LVL_SEL_6_V2 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 || ESP_BROWNOUT_DET_LVL_SEL_7_V2 endmenu diff --git a/components/esp_system/port/soc/esp32p4/clk.c b/components/esp_system/port/soc/esp32p4/clk.c index fabbfe22ed06..bb9a6e0aa51b 100644 --- a/components/esp_system/port/soc/esp32p4/clk.c +++ b/components/esp_system/port/soc/esp32p4/clk.c @@ -189,6 +189,15 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) } rtc_clk_slow_src_set(rtc_slow_clk_src); + // Disable unused clock sources after clock source switching is complete. + // Regardless of the clock source selection, the internal 136K clock source will always keep on. + if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + rtc_clk_32k_enable(false); + } + if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_RC32K) { + rtc_clk_rc32k_enable(false); + } + if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. * Improve calibration routine to wait until the frequency is stable. diff --git a/components/esp_system/port/soc/esp32s2/clk.c b/components/esp_system/port/soc/esp32s2/clk.c index 45d932ba5205..2b786b62f9ab 100644 --- a/components/esp_system/port/soc/esp32s2/clk.c +++ b/components/esp_system/port/soc/esp32s2/clk.c @@ -240,7 +240,6 @@ __attribute__((weak)) void esp_perip_clk_init(void) DPORT_PWM0_CLK_EN | DPORT_TWAI_CLK_EN | DPORT_PWM1_CLK_EN | - DPORT_I2S1_CLK_EN | DPORT_SPI2_DMA_CLK_EN | DPORT_SPI3_DMA_CLK_EN | DPORT_PWM2_CLK_EN | @@ -276,7 +275,6 @@ __attribute__((weak)) void esp_perip_clk_init(void) DPORT_UHCI1_CLK_EN | DPORT_SPI3_CLK_EN | DPORT_I2C_EXT1_CLK_EN | - DPORT_I2S1_CLK_EN | DPORT_SPI2_DMA_CLK_EN | DPORT_SPI3_DMA_CLK_EN; common_perip_clk1 = 0; diff --git a/components/esp_system/port/soc/esp32s2/system_internal.c b/components/esp_system/port/soc/esp32s2/system_internal.c index 3de3bafdf187..8eb6c0325c25 100644 --- a/components/esp_system/port/soc/esp32s2/system_internal.c +++ b/components/esp_system/port/soc/esp32s2/system_internal.c @@ -85,9 +85,9 @@ void IRAM_ATTR esp_restart_noos(void) wdt_hal_disable(&wdt1_context); wdt_hal_write_protect_enable(&wdt1_context); -#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#ifdef CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM if (esp_ptr_external_ram(esp_cpu_get_sp())) { - // If stack_addr is from External Memory (CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY is used) + // If stack_addr is from External Memory (CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM is used) // then need to switch SP to Internal Memory otherwise // we will get the "Cache disabled but cached memory region accessed" error after Cache_Read_Disable. uint32_t new_sp = ALIGN_DOWN(_bss_end, 16); diff --git a/components/esp_system/port/soc/esp32s3/system_internal.c b/components/esp_system/port/soc/esp32s3/system_internal.c index ebdaccbcb25f..f0edae876cbb 100644 --- a/components/esp_system/port/soc/esp32s3/system_internal.c +++ b/components/esp_system/port/soc/esp32s3/system_internal.c @@ -92,9 +92,9 @@ void IRAM_ATTR esp_restart_noos(void) wdt_hal_disable(&wdt1_context); wdt_hal_write_protect_enable(&wdt1_context); -#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#ifdef CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM if (esp_ptr_external_ram(esp_cpu_get_sp())) { - // If stack_addr is from External Memory (CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY is used) + // If stack_addr is from External Memory (CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM is used) // then need to switch SP to Internal Memory otherwise // we will get the "Cache disabled but cached memory region accessed" error after Cache_Read_Disable. uint32_t new_sp = ALIGN_DOWN(_bss_end, 16); diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_reset_reason.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_reset_reason.c index 3008f15b62cd..491c3299b45b 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_reset_reason.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_reset_reason.c @@ -318,7 +318,7 @@ TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_BROWNOUT after brownout event", do_brownout, check_reset_reason_brownout); -#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#ifdef CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM #ifndef CONFIG_FREERTOS_UNICORE #if CONFIG_IDF_TARGET_ARCH_XTENSA #include "xt_instr_macros.h" @@ -402,6 +402,6 @@ TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_PANIC after an exception in a ta #endif //CONFIG_IDF_TARGET_ARCH_XTENSA #endif // CONFIG_FREERTOS_UNICORE -#endif // CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#endif // CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM /* Not tested here: ESP_RST_SDIO */ diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_systick_etm.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_systick_etm.c index d82cf13d625c..58793d18249c 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_systick_etm.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_systick_etm.c @@ -51,7 +51,7 @@ TEST_CASE("rtos_systick_etm_event", "[etm]") TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a)); - // should see a 500Hz square wave on the GPIO (if RTOS systick is set to 1000Hz) + // should see a 50Hz square wave on the GPIO (if RTOS systick is set to 100Hz) vTaskDelay(pdMS_TO_TICKS(1000)); // delete etm primitives diff --git a/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.psram b/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.psram index 482bcd8baa53..f29df53fffe5 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.psram +++ b/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.psram @@ -1,2 +1,2 @@ CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y diff --git a/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.psram_with_pd_top b/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.psram_with_pd_top index 440009beb18b..d1b0d3024436 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.psram_with_pd_top +++ b/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.psram_with_pd_top @@ -1,4 +1,4 @@ CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y diff --git a/components/esp_timer/src/esp_timer_impl_lac.c b/components/esp_timer/src/esp_timer_impl_lac.c index d557716e659f..79503303af56 100644 --- a/components/esp_timer/src/esp_timer_impl_lac.c +++ b/components/esp_timer/src/esp_timer_impl_lac.c @@ -222,11 +222,11 @@ static void IRAM_ATTR timer_alarm_isr(void *arg) void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us) { - portENTER_CRITICAL(&s_time_update_lock); + portENTER_CRITICAL_SAFE(&s_time_update_lock); assert(apb_ticks_per_us >= 3 && "divider value too low"); assert(apb_ticks_per_us % TICKS_PER_US == 0 && "APB frequency (in MHz) should be divisible by TICK_PER_US"); REG_SET_FIELD(CONFIG_REG, TIMG_LACT_DIVIDER, apb_ticks_per_us / TICKS_PER_US); - portEXIT_CRITICAL(&s_time_update_lock); + portEXIT_CRITICAL_SAFE(&s_time_update_lock); } void esp_timer_impl_set(uint64_t new_us) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index eb69f2056cef..f105c83ff3fd 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -28,8 +28,8 @@ menu "Wi-Fi" int "Max number of WiFi static RX buffers" range 2 25 if !SOC_WIFI_HE_SUPPORT range 2 128 if SOC_WIFI_HE_SUPPORT - default 10 if !SPIRAM_TRY_ALLOCATE_WIFI_LWIP - default 16 if SPIRAM_TRY_ALLOCATE_WIFI_LWIP + default 10 if !(SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) + default 16 if (SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) help Set the number of WiFi static RX buffers. Each buffer takes approximately 1.6KB of RAM. The static rx buffers are allocated when esp_wifi_init is called, they are not freed @@ -80,7 +80,7 @@ menu "Wi-Fi" bool "Static" config ESP_WIFI_DYNAMIC_TX_BUFFER bool "Dynamic" - depends on !SPIRAM_USE_MALLOC + depends on !(SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) endchoice config ESP_WIFI_TX_BUFFER_TYPE @@ -105,8 +105,8 @@ menu "Wi-Fi" config ESP_WIFI_CACHE_TX_BUFFER_NUM int "Max number of WiFi cache TX buffers" - depends on SPIRAM - range 16 128 + depends on (SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) + range 0 128 default 32 help Set the number of WiFi cache TX buffer number. @@ -203,8 +203,8 @@ menu "Wi-Fi" depends on ESP_WIFI_AMPDU_RX_ENABLED range 2 32 if !SOC_WIFI_HE_SUPPORT range 2 64 if SOC_WIFI_HE_SUPPORT - default 6 if !SPIRAM_TRY_ALLOCATE_WIFI_LWIP - default 16 if SPIRAM_TRY_ALLOCATE_WIFI_LWIP + default 6 if !(SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) + default 16 if (SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) help Set the size of WiFi Block Ack RX window. Generally a bigger value means higher throughput and better compatibility but more memory. Most of time we should NOT change the default value unless special @@ -215,7 +215,7 @@ menu "Wi-Fi" config ESP_WIFI_AMSDU_TX_ENABLED bool "WiFi AMSDU TX" - depends on SPIRAM + depends on (ESP_WIFI_CACHE_TX_BUFFER_NUM >= 2) default n help Select this option to enable AMSDU TX feature diff --git a/components/esp_wifi/include/esp_mesh.h b/components/esp_wifi/include/esp_mesh.h index 18e55c2dfdb9..7a7e85cf893b 100644 --- a/components/esp_wifi/include/esp_mesh.h +++ b/components/esp_wifi/include/esp_mesh.h @@ -637,7 +637,8 @@ esp_err_t esp_mesh_stop(void); * @param[in] to the address of the final destination of the packet * - If the packet is to the root, set this parameter to NULL. * - If the packet is to an external IP network, set this parameter to the IPv4:PORT combination. - * This packet will be delivered to the root firstly, then the root will forward this packet to the final IP server address. + * This packet will be delivered to the root firstly, then users need to call esp_mesh_recv_toDS() on the root node to forward this + * packet to the final IP server address. * @param[in] data pointer to a sending mesh packet * - Field size should not exceed MESH_MPS. Note that the size of one mesh packet should not exceed MESH_MTU. * - Field proto should be set to data protocol in use (default is MESH_PROTO_BIN for binary). diff --git a/components/esp_wifi/include/esp_now.h b/components/esp_wifi/include/esp_now.h index 734fbcf8bf9d..af7695e25871 100644 --- a/components/esp_wifi/include/esp_now.h +++ b/components/esp_wifi/include/esp_now.h @@ -98,9 +98,10 @@ typedef struct esp_now_recv_info { */ typedef struct esp_now_rate_config { wifi_phy_mode_t phymode; /**< ESPNOW phymode of specified interface */ - wifi_phy_rate_t rate; /**< ESPNOW rate of specified interface*/ - bool ersu; /**< ESPNOW using ersu send frame*/ - bool dcm; /**< ESPNOW using dcm rate to send frame*/ + wifi_phy_rate_t rate; /**< ESPNOW rate of specified interface */ + bool ersu; /**< ESPNOW using ERSU to send frame, ERSU is a transmission mode related to 802.11 ax. + ERSU is always used in long distance transmission, and its frame has lower rate compared with SU mode */ + bool dcm; /**< ESPNOW using dcm rate to send frame */ } esp_now_rate_config_t; /** diff --git a/components/esp_wifi/include/esp_wifi.h b/components/esp_wifi/include/esp_wifi.h index ce08ecb74846..fc321d20367c 100644 --- a/components/esp_wifi/include/esp_wifi.h +++ b/components/esp_wifi/include/esp_wifi.h @@ -129,7 +129,7 @@ typedef struct { #define WIFI_STATIC_TX_BUFFER_NUM 0 #endif -#if CONFIG_SPIRAM +#ifdef CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM #define WIFI_CACHE_TX_BUFFER_NUM CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM #else #define WIFI_CACHE_TX_BUFFER_NUM 0 @@ -224,10 +224,10 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs; #define WIFI_ENABLE_WPA3_SAE 0 #endif -#if CONFIG_SPIRAM -#define WIFI_ENABLE_SPIRAM (1<<1) +#if WIFI_CACHE_TX_BUFFER_NUM > 0 +#define WIFI_ENABLE_CACHE_TX_BUFFER (1<<1) #else -#define WIFI_ENABLE_SPIRAM 0 +#define WIFI_ENABLE_CACHE_TX_BUFFER 0 #endif #if CONFIG_ESP_WIFI_FTM_INITIATOR_SUPPORT @@ -289,7 +289,7 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs; /* Set additional WiFi features and capabilities */ #define WIFI_FEATURE_CAPS (WIFI_ENABLE_WPA3_SAE | \ - WIFI_ENABLE_SPIRAM | \ + WIFI_ENABLE_CACHE_TX_BUFFER | \ WIFI_FTM_INITIATOR | \ WIFI_FTM_RESPONDER | \ WIFI_ENABLE_GCMP | \ diff --git a/components/esp_wifi/include/esp_wifi_he.h b/components/esp_wifi/include/esp_wifi_he.h index 99a3be564b27..619c7b3fa6c0 100644 --- a/components/esp_wifi/include/esp_wifi_he.h +++ b/components/esp_wifi/include/esp_wifi_he.h @@ -9,6 +9,7 @@ #include #include #include "esp_err.h" +#include "esp_wifi_types.h" #include "esp_wifi_he_types.h" #ifdef __cplusplus @@ -219,15 +220,18 @@ esp_err_t esp_wifi_sta_twt_config(wifi_twt_config_t *config); /** * @brief Enable bss color collision detection. * - * @param[in] enable If true, when the station detects a BSS color collision, it will report the BSS color collision event to the access point (AP). + * @attention Currently, only STA BSS color collision detection is supported. + * + * @param ifx interface to be configured + * @param enable If true, when the STA detects a BSS color collision, it will report the BSS color collision event to the access point (AP). * * @return * - ESP_OK: succeed + * - ESP_ERR_WIFI_IF: Invalid interface * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init * - ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start - * - ESP_ERR_NOT_SUPPORTED: This API is not supported in AP mode yet */ -esp_err_t esp_wifi_sta_enable_bsscolor_collision_detection(bool enable); +esp_err_t esp_wifi_enable_bsscolor_collision_detection(wifi_interface_t ifx, bool enable); #ifdef __cplusplus } diff --git a/components/esp_wifi/include/esp_wifi_he_types.h b/components/esp_wifi/include/esp_wifi_he_types.h index e9dc2e17a4db..e2fe9c9f7551 100644 --- a/components/esp_wifi/include/esp_wifi_he_types.h +++ b/components/esp_wifi/include/esp_wifi_he_types.h @@ -406,6 +406,7 @@ typedef enum { /** Argument structure for twt configuration */ typedef struct { bool post_wakeup_event; /**< post twt wakeup event */ + bool twt_enable_keep_alive; /**< twt enable send qos null to keep alive */ } wifi_twt_config_t; /** Argument structure for WIFI_EVENT_TWT_WAKEUP event */ diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index 3e49682df5a7..832ce0cfb678 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -17,145 +17,173 @@ extern "C" { #endif +/** + * @brief Wi-Fi mode type + */ typedef enum { - WIFI_MODE_NULL = 0, /**< null mode */ - WIFI_MODE_STA, /**< WiFi station mode */ - WIFI_MODE_AP, /**< WiFi soft-AP mode */ - WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */ - WIFI_MODE_NAN, /**< WiFi NAN mode */ + WIFI_MODE_NULL = 0, /**< Null mode */ + WIFI_MODE_STA, /**< Wi-Fi station mode */ + WIFI_MODE_AP, /**< Wi-Fi soft-AP mode */ + WIFI_MODE_APSTA, /**< Wi-Fi station + soft-AP mode */ + WIFI_MODE_NAN, /**< Wi-Fi NAN mode */ WIFI_MODE_MAX } wifi_mode_t; +/** + * @brief Wi-Fi interface type + */ typedef enum { - WIFI_IF_STA = ESP_IF_WIFI_STA, - WIFI_IF_AP = ESP_IF_WIFI_AP, + WIFI_IF_STA = ESP_IF_WIFI_STA, /**< Station interface */ + WIFI_IF_AP = ESP_IF_WIFI_AP, /**< Soft-AP interface */ #if CONFIG_SOC_WIFI_NAN_SUPPORT || !CONFIG_SOC_WIFI_ENABLED - WIFI_IF_NAN = ESP_IF_WIFI_NAN, + WIFI_IF_NAN = ESP_IF_WIFI_NAN, /**< NAN interface */ #endif - WIFI_IF_MAX + WIFI_IF_MAX /**< Maximum number of interfaces */ } wifi_interface_t; -#define WIFI_OFFCHAN_TX_REQ 1 -#define WIFI_OFFCHAN_TX_CANCEL 0 +#define WIFI_OFFCHAN_TX_REQ 1 /**< Request off-channel transmission */ +#define WIFI_OFFCHAN_TX_CANCEL 0 /**< Cancel off-channel transmission */ -#define WIFI_ROC_REQ 1 -#define WIFI_ROC_CANCEL 0 +#define WIFI_ROC_REQ 1 /**< Request remain on channel */ +#define WIFI_ROC_CANCEL 0 /**< Cancel remain on channel */ +/** + * @brief Wi-Fi country policy + */ typedef enum { WIFI_COUNTRY_POLICY_AUTO, /**< Country policy is auto, use the country info of AP to which the station is connected */ WIFI_COUNTRY_POLICY_MANUAL, /**< Country policy is manual, always use the configured country info */ } wifi_country_policy_t; -/** @brief Structure describing WiFi country-based regional restrictions. */ +/** + * @brief Structure describing Wi-Fi country-based regional restrictions. + */ typedef struct { - char cc[3]; /**< country code string */ - uint8_t schan; /**< start channel of the allowed 2.4GHz WiFi channels */ - uint8_t nchan; /**< total channel number of the allowed 2.4GHz WiFi channels */ - int8_t max_tx_power; /**< This field is used for getting WiFi maximum transmitting power, call esp_wifi_set_max_tx_power to set the maximum transmitting power. */ - wifi_country_policy_t policy; /**< country policy */ + char cc[3]; /**< Country code string */ + uint8_t schan; /**< Start channel of the allowed 2.4GHz Wi-Fi channels */ + uint8_t nchan; /**< Total channel number of the allowed 2.4GHz Wi-Fi channels */ + int8_t max_tx_power; /**< This field is used for getting Wi-Fi maximum transmitting power, call esp_wifi_set_max_tx_power to set the maximum transmitting power. */ + wifi_country_policy_t policy; /**< Country policy */ #if CONFIG_SOC_WIFI_SUPPORT_5G - uint32_t wifi_5g_channel_mask; /**< A bitmask representing the allowed 5GHz WiFi channels. + uint32_t wifi_5g_channel_mask; /**< A bitmask representing the allowed 5GHz Wi-Fi channels. Each bit in the mask corresponds to a specific channel as wifi_5g_channel_bit_t shown. Bitmask set to 0 indicates 5GHz channels are allowed according to local regulatory rules. Please note that configured bitmask takes effect only when policy is manual. */ #endif } wifi_country_t; -/* Strength of authmodes */ -/* OPEN < WEP < WPA_PSK < OWE < WPA2_PSK = WPA_WPA2_PSK < WAPI_PSK < WPA3_PSK = WPA2_WPA3_PSK = DPP */ +/** + * @brief Wi-Fi authmode type + * Strength of authmodes + * Personal Networks : OPEN < WEP < WPA_PSK < OWE < WPA2_PSK = WPA_WPA2_PSK < WAPI_PSK < WPA3_PSK = WPA2_WPA3_PSK = DPP + * Enterprise Networks : WIFI_AUTH_WPA2_ENTERPRISE < WIFI_AUTH_WPA3_ENTERPRISE = WIFI_AUTH_WPA2_WPA3_ENTERPRISE < WIFI_AUTH_WPA3_ENT_192 + */ typedef enum { - WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */ - WIFI_AUTH_WEP, /**< authenticate mode : WEP */ - WIFI_AUTH_WPA_PSK, /**< authenticate mode : WPA_PSK */ - WIFI_AUTH_WPA2_PSK, /**< authenticate mode : WPA2_PSK */ - WIFI_AUTH_WPA_WPA2_PSK, /**< authenticate mode : WPA_WPA2_PSK */ - WIFI_AUTH_ENTERPRISE, /**< authenticate mode : WiFi EAP security */ - WIFI_AUTH_WPA2_ENTERPRISE = WIFI_AUTH_ENTERPRISE, /**< authenticate mode : WiFi EAP security */ - WIFI_AUTH_WPA3_PSK, /**< authenticate mode : WPA3_PSK */ - WIFI_AUTH_WPA2_WPA3_PSK, /**< authenticate mode : WPA2_WPA3_PSK */ - WIFI_AUTH_WAPI_PSK, /**< authenticate mode : WAPI_PSK */ - WIFI_AUTH_OWE, /**< authenticate mode : OWE */ - WIFI_AUTH_WPA3_ENT_192, /**< authenticate mode : WPA3_ENT_SUITE_B_192_BIT */ - WIFI_AUTH_WPA3_EXT_PSK, /**< this authentication mode will yield same result as WIFI_AUTH_WPA3_PSK and not recommended to be used. It will be deprecated in future, please use WIFI_AUTH_WPA3_PSK instead. */ - WIFI_AUTH_WPA3_EXT_PSK_MIXED_MODE, /**< this authentication mode will yield same result as WIFI_AUTH_WPA3_PSK and not recommended to be used. It will be deprecated in future, please use WIFI_AUTH_WPA3_PSK instead.*/ - WIFI_AUTH_DPP, /**< authenticate mode : DPP */ + WIFI_AUTH_OPEN = 0, /**< Authenticate mode : open */ + WIFI_AUTH_WEP, /**< Authenticate mode : WEP */ + WIFI_AUTH_WPA_PSK, /**< Authenticate mode : WPA_PSK */ + WIFI_AUTH_WPA2_PSK, /**< Authenticate mode : WPA2_PSK */ + WIFI_AUTH_WPA_WPA2_PSK, /**< Authenticate mode : WPA_WPA2_PSK */ + WIFI_AUTH_ENTERPRISE, /**< Authenticate mode : Wi-Fi EAP security */ + WIFI_AUTH_WPA2_ENTERPRISE = WIFI_AUTH_ENTERPRISE, /**< Authenticate mode : Wi-Fi EAP security */ + WIFI_AUTH_WPA3_PSK, /**< Authenticate mode : WPA3_PSK */ + WIFI_AUTH_WPA2_WPA3_PSK, /**< Authenticate mode : WPA2_WPA3_PSK */ + WIFI_AUTH_WAPI_PSK, /**< Authenticate mode : WAPI_PSK */ + WIFI_AUTH_OWE, /**< Authenticate mode : OWE */ + WIFI_AUTH_WPA3_ENT_192, /**< Authenticate mode : WPA3_ENT_SUITE_B_192_BIT */ + WIFI_AUTH_WPA3_EXT_PSK, /**< This authentication mode will yield same result as WIFI_AUTH_WPA3_PSK and not recommended to be used. It will be deprecated in future, please use WIFI_AUTH_WPA3_PSK instead. */ + WIFI_AUTH_WPA3_EXT_PSK_MIXED_MODE, /**< This authentication mode will yield same result as WIFI_AUTH_WPA3_PSK and not recommended to be used. It will be deprecated in future, please use WIFI_AUTH_WPA3_PSK instead.*/ + WIFI_AUTH_DPP, /**< Authenticate mode : DPP */ + WIFI_AUTH_WPA3_ENTERPRISE, /**< Authenticate mode : WPA3-Enterprise Only Mode */ + WIFI_AUTH_WPA2_WPA3_ENTERPRISE, /**< Authenticate mode : WPA3-Enterprise Transition Mode */ WIFI_AUTH_MAX } wifi_auth_mode_t; +/** + * @brief Wi-Fi disconnection reason codes + * + * These reason codes are used to indicate the cause of disconnection. + */ typedef enum { - WIFI_REASON_UNSPECIFIED = 1, - WIFI_REASON_AUTH_EXPIRE = 2, - WIFI_REASON_AUTH_LEAVE = 3, - WIFI_REASON_ASSOC_EXPIRE = 4, - WIFI_REASON_ASSOC_TOOMANY = 5, - WIFI_REASON_NOT_AUTHED = 6, - WIFI_REASON_NOT_ASSOCED = 7, - WIFI_REASON_ASSOC_LEAVE = 8, - WIFI_REASON_ASSOC_NOT_AUTHED = 9, - WIFI_REASON_DISASSOC_PWRCAP_BAD = 10, - WIFI_REASON_DISASSOC_SUPCHAN_BAD = 11, - WIFI_REASON_BSS_TRANSITION_DISASSOC = 12, - WIFI_REASON_IE_INVALID = 13, - WIFI_REASON_MIC_FAILURE = 14, - WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, - WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, - WIFI_REASON_IE_IN_4WAY_DIFFERS = 17, - WIFI_REASON_GROUP_CIPHER_INVALID = 18, - WIFI_REASON_PAIRWISE_CIPHER_INVALID = 19, - WIFI_REASON_AKMP_INVALID = 20, - WIFI_REASON_UNSUPP_RSN_IE_VERSION = 21, - WIFI_REASON_INVALID_RSN_IE_CAP = 22, - WIFI_REASON_802_1X_AUTH_FAILED = 23, - WIFI_REASON_CIPHER_SUITE_REJECTED = 24, - WIFI_REASON_TDLS_PEER_UNREACHABLE = 25, - WIFI_REASON_TDLS_UNSPECIFIED = 26, - WIFI_REASON_SSP_REQUESTED_DISASSOC = 27, - WIFI_REASON_NO_SSP_ROAMING_AGREEMENT = 28, - WIFI_REASON_BAD_CIPHER_OR_AKM = 29, - WIFI_REASON_NOT_AUTHORIZED_THIS_LOCATION = 30, - WIFI_REASON_SERVICE_CHANGE_PERCLUDES_TS = 31, - WIFI_REASON_UNSPECIFIED_QOS = 32, - WIFI_REASON_NOT_ENOUGH_BANDWIDTH = 33, - WIFI_REASON_MISSING_ACKS = 34, - WIFI_REASON_EXCEEDED_TXOP = 35, - WIFI_REASON_STA_LEAVING = 36, - WIFI_REASON_END_BA = 37, - WIFI_REASON_UNKNOWN_BA = 38, - WIFI_REASON_TIMEOUT = 39, - WIFI_REASON_PEER_INITIATED = 46, - WIFI_REASON_AP_INITIATED = 47, - WIFI_REASON_INVALID_FT_ACTION_FRAME_COUNT = 48, - WIFI_REASON_INVALID_PMKID = 49, - WIFI_REASON_INVALID_MDE = 50, - WIFI_REASON_INVALID_FTE = 51, - WIFI_REASON_TRANSMISSION_LINK_ESTABLISH_FAILED = 67, - WIFI_REASON_ALTERATIVE_CHANNEL_OCCUPIED = 68, - - WIFI_REASON_BEACON_TIMEOUT = 200, - WIFI_REASON_NO_AP_FOUND = 201, - WIFI_REASON_AUTH_FAIL = 202, - WIFI_REASON_ASSOC_FAIL = 203, - WIFI_REASON_HANDSHAKE_TIMEOUT = 204, - WIFI_REASON_CONNECTION_FAIL = 205, - WIFI_REASON_AP_TSF_RESET = 206, - WIFI_REASON_ROAMING = 207, - WIFI_REASON_ASSOC_COMEBACK_TIME_TOO_LONG = 208, - WIFI_REASON_SA_QUERY_TIMEOUT = 209, - WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY = 210, - WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD = 211, - WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD = 212, + WIFI_REASON_UNSPECIFIED = 1, /**< Unspecified reason */ + WIFI_REASON_AUTH_EXPIRE = 2, /**< Authentication expired */ + WIFI_REASON_AUTH_LEAVE = 3, /**< Deauthentication due to leaving */ + WIFI_REASON_ASSOC_EXPIRE = 4, /**< Deprecated, will be removed in next IDF major release */ + WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, /**< Disassociated due to inactivity */ + WIFI_REASON_ASSOC_TOOMANY = 5, /**< Too many associated stations */ + WIFI_REASON_NOT_AUTHED = 6, /**< Deprecated, will be removed in next IDF major release */ + WIFI_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, /**< Class 2 frame received from nonauthenticated STA */ + WIFI_REASON_NOT_ASSOCED = 7, /**< Deprecated, will be removed in next IDF major release */ + WIFI_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, /**< Class 3 frame received from nonassociated STA */ + WIFI_REASON_ASSOC_LEAVE = 8, /**< Deassociated due to leaving */ + WIFI_REASON_ASSOC_NOT_AUTHED = 9, /**< Association but not authenticated */ + WIFI_REASON_DISASSOC_PWRCAP_BAD = 10, /**< Disassociated due to poor power capability */ + WIFI_REASON_DISASSOC_SUPCHAN_BAD = 11, /**< Disassociated due to unsupported channel */ + WIFI_REASON_BSS_TRANSITION_DISASSOC = 12, /**< Disassociated due to BSS transition */ + WIFI_REASON_IE_INVALID = 13, /**< Invalid Information Element (IE) */ + WIFI_REASON_MIC_FAILURE = 14, /**< MIC failure */ + WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, /**< 4-way handshake timeout */ + WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, /**< Group key update timeout */ + WIFI_REASON_IE_IN_4WAY_DIFFERS = 17, /**< IE differs in 4-way handshake */ + WIFI_REASON_GROUP_CIPHER_INVALID = 18, /**< Invalid group cipher */ + WIFI_REASON_PAIRWISE_CIPHER_INVALID = 19, /**< Invalid pairwise cipher */ + WIFI_REASON_AKMP_INVALID = 20, /**< Invalid AKMP */ + WIFI_REASON_UNSUPP_RSN_IE_VERSION = 21, /**< Unsupported RSN IE version */ + WIFI_REASON_INVALID_RSN_IE_CAP = 22, /**< Invalid RSN IE capabilities */ + WIFI_REASON_802_1X_AUTH_FAILED = 23, /**< 802.1X authentication failed */ + WIFI_REASON_CIPHER_SUITE_REJECTED = 24, /**< Cipher suite rejected */ + WIFI_REASON_TDLS_PEER_UNREACHABLE = 25, /**< TDLS peer unreachable */ + WIFI_REASON_TDLS_UNSPECIFIED = 26, /**< TDLS unspecified */ + WIFI_REASON_SSP_REQUESTED_DISASSOC = 27, /**< SSP requested disassociation */ + WIFI_REASON_NO_SSP_ROAMING_AGREEMENT = 28, /**< No SSP roaming agreement */ + WIFI_REASON_BAD_CIPHER_OR_AKM = 29, /**< Bad cipher or AKM */ + WIFI_REASON_NOT_AUTHORIZED_THIS_LOCATION = 30, /**< Not authorized in this location */ + WIFI_REASON_SERVICE_CHANGE_PERCLUDES_TS = 31, /**< Service change precludes TS */ + WIFI_REASON_UNSPECIFIED_QOS = 32, /**< Unspecified QoS reason */ + WIFI_REASON_NOT_ENOUGH_BANDWIDTH = 33, /**< Not enough bandwidth */ + WIFI_REASON_MISSING_ACKS = 34, /**< Missing ACKs */ + WIFI_REASON_EXCEEDED_TXOP = 35, /**< Exceeded TXOP */ + WIFI_REASON_STA_LEAVING = 36, /**< Station leaving */ + WIFI_REASON_END_BA = 37, /**< End of Block Ack (BA) */ + WIFI_REASON_UNKNOWN_BA = 38, /**< Unknown Block Ack (BA) */ + WIFI_REASON_TIMEOUT = 39, /**< Timeout */ + WIFI_REASON_PEER_INITIATED = 46, /**< Peer initiated disassociation */ + WIFI_REASON_AP_INITIATED = 47, /**< AP initiated disassociation */ + WIFI_REASON_INVALID_FT_ACTION_FRAME_COUNT = 48, /**< Invalid FT action frame count */ + WIFI_REASON_INVALID_PMKID = 49, /**< Invalid PMKID */ + WIFI_REASON_INVALID_MDE = 50, /**< Invalid MDE */ + WIFI_REASON_INVALID_FTE = 51, /**< Invalid FTE */ + WIFI_REASON_TRANSMISSION_LINK_ESTABLISH_FAILED = 67, /**< Transmission link establishment failed */ + WIFI_REASON_ALTERATIVE_CHANNEL_OCCUPIED = 68, /**< Alternative channel occupied */ + + WIFI_REASON_BEACON_TIMEOUT = 200, /**< Beacon timeout */ + WIFI_REASON_NO_AP_FOUND = 201, /**< No AP found */ + WIFI_REASON_AUTH_FAIL = 202, /**< Authentication failed */ + WIFI_REASON_ASSOC_FAIL = 203, /**< Association failed */ + WIFI_REASON_HANDSHAKE_TIMEOUT = 204, /**< Handshake timeout */ + WIFI_REASON_CONNECTION_FAIL = 205, /**< Connection failed */ + WIFI_REASON_AP_TSF_RESET = 206, /**< AP TSF reset */ + WIFI_REASON_ROAMING = 207, /**< Roaming */ + WIFI_REASON_ASSOC_COMEBACK_TIME_TOO_LONG = 208, /**< Association comeback time too long */ + WIFI_REASON_SA_QUERY_TIMEOUT = 209, /**< SA query timeout */ + WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY = 210, /**< No AP found with compatible security */ + WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD = 211, /**< No AP found in auth mode threshold */ + WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD = 212, /**< No AP found in RSSI threshold */ } wifi_err_reason_t; +/** + * @brief Wi-Fi second channel type + */ typedef enum { - WIFI_SECOND_CHAN_NONE = 0, /**< the channel width is HT20 */ - WIFI_SECOND_CHAN_ABOVE, /**< the channel width is HT40 and the secondary channel is above the primary channel */ - WIFI_SECOND_CHAN_BELOW, /**< the channel width is HT40 and the secondary channel is below the primary channel */ + WIFI_SECOND_CHAN_NONE = 0, /**< The channel width is HT20 */ + WIFI_SECOND_CHAN_ABOVE, /**< The channel width is HT40 and the secondary channel is above the primary channel */ + WIFI_SECOND_CHAN_BELOW, /**< The channel width is HT40 and the secondary channel is below the primary channel */ } wifi_second_chan_t; -#define WIFI_ACTIVE_SCAN_MIN_DEFAULT_TIME 0 -#define WIFI_ACTIVE_SCAN_MAX_DEFAULT_TIME 120 -#define WIFI_PASSIVE_SCAN_DEFAULT_TIME 360 -#define WIFI_SCAN_HOME_CHANNEL_DWELL_DEFAULT_TIME 30 +#define WIFI_ACTIVE_SCAN_MIN_DEFAULT_TIME 0 /**< Default minimum active scan time per channel */ +#define WIFI_ACTIVE_SCAN_MAX_DEFAULT_TIME 120 /**< Default maximum active scan time per channel */ +#define WIFI_PASSIVE_SCAN_DEFAULT_TIME 360 /**< Default passive scan time per channel */ +#define WIFI_SCAN_HOME_CHANNEL_DWELL_DEFAULT_TIME 30 /**< Default time spent at home channel between scanning consecutive channels */ #define WIFI_SCAN_PARAMS_DEFAULT_CONFIG() { \ .scan_time.active.min = WIFI_ACTIVE_SCAN_MIN_DEFAULT_TIME, \ @@ -164,153 +192,199 @@ typedef enum { .home_chan_dwell_time = WIFI_SCAN_HOME_CHANNEL_DWELL_DEFAULT_TIME\ } +/** + * @brief Wi-Fi scan type + */ typedef enum { - WIFI_SCAN_TYPE_ACTIVE = 0, /**< active scan */ - WIFI_SCAN_TYPE_PASSIVE, /**< passive scan */ + WIFI_SCAN_TYPE_ACTIVE = 0, /**< Active scan */ + WIFI_SCAN_TYPE_PASSIVE, /**< Passive scan */ } wifi_scan_type_t; -/** @brief Range of active scan times per channel */ +/** + * @brief Range of active scan times per channel + */ typedef struct { - uint32_t min; /**< minimum active scan time per channel, units: millisecond */ - uint32_t max; /**< maximum active scan time per channel, units: millisecond, values above 1500ms may + uint32_t min; /**< Minimum active scan time per channel, units: millisecond */ + uint32_t max; /**< Maximum active scan time per channel, units: millisecond, values above 1500 ms may cause station to disconnect from AP and are not recommended. */ } wifi_active_scan_time_t; -/** @brief Aggregate of active & passive scan time per channel */ +/** + * @brief Aggregate of active & passive scan time per channel + */ typedef struct { - wifi_active_scan_time_t active; /**< active scan time per channel, units: millisecond. */ - uint32_t passive; /**< passive scan time per channel, units: millisecond, values above 1500ms may + wifi_active_scan_time_t active; /**< Active scan time per channel, units: millisecond. */ + uint32_t passive; /**< Passive scan time per channel, units: millisecond, values above 1500 ms may cause station to disconnect from AP and are not recommended. */ } wifi_scan_time_t; +/** + * @brief Channel bitmap for setting specific channels to be scanned + */ typedef struct { uint16_t ghz_2_channels; /**< Represents 2.4 GHz channels, that bits can be set as wifi_2g_channel_bit_t shown. */ uint32_t ghz_5_channels; /**< Represents 5 GHz channels, that bits can be set as wifi_5g_channel_bit_t shown. */ } wifi_scan_channel_bitmap_t; -/** @brief Parameters for an SSID scan. */ +/** + * @brief Parameters for an SSID scan + */ typedef struct { uint8_t *ssid; /**< SSID of AP */ uint8_t *bssid; /**< MAC address of AP */ - uint8_t channel; /**< channel, scan the specific channel */ - bool show_hidden; /**< enable to scan AP whose SSID is hidden */ - wifi_scan_type_t scan_type; /**< scan type, active or passive */ - wifi_scan_time_t scan_time; /**< scan time per channel */ - uint8_t home_chan_dwell_time; /**< time spent at home channel between scanning consecutive channels. */ + uint8_t channel; /**< Channel, scan the specific channel */ + bool show_hidden; /**< Enable it to scan AP whose SSID is hidden */ + wifi_scan_type_t scan_type; /**< Scan type, active or passive */ + wifi_scan_time_t scan_time; /**< Scan time per channel */ + uint8_t home_chan_dwell_time; /**< Time spent at home channel between scanning consecutive channels. */ wifi_scan_channel_bitmap_t channel_bitmap; /**< Channel bitmap for setting specific channels to be scanned. Please note that the 'channel' parameter above needs to be set to 0 to allow scanning by bitmap. - Also, note that only allowed channels configured by wifi_country_t can be scaned. */ + Also, note that only allowed channels configured by wifi_country_t can be scanned. */ } wifi_scan_config_t; -/** @brief Parameters default scan configurations. */ +/** + * @brief Parameters default scan configurations + */ typedef struct { - wifi_scan_time_t scan_time; /**< scan time per channel */ - uint8_t home_chan_dwell_time;/**< time spent at home channel between scanning consecutive channels.*/ + wifi_scan_time_t scan_time; /**< Scan time per channel */ + uint8_t home_chan_dwell_time;/**< Time spent at home channel between scanning consecutive channels.*/ } wifi_scan_default_params_t; +/** + * @brief Wi-Fi cipher type + */ typedef enum { - WIFI_CIPHER_TYPE_NONE = 0, /**< the cipher type is none */ - WIFI_CIPHER_TYPE_WEP40, /**< the cipher type is WEP40 */ - WIFI_CIPHER_TYPE_WEP104, /**< the cipher type is WEP104 */ - WIFI_CIPHER_TYPE_TKIP, /**< the cipher type is TKIP */ - WIFI_CIPHER_TYPE_CCMP, /**< the cipher type is CCMP */ - WIFI_CIPHER_TYPE_TKIP_CCMP, /**< the cipher type is TKIP and CCMP */ - WIFI_CIPHER_TYPE_AES_CMAC128,/**< the cipher type is AES-CMAC-128 */ - WIFI_CIPHER_TYPE_SMS4, /**< the cipher type is SMS4 */ - WIFI_CIPHER_TYPE_GCMP, /**< the cipher type is GCMP */ - WIFI_CIPHER_TYPE_GCMP256, /**< the cipher type is GCMP-256 */ - WIFI_CIPHER_TYPE_AES_GMAC128,/**< the cipher type is AES-GMAC-128 */ - WIFI_CIPHER_TYPE_AES_GMAC256,/**< the cipher type is AES-GMAC-256 */ - WIFI_CIPHER_TYPE_UNKNOWN, /**< the cipher type is unknown */ + WIFI_CIPHER_TYPE_NONE = 0, /**< The cipher type is none */ + WIFI_CIPHER_TYPE_WEP40, /**< The cipher type is WEP40 */ + WIFI_CIPHER_TYPE_WEP104, /**< The cipher type is WEP104 */ + WIFI_CIPHER_TYPE_TKIP, /**< The cipher type is TKIP */ + WIFI_CIPHER_TYPE_CCMP, /**< The cipher type is CCMP */ + WIFI_CIPHER_TYPE_TKIP_CCMP, /**< The cipher type is TKIP and CCMP */ + WIFI_CIPHER_TYPE_AES_CMAC128,/**< The cipher type is AES-CMAC-128 */ + WIFI_CIPHER_TYPE_SMS4, /**< The cipher type is SMS4 */ + WIFI_CIPHER_TYPE_GCMP, /**< The cipher type is GCMP */ + WIFI_CIPHER_TYPE_GCMP256, /**< The cipher type is GCMP-256 */ + WIFI_CIPHER_TYPE_AES_GMAC128,/**< The cipher type is AES-GMAC-128 */ + WIFI_CIPHER_TYPE_AES_GMAC256,/**< The cipher type is AES-GMAC-256 */ + WIFI_CIPHER_TYPE_UNKNOWN, /**< The cipher type is unknown */ } wifi_cipher_type_t; /** - * @brief WiFi antenna - * + * @brief Wi-Fi bandwidth type */ typedef enum { - WIFI_ANT_ANT0, /**< WiFi antenna 0 */ - WIFI_ANT_ANT1, /**< WiFi antenna 1 */ - WIFI_ANT_MAX, /**< Invalid WiFi antenna */ + WIFI_BW_HT20 = 1, /**< Bandwidth is HT20 */ + WIFI_BW20 = WIFI_BW_HT20, /**< Bandwidth is 20 MHz */ + WIFI_BW_HT40 = 2, /**< Bandwidth is HT40 */ + WIFI_BW40 = WIFI_BW_HT40, /**< Bandwidth is 40 MHz */ + WIFI_BW80 = 3, /**< Bandwidth is 80 MHz */ + WIFI_BW160 = 4, /**< Bandwidth is 160 MHz */ + WIFI_BW80_BW80 = 5, /**< Bandwidth is 80 + 80 MHz */ +} wifi_bandwidth_t; + +/** + * @brief Wi-Fi antenna + */ +typedef enum { + WIFI_ANT_ANT0, /**< Wi-Fi antenna 0 */ + WIFI_ANT_ANT1, /**< Wi-Fi antenna 1 */ + WIFI_ANT_MAX, /**< Invalid Wi-Fi antenna */ } wifi_ant_t; -/** @brief Description of a WiFi AP HE Info */ +/** + * @brief Description of a Wi-Fi AP HE Info + */ typedef struct { - uint8_t bss_color: 6; /**< an unsigned integer whose value is the BSS Color of the BSS corresponding to the AP */ - uint8_t partial_bss_color: 1; /**< indicate if an AID assignment rule based on the BSS color */ - uint8_t bss_color_disabled: 1; /**< indicate if the use of BSS color is disabled */ - uint8_t bssid_index; /**< in M-BSSID set, identifies the nontransmitted BSSID */ + uint8_t bss_color: 6; /**< The BSS Color value associated with the AP's corresponding BSS */ + uint8_t partial_bss_color: 1; /**< Indicates whether an AID assignment rule is based on the BSS color */ + uint8_t bss_color_disabled: 1; /**< Indicates whether the BSS color usage is disabled */ + uint8_t bssid_index; /**< In a M-BSSID set, identifies the non-transmitted BSSID */ } wifi_he_ap_info_t; -/** @brief Description of a WiFi AP */ +/** + * @brief Description of a Wi-Fi AP + */ typedef struct { uint8_t bssid[6]; /**< MAC address of AP */ uint8_t ssid[33]; /**< SSID of AP */ - uint8_t primary; /**< channel of AP */ - wifi_second_chan_t second; /**< secondary channel of AP */ - int8_t rssi; /**< signal strength of AP. Note that in some rare cases where signal strength is very strong, rssi values can be slightly positive */ - wifi_auth_mode_t authmode; /**< authmode of AP */ - wifi_cipher_type_t pairwise_cipher; /**< pairwise cipher of AP */ - wifi_cipher_type_t group_cipher; /**< group cipher of AP */ - wifi_ant_t ant; /**< antenna used to receive beacon from AP */ - uint32_t phy_11b: 1; /**< bit: 0 flag to identify if 11b mode is enabled or not */ - uint32_t phy_11g: 1; /**< bit: 1 flag to identify if 11g mode is enabled or not */ - uint32_t phy_11n: 1; /**< bit: 2 flag to identify if 11n mode is enabled or not */ - uint32_t phy_lr: 1; /**< bit: 3 flag to identify if low rate is enabled or not */ - uint32_t phy_11a: 1; /**< bit: 4 flag to identify if 11ax mode is enabled or not */ - uint32_t phy_11ac: 1; /**< bit: 5 flag to identify if 11ax mode is enabled or not */ - uint32_t phy_11ax: 1; /**< bit: 6 flag to identify if 11ax mode is enabled or not */ - uint32_t wps: 1; /**< bit: 7 flag to identify if WPS is supported or not */ - uint32_t ftm_responder: 1; /**< bit: 8 flag to identify if FTM is supported in responder mode */ - uint32_t ftm_initiator: 1; /**< bit: 9 flag to identify if FTM is supported in initiator mode */ - uint32_t reserved: 22; /**< bit: 10..31 reserved */ - wifi_country_t country; /**< country information of AP */ + uint8_t primary; /**< Channel of AP */ + wifi_second_chan_t second; /**< Secondary channel of AP */ + int8_t rssi; /**< Signal strength of AP. Note that in some rare cases where signal strength is very strong, RSSI values can be slightly positive */ + wifi_auth_mode_t authmode; /**< Auth mode of AP */ + wifi_cipher_type_t pairwise_cipher; /**< Pairwise cipher of AP */ + wifi_cipher_type_t group_cipher; /**< Group cipher of AP */ + wifi_ant_t ant; /**< Antenna used to receive beacon from AP */ + uint32_t phy_11b: 1; /**< Bit: 0 flag to identify if 11b mode is enabled or not */ + uint32_t phy_11g: 1; /**< Bit: 1 flag to identify if 11g mode is enabled or not */ + uint32_t phy_11n: 1; /**< Bit: 2 flag to identify if 11n mode is enabled or not */ + uint32_t phy_lr: 1; /**< Bit: 3 flag to identify if low rate is enabled or not */ + uint32_t phy_11a: 1; /**< Bit: 4 flag to identify if 11ax mode is enabled or not */ + uint32_t phy_11ac: 1; /**< Bit: 5 flag to identify if 11ax mode is enabled or not */ + uint32_t phy_11ax: 1; /**< Bit: 6 flag to identify if 11ax mode is enabled or not */ + uint32_t wps: 1; /**< Bit: 7 flag to identify if WPS is supported or not */ + uint32_t ftm_responder: 1; /**< Bit: 8 flag to identify if FTM is supported in responder mode */ + uint32_t ftm_initiator: 1; /**< Bit: 9 flag to identify if FTM is supported in initiator mode */ + uint32_t reserved: 22; /**< Bit: 10..31 reserved */ + wifi_country_t country; /**< Country information of AP */ wifi_he_ap_info_t he_ap; /**< HE AP info */ - uint8_t bandwidth; /**< For either 20 MHz or 40 MHz operation, the Channel Width field is set to 0. - For AP 80 MHz this value is set to 1. For AP 160MHz sets this value is set to 2. - For AP 80+80MHz this value is set to 3*/ - uint8_t vht_ch_freq1; /**< this fields are used only AP bandwidth is 80 and 160 MHz, to transmit the center channel - frequency of the BSS. For AP bandwidth is 80+80MHz, it is the center channel frequency + wifi_bandwidth_t bandwidth; /**< Bandwidth of AP */ + uint8_t vht_ch_freq1; /**< This fields are used only AP bandwidth is 80 and 160 MHz, to transmit the center channel + frequency of the BSS. For AP bandwidth is 80 + 80 MHz, it is the center channel frequency of the lower frequency segment.*/ - uint8_t vht_ch_freq2; /**< this fields are used only AP bandwidth is 80+80MHz, and is used to transmit the center + uint8_t vht_ch_freq2; /**< this fields are used only AP bandwidth is 80 + 80 MHz, and is used to transmit the center channel frequency of the second segment. */ } wifi_ap_record_t; +/** + * @brief Wi-Fi scan method + */ typedef enum { WIFI_FAST_SCAN = 0, /**< Do fast scan, scan will end after find SSID match AP */ WIFI_ALL_CHANNEL_SCAN, /**< All channel scan, scan will end after scan all the channel */ } wifi_scan_method_t; +/** + * @brief Wi-Fi sort AP method + */ typedef enum { WIFI_CONNECT_AP_BY_SIGNAL = 0, /**< Sort match AP in scan list by RSSI */ WIFI_CONNECT_AP_BY_SECURITY, /**< Sort match AP in scan list by security mode */ } wifi_sort_method_t; -/** @brief Structure describing parameters for a WiFi fast scan */ +/** + * @brief Structure describing parameters for a Wi-Fi fast scan + */ typedef struct { - int8_t rssi; /**< The minimum rssi to accept in the fast scan mode */ - wifi_auth_mode_t authmode; /**< The weakest authmode to accept in the fast scan mode - Note: In case this value is not set and password is set as per WPA2 standards(password len >= 8), it will be defaulted to WPA2 and device won't connect to deprecated WEP/WPA networks. Please set authmode threshold as WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK to connect to WEP/WPA networks */ + int8_t rssi; /**< The minimum rssi to accept in the fast scan mode */ + wifi_auth_mode_t authmode; /**< The weakest auth mode to accept in the fast scan mode + Note: In case this value is not set and password is set as per WPA2 standards(password len >= 8), it will be defaulted to WPA2 and device won't connect to deprecated WEP/WPA networks. Please set auth mode threshold as WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK to connect to WEP/WPA networks */ uint8_t rssi_5g_adjustment; /**< The RSSI value of the 5G AP is within the rssi_5g_adjustment range compared to the 2G AP, the 5G AP will be given priority for connection. */ } wifi_scan_threshold_t; +/** + * @brief Wi-Fi power save type + */ typedef enum { WIFI_PS_NONE, /**< No power save */ WIFI_PS_MIN_MODEM, /**< Minimum modem power saving. In this mode, station wakes up to receive beacon every DTIM period */ WIFI_PS_MAX_MODEM, /**< Maximum modem power saving. In this mode, interval to receive beacons is determined by the listen_interval parameter in wifi_sta_config_t */ } wifi_ps_type_t; -/** Argument structure for WiFi band */ +/** + * @brief Argument structure for Wi-Fi band + */ typedef enum { - WIFI_BAND_2G = 1, /* Band is 2.4G */ - WIFI_BAND_5G = 2, /* Band is 5G */ + WIFI_BAND_2G = 1, /**< Band is 2.4 GHz */ + WIFI_BAND_5G = 2, /**< Band is 5 GHz */ } wifi_band_t; -/** Argument structure for WiFi band mode */ +/** + * @brief Argument structure for Wi-Fi band mode + */ typedef enum { - WIFI_BAND_MODE_2G_ONLY = 1, /* WiFi band mode is 2.4G only */ - WIFI_BAND_MODE_5G_ONLY = 2, /* WiFi band mode is 5G only */ - WIFI_BAND_MODE_AUTO = 3, /* WiFi band mode is 2.4G + 5G */ + WIFI_BAND_MODE_2G_ONLY = 1, /**< Wi-Fi band mode is 2.4 GHz only */ + WIFI_BAND_MODE_5G_ONLY = 2, /**< Wi-Fi band mode is 5 GHz only */ + WIFI_BAND_MODE_AUTO = 3, /**< Wi-Fi band mode is 2.4 GHz + 5 GHz */ } wifi_band_mode_t; #ifndef BIT @@ -331,91 +405,89 @@ typedef enum { /** Argument structure for 2.4G channels */ typedef enum { - WIFI_CHANNEL_1 = BIT(1), /**< wifi channel 1 */ - WIFI_CHANNEL_2 = BIT(2), /**< wifi channel 2 */ - WIFI_CHANNEL_3 = BIT(3), /**< wifi channel 3 */ - WIFI_CHANNEL_4 = BIT(4), /**< wifi channel 4 */ - WIFI_CHANNEL_5 = BIT(5), /**< wifi channel 5 */ - WIFI_CHANNEL_6 = BIT(6), /**< wifi channel 6 */ - WIFI_CHANNEL_7 = BIT(7), /**< wifi channel 7 */ - WIFI_CHANNEL_8 = BIT(8), /**< wifi channel 8 */ - WIFI_CHANNEL_9 = BIT(9), /**< wifi channel 9 */ - WIFI_CHANNEL_10 = BIT(10), /**< wifi channel 10 */ - WIFI_CHANNEL_11 = BIT(11), /**< wifi channel 11 */ - WIFI_CHANNEL_12 = BIT(12), /**< wifi channel 12 */ - WIFI_CHANNEL_13 = BIT(13), /**< wifi channel 13 */ - WIFI_CHANNEL_14 = BIT(14), /**< wifi channel 14 */ + WIFI_CHANNEL_1 = BIT(1), /**< Wi-Fi channel 1 */ + WIFI_CHANNEL_2 = BIT(2), /**< Wi-Fi channel 2 */ + WIFI_CHANNEL_3 = BIT(3), /**< Wi-Fi channel 3 */ + WIFI_CHANNEL_4 = BIT(4), /**< Wi-Fi channel 4 */ + WIFI_CHANNEL_5 = BIT(5), /**< Wi-Fi channel 5 */ + WIFI_CHANNEL_6 = BIT(6), /**< Wi-Fi channel 6 */ + WIFI_CHANNEL_7 = BIT(7), /**< Wi-Fi channel 7 */ + WIFI_CHANNEL_8 = BIT(8), /**< Wi-Fi channel 8 */ + WIFI_CHANNEL_9 = BIT(9), /**< Wi-Fi channel 9 */ + WIFI_CHANNEL_10 = BIT(10), /**< Wi-Fi channel 10 */ + WIFI_CHANNEL_11 = BIT(11), /**< Wi-Fi channel 11 */ + WIFI_CHANNEL_12 = BIT(12), /**< Wi-Fi channel 12 */ + WIFI_CHANNEL_13 = BIT(13), /**< Wi-Fi channel 13 */ + WIFI_CHANNEL_14 = BIT(14), /**< Wi-Fi channel 14 */ } wifi_2g_channel_bit_t; /** Argument structure for 5G channels */ typedef enum { - WIFI_CHANNEL_36 = BIT(1), /**< wifi channel 36 */ - WIFI_CHANNEL_40 = BIT(2), /**< wifi channel 40 */ - WIFI_CHANNEL_44 = BIT(3), /**< wifi channel 44 */ - WIFI_CHANNEL_48 = BIT(4), /**< wifi channel 48 */ - WIFI_CHANNEL_52 = BIT(5), /**< wifi channel 52 */ - WIFI_CHANNEL_56 = BIT(6), /**< wifi channel 56 */ - WIFI_CHANNEL_60 = BIT(7), /**< wifi channel 60 */ - WIFI_CHANNEL_64 = BIT(8), /**< wifi channel 64 */ - WIFI_CHANNEL_100 = BIT(9), /**< wifi channel 100 */ - WIFI_CHANNEL_104 = BIT(10), /**< wifi channel 104 */ - WIFI_CHANNEL_108 = BIT(11), /**< wifi channel 108 */ - WIFI_CHANNEL_112 = BIT(12), /**< wifi channel 112 */ - WIFI_CHANNEL_116 = BIT(13), /**< wifi channel 116 */ - WIFI_CHANNEL_120 = BIT(14), /**< wifi channel 120 */ - WIFI_CHANNEL_124 = BIT(15), /**< wifi channel 124 */ - WIFI_CHANNEL_128 = BIT(16), /**< wifi channel 128 */ - WIFI_CHANNEL_132 = BIT(17), /**< wifi channel 132 */ - WIFI_CHANNEL_136 = BIT(18), /**< wifi channel 136 */ - WIFI_CHANNEL_140 = BIT(19), /**< wifi channel 140 */ - WIFI_CHANNEL_144 = BIT(20), /**< wifi channel 144 */ - WIFI_CHANNEL_149 = BIT(21), /**< wifi channel 149 */ - WIFI_CHANNEL_153 = BIT(22), /**< wifi channel 153 */ - WIFI_CHANNEL_157 = BIT(23), /**< wifi channel 157 */ - WIFI_CHANNEL_161 = BIT(24), /**< wifi channel 161 */ - WIFI_CHANNEL_165 = BIT(25), /**< wifi channel 165 */ - WIFI_CHANNEL_169 = BIT(26), /**< wifi channel 169 */ - WIFI_CHANNEL_173 = BIT(27), /**< wifi channel 173 */ - WIFI_CHANNEL_177 = BIT(28), /**< wifi channel 177 */ + WIFI_CHANNEL_36 = BIT(1), /**< Wi-Fi channel 36 */ + WIFI_CHANNEL_40 = BIT(2), /**< Wi-Fi channel 40 */ + WIFI_CHANNEL_44 = BIT(3), /**< Wi-Fi channel 44 */ + WIFI_CHANNEL_48 = BIT(4), /**< Wi-Fi channel 48 */ + WIFI_CHANNEL_52 = BIT(5), /**< Wi-Fi channel 52 */ + WIFI_CHANNEL_56 = BIT(6), /**< Wi-Fi channel 56 */ + WIFI_CHANNEL_60 = BIT(7), /**< Wi-Fi channel 60 */ + WIFI_CHANNEL_64 = BIT(8), /**< Wi-Fi channel 64 */ + WIFI_CHANNEL_100 = BIT(9), /**< Wi-Fi channel 100 */ + WIFI_CHANNEL_104 = BIT(10), /**< Wi-Fi channel 104 */ + WIFI_CHANNEL_108 = BIT(11), /**< Wi-Fi channel 108 */ + WIFI_CHANNEL_112 = BIT(12), /**< Wi-Fi channel 112 */ + WIFI_CHANNEL_116 = BIT(13), /**< Wi-Fi channel 116 */ + WIFI_CHANNEL_120 = BIT(14), /**< Wi-Fi channel 120 */ + WIFI_CHANNEL_124 = BIT(15), /**< Wi-Fi channel 124 */ + WIFI_CHANNEL_128 = BIT(16), /**< Wi-Fi channel 128 */ + WIFI_CHANNEL_132 = BIT(17), /**< Wi-Fi channel 132 */ + WIFI_CHANNEL_136 = BIT(18), /**< Wi-Fi channel 136 */ + WIFI_CHANNEL_140 = BIT(19), /**< Wi-Fi channel 140 */ + WIFI_CHANNEL_144 = BIT(20), /**< Wi-Fi channel 144 */ + WIFI_CHANNEL_149 = BIT(21), /**< Wi-Fi channel 149 */ + WIFI_CHANNEL_153 = BIT(22), /**< Wi-Fi channel 153 */ + WIFI_CHANNEL_157 = BIT(23), /**< Wi-Fi channel 157 */ + WIFI_CHANNEL_161 = BIT(24), /**< Wi-Fi channel 161 */ + WIFI_CHANNEL_165 = BIT(25), /**< Wi-Fi channel 165 */ + WIFI_CHANNEL_169 = BIT(26), /**< Wi-Fi channel 169 */ + WIFI_CHANNEL_173 = BIT(27), /**< Wi-Fi channel 173 */ + WIFI_CHANNEL_177 = BIT(28), /**< Wi-Fi channel 177 */ } wifi_5g_channel_bit_t; -#define WIFI_PROTOCOL_11B 0x1 -#define WIFI_PROTOCOL_11G 0x2 -#define WIFI_PROTOCOL_11N 0x4 -#define WIFI_PROTOCOL_LR 0x8 -#define WIFI_PROTOCOL_11A 0x10 -#define WIFI_PROTOCOL_11AC 0x20 -#define WIFI_PROTOCOL_11AX 0x40 +#define WIFI_PROTOCOL_11B 0x1 /**< 802.11b protocol */ +#define WIFI_PROTOCOL_11G 0x2 /**< 802.11g protocol */ +#define WIFI_PROTOCOL_11N 0x4 /**< 802.11n protocol */ +#define WIFI_PROTOCOL_LR 0x8 /**< Low Rate protocol */ +#define WIFI_PROTOCOL_11A 0x10 /**< 802.11a protocol */ +#define WIFI_PROTOCOL_11AC 0x20 /**< 802.11ac protocol */ +#define WIFI_PROTOCOL_11AX 0x40 /**< 802.11ax protocol */ -/** @brief Description of a WiFi protocols */ +/** + * @brief Description of a Wi-Fi protocols + */ typedef struct { uint16_t ghz_2g; /**< Represents 2.4 GHz protocol, support 802.11b or 802.11g or 802.11n or 802.11ax or LR mode */ uint16_t ghz_5g; /**< Represents 5 GHz protocol, support 802.11a or 802.11n or 802.11ac or 802.11ax */ } wifi_protocols_t; -typedef enum { - WIFI_BW_HT20 = 1, /* Bandwidth is HT20 */ - WIFI_BW20 = WIFI_BW_HT20, /* Bandwidth is 20 MHz */ - WIFI_BW_HT40 = 2, /* Bandwidth is HT40 */ - WIFI_BW40 = WIFI_BW_HT40, /* Bandwidth is 40 MHz */ - WIFI_BW80 = 3, /* Bandwidth is 80 MHz */ - WIFI_BW160 = 4, /* Bandwidth is 160 MHz */ - WIFI_BW80_BW80 = 5, /* Bandwidth is 80+80 MHz */ -} wifi_bandwidth_t; - -/** @brief Description of a WiFi band bandwidths */ +/** + * @brief Description of a Wi-Fi band bandwidths + */ typedef struct { - wifi_bandwidth_t ghz_2g; /* Represents 2.4 GHz bandwidth */ - wifi_bandwidth_t ghz_5g; /* Represents 5 GHz bandwidth */ + wifi_bandwidth_t ghz_2g; /**< Represents 2.4 GHz bandwidth */ + wifi_bandwidth_t ghz_5g; /**< Represents 5 GHz bandwidth */ } wifi_bandwidths_t; -/** Configuration structure for Protected Management Frame */ +/** + * @brief Configuration structure for Protected Management Frame + */ typedef struct { bool capable; /**< Deprecated variable. Device will always connect in PMF mode if other device also advertises PMF capability. */ bool required; /**< Advertises that Protected Management Frame is required. Device will not associate to non-PMF capable devices. */ } wifi_pmf_config_t; -/** Configuration for SAE PWE derivation */ +/** + * @brief Configuration for SAE PWE derivation + */ typedef enum { WPA3_SAE_PWE_UNSPECIFIED, WPA3_SAE_PWE_HUNT_AND_PECK, @@ -423,14 +495,18 @@ typedef enum { WPA3_SAE_PWE_BOTH, } wifi_sae_pwe_method_t; -/** Configuration for SAE-PK */ +/** + * @brief Configuration for SAE-PK + */ typedef enum { WPA3_SAE_PK_MODE_AUTOMATIC = 0, WPA3_SAE_PK_MODE_ONLY = 1, WPA3_SAE_PK_MODE_DISABLED = 2, } wifi_sae_pk_mode_t; -/** @brief Soft-AP configuration settings for the device */ +/** + * @brief Soft-AP configuration settings for the device + */ typedef struct { uint8_t ssid[32]; /**< SSID of soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */ uint8_t password[64]; /**< Password of soft-AP. */ @@ -448,17 +524,20 @@ typedef struct { wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ } wifi_ap_config_t; -#define SAE_H2E_IDENTIFIER_LEN 32 -/** @brief STA configuration settings for the device */ +#define SAE_H2E_IDENTIFIER_LEN 32 /**< Length of the password identifier for H2E */ + +/** + * @brief STA configuration settings for the device + */ typedef struct { uint8_t ssid[32]; /**< SSID of target AP. */ uint8_t password[64]; /**< Password of target AP. */ - wifi_scan_method_t scan_method; /**< do all channel scan or fast scan */ - bool bssid_set; /**< whether set MAC address of target AP or not. Generally, station_config.bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.*/ + wifi_scan_method_t scan_method; /**< Do all channel scan or fast scan */ + bool bssid_set; /**< Whether set MAC address of target AP or not. Generally, station_config.bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.*/ uint8_t bssid[6]; /**< MAC address of target AP*/ - uint8_t channel; /**< channel of target AP. For 2.4G AP, set to 1~13 to scan starting from the specified channel before connecting to AP. For 5G AP, set to 36~177 (36, 40, 44 ... 177) to scan starting from the specified channel before connecting to AP. If the channel of AP is unknown, set it to 0.*/ + uint8_t channel; /**< Channel of target AP. For 2.4G AP, set to 1~13 to scan starting from the specified channel before connecting to AP. For 5G AP, set to 36~177 (36, 40, 44 ... 177) to scan starting from the specified channel before connecting to AP. If the channel of AP is unknown, set it to 0.*/ uint16_t listen_interval; /**< Listen interval for ESP32 station to receive beacon when WIFI_PS_MAX_MODEM is set. Units: AP beacon intervals. Defaults to 3 if set to 0. */ - wifi_sort_method_t sort_method; /**< sort the connect AP in the list by rssi or security mode */ + wifi_sort_method_t sort_method; /**< Sort the connect AP in the list by rssi or security mode */ wifi_scan_threshold_t threshold; /**< When scan_threshold is set, only APs which have an auth mode that is more secure than the selected auth mode and a signal stronger than the minimum RSSI will be used. */ wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame. Will be advertised in RSN Capabilities in RSN IE. */ uint32_t rm_enabled: 1; /**< Whether Radio Measurements are enabled for the connection */ @@ -486,7 +565,6 @@ typedef struct { /** * @brief NAN Discovery start configuration - * */ typedef struct { uint8_t op_channel; /**< NAN Discovery operating channel */ @@ -495,36 +573,42 @@ typedef struct { uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */ } wifi_nan_config_t; -/** @brief Configuration data for device's AP or STA or NAN. - * - * The usage of this union (for ap, sta or nan configuration) is determined by the accompanying - * interface argument passed to esp_wifi_set_config() or esp_wifi_get_config() - * - */ +/** + * @brief Configuration data for device's AP or STA or NAN. + * + * The usage of this union (for ap, sta or nan configuration) is determined by the accompanying + * interface argument passed to esp_wifi_set_config() or esp_wifi_get_config() + * + */ typedef union { - wifi_ap_config_t ap; /**< configuration of AP */ - wifi_sta_config_t sta; /**< configuration of STA */ - wifi_nan_config_t nan; /**< configuration of NAN */ + wifi_ap_config_t ap; /**< Configuration of AP */ + wifi_sta_config_t sta; /**< Configuration of STA */ + wifi_nan_config_t nan; /**< Configuration of NAN */ } wifi_config_t; -/** @brief Description of STA associated with AP */ +/** + * @brief Description of STA associated with AP + */ typedef struct { - uint8_t mac[6]; /**< mac address */ - int8_t rssi; /**< current average rssi of sta connected */ - uint32_t phy_11b: 1; /**< bit: 0 flag to identify if 11b mode is enabled or not */ - uint32_t phy_11g: 1; /**< bit: 1 flag to identify if 11g mode is enabled or not */ - uint32_t phy_11n: 1; /**< bit: 2 flag to identify if 11n mode is enabled or not */ - uint32_t phy_lr: 1; /**< bit: 3 flag to identify if low rate is enabled or not */ - uint32_t phy_11a: 1; /**< bit: 4 flag to identify if 11ax mode is enabled or not */ - uint32_t phy_11ac: 1; /**< bit: 5 flag to identify if 11ax mode is enabled or not */ - uint32_t phy_11ax: 1; /**< bit: 6 flag to identify if 11ax mode is enabled or not */ - uint32_t is_mesh_child: 1; /**< bit: 7 flag to identify mesh child */ - uint32_t reserved: 24; /**< bit: 8..31 reserved */ + uint8_t mac[6]; /**< MAC address */ + int8_t rssi; /**< Current average rssi of sta connected */ + uint32_t phy_11b: 1; /**< Bit: 0 flag to identify if 11b mode is enabled or not */ + uint32_t phy_11g: 1; /**< Bit: 1 flag to identify if 11g mode is enabled or not */ + uint32_t phy_11n: 1; /**< Bit: 2 flag to identify if 11n mode is enabled or not */ + uint32_t phy_lr: 1; /**< Bit: 3 flag to identify if low rate is enabled or not */ + uint32_t phy_11a: 1; /**< Bit: 4 flag to identify if 11ax mode is enabled or not */ + uint32_t phy_11ac: 1; /**< Bit: 5 flag to identify if 11ax mode is enabled or not */ + uint32_t phy_11ax: 1; /**< Bit: 6 flag to identify if 11ax mode is enabled or not */ + uint32_t is_mesh_child: 1; /**< Bit: 7 flag to identify mesh child */ + uint32_t reserved: 24; /**< Bit: 8..31 reserved */ } wifi_sta_info_t; +/** + * @brief Wi-Fi storage type + */ typedef enum { - WIFI_STORAGE_FLASH, /**< all configuration will store in both memory and flash */ - WIFI_STORAGE_RAM, /**< all configuration will only store in the memory */ + WIFI_STORAGE_FLASH, /**< All configuration will store in both memory and flash */ + WIFI_STORAGE_RAM, /**< All configuration will only store in the memory */ } wifi_storage_t; /** @@ -533,11 +617,11 @@ typedef enum { * Determines the frame type that the IE will be associated with. */ typedef enum { - WIFI_VND_IE_TYPE_BEACON, - WIFI_VND_IE_TYPE_PROBE_REQ, - WIFI_VND_IE_TYPE_PROBE_RESP, - WIFI_VND_IE_TYPE_ASSOC_REQ, - WIFI_VND_IE_TYPE_ASSOC_RESP, + WIFI_VND_IE_TYPE_BEACON, /**< Beacon frame */ + WIFI_VND_IE_TYPE_PROBE_REQ, /**< Probe request frame */ + WIFI_VND_IE_TYPE_PROBE_RESP, /**< Probe response frame */ + WIFI_VND_IE_TYPE_ASSOC_REQ, /**< Association request frame */ + WIFI_VND_IE_TYPE_ASSOC_RESP, /**< Association response frame */ } wifi_vendor_ie_type_t; /** @@ -546,14 +630,14 @@ typedef enum { * Each IE type can have up to two associated vendor ID elements. */ typedef enum { - WIFI_VND_IE_ID_0, - WIFI_VND_IE_ID_1, + WIFI_VND_IE_ID_0, /**< Vendor ID element 0 */ + WIFI_VND_IE_ID_1, /**< Vendor ID element 1 */ } wifi_vendor_ie_id_t; -#define WIFI_VENDOR_IE_ELEMENT_ID 0xDD +#define WIFI_VENDOR_IE_ELEMENT_ID 0xDD /**< Vendor Information Element ID */ /** - * @brief Operation Phymode + * @brief Operation PHY mode */ typedef enum { WIFI_PHY_MODE_LR, /**< PHY mode for Low Rate */ @@ -567,10 +651,10 @@ typedef enum { } wifi_phy_mode_t; /** - * @brief Vendor Information Element header - * - * The first bytes of the Information Element will match this header. Payload follows. - */ + * @brief Vendor Information Element header + * + * The first bytes of the Information Element will match this header. Payload follows. + */ typedef struct { uint8_t element_id; /**< Should be set to WIFI_VENDOR_IE_ELEMENT_ID (0xDD) */ uint8_t length; /**< Length of all bytes in the element data following this field. Minimum 4. */ @@ -592,34 +676,36 @@ typedef enum { WIFI_PKT_MISC, /**< Other type, such as MIMO etc. 'buf' argument is wifi_promiscuous_pkt_t but the payload is zero length. */ } wifi_promiscuous_pkt_type_t; -#define WIFI_PROMIS_FILTER_MASK_ALL (0xFFFFFFFF) /**< filter all packets */ -#define WIFI_PROMIS_FILTER_MASK_MGMT (1) /**< filter the packets with type of WIFI_PKT_MGMT */ -#define WIFI_PROMIS_FILTER_MASK_CTRL (1<<1) /**< filter the packets with type of WIFI_PKT_CTRL */ -#define WIFI_PROMIS_FILTER_MASK_DATA (1<<2) /**< filter the packets with type of WIFI_PKT_DATA */ -#define WIFI_PROMIS_FILTER_MASK_MISC (1<<3) /**< filter the packets with type of WIFI_PKT_MISC */ -#define WIFI_PROMIS_FILTER_MASK_DATA_MPDU (1<<4) /**< filter the MPDU which is a kind of WIFI_PKT_DATA */ -#define WIFI_PROMIS_FILTER_MASK_DATA_AMPDU (1<<5) /**< filter the AMPDU which is a kind of WIFI_PKT_DATA */ -#define WIFI_PROMIS_FILTER_MASK_FCSFAIL (1<<6) /**< filter the FCS failed packets, do not open it in general */ - -#define WIFI_PROMIS_CTRL_FILTER_MASK_ALL (0xFF800000) /**< filter all control packets */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_WRAPPER (1<<23) /**< filter the control packets with subtype of Control Wrapper */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_BAR (1<<24) /**< filter the control packets with subtype of Block Ack Request */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_BA (1<<25) /**< filter the control packets with subtype of Block Ack */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_PSPOLL (1<<26) /**< filter the control packets with subtype of PS-Poll */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_RTS (1<<27) /**< filter the control packets with subtype of RTS */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_CTS (1<<28) /**< filter the control packets with subtype of CTS */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_ACK (1<<29) /**< filter the control packets with subtype of ACK */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_CFEND (1<<30) /**< filter the control packets with subtype of CF-END */ -#define WIFI_PROMIS_CTRL_FILTER_MASK_CFENDACK (1<<31) /**< filter the control packets with subtype of CF-END+CF-ACK */ - -/** @brief Mask for filtering different packet types in promiscuous mode. */ +#define WIFI_PROMIS_FILTER_MASK_ALL (0xFFFFFFFF) /**< Filter all packets */ +#define WIFI_PROMIS_FILTER_MASK_MGMT (1) /**< Filter the packets with type of WIFI_PKT_MGMT */ +#define WIFI_PROMIS_FILTER_MASK_CTRL (1<<1) /**< Filter the packets with type of WIFI_PKT_CTRL */ +#define WIFI_PROMIS_FILTER_MASK_DATA (1<<2) /**< Filter the packets with type of WIFI_PKT_DATA */ +#define WIFI_PROMIS_FILTER_MASK_MISC (1<<3) /**< Filter the packets with type of WIFI_PKT_MISC */ +#define WIFI_PROMIS_FILTER_MASK_DATA_MPDU (1<<4) /**< Filter the MPDU which is a kind of WIFI_PKT_DATA */ +#define WIFI_PROMIS_FILTER_MASK_DATA_AMPDU (1<<5) /**< Filter the AMPDU which is a kind of WIFI_PKT_DATA */ +#define WIFI_PROMIS_FILTER_MASK_FCSFAIL (1<<6) /**< Filter the FCS failed packets, do not open it in general */ + +#define WIFI_PROMIS_CTRL_FILTER_MASK_ALL (0xFF800000) /**< Filter all control packets */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_WRAPPER (1<<23) /**< Filter the control packets with subtype of Control Wrapper */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_BAR (1<<24) /**< Filter the control packets with subtype of Block Ack Request */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_BA (1<<25) /**< Filter the control packets with subtype of Block Ack */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_PSPOLL (1<<26) /**< Filter the control packets with subtype of PS-Poll */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_RTS (1<<27) /**< Filter the control packets with subtype of RTS */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_CTS (1<<28) /**< Filter the control packets with subtype of CTS */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_ACK (1<<29) /**< Filter the control packets with subtype of ACK */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_CFEND (1<<30) /**< Filter the control packets with subtype of CF-END */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_CFENDACK (1<<31) /**< Filter the control packets with subtype of CF-END+CF-ACK */ + +/** + * @brief Mask for filtering different packet types in promiscuous mode + */ typedef struct { uint32_t filter_mask; /**< OR of one or more filter values WIFI_PROMIS_FILTER_* */ } wifi_promiscuous_filter_t; -#define WIFI_EVENT_MASK_ALL (0xFFFFFFFF) /**< mask all WiFi events */ -#define WIFI_EVENT_MASK_NONE (0) /**< mask none of the WiFi events */ -#define WIFI_EVENT_MASK_AP_PROBEREQRECVED (BIT(0)) /**< mask SYSTEM_EVENT_AP_PROBEREQRECVED event */ +#define WIFI_EVENT_MASK_ALL (0xFFFFFFFF) /**< Mask all Wi-Fi events */ +#define WIFI_EVENT_MASK_NONE (0) /**< Mask none of the Wi-Fi events */ +#define WIFI_EVENT_MASK_AP_PROBEREQRECVED (BIT(0)) /**< Mask SYSTEM_EVENT_AP_PROBEREQRECVED event */ /** * @brief CSI data type @@ -628,7 +714,7 @@ typedef struct { typedef struct wifi_csi_info_t wifi_csi_info_t; /** - * @brief WiFi GPIO configuration for antenna selection + * @brief Wi-Fi GPIO configuration for antenna selection * */ typedef struct { @@ -637,7 +723,7 @@ typedef struct { } wifi_ant_gpio_t; /** - * @brief WiFi GPIOs configuration for antenna selection + * @brief Wi-Fi GPIOs configuration for antenna selection * */ typedef struct { @@ -645,24 +731,24 @@ typedef struct { } wifi_ant_gpio_config_t; /** - * @brief WiFi antenna mode + * @brief Wi-Fi antenna mode * */ typedef enum { - WIFI_ANT_MODE_ANT0, /**< Enable WiFi antenna 0 only */ - WIFI_ANT_MODE_ANT1, /**< Enable WiFi antenna 1 only */ - WIFI_ANT_MODE_AUTO, /**< Enable WiFi antenna 0 and 1, automatically select an antenna */ - WIFI_ANT_MODE_MAX, /**< Invalid WiFi enabled antenna */ + WIFI_ANT_MODE_ANT0, /**< Enable Wi-Fi antenna 0 only */ + WIFI_ANT_MODE_ANT1, /**< Enable Wi-Fi antenna 1 only */ + WIFI_ANT_MODE_AUTO, /**< Enable Wi-Fi antenna 0 and 1, automatically select an antenna */ + WIFI_ANT_MODE_MAX, /**< Invalid Wi-Fi enabled antenna */ } wifi_ant_mode_t; /** - * @brief WiFi antenna configuration + * @brief Wi-Fi antenna configuration * */ typedef struct { - wifi_ant_mode_t rx_ant_mode; /**< WiFi antenna mode for receiving */ + wifi_ant_mode_t rx_ant_mode; /**< Wi-Fi antenna mode for receiving */ wifi_ant_t rx_ant_default; /**< Default antenna mode for receiving, it's ignored if rx_ant_mode is not WIFI_ANT_MODE_AUTO */ - wifi_ant_mode_t tx_ant_mode; /**< WiFi antenna mode for transmission, it can be set to WIFI_ANT_MODE_AUTO only if rx_ant_mode is set to WIFI_ANT_MODE_AUTO */ + wifi_ant_mode_t tx_ant_mode; /**< Wi-Fi antenna mode for transmission, it can be set to WIFI_ANT_MODE_AUTO only if rx_ant_mode is set to WIFI_ANT_MODE_AUTO */ uint8_t enabled_ant0: 4, /**< Index (in antenna GPIO configuration) of enabled WIFI_ANT_MODE_ANT0 */ enabled_ant1: 4; /**< Index (in antenna GPIO configuration) of enabled WIFI_ANT_MODE_ANT1 */ } wifi_ant_config_t; @@ -670,21 +756,19 @@ typedef struct { /** * @brief The Rx callback function of Action Tx operations * - * @param hdr pointer to the IEEE 802.11 Header structure - * @param payload pointer to the Payload following 802.11 Header - * @param len length of the Payload - * @param channel channel number the frame is received on + * @param hdr Pointer to the IEEE 802.11 Header structure + * @param payload Pointer to the Payload following 802.11 Header + * @param len Length of the Payload + * @param channel Channel number the frame is received on * */ typedef int (* wifi_action_rx_cb_t)(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel); /** - * @brief Action Frame Tx Request - * - * - */ + * @brief Action Frame Tx Request + */ typedef struct { - wifi_interface_t ifx; /**< WiFi interface to send request to */ + wifi_interface_t ifx; /**< Wi-Fi interface to send request to */ uint8_t dest_mac[6]; /**< Destination MAC address */ bool no_ack; /**< Indicates no ack required */ wifi_action_rx_cb_t rx_cb; /**< Rx Callback to receive any response */ @@ -705,16 +789,17 @@ typedef struct { WIFI_EVENT_FTM_REPORT to get FTM report */ } wifi_ftm_initiator_cfg_t; -#define ESP_WIFI_NAN_MAX_SVC_SUPPORTED 2 -#define ESP_WIFI_NAN_DATAPATH_MAX_PEERS 2 +#define ESP_WIFI_NAN_MAX_SVC_SUPPORTED 2 /**< Maximum number of NAN services supported */ +#define ESP_WIFI_NAN_DATAPATH_MAX_PEERS 2 /**< Maximum number of NAN datapath peers supported */ -#define ESP_WIFI_NDP_ROLE_INITIATOR 1 -#define ESP_WIFI_NDP_ROLE_RESPONDER 2 +#define ESP_WIFI_NDP_ROLE_INITIATOR 1 /**< Initiator role for NAN Data Path */ +#define ESP_WIFI_NDP_ROLE_RESPONDER 2 /**< Responder role for NAN Data Path */ + +#define ESP_WIFI_MAX_SVC_NAME_LEN 256 /**< Maximum length of NAN service name */ +#define ESP_WIFI_MAX_FILTER_LEN 256 /**< Maximum length of NAN service filter */ +#define ESP_WIFI_MAX_SVC_INFO_LEN 64 /**< Maximum length of NAN service info */ +#define ESP_WIFI_MAX_NEIGHBOR_REP_LEN 64 /**< Maximum length of NAN Neighbor Report */ -#define ESP_WIFI_MAX_SVC_NAME_LEN 256 -#define ESP_WIFI_MAX_FILTER_LEN 256 -#define ESP_WIFI_MAX_SVC_INFO_LEN 64 -#define ESP_WIFI_MAX_NEIGHBOR_REP_LEN 64 /** * @brief NAN Services types * @@ -794,7 +879,35 @@ typedef struct { } wifi_nan_datapath_end_req_t; /** - * @brief WiFi PHY rate encodings + * @brief Wi-Fi PHY rate encodings + * + * @note Rate Table: MCS Rate and Guard Interval Information + * | MCS RATE | HT20 | HT40 | HE20 | VHT20 | + * |-----------------------------|-------------------------|-------------------------|-------------------------|-------------------------| + * | WIFI_PHY_RATE_MCS0_LGI | 6.5 Mbps (800 ns) | 13.5 Mbps (800 ns) | 8.1 Mbps (1600 ns) | 6.5 Mbps (800 ns) | + * | WIFI_PHY_RATE_MCS1_LGI | 13 Mbps (800 ns) | 27 Mbps (800 ns) | 16.3 Mbps (1600 ns) | 13 Mbps (800 ns) | + * | WIFI_PHY_RATE_MCS2_LGI | 19.5 Mbps (800 ns) | 40.5 Mbps (800 ns) | 24.4 Mbps (1600 ns) | 19.5 Mbps (800 ns) | + * | WIFI_PHY_RATE_MCS3_LGI | 26 Mbps (800 ns) | 54 Mbps (800 ns) | 32.5 Mbps (1600 ns) | 26 Mbps (800 ns) | + * | WIFI_PHY_RATE_MCS4_LGI | 39 Mbps (800 ns) | 81 Mbps (800 ns) | 48.8 Mbps (1600 ns) | 39 Mbps (800 ns) | + * | WIFI_PHY_RATE_MCS5_LGI | 52 Mbps (800 ns) | 108 Mbps (800 ns) | 65 Mbps (1600 ns) | 52 Mbps (800 ns) | + * | WIFI_PHY_RATE_MCS6_LGI | 58.5 Mbps (800 ns) | 121.5 Mbps (800 ns) | 73.1 Mbps (1600 ns) | 58.5 Mbps (800 ns) | + * | WIFI_PHY_RATE_MCS7_LGI | 65 Mbps (800 ns) | 135 Mbps (800 ns) | 81.3 Mbps (1600 ns) | 65 Mbps (800 ns) | + * | WIFI_PHY_RATE_MCS8_LGI | | | 97.5 Mbps (1600 ns) | | + * | WIFI_PHY_RATE_MCS9_LGI | | | 108.3 Mbps (1600 ns) | | + * + * @note + * | MCS RATE | HT20 | HT40 | HE20 | VHT20 | + * |-----------------------------|-------------------------|-------------------------|-------------------------|-------------------------| + * | WIFI_PHY_RATE_MCS0_SGI | 7.2 Mbps (400 ns) | 15 Mbps (400 ns) | 8.6 Mbps (800 ns) | 7.2 Mbps (400 ns) | + * | WIFI_PHY_RATE_MCS1_SGI | 14.4 Mbps (400 ns) | 30 Mbps (400 ns) | 17.2 Mbps (800 ns) | 14.4 Mbps (400 ns) | + * | WIFI_PHY_RATE_MCS2_SGI | 21.7 Mbps (400 ns) | 45 Mbps (400 ns) | 25.8 Mbps (800 ns) | 21.7 Mbps (400 ns) | + * | WIFI_PHY_RATE_MCS3_SGI | 28.9 Mbps (400 ns) | 60 Mbps (400 ns) | 34.4 Mbps (800 ns) | 28.9 Mbps (400 ns) | + * | WIFI_PHY_RATE_MCS4_SGI | 43.3 Mbps (400 ns) | 90 Mbps (400 ns) | 51.6 Mbps (800 ns) | 43.3 Mbps (400 ns) | + * | WIFI_PHY_RATE_MCS5_SGI | 57.8 Mbps (400 ns) | 120 Mbps (400 ns) | 68.8 Mbps (800 ns) | 57.8 Mbps (400 ns) | + * | WIFI_PHY_RATE_MCS6_SGI | 65 Mbps (400 ns) | 135 Mbps (400 ns) | 77.4 Mbps (800 ns) | 65 Mbps (400 ns) | + * | WIFI_PHY_RATE_MCS7_SGI | 72.2 Mbps (400 ns) | 150 Mbps (400 ns) | 86 Mbps (800 ns) | 72.2 Mbps (400 ns) | + * | WIFI_PHY_RATE_MCS8_SGI | | | 103.2 Mbps (800 ns) | | + * | WIFI_PHY_RATE_MCS9_SGI | | | 114.7 Mbps (800 ns) | | * */ typedef enum { @@ -813,22 +926,7 @@ typedef enum { WIFI_PHY_RATE_36M = 0x0D, /**< 36 Mbps */ WIFI_PHY_RATE_18M = 0x0E, /**< 18 Mbps */ WIFI_PHY_RATE_9M = 0x0F, /**< 9 Mbps */ - /**< rate table and guard interval information for each MCS rate*/ - /* - ------------------------------------------------------------------------------------------------------------------------------------- - MCS RATE | HT20 | HT40 | HE20 | VHT20 | - WIFI_PHY_RATE_MCS0_LGI | 6.5 Mbps (800ns) | 13.5 Mbps (800ns) | 8.1 Mbps (1600ns) | 6.5 Mbps (800ns) | - WIFI_PHY_RATE_MCS1_LGI | 13 Mbps (800ns) | 27 Mbps (800ns) | 16.3 Mbps (1600ns) | 13 Mbps (800ns) | - WIFI_PHY_RATE_MCS2_LGI | 19.5 Mbps (800ns) | 40.5 Mbps (800ns) | 24.4 Mbps (1600ns) | 19.5 Mbps (800ns) | - WIFI_PHY_RATE_MCS3_LGI | 26 Mbps (800ns) | 54 Mbps (800ns) | 32.5 Mbps (1600ns) | 26 Mbps (800ns) | - WIFI_PHY_RATE_MCS4_LGI | 39 Mbps (800ns) | 81 Mbps (800ns) | 48.8 Mbps (1600ns) | 39 Mbps (800ns) | - WIFI_PHY_RATE_MCS5_LGI | 52 Mbps (800ns) | 108 Mbps (800ns) | 65 Mbps (1600ns) | 52 Mbps (800ns) | - WIFI_PHY_RATE_MCS6_LGI | 58.5 Mbps (800ns) | 121.5 Mbps (800ns) | 73.1 Mbps (1600ns) | 58.5 Mbps (800ns) | - WIFI_PHY_RATE_MCS7_LGI | 65 Mbps (800ns) | 135 Mbps (800ns) | 81.3 Mbps (1600ns) | 65 Mbps (800ns) | - WIFI_PHY_RATE_MCS8_LGI | ----- | ----- | 97.5 Mbps (1600ns) | ----- | - WIFI_PHY_RATE_MCS9_LGI | ----- | ----- | 108.3 Mbps (1600ns) | ----- | - ------------------------------------------------------------------------------------------------------------------------------------- - */ + WIFI_PHY_RATE_MCS0_LGI = 0x10, /**< MCS0 with long GI */ WIFI_PHY_RATE_MCS1_LGI = 0x11, /**< MCS1 with long GI */ WIFI_PHY_RATE_MCS2_LGI = 0x12, /**< MCS2 with long GI */ @@ -841,21 +939,7 @@ typedef enum { WIFI_PHY_RATE_MCS8_LGI, /**< MCS8 with long GI */ WIFI_PHY_RATE_MCS9_LGI, /**< MCS9 with long GI */ #endif - /* - ------------------------------------------------------------------------------------------------------------------------------------- - MCS RATE | HT20 | HT40 | HE20 | VHT20 | - WIFI_PHY_RATE_MCS0_SGI | 7.2 Mbps (400ns) | 15 Mbps (400ns) | 8.6 Mbps (800ns) | 7.2 Mbps (400ns) | - WIFI_PHY_RATE_MCS1_SGI | 14.4 Mbps (400ns) | 30 Mbps (400ns) | 17.2 Mbps (800ns) | 14.4 Mbps (400ns) | - WIFI_PHY_RATE_MCS2_SGI | 21.7 Mbps (400ns) | 45 Mbps (400ns) | 25.8 Mbps (800ns) | 21.7 Mbps (400ns) | - WIFI_PHY_RATE_MCS3_SGI | 28.9 Mbps (400ns) | 60 Mbps (400ns) | 34.4 Mbps (800ns) | 28.9 Mbps (400ns) | - WIFI_PHY_RATE_MCS4_SGI | 43.3 Mbps (400ns) | 90 Mbps (400ns) | 51.6 Mbps (800ns) | 43.3 Mbps (400ns) | - WIFI_PHY_RATE_MCS5_SGI | 57.8 Mbps (400ns) | 120 Mbps (400ns) | 68.8 Mbps (800ns) | 57.8 Mbps (400ns) | - WIFI_PHY_RATE_MCS6_SGI | 65 Mbps (400ns) | 135 Mbps (400ns) | 77.4 Mbps (800ns) | 65 Mbps (400ns) | - WIFI_PHY_RATE_MCS7_SGI | 72.2 Mbps (400ns) | 150 Mbps (400ns) | 86 Mbps (800ns) | 72.2 Mbps (400ns) | - WIFI_PHY_RATE_MCS8_SGI | ----- | ----- | 103.2 Mbps (800ns) | ----- | - WIFI_PHY_RATE_MCS9_SGI | ----- | ----- | 114.7 Mbps (800ns) | ----- | - ------------------------------------------------------------------------------------------------------------------------------------- - */ + WIFI_PHY_RATE_MCS0_SGI, /**< MCS0 with short GI */ WIFI_PHY_RATE_MCS1_SGI, /**< MCS1 with short GI */ WIFI_PHY_RATE_MCS2_SGI, /**< MCS2 with short GI */ @@ -868,31 +952,33 @@ typedef enum { WIFI_PHY_RATE_MCS8_SGI, /**< MCS8 with short GI */ WIFI_PHY_RATE_MCS9_SGI, /**< MCS9 with short GI */ #endif - WIFI_PHY_RATE_LORA_250K = 0x29, /**< 250 Kbps */ - WIFI_PHY_RATE_LORA_500K = 0x2A, /**< 500 Kbps */ + WIFI_PHY_RATE_LORA_250K = 0x29, /**< Espressif-specific Long Range mode rate, 250 Kbps */ + WIFI_PHY_RATE_LORA_500K = 0x2A, /**< Espressif-specific Long Range mode rate, 500 Kbps */ WIFI_PHY_RATE_MAX, } wifi_phy_rate_t; -/** WiFi event declarations */ +/** + * @brief Wi-Fi event declarations + */ typedef enum { - WIFI_EVENT_WIFI_READY = 0, /**< WiFi ready */ + WIFI_EVENT_WIFI_READY = 0, /**< Wi-Fi ready */ WIFI_EVENT_SCAN_DONE, /**< Finished scanning AP */ WIFI_EVENT_STA_START, /**< Station start */ WIFI_EVENT_STA_STOP, /**< Station stop */ WIFI_EVENT_STA_CONNECTED, /**< Station connected to AP */ WIFI_EVENT_STA_DISCONNECTED, /**< Station disconnected from AP */ - WIFI_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by device's station changed */ + WIFI_EVENT_STA_AUTHMODE_CHANGE, /**< The auth mode of AP connected by device's station changed */ - WIFI_EVENT_STA_WPS_ER_SUCCESS, /**< Station wps succeeds in enrollee mode */ - WIFI_EVENT_STA_WPS_ER_FAILED, /**< Station wps fails in enrollee mode */ - WIFI_EVENT_STA_WPS_ER_TIMEOUT, /**< Station wps timeout in enrollee mode */ - WIFI_EVENT_STA_WPS_ER_PIN, /**< Station wps pin code in enrollee mode */ - WIFI_EVENT_STA_WPS_ER_PBC_OVERLAP, /**< Station wps overlap in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_SUCCESS, /**< Station WPS succeeds in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_FAILED, /**< Station WPS fails in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_TIMEOUT, /**< Station WPS timeout in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_PIN, /**< Station WPS pin code in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_PBC_OVERLAP, /**< Station WPS overlap in enrollee mode */ WIFI_EVENT_AP_START, /**< Soft-AP start */ WIFI_EVENT_AP_STOP, /**< Soft-AP stop */ - WIFI_EVENT_AP_STACONNECTED, /**< a station connected to Soft-AP */ - WIFI_EVENT_AP_STADISCONNECTED, /**< a station disconnected from Soft-AP */ + WIFI_EVENT_AP_STACONNECTED, /**< A station connected to Soft-AP */ + WIFI_EVENT_AP_STADISCONNECTED, /**< A station disconnected from Soft-AP */ WIFI_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ WIFI_EVENT_FTM_REPORT, /**< Receive report of FTM procedure */ @@ -929,68 +1015,82 @@ typedef enum { WIFI_EVENT_NDP_INDICATION, /**< Received NDP Request from a NAN Peer */ WIFI_EVENT_NDP_CONFIRM, /**< NDP Confirm Indication */ WIFI_EVENT_NDP_TERMINATED, /**< NAN Datapath terminated indication */ - WIFI_EVENT_HOME_CHANNEL_CHANGE, /**< WiFi home channel change,doesn't occur when scanning */ + WIFI_EVENT_HOME_CHANNEL_CHANGE, /**< Wi-Fi home channel change,doesn't occur when scanning */ WIFI_EVENT_STA_NEIGHBOR_REP, /**< Received Neighbor Report response */ - WIFI_EVENT_MAX, /**< Invalid WiFi event ID */ + WIFI_EVENT_MAX, /**< Invalid Wi-Fi event ID */ } wifi_event_t; /** @cond **/ -/** @brief WiFi event base declaration */ +/** @brief Wi-Fi event base declaration */ ESP_EVENT_DECLARE_BASE(WIFI_EVENT); /** @endcond **/ -/** Argument structure for WIFI_EVENT_SCAN_DONE event */ +/** + * @brief Argument structure for WIFI_EVENT_SCAN_DONE event + */ typedef struct { - uint32_t status; /**< status of scanning APs: 0 — success, 1 - failure */ - uint8_t number; /**< number of scan results */ - uint8_t scan_id; /**< scan sequence number, used for block scan */ + uint32_t status; /**< Status of scanning APs: 0 — success, 1 - failure */ + uint8_t number; /**< Number of scan results */ + uint8_t scan_id; /**< Scan sequence number, used for block scan */ } wifi_event_sta_scan_done_t; -/** Argument structure for WIFI_EVENT_STA_CONNECTED event */ +/** + * @brief Argument structure for WIFI_EVENT_STA_CONNECTED event + */ typedef struct { uint8_t ssid[32]; /**< SSID of connected AP */ uint8_t ssid_len; /**< SSID length of connected AP */ uint8_t bssid[6]; /**< BSSID of connected AP*/ - uint8_t channel; /**< channel of connected AP*/ - wifi_auth_mode_t authmode;/**< authentication mode used by AP*/ - uint16_t aid; /**< authentication id assigned by the connected AP */ + uint8_t channel; /**< Channel of connected AP*/ + wifi_auth_mode_t authmode;/**< Authentication mode used by AP*/ + uint16_t aid; /**< Authentication id assigned by the connected AP */ } wifi_event_sta_connected_t; -/** Argument structure for WIFI_EVENT_STA_DISCONNECTED event */ +/** + * @brief Argument structure for WIFI_EVENT_STA_DISCONNECTED event + */ typedef struct { uint8_t ssid[32]; /**< SSID of disconnected AP */ uint8_t ssid_len; /**< SSID length of disconnected AP */ uint8_t bssid[6]; /**< BSSID of disconnected AP */ - uint8_t reason; /**< reason of disconnection */ - int8_t rssi; /**< rssi of disconnection */ + uint8_t reason; /**< Disconnection reason */ + int8_t rssi; /**< Disconnection RSSI */ } wifi_event_sta_disconnected_t; -/** Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event */ +/** + * @brief Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event + */ typedef struct { - wifi_auth_mode_t old_mode; /**< the old auth mode of AP */ - wifi_auth_mode_t new_mode; /**< the new auth mode of AP */ + wifi_auth_mode_t old_mode; /**< Old auth mode of AP */ + wifi_auth_mode_t new_mode; /**< New auth mode of AP */ } wifi_event_sta_authmode_change_t; -/** Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event */ +/** + * @brief Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event + */ typedef struct { uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */ } wifi_event_sta_wps_er_pin_t; -/** Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event */ +/** + * @brief Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event + */ typedef enum { WPS_FAIL_REASON_NORMAL = 0, /**< WPS normal fail reason */ WPS_FAIL_REASON_RECV_M2D, /**< WPS receive M2D frame */ WPS_FAIL_REASON_RECV_DEAUTH, /**< Recv deauth from AP while wps handshake */ - WPS_FAIL_REASON_MAX + WPS_FAIL_REASON_MAX /**< Max WPS fail reason */ } wifi_event_sta_wps_fail_reason_t; -#define MAX_SSID_LEN 32 -#define MAX_PASSPHRASE_LEN 64 -#define MAX_WPS_AP_CRED 3 +#define MAX_SSID_LEN 32 /**< Maximum length of SSID */ +#define MAX_PASSPHRASE_LEN 64 /**< Maximum length of passphrase */ +#define MAX_WPS_AP_CRED 3 /**< Maximum number of AP credentials received from WPS handshake */ -/** Argument structure for WIFI_EVENT_STA_WPS_ER_SUCCESS event */ +/** + * @brief Argument structure for WIFI_EVENT_STA_WPS_ER_SUCCESS event + */ typedef struct { uint8_t ap_cred_cnt; /**< Number of AP credentials received */ struct { @@ -999,38 +1099,48 @@ typedef struct { } ap_cred[MAX_WPS_AP_CRED]; /**< All AP credentials received from WPS handshake */ } wifi_event_sta_wps_er_success_t; -/** Argument structure for WIFI_EVENT_AP_STACONNECTED event */ +/** + * @brief Argument structure for WIFI_EVENT_AP_STACONNECTED event + */ typedef struct { uint8_t mac[6]; /**< MAC address of the station connected to Soft-AP */ - uint8_t aid; /**< the aid that soft-AP gives to the station connected to */ - bool is_mesh_child; /**< flag to identify mesh child */ + uint8_t aid; /**< AID assigned by the Soft-AP to the connected station */ + bool is_mesh_child; /**< Flag indicating whether the connected station is a mesh child */ } wifi_event_ap_staconnected_t; -/** Argument structure for WIFI_EVENT_AP_STADISCONNECTED event */ +/** + * @brief Argument structure for WIFI_EVENT_AP_STADISCONNECTED event + */ typedef struct { - uint8_t mac[6]; /**< MAC address of the station disconnects to soft-AP */ - uint8_t aid; /**< the aid that soft-AP gave to the station disconnects to */ - bool is_mesh_child; /**< flag to identify mesh child */ - uint16_t reason; /**< reason of disconnection */ + uint8_t mac[6]; /**< MAC address of the station disconnects from the soft-AP */ + uint8_t aid; /**< AID that the Soft-AP assigned to the disconnected station */ + bool is_mesh_child; /**< Flag indicating whether the disconnected station is a mesh child */ + uint16_t reason; /**< Disconnection reason */ } wifi_event_ap_stadisconnected_t; -/** Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event */ +/** + * @brief Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event + */ typedef struct { int rssi; /**< Received probe request signal strength */ uint8_t mac[6]; /**< MAC address of the station which send probe request */ } wifi_event_ap_probe_req_rx_t; -/** Argument structure for WIFI_EVENT_STA_BSS_RSSI_LOW event */ +/** + * @brief Argument structure for WIFI_EVENT_STA_BSS_RSSI_LOW event + */ typedef struct { int32_t rssi; /**< RSSI value of bss */ } wifi_event_bss_rssi_low_t; -/** Argument structure for WIFI_EVENT_HOME_CHANNEL_CHANGE event */ +/** + * @brief Argument structure for WIFI_EVENT_HOME_CHANNEL_CHANGE event + */ typedef struct { - uint8_t old_chan; /**< old home channel of the device */ - wifi_second_chan_t old_snd; /**< old second channel of the device */ - uint8_t new_chan; /**< new home channel of the device */ - wifi_second_chan_t new_snd; /**< new second channel of the device */ + uint8_t old_chan; /**< Old home channel of the device */ + wifi_second_chan_t old_snd; /**< Old second channel of the device */ + uint8_t new_chan; /**< New home channel of the device */ + wifi_second_chan_t new_snd; /**< New second channel of the device */ } wifi_event_home_channel_change_t; /** @@ -1047,7 +1157,13 @@ typedef enum { FTM_STATUS_USER_TERM, /**< User triggered termination */ } wifi_ftm_status_t; -/** Argument structure for */ +/** + * @brief Structure representing a report entry for Fine Timing Measurement (FTM) in Wi-Fi. + * + * This structure holds the information related to the FTM process between a Wi-Fi FTM Initiator + * and a Wi-Fi FTM Responder. FTM is used for precise distance measurement by timing the exchange + * of frames between devices. + */ typedef struct { uint8_t dlog_token; /**< Dialog Token of the FTM frame */ int8_t rssi; /**< RSSI of the FTM frame received */ @@ -1058,7 +1174,9 @@ typedef struct { uint64_t t4; /**< Time of arrival of ACK at FTM Responder in pSec */ } wifi_ftm_report_entry_t; -/** Argument structure for WIFI_EVENT_FTM_REPORT event */ +/** + * @brief Argument structure for WIFI_EVENT_FTM_REPORT event + */ typedef struct { uint8_t peer_mac[6]; /**< MAC address of the FTM Peer */ wifi_ftm_status_t status; /**< Status of the FTM operation */ @@ -1070,50 +1188,65 @@ typedef struct { uint8_t ftm_report_num_entries; /**< Number of entries in the FTM Report data */ } wifi_event_ftm_report_t; -#define WIFI_STATIS_BUFFER (1<<0) -#define WIFI_STATIS_RXTX (1<<1) -#define WIFI_STATIS_HW (1<<2) -#define WIFI_STATIS_DIAG (1<<3) -#define WIFI_STATIS_PS (1<<4) -#define WIFI_STATIS_ALL (-1) +#define WIFI_STATIS_BUFFER (1<<0) /**< Buffer status */ +#define WIFI_STATIS_RXTX (1<<1) /**< RX/TX status */ +#define WIFI_STATIS_HW (1<<2) /**< Hardware status */ +#define WIFI_STATIS_DIAG (1<<3) /**< Diagnostic status */ +#define WIFI_STATIS_PS (1<<4) /**< Power save status */ +#define WIFI_STATIS_ALL (-1) /**< All status */ -/** Argument structure for WIFI_EVENT_ACTION_TX_STATUS event */ +/** + * @brief Argument structure for WIFI_EVENT_ACTION_TX_STATUS event + */ typedef struct { - wifi_interface_t ifx; /**< WiFi interface to send request to */ + wifi_interface_t ifx; /**< Wi-Fi interface to send request to */ uint32_t context; /**< Context to identify the request */ uint8_t da[6]; /**< Destination MAC address */ uint8_t status; /**< Status of the operation */ } wifi_event_action_tx_status_t; -/** Argument structure for WIFI_EVENT_ROC_DONE event */ +/** + * @brief Argument structure for WIFI_EVENT_ROC_DONE event + */ typedef struct { uint32_t context; /**< Context to identify the request */ } wifi_event_roc_done_t; -/** Argument structure for WIFI_EVENT_AP_WPS_RG_PIN event */ +/** + * @brief Argument structure for WIFI_EVENT_AP_WPS_RG_PIN event + */ typedef struct { uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */ } wifi_event_ap_wps_rg_pin_t; +/** + * @brief WPS fail reason + */ typedef enum { WPS_AP_FAIL_REASON_NORMAL = 0, /**< WPS normal fail reason */ WPS_AP_FAIL_REASON_CONFIG, /**< WPS failed due to incorrect config */ WPS_AP_FAIL_REASON_AUTH, /**< WPS failed during auth */ - WPS_AP_FAIL_REASON_MAX, + WPS_AP_FAIL_REASON_MAX, /**< Max WPS fail reason */ } wps_fail_reason_t; -/** Argument structure for WIFI_EVENT_AP_WPS_RG_FAILED event */ +/** + * @brief Argument structure for WIFI_EVENT_AP_WPS_RG_FAILED event + */ typedef struct { wps_fail_reason_t reason; /**< WPS failure reason wps_fail_reason_t */ uint8_t peer_macaddr[6]; /**< Enrollee mac address */ } wifi_event_ap_wps_rg_fail_reason_t; -/** Argument structure for WIFI_EVENT_AP_WPS_RG_SUCCESS event */ +/** + * @brief Argument structure for WIFI_EVENT_AP_WPS_RG_SUCCESS event + */ typedef struct { uint8_t peer_macaddr[6]; /**< Enrollee mac address */ } wifi_event_ap_wps_rg_success_t; -/** Argument structure for WIFI_EVENT_NAN_SVC_MATCH event */ +/** + * @brief Argument structure for WIFI_EVENT_NAN_SVC_MATCH event + */ typedef struct { uint8_t subscribe_id; /**< Subscribe Service Identifier */ uint8_t publish_id; /**< Publish Service Identifier */ @@ -1121,14 +1254,18 @@ typedef struct { bool update_pub_id; /**< Indicates whether publisher's service ID needs to be updated */ } wifi_event_nan_svc_match_t; -/** Argument structure for WIFI_EVENT_NAN_REPLIED event */ +/** + * @brief Argument structure for WIFI_EVENT_NAN_REPLIED event + */ typedef struct { uint8_t publish_id; /**< Publish Service Identifier */ uint8_t subscribe_id; /**< Subscribe Service Identifier */ uint8_t sub_if_mac[6]; /**< NAN Interface MAC of the Subscriber */ } wifi_event_nan_replied_t; -/** Argument structure for WIFI_EVENT_NAN_RECEIVE event */ +/** + * @brief Argument structure for WIFI_EVENT_NAN_RECEIVE event + */ typedef struct { uint8_t inst_id; /**< Our Service Identifier */ uint8_t peer_inst_id; /**< Peer's Service Identifier */ @@ -1136,7 +1273,9 @@ typedef struct { uint8_t peer_svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Peer Service Info */ } wifi_event_nan_receive_t; -/** Argument structure for WIFI_EVENT_NDP_INDICATION event */ +/** + * @brief Argument structure for WIFI_EVENT_NDP_INDICATION event + */ typedef struct { uint8_t publish_id; /**< Publish Id for NAN Service */ uint8_t ndp_id; /**< NDP instance id */ @@ -1145,7 +1284,9 @@ typedef struct { uint8_t svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Service Specific Info */ } wifi_event_ndp_indication_t; -/** Argument structure for WIFI_EVENT_NDP_CONFIRM event */ +/** + * @brief Argument structure for WIFI_EVENT_NDP_CONFIRM event + */ typedef struct { uint8_t status; /**< NDP status code */ uint8_t ndp_id; /**< NDP instance id */ @@ -1155,14 +1296,18 @@ typedef struct { uint8_t svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Service Specific Info */ } wifi_event_ndp_confirm_t; -/** Argument structure for WIFI_EVENT_NDP_TERMINATED event */ +/** + * @brief Argument structure for WIFI_EVENT_NDP_TERMINATED event + */ typedef struct { uint8_t reason; /**< Termination reason code */ uint8_t ndp_id; /**< NDP instance id */ uint8_t init_ndi[6]; /**< Initiator's NAN Data Interface MAC */ } wifi_event_ndp_terminated_t; -/** Argument structure for WIFI_EVENT_STA_NEIGHBOR_REP event */ +/** + * @brief Argument structure for WIFI_EVENT_STA_NEIGHBOR_REP event + */ typedef struct { uint8_t report[ESP_WIFI_MAX_NEIGHBOR_REP_LEN]; /**< Neighbor Report received from the AP*/ uint16_t report_len; /**< Length of the report*/ diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 43c2ddb15a1f..9d69ec4c3a57 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 43c2ddb15a1f4d026f20f98249ca63885630c813 +Subproject commit 9d69ec4c3a5784a769f20ba2c5014ec04d58ba1b diff --git a/components/esp_wifi/src/wifi_netif.c b/components/esp_wifi/src/wifi_netif.c index 60559b6fe4fd..f42ff6bd52e3 100644 --- a/components/esp_wifi/src/wifi_netif.c +++ b/components/esp_wifi/src/wifi_netif.c @@ -69,7 +69,7 @@ static esp_err_t wifi_transmit(void *h, void *buffer, size_t len) static esp_err_t wifi_transmit_wrap(void *h, void *buffer, size_t len, void *netstack_buf) { wifi_netif_driver_t driver = h; -#if CONFIG_SPIRAM +#if CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !CONFIG_SPIRAM_IGNORE_NOTFOUND return esp_wifi_internal_tx_by_ref(driver->wifi_if, buffer, len, netstack_buf); #else return esp_wifi_internal_tx(driver->wifi_if, buffer, len); @@ -114,6 +114,9 @@ wifi_netif_driver_t esp_wifi_create_if_driver(wifi_interface_t wifi_if) esp_err_t esp_wifi_get_if_mac(wifi_netif_driver_t ifx, uint8_t mac[6]) { + if (ifx == NULL || mac == NULL) { + return ESP_ERR_INVALID_ARG; + } wifi_interface_t wifi_interface = ifx->wifi_if; return esp_wifi_get_mac(wifi_interface, mac); @@ -123,7 +126,7 @@ bool esp_wifi_is_if_ready_when_started(wifi_netif_driver_t ifx) { #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT // WiFi rxcb to be register wifi rxcb on start for AP only, station gets it registered on connect event - return (ifx->wifi_if == WIFI_IF_AP); + return (ifx && ifx->wifi_if == WIFI_IF_AP); #else return false; #endif @@ -131,6 +134,9 @@ bool esp_wifi_is_if_ready_when_started(wifi_netif_driver_t ifx) esp_err_t esp_wifi_register_if_rxcb(wifi_netif_driver_t ifx, esp_netif_receive_t fn, void * arg) { + if (ifx == NULL || fn == NULL || arg == NULL) { + return ESP_ERR_INVALID_ARG; + } if (ifx->base.netif != arg) { ESP_LOGE(TAG, "Invalid argument: supplied netif=%p does not equal to interface netif=%p", arg, ifx->base.netif); return ESP_ERR_INVALID_ARG; diff --git a/components/esp_wifi/test_md5/test_md5.sh b/components/esp_wifi/test_md5/test_md5.sh index 98c29f77322a..788a8744b7e8 100755 --- a/components/esp_wifi/test_md5/test_md5.sh +++ b/components/esp_wifi/test_md5/test_md5.sh @@ -22,7 +22,7 @@ case $IDF_TARGET in esp32s3) PREFIX=xtensa-esp32s3-elf- ;; - esp32c2|esp32c3|esp32c6) + esp32c2|esp32c3|esp32c6|esp32c5|esp32_host|esp32c61) PREFIX=riscv32-esp-elf- ;; *) diff --git a/components/espcoredump/Kconfig b/components/espcoredump/Kconfig index c19b0eabbaeb..90b806d96aa5 100644 --- a/components/espcoredump/Kconfig +++ b/components/espcoredump/Kconfig @@ -108,7 +108,7 @@ menu "Core dump" config ESP_COREDUMP_USE_STACK_SIZE bool - default y if ESP_COREDUMP_ENABLE_TO_FLASH && SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY + default y if ESP_COREDUMP_ENABLE_TO_FLASH && FREERTOS_TASK_CREATE_ALLOW_EXT_MEM default n help Force the use of a custom DRAM stack for coredump when Task stacks can be in PSRAM. diff --git a/components/espcoredump/src/core_dump_sha.c b/components/espcoredump/src/core_dump_sha.c index 5de67eaa56f3..fcd81ae978c5 100644 --- a/components/espcoredump/src/core_dump_sha.c +++ b/components/espcoredump/src/core_dump_sha.c @@ -31,7 +31,9 @@ static void core_dump_sha256_start(core_dump_sha_ctx_t *sha_ctx) static void core_dump_sha256_update(core_dump_sha_ctx_t *sha_ctx, const void *data, size_t data_len) { // set software mode of SHA calculation +#if CONFIG_MBEDTLS_HARDWARE_SHA sha_ctx->ctx.mode = ESP_MBEDTLS_SHA256_SOFTWARE; +#endif mbedtls_sha256_update(&sha_ctx->ctx, data, data_len); } diff --git a/components/espcoredump/src/port/riscv/core_dump_port.c b/components/espcoredump/src/port/riscv/core_dump_port.c index 60a2ac39546a..7d872ce62e55 100644 --- a/components/espcoredump/src/port/riscv/core_dump_port.c +++ b/components/espcoredump/src/port/riscv/core_dump_port.c @@ -37,7 +37,7 @@ const static char TAG[] __attribute__((unused)) = "esp_core_dump_port"; /** * Union representing the registers of the CPU as they will be written * in the core dump. - * Registers can be adressed with their names thanks to the structure, or as + * Registers can be addressed with their names thanks to the structure, or as * an array of 32 words. */ #define RISCV_GP_REGS_COUNT 32 @@ -222,7 +222,7 @@ uint32_t esp_core_dump_get_isr_stack_end(void) static inline bool esp_core_dump_task_stack_end_is_sane(uint32_t sp) { return esp_ptr_in_dram((void *)sp) -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM || esp_stack_ptr_in_extram(sp) #endif #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP @@ -315,7 +315,7 @@ bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz) } /** - * Get the task's registers dump when the panic occured. + * Get the task's registers dump when the panic occurred. * Returns the size, in bytes, of the data pointed by reg_dumps. * The data pointed by reg_dump are allocated statically, thus, they must be * used (or copied) before calling this function again. diff --git a/components/espcoredump/src/port/xtensa/core_dump_port.c b/components/espcoredump/src/port/xtensa/core_dump_port.c index cee4c1ebc1e0..8efae60d576e 100644 --- a/components/espcoredump/src/port/xtensa/core_dump_port.c +++ b/components/espcoredump/src/port/xtensa/core_dump_port.c @@ -299,7 +299,7 @@ uint32_t esp_core_dump_get_isr_stack_end(void) static inline bool esp_core_dump_task_stack_end_is_sane(uint32_t sp) { return esp_ptr_in_dram((void *)sp) -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM || esp_stack_ptr_in_extram(sp) #endif #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index aee227580275..de0efe407ccc 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -5,6 +5,7 @@ idf_build_get_property(target IDF_TARGET) idf_build_get_property(python PYTHON) idf_build_get_property(idf_path IDF_PATH) +idf_build_get_property(non_os_build NON_OS_BUILD) set(chip_model ${target}) @@ -12,7 +13,6 @@ set(ESPTOOLPY ${python} "$ENV{ESPTOOL_WRAPPER}" "${CMAKE_CURRENT_LIST_DIR}/espto set(ESPSECUREPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espsecure.py") set(ESPEFUSEPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espefuse.py") set(ESPMONITOR ${python} -m esp_idf_monitor) -set(ESPMKUF2 ${python} "${idf_path}/tools/mkuf2.py" write --chip ${chip_model}) set(ESPTOOLPY_CHIP "${chip_model}") if(NOT CONFIG_APP_BUILD_TYPE_RAM AND CONFIG_APP_BUILD_GENERATE_BINARIES) @@ -152,7 +152,7 @@ elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V set(secure_boot_version "2") endif() -if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS) +if(NOT non_os_build AND CONFIG_SECURE_SIGNED_APPS) if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) # for locally signed secure boot image, add a signing step to get from unsigned app to signed app get_filename_component(secure_boot_signing_key "${CONFIG_SECURE_BOOT_SIGNING_KEY}" @@ -197,30 +197,6 @@ add_custom_target(erase_flash VERBATIM ) -set(UF2_ARGS --json "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json") - -add_custom_target(uf2 - COMMAND ${CMAKE_COMMAND} - -D "IDF_PATH=${idf_path}" - -D "SERIAL_TOOL=${ESPMKUF2}" - -D "SERIAL_TOOL_ARGS=${UF2_ARGS};-o;${CMAKE_CURRENT_BINARY_DIR}/uf2.bin" - -P run_serial_tool.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - USES_TERMINAL - VERBATIM - ) - -add_custom_target(uf2-app - COMMAND ${CMAKE_COMMAND} - -D "IDF_PATH=${idf_path}" - -D "SERIAL_TOOL=${ESPMKUF2}" - -D "SERIAL_TOOL_ARGS=${UF2_ARGS};-o;${CMAKE_CURRENT_BINARY_DIR}/uf2-app.bin;--bin;app" - -P run_serial_tool.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - USES_TERMINAL - VERBATIM - ) - set(MERGE_BIN_ARGS merge_bin) if(DEFINED ENV{ESP_MERGE_BIN_OUTPUT}) list(APPEND MERGE_BIN_ARGS "-o" "$ENV{ESP_MERGE_BIN_OUTPUT}") @@ -551,7 +527,7 @@ function(esptool_py_custom_target target_name flasher_filename dependencies) endif() endfunction() -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) set(flash_deps "") if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT) diff --git a/components/fatfs/fatfsgen.py b/components/fatfs/fatfsgen.py index 4ab130200158..30d274f52604 100755 --- a/components/fatfs/fatfsgen.py +++ b/components/fatfs/fatfsgen.py @@ -1,10 +1,11 @@ #!/usr/bin/env python # SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import os from datetime import datetime -from typing import Any, List, Optional +from typing import Any +from typing import List +from typing import Optional from fatfs_utils.boot_sector import BootSector from fatfs_utils.exceptions import NoFreeClusterException @@ -12,10 +13,16 @@ from fatfs_utils.fatfs_state import FATFSState from fatfs_utils.fs_object import Directory from fatfs_utils.long_filename_utils import get_required_lfn_entries_count -from fatfs_utils.utils import (BYTES_PER_DIRECTORY_ENTRY, FATFS_INCEPTION, FATFS_MIN_ALLOC_UNIT, - RESERVED_CLUSTERS_COUNT, FATDefaults, get_args_for_partition_generator, - get_fat_sectors_count, get_non_data_sectors_cnt, read_filesystem, - required_clusters_count) +from fatfs_utils.utils import BYTES_PER_DIRECTORY_ENTRY +from fatfs_utils.utils import FATDefaults +from fatfs_utils.utils import FATFS_INCEPTION +from fatfs_utils.utils import FATFS_MIN_ALLOC_UNIT +from fatfs_utils.utils import get_args_for_partition_generator +from fatfs_utils.utils import get_fat_sectors_count +from fatfs_utils.utils import get_non_data_sectors_cnt +from fatfs_utils.utils import read_filesystem +from fatfs_utils.utils import required_clusters_count +from fatfs_utils.utils import RESERVED_CLUSTERS_COUNT def duplicate_fat_decorator(func): # type: ignore @@ -48,14 +55,15 @@ def __init__(self, volume_label: str = FATDefaults.VOLUME_LABEL, file_sys_type: str = FATDefaults.FILE_SYS_TYPE, root_entry_count: int = FATDefaults.ROOT_ENTRIES_COUNT, - explicit_fat_type: int = None, + explicit_fat_type: Optional[int] = None, media_type: int = FATDefaults.MEDIA_TYPE) -> None: # root directory bytes should be aligned by sector size - assert (root_entry_count * BYTES_PER_DIRECTORY_ENTRY) % sector_size == 0 + assert (int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) % sector_size == 0 # number of bytes in the root dir must be even multiple of BPB_BytsPerSec - assert ((root_entry_count * BYTES_PER_DIRECTORY_ENTRY) // sector_size) % 2 == 0 + if (int(root_entry_count) > 128): + assert ((int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) // sector_size) % 2 == 0 - root_dir_sectors_cnt: int = (root_entry_count * BYTES_PER_DIRECTORY_ENTRY) // sector_size + root_dir_sectors_cnt: int = (int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) // sector_size self.state: FATFSState = FATFSState(sector_size=sector_size, explicit_fat_type=explicit_fat_type, diff --git a/components/fatfs/host_test/main/test_fatfs.cpp b/components/fatfs/host_test/main/test_fatfs.cpp index a948822eef8d..88aa16e1c490 100644 --- a/components/fatfs/host_test/main/test_fatfs.cpp +++ b/components/fatfs/host_test/main/test_fatfs.cpp @@ -44,7 +44,10 @@ TEST_CASE("Create volume, open file, write and read back data", "[fatfs]") fr_result = f_fdisk(pdrv, part_list, work_area); REQUIRE(fr_result == FR_OK); - const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, 0}; + + // For host tests, include FM_SFD flag when formatting partitions smaller than 128KB. + // if n_root field of MKFS_PARM is set to 128 => 1 root directory sec and if set to 0(default 512) => 4 root directory sectors. + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, 0}; fr_result = f_mkfs("", &opt, work_area, sizeof(work_area)); // Use default volume // Mount the volume @@ -56,7 +59,7 @@ TEST_CASE("Create volume, open file, write and read back data", "[fatfs]") REQUIRE(fr_result == FR_OK); // Generate data - uint32_t data_size = 100000; + uint32_t data_size = 1000; char *data = (char*) malloc(data_size); char *read = (char*) malloc(data_size); @@ -130,7 +133,7 @@ static void prepare_fatfs(const char* partition_label, const esp_partition_t** p fr_result = f_fdisk(_pdrv, part_list, work_area); REQUIRE(fr_result == FR_OK); - const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, 0}; + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, 0}; fr_result = f_mkfs(drv, &opt, work_area, sizeof(work_area)); // Use default volume REQUIRE(fr_result == FR_OK); } @@ -222,7 +225,7 @@ TEST_CASE("Test mounting 2 volumes, writing data and formatting the 2nd one, rea const size_t workbuf_size = 4096; void *workbuf = ff_memalloc(workbuf_size); REQUIRE(workbuf != NULL); - const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 0, CONFIG_WL_SECTOR_SIZE}; + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, CONFIG_WL_SECTOR_SIZE}; fr_result = f_mkfs(drv1, &opt, workbuf, workbuf_size); free(workbuf); workbuf = NULL; diff --git a/components/fatfs/host_test/partition_table.csv b/components/fatfs/host_test/partition_table.csv index 30d2d9092588..777a3e67e9fc 100644 --- a/components/fatfs/host_test/partition_table.csv +++ b/components/fatfs/host_test/partition_table.csv @@ -3,5 +3,5 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, -storage, data, fat, , 1M, -storage2, data, fat, , 1M, +storage, data, fat, , 32k, +storage2, data, fat, , 32k, diff --git a/components/fatfs/src/ff.c b/components/fatfs/src/ff.c index 49b8d89620f9..3c3f1ace61d1 100644 --- a/components/fatfs/src/ff.c +++ b/components/fatfs/src/ff.c @@ -34,7 +34,6 @@ #error Wrong include file (ff.h). #endif - /* Limits and boundaries */ #define MAX_DIR 0x200000 /* Max size of FAT directory */ #define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ @@ -43,6 +42,10 @@ #define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ #define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ +#define MIN_FAT12_SEC_VOL 4 /* Min size of the FAT sector volume + 1 FAT, 1 root dir, 1 reserved, 1 data sector */ +#define MIN_FAT12_DATA_SEC 1 /* Min FAT data sectors */ + /* Character code support macros */ #define IsUpper(c) ((c) >= 'A' && (c) <= 'Z') @@ -3318,7 +3321,7 @@ static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS, && ld_word(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of reserved sectors (MNBZ) */ && (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of FATs (1 or 2) */ && ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir entries (MNBZ) */ - && (ld_word(fs->win + BPB_TotSec16) >= 128 || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume sectors (>=128) */ + && (ld_word(fs->win + BPB_TotSec16) >= MIN_FAT12_SEC_VOL || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume sectors (>=MIN_FAT12_SEC_VOL) */ && ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */ return 0; /* It can be presumed an FAT VBR */ } @@ -6034,7 +6037,11 @@ FRESULT f_mkfs ( } } } - if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128s */ + if (n_fat == 1) { + if (sz_vol < MIN_FAT12_SEC_VOL) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >= MIN_FAT12_SEC_VOLs */ + } else { + if (sz_vol < (MIN_FAT12_SEC_VOL + 1)) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >= (MIN_FAT12_SEC_VOL+1)s */ + } /* Now start to create an FAT volume at b_vol and sz_vol */ @@ -6265,7 +6272,7 @@ FRESULT f_mkfs ( } /* Determine number of clusters and final check of validity of the FAT sub-type */ - if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ + if (sz_vol < b_data + pau * MIN_FAT12_DATA_SEC - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ n_clst = ((DWORD)sz_vol - sz_rsv - sz_fat * n_fat - sz_dir) / pau; if (fsty == FS_FAT32) { if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32? */ diff --git a/components/fatfs/test_apps/.build-test-rules.yml b/components/fatfs/test_apps/.build-test-rules.yml index 5aae749df654..2fb48788cccd 100644 --- a/components/fatfs/test_apps/.build-test-rules.yml +++ b/components/fatfs/test_apps/.build-test-rules.yml @@ -23,10 +23,6 @@ components/fatfs/test_apps/flash_wl: - wear_leveling components/fatfs/test_apps/sdcard: - disable: - - if: IDF_TARGET in ["esp32p4", "esp32c5", "esp32c61"] - temporary: true - reason: target esp32p4, esp32c5 is not supported yet # TODO: [ESP32P4] IDF-7501 [ESP32C5] IDF-8704, [esp32c61] IDF-9305 disable_test: - if: IDF_TARGET not in ["esp32", "esp32c3"] temporary: true diff --git a/components/fatfs/test_apps/flash_wl/main/CMakeLists.txt b/components/fatfs/test_apps/flash_wl/main/CMakeLists.txt index 20b600fca29f..f6501bda48f0 100644 --- a/components/fatfs/test_apps/flash_wl/main/CMakeLists.txt +++ b/components/fatfs/test_apps/flash_wl/main/CMakeLists.txt @@ -1,4 +1,4 @@ -idf_component_register(SRCS "test_fatfs_flash_wl.c" +idf_component_register(SRCS "test_fatfs_flash_wl.c" "test_fatfs_small_partition.c" INCLUDE_DIRS "." PRIV_REQUIRES unity spi_flash fatfs vfs test_fatfs_common WHOLE_ARCHIVE) diff --git a/components/fatfs/test_apps/flash_wl/main/test_fatfs_small_partition.c b/components/fatfs/test_apps/flash_wl/main/test_fatfs_small_partition.c new file mode 100644 index 000000000000..fd65a4db811b --- /dev/null +++ b/components/fatfs/test_apps/flash_wl/main/test_fatfs_small_partition.c @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "unity.h" +#include "esp_vfs_fat.h" + +static wl_handle_t s_test_wl_handle; +static void test_setup(void) +{ + // With this configuration, for 32k partition size, + // 4 sectors will be used for WL and 4 sectors for FATFS + // (1 FAT, 1 root directory, 1 reserved and 1 data sector) + esp_vfs_fat_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5, + .use_one_fat = true, + }; + + TEST_ESP_OK(esp_vfs_fat_spiflash_format_cfg_rw_wl("/spiflash", "storage1", &mount_config)); + TEST_ESP_OK(esp_vfs_fat_spiflash_mount_rw_wl("/spiflash", "storage1", &mount_config, &s_test_wl_handle)); +} + +static void test_teardown(void) +{ + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount_rw_wl("/spiflash", s_test_wl_handle)); +} + +static void test_write_data_sec(int num_data_sec) +{ + int fd = open("/spiflash/test.txt", O_CREAT | O_WRONLY); + TEST_ASSERT_NOT_EQUAL(-1, fd); + + // Generate data + uint32_t data_size = 4096*num_data_sec; + + char *data = (char*) malloc(data_size); + char *read_data = (char*) malloc(data_size); + + for(uint32_t i = 0; i < (data_size); i += sizeof(i)) + { + *((uint32_t*)(data + i)) = i; + } + ssize_t wr = write(fd, data, data_size); + if (num_data_sec == 1) { + TEST_ASSERT_EQUAL(data_size, wr); + } else { + TEST_ASSERT_NOT_EQUAL(data_size, wr); + } + TEST_ASSERT_EQUAL(0, close(fd)); + + fd = open("/spiflash/test.txt", O_RDONLY); + int r = read(fd, read_data, data_size); + if (num_data_sec == 1) { + TEST_ASSERT_EQUAL(data_size, r); + } else { + TEST_ASSERT_NOT_EQUAL(data_size, r); + } + TEST_ASSERT_EQUAL(0, strcmp(data, read_data)); + TEST_ASSERT_EQUAL(0, close(fd)); +} + +TEST_CASE("(WL) can format small partition and read-write data", "[fatfs][wear_levelling][timeout=120]") +{ + test_setup(); + test_write_data_sec(1); //for 1 data sectors, write and read func should work + test_write_data_sec(2); //for 2 data sectors, write and read func should fail + test_teardown(); +} diff --git a/components/fatfs/test_apps/flash_wl/partitions.csv b/components/fatfs/test_apps/flash_wl/partitions.csv index d1dcbae61db8..d68a9de0115c 100644 --- a/components/fatfs/test_apps/flash_wl/partitions.csv +++ b/components/fatfs/test_apps/flash_wl/partitions.csv @@ -2,3 +2,4 @@ factory, app, factory, 0x10000, 768k, storage, data, fat, , 528k, storage2, data, fat, , 528k, +storage1, data, fat, , 32k, diff --git a/components/fatfs/test_apps/sdcard/README.md b/components/fatfs/test_apps/sdcard/README.md index 639f1d386dc1..381b38a983bc 100644 --- a/components/fatfs/test_apps/sdcard/README.md +++ b/components/fatfs/test_apps/sdcard/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | This test app runs a few FATFS test cases in a FAT-formatted SD card. diff --git a/components/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c b/components/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c index 7ff45e3caa49..a3247bd24566 100644 --- a/components/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c +++ b/components/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c @@ -35,13 +35,13 @@ #define SDSPI_MOSI_PIN 35 #define SDSPI_CLK_PIN 36 #define SDSPI_CS_PIN 34 -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61 #define SDSPI_MISO_PIN 6 #define SDSPI_MOSI_PIN 4 #define SDSPI_CLK_PIN 5 #define SDSPI_CS_PIN 1 #define SPI_DMA_CHAN SPI_DMA_CH_AUTO -#elif CONFIG_IDF_TARGET_ESP32H2 +#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32P4 #define SDSPI_MISO_PIN 0 #define SDSPI_MOSI_PIN 5 #define SDSPI_CLK_PIN 4 diff --git a/components/fatfs/vfs/vfs_fat_spiflash.c b/components/fatfs/vfs/vfs_fat_spiflash.c index dffd7ec1bb85..7144f165f6a5 100644 --- a/components/fatfs/vfs/vfs_fat_spiflash.c +++ b/components/fatfs/vfs/vfs_fat_spiflash.c @@ -15,6 +15,10 @@ #include "wear_levelling.h" #include "diskio_wl.h" +// If the available sectors based on partition size are less than 128, +// the root directory sector should be set to 1. +#define MIN_REQ_SEC 128 + static const char* TAG = "vfs_fat_spiflash"; static vfs_fat_spiflash_ctx_t *s_ctx[FF_VOLUMES] = {}; @@ -74,7 +78,7 @@ vfs_fat_spiflash_ctx_t* get_vfs_fat_spiflash_ctx(wl_handle_t wlhandle) return NULL; } -static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags) +static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags, size_t sec_num) { FRESULT fresult = f_mount(fs, drv, 1); if (fresult != FR_OK) { @@ -93,7 +97,13 @@ static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_moun size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, mount_config->allocation_unit_size); ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size); - const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (mount_config->use_one_fat ? 1 : 2), 0, 0, alloc_unit_size}; + UINT root_dir_entries; + if (CONFIG_WL_SECTOR_SIZE == 512) { + root_dir_entries = 16; + } else { + root_dir_entries = 128; + } + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (mount_config->use_one_fat ? 1 : 2), 0, (sec_num <= MIN_REQ_SEC ? root_dir_entries : 0), alloc_unit_size}; fresult = f_mkfs(drv, &opt, workbuf, workbuf_size); free(workbuf); workbuf = NULL; @@ -157,8 +167,9 @@ esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char* base_path, vfs_fat_x_ctx_flags_t flags = 0; + size_t sec_num = wl_size(*wl_handle) / wl_sector_size(*wl_handle); // Try to mount partition - ret = s_f_mount_rw(fs, drv, mount_config, &flags); + ret = s_f_mount_rw(fs, drv, mount_config, &flags, sec_num); if (ret != ESP_OK) { goto fail; } @@ -224,6 +235,7 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha wl_handle_t temp_handle = WL_INVALID_HANDLE; uint32_t id = FF_VOLUMES; + size_t sec_num = 0; bool found = s_get_context_id_by_label(partition_label, &id); if (!found) { @@ -239,6 +251,7 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha } ESP_RETURN_ON_ERROR(esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, mount_cfg, &temp_handle), TAG, "Failed to mount"); found = s_get_context_id_by_label(partition_label, &id); + sec_num = wl_size(temp_handle) / wl_sector_size(temp_handle); assert(found); if (s_ctx[id]->flags & FORMATTED_DURING_LAST_MOUNT) { ESP_LOGD(TAG, "partition was formatted during mounting, skipping another format"); @@ -250,6 +263,8 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha if (cfg) { s_ctx[id]->mount_config = *cfg; } + temp_handle = s_ctx[id]->wlhandle; + sec_num = wl_size(temp_handle) / wl_sector_size(temp_handle); } //unmount @@ -266,7 +281,13 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha } size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, s_ctx[id]->mount_config.allocation_unit_size); ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size); - const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, 0, alloc_unit_size}; + UINT root_dir_entries; + if (CONFIG_WL_SECTOR_SIZE == 512) { + root_dir_entries = 16; + } else { + root_dir_entries = 128; + } + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, (sec_num <= MIN_REQ_SEC ? root_dir_entries : 0), alloc_unit_size}; fresult = f_mkfs(drv, &opt, workbuf, workbuf_size); free(workbuf); workbuf = NULL; @@ -274,7 +295,7 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha mount_back: if (partition_was_mounted) { - esp_err_t err = s_f_mount_rw(s_ctx[id]->fs, drv, &s_ctx[id]->mount_config, NULL); + esp_err_t err = s_f_mount_rw(s_ctx[id]->fs, drv, &s_ctx[id]->mount_config, NULL, sec_num); if (err != ESP_OK) { ESP_LOGE(TAG, "failed to mount back, go to recycle"); goto recycle; diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 5776b7f37834..87798ab7885e 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -20,7 +20,9 @@ # - Files common across all kernel implementations and all ports # Bootloader builds only needs FreeRTOS for config, not for anything else -if(BOOTLOADER_BUILD) +idf_build_get_property(non_os_build NON_OS_BUILD) + +if(non_os_build) idf_component_register() return() endif() diff --git a/components/freertos/FreeRTOS-Kernel/idf_changes.md b/components/freertos/FreeRTOS-Kernel/idf_changes.md index a3ef8454601c..7bf620e6e413 100644 --- a/components/freertos/FreeRTOS-Kernel/idf_changes.md +++ b/components/freertos/FreeRTOS-Kernel/idf_changes.md @@ -123,6 +123,10 @@ The following functions were modified to accommodate SMP behavior: - In SMP, the function now disables interrupts to ensure that the calling task does not switch cores while checking its own copy of `uxSchedulerSuspended`. - `prvAddCurrentTaskToDelayedList()` - Added extra check to see if current blocking task has already been deleted by the other core. +- `xStreamBufferReceive()` + - Added a critical section for setting `xTaskWaitingToReceive` to `NULL` so that the write is SMP safe. +- `xStreamBufferSend()` + - Added a critical section for setting `xTaskWaitingToSend` to `NULL` so that the write is SMP safe. ### Critical Section Changes diff --git a/components/freertos/FreeRTOS-Kernel/portable/linux/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/linux/include/freertos/portmacro.h index 179265b778e4..583c568d8880 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/linux/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/linux/include/freertos/portmacro.h @@ -94,8 +94,8 @@ extern void vPortEnableInterrupts( void ); extern BaseType_t xPortSetInterruptMask( void ); extern void vPortClearInterruptMask( BaseType_t xMask ); -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); +void vPortEnterCritical( void ); +void vPortExitCritical( void ); #define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask() #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) #define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK() diff --git a/components/freertos/FreeRTOS-Kernel/stream_buffer.c b/components/freertos/FreeRTOS-Kernel/stream_buffer.c index 50c2fb13caeb..04d67a20056b 100644 --- a/components/freertos/FreeRTOS-Kernel/stream_buffer.c +++ b/components/freertos/FreeRTOS-Kernel/stream_buffer.c @@ -6,7 +6,7 @@ * * SPDX-License-Identifier: MIT * - * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -774,7 +774,18 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ); ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); - pxStreamBuffer->xTaskWaitingToSend = NULL; + /* In SMP mode, the task may have been woken and scheduled on + * another core. Hence, we must clear the xTaskWaitingToSend + * handle in a critical section. */ + #if ( configNUMBER_OF_CORES > 1 ) + taskENTER_CRITICAL( &( pxStreamBuffer->xStreamBufferLock ) ); + #endif /* configNUMBER_OF_CORES > 1 */ + { + pxStreamBuffer->xTaskWaitingToSend = NULL; + } + #if ( configNUMBER_OF_CORES > 1 ) + taskEXIT_CRITICAL( &( pxStreamBuffer->xStreamBufferLock ) ); + #endif /* configNUMBER_OF_CORES > 1 */ } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ); } else @@ -977,7 +988,19 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, /* Wait for data to be available. */ traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ); ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); - pxStreamBuffer->xTaskWaitingToReceive = NULL; + + /* In SMP mode, the task may have been woken and scheduled on + * another core. Hence, we must clear the xTaskWaitingToReceive + * handle in a critical section. */ + #if ( configNUMBER_OF_CORES > 1 ) + taskENTER_CRITICAL( &( pxStreamBuffer->xStreamBufferLock ) ); + #endif /* configNUMBER_OF_CORES > 1 */ + { + pxStreamBuffer->xTaskWaitingToReceive = NULL; + } + #if ( configNUMBER_OF_CORES > 1 ) + taskEXIT_CRITICAL( &( pxStreamBuffer->xStreamBufferLock ) ); + #endif /* configNUMBER_OF_CORES > 1 */ /* Recheck the data available after blocking. */ xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); @@ -1421,7 +1444,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, * result in confusion as to what is actually being observed. */ const BaseType_t xWriteValue = 0x55; configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer ); - (void)xWriteValue; + ( void ) xWriteValue; } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */ #endif diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 8d06ea30b0d0..368a20599fd5 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -4123,10 +4123,19 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, if( taskIS_YIELD_REQUIRED( pxUnblockedTCB, pdFALSE ) == pdTRUE ) { /* The unblocked task has a priority above that of the calling task, so - * a context switch is required. This function is called with the - * scheduler suspended so xYieldPending is set so the context switch - * occurs immediately that the scheduler is resumed (unsuspended). */ - xYieldPending[ xCurCoreID ] = pdTRUE; + * a context switch is required. */ + #if ( configNUM_CORES > 1 ) + + /* In SMP mode, this function is called from a critical section, so we + * yield the current core to schedule the unblocked task. */ + portYIELD_WITHIN_API(); + #else /* configNUM_CORES > 1 */ + + /* In single-core mode, this function is called with the scheduler suspended + * so xYieldPending is set so the context switch occurs immediately once the + * scheduler is resumed (unsuspended). */ + xYieldPending[ xCurCoreID ] = pdTRUE; + #endif /* configNUM_CORES > 1 */ } } } diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index ba0bb786f48b..dec261a93c85 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -573,6 +573,33 @@ menu "FreeRTOS" endmenu # Port + menu "Extra" + + config FREERTOS_TASK_CREATE_ALLOW_EXT_MEM + depends on SPIRAM + depends on FREERTOS_SUPPORT_STATIC_ALLOCATION + bool "Allow external memory as an argument to xTaskCreateStatic (READ HELP)" + default n if IDF_TARGET_ESP32 + default y + help + Accessing memory in PSRAM has certain restrictions, so task stacks allocated by xTaskCreate + are by default allocated from internal RAM. + + This option allows for passing memory allocated from SPIRAM to be passed to xTaskCreateStatic. + This should only be used for tasks where the stack is never accessed while the cache is disabled. + + Extra notes for ESP32: + + Because some bits of the ESP32 code environment cannot be recompiled with the cache workaround, + normally tasks cannot be safely run with their stack residing in external memory; for this reason + xTaskCreate (and related task creation functions) always allocate stack in internal memory and + xTaskCreateStatic will check if the memory passed to it is in internal memory. + If you have a task that needs a large amount of stack and does not call on ROM code in any way + (no direct calls, but also no Bluetooth/WiFi), you can try enable this to + cause xTaskCreateStatic to allow tasks stack in external memory. + + endmenu # Extra + # Hidden or compatibility options config FREERTOS_PORT diff --git a/components/freertos/heap_idf.c b/components/freertos/heap_idf.c index 57ff845f742f..60974047097e 100644 --- a/components/freertos/heap_idf.c +++ b/components/freertos/heap_idf.c @@ -99,7 +99,7 @@ bool xPortcheckValidStackMem(const void * ptr) #if CONFIG_IDF_TARGET_LINUX return true; #else /* CONFIG_IDF_TARGET_LINUX */ -#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#ifdef CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM return esp_ptr_byte_accessible(ptr); #else return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr); diff --git a/components/freertos/sdkconfig.rename b/components/freertos/sdkconfig.rename index 5720544d0e79..da4c466482ae 100644 --- a/components/freertos/sdkconfig.rename +++ b/components/freertos/sdkconfig.rename @@ -5,3 +5,4 @@ CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK CONFIG_FREERTOS_ENABLE_STATIC_TASK_C CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM diff --git a/components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c b/components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c index b14f1ea1ca24..00ff6980c9ea 100644 --- a/components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c +++ b/components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c @@ -132,6 +132,57 @@ TEST_CASE("FreeRTOS Event Group Sync", "[freertos]") vEventGroupDelete(eg); } +static TaskHandle_t run_order[2]; +static uint32_t run_order_index = 0; + +void task_test_eg_prio(void *arg) +{ + TaskHandle_t main_task_hdl = (TaskHandle_t)arg; + + /* Notify the main task that this task has been created */ + xTaskNotifyGive(main_task_hdl); + + /* Wait for the event group bits to be set */ + TEST_ASSERT_EQUAL(1, xEventGroupWaitBits(eg, 1, pdTRUE, pdTRUE, portMAX_DELAY)); + + /* Record the task handle in the run order array */ + run_order[run_order_index++] = xTaskGetCurrentTaskHandle(); + + /* Suspend the task */ + vTaskSuspend(NULL); +} + +TEST_CASE("FreeRTOS Event Groups do not cause priority inversion when higher priority task is unblocked", "[freertos]") +{ + run_order[0] = NULL; + run_order[1] = NULL; + run_order_index = 0; + + /* Initialize the event group */ + eg = xEventGroupCreate(); + + /* Create a task with higher priority than the task that will set the event group bits */ + TaskHandle_t higher_prio_hdl; + TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(task_test_eg_prio, "task_test_eg_prio", 2048, (void *)xTaskGetCurrentTaskHandle(), CONFIG_UNITY_FREERTOS_PRIORITY + 1, &higher_prio_hdl, CONFIG_UNITY_FREERTOS_CPU)); + + /* Wait for the task to be created */ + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + + /* Set the event group bits */ + xEventGroupSetBits(eg, 1); + + /* Record the task handle in the run order array */ + run_order[run_order_index++] = xTaskGetCurrentTaskHandle(); + + /* Verify that the higher priority task was unblocked and immediately scheduled and the lower priority task was preempted */ + TEST_ASSERT_EQUAL(higher_prio_hdl, run_order[0]); + TEST_ASSERT_EQUAL(xTaskGetCurrentTaskHandle(), run_order[1]); + + /* Clean up */ + vEventGroupDelete(eg); + vTaskDelete(higher_prio_hdl); +} + /*-----------------Test case for event group trace facilities-----------------*/ #ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY /* diff --git a/components/freertos/test_apps/freertos/misc/test_idf_additions.c b/components/freertos/test_apps/freertos/misc/test_idf_additions.c index 2f4d4a1fb769..5c5c3d69adda 100644 --- a/components/freertos/test_apps/freertos/misc/test_idf_additions.c +++ b/components/freertos/test_apps/freertos/misc/test_idf_additions.c @@ -89,7 +89,7 @@ TEST_CASE("IDF additions: Task creation with memory caps and self deletion", "[f xTaskNotifyGive(task_handle); } -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM TEST_CASE("IDF additions: Task creation with SPIRAM memory caps and self deletion stress test", "[freertos]") { @@ -115,7 +115,7 @@ TEST_CASE("IDF additions: Task creation with SPIRAM memory caps and self deletio } } -#endif /* CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ +#endif /* CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM */ #if ( CONFIG_FREERTOS_NUMBER_OF_CORES > 1 ) diff --git a/components/freertos/test_apps/freertos/pytest_freertos.py b/components/freertos/test_apps/freertos/pytest_freertos.py index ff27e9bc354f..e2cdb05bd2c8 100644 --- a/components/freertos/test_apps/freertos/pytest_freertos.py +++ b/components/freertos/test_apps/freertos/pytest_freertos.py @@ -7,7 +7,7 @@ CONFIGS = [ pytest.param('default', marks=[pytest.mark.supported_targets,]), pytest.param('freertos_options', marks=[pytest.mark.supported_targets]), - pytest.param('psram', marks=[pytest.mark.esp32]), + pytest.param('psram', marks=[pytest.mark.esp32, pytest.mark.esp32s3, pytest.mark.esp32p4, pytest.mark.esp32c5]), pytest.param('single_core', marks=[pytest.mark.esp32, pytest.mark.esp32p4]), # TODO: [ESP32C5] IDF-10335 # TODO: [ESP32C61] IDF-11146 diff --git a/components/freertos/test_apps/freertos/sdkconfig.ci.psram b/components/freertos/test_apps/freertos/sdkconfig.ci.psram index 1e3309831549..776e127a2aa4 100644 --- a/components/freertos/test_apps/freertos/sdkconfig.ci.psram +++ b/components/freertos/test_apps/freertos/sdkconfig.ci.psram @@ -5,7 +5,7 @@ CONFIG_IDF_TARGET="esp32" # Enable SPIRAM CONFIG_SPIRAM=y CONFIG_SPIRAM_OCCUPY_NO_HOST=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y # Disable encrypted flash reads/writes to save IRAM in this build configuration CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n diff --git a/components/hal/.build-test-rules.yml b/components/hal/.build-test-rules.yml index 2577a357be26..161bbc1df3b2 100644 --- a/components/hal/.build-test-rules.yml +++ b/components/hal/.build-test-rules.yml @@ -1,6 +1,8 @@ components/hal/test_apps/crypto: depends_components: - efuse + - mbedtls + - esp_security components/hal/test_apps/hal_i2c: disable: diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 35ca479f78fc..ba107dbf84f2 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -271,6 +271,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "usb_serial_jtag_hal.c") endif() + if(CONFIG_SOC_USB_UTMI_PHY_NUM GREATER 0) + list(APPEND srcs "usb_utmi_hal.c") + endif() + if(CONFIG_SOC_USB_OTG_SUPPORTED) list(APPEND srcs "usb_dwc_hal.c" @@ -330,8 +334,3 @@ if(CONFIG_HAL_DEFAULT_ASSERTION_LEVEL EQUAL 1) elseif(CONFIG_HAL_DEFAULT_ASSERTION_LEVEL EQUAL 2) target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __assert_func") endif() - -if((CONFIG_IDF_TARGET_ESP32H2 OR CONFIG_IDF_TARGET_ESP32S2 OR CONFIG_IDF_TARGET_ESP32S3) AND - CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU") # TODO IDF-10234 - target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-analyzer") -endif() diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index 237a461f6d73..bec830e3914b 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -14,13 +14,8 @@ #include "esp_random.h" #endif -// Need to remove in IDF-8621 -#if CONFIG_IDF_TARGET_ESP32C5 -#include "soc/keymng_reg.h" -#endif - #ifdef SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY -#include "hal/key_mgr_hal.h" +#include "hal/key_mgr_ll.h" #endif #define ECDSA_HAL_P192_COMPONENT_LEN 24 @@ -32,11 +27,6 @@ static void configure_ecdsa_periph(ecdsa_hal_config_t *conf) if (conf->use_km_key == 0) { efuse_hal_set_ecdsa_key(conf->efuse_key_blk); -// Need to remove in IDF-8621 -#if CONFIG_IDF_TARGET_ESP32C5 - REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, 1); -#endif - #if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY // Force Key Manager to use eFuse key for XTS-AES operation key_mgr_ll_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); diff --git a/components/hal/esp32/include/hal/gpio_ll.h b/components/hal/esp32/include/hal/gpio_ll.h index a6f62de1c5b8..3f5f64a4dba0 100644 --- a/components/hal/esp32/include/hal/gpio_ll.h +++ b/components/hal/esp32/include/hal/gpio_ll.h @@ -498,15 +498,15 @@ static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t { if (level) { if (gpio_num < 32) { - hw->out_w1ts = (1 << gpio_num); + hw->out_w1ts = 1 << gpio_num; } else { - HAL_FORCE_MODIFY_U32_REG_FIELD(hw->out1_w1ts, data, (1 << (gpio_num - 32))); + hw->out1_w1ts.val = 1 << (gpio_num - 32); } } else { if (gpio_num < 32) { - hw->out_w1tc = (1 << gpio_num); + hw->out_w1tc = 1 << gpio_num; } else { - HAL_FORCE_MODIFY_U32_REG_FIELD(hw->out1_w1tc, data, (1 << (gpio_num - 32))); + hw->out1_w1tc.val = 1 << (gpio_num - 32); } } } diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index 9ce5dbec7887..0ebc2fe9ea14 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -350,11 +350,6 @@ static inline void i2s_ll_set_raw_mclk_div(i2s_dev_t *hw, uint32_t mclk_div, uin */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that unlike to calculate from the regular decimal */ - i2s_ll_set_raw_mclk_div(hw, 7, 47, 3); i2s_ll_set_raw_mclk_div(hw, mclk_div->integer, mclk_div->denominator, mclk_div->numerator); } @@ -659,7 +654,7 @@ static inline void i2s_ll_tx_set_bits_mod(i2s_dev_t *hw, uint32_t val) } /** - * @brief Congfigure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit + * @brief Configure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -672,7 +667,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int } /** - * @brief Congfigure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit + * @brief Configure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width diff --git a/components/hal/esp32c2/include/hal/gpio_ll.h b/components/hal/esp32c2/include/hal/gpio_ll.h index 6906faa7db40..80301ddf7066 100644 --- a/components/hal/esp32c2/include/hal/gpio_ll.h +++ b/components/hal/esp32c2/include/hal/gpio_ll.h @@ -330,9 +330,9 @@ __attribute__((always_inline)) static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level) { if (level) { - hw->out_w1ts.out_w1ts = (1 << gpio_num); + hw->out_w1ts.val = 1 << gpio_num; } else { - hw->out_w1tc.out_w1tc = (1 << gpio_num); + hw->out_w1tc.val = 1 << gpio_num; } } diff --git a/components/hal/esp32c3/include/hal/clk_gate_ll.h b/components/hal/esp32c3/include/hal/clk_gate_ll.h index 5765a5e57e1c..daf544184b70 100644 --- a/components/hal/esp32c3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c3/include/hal/clk_gate_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,8 +35,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return SYSTEM_UART1_CLK_EN; case PERIPH_I2C0_MODULE: return SYSTEM_I2C_EXT0_CLK_EN; - case PERIPH_I2S1_MODULE: - return SYSTEM_I2S1_CLK_EN; + case PERIPH_I2S0_MODULE: + return SYSTEM_I2S0_CLK_EN; case PERIPH_TIMG0_MODULE: return SYSTEM_TIMERGROUP_CLK_EN; case PERIPH_TIMG1_MODULE: @@ -106,8 +106,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return SYSTEM_UART1_RST; case PERIPH_I2C0_MODULE: return SYSTEM_I2C_EXT0_RST; - case PERIPH_I2S1_MODULE: - return SYSTEM_I2S1_RST; + case PERIPH_I2S0_MODULE: + return SYSTEM_I2S0_RST; case PERIPH_TIMG0_MODULE: return SYSTEM_TIMERGROUP_RST; case PERIPH_TIMG1_MODULE: diff --git a/components/hal/esp32c3/include/hal/gpio_ll.h b/components/hal/esp32c3/include/hal/gpio_ll.h index 798d190970fb..cd96a95d93b0 100644 --- a/components/hal/esp32c3/include/hal/gpio_ll.h +++ b/components/hal/esp32c3/include/hal/gpio_ll.h @@ -339,9 +339,9 @@ __attribute__((always_inline)) static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level) { if (level) { - hw->out_w1ts.out_w1ts = (1 << gpio_num); + hw->out_w1ts.val = 1 << gpio_num; } else { - hw->out_w1tc.out_w1tc = (1 << gpio_num); + hw->out_w1tc.val = 1 << gpio_num; } } diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 1b7e9de0da51..3eecccacd24e 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -47,7 +47,7 @@ extern "C" { static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) { (void)i2s_id; - SYSTEM.perip_clk_en0.reg_i2s1_clk_en = enable; + SYSTEM.perip_clk_en0.reg_i2s0_clk_en = enable; } /// use a macro to wrap the function, force the caller to use it in a critical section @@ -63,8 +63,8 @@ static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) static inline void i2s_ll_reset_register(int i2s_id) { (void)i2s_id; - SYSTEM.perip_rst_en0.reg_i2s1_rst = 1; - SYSTEM.perip_rst_en0.reg_i2s1_rst = 0; + SYSTEM.perip_rst_en0.reg_i2s0_rst = 1; + SYSTEM.perip_rst_en0.reg_i2s0_rst = 0; } /// use a macro to wrap the function, force the caller to use it in a critical section @@ -285,15 +285,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - /* Set the integer part of mclk division */ + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, 2); + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; + hw->tx_clkm_div_conf.tx_clkm_div_y = 1; + hw->tx_clkm_div_conf.tx_clkm_div_z = 0; + hw->tx_clkm_div_conf.tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = yn1; + hw->tx_clkm_div_conf.tx_clkm_div_z = z; + hw->tx_clkm_div_conf.tx_clkm_div_y = y; + hw->tx_clkm_div_conf.tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, div_int); - /* Set the decimal part of the mclk division */ - typeof(hw->tx_clkm_div_conf) div = {}; - div.tx_clkm_div_x = x; - div.tx_clkm_div_y = y; - div.tx_clkm_div_z = z; - div.tx_clkm_div_yn1 = yn1; - hw->tx_clkm_div_conf.val = div.val; } /** @@ -308,15 +314,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - /* Set the integer part of mclk division */ + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, 2); + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; + hw->rx_clkm_div_conf.rx_clkm_div_y = 1; + hw->rx_clkm_div_conf.rx_clkm_div_z = 0; + hw->rx_clkm_div_conf.rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = yn1; + hw->rx_clkm_div_conf.rx_clkm_div_z = z; + hw->rx_clkm_div_conf.rx_clkm_div_y = y; + hw->rx_clkm_div_conf.rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, div_int); - /* Set the decimal part of the mclk division */ - typeof(hw->rx_clkm_div_conf) div = {}; - div.rx_clkm_div_x = x; - div.rx_clkm_div_y = y; - div.rx_clkm_div_z = z; - div.rx_clkm_div_yn1 = yn1; - hw->rx_clkm_div_conf.val = div.val; } /** @@ -327,12 +339,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -360,19 +366,13 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) /** * @brief Configure I2S RX module clock divider - * @note mclk on ESP32 is shared by both TX and RX channel + * @note mclk on ESP32C3 is shared by both TX and RX channel * * @param hw Peripheral I2S hardware instance address. * @param mclk_div The mclk division coefficients */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -467,7 +467,7 @@ static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) } /** - * @brief Congfigure TX chan bit and audio data bit + * @brief Configure TX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -480,7 +480,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int } /** - * @brief Congfigure RX chan bit and audio data bit + * @brief Configure RX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -880,11 +880,11 @@ static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f } /** - * @brief Get I2S TX PDM fp configuration paramater + * @brief Get I2S TX PDM fp configuration parameter * * @param hw Peripheral I2S hardware instance address. * @return - * - fp configuration paramater + * - fp configuration parameter */ static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { @@ -892,11 +892,11 @@ static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) } /** - * @brief Get I2S TX PDM fs configuration paramater + * @brief Get I2S TX PDM fs configuration parameter * * @param hw Peripheral I2S hardware instance address. * @return - * - fs configuration paramater + * - fs configuration parameter */ static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) { @@ -922,7 +922,7 @@ static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) * @brief Configura TX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. - * @param pcm_cfg PCM configuration paramater + * @param pcm_cfg PCM configuration parameter */ static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { @@ -934,7 +934,7 @@ static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_ * @brief Configure RX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. - * @param pcm_cfg PCM configuration paramater + * @param pcm_cfg PCM configuration parameter */ static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { @@ -1106,7 +1106,7 @@ static inline void i2s_ll_tx_pdm_dma_take_mode(i2s_dev_t *hw, bool is_mono, bool * @param is_mono The DMA data only has one slot (mono) or contains two slots (stereo) * @param is_copy Whether the un-selected slot copies the data from the selected one * If not, the un-selected slot will transmit the data from 'conf_single_data' - * @param mask The slot mask to selet the slot + * @param mask The slot mask to select the slot */ static inline void i2s_ll_tx_pdm_slot_mode(i2s_dev_t *hw, bool is_mono, bool is_copy, i2s_pdm_slot_mask_t mask) { diff --git a/components/hal/esp32c5/include/hal/brownout_ll.h b/components/hal/esp32c5/include/hal/brownout_ll.h index 09dcb3cb5e9c..e103d2639c9e 100644 --- a/components/hal/esp32c5/include/hal/brownout_ll.h +++ b/components/hal/esp32c5/include/hal/brownout_ll.h @@ -113,8 +113,6 @@ static inline void brownout_ll_ana_reset_enable(bool enable) LP_ANA_PERI.fib_enable.val &= ~BROWNOUT_DETECTOR_LL_FIB_ENABLE; // then we can enable or disable if we want the BOD mode1 to reset the system LP_ANA_PERI.bod_mode1_cntl.bod_mode1_reset_ena = enable; - // Disable the power glitch detect. - LP_ANA_PERI.fib_enable.val &= ~(BIT2|BIT3|BIT4|BIT5); } /** diff --git a/components/hal/esp32c5/include/hal/etm_ll.h b/components/hal/esp32c5/include/hal/etm_ll.h index fa76af9f99b4..ebed4861b561 100644 --- a/components/hal/esp32c5/include/hal/etm_ll.h +++ b/components/hal/esp32c5/include/hal/etm_ll.h @@ -11,7 +11,6 @@ #include #include "hal/assert.h" #include "hal/misc.h" -#include "hal/lp_aon_ll.h" #include "soc/soc_etm_struct.h" #include "soc/pcr_struct.h" diff --git a/components/hal/esp32c5/include/hal/gpio_ll.h b/components/hal/esp32c5/include/hal/gpio_ll.h index 0f17f99f0693..31894abc0282 100644 --- a/components/hal/esp32c5/include/hal/gpio_ll.h +++ b/components/hal/esp32c5/include/hal/gpio_ll.h @@ -360,9 +360,9 @@ __attribute__((always_inline)) static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level) { if (level) { - hw->out_w1ts.out_w1ts = (1 << gpio_num); + hw->out_w1ts.val = 1 << gpio_num; } else { - hw->out_w1tc.out_w1tc = (1 << gpio_num); + hw->out_w1tc.val = 1 << gpio_num; } } diff --git a/components/hal/esp32c5/include/hal/huk_ll.h b/components/hal/esp32c5/include/hal/huk_ll.h new file mode 100644 index 000000000000..37215ae35ea9 --- /dev/null +++ b/components/hal/esp32c5/include/hal/huk_ll.h @@ -0,0 +1,118 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use it in application code. + ******************************************************************************/ + +#pragma once + +#include "soc/soc_caps.h" + +#if SOC_KEY_MANAGER_SUPPORTED + +#include +#include +#include + +#include "hal/huk_types.h" +#include "soc/huk_reg.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* @brief Configure the HUK mode */ +static inline void huk_ll_configure_mode(const esp_huk_mode_t huk_mode) +{ + REG_SET_FIELD(HUK_CONF_REG, HUK_MODE, huk_mode); +} + +static inline void huk_ll_write_info(const uint8_t *buffer, const size_t size) +{ + memcpy((uint8_t *)HUK_INFO_MEM, buffer, size); +} + +static inline void huk_ll_read_info(uint8_t *buffer, const size_t size) +{ + memcpy(buffer, (uint8_t *)HUK_INFO_MEM, size); +} + +/* @brief Start the HUK at IDLE state */ +static inline void huk_ll_start(void) +{ + REG_SET_FIELD(HUK_START_REG, HUK_START, 1); +} + +/* @brief Continue HUK operation at LOAD/GAIN state */ +static inline void huk_ll_continue(void) +{ + REG_SET_FIELD(HUK_START_REG, HUK_CONTINUE, 1); +} + +/* @bried Enable or Disable the HUK interrupts */ +static inline void huk_ll_configure_interrupt(const esp_huk_interrupt_type_t intr, const bool en) +{ + switch(intr) { + case ESP_HUK_INT_PREP_DONE: + REG_SET_FIELD(HUK_INT_ENA_REG, HUK_PREP_DONE_INT_ENA, en); + case ESP_HUK_INT_PROC_DONE: + REG_SET_FIELD(HUK_INT_ENA_REG, HUK_PROC_DONE_INT_ENA, en); + case ESP_HUK_INT_POST_DONE: + REG_SET_FIELD(HUK_INT_ENA_REG, HUK_POST_DONE_INT_ENA, en); + default: + return; + } +} + +/* @bried Clear the HUK interrupts */ +static inline void huk_ll_clear_int(const esp_huk_interrupt_type_t intr) +{ + switch(intr) { + case ESP_HUK_INT_PREP_DONE: + REG_SET_FIELD(HUK_INT_CLR_REG, HUK_PREP_DONE_INT_CLR, 1); + case ESP_HUK_INT_PROC_DONE: + REG_SET_FIELD(HUK_INT_CLR_REG, HUK_PROC_DONE_INT_CLR, 1); + case ESP_HUK_INT_POST_DONE: + REG_SET_FIELD(HUK_INT_CLR_REG, HUK_POST_DONE_INT_CLR, 1); + default: + return; + } +} + +/** + * @brief Read state of Hardware Unique Key Generator + * + * @return esp_huk_state_t + */ +static inline esp_huk_state_t huk_ll_get_state(void) +{ + return (esp_huk_state_t) REG_GET_FIELD(HUK_STATE_REG, HUK_STATE); +} + +/** + * @brief Get the HUK generation status + */ +static inline esp_huk_gen_status_t huk_ll_get_gen_status(void) +{ + return (esp_huk_gen_status_t) REG_GET_FIELD(HUK_STATUS_REG, HUK_STATUS); +} + +/** + * @brief Read the HUK date information + */ +static inline uint32_t huk_ll_get_date_info(void) +{ + // Only the least significant 28 bits have desired information + return (uint32_t)(0x0FFFFFFF & REG_READ(HUK_DATE_REG)); +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/hal/esp32c5/include/hal/i2s_ll.h b/components/hal/esp32c5/include/hal/i2s_ll.h index 0b9fb644cd10..02288bd1cd64 100644 --- a/components/hal/esp32c5/include/hal/i2s_ll.h +++ b/components/hal/esp32c5/include/hal/i2s_ll.h @@ -316,13 +316,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, 2); + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = 1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = yn1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = z; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = y; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int); - typeof(PCR.i2s_tx_clkm_div_conf) div = {}; - div.i2s_tx_clkm_div_x = x; - div.i2s_tx_clkm_div_y = y; - div.i2s_tx_clkm_div_z = z; - div.i2s_tx_clkm_div_yn1 = yn1; - PCR.i2s_tx_clkm_div_conf.val = div.val; } /** @@ -338,13 +346,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, 2); + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = 1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = yn1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = z; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = y; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int); - typeof(PCR.i2s_rx_clkm_div_conf) div = {}; - div.i2s_rx_clkm_div_x = x; - div.i2s_rx_clkm_div_y = y; - div.i2s_rx_clkm_div_z = z; - div.i2s_rx_clkm_div_yn1 = yn1; - PCR.i2s_rx_clkm_div_conf.val = div.val; } /** @@ -355,12 +371,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -388,19 +398,13 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) /** * @brief Configure I2S RX module clock divider - * @note mclk on ESP32 is shared by both TX and RX channel + * @note mclk on ESP32C5 is shared by both TX and RX channel * * @param hw Peripheral I2S hardware instance address. * @param mclk_div The mclk division coefficients */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -941,7 +945,7 @@ static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) */ static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { - // Due to the lack of `PDM to PCM` module on ESP32-H2, PDM RX is not available + // Due to the lack of `PDM to PCM` module on ESP32-C5, PDM RX is not available HAL_ASSERT(!pdm_enable); hw->rx_conf.rx_pdm_en = 0; hw->rx_conf.rx_tdm_en = 1; diff --git a/components/hal/esp32c5/include/hal/key_mgr_ll.h b/components/hal/esp32c5/include/hal/key_mgr_ll.h new file mode 100644 index 000000000000..f46c7c2e4cd5 --- /dev/null +++ b/components/hal/esp32c5/include/hal/key_mgr_ll.h @@ -0,0 +1,359 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use it in application code. + ******************************************************************************/ + +#pragma once + +#include +#include +#include + +#include "hal/assert.h" +#include "hal/key_mgr_types.h" +#include "soc/keymng_reg.h" +#include "soc/pcr_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Read state of Key Manager + * + * @return esp_key_mgr_state_t + */ +static inline esp_key_mgr_state_t key_mgr_ll_get_state(void) +{ + return (esp_key_mgr_state_t) REG_GET_FIELD(KEYMNG_STATE_REG, KEYMNG_STATE); +} + +/** + * @brief Enable the bus clock for Key Manager peripheral + * Note: Please use key_mgr_ll_enable_bus_clock which requires the critical section + * and do not use _key_mgr_ll_enable_bus_clock + * @param true to enable, false to disable + */ +static inline void _key_mgr_ll_enable_bus_clock(bool enable) +{ + // Set the force power down bit to 0 to enable key manager + PCR.km_pd_ctrl.km_mem_force_pd = 0; + // Enable key manager clock + PCR.km_conf.km_clk_en = 1; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define key_mgr_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Enable the peripheral clock for Key Manager + * + * Note: Please use key_mgr_ll_enable_peripheral_clock which requires the critical section + * and do not use _key_mgr_ll_enable_peripheral_clock + * @param true to enable, false to disable + */ +static inline void _key_mgr_ll_enable_peripheral_clock(bool enable) +{ + ; /* Nothing to do here, Kept for compatibility with other SoC */ +} + +#define key_mgr_ll_enable_peripheral_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_enable_peripheral_clock(__VA_ARGS__) + +/** + * @brief Reset the Key Manager peripheral + * Note: Please use key_mgr_ll_reset_register which requires the critical section + * and do not use _key_mgr_ll_reset_register + */ +static inline void _key_mgr_ll_reset_register(void) +{ + PCR.km_conf.km_rst_en = 1; + PCR.km_conf.km_rst_en = 0; + // Wait for key manager to be ready + while (!PCR.km_conf.km_ready) { + }; + + while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) { + }; + +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define key_mgr_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_reset_register(__VA_ARGS__) + +/* @brief Start the key manager at IDLE state */ +static inline void key_mgr_ll_start(void) +{ + REG_SET_BIT(KEYMNG_START_REG, KEYMNG_START); +} + +/* @brief Continue key manager operation at LOAD/GAIN state */ +static inline void key_mgr_ll_continue(void) +{ + REG_SET_BIT(KEYMNG_START_REG, KEYMNG_CONTINUE); +} + +/* @brief Enable or Disable the KEY_MGR interrupts */ +static inline void key_mgr_ll_configure_interrupt(const esp_key_mgr_interrupt_type_t intr, bool en) +{ + switch(intr) { + case ESP_KEY_MGR_INT_PREP_DONE: + REG_SET_FIELD(KEYMNG_INT_ENA_REG, KEYMNG_PREP_DONE_INT_ENA, en); + break; + case ESP_KEY_MGR_INT_PROC_DONE: + REG_SET_FIELD(KEYMNG_INT_ENA_REG, KEYMNG_PROC_DONE_INT_ENA, en); + break; + case ESP_KEY_MGR_INT_POST_DONE: + REG_SET_FIELD(KEYMNG_INT_ENA_REG, KEYMNG_POST_DONE_INT_ENA, en); + break; + default: + return; + } +} + +/* @brief Clear the KEY_MGR interrupts */ +static inline void key_mgr_ll_clear_int(const esp_key_mgr_interrupt_type_t intr) +{ + switch(intr) { + case ESP_KEY_MGR_INT_PREP_DONE: + REG_SET_FIELD(KEYMNG_INT_CLR_REG, KEYMNG_PREP_DONE_INT_CLR, 1); + break; + case ESP_KEY_MGR_INT_PROC_DONE: + REG_SET_FIELD(KEYMNG_INT_CLR_REG, KEYMNG_PROC_DONE_INT_CLR, 1); + break; + case ESP_KEY_MGR_INT_POST_DONE: + REG_SET_FIELD(KEYMNG_INT_CLR_REG, KEYMNG_POST_DONE_INT_CLR, 1); + break; + default: + return; + } +} + +/** + * @brief Set the key manager to use the software provided init key + */ +static inline void key_mgr_ll_use_sw_init_key(void) +{ + REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_SW_INIT_KEY); +} + +/** + * @brief Configure the key manager key usage policy for a particular key type + * + */ +static inline void key_mgr_ll_set_key_usage(const esp_key_mgr_key_type_t key_type, const esp_key_mgr_key_usage_t key_usage) +{ + switch (key_type) { + case ESP_KEY_MGR_ECDSA_KEY: + if (key_usage == ESP_KEY_MGR_USE_EFUSE_KEY) { + REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_ECDSA); + } else { + REG_CLR_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_ECDSA); + } + break; + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + if (key_usage == ESP_KEY_MGR_USE_EFUSE_KEY) { + REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH); + } else { + REG_CLR_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH); + } + break; + + default: + HAL_ASSERT(false && "Unsupported mode"); + return; + } +} + +static inline esp_key_mgr_key_usage_t key_mgr_ll_get_key_usage(esp_key_mgr_key_type_t key_type) +{ + switch (key_type) { + case ESP_KEY_MGR_ECDSA_KEY: + return (esp_key_mgr_key_usage_t) (REG_GET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_ECDSA)); + break; + + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + return (esp_key_mgr_key_usage_t) (REG_GET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH)); + break; + + default: + HAL_ASSERT(false && "Unsupported mode"); + return ESP_KEY_MGR_USAGE_INVALID; + } + return ESP_KEY_MGR_USAGE_INVALID; +} + +/** + * @brief Set the lock for the use_sw_init_key_reg + * After this lock has been set, + * The Key manager configuration about the use of software init key cannot be changed + */ +static inline void key_mgr_ll_lock_use_sw_init_key_reg(void) +{ + REG_SET_BIT(KEYMNG_LOCK_REG, KEYMNG_USE_SW_INIT_KEY_LOCK); +} + +/** + * @brief Set the lock for the use_sw_init_key_reg + * After this lock has been set, + * The Key manager configuration about whether to use a particular key from efuse or key manager cannot be changed. + */ +static inline void key_mgr_ll_lock_use_efuse_key_reg(esp_key_mgr_key_type_t key_type) +{ + switch(key_type) { + case ESP_KEY_MGR_ECDSA_KEY: + REG_SET_BIT(KEYMNG_LOCK_REG, KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA); + break; + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + REG_SET_BIT(KEYMNG_LOCK_REG, KEYMNG_USE_EFUSE_KEY_LOCK_FLASH); + break; + default: + HAL_ASSERT(false && "Unsupported mode"); + return; + } +} + +/* @brief Configure the key purpose to be used by the Key Manager for key generator operation */ +static inline void key_mgr_ll_set_key_purpose(const esp_key_mgr_key_purpose_t key_purpose) +{ + REG_SET_FIELD(KEYMNG_CONF_REG, KEYMNG_KEY_PURPOSE, key_purpose); +} + +/** + * @brief Configure the mode which is used by the Key Manager for the generator key deployment process + */ +static inline void key_mgr_ll_set_key_generator_mode(const esp_key_mgr_key_generator_mode_t mode) +{ + REG_SET_FIELD(KEYMNG_CONF_REG, KEYMNG_KGEN_MODE, mode); +} + +/** + * @brief Read the key manager process result + * @return 1 for Success + * 0 for failure + */ +static inline bool key_mgr_ll_is_result_success(void) +{ + return REG_GET_FIELD(KEYMNG_RESULT_REG, KEYMNG_PROC_RESULT); +} + +/** + * @brief Check if the deployed key is valid or not + * @return 1 for Success + * 0 for failure + */ +static inline bool key_mgr_ll_is_key_deployment_valid(const esp_key_mgr_key_type_t key_type) +{ + switch (key_type) { + + case ESP_KEY_MGR_ECDSA_KEY: + return REG_GET_FIELD(KEYMNG_KEY_VLD_REG, KEYMNG_KEY_ECDSA_VLD); + break; + + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + return REG_GET_FIELD(KEYMNG_KEY_VLD_REG, KEYMNG_KEY_FLASH_VLD); + break; + + default: + HAL_ASSERT(false && "Unsupported mode"); + return 0; + } +} + +/* + * @brief Write the SW init key in the key manager registers + * + * @input + * sw_init_key_buf Init key buffer, this should be a readable buffer of data_len size which should contain the sw init key. The buffer must be 32 bit aligned + * data_len Length of the init key buffer + */ +static inline void key_mgr_ll_write_sw_init_key(const uint8_t *sw_init_key_buf, const size_t data_len) +{ + memcpy((uint8_t *)KEYMNG_SW_INIT_KEY_MEM, sw_init_key_buf, data_len); +} + +/* + * @brief Write the Assist info in the key manager registers + * + * @input + * assist_info_buf Assist info buffer, this should be a readable buffer of data_len size which should contain the assist info. The buffer must be 32 bit aligned + * data_len Length of the assist info buffer + */ +static inline void key_mgr_ll_write_assist_info(const uint8_t *assist_info_buf, const size_t data_len) +{ + memcpy((uint8_t *)KEYMNG_ASSIST_INFO_MEM, assist_info_buf, data_len); +} + +/* + * @brief Read the Assist info from the key manager registers + * + * @input + * assist_info_buf Assist info buffer, this should be a writable buffer of size KEY_MGR_ASSIST_INFO_LEN. The buffer must be 32 bit aligned + */ +static inline void key_mgr_ll_read_assist_info( uint8_t *assist_info_buf) +{ + memcpy(assist_info_buf, (uint8_t *)KEYMNG_ASSIST_INFO_MEM, KEY_MGR_ASSIST_INFO_LEN); +} + +/* + * @brief Write the Public info in the key manager registers + * @input + * public_info_buf Public info buffer, this should be a readable buffer of data_len size which should contain the public info. The buffer must be 32 bit aligned + * data_len Length of the public info buffer + */ +static inline void key_mgr_ll_write_public_info(const uint8_t *public_info_buf, const size_t data_len) +{ + memcpy((uint8_t *)KEYMNG_PUBLIC_INFO_MEM, public_info_buf, data_len); +} + +/* + * @brief Read the Public info in the key manager registers + * @input + * public_info_buf Public info buffer, this should be a writable buffer of read_len, The buffer must be 32 bit aligned + * read_len Length of the public info buffer + */ +static inline void key_mgr_ll_read_public_info(uint8_t *public_info_buf, const size_t read_len) +{ + memcpy(public_info_buf, (uint8_t *)KEYMNG_PUBLIC_INFO_MEM, read_len); +} + +static inline bool key_mgr_ll_is_huk_valid(void) +{ + return REG_GET_FIELD(KEYMNG_HUK_VLD_REG, KEYMNG_HUK_VALID); +} + +/* @brief Set the XTS-AES (Flash Encryption) key length for the Key Manager */ +static inline void key_mgr_ll_set_xts_aes_key_len(const esp_key_mgr_xts_aes_key_len_t key_len) +{ + REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_FLASH_KEY_LEN, key_len); +} + +/* @brief Get the XTS-AES (Flash Encryption) key length for the Key Manager */ +static inline esp_key_mgr_xts_aes_key_len_t key_mgr_ll_get_xts_aes_key_len(void) +{ + return (esp_key_mgr_xts_aes_key_len_t) REG_GET_FIELD(KEYMNG_STATIC_REG, KEYMNG_FLASH_KEY_LEN); +} + +/** + * @brief Read the Key Manager date information + */ +static inline uint32_t key_mgr_ll_get_date_info(void) +{ + // Only the least significant 28 bits have desired information + return (uint32_t)(0x0FFFFFFF & REG_READ(KEYMNG_DATE_REG)); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h b/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h index 9a01d99830eb..2d4416657fb6 100644 --- a/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h +++ b/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h @@ -63,6 +63,17 @@ static inline __attribute__((always_inline)) void mspi_ll_enable_bus_clock(bool PCR.mspi_conf.mspi_clk_en = enable; } +/** + * Reset the MSPI clock + */ +static inline __attribute__((always_inline)) void _mspi_timing_ll_reset_mspi(void) +{ + PCR.mspi_clk_conf.mspi_axi_rst_en = 1; + PCR.mspi_clk_conf.mspi_axi_rst_en = 0; + // Wait for mspi to be ready + while (!PCR.mspi_conf.mspi_ready) { + }; +} #ifdef __cplusplus } diff --git a/components/hal/esp32c5/include/hal/rmt_ll.h b/components/hal/esp32c5/include/hal/rmt_ll.h index 053e27d0e9b4..0e54a0b37867 100644 --- a/components/hal/esp32c5/include/hal/rmt_ll.h +++ b/components/hal/esp32c5/include/hal/rmt_ll.h @@ -38,8 +38,6 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 -#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0) - typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32c5/include/hal/uart_ll.h b/components/hal/esp32c5/include/hal/uart_ll.h index 7bc6606bc98a..58a377bdc7e9 100644 --- a/components/hal/esp32c5/include/hal/uart_ll.h +++ b/components/hal/esp32c5/include/hal/uart_ll.h @@ -61,10 +61,6 @@ extern "C" { #define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \ (((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix) -// UART sleep retention module -#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ - (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1) - // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), diff --git a/components/hal/esp32c5/modem_clock_hal.c b/components/hal/esp32c5/modem_clock_hal.c index 0c6370faa08b..554aaa94735e 100644 --- a/components/hal/esp32c5/modem_clock_hal.c +++ b/components/hal/esp32c5/modem_clock_hal.c @@ -101,12 +101,9 @@ uint32_t IRAM_ATTR modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_c return bitmap; } -void IRAM_ATTR modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) +void IRAM_ATTR modem_clock_hal_enable_modem_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) { if (enable) { - modem_syscon_ll_enable_fe_adc_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_dac_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_pwdet_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_80m_clock(hal->syscon_dev, enable); } @@ -116,6 +113,9 @@ void IRAM_ATTR modem_clock_hal_enable_modem_private_fe_clock(modem_clock_hal_con { if (enable) { modem_syscon_ll_enable_fe_160m_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_dac_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_pwdet_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_adc_clock(hal->syscon_dev, enable); } } diff --git a/components/hal/esp32c6/include/hal/clk_gate_ll.h b/components/hal/esp32c6/include/hal/clk_gate_ll.h index ecac26fd4575..eaff2e377603 100644 --- a/components/hal/esp32c6/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c6/include/hal/clk_gate_ll.h @@ -36,7 +36,7 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return PCR_UART1_CLK_EN; case PERIPH_I2C0_MODULE: return PCR_I2C_CLK_EN; - case PERIPH_I2S1_MODULE: + case PERIPH_I2S0_MODULE: return PCR_I2S_CLK_EN; case PERIPH_TIMG0_MODULE: return PCR_TG0_CLK_EN; @@ -104,7 +104,7 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return PCR_UART1_RST_EN; case PERIPH_I2C0_MODULE: return PCR_I2C_RST_EN; - case PERIPH_I2S1_MODULE: + case PERIPH_I2S0_MODULE: return PCR_I2S_RST_EN; case PERIPH_TIMG0_MODULE: return PCR_TG0_RST_EN; @@ -183,7 +183,7 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) return PCR_UART1_CONF_REG; case PERIPH_I2C0_MODULE: return PCR_I2C_CONF_REG; - case PERIPH_I2S1_MODULE: + case PERIPH_I2S0_MODULE: return PCR_I2S_CONF_REG; case PERIPH_TIMG0_MODULE: return PCR_TIMERGROUP0_CONF_REG; @@ -249,7 +249,7 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) return PCR_UART1_CONF_REG; case PERIPH_I2C0_MODULE: return PCR_I2C_CONF_REG; - case PERIPH_I2S1_MODULE: + case PERIPH_I2S0_MODULE: return PCR_I2S_CONF_REG; case PERIPH_TIMG0_MODULE: return PCR_TIMERGROUP0_CONF_REG; diff --git a/components/hal/esp32c6/include/hal/etm_ll.h b/components/hal/esp32c6/include/hal/etm_ll.h index 9d7079619d02..e77bfeec5f94 100644 --- a/components/hal/esp32c6/include/hal/etm_ll.h +++ b/components/hal/esp32c6/include/hal/etm_ll.h @@ -11,7 +11,6 @@ #include #include "hal/assert.h" #include "hal/misc.h" -#include "hal/lp_aon_ll.h" #include "soc/soc_etm_struct.h" #include "soc/pcr_struct.h" diff --git a/components/hal/esp32c6/include/hal/gpio_ll.h b/components/hal/esp32c6/include/hal/gpio_ll.h index 7871b705120b..2409c412e060 100644 --- a/components/hal/esp32c6/include/hal/gpio_ll.h +++ b/components/hal/esp32c6/include/hal/gpio_ll.h @@ -332,9 +332,9 @@ __attribute__((always_inline)) static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level) { if (level) { - hw->out_w1ts.out_w1ts = (1 << gpio_num); + hw->out_w1ts.val = 1 << gpio_num; } else { - hw->out_w1tc.out_w1tc = (1 << gpio_num); + hw->out_w1tc.val = 1 << gpio_num; } } diff --git a/components/hal/esp32c6/include/hal/i2c_ll.h b/components/hal/esp32c6/include/hal/i2c_ll.h index e8aaa77828dd..c50ad9c13610 100644 --- a/components/hal/esp32c6/include/hal/i2c_ll.h +++ b/components/hal/esp32c6/include/hal/i2c_ll.h @@ -85,9 +85,6 @@ typedef enum { #define LP_I2C_SDA_IOMUX_PAD 6 #define LP_I2C_SCL_IOMUX_PAD 7 -// I2C sleep retention module -#define I2C_SLEEP_RETENTION_MODULE(i2c_num) (SLEEP_RETENTION_MODULE_I2C0) - /** * @brief Calculate I2C bus frequency * Note that the clock accuracy is affected by the external pull-up resistor, diff --git a/components/hal/esp32c6/include/hal/i2s_ll.h b/components/hal/esp32c6/include/hal/i2s_ll.h index c95ab9321b1d..f38ec506c392 100644 --- a/components/hal/esp32c6/include/hal/i2s_ll.h +++ b/components/hal/esp32c6/include/hal/i2s_ll.h @@ -306,13 +306,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, 2); + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = 1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = yn1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = z; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = y; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int); - typeof(PCR.i2s_tx_clkm_div_conf) div = {}; - div.i2s_tx_clkm_div_x = x; - div.i2s_tx_clkm_div_y = y; - div.i2s_tx_clkm_div_z = z; - div.i2s_tx_clkm_div_yn1 = yn1; - PCR.i2s_tx_clkm_div_conf.val = div.val; } /** @@ -328,13 +336,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, 2); + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = 1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = yn1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = z; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = y; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int); - typeof(PCR.i2s_rx_clkm_div_conf) div = {}; - div.i2s_rx_clkm_div_x = x; - div.i2s_rx_clkm_div_y = y; - div.i2s_rx_clkm_div_z = z; - div.i2s_rx_clkm_div_yn1 = yn1; - PCR.i2s_rx_clkm_div_conf.val = div.val; } /** @@ -345,12 +361,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -378,19 +388,13 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) /** * @brief Configure I2S RX module clock divider - * @note mclk on ESP32 is shared by both TX and RX channel + * @note mclk on ESP32C6 is shared by both TX and RX channel * * @param hw Peripheral I2S hardware instance address. * @param mclk_div The mclk division coefficients */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; diff --git a/components/hal/esp32c6/include/hal/rmt_ll.h b/components/hal/esp32c6/include/hal/rmt_ll.h index 247d63e5fe80..9fdc75764e0b 100644 --- a/components/hal/esp32c6/include/hal/rmt_ll.h +++ b/components/hal/esp32c6/include/hal/rmt_ll.h @@ -38,8 +38,6 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 -#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0) - typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32c6/include/hal/rtc_io_ll.h b/components/hal/esp32c6/include/hal/rtc_io_ll.h index 0cd64df36d5d..6fcac4cd406f 100644 --- a/components/hal/esp32c6/include/hal/rtc_io_ll.h +++ b/components/hal/esp32c6/include/hal/rtc_io_ll.h @@ -309,6 +309,14 @@ static inline void rtcio_ll_wakeup_enable(int rtcio_num, rtcio_ll_wake_type_t ty { LP_IO.pin[rtcio_num].wakeup_enable = 1; LP_IO.pin[rtcio_num].int_type = type; + + /* Work around for HW issue, + need to also enable this clk, otherwise it will + not trigger a wake-up on the ULP. This is not needed + for triggering a wakeup on HP CPU, but always setting this + has no side-effects. + */ + LP_IO.date.clk_en = 1; } /** diff --git a/components/hal/esp32c6/include/hal/uart_ll.h b/components/hal/esp32c6/include/hal/uart_ll.h index 653fb37bbc14..48a0e29499bf 100644 --- a/components/hal/esp32c6/include/hal/uart_ll.h +++ b/components/hal/esp32c6/include/hal/uart_ll.h @@ -61,10 +61,6 @@ extern "C" { #define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \ (((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix) -// UART sleep retention module -#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ - (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1) - // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), diff --git a/components/hal/esp32c6/modem_clock_hal.c b/components/hal/esp32c6/modem_clock_hal.c index ed242febec45..7901b829dab0 100644 --- a/components/hal/esp32c6/modem_clock_hal.c +++ b/components/hal/esp32c6/modem_clock_hal.c @@ -101,7 +101,7 @@ uint32_t IRAM_ATTR modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_c return bitmap; } -void IRAM_ATTR modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) +void IRAM_ATTR modem_clock_hal_enable_modem_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) { if (enable) { modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); diff --git a/components/hal/esp32c61/include/hal/brownout_ll.h b/components/hal/esp32c61/include/hal/brownout_ll.h index 7a4bb9e1841b..ac3b966d56a7 100644 --- a/components/hal/esp32c61/include/hal/brownout_ll.h +++ b/components/hal/esp32c61/include/hal/brownout_ll.h @@ -113,8 +113,6 @@ static inline void brownout_ll_ana_reset_enable(bool enable) LP_ANA.fib_enable.val &= ~BROWNOUT_DETECTOR_LL_FIB_ENABLE; // then we can enable or disable if we want the BOD mode1 to reset the system LP_ANA.bod_mode1_cntl.bod_mode1_reset_ena = enable; - // Disable the power glitch detect. - LP_ANA.fib_enable.val &= ~(BIT2|BIT3|BIT4|BIT5); } /** diff --git a/components/hal/esp32c61/include/hal/etm_ll.h b/components/hal/esp32c61/include/hal/etm_ll.h new file mode 100644 index 000000000000..6708cd7f17ee --- /dev/null +++ b/components/hal/esp32c61/include/hal/etm_ll.h @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include "hal/assert.h" +#include "hal/misc.h" +#include "soc/soc_etm_struct.h" +#include "soc/pcr_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Enable the clock for ETM register + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void etm_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.etm_conf.etm_clk_en = enable; +} + +/** + * @brief Reset the ETM register + * + * @param group_id Group ID + */ +static inline void etm_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.etm_conf.etm_rst_en = 1; + PCR.etm_conf.etm_rst_en = 0; +} + +/** + * @brief Enable ETM channel + * + * @param hw ETM register base address + * @param chan Channel ID + */ +static inline void etm_ll_enable_channel(soc_etm_dev_t *hw, uint32_t chan) +{ + if (chan < 32) { + hw->ch_ena_ad0_set.val = 1 << chan; + } else { + hw->ch_ena_ad1_set.val = 1 << (chan - 32); + } +} + +/** + * @brief Disable ETM channel + * + * @param hw ETM register base address + * @param chan Channel ID + */ +static inline void etm_ll_disable_channel(soc_etm_dev_t *hw, uint32_t chan) +{ + if (chan < 32) { + hw->ch_ena_ad0_clr.val = 1 << chan; + } else { + hw->ch_ena_ad1_clr.val = 1 << (chan - 32); + } +} + +/** + * @brief Check whether the ETM channel is enabled or not + * + * @param hw ETM register base address + * @param chan Channel ID + * @return true if the channel is enabled, false otherwise + */ +static inline bool etm_ll_is_channel_enabled(soc_etm_dev_t *hw, uint32_t chan) +{ + if (chan < 32) { + return hw->ch_ena_ad0.val & (1 << chan); + } else { + return hw->ch_ena_ad1.val & (1 << (chan - 32)); + } +} + +/** + * @brief Set the input event for the ETM channel + * + * @param hw ETM register base address + * @param chan Channel ID + * @param event Event ID + */ +static inline void etm_ll_channel_set_event(soc_etm_dev_t *hw, uint32_t chan, uint32_t event) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[chan].eid, chn_evt_id, event); +} + +/** + * @brief Set the output task for the ETM channel + * + * @param hw ETM register base address + * @param chan Channel ID + * @param task Task ID + */ +static inline void etm_ll_channel_set_task(soc_etm_dev_t *hw, uint32_t chan, uint32_t task) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[chan].tid, chn_task_id, task); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c61/include/hal/gpio_etm_ll.h b/components/hal/esp32c61/include/hal/gpio_etm_ll.h new file mode 100644 index 000000000000..52a06e7fc3e6 --- /dev/null +++ b/components/hal/esp32c61/include/hal/gpio_etm_ll.h @@ -0,0 +1,136 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include "hal/assert.h" +#include "hal/misc.h" +#include "soc/gpio_ext_struct.h" +#include "soc/soc_etm_source.h" + +#define GPIO_LL_ETM_EVENT_ID_POS_EDGE(ch) (GPIO_EVT_CH0_RISE_EDGE + (ch)) +#define GPIO_LL_ETM_EVENT_ID_NEG_EDGE(ch) (GPIO_EVT_CH0_FALL_EDGE + (ch)) +#define GPIO_LL_ETM_EVENT_ID_ANY_EDGE(ch) (GPIO_EVT_CH0_ANY_EDGE + (ch)) + +#define GPIO_LL_ETM_TASK_ID_SET(ch) (GPIO_TASK_CH0_SET + (ch)) +#define GPIO_LL_ETM_TASK_ID_CLR(ch) (GPIO_TASK_CH0_CLEAR + (ch)) +#define GPIO_LL_ETM_TASK_ID_TOG(ch) (GPIO_TASK_CH0_TOGGLE + (ch)) + +#define GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP 8 +#define GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP 8 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set which GPIO to be bound to the event channel + * + * @note Different channels can be bound to one GPIO + * + * @param dev Register base address + * @param chan GPIO ETM Event channel number + * @param gpio_num GPIO number + */ +static inline void gpio_ll_etm_event_channel_set_gpio(gpio_etm_dev_t *dev, uint32_t chan, uint32_t gpio_num) +{ + dev->etm_event_chn_cfg[chan].etm_chn_event_sel = gpio_num; +} + +/** + * @brief Whether to enable the event channel + * + * @param dev Register base address + * @param chan GPIO ETM Event channel number + * @param enable True to enable, false to disable + */ +static inline void gpio_ll_etm_enable_event_channel(gpio_etm_dev_t *dev, uint32_t chan, bool enable) +{ + dev->etm_event_chn_cfg[chan].etm_chn_event_en = enable; +} + +/** + * @brief Get which GPIO is bound to the event channel + * + * @param dev Register base address + * @param chan GPIO ETM Event channel number + * @return GPIO number + */ +static inline uint32_t gpio_ll_etm_event_channel_get_gpio(gpio_etm_dev_t *dev, uint32_t chan) +{ + return dev->etm_event_chn_cfg[chan].etm_chn_event_sel; +} + +/** + * @brief Set which GPIO to be bound to the task channel + * + * @note One channel can be bound to multiple different GPIOs + * + * @param dev Register base address + * @param chan GPIO ETM Task channel number + * @param gpio_num GPIO number + */ +static inline void gpio_ll_etm_gpio_set_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num, uint32_t chan) +{ + int g_p = gpio_num / 5; + int g_idx = gpio_num % 5; + uint32_t reg_val = dev->etm_task_pn_cfg[g_p].val; + reg_val &= ~(0x07 << (g_idx * 6)); + reg_val |= ((chan & 0x07) << (g_idx * 6)); + dev->etm_task_pn_cfg[g_p].val = reg_val; +} + +/** + * @brief Whether to enable the GPIO to be managed by the task channel + * + * @param dev Register base address + * @param gpio_num GPIO number + * @param enable True to enable, false to disable + */ +static inline void gpio_ll_etm_enable_task_gpio(gpio_etm_dev_t *dev, uint32_t gpio_num, bool enable) +{ + int g_p = gpio_num / 5; + int g_idx = gpio_num % 5; + uint32_t reg_val = dev->etm_task_pn_cfg[g_p].val; + reg_val &= ~(0x01 << (g_idx * 6 + 5)); + reg_val |= ((enable & 0x01) << (g_idx * 6 + 5)); + dev->etm_task_pn_cfg[g_p].val = reg_val; +} + +/** + * @brief Check whether a GPIO has been enabled and managed by a task channel + * + * @param dev Register base address + * @param gpio_num GPIO number + * @return True if enabled, false otherwise + */ +static inline bool gpio_ll_etm_is_task_gpio_enabled(gpio_etm_dev_t *dev, uint32_t gpio_num) +{ + int g_p = gpio_num / 5; + int g_idx = gpio_num % 5; + return dev->etm_task_pn_cfg[g_p].val & (0x01 << (g_idx * 6 + 5)); +} + +/** + * @brief Get the channel number that the GPIO is bound to + * + * @param dev Register base address + * @param gpio_num GPIO number + * @return GPIO ETM Task channel number + */ +static inline uint32_t gpio_ll_etm_gpio_get_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num) +{ + int g_p = gpio_num / 5; + int g_idx = gpio_num % 5; + return (dev->etm_task_pn_cfg[g_p].val >> (g_idx * 6)) & 0x07; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c61/include/hal/gpio_ll.h b/components/hal/esp32c61/include/hal/gpio_ll.h index 1f1670aff833..a04c6ce2e5ce 100644 --- a/components/hal/esp32c61/include/hal/gpio_ll.h +++ b/components/hal/esp32c61/include/hal/gpio_ll.h @@ -356,9 +356,9 @@ __attribute__((always_inline)) static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level) { if (level) { - hw->out_w1ts.out_w1ts = (1 << gpio_num); + hw->out_w1ts.val = 1 << gpio_num; } else { - hw->out_w1tc.out_w1tc = (1 << gpio_num); + hw->out_w1tc.val = 1 << gpio_num; } } diff --git a/components/hal/esp32c61/include/hal/i2s_ll.h b/components/hal/esp32c61/include/hal/i2s_ll.h new file mode 100644 index 000000000000..5bbad89e5a1d --- /dev/null +++ b/components/hal/esp32c61/include/hal/i2s_ll.h @@ -0,0 +1,1241 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for I2S register operations +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in hal/include/hal/readme.md + ******************************************************************************/ + +#pragma once +#include +#include "hal/misc.h" +#include "hal/assert.h" +#include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" +#include "soc/pcr_struct.h" +#include "soc/soc_etm_source.h" +#include "hal/i2s_types.h" +#include "hal/hal_utils.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2S_LL_GET_HW(num) (((num) == 0)? (&I2S0) : NULL) + +#define I2S_LL_TDM_CH_MASK (0xffff) +#define I2S_LL_PDM_BCK_FACTOR (64) + +#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width +#define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width + +#define I2S_LL_PLL_F120M_CLK_FREQ (120 * 1000000) // PLL_F160M_CLK: 120MHz +#define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz +#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT + +#define I2S_LL_ETM_EVENT_TABLE(i2s_port, chan_dir, event) \ + (uint32_t[SOC_I2S_NUM][2][I2S_ETM_EVENT_MAX]){{ \ + [I2S_DIR_RX - 1] = { \ + [I2S_ETM_EVENT_DONE] = I2S0_EVT_RX_DONE, \ + [I2S_ETM_EVENT_REACH_THRESH] = I2S0_EVT_X_WORDS_RECEIVED, \ + }, \ + [I2S_DIR_TX - 1] = { \ + [I2S_ETM_EVENT_DONE] = I2S0_EVT_TX_DONE, \ + [I2S_ETM_EVENT_REACH_THRESH] = I2S0_EVT_X_WORDS_SENT, \ + }}}[i2s_port][(chan_dir) - 1][event] + + +#define I2S_LL_ETM_TASK_TABLE(i2s_port, chan_dir, task) \ + (uint32_t[SOC_I2S_NUM][2][I2S_ETM_TASK_MAX]){{ \ + [I2S_DIR_RX - 1] = { \ + [I2S_ETM_TASK_START] = I2S0_TASK_START_RX, \ + [I2S_ETM_TASK_STOP] = I2S0_TASK_STOP_RX, \ + }, \ + [I2S_DIR_TX - 1] = { \ + [I2S_ETM_TASK_START] = I2S0_TASK_START_TX, \ + [I2S_ETM_TASK_STOP] = I2S0_TASK_STOP_TX, \ + }}}[i2s_port][(chan_dir) - 1][task] +#define I2S_LL_ETM_MAX_THRESH_NUM (0x3FFUL) + +/** + * + * @param i2s_id The port id of I2S + * @param enable Set true to enable the buf clock + */ +static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) +{ + (void)i2s_id; + PCR.i2s_conf.i2s_clk_en = enable; +} + +/** + * @brief Reset the I2S module + * + * @param i2s_id The port id of I2S + */ +static inline void i2s_ll_reset_register(int i2s_id) +{ + (void)i2s_id; + PCR.i2s_conf.i2s_rst_en = 1; + PCR.i2s_conf.i2s_rst_en = 0; +} + +/** + * @brief I2S module general init, enable I2S clock. + * + * @param hw Peripheral I2S hardware instance address. + * @param enable set true to enable the core clock + */ +static inline void i2s_ll_enable_core_clock(i2s_dev_t *hw, bool enable) +{ + (void)hw; + (void)enable; + // No need to do anything +} + +/** + * @brief Enable I2S tx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 1; +} + +/** + * @brief Enable I2S rx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 1; +} + +/** + * @brief Disable I2S tx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 0; +} + +/** + * @brief Disable I2S rx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 0; +} + +/** + * @brief I2S mclk use tx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_rx_clkm_conf.i2s_mclk_sel = 0; +} + +/** + * @brief I2S mclk use rx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_mclk_bind_to_rx_clk(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_rx_clkm_conf.i2s_mclk_sel = 1; +} + +/** + * @brief Enable I2S TX slave mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slave_en Set true to enable slave mode + */ +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) +{ + hw->tx_conf.tx_slave_mod = slave_en; +} + +/** + * @brief Enable I2S RX slave mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slave_en Set true to enable slave mode + */ +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) +{ + hw->rx_conf.rx_slave_mod = slave_en; +} + +/** + * @brief Reset I2S TX module + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) +{ + hw->tx_conf.tx_reset = 1; + hw->tx_conf.tx_reset = 0; +} + +/** + * @brief Reset I2S RX module + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) +{ + hw->rx_conf.rx_reset = 1; + hw->rx_conf.rx_reset = 0; +} + +/** + * @brief Reset I2S TX FIFO + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) +{ + hw->tx_conf.tx_fifo_reset = 1; + hw->tx_conf.tx_fifo_reset = 0; +} + +/** + * @brief Reset I2S RX FIFO + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) +{ + hw->rx_conf.rx_fifo_reset = 1; + hw->rx_conf.rx_fifo_reset = 0; +} + +/** + * @brief Set TX source clock + * + * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock. + */ +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) +{ + (void)hw; + switch (src) + { + case I2S_CLK_SRC_XTAL: + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 0; + break; + case I2S_CLK_SRC_PLL_120M: + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 1; + break; + case I2S_CLK_SRC_PLL_160M: + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 2; + break; + case I2S_CLK_SRC_EXTERNAL: + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 3; + break; + default: + HAL_ASSERT(false && "unsupported clock source"); + break; + } +} + +/** + * @brief Set RX source clock + * + * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock + */ +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) +{ + (void)hw; + switch (src) + { + case I2S_CLK_SRC_XTAL: + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 0; + break; + case I2S_CLK_SRC_PLL_120M: + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 1; + break; + case I2S_CLK_SRC_PLL_160M: + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 2; + break; + case I2S_CLK_SRC_EXTERNAL: + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 3; + break; + default: + HAL_ASSERT(false && "unsupported clock source"); + break; + } +} + +/** + * @brief Set I2S tx bck div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx bck div num + */ +static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->tx_conf.tx_bck_div_num = val - 1; +} + +/** + * @brief Set I2S tx raw clock division + * + * @param hw Peripheral I2S hardware instance address. + * @param div_int Integer part of division + * @param x div x + * @param y div y + * @param z div z + * @param yn1 yn1 + */ +static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) +{ + (void)hw; + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int); + typeof(PCR.i2s_tx_clkm_div_conf) div = {}; + div.i2s_tx_clkm_div_x = x; + div.i2s_tx_clkm_div_y = y; + div.i2s_tx_clkm_div_z = z; + div.i2s_tx_clkm_div_yn1 = yn1; + PCR.i2s_tx_clkm_div_conf.val = div.val; +} + +/** + * @brief Set I2S rx raw clock division + * + * @param hw Peripheral I2S hardware instance address. + * @param div_int Integer part of division + * @param x div x + * @param y div y + * @param z div z + * @param yn1 yn1 + */ +static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) +{ + (void)hw; + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int); + typeof(PCR.i2s_rx_clkm_div_conf) div = {}; + div.i2s_rx_clkm_div_x = x; + div.i2s_rx_clkm_div_y = y; + div.i2s_rx_clkm_div_z = z; + div.i2s_rx_clkm_div_yn1 = yn1; + PCR.i2s_rx_clkm_div_conf.val = div.val; +} + +/** + * @brief Configure I2S TX module clock divider + * + * @param hw Peripheral I2S hardware instance address. + * @param mclk_div The mclk division coefficients + */ +static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) +{ + /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate + * Set to particular coefficients first then update to the target coefficients, + * otherwise the clock division might be inaccurate. + * the general idea is to set a value that impossible to calculate from the regular decimal */ + i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); + + uint32_t div_x = 0; + uint32_t div_y = 0; + uint32_t div_z = 0; + uint32_t div_yn1 = 0; + /* If any of denominator and numerator is 0, set all the coefficients to 0 */ + if (mclk_div->denominator && mclk_div->numerator) { + div_yn1 = mclk_div->numerator * 2 > mclk_div->denominator; + div_z = div_yn1 ? mclk_div->denominator - mclk_div->numerator : mclk_div->numerator; + div_x = mclk_div->denominator / div_z - 1; + div_y = mclk_div->denominator % div_z; + } + i2s_ll_tx_set_raw_clk_div(hw, mclk_div->integer, div_x, div_y, div_z, div_yn1); +} + +/** + * @brief Set I2S rx bck div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx bck div num + */ +static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->rx_conf.rx_bck_div_num = val - 1; +} + +/** + * @brief Configure I2S RX module clock divider + * @note mclk on ESP32C61 is shared by both TX and RX channel + * + * @param hw Peripheral I2S hardware instance address. + * @param mclk_div The mclk division coefficients + */ +static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) +{ + /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate + * Set to particular coefficients first then update to the target coefficients, + * otherwise the clock division might be inaccurate. + * the general idea is to set a value that impossible to calculate from the regular decimal */ + i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); + + uint32_t div_x = 0; + uint32_t div_y = 0; + uint32_t div_z = 0; + uint32_t div_yn1 = 0; + /* If any of denominator and numerator is 0, set all the coefficients to 0 */ + if (mclk_div->denominator && mclk_div->numerator) { + div_yn1 = mclk_div->numerator * 2 > mclk_div->denominator; + div_z = div_yn1 ? mclk_div->denominator - mclk_div->numerator : mclk_div->numerator; + div_x = mclk_div->denominator / div_z - 1; + div_y = mclk_div->denominator % div_z; + } + i2s_ll_rx_set_raw_clk_div(hw, mclk_div->integer, div_x, div_y, div_z, div_yn1); +} + +/** + * @brief Start I2S TX + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_start(i2s_dev_t *hw) +{ + // Have to update registers before start + hw->tx_conf.tx_update = 1; + while (hw->tx_conf.tx_update); + hw->tx_conf.tx_start = 1; +} + +/** + * @brief Start I2S RX + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_start(i2s_dev_t *hw) +{ + // Have to update registers before start + hw->rx_conf.rx_update = 1; + while (hw->rx_conf.rx_update); + hw->rx_conf.rx_start = 1; +} + +/** + * @brief Stop I2S TX + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) +{ + hw->tx_conf.tx_start = 0; +} + +/** + * @brief Stop I2S RX + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) +{ + hw->rx_conf.rx_start = 0; +} + +/** + * @brief Configure TX WS signal width + * + * @param hw Peripheral I2S hardware instance address. + * @param width WS width in BCK cycle + */ +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) +{ + hw->tx_conf1.tx_tdm_ws_width = width - 1; +} + +/** + * @brief Configure RX WS signal width + * + * @param hw Peripheral I2S hardware instance address. + * @param width WS width in BCK cycle + */ +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) +{ + hw->rx_conf1.rx_tdm_ws_width = width - 1; +} + +/** + * @brief Configure the received length to trigger in_suc_eof interrupt + * + * @param hw Peripheral I2S hardware instance address. + * @param eof_num the byte length to trigger in_suc_eof interrupt + */ +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) +{ + hw->rx_eof_num.rx_eof_num = eof_num; +} + +/** + * @brief Configure TX chan bit and audio data bit + * + * @param hw Peripheral I2S hardware instance address. + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width + */ +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) +{ + hw->tx_conf1.tx_bits_mod = data_bit - 1; + hw->tx_conf1.tx_tdm_chan_bits = chan_bit - 1; +} + +/** + * @brief Configure RX chan bit and audio data bit + * + * @param hw Peripheral I2S hardware instance address. + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width + */ +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) +{ + hw->rx_conf1.rx_bits_mod = data_bit - 1; + hw->rx_conf1.rx_tdm_chan_bits = chan_bit - 1; +} + +/** + * @brief Configure RX half_sample_bit + * + * @param hw Peripheral I2S hardware instance address. + * @param half_sample_bits half sample bit width + */ +static inline void i2s_ll_tx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +{ + hw->tx_conf1.tx_half_sample_bits = half_sample_bits - 1; +} + +/** + * @brief Configure RX half_sample_bit + * + * @param hw Peripheral I2S hardware instance address. + * @param half_sample_bits half sample bit width + */ +static inline void i2s_ll_rx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +{ + hw->rx_conf1.rx_half_sample_bits = half_sample_bits - 1; +} + +/** + * @brief Enable TX MSB shift, the data will be launch at the first BCK clock + * + * @param hw Peripheral I2S hardware instance address. + * @param msb_shift_enable Set true to enable MSB shift + */ +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) +{ + hw->tx_conf.tx_msb_shift = msb_shift_enable; +} + +/** + * @brief Enable RX MSB shift, the data will be launch at the first BCK clock + * + * @param hw Peripheral I2S hardware instance address. + * @param msb_shift_enable Set true to enable MSB shift + */ +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) +{ + hw->rx_conf.rx_msb_shift = msb_shift_enable; +} + +/** + * @brief Configure TX total chan number + * + * @param hw Peripheral I2S hardware instance address. + * @param total_num Total chan number + */ +static inline void i2s_ll_tx_set_chan_num(i2s_dev_t *hw, int total_num) +{ + hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1; +} + +/** + * @brief Configure RX total chan number + * + * @param hw Peripheral I2S hardware instance address. + * @param total_num Total chan number + */ +static inline void i2s_ll_rx_set_chan_num(i2s_dev_t *hw, int total_num) +{ + hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1; +} + +/** + * @brief Set the bimap of the active TX chan, only the active chan can launch audio data. + * + * @param hw Peripheral I2S hardware instance address. + * @param chan_mask mask of tx active chan + */ +static inline void i2s_ll_tx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +{ + uint32_t tdm_ctrl = hw->tx_tdm_ctrl.val; + tdm_ctrl &= 0xFFFF0000; + tdm_ctrl |= chan_mask; + hw->tx_tdm_ctrl.val = tdm_ctrl; +} + +/** + * @brief Set the bimap of the active RX chan, only the active chan can receive audio data. + * + * @param hw Peripheral I2S hardware instance address. + * @param chan_mask mask of rx active chan + */ +static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +{ + uint32_t tdm_ctrl = hw->rx_tdm_ctrl.val; + tdm_ctrl &= 0xFFFF0000; + tdm_ctrl |= chan_mask; + hw->rx_tdm_ctrl.val = tdm_ctrl; +} + +/** + * @brief Set I2S tx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_mask select slot to send data + */ +static inline void i2s_ll_tx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = 1; // tx_tdm_tot_chan_num = 2 slots - 1 = 1 + uint32_t chan_mask = 0; + switch (slot_mask) + { + case I2S_STD_SLOT_LEFT: + chan_mask |= 0x01; + break; + case I2S_STD_SLOT_RIGHT: + chan_mask |= 0x02; + break; + case I2S_STD_SLOT_BOTH: + chan_mask |= 0x03; + break; + default: + break; + } + i2s_ll_tx_set_active_chan_mask(hw, chan_mask); +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_mask select slot to receive data + */ +static inline void i2s_ll_rx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = 1; // rx_tdm_tot_chan_num = 2 slots - 1 = 1 + uint32_t chan_mask = 0; + switch (slot_mask) + { + case I2S_STD_SLOT_LEFT: + chan_mask |= 0x01; + break; + case I2S_STD_SLOT_RIGHT: + chan_mask |= 0x02; + break; + case I2S_STD_SLOT_BOTH: + chan_mask |= 0x03; + break; + default: + break; + } + i2s_ll_rx_set_active_chan_mask(hw, chan_mask); +} + +/** + * @brief PDM slot mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mod Channel mode + * while tx_ws_idle_pol = 0: + * 0: stereo + * 1: Both slots transmit left + * 2: Both slots transmit right + * 3: Left transmits `conf_single_data` right transmits data + * 4: Right transmits `conf_single_data` left transmits data + * while tx_ws_idle_pol = 1: + 0: stereo + * 1: Both slots transmit right + * 2: Both slots transmit left + * 3: Right transmits `conf_single_data` left transmits data + * 4: Left transmits `conf_single_data` right transmits data + */ +static inline void i2s_ll_tx_set_pdm_chan_mod(i2s_dev_t *hw, uint32_t mod) +{ + hw->tx_conf.tx_chan_mod = mod; +} + +/** + * @brief Set TX WS signal pol level + * + * @param hw Peripheral I2S hardware instance address. + * @param ws_pol_level pin level of WS(output) when receiving left channel data + */ +static inline void i2s_ll_tx_set_ws_idle_pol(i2s_dev_t *hw, bool ws_pol_level) +{ + hw->tx_conf.tx_ws_idle_pol = ws_pol_level; +} + +/** + * @brief Set RX WS signal pol level + * + * @param hw Peripheral I2S hardware instance address. + * @param ws_pol_level pin level of WS(input) when receiving left channel data + */ +static inline void i2s_ll_rx_set_ws_idle_pol(i2s_dev_t *hw, bool ws_pol_level) +{ + hw->rx_conf.rx_ws_idle_pol = ws_pol_level; +} + +/** + * @brief Enable I2S TX TDM mode + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_enable_tdm(i2s_dev_t *hw) +{ + hw->tx_conf.tx_pdm_en = false; + hw->tx_conf.tx_tdm_en = true; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = false; +} + +/** + * @brief Enable I2S RX TDM mode + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_enable_tdm(i2s_dev_t *hw) +{ + hw->rx_conf.rx_pdm_en = false; + hw->rx_conf.rx_tdm_en = true; +} + +/** + * @brief Enable I2S TX STD mode + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw) +{ + i2s_ll_tx_enable_tdm(hw); +} + +/** + * @brief Enable I2S RX STD mode + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw) +{ + i2s_ll_rx_enable_tdm(hw); +} + +/** + * @brief Enable TX PDM mode. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw) +{ + hw->tx_conf.tx_pdm_en = true; + hw->tx_conf.tx_tdm_en = false; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = true; +} + +/** + * @brief Set I2S TX PDM prescale + * + * @param hw Peripheral I2S hardware instance address. + * @param prescale I2S TX PDM prescale + */ +static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_pcm2pdm_conf, tx_pdm_prescale, prescale); +} + +/** + * @brief Set I2S TX PDM high pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_hp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM low pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_lp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sinc filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sinc_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sigma-delta filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM high pass filter param0 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 1 is (504 + I2S_TX_IIR_HP_MULT12_0[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param0(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_0 = param; +} + +/** + * @brief Set I2S TX PDM high pass filter param5 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 2 is (504 + I2S_TX_IIR_HP_MULT12_5[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param5(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_5 = param; +} + +/** + * @brief Enable I2S TX PDM high pass filter + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable I2S TX PDM high pass filter, set false to bypass it + */ +static inline void i2s_ll_tx_enable_pdm_hp_filter(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_pdm_hp_bypass = !enable; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither(i2s_dev_t *hw, uint32_t dither) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither = dither; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither2 I2S TX PDM sigmadelta dither2 value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither2 = dither2; +} + +/** + * @brief Set the PDM TX over sampling ratio + * + * @param hw Peripheral I2S hardware instance address. + * @param ovr Over sampling ratio + */ +static inline void i2s_ll_tx_set_pdm_over_sample_ratio(i2s_dev_t *hw, uint32_t ovr) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sinc_osr2 = ovr; +} + +/** + * @brief Configure I2S TX PDM sample rate + * Fpdm = 64*Fpcm*fp/fs + * + * @param hw Peripheral I2S hardware instance address. + * @param fp The fp value of TX PDM filter module group0. + * @param fs The fs value of TX PDM filter module group0. + */ +static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t fs) +{ + hw->tx_pcm2pdm_conf1.tx_pdm_fp = fp; + hw->tx_pcm2pdm_conf1.tx_pdm_fs = fs; +} + +/** + * @brief Get I2S TX PDM fp configuration parameter + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fp configuration parameter + */ +static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) +{ + return hw->tx_pcm2pdm_conf1.tx_pdm_fp; +} + +/** + * @brief Get I2S TX PDM fs configuration parameter + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fs configuration parameter + */ +static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) +{ + return hw->tx_pcm2pdm_conf1.tx_pdm_fs; +} + +/** + * @brief Enable RX PDM mode. + * @note ESP32-C61 doesn't support pdm in rx mode, disable anyway + * + * @param hw Peripheral I2S hardware instance address. + * @param pdm_enable Set true to RX enable PDM mode (ignored) + */ +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) +{ + // Due to the lack of `PDM to PCM` module on ESP32-C61, PDM RX is not available + HAL_ASSERT(!pdm_enable); + hw->rx_conf.rx_pdm_en = 0; + hw->rx_conf.rx_tdm_en = 1; +} + +/** + * @brief Configura TX a/u-law decompress or compress + * + * @param hw Peripheral I2S hardware instance address. + * @param pcm_cfg PCM configuration parameter + */ +static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) +{ + hw->tx_conf.tx_pcm_conf = pcm_cfg; + hw->tx_conf.tx_pcm_bypass = !pcm_cfg; +} + +/** + * @brief Configure RX a/u-law decompress or compress + * + * @param hw Peripheral I2S hardware instance address. + * @param pcm_cfg PCM configuration parameter + */ +static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) +{ + hw->rx_conf.rx_pcm_conf = pcm_cfg; + hw->rx_conf.rx_pcm_bypass = !pcm_cfg; +} + +/** + * @brief Enable TX audio data left alignment + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to enable left alignment + */ +static inline void i2s_ll_tx_enable_left_align(i2s_dev_t *hw, bool ena) +{ + hw->tx_conf.tx_left_align = ena; +} + +/** + * @brief Enable RX audio data left alignment + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to enable left alignment + */ +static inline void i2s_ll_rx_enable_left_align(i2s_dev_t *hw, bool ena) +{ + hw->rx_conf.rx_left_align = ena; +} + +/** + * @brief Enable TX big endian mode + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to enable big endian mode + */ +static inline void i2s_ll_rx_enable_big_endian(i2s_dev_t *hw, bool ena) +{ + hw->rx_conf.rx_big_endian = ena; +} + +/** + * @brief Enable RX big endian mode + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to enable big endian mode + */ +static inline void i2s_ll_tx_enable_big_endian(i2s_dev_t *hw, bool ena) +{ + hw->tx_conf.tx_big_endian = ena; +} + +/** + * @brief Configure TX bit order + * + * @param hw Peripheral I2S hardware instance address. + * @param lsb_order_ena Set true to enable LSB bit order + */ +static inline void i2s_ll_tx_set_bit_order(i2s_dev_t *hw, bool lsb_order_ena) +{ + hw->tx_conf.tx_bit_order = lsb_order_ena; +} + +/** + * @brief Configure RX bit order + * + * @param hw Peripheral I2S hardware instance address. + * @param lsb_order_ena Set true to enable LSB bit order + */ +static inline void i2s_ll_rx_set_bit_order(i2s_dev_t *hw, bool lsb_order_ena) +{ + hw->rx_conf.rx_bit_order = lsb_order_ena; +} + +/** + * @brief Configure TX skip mask enable + * + * @param hw Peripheral I2S hardware instance address. + * @param skip_mask_ena Set true to skip inactive channels. + */ +static inline void i2s_ll_tx_set_skip_mask(i2s_dev_t *hw, bool skip_mask_ena) +{ + hw->tx_tdm_ctrl.tx_tdm_skip_msk_en = skip_mask_ena; +} + + +/** + * @brief Configure single data + * + * @param hw Peripheral I2S hardware instance address. + * @param data Single data to be set + */ +static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) +{ + hw->conf_single_data.val = data; +} + +/** + * @brief Enable TX mono mode + * @note MONO in hardware means only one channel got data, but another doesn't + * MONO in software means two channel share same data + * This function aims to use MONO in software meaning + * so 'tx_mono' and 'tx_chan_equal' should be enabled at the same time + * + * @param hw Peripheral I2S hardware instance address. + * @param mono_ena Set true to enable mono mde. + */ +static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) +{ + hw->tx_conf.tx_mono = mono_ena; + hw->tx_conf.tx_chan_equal = mono_ena; +} + +/** + * @brief Enable RX mono mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mono_ena Set true to enable mono mde. + */ +static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) +{ + hw->rx_conf.rx_mono = mono_ena; + hw->rx_conf.rx_mono_fst_vld = mono_ena; +} + +/** + * @brief Enable loopback mode + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to share BCK and WS signal for tx module and rx module. + */ +static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool ena) +{ + hw->tx_conf.sig_loopback = ena; +} + +/** + * @brief PDM TX DMA data take mode + * + * @param hw Peripheral I2S hardware instance address. + * @param is_mono The DMA data only has one slot (mono) or contains two slots (stereo) + * @param is_fst_valid Whether take the DMA data at the first half period + * Only take effet when 'is_mono' is true + */ +static inline void i2s_ll_tx_pdm_dma_take_mode(i2s_dev_t *hw, bool is_mono, bool is_fst_valid) +{ + hw->tx_conf.tx_mono = is_mono; + hw->tx_conf.tx_mono_fst_vld = is_fst_valid; +} + +/** + * @brief PDM TX slot mode + * @note Mode Left Slot Right Slot Chan Mode WS Pol + * ----------------------------------------------------------------- + * Stereo Left Right 0 x + * ----------------------------------------------------------------- + * Mono Left Left 1 0 + * Mono Right Right 2 0 + * Mono Single Right 3 0 + * Mono Left Single 4 0 + * ----------------------------------------------------------------- + * Mono Right Right 1 1 + * Mono Left Left 2 1 + * Mono Left Single 3 1 + * Mono Single Right 4 1 + * @note The 'Single' above means always sending the value of `conf_single_data` reg + * The default value of `conf_single_data` reg is '0', it is not public for now + * + * @param hw Peripheral I2S hardware instance address. + * @param is_mono The DMA data only has one slot (mono) or contains two slots (stereo) + * @param is_copy Whether the un-selected slot copies the data from the selected one + * If not, the un-selected slot will transmit the data from 'conf_single_data' + * @param mask The slot mask to select the slot + */ +static inline void i2s_ll_tx_pdm_slot_mode(i2s_dev_t *hw, bool is_mono, bool is_copy, i2s_pdm_slot_mask_t mask) +{ + if (is_mono) { + /* The default tx_ws_idle_pol is false */ + if (is_copy) { + hw->tx_conf.tx_chan_mod = mask == I2S_PDM_SLOT_LEFT ? 1 : 2; + } else { + hw->tx_conf.tx_chan_mod = mask == I2S_PDM_SLOT_LEFT ? 4 : 3; + } + } else { + hw->tx_conf.tx_chan_mod = 0; + } +} + +/** + * @brief PDM TX line mode + * @note Mode DAC Mode 2 lines output + * ------------------------------------------- + * PDM codec 0 1 + * DAC 1-line 1 0 + * DAC 2-line 1 1 + * + * @param hw Peripheral I2S hardware instance address. + * @param line_mode PDM TX line mode + */ +static inline void i2s_ll_tx_pdm_line_mode(i2s_dev_t *hw, i2s_pdm_tx_line_mode_t line_mode) +{ + hw->tx_pcm2pdm_conf.tx_pdm_dac_mode_en = line_mode > I2S_PDM_TX_ONE_LINE_CODEC; + hw->tx_pcm2pdm_conf.tx_pdm_dac_2out_en = line_mode != I2S_PDM_TX_ONE_LINE_DAC; +} + +/** + * @brief Reset TX FIFO synchronization counter + * + * @param hw Peripheral I2S hardware instance address. + */ +__attribute__((always_inline)) +static inline void i2s_ll_tx_reset_fifo_sync_counter(i2s_dev_t *hw) +{ + hw->fifo_cnt.tx_fifo_cnt_rst = 1; + hw->fifo_cnt.tx_fifo_cnt_rst = 0; +} + +/** + * @brief Get TX FIFO synchronization count value + * + * @param hw Peripheral I2S hardware instance address. + * @return + * bclk count value + */ +__attribute__((always_inline)) +static inline uint32_t i2s_ll_tx_get_fifo_sync_count(i2s_dev_t *hw) +{ + return hw->fifo_cnt.tx_fifo_cnt; +} + +/** + * @brief Reset TX bclk synchronization counter + * + * @param hw Peripheral I2S hardware instance address. + */ +__attribute__((always_inline)) +static inline void i2s_ll_tx_reset_bclk_sync_counter(i2s_dev_t *hw) +{ + hw->bck_cnt.tx_bck_cnt_rst = 1; + hw->bck_cnt.tx_bck_cnt_rst = 0; +} + +/** + * @brief Get TX bclk synchronization count value + * + * @param hw Peripheral I2S hardware instance address. + * @return + * fifo count value + */ +__attribute__((always_inline)) +static inline uint32_t i2s_ll_tx_get_bclk_sync_count(i2s_dev_t *hw) +{ + return hw->bck_cnt.tx_bck_cnt; +} + +/** + * @brief Set the TX ETM threshold of REACH_THRESH event + * + * @param hw Peripheral I2S hardware instance address. + * @param thresh The threshold that send + */ +static inline void i2s_ll_tx_set_etm_threshold(i2s_dev_t *hw, uint32_t thresh) +{ + hw->etm_conf.etm_tx_send_word_num = thresh; +} + +/** + * @brief Set the RX ETM threshold of REACH_THRESH event + * + * @param hw Peripheral I2S hardware instance address. + * @param thresh The threshold that received + */ +static inline void i2s_ll_rx_set_etm_threshold(i2s_dev_t *hw, uint32_t thresh) +{ + hw->etm_conf.etm_rx_receive_word_num = thresh; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c61/include/hal/uart_ll.h b/components/hal/esp32c61/include/hal/uart_ll.h index 2a6a014108f0..f6599d94bded 100644 --- a/components/hal/esp32c61/include/hal/uart_ll.h +++ b/components/hal/esp32c61/include/hal/uart_ll.h @@ -64,10 +64,6 @@ extern "C" { ((hw) == &UART1) ? PCR.uart1_##reg_suffix.uart1_##field_suffix : \ PCR.uart2_##reg_suffix.uart2_##field_suffix) -// UART sleep retention module -#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ - (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1) - // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), diff --git a/components/hal/esp32c61/modem_clock_hal.c b/components/hal/esp32c61/modem_clock_hal.c index fe84dcfb850d..3af99192403a 100644 --- a/components/hal/esp32c61/modem_clock_hal.c +++ b/components/hal/esp32c61/modem_clock_hal.c @@ -101,12 +101,9 @@ uint32_t IRAM_ATTR modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_c return bitmap; } -void IRAM_ATTR modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) +void IRAM_ATTR modem_clock_hal_enable_modem_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) { if (enable) { - modem_syscon_ll_enable_fe_adc_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_dac_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_pwdet_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_80m_clock(hal->syscon_dev, enable); } @@ -116,6 +113,9 @@ void IRAM_ATTR modem_clock_hal_enable_modem_private_fe_clock(modem_clock_hal_con { if (enable) { modem_syscon_ll_enable_fe_160m_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_adc_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_dac_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_pwdet_clock(hal->syscon_dev, enable); } } diff --git a/components/hal/esp32h2/include/hal/brownout_ll.h b/components/hal/esp32h2/include/hal/brownout_ll.h index 6553c8bd1419..9dce284ac8b0 100644 --- a/components/hal/esp32h2/include/hal/brownout_ll.h +++ b/components/hal/esp32h2/include/hal/brownout_ll.h @@ -69,7 +69,8 @@ static inline void brownout_ll_reset_config(bool reset_ena, uint32_t reset_wait, */ static inline void brownout_ll_set_threshold(uint8_t threshold) { - REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD, threshold); + REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD_L, threshold); + REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD_H, threshold); } /** diff --git a/components/hal/esp32h2/include/hal/clk_gate_ll.h b/components/hal/esp32h2/include/hal/clk_gate_ll.h index 3eef499230d5..7ac7b7d7fcde 100644 --- a/components/hal/esp32h2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32h2/include/hal/clk_gate_ll.h @@ -38,7 +38,7 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return PCR_I2C0_CLK_EN; case PERIPH_I2C1_MODULE: return PCR_I2C1_CLK_EN; - case PERIPH_I2S1_MODULE: + case PERIPH_I2S0_MODULE: return PCR_I2S_CLK_EN; case PERIPH_TIMG0_MODULE: return PCR_TG0_CLK_EN; @@ -119,7 +119,7 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return PCR_I2C0_RST_EN; case PERIPH_I2C1_MODULE: return PCR_I2C1_RST_EN; - case PERIPH_I2S1_MODULE: + case PERIPH_I2S0_MODULE: return PCR_I2S_RST_EN; case PERIPH_TIMG0_MODULE: return PCR_TG0_RST_EN; @@ -224,7 +224,7 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) return PCR_I2C0_CONF_REG; case PERIPH_I2C1_MODULE: return PCR_I2C1_CONF_REG; - case PERIPH_I2S1_MODULE: + case PERIPH_I2S0_MODULE: return PCR_I2S_CONF_REG; case PERIPH_TIMG0_MODULE: return PCR_TIMERGROUP0_CONF_REG; @@ -291,7 +291,7 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) return PCR_I2C0_CONF_REG; case PERIPH_I2C1_MODULE: return PCR_I2C1_CONF_REG; - case PERIPH_I2S1_MODULE: + case PERIPH_I2S0_MODULE: return PCR_I2S_CONF_REG; case PERIPH_TIMG0_MODULE: return PCR_TIMERGROUP0_CONF_REG; diff --git a/components/hal/esp32h2/include/hal/gpio_ll.h b/components/hal/esp32h2/include/hal/gpio_ll.h index be799df21464..8a7cfd448bd6 100644 --- a/components/hal/esp32h2/include/hal/gpio_ll.h +++ b/components/hal/esp32h2/include/hal/gpio_ll.h @@ -377,9 +377,9 @@ __attribute__((always_inline)) static inline void gpio_ll_set_level(gpio_dev_t *hw, gpio_num_t gpio_num, uint32_t level) { if (level) { - hw->out_w1ts.out_w1ts = (1 << gpio_num); + hw->out_w1ts.val = 1 << gpio_num; } else { - hw->out_w1tc.out_w1tc = (1 << gpio_num); + hw->out_w1tc.val = 1 << gpio_num; } } diff --git a/components/hal/esp32h2/include/hal/i2c_ll.h b/components/hal/esp32h2/include/hal/i2c_ll.h index d636cc0c7194..83d8816f734b 100644 --- a/components/hal/esp32h2/include/hal/i2c_ll.h +++ b/components/hal/esp32h2/include/hal/i2c_ll.h @@ -76,9 +76,6 @@ typedef enum { #define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9) #define I2C_LL_SCL_WAIT_US_VAL_DEFAULT (2500) // Approximate value for SCL timeout regs (in us). -// I2C sleep retention module -#define I2C_SLEEP_RETENTION_MODULE(i2c_num) ((i2c_num == 0) ? SLEEP_RETENTION_MODULE_I2C0 : SLEEP_RETENTION_MODULE_I2C1) - /** * @brief Calculate I2C bus frequency * Note that the clock accuracy is affected by the external pull-up resistor, diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 85e920a2a9f7..e640c8d5f499 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -313,13 +313,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, 2); + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = 1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = yn1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = z; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = y; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int); - typeof(PCR.i2s_tx_clkm_div_conf) div = {}; - div.i2s_tx_clkm_div_x = x; - div.i2s_tx_clkm_div_y = y; - div.i2s_tx_clkm_div_z = z; - div.i2s_tx_clkm_div_yn1 = yn1; - PCR.i2s_tx_clkm_div_conf.val = div.val; } /** @@ -335,13 +343,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, 2); + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = 1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = yn1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = z; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = y; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int); - typeof(PCR.i2s_rx_clkm_div_conf) div = {}; - div.i2s_rx_clkm_div_x = x; - div.i2s_rx_clkm_div_y = y; - div.i2s_rx_clkm_div_z = z; - div.i2s_rx_clkm_div_yn1 = yn1; - PCR.i2s_rx_clkm_div_conf.val = div.val; } /** @@ -352,12 +368,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 8, 1, 1, 73, 1); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -385,19 +395,13 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) /** * @brief Configure I2S RX module clock divider - * @note mclk on ESP32 is shared by both TX and RX channel + * @note mclk on ESP32H2 is shared by both TX and RX channel * * @param hw Peripheral I2S hardware instance address. * @param mclk_div The mclk division coefficients */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 8, 1, 1, 73, 1); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; diff --git a/components/hal/esp32h2/include/hal/rmt_ll.h b/components/hal/esp32h2/include/hal/rmt_ll.h index a3179addba59..4ebb3a1e0628 100644 --- a/components/hal/esp32h2/include/hal/rmt_ll.h +++ b/components/hal/esp32h2/include/hal/rmt_ll.h @@ -38,8 +38,6 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 -#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0) - typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index 4fa29d216f32..77c0291a0237 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -57,10 +57,6 @@ extern "C" { #define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \ (((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix) -// UART sleep retention module -#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ - (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1) - // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), @@ -94,14 +90,14 @@ typedef enum { */ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) { - uint32_t uart_clk_config_reg = ((uart_num == 0) ? PCR_UART0_CONF_REG : - (uart_num == 1) ? PCR_UART1_CONF_REG : 0); - uint32_t uart_rst_bit = ((uart_num == 0) ? PCR_UART0_RST_EN : - (uart_num == 1) ? PCR_UART1_RST_EN : 0); - uint32_t uart_en_bit = ((uart_num == 0) ? PCR_UART0_CLK_EN : - (uart_num == 1) ? PCR_UART1_CLK_EN : 0); - return REG_GET_BIT(uart_clk_config_reg, uart_rst_bit) == 0 && - REG_GET_BIT(uart_clk_config_reg, uart_en_bit) != 0; + switch (uart_num) { + case 0: + return PCR.uart0_conf.uart0_clk_en && !PCR.uart0_conf.uart0_rst_en; + case 1: + return PCR.uart1_conf.uart1_clk_en && !PCR.uart1_conf.uart1_rst_en; + default: + return false; + } } /** @@ -194,18 +190,18 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) FORCE_INLINE_ATTR void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_clk) { switch (source_clk) { - case UART_SCLK_PLL_F48M: - UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 1); - break; - case UART_SCLK_RTC: - UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 2); - break; - case UART_SCLK_XTAL: - UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 3); - break; - default: - // Invalid UART clock source - abort(); + case UART_SCLK_PLL_F48M: + UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 1); + break; + case UART_SCLK_RTC: + UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 2); + break; + case UART_SCLK_XTAL: + UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 3); + break; + default: + // Invalid UART clock source + abort(); } } @@ -220,16 +216,16 @@ FORCE_INLINE_ATTR void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source_clk) { switch (UART_LL_PCR_REG_GET(hw, sclk_conf, sclk_sel)) { - default: - case 1: - *source_clk = (soc_module_clk_t)UART_SCLK_PLL_F48M; - break; - case 2: - *source_clk = (soc_module_clk_t)UART_SCLK_RTC; - break; - case 3: - *source_clk = (soc_module_clk_t)UART_SCLK_XTAL; - break; + default: + case 1: + *source_clk = (soc_module_clk_t)UART_SCLK_PLL_F48M; + break; + case 2: + *source_clk = (soc_module_clk_t)UART_SCLK_RTC; + break; + case 3: + *source_clk = (soc_module_clk_t)UART_SCLK_XTAL; + break; } } @@ -248,7 +244,9 @@ FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint3 const uint32_t max_div = BIT(12) - 1; // UART divider integer part only has 12 bits uint32_t sclk_div = DIV_UP(sclk_freq, (uint64_t)max_div * baud); - if (sclk_div == 0) abort(); + if (sclk_div == 0) { + abort(); + } uint32_t clk_div = ((sclk_freq) << 4) / (baud * sclk_div); // The baud rate configuration register is divided into @@ -844,22 +842,22 @@ FORCE_INLINE_ATTR void uart_ll_set_mode_irda(uart_dev_t *hw) FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) { switch (mode) { - default: - case UART_MODE_UART: - uart_ll_set_mode_normal(hw); - break; - case UART_MODE_RS485_COLLISION_DETECT: - uart_ll_set_mode_collision_detect(hw); - break; - case UART_MODE_RS485_APP_CTRL: - uart_ll_set_mode_rs485_app_ctrl(hw); - break; - case UART_MODE_RS485_HALF_DUPLEX: - uart_ll_set_mode_rs485_half_duplex(hw); - break; - case UART_MODE_IRDA: - uart_ll_set_mode_irda(hw); - break; + default: + case UART_MODE_UART: + uart_ll_set_mode_normal(hw); + break; + case UART_MODE_RS485_COLLISION_DETECT: + uart_ll_set_mode_collision_detect(hw); + break; + case UART_MODE_RS485_APP_CTRL: + uart_ll_set_mode_rs485_app_ctrl(hw); + break; + case UART_MODE_RS485_HALF_DUPLEX: + uart_ll_set_mode_rs485_half_duplex(hw); + break; + case UART_MODE_IRDA: + uart_ll_set_mode_irda(hw); + break; } } @@ -957,7 +955,7 @@ FORCE_INLINE_ATTR void uart_ll_xon_force_on(uart_dev_t *hw, bool always_on) { hw->swfc_conf0_sync.force_xon = 1; uart_ll_update(hw); - if(!always_on) { + if (!always_on) { hw->swfc_conf0_sync.force_xon = 0; uart_ll_update(hw); } @@ -1003,7 +1001,7 @@ FORCE_INLINE_ATTR void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask) FORCE_INLINE_ATTR void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd) { uint16_t tout_val = tout_thrd; - if(tout_thrd > 0) { + if (tout_thrd > 0) { hw->tout_conf_sync.rx_tout_thrhd = tout_val; hw->tout_conf_sync.rx_tout_en = 1; } else { @@ -1022,7 +1020,7 @@ FORCE_INLINE_ATTR void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd) FORCE_INLINE_ATTR uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw) { uint16_t tout_thrd = 0; - if(hw->tout_conf_sync.rx_tout_en > 0) { + if (hw->tout_conf_sync.rx_tout_en > 0) { tout_thrd = hw->tout_conf_sync.rx_tout_thrhd; } return tout_thrd; diff --git a/components/hal/esp32h2/modem_clock_hal.c b/components/hal/esp32h2/modem_clock_hal.c index 879e694d2a4a..851e0c01ffc3 100644 --- a/components/hal/esp32h2/modem_clock_hal.c +++ b/components/hal/esp32h2/modem_clock_hal.c @@ -19,7 +19,7 @@ typedef enum { MODEM_CLOCK_EXT32K_CODE = 2 } modem_clock_32k_clk_src_code_t; -void IRAM_ATTR modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) +void IRAM_ATTR modem_clock_hal_enable_modem_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) { modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_32m_clock(hal->syscon_dev, enable); diff --git a/components/hal/esp32p4/include/hal/brownout_ll.h b/components/hal/esp32p4/include/hal/brownout_ll.h index 8327f9f8901c..91e0e4560d05 100644 --- a/components/hal/esp32p4/include/hal/brownout_ll.h +++ b/components/hal/esp32p4/include/hal/brownout_ll.h @@ -68,7 +68,8 @@ static inline void brownout_ll_reset_config(bool reset_ena, uint32_t reset_wait, */ static inline void brownout_ll_set_threshold(uint8_t threshold) { - REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD, threshold); + REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD_L, threshold); + REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD_H, threshold); } /** diff --git a/components/hal/esp32p4/include/hal/clk_gate_ll.h b/components/hal/esp32p4/include/hal/clk_gate_ll.h index 8c5fc05cfbff..9a49fd41e01d 100644 --- a/components/hal/esp32p4/include/hal/clk_gate_ll.h +++ b/components/hal/esp32p4/include/hal/clk_gate_ll.h @@ -14,6 +14,7 @@ extern "C" { #include #include "esp_attr.h" #include "soc/hp_sys_clkrst_struct.h" +#include "soc/lp_clkrst_struct.h" /** * Enable or disable the clock gate for ref_20m. @@ -75,6 +76,18 @@ FORCE_INLINE_ATTR void _clk_gate_ll_ref_240m_clk_en(bool enable) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define clk_gate_ll_ref_240m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_240m_clk_en(__VA_ARGS__) +/** + * Enable or disable the clock gate for xtal to lp periph + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_xtal_to_lp_periph_en(bool enable) +{ + LP_AON_CLKRST.lp_clk_en.xtal_clk_force_on = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_xtal_to_lp_periph_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_xtal_to_lp_periph_en(__VA_ARGS__) + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/gpio_ll.h b/components/hal/esp32p4/include/hal/gpio_ll.h index b152f9f863ee..7fb9bec340d3 100644 --- a/components/hal/esp32p4/include/hal/gpio_ll.h +++ b/components/hal/esp32p4/include/hal/gpio_ll.h @@ -400,15 +400,15 @@ static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t { if (level) { if (gpio_num < 32) { - hw->out_w1ts.out_w1ts = (1 << gpio_num); + hw->out_w1ts.val = 1 << gpio_num; } else { - hw->out1_w1ts.out1_w1ts = (1 << (gpio_num - 32)); + hw->out1_w1ts.val = 1 << (gpio_num - 32); } } else { if (gpio_num < 32) { - hw->out_w1tc.out_w1tc = (1 << gpio_num); + hw->out_w1tc.val = 1 << gpio_num; } else { - hw->out1_w1tc.out1_w1tc = (1 << (gpio_num - 32)); + hw->out1_w1tc.val = 1 << (gpio_num - 32); } } } diff --git a/components/hal/esp32p4/include/hal/i2s_ll.h b/components/hal/esp32p4/include/hal/i2s_ll.h index cfb2f2d7c61e..6cee5068a3b3 100644 --- a/components/hal/esp32p4/include/hal/i2s_ll.h +++ b/components/hal/esp32p4/include/hal/i2s_ll.h @@ -498,25 +498,52 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer switch (I2S_LL_GET_ID(hw)) { case 0: - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl13, reg_i2s0_tx_div_n, div_int); - HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_div_x = x; - HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_y = y; - HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_z = z; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl13, reg_i2s0_tx_div_n, 2); + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_yn1 = 0; + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_y = 1; + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_z = 0; + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_div_x = 0; + /* Set the target mclk division coefficients */ HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_yn1 = yn1; + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_div_x = x; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl13, reg_i2s0_tx_div_n, div_int); return; case 1: - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl16, reg_i2s1_tx_div_n, div_int); - HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_x = x; - HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_y = y; - HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_z = z; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl16, reg_i2s1_tx_div_n, 2); + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_yn1 = 0; + HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_y = 1; + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_z = 0; + HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_x = 0; + /* Set the target mclk division coefficients */ HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_yn1 = yn1; + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_x = x; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl16, reg_i2s1_tx_div_n, div_int); return; case 2: - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl18, reg_i2s2_tx_div_n, div_int); - HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_x = x; - HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_y = y; - HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_z = z; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl18, reg_i2s2_tx_div_n, 2); + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_yn1 = 0; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_y = 1; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_z = 0; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_x = 0; + /* Set the target mclk division coefficients */ HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_yn1 = yn1; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_x = x; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl18, reg_i2s2_tx_div_n, div_int); return; } } @@ -536,25 +563,52 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer switch (I2S_LL_GET_ID(hw)) { case 0: - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl12, reg_i2s0_rx_div_n, div_int); - HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_x = x; - HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_y = y; - HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_z = z; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl12, reg_i2s0_rx_div_n, 2); + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_yn1 = 0; + HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_y = 1; + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_z = 0; + HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_x = 0; + /* Set the target mclk division coefficients */ HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_yn1 = yn1; + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_x = x; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl12, reg_i2s0_rx_div_n, div_int); return; case 1: - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl14, reg_i2s1_rx_div_n, div_int); - HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_x = x; - HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_y = y; - HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_z = z; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl14, reg_i2s1_rx_div_n, 2); + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_yn1 = 0; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_y = 1; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_z = 0; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_x = 0; + /* Set the target mclk division coefficients */ HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_yn1 = yn1; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_x = x; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl14, reg_i2s1_rx_div_n, div_int); return; case 2: - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl17, reg_i2s2_rx_div_n, div_int); - HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_div_x = x; - HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_y = y; - HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_z = z; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl17, reg_i2s2_rx_div_n, 2); + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_yn1 = 0; + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_y = 1; + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_z = 0; + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_div_x = 0; + /* Set the target mclk division coefficients */ HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_yn1 = yn1; + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_div_x = x; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl17, reg_i2s2_rx_div_n, div_int); return; } } @@ -567,12 +621,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void _i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -604,19 +652,13 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) /** * @brief Configure I2S RX module clock divider - * @note mclk on ESP32 is shared by both TX and RX channel + * @note mclk on ESP32P4 is shared by both TX and RX channel * * @param hw Peripheral I2S hardware instance address. * @param mclk_div The mclk division coefficients */ static inline void _i2s_ll_rx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 9deb1b878119..00712b12564c 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -22,7 +22,10 @@ extern "C" { #endif -#define ISP_LL_GET_HW(num) (((num) == 0) ? (&ISP) : NULL) +#define ISP_LL_GET_HW(num) (((num) == 0) ? (&ISP) : NULL) + +#define ISP_LL_HSIZE_MAX 1920 +#define ISP_LL_VSIZE_MAX 1080 /*--------------------------------------------------------------- Clock @@ -81,6 +84,14 @@ extern "C" { ---------------------------------------------------------------*/ #define ISP_LL_AE_WINDOW_MAX_RANGE ((1<<12) - 1) +/*--------------------------------------------------------------- + AWB +---------------------------------------------------------------*/ +#define ISP_LL_AWB_WINDOW_MAX_RANGE ((1<<12) - 1) +#define ISP_LL_AWB_LUM_MAX_RANGE ((1<<10) - 1) +#define ISP_LL_AWB_RGB_RATIO_INT_BITS (2) +#define ISP_LL_AWB_RGB_RATIO_FRAC_BITS (8) + /*--------------------------------------------------------------- BF ---------------------------------------------------------------*/ @@ -103,20 +114,10 @@ extern "C" { #define ISP_LL_COLOR_BRIGNTNESS_MAX 127 /*--------------------------------------------------------------- - AWB + LSC ---------------------------------------------------------------*/ -#define ISP_LL_AWB_WINDOW_MAX_RANGE ((1<<12) - 1) -#define ISP_LL_AWB_LUM_MAX_RANGE ((1<<10) - 1) -#define ISP_LL_AWB_RGB_RATIO_INT_BITS (2) -#define ISP_LL_AWB_RGB_RATIO_FRAC_BITS (8) - -typedef union { - struct { - uint32_t fraction: ISP_LL_AWB_RGB_RATIO_FRAC_BITS; - uint32_t integer: ISP_LL_AWB_RGB_RATIO_INT_BITS; - }; - uint32_t val; -} isp_ll_awb_rgb_ratio_t; +#define ISP_LL_LSC_GRID_HEIGHT 32 +#define ISP_LL_LSC_GRID_WIDTH 32 /*--------------------------------------------------------------- CCM @@ -150,6 +151,22 @@ typedef enum { ISP_LL_AF_EDGE_DETECTOR_MODE_MANUAL, ///< Manual set threshold } isp_ll_af_edge_detector_mode_t; +typedef union { + struct { + uint32_t fraction: ISP_LL_AWB_RGB_RATIO_FRAC_BITS; + uint32_t integer: ISP_LL_AWB_RGB_RATIO_INT_BITS; + }; + uint32_t val; +} isp_ll_awb_rgb_ratio_t; + +/** + * @brief ISP LUT + */ +typedef enum { + ISP_LL_LUT_LSC, ///< LUT for LSC + ISP_LL_LUT_DPC, ///< LUT for DPC +} isp_ll_lut_t; + /*--------------------------------------------------------------- Clock @@ -463,6 +480,17 @@ static inline bool isp_ll_is_rgb2yuv_enabled(isp_dev_t *hw) return hw->cntl.rgb2yuv_en; } +/** + * @brief Set bayer mode + * + * @param[in] hw Hardware instance address + * @param[in] bayer_order Bayer order + */ +static inline void isp_ll_set_bayer_mode(isp_dev_t *hw, color_raw_element_order_t bayer_order) +{ + hw->frame_cfg.bayer_mode = bayer_order; +} + /*--------------------------------------------------------------- AF ---------------------------------------------------------------*/ @@ -1153,6 +1181,88 @@ static inline void isp_ll_ae_env_detector_set_period(isp_dev_t *hw, uint32_t per hw->ae_monitor.ae_monitor_period = period; } +/*--------------------------------------------------------------- + LSC +---------------------------------------------------------------*/ +/** + * @brief Enable / Disable LSC clock + * + * @param[in] hw Hardware instance address + * @param[in] enable Enable / Disable + */ +static inline void isp_ll_lsc_clk_enable(isp_dev_t *hw, bool enable) +{ + hw->clk_en.clk_lsc_force_on = enable; +} + +/** + * @brief Enable / Disable Color + * + * @param[in] hw Hardware instance address + * @param[in] enable Enable / Disable + */ +static inline void isp_ll_lsc_enable(isp_dev_t *hw, bool enable) +{ + hw->cntl.lsc_en = enable; +} + +/** + * @brief Set xtable size + * + * @param[in] hw Hardware instance address + * @param[in] xtablesize xtablesize + */ +static inline void isp_ll_lsc_set_xtablesize(isp_dev_t *hw, uint8_t xtablesize) +{ + hw->lsc_tablesize.lsc_xtablesize = xtablesize; +} + +/*--------------------------------------------------------------- + LUT +---------------------------------------------------------------*/ +/** + * @brief Select ISP LUT + * + * @param[in] hw Hardware instance address + * @param[in] is_write Is write or not + * @param[in] is_gb_b Is gb_b or not + * @param[in] addr LUT addr + * @param[in] lut ISP LUT + */ +static inline void isp_ll_lut_set_cmd(isp_dev_t *hw, bool is_write, bool is_gb_b, uint32_t addr, isp_ll_lut_t lut) +{ + uint32_t val = 0; + val |= is_write ? (1 << 16) : 0; + val |= is_gb_b ? 0 : (1 << 10); + val |= addr & ((1 << 10) - 1); + val |= lut << 12; + hw->lut_cmd.val = val; +} + +/** + * @brief Set lut gb and b gain + * + * @param[in] hw Hardware instance address + * @param[in] gb_gain gb gain + * @param[in] b_gain b gain + */ +static inline void isp_ll_lut_set_wdata_gb_b(isp_dev_t *hw, isp_lsc_gain_t gb_gain, isp_lsc_gain_t b_gain) +{ + hw->lut_wdata.lut_wdata = (gb_gain.val & 0x3ff) << 10 | (b_gain.val & 0x3ff); +} + +/** + * @brief Set lut r and gr gain + * + * @param[in] hw Hardware instance address + * @param[in] r_gain r gain + * @param[in] gr_gain gr gain + */ +static inline void isp_ll_lut_set_wdata_r_gr(isp_dev_t *hw, isp_lsc_gain_t r_gain, isp_lsc_gain_t gr_gain) +{ + hw->lut_wdata.lut_wdata = (r_gain.val & 0x3ff) << 10 | (gr_gain.val & 0x3ff); +} + /*--------------------------------------------------------------- INTR ---------------------------------------------------------------*/ diff --git a/components/hal/esp32p4/include/hal/key_mgr_ll.h b/components/hal/esp32p4/include/hal/key_mgr_ll.h index 15923a67ffa0..3aa13bc36313 100644 --- a/components/hal/esp32p4/include/hal/key_mgr_ll.h +++ b/components/hal/esp32p4/include/hal/key_mgr_ll.h @@ -54,19 +54,35 @@ static inline void _key_mgr_ll_enable_peripheral_clock(bool enable) #define key_mgr_ll_enable_peripheral_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_enable_peripheral_clock(__VA_ARGS__) /** - * @brief Reset the Key Manager peripheral */ -static inline void key_mgr_ll_reset_register(void) + * @brief Read state of Key Manager + * + * @return esp_key_mgr_state_t + */ +static inline esp_key_mgr_state_t key_mgr_ll_get_state(void) +{ + return (esp_key_mgr_state_t) REG_GET_FIELD(KEYMNG_STATE_REG, KEYMNG_STATE); +} + +/** + * @brief Reset the Key Manager peripheral + * Note: Please use key_mgr_ll_reset_register which requires the critical section + * and do not use _key_mgr_ll_reset_register + */ +static inline void _key_mgr_ll_reset_register(void) { HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_km = 1; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_km = 0; // Clear reset on parent crypto, otherwise Key Manager is held in reset HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_crypto = 0; + + while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) { + }; } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define key_mgr_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; key_mgr_ll_reset_register(__VA_ARGS__) +#define key_mgr_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_reset_register(__VA_ARGS__) /* @brief Start the key manager at IDLE state */ static inline void key_mgr_ll_start(void) @@ -323,16 +339,6 @@ static inline esp_key_mgr_xts_aes_key_len_t key_mgr_ll_get_xts_aes_key_len(void) return (esp_key_mgr_xts_aes_key_len_t) REG_GET_FIELD(KEYMNG_STATIC_REG, KEYMNG_XTS_AES_KEY_LEN); } -/** - * @brief Read state of Key Manager - * - * @return esp_key_mgr_state_t - */ -static inline esp_key_mgr_state_t key_mgr_ll_get_state(void) -{ - return (esp_key_mgr_state_t) REG_GET_FIELD(KEYMNG_STATE_REG, KEYMNG_STATE); -} - /** * @brief Read the Key Manager date information */ diff --git a/components/hal/esp32p4/include/hal/ldo_ll.h b/components/hal/esp32p4/include/hal/ldo_ll.h index 6e707890adb4..73a63eff19a0 100644 --- a/components/hal/esp32p4/include/hal/ldo_ll.h +++ b/components/hal/esp32p4/include/hal/ldo_ll.h @@ -8,8 +8,11 @@ #include #include +#include "soc/chip_revision.h" #include "esp_bit_defs.h" #include "hal/misc.h" +#include "hal/efuse_hal.h" +#include "hal/pmu_types.h" #include "soc/pmu_struct.h" #ifdef __cplusplus @@ -122,6 +125,10 @@ __attribute__((always_inline)) static inline void ldo_ll_enable(int ldo_unit, bool enable) { uint8_t index_array[LDO_LL_NUM_UNITS] = {0, 3, 1, 4}; + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100) && (ldo_unit == 0)) { + // If chip_rev >= v1.0, slp_mem_dbias[3] is used to control the volt output of VO1. + PMU.hp_sys[PMU_MODE_HP_ACTIVE].regulator0.xpd_0p1a = (enable ? 8 : 0); + } PMU.ext_ldo[index_array[ldo_unit]].pmu_ext_ldo.xpd = enable; } diff --git a/components/hal/esp32p4/include/hal/lp_core_ll.h b/components/hal/esp32p4/include/hal/lp_core_ll.h index 27a9a0997fa2..eb2c57be317f 100644 --- a/components/hal/esp32p4/include/hal/lp_core_ll.h +++ b/components/hal/esp32p4/include/hal/lp_core_ll.h @@ -28,7 +28,7 @@ extern "C" { #define LP_CORE_LL_WAKEUP_SOURCE_LP_BOD BIT(14) #define LP_CORE_LL_WAKEUP_SOURCE_ETM BIT(17) #define LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER_1 BIT(18) -#define LP_CORE_LL_WAKEUP_SOURCE_LP_I2S BIT(19) +#define LP_CORE_LL_WAKEUP_SOURCE_LP_VAD BIT(19) #define LP_CORE_LL_WAKEUP_SOURCE_HP_CPU BIT(22) /* Use lp timer 1 as the normal wakeup timer, timer 0 is used by deep sleep */ diff --git a/components/hal/esp32p4/include/hal/lp_i2s_ll.h b/components/hal/esp32p4/include/hal/lp_i2s_ll.h index c9f0d5611bd5..23e81cd2a5f2 100644 --- a/components/hal/esp32p4/include/hal/lp_i2s_ll.h +++ b/components/hal/esp32p4/include/hal/lp_i2s_ll.h @@ -32,6 +32,8 @@ extern "C" { #define LP_I2S_LL_EVENT_RX_DONE_INT (1<<0) #define LP_I2S_LL_EVENT_RX_HUNG_INT_INT (1<<1) #define LP_I2S_LL_EVENT_RX_FIFOMEM_UDF_INT (1<<2) +#define LP_I2S_LL_EVENT_VAD_DONE_INT (1<<3) +#define LP_I2S_LL_EVENT_VAD_RESET_DONE_INT (1<<4) #define LP_I2S_LL_EVENT_RX_MEM_THRESHOLD_INT (1<<5) #define LP_I2S_LL_TDM_CH_MASK (0x03UL) @@ -709,9 +711,9 @@ static inline uint32_t lp_i2s_ll_get_intr_status_reg_addr(lp_i2s_dev_t *hw) /** * @brief Enable LP I2S RX channel interrupt * - * @param hw LP I2S hardware instance - * @param mask mask - * @param enable enable or disable + * @param[in] hw LP I2S hardware instance + * @param[in] mask mask + * @param[in] enable enable or disable */ static inline void lp_i2s_ll_rx_enable_interrupt(lp_i2s_dev_t *hw, uint32_t mask, bool enable) { @@ -727,8 +729,8 @@ static inline void lp_i2s_ll_rx_enable_interrupt(lp_i2s_dev_t *hw, uint32_t mask /** * @brief Clear LP I2S RX channel interrupt * - * @param hw LP I2S hardware instance - * @param mask mask + * @param[in] hw LP I2S hardware instance + * @param[in] mask mask */ __attribute__((always_inline)) static inline void lp_i2s_ll_rx_clear_interrupt_status(lp_i2s_dev_t *hw, uint32_t mask) @@ -736,6 +738,100 @@ static inline void lp_i2s_ll_rx_clear_interrupt_status(lp_i2s_dev_t *hw, uint32_ hw->int_clr.val = mask; } +/*--------------------------------------------------------------- + VAD +---------------------------------------------------------------*/ +#define LP_VAD_LL_INIT_FRAME_MIN 100 +#define LP_VAD_LL_INIT_FRAME_MAX 200 + +/** + * @brief Set VAD init frame number + * + * @param[in] hw LP I2S hardware instance + * @param[in] frame_num Frame number + */ +static inline void lp_vad_ll_set_init_frame_num(lp_i2s_dev_t *hw, int frame_num) +{ + hw->vad_param0.param_init_frame_num = frame_num; +} + +/** + * @brief Set VAD min energy + * + * @param[in] hw LP I2S hardware instance + * @param[in] min_energy Min energy + */ +static inline void lp_vad_ll_set_init_min_energy(lp_i2s_dev_t *hw, int min_energy) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->vad_param0, param_min_energy, min_energy); +} + +/** + * @brief Set VAD speak activity thresh + * + * @param[in] hw LP I2S hardware instance + * @param[in] thresh Threshold + */ +static inline void lp_vad_ll_set_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) +{ + hw->vad_param1.param_hangover_speech = thresh; +} + +/** + * @brief Set VAD non speak activity thresh + * + * @param[in] hw LP I2S hardware instance + * @param[in] thresh Threshold + */ +static inline void lp_vad_ll_set_non_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) +{ + hw->vad_param1.param_hangover_silent = thresh; +} + +/** + * @brief Set VAD min speak activity thresh + * + * @param[in] hw LP I2S hardware instance + * @param[in] thresh Threshold + */ +static inline void lp_vad_ll_set_min_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) +{ + hw->vad_param1.param_min_speech_count = thresh; +} + +/** + * @brief Set VAD max speak activity thresh + * + * @param[in] hw LP I2S hardware instance + * @param[in] thresh Threshold + */ +static inline void lp_vad_ll_set_max_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) +{ + hw->vad_param1.param_max_speech_count = thresh; +} + +/** + * @brief Skip band energy check + * + * @param[in] hw LP I2S hardware instance + * @param[in] skip 1: skip; 0: not skip + */ +static inline void lp_vad_ll_skip_band_energy(lp_i2s_dev_t *hw, bool skip) +{ + hw->vad_param1.param_skip_band_energy = skip; +} + +/** + * @brief Enable LP I2S 24 fill + * + * @param[in] hw LP I2S hardware instance + * @param[in] en enable or disable + */ +static inline void lp_vad_ll_enable(lp_i2s_dev_t *hw, bool en) +{ + hw->vad_conf.vad_en = en; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h b/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h index f9cfe4e68557..78979e8453a3 100644 --- a/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h +++ b/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h @@ -170,23 +170,25 @@ static inline void mipi_dsi_brg_ll_credit_reset(dsi_brg_dev_t *dev) * @brief Set the color coding for the bridge controller * * @param dev Pointer to the DSI bridge controller register base address - * @param pixel_format Color coding + * @param color_coding Color coding value * @param sub_config Sub configuration */ -static inline void mipi_dsi_brg_ll_set_pixel_format(dsi_brg_dev_t *dev, lcd_color_rgb_pixel_format_t pixel_format, uint32_t sub_config) +static inline void mipi_dsi_brg_ll_set_pixel_format(dsi_brg_dev_t *dev, lcd_color_format_t color_coding, uint32_t sub_config) { - switch (pixel_format) { - case LCD_COLOR_PIXEL_FORMAT_RGB565: + switch (color_coding) { + case LCD_COLOR_FMT_RGB565: dev->pixel_type.raw_type = 2; break; - case LCD_COLOR_PIXEL_FORMAT_RGB666: + case LCD_COLOR_FMT_RGB666: dev->pixel_type.raw_type = 1; break; - case LCD_COLOR_PIXEL_FORMAT_RGB888: + case LCD_COLOR_FMT_RGB888: dev->pixel_type.raw_type = 0; break; default: - abort(); + // MIPI DSI host can only accept RGB data, no YUV data + HAL_ASSERT(false); + break; } dev->pixel_type.dpi_config = sub_config; } @@ -344,6 +346,36 @@ static inline void mipi_dsi_brg_ll_set_yuv_convert_std(dsi_brg_dev_t *dev, lcd_y } } +/** + * @brief Set the YUV422 packing order + * + * @param dev Pointer to the DSI bridge controller register base address + * @param order YUV422 packing order + */ +static inline void mipi_dsi_brg_ll_set_yuv422_pack_order(dsi_brg_dev_t *dev, lcd_yuv422_pack_order_t order) +{ + switch (order) { + case LCD_YUV422_PACK_ORDER_UYVY: + dev->yuv_cfg.yuv422_format = 0; + dev->yuv_cfg.yuv_pix_endian = 1; + break; + case LCD_YUV422_PACK_ORDER_VYUY: + dev->yuv_cfg.yuv422_format = 1; + dev->yuv_cfg.yuv_pix_endian = 1; + break; + case LCD_YUV422_PACK_ORDER_YUYV: + dev->yuv_cfg.yuv422_format = 2; + dev->yuv_cfg.yuv_pix_endian = 1; + break; + case LCD_YUV422_PACK_ORDER_YVYU: + dev->yuv_cfg.yuv422_format = 3; + dev->yuv_cfg.yuv_pix_endian = 1; + break; + default: + abort(); + } +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/mipi_dsi_host_ll.h b/components/hal/esp32p4/include/hal/mipi_dsi_host_ll.h index e88ea9e7a51c..c1a295959912 100644 --- a/components/hal/esp32p4/include/hal/mipi_dsi_host_ll.h +++ b/components/hal/esp32p4/include/hal/mipi_dsi_host_ll.h @@ -181,19 +181,20 @@ static inline void mipi_dsi_host_ll_dpi_set_vcid(dsi_host_dev_t *dev, uint32_t v * @param color_coding Color coding value * @param sub_config Sub configuration value */ -static inline void mipi_dsi_host_ll_dpi_set_color_coding(dsi_host_dev_t *dev, lcd_color_rgb_pixel_format_t color_coding, uint32_t sub_config) +static inline void mipi_dsi_host_ll_dpi_set_color_coding(dsi_host_dev_t *dev, lcd_color_format_t color_coding, uint32_t sub_config) { switch (color_coding) { - case LCD_COLOR_PIXEL_FORMAT_RGB565: + case LCD_COLOR_FMT_RGB565: dev->dpi_color_coding.dpi_color_coding = MIPI_DSI_LL_COLOR_CODE_16BIT_CONFIG1 + sub_config; break; - case LCD_COLOR_PIXEL_FORMAT_RGB666: + case LCD_COLOR_FMT_RGB666: dev->dpi_color_coding.dpi_color_coding = MIPI_DSI_LL_COLOR_CODE_18BIT_CONFIG1 + sub_config; break; - case LCD_COLOR_PIXEL_FORMAT_RGB888: + case LCD_COLOR_FMT_RGB888: dev->dpi_color_coding.dpi_color_coding = MIPI_DSI_LL_COLOR_CODE_24BIT; break; default: + // MIPI DSI bridge can only write RGB data to the DSI host controller, no YUV data HAL_ASSERT(false); break; } diff --git a/components/hal/esp32p4/include/hal/pmu_ll.h b/components/hal/esp32p4/include/hal/pmu_ll.h index 0378fbaf4213..f64b60cccda9 100644 --- a/components/hal/esp32p4/include/hal/pmu_ll.h +++ b/components/hal/esp32p4/include/hal/pmu_ll.h @@ -216,9 +216,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_dbias(pmu_dev_t *hw, hw->hp_sys[mode].regulator0.slp_logic_dbias = slp_dbias; } -FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias) +FORCE_INLINE_ATTR void pmu_ll_hp_enable_sleep_flash_ldo_channel(pmu_dev_t *hw, bool enable) { - hw->hp_sys[mode].regulator0.slp_mem_dbias = slp_dbias; + // slp_mem_dbias[3] is used to control the volt output of VO1 for chip_revision >= 100, + // and this field is not used for chip_revision < 100. + hw->hp_sys[PMU_MODE_HP_SLEEP].regulator0.xpd_0p1a = (enable ? 8 : 0); } FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t dbias) diff --git a/components/hal/esp32p4/include/hal/ppa_ll.h b/components/hal/esp32p4/include/hal/ppa_ll.h index 60facd94fec5..1d82fdce92ab 100644 --- a/components/hal/esp32p4/include/hal/ppa_ll.h +++ b/components/hal/esp32p4/include/hal/ppa_ll.h @@ -24,8 +24,8 @@ extern "C" { #define PPA_LL_BLEND0_CLUT_MEM_ADDR_OFFSET 0x400 #define PPA_LL_BLEND1_CLUT_MEM_ADDR_OFFSET 0x800 -#define PPA_LL_SRM_SCALING_INT_MAX PPA_SR_SCAL_X_INT_V -#define PPA_LL_SRM_SCALING_FRAG_MAX PPA_SR_SCAL_X_FRAG_V +#define PPA_LL_SRM_SCALING_INT_MAX (PPA_SR_SCAL_X_INT_V + 1) +#define PPA_LL_SRM_SCALING_FRAG_MAX (PPA_SR_SCAL_X_FRAG_V + 1) // TODO: On P4 ECO2, SRM block size needs update #define PPA_LL_SRM_DEFAULT_BLOCK_SIZE 18 // 18 x 18 block size diff --git a/components/hal/esp32p4/include/hal/rmt_ll.h b/components/hal/esp32p4/include/hal/rmt_ll.h index affcc3eeacd9..105aa426925e 100644 --- a/components/hal/esp32p4/include/hal/rmt_ll.h +++ b/components/hal/esp32p4/include/hal/rmt_ll.h @@ -33,8 +33,6 @@ extern "C" { #define RMT_LL_EVENT_TX_MASK(channel) (RMT_LL_EVENT_TX_DONE(channel) | RMT_LL_EVENT_TX_THRES(channel) | RMT_LL_EVENT_TX_LOOP_END(channel)) #define RMT_LL_EVENT_RX_MASK(channel) (RMT_LL_EVENT_RX_DONE(channel) | RMT_LL_EVENT_RX_THRES(channel)) -#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0) - #define RMT_LL_MAX_LOOP_COUNT_PER_BATCH 1023 #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 diff --git a/components/hal/esp32p4/include/hal/uart_ll.h b/components/hal/esp32p4/include/hal/uart_ll.h index 9b62cea267d7..886cb757e76f 100644 --- a/components/hal/esp32p4/include/hal/uart_ll.h +++ b/components/hal/esp32p4/include/hal/uart_ll.h @@ -45,13 +45,6 @@ extern "C" { #define UART_LL_FSM_IDLE (0x0) #define UART_LL_FSM_TX_WAIT_SEND (0xf) -// UART sleep retention module -#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ - (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : \ - (uart_num == UART_NUM_2) ? SLEEP_RETENTION_MODULE_UART2 : \ - (uart_num == UART_NUM_3) ? SLEEP_RETENTION_MODULE_UART3 : \ - (uart_num == UART_NUM_4) ? SLEEP_RETENTION_MODULE_UART4 : -1) - // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), diff --git a/components/hal/include/hal/usb_dwc_ll.h b/components/hal/esp32p4/include/hal/usb_dwc_ll.h similarity index 97% rename from components/hal/include/hal/usb_dwc_ll.h rename to components/hal/esp32p4/include/hal/usb_dwc_ll.h index 49ade5040512..f93db6623c85 100644 --- a/components/hal/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32p4/include/hal/usb_dwc_ll.h @@ -6,25 +6,22 @@ #pragma once -#include "soc/soc_caps.h" -/* -This header is shared across all targets. Resolve to an empty header for targets -that don't support USB OTG. -*/ -#if SOC_USB_OTG_SUPPORTED #include #include #include "soc/usb_dwc_struct.h" #include "soc/usb_dwc_cfg.h" #include "hal/usb_dwc_types.h" #include "hal/misc.h" -#endif // SOC_USB_OTG_SUPPORTED #ifdef __cplusplus extern "C" { #endif -#if SOC_USB_OTG_SUPPORTED +/* ----------------------------- Helper Macros ------------------------------ */ + +// Get USB hardware instance +// TODO: extend this macros when we have support for both FS and HS hardware on P4 +#define USB_DWC_LL_GET_HW(num) (&USB_DWC_HS) /* ----------------------------------------------------------------------------- --------------------------------- DWC Constants -------------------------------- @@ -222,14 +219,14 @@ static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t hw->gusbcfg_reg.toutcal = tout_cal; } -#if (OTG_HSPHY_INTERFACE != 0) static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw) { +#if (OTG_HSPHY_INTERFACE != 0) hw->gusbcfg_reg.phyif = 1; // 16 bits interface hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+ hw->gusbcfg_reg.physel = 0; // HS PHY -} #endif // (OTG_HSPHY_INTERFACE != 0) +} // --------------------------- GRSTCTL Register -------------------------------- @@ -356,9 +353,9 @@ static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw) // --------------------------- GHWCFGx Register -------------------------------- /** - * @brief Get the hardware configuration regiters of the DWC_OTG controller + * @brief Get the hardware configuration registers of the DWC_OTG controller * - * The hardware configuraiton regitsers are read only and indicate the various + * The hardware configuration regitsers are read only and indicate the various * features of the DWC_OTG core. * * @param hw Start address of the DWC_OTG registers @@ -405,7 +402,7 @@ static inline void usb_dwc_ll_hcfg_dis_perio_sched(usb_dwc_dev_t *hw) /** * Sets the length of the frame list * - * @param num_entires Number of entires in the frame list + * @param num_entires Number of entries in the frame list */ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw, usb_hal_frame_list_len_t num_entries) { @@ -903,7 +900,7 @@ static inline usb_dwc_host_chan_regs_t *usb_dwc_ll_chan_get_regs(usb_dwc_dev_t * // ------------------------------ QTD related ---------------------------------- #define USB_DWC_LL_QTD_STATUS_SUCCESS 0x0 //If QTD was processed, it indicates the data was transmitted/received successfully -#define USB_DWC_LL_QTD_STATUS_PKTERR 0x1 //Data trasnmitted/received with errors (CRC/Timeout/Stuff/False EOP/Excessive NAK). +#define USB_DWC_LL_QTD_STATUS_PKTERR 0x1 //Data transmitted/received with errors (CRC/Timeout/Stuff/False EOP/Excessive NAK). //Note: 0x2 is reserved #define USB_DWC_LL_QTD_STATUS_BUFFER 0x3 //AHB error occurred. #define USB_DWC_LL_QTD_STATUS_NOT_EXECUTED 0x4 //QTD as never processed @@ -914,7 +911,7 @@ static inline usb_dwc_host_chan_regs_t *usb_dwc_ll_chan_get_regs(usb_dwc_dev_t * * @param qtd Pointer to the QTD * @param data_buff Pointer to buffer containing the data to transfer * @param xfer_len Number of bytes in transfer. Setting 0 will do a zero length IN transfer. - * Non zero length must be mulitple of the endpoint's MPS. + * Non zero length must be multiple of the endpoint's MPS. * @param hoc Halt on complete (will generate an interrupt and halt the channel) */ static inline void usb_dwc_ll_qtd_set_in(usb_dwc_ll_dma_qtd_t *qtd, uint8_t *data_buff, int xfer_len, bool hoc) @@ -932,7 +929,7 @@ static inline void usb_dwc_ll_qtd_set_in(usb_dwc_ll_dma_qtd_t *qtd, uint8_t *dat /** * @brief Set a QTD for a non isochronous OUT transfer * - * @param qtd Poitner to the QTD + * @param qtd Pointer to the QTD * @param data_buff Pointer to buffer containing the data to transfer * @param xfer_len Number of bytes to transfer. Setting 0 will do a zero length transfer. * For ctrl setup packets, this should be set to 8. @@ -972,9 +969,9 @@ static inline void usb_dwc_ll_qtd_set_null(usb_dwc_ll_dma_qtd_t *qtd) /** * @brief Get the status of a QTD * - * When a channel get's halted, call this to check whether each QTD was executed successfully + * When a channel gets halted, call this to check whether each QTD was executed successfully * - * @param qtd Poitner to the QTD + * @param qtd Pointer to the QTD * @param[out] rem_len Number of bytes ramining in the QTD * @param[out] status Status of the QTD */ @@ -992,8 +989,6 @@ static inline void usb_dwc_ll_qtd_get_status(usb_dwc_ll_dma_qtd_t *qtd, int *rem qtd->buffer_status_val = 0; } -#endif // SOC_USB_OTG_SUPPORTED - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/usb_utmi_ll.h b/components/hal/esp32p4/include/hal/usb_utmi_ll.h index 14eb8fd17668..f2ea99d8b6bc 100644 --- a/components/hal/esp32p4/include/hal/usb_utmi_ll.h +++ b/components/hal/esp32p4/include/hal/usb_utmi_ll.h @@ -53,7 +53,7 @@ FORCE_INLINE_ATTR void _usb_utmi_ll_enable_bus_clock(bool clk_en) /** * @brief Reset the USB UTMI PHY and USB_DWC_HS controller */ -FORCE_INLINE_ATTR void usb_utmi_ll_reset_register(void) +FORCE_INLINE_ATTR void _usb_utmi_ll_reset_register(void) { // Reset the USB_UTMI and USB_DWC_HS LP_AON_CLKRST.hp_usb_clkrst_ctrl1.rst_en_usb_otg20 = 1; @@ -63,7 +63,7 @@ FORCE_INLINE_ATTR void usb_utmi_ll_reset_register(void) } // P_AON_CLKRST.hp_usb_clkrst_ctrlx is shared register, so this function must be used in an atomic way -#define usb_utmi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_utmi_ll_reset_register(__VA_ARGS__) +#define usb_utmi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_utmi_ll_reset_register(__VA_ARGS__) /** * @brief Enable precise detection of VBUS diff --git a/components/hal/esp32s2/include/hal/gpio_ll.h b/components/hal/esp32s2/include/hal/gpio_ll.h index 382cc455ad53..233b86c3677b 100644 --- a/components/hal/esp32s2/include/hal/gpio_ll.h +++ b/components/hal/esp32s2/include/hal/gpio_ll.h @@ -338,15 +338,15 @@ static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t { if (level) { if (gpio_num < 32) { - hw->out_w1ts = (1 << gpio_num); + hw->out_w1ts = 1 << gpio_num; } else { - hw->out1_w1ts.data = (1 << (gpio_num - 32)); + hw->out1_w1ts.val = 1 << (gpio_num - 32); } } else { if (gpio_num < 32) { - hw->out_w1tc = (1 << gpio_num); + hw->out_w1tc = 1 << gpio_num; } else { - hw->out1_w1tc.data = (1 << (gpio_num - 32)); + hw->out1_w1tc.val = 1 << (gpio_num - 32); } } } diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 8ae76c41cd20..a5221fbc5c3b 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -90,18 +90,11 @@ static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en) */ static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) { + (void) i2s_id; if (enable) { - if (i2s_id == 0) { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); - } else { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); - } + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); } else { - if (i2s_id == 0) { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); - } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); - } + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); } } @@ -116,13 +109,9 @@ static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) */ static inline void i2s_ll_reset_register(int i2s_id) { - if (i2s_id == 0) { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); - } else { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); - } + (void) i2s_id; + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); } /// use a macro to wrap the function, force the caller to use it in a critical section @@ -341,11 +330,6 @@ static inline void i2s_ll_set_raw_mclk_div(i2s_dev_t *hw, uint32_t mclk_div, uin */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that unlike to calculate from the regular decimal */ - i2s_ll_set_raw_mclk_div(hw, 7, 47, 3); i2s_ll_set_raw_mclk_div(hw, mclk_div->integer, mclk_div->denominator, mclk_div->numerator); } @@ -362,7 +346,7 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) /** * @brief Configure I2S RX module clock divider - * @note mclk on ESP32 is shared by both TX and RX channel + * @note mclk on ESP32S2 is shared by both TX and RX channel * * @param hw Peripheral I2S hardware instance address. * @param mclk_div The mclk division coefficients @@ -682,7 +666,7 @@ static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, uint32_t eof_num) } /** - * @brief Congfigure TX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit + * @brief Configure TX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -695,7 +679,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int } /** - * @brief Congfigure RX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit + * @brief Configure RX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width diff --git a/components/hal/esp32s2/include/hal/usb_dwc_ll.h b/components/hal/esp32s2/include/hal/usb_dwc_ll.h new file mode 100644 index 000000000000..954a54bf8037 --- /dev/null +++ b/components/hal/esp32s2/include/hal/usb_dwc_ll.h @@ -0,0 +1,993 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/usb_dwc_struct.h" +#include "soc/usb_dwc_cfg.h" +#include "hal/usb_dwc_types.h" +#include "hal/misc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------- Helper Macros ------------------------------ */ + +// Get USB hardware instance +#define USB_DWC_LL_GET_HW(num) (&USB_DWC) + +/* ----------------------------------------------------------------------------- +--------------------------------- DWC Constants -------------------------------- +----------------------------------------------------------------------------- */ + +#define USB_DWC_QTD_LIST_MEM_ALIGN 512 +#define USB_DWC_FRAME_LIST_MEM_ALIGN 512 // The frame list needs to be 512 bytes aligned (contrary to the databook) + +/* ----------------------------------------------------------------------------- +------------------------------- Global Registers ------------------------------- +----------------------------------------------------------------------------- */ + +/* + * Interrupt bit masks of the GINTSTS and GINTMSK registers + */ +#define USB_DWC_LL_INTR_CORE_WKUPINT (1 << 31) +#define USB_DWC_LL_INTR_CORE_SESSREQINT (1 << 30) +#define USB_DWC_LL_INTR_CORE_DISCONNINT (1 << 29) +#define USB_DWC_LL_INTR_CORE_CONIDSTSCHNG (1 << 28) +#define USB_DWC_LL_INTR_CORE_PTXFEMP (1 << 26) +#define USB_DWC_LL_INTR_CORE_HCHINT (1 << 25) +#define USB_DWC_LL_INTR_CORE_PRTINT (1 << 24) +#define USB_DWC_LL_INTR_CORE_RESETDET (1 << 23) +#define USB_DWC_LL_INTR_CORE_FETSUSP (1 << 22) +#define USB_DWC_LL_INTR_CORE_INCOMPIP (1 << 21) +#define USB_DWC_LL_INTR_CORE_INCOMPISOIN (1 << 20) +#define USB_DWC_LL_INTR_CORE_OEPINT (1 << 19) +#define USB_DWC_LL_INTR_CORE_IEPINT (1 << 18) +#define USB_DWC_LL_INTR_CORE_EPMIS (1 << 17) +#define USB_DWC_LL_INTR_CORE_EOPF (1 << 15) +#define USB_DWC_LL_INTR_CORE_ISOOUTDROP (1 << 14) +#define USB_DWC_LL_INTR_CORE_ENUMDONE (1 << 13) +#define USB_DWC_LL_INTR_CORE_USBRST (1 << 12) +#define USB_DWC_LL_INTR_CORE_USBSUSP (1 << 11) +#define USB_DWC_LL_INTR_CORE_ERLYSUSP (1 << 10) +#define USB_DWC_LL_INTR_CORE_GOUTNAKEFF (1 << 7) +#define USB_DWC_LL_INTR_CORE_GINNAKEFF (1 << 6) +#define USB_DWC_LL_INTR_CORE_NPTXFEMP (1 << 5) +#define USB_DWC_LL_INTR_CORE_RXFLVL (1 << 4) +#define USB_DWC_LL_INTR_CORE_SOF (1 << 3) +#define USB_DWC_LL_INTR_CORE_OTGINT (1 << 2) +#define USB_DWC_LL_INTR_CORE_MODEMIS (1 << 1) +#define USB_DWC_LL_INTR_CORE_CURMOD (1 << 0) + +/* + * Bit mask of interrupt generating bits of the the HPRT register. These bits + * are ORd into the USB_DWC_LL_INTR_CORE_PRTINT interrupt. + * + * Note: Some fields of the HPRT are W1C (write 1 clear), this we cannot do a + * simple read and write-back to clear the HPRT interrupt bits. Instead we need + * a W1C mask the non-interrupt related bits + */ +#define USB_DWC_LL_HPRT_W1C_MSK (0x2E) +#define USB_DWC_LL_HPRT_ENA_MSK (0x04) +#define USB_DWC_LL_INTR_HPRT_PRTOVRCURRCHNG (1 << 5) +#define USB_DWC_LL_INTR_HPRT_PRTENCHNG (1 << 3) +#define USB_DWC_LL_INTR_HPRT_PRTCONNDET (1 << 1) + +/* + * Bit mask of channel interrupts (HCINTi and HCINTMSKi registers) + * + * Note: Under Scatter/Gather DMA mode, only the following interrupts can be unmasked + * - DESC_LS_ROLL + * - XCS_XACT_ERR (always unmasked) + * - BNAINTR + * - CHHLTD + * - XFERCOMPL + * The remaining interrupt bits will still be set (when the corresponding event occurs) + * but will not generate an interrupt. Therefore we must proxy through the + * USB_DWC_LL_INTR_CHAN_CHHLTD interrupt to check the other interrupt bits. + */ +#define USB_DWC_LL_INTR_CHAN_DESC_LS_ROLL (1 << 13) +#define USB_DWC_LL_INTR_CHAN_XCS_XACT_ERR (1 << 12) +#define USB_DWC_LL_INTR_CHAN_BNAINTR (1 << 11) +#define USB_DWC_LL_INTR_CHAN_DATATGLERR (1 << 10) +#define USB_DWC_LL_INTR_CHAN_FRMOVRUN (1 << 9) +#define USB_DWC_LL_INTR_CHAN_BBLEER (1 << 8) +#define USB_DWC_LL_INTR_CHAN_XACTERR (1 << 7) +#define USB_DWC_LL_INTR_CHAN_NYET (1 << 6) +#define USB_DWC_LL_INTR_CHAN_ACK (1 << 5) +#define USB_DWC_LL_INTR_CHAN_NAK (1 << 4) +#define USB_DWC_LL_INTR_CHAN_STALL (1 << 3) +#define USB_DWC_LL_INTR_CHAN_AHBERR (1 << 2) +#define USB_DWC_LL_INTR_CHAN_CHHLTD (1 << 1) +#define USB_DWC_LL_INTR_CHAN_XFERCOMPL (1 << 0) + +/* + * QTD (Queue Transfer Descriptor) structure used in Scatter/Gather DMA mode. + * Each QTD describes one transfer. Scatter gather mode will automatically split + * a transfer into multiple MPS packets. Each QTD is 64bits in size + * + * Note: The status information part of the QTD is interpreted differently depending + * on IN or OUT, and ISO or non-ISO + */ +typedef struct { + union { + struct { + uint32_t xfer_size: 17; + uint32_t aqtd_offset: 6; + uint32_t aqtd_valid: 1; + uint32_t reserved_24: 1; + uint32_t intr_cplt: 1; + uint32_t eol: 1; + uint32_t reserved_27: 1; + uint32_t rx_status: 2; + uint32_t reserved_30: 1; + uint32_t active: 1; + } in_non_iso; + struct { + uint32_t xfer_size: 12; + uint32_t reserved_12_24: 13; + uint32_t intr_cplt: 1; + uint32_t reserved_26_27: 2; + uint32_t rx_status: 2; + uint32_t reserved_30: 1; + uint32_t active: 1; + } in_iso; + struct { + uint32_t xfer_size: 17; + uint32_t reserved_17_23: 7; + uint32_t is_setup: 1; + uint32_t intr_cplt: 1; + uint32_t eol: 1; + uint32_t reserved_27: 1; + uint32_t tx_status: 2; + uint32_t reserved_30: 1; + uint32_t active: 1; + } out_non_iso; + struct { + uint32_t xfer_size: 12; + uint32_t reserved_12_24: 13; + uint32_t intr_cplt: 1; + uint32_t eol: 1; + uint32_t reserved_27: 1; + uint32_t tx_status: 2; + uint32_t reserved_30: 1; + uint32_t active: 1; + } out_iso; + uint32_t buffer_status_val; + }; + uint8_t *buffer; +} usb_dwc_ll_dma_qtd_t; + + +/* ----------------------------------------------------------------------------- +------------------------------- Global Registers ------------------------------- +----------------------------------------------------------------------------- */ + +// --------------------------- GAHBCFG Register -------------------------------- + +static inline void usb_dwc_ll_gahbcfg_en_dma_mode(usb_dwc_dev_t *hw) +{ + hw->gahbcfg_reg.dmaen = 1; +} + +static inline void usb_dwc_ll_gahbcfg_en_slave_mode(usb_dwc_dev_t *hw) +{ + hw->gahbcfg_reg.dmaen = 0; +} + +static inline void usb_dwc_ll_gahbcfg_set_hbstlen(usb_dwc_dev_t *hw, uint32_t burst_len) +{ + hw->gahbcfg_reg.hbstlen = burst_len; +} + +static inline void usb_dwc_ll_gahbcfg_en_global_intr(usb_dwc_dev_t *hw) +{ + hw->gahbcfg_reg.glbllntrmsk = 1; +} + +static inline void usb_dwc_ll_gahbcfg_dis_global_intr(usb_dwc_dev_t *hw) +{ + hw->gahbcfg_reg.glbllntrmsk = 0; +} + +// --------------------------- GUSBCFG Register -------------------------------- + +static inline void usb_dwc_ll_gusbcfg_force_host_mode(usb_dwc_dev_t *hw) +{ + hw->gusbcfg_reg.forcehstmode = 1; +} + +static inline void usb_dwc_ll_gusbcfg_dis_hnp_cap(usb_dwc_dev_t *hw) +{ + hw->gusbcfg_reg.hnpcap = 0; +} + +static inline void usb_dwc_ll_gusbcfg_dis_srp_cap(usb_dwc_dev_t *hw) +{ + hw->gusbcfg_reg.srpcap = 0; +} + +static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t tout_cal) +{ + hw->gusbcfg_reg.toutcal = tout_cal; +} + +static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw) +{ +#if (OTG_HSPHY_INTERFACE != 0) + hw->gusbcfg_reg.phyif = 1; // 16 bits interface + hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+ + hw->gusbcfg_reg.physel = 0; // HS PHY +#endif // (OTG_HSPHY_INTERFACE != 0) +} + +// --------------------------- GRSTCTL Register -------------------------------- + +static inline bool usb_dwc_ll_grstctl_is_ahb_idle(usb_dwc_dev_t *hw) +{ + return hw->grstctl_reg.ahbidle; +} + +static inline bool usb_dwc_ll_grstctl_is_dma_req_in_progress(usb_dwc_dev_t *hw) +{ + return hw->grstctl_reg.dmareq; +} + +static inline void usb_dwc_ll_grstctl_flush_nptx_fifo(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.txfnum = 0; //Set the TX FIFO number to 0 to select the non-periodic TX FIFO + hw->grstctl_reg.txfflsh = 1; //Flush the selected TX FIFO + //Wait for the flushing to complete + while (hw->grstctl_reg.txfflsh) { + ; + } +} + +static inline void usb_dwc_ll_grstctl_flush_ptx_fifo(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.txfnum = 1; //Set the TX FIFO number to 1 to select the periodic TX FIFO + hw->grstctl_reg.txfflsh = 1; //FLush the select TX FIFO + //Wait for the flushing to complete + while (hw->grstctl_reg.txfflsh) { + ; + } +} + +static inline void usb_dwc_ll_grstctl_flush_rx_fifo(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.rxfflsh = 1; + //Wait for the flushing to complete + while (hw->grstctl_reg.rxfflsh) { + ; + } +} + +static inline void usb_dwc_ll_grstctl_reset_frame_counter(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.frmcntrrst = 1; +} + +static inline void usb_dwc_ll_grstctl_core_soft_reset(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.csftrst = 1; +} + +static inline bool usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(usb_dwc_dev_t *hw) +{ + return hw->grstctl_reg.csftrst; +} + +// --------------------------- GINTSTS Register -------------------------------- + +/** + * @brief Reads and clears the global interrupt register + * + * @param hw Start address of the DWC_OTG registers + * @return uint32_t Mask of interrupts + */ +static inline uint32_t usb_dwc_ll_gintsts_read_and_clear_intrs(usb_dwc_dev_t *hw) +{ + usb_dwc_gintsts_reg_t gintsts; + gintsts.val = hw->gintsts_reg.val; + hw->gintsts_reg.val = gintsts.val; //Write back to clear + return gintsts.val; +} + +/** + * @brief Clear specific interrupts + * + * @param hw Start address of the DWC_OTG registers + * @param intr_msk Mask of interrupts to clear + */ +static inline void usb_dwc_ll_gintsts_clear_intrs(usb_dwc_dev_t *hw, uint32_t intr_msk) +{ + //All GINTSTS fields are either W1C or read only. So safe to write directly + hw->gintsts_reg.val = intr_msk; +} + +// --------------------------- GINTMSK Register -------------------------------- + +static inline void usb_dwc_ll_gintmsk_en_intrs(usb_dwc_dev_t *hw, uint32_t intr_mask) +{ + hw->gintmsk_reg.val |= intr_mask; +} + +static inline void usb_dwc_ll_gintmsk_dis_intrs(usb_dwc_dev_t *hw, uint32_t intr_mask) +{ + hw->gintmsk_reg.val &= ~intr_mask; +} + +// --------------------------- GRXFSIZ Register -------------------------------- + +static inline void usb_dwc_ll_grxfsiz_set_fifo_size(usb_dwc_dev_t *hw, uint32_t num_lines) +{ + //Set size in words + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->grxfsiz_reg, rxfdep, num_lines); +} + +// -------------------------- GNPTXFSIZ Register ------------------------------- + +static inline void usb_dwc_ll_gnptxfsiz_set_fifo_size(usb_dwc_dev_t *hw, uint32_t addr, uint32_t num_lines) +{ + usb_dwc_gnptxfsiz_reg_t gnptxfsiz; + gnptxfsiz.val = hw->gnptxfsiz_reg.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(gnptxfsiz, nptxfstaddr, addr); + HAL_FORCE_MODIFY_U32_REG_FIELD(gnptxfsiz, nptxfdep, num_lines); + hw->gnptxfsiz_reg.val = gnptxfsiz.val; +} + +// --------------------------- GSNPSID Register -------------------------------- + +static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw) +{ + return hw->gsnpsid_reg.val; +} + +// --------------------------- GHWCFGx Register -------------------------------- + +/** + * @brief Get the hardware configuration registers of the DWC_OTG controller + * + * The hardware configuration regitsers are read only and indicate the various + * features of the DWC_OTG core. + * + * @param hw Start address of the DWC_OTG registers + * @param[out] ghwcfg1 Hardware configuration registesr 1 + * @param[out] ghwcfg2 Hardware configuration registesr 2 + * @param[out] ghwcfg3 Hardware configuration registesr 3 + * @param[out] ghwcfg4 Hardware configuration registesr 4 + */ +static inline void usb_dwc_ll_ghwcfg_get_hw_config(usb_dwc_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4) +{ + *ghwcfg1 = hw->ghwcfg1_reg.val; + *ghwcfg2 = hw->ghwcfg2_reg.val; + *ghwcfg3 = hw->ghwcfg3_reg.val; + *ghwcfg4 = hw->ghwcfg4_reg.val; +} + +// --------------------------- HPTXFSIZ Register ------------------------------- + +static inline void usb_dwc_ll_hptxfsiz_set_ptx_fifo_size(usb_dwc_dev_t *hw, uint32_t addr, uint32_t num_lines) +{ + usb_dwc_hptxfsiz_reg_t hptxfsiz; + hptxfsiz.val = hw->hptxfsiz_reg.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(hptxfsiz, ptxfstaddr, addr); + HAL_FORCE_MODIFY_U32_REG_FIELD(hptxfsiz, ptxfsize, num_lines); + hw->hptxfsiz_reg.val = hptxfsiz.val; +} + +/* ----------------------------------------------------------------------------- +-------------------------------- Host Registers -------------------------------- +----------------------------------------------------------------------------- */ + +// ----------------------------- HCFG Register --------------------------------- + +static inline void usb_dwc_ll_hcfg_en_perio_sched(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.perschedena = 1; +} + +static inline void usb_dwc_ll_hcfg_dis_perio_sched(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.perschedena = 0; +} + +/** + * Sets the length of the frame list + * + * @param num_entires Number of entries in the frame list + */ +static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw, usb_hal_frame_list_len_t num_entries) +{ + uint32_t frlisten; + switch (num_entries) { + case USB_HAL_FRAME_LIST_LEN_8: + frlisten = 0; + break; + case USB_HAL_FRAME_LIST_LEN_16: + frlisten = 1; + break; + case USB_HAL_FRAME_LIST_LEN_32: + frlisten = 2; + break; + default: //USB_HAL_FRAME_LIST_LEN_64 + frlisten = 3; + break; + } + hw->hcfg_reg.frlisten = frlisten; +} + +static inline void usb_dwc_ll_hcfg_en_scatt_gatt_dma(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.descdma = 1; +} + +static inline void usb_dwc_ll_hcfg_set_fsls_supp_only(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.fslssupp = 1; +} + +static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.fslspclksel = 1; +} + +/** + * @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA + * + * @param[in] hw Start address of the DWC_OTG registers + * @param[in] speed Speed to initialize the host port at + */ +static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +{ + hw->hcfg_reg.descdma = 1; //Enable scatt/gatt +#if (OTG_HSPHY_INTERFACE == 0) + /* + Indicate to the OTG core what speed the PHY clock is at + Note: It seems like S2/S3 PHY has an implicit 8 divider applied when in LS mode, + so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. + */ + hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only +#endif // (OTG_HSPHY_INTERFACE == 0) + hw->hcfg_reg.perschedena = 0; //Disable perio sched +} + +// ----------------------------- HFIR Register --------------------------------- + +static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +{ +#if (OTG_HSPHY_INTERFACE == 0) + usb_dwc_hfir_reg_t hfir; + hfir.val = hw->hfir_reg.val; + hfir.hfirrldctrl = 0; //Disable dynamic loading + /* + Set frame interval to be equal to 1ms + Note: It seems like our PHY has an implicit 8 divider applied when in LS mode, + so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. + */ + hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS + hw->hfir_reg.val = hfir.val; +#endif // (OTG_HSPHY_INTERFACE == 0) +} + +// ----------------------------- HFNUM Register -------------------------------- + +static inline uint32_t usb_dwc_ll_hfnum_get_frame_time_rem(usb_dwc_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->hfnum_reg, frrem); +} + +static inline uint32_t usb_dwc_ll_hfnum_get_frame_num(usb_dwc_dev_t *hw) +{ + return hw->hfnum_reg.frnum; +} + +// ---------------------------- HPTXSTS Register ------------------------------- + +static inline uint32_t usb_dwc_ll_hptxsts_get_ptxq_top(usb_dwc_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->hptxsts_reg, ptxqtop); +} + +static inline uint32_t usb_dwc_ll_hptxsts_get_ptxq_space_avail(usb_dwc_dev_t *hw) +{ + return hw->hptxsts_reg.ptxqspcavail; +} + +static inline uint32_t usb_dwc_ll_ptxsts_get_ptxf_space_avail(usb_dwc_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->hptxsts_reg, ptxfspcavail); +} + +// ----------------------------- HAINT Register -------------------------------- + +static inline uint32_t usb_dwc_ll_haint_get_chan_intrs(usb_dwc_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->haint_reg, haint); +} + +// --------------------------- HAINTMSK Register ------------------------------- + +static inline void usb_dwc_ll_haintmsk_en_chan_intr(usb_dwc_dev_t *hw, uint32_t mask) +{ + + hw->haintmsk_reg.val |= mask; +} + +static inline void usb_dwc_ll_haintmsk_dis_chan_intr(usb_dwc_dev_t *hw, uint32_t mask) +{ + hw->haintmsk_reg.val &= ~mask; +} + +// --------------------------- HFLBAddr Register ------------------------------- + +/** + * @brief Set the base address of the scheduling frame list + * + * @note For some reason, this address must be 512 bytes aligned or else a bunch of frames will not be scheduled when + * the frame list rolls over. However, according to the databook, there is no mention of the HFLBAddr needing to + * be aligned. + * + * @param hw Start address of the DWC_OTG registers + * @param addr Base address of the scheduling frame list + */ +static inline void usb_dwc_ll_hflbaddr_set_base_addr(usb_dwc_dev_t *hw, uint32_t addr) +{ + hw->hflbaddr_reg.hflbaddr = addr; +} + +/** + * @brief Get the base address of the scheduling frame list + * + * @param hw Start address of the DWC_OTG registers + * @return uint32_t Base address of the scheduling frame list + */ +static inline uint32_t usb_dwc_ll_hflbaddr_get_base_addr(usb_dwc_dev_t *hw) +{ + return hw->hflbaddr_reg.hflbaddr; +} + +// ----------------------------- HPRT Register --------------------------------- + +static inline usb_dwc_speed_t usb_dwc_ll_hprt_get_speed(usb_dwc_dev_t *hw) +{ + return (usb_dwc_speed_t)hw->hprt_reg.prtspd; +} + +static inline uint32_t usb_dwc_ll_hprt_get_test_ctl(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prttstctl; +} + +static inline void usb_dwc_ll_hprt_set_test_ctl(usb_dwc_dev_t *hw, uint32_t test_mode) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prttstctl = test_mode; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline void usb_dwc_ll_hprt_en_pwr(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtpwr = 1; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline void usb_dwc_ll_hprt_dis_pwr(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtpwr = 0; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline uint32_t usb_dwc_ll_hprt_get_pwr_line_status(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtlnsts; +} + +static inline void usb_dwc_ll_hprt_set_port_reset(usb_dwc_dev_t *hw, bool reset) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtrst = reset; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline bool usb_dwc_ll_hprt_get_port_reset(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtrst; +} + +static inline void usb_dwc_ll_hprt_set_port_suspend(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtsusp = 1; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline bool usb_dwc_ll_hprt_get_port_suspend(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtsusp; +} + +static inline void usb_dwc_ll_hprt_set_port_resume(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtres = 1; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline void usb_dwc_ll_hprt_clr_port_resume(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtres = 0; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline bool usb_dwc_ll_hprt_get_port_resume(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtres; +} + +static inline bool usb_dwc_ll_hprt_get_port_overcur(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtovrcurract; +} + +static inline bool usb_dwc_ll_hprt_get_port_en(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtena; +} + +static inline void usb_dwc_ll_hprt_port_dis(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtena = 1; //W1C to disable + //we want to W1C ENA but not W1C the interrupt bits + hw->hprt_reg.val = hprt.val & ((~USB_DWC_LL_HPRT_W1C_MSK) | USB_DWC_LL_HPRT_ENA_MSK); +} + +static inline bool usb_dwc_ll_hprt_get_conn_status(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtconnsts; +} + +static inline uint32_t usb_dwc_ll_hprt_intr_read_and_clear(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + //We want to W1C the interrupt bits but not that ENA + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_ENA_MSK); + //Return only the interrupt bits + return (hprt.val & (USB_DWC_LL_HPRT_W1C_MSK & ~(USB_DWC_LL_HPRT_ENA_MSK))); +} + +static inline void usb_dwc_ll_hprt_intr_clear(usb_dwc_dev_t *hw, uint32_t intr_mask) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hw->hprt_reg.val = ((hprt.val & ~USB_DWC_LL_HPRT_ENA_MSK) & ~USB_DWC_LL_HPRT_W1C_MSK) | intr_mask; +} + +//Per Channel registers + +// --------------------------- HCCHARi Register -------------------------------- + +static inline void usb_dwc_ll_hcchar_enable_chan(volatile usb_dwc_host_chan_regs_t *chan) +{ + chan->hcchar_reg.chena = 1; +} + +static inline bool usb_dwc_ll_hcchar_chan_is_enabled(volatile usb_dwc_host_chan_regs_t *chan) +{ + return chan->hcchar_reg.chena; +} + +static inline void usb_dwc_ll_hcchar_disable_chan(volatile usb_dwc_host_chan_regs_t *chan) +{ + chan->hcchar_reg.chdis = 1; +} + +static inline void usb_dwc_ll_hcchar_set_odd_frame(volatile usb_dwc_host_chan_regs_t *chan) +{ + chan->hcchar_reg.oddfrm = 1; +} + +static inline void usb_dwc_ll_hcchar_set_even_frame(volatile usb_dwc_host_chan_regs_t *chan) +{ + chan->hcchar_reg.oddfrm = 0; +} + +static inline void usb_dwc_ll_hcchar_set_dev_addr(volatile usb_dwc_host_chan_regs_t *chan, uint32_t addr) +{ + chan->hcchar_reg.devaddr = addr; +} + +static inline void usb_dwc_ll_hcchar_set_ep_type(volatile usb_dwc_host_chan_regs_t *chan, usb_dwc_xfer_type_t type) +{ + chan->hcchar_reg.eptype = (uint32_t)type; +} + +//Indicates whether channel is commuunicating with a LS device connected via a FS hub. Setting this bit to 1 will cause +//each packet to be preceded by a PREamble packet +static inline void usb_dwc_ll_hcchar_set_lspddev(volatile usb_dwc_host_chan_regs_t *chan, bool is_ls) +{ + chan->hcchar_reg.lspddev = is_ls; +} + +static inline void usb_dwc_ll_hcchar_set_dir(volatile usb_dwc_host_chan_regs_t *chan, bool is_in) +{ + chan->hcchar_reg.epdir = is_in; +} + +static inline void usb_dwc_ll_hcchar_set_ep_num(volatile usb_dwc_host_chan_regs_t *chan, uint32_t num) +{ + chan->hcchar_reg.epnum = num; +} + +static inline void usb_dwc_ll_hcchar_set_mps(volatile usb_dwc_host_chan_regs_t *chan, uint32_t mps) +{ + chan->hcchar_reg.mps = mps; +} + +static inline void usb_dwc_ll_hcchar_init(volatile usb_dwc_host_chan_regs_t *chan, int dev_addr, int ep_num, int mps, usb_dwc_xfer_type_t type, bool is_in, bool is_ls) +{ + //Sets all persistent fields of the channel over its lifetimez + usb_dwc_ll_hcchar_set_dev_addr(chan, dev_addr); + usb_dwc_ll_hcchar_set_ep_type(chan, type); + usb_dwc_ll_hcchar_set_lspddev(chan, is_ls); + usb_dwc_ll_hcchar_set_dir(chan, is_in); + usb_dwc_ll_hcchar_set_ep_num(chan, ep_num); + usb_dwc_ll_hcchar_set_mps(chan, mps); +} + +// ---------------------------- HCINTi Register -------------------------------- + +static inline uint32_t usb_dwc_ll_hcint_read_and_clear_intrs(volatile usb_dwc_host_chan_regs_t *chan) +{ + usb_dwc_hcint_reg_t hcint; + hcint.val = chan->hcint_reg.val; + chan->hcint_reg.val = hcint.val; + return hcint.val; +} + +// --------------------------- HCINTMSKi Register ------------------------------ + +static inline void usb_dwc_ll_hcintmsk_set_intr_mask(volatile usb_dwc_host_chan_regs_t *chan, uint32_t mask) +{ + chan->hcintmsk_reg.val = mask; +} + +// ---------------------------- HCTSIZi Register ------------------------------- + +static inline void usb_dwc_ll_hctsiz_set_pid(volatile usb_dwc_host_chan_regs_t *chan, uint32_t data_pid) +{ + if (data_pid == 0) { + chan->hctsiz_reg.pid = 0; + } else { + chan->hctsiz_reg.pid = 2; + } +} + +static inline uint32_t usb_dwc_ll_hctsiz_get_pid(volatile usb_dwc_host_chan_regs_t *chan) +{ + if (chan->hctsiz_reg.pid == 0) { + return 0; //DATA0 + } else { + return 1; //DATA1 + } +} + +static inline void usb_dwc_ll_hctsiz_set_qtd_list_len(volatile usb_dwc_host_chan_regs_t *chan, int qtd_list_len) +{ + usb_dwc_hctsiz_reg_t hctsiz; + hctsiz.val = chan->hctsiz_reg.val; + //Set the length of the descriptor list. NTD occupies xfersize[15:8] + hctsiz.xfersize &= ~(0xFF << 8); + hctsiz.xfersize |= ((qtd_list_len - 1) & 0xFF) << 8; + chan->hctsiz_reg.val = hctsiz.val; +} + +static inline void usb_dwc_ll_hctsiz_init(volatile usb_dwc_host_chan_regs_t *chan) +{ + usb_dwc_hctsiz_reg_t hctsiz; + hctsiz.val = chan->hctsiz_reg.val; + hctsiz.dopng = 0; //Don't do ping + /* + Set SCHED_INFO which occupies xfersize[7:0] + It is always set to 0xFF for full speed and not used in Bulk/Ctrl channels + */ + hctsiz.xfersize |= 0xFF; + chan->hctsiz_reg.val = hctsiz.val; +} + +static inline void usb_dwc_ll_hctsiz_set_sched_info(volatile usb_dwc_host_chan_regs_t *chan, int tokens_per_frame, int offset) +{ + // @see USB-OTG databook: Table 5-47 + // This function is relevant only for HS + usb_dwc_hctsiz_reg_t hctsiz; + hctsiz.val = chan->hctsiz_reg.val; + uint8_t sched_info_val; + switch (tokens_per_frame) { + case 1: + offset %= 8; // If the required offset > 8, we must wrap around to SCHED_INFO size = 8 + sched_info_val = 0b00000001; + break; + case 2: + offset %= 4; + sched_info_val = 0b00010001; + break; + case 4: + offset %= 2; + sched_info_val = 0b01010101; + break; + case 8: + offset = 0; + sched_info_val = 0b11111111; + break; + default: + abort(); + break; + } + sched_info_val <<= offset; + hctsiz.xfersize &= ~(0xFF); + hctsiz.xfersize |= sched_info_val; + chan->hctsiz_reg.val = hctsiz.val; +} + +// ---------------------------- HCDMAi Register -------------------------------- + +static inline void usb_dwc_ll_hcdma_set_qtd_list_addr(volatile usb_dwc_host_chan_regs_t *chan, void *dmaaddr, uint32_t qtd_idx) +{ + usb_dwc_hcdma_reg_t hcdma; + /* + Set the base address portion of the field which is dmaaddr[31:9]. This is + the based address of the QTD list and must be 512 bytes aligned + */ + hcdma.dmaaddr = ((uint32_t)dmaaddr) & 0xFFFFFE00; + //Set the current QTD index in the QTD list which is dmaaddr[8:3] + hcdma.dmaaddr |= (qtd_idx & 0x3F) << 3; + //dmaaddr[2:0] is reserved thus doesn't not need to be set + + chan->hcdma_reg.val = hcdma.val; +} + +static inline int usb_dwc_ll_hcdam_get_cur_qtd_idx(usb_dwc_host_chan_regs_t *chan) +{ + //The current QTD index is dmaaddr[8:3] + return (chan->hcdma_reg.dmaaddr >> 3) & 0x3F; +} + +// ---------------------------- HCDMABi Register ------------------------------- + +static inline void *usb_dwc_ll_hcdmab_get_buff_addr(volatile usb_dwc_host_chan_regs_t *chan) +{ + return (void *)chan->hcdmab_reg.hcdmab; +} + +/* ----------------------------------------------------------------------------- +---------------------------- Scatter/Gather DMA QTDs --------------------------- +----------------------------------------------------------------------------- */ + +// ---------------------------- Helper Functions ------------------------------- + +/** + * @brief Get the base address of a channel's register based on the channel's index + * + * @param dev Start address of the DWC_OTG registers + * @param chan_idx The channel's index + * @return usb_dwc_host_chan_regs_t* Pointer to channel's registers + */ +static inline usb_dwc_host_chan_regs_t *usb_dwc_ll_chan_get_regs(usb_dwc_dev_t *dev, int chan_idx) +{ + return &dev->host_chans[chan_idx]; +} + +// ------------------------------ QTD related ---------------------------------- + +#define USB_DWC_LL_QTD_STATUS_SUCCESS 0x0 //If QTD was processed, it indicates the data was transmitted/received successfully +#define USB_DWC_LL_QTD_STATUS_PKTERR 0x1 //Data transmitted/received with errors (CRC/Timeout/Stuff/False EOP/Excessive NAK). +//Note: 0x2 is reserved +#define USB_DWC_LL_QTD_STATUS_BUFFER 0x3 //AHB error occurred. +#define USB_DWC_LL_QTD_STATUS_NOT_EXECUTED 0x4 //QTD as never processed + +/** + * @brief Set a QTD for a non isochronous IN transfer + * + * @param qtd Pointer to the QTD + * @param data_buff Pointer to buffer containing the data to transfer + * @param xfer_len Number of bytes in transfer. Setting 0 will do a zero length IN transfer. + * Non zero length must be multiple of the endpoint's MPS. + * @param hoc Halt on complete (will generate an interrupt and halt the channel) + */ +static inline void usb_dwc_ll_qtd_set_in(usb_dwc_ll_dma_qtd_t *qtd, uint8_t *data_buff, int xfer_len, bool hoc) +{ + qtd->buffer = data_buff; //Set pointer to data buffer + qtd->buffer_status_val = 0; //Reset all flags to zero + qtd->in_non_iso.xfer_size = xfer_len; + if (hoc) { + qtd->in_non_iso.intr_cplt = 1; //We need to set this to distinguish between a halt due to a QTD + qtd->in_non_iso.eol = 1; //Used to halt the channel at this qtd + } + qtd->in_non_iso.active = 1; +} + +/** + * @brief Set a QTD for a non isochronous OUT transfer + * + * @param qtd Pointer to the QTD + * @param data_buff Pointer to buffer containing the data to transfer + * @param xfer_len Number of bytes to transfer. Setting 0 will do a zero length transfer. + * For ctrl setup packets, this should be set to 8. + * @param hoc Halt on complete (will generate an interrupt) + * @param is_setup Indicates whether this is a control transfer setup packet or a normal OUT Data transfer. + * (As per the USB protocol, setup packets cannot be STALLd or NAKd by the device) + */ +static inline void usb_dwc_ll_qtd_set_out(usb_dwc_ll_dma_qtd_t *qtd, uint8_t *data_buff, int xfer_len, bool hoc, bool is_setup) +{ + qtd->buffer = data_buff; //Set pointer to data buffer + qtd->buffer_status_val = 0; //Reset all flags to zero + qtd->out_non_iso.xfer_size = xfer_len; + if (is_setup) { + qtd->out_non_iso.is_setup = 1; + } + if (hoc) { + qtd->in_non_iso.intr_cplt = 1; //We need to set this to distinguish between a halt due to a QTD + qtd->in_non_iso.eol = 1; //Used to halt the channel at this qtd + } + qtd->out_non_iso.active = 1; +} + +/** + * @brief Set a QTD as NULL + * + * This sets the QTD to a value of 0. This is only useful when you need to insert + * blank QTDs into a list of QTDs + * + * @param qtd Pointer to the QTD + */ +static inline void usb_dwc_ll_qtd_set_null(usb_dwc_ll_dma_qtd_t *qtd) +{ + qtd->buffer = NULL; + qtd->buffer_status_val = 0; //Disable qtd by clearing it to zero. Used by interrupt/isoc as an unscheudled frame +} + +/** + * @brief Get the status of a QTD + * + * When a channel gets halted, call this to check whether each QTD was executed successfully + * + * @param qtd Pointer to the QTD + * @param[out] rem_len Number of bytes ramining in the QTD + * @param[out] status Status of the QTD + */ +static inline void usb_dwc_ll_qtd_get_status(usb_dwc_ll_dma_qtd_t *qtd, int *rem_len, int *status) +{ + //Status is the same regardless of IN or OUT + if (qtd->in_non_iso.active) { + //QTD was never processed + *status = USB_DWC_LL_QTD_STATUS_NOT_EXECUTED; + } else { + *status = qtd->in_non_iso.rx_status; + } + *rem_len = qtd->in_non_iso.xfer_size; + //Clear the QTD just for safety + qtd->buffer_status_val = 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/gpio_ll.h b/components/hal/esp32s3/include/hal/gpio_ll.h index 9a27591e8e5a..3410e4f973b7 100644 --- a/components/hal/esp32s3/include/hal/gpio_ll.h +++ b/components/hal/esp32s3/include/hal/gpio_ll.h @@ -354,15 +354,15 @@ static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t { if (level) { if (gpio_num < 32) { - hw->out_w1ts = (1 << gpio_num); + hw->out_w1ts = 1 << gpio_num; } else { - hw->out1_w1ts.data = (1 << (gpio_num - 32)); + hw->out1_w1ts.val = 1 << (gpio_num - 32); } } else { if (gpio_num < 32) { - hw->out_w1tc = (1 << gpio_num); + hw->out_w1tc = 1 << gpio_num; } else { - hw->out1_w1tc.data = (1 << (gpio_num - 32)); + hw->out1_w1tc.val = 1 << (gpio_num - 32); } } } diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 89b53f8c24f1..c2ae3b9bedab 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -291,15 +291,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - /* Set the integer part of mclk division */ + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, 2); + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; + hw->tx_clkm_div_conf.tx_clkm_div_y = 1; + hw->tx_clkm_div_conf.tx_clkm_div_z = 0; + hw->tx_clkm_div_conf.tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = yn1; + hw->tx_clkm_div_conf.tx_clkm_div_z = z; + hw->tx_clkm_div_conf.tx_clkm_div_y = y; + hw->tx_clkm_div_conf.tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, div_int); - /* Set the decimal part of the mclk division */ - typeof(hw->tx_clkm_div_conf) div = {}; - div.tx_clkm_div_x = x; - div.tx_clkm_div_y = y; - div.tx_clkm_div_z = z; - div.tx_clkm_div_yn1 = yn1; - hw->tx_clkm_div_conf.val = div.val; } /** @@ -314,15 +320,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - /* Set the integer part of mclk division */ + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, 2); + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; + hw->rx_clkm_div_conf.rx_clkm_div_y = 1; + hw->rx_clkm_div_conf.rx_clkm_div_z = 0; + hw->rx_clkm_div_conf.rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = yn1; + hw->rx_clkm_div_conf.rx_clkm_div_z = z; + hw->rx_clkm_div_conf.rx_clkm_div_y = y; + hw->rx_clkm_div_conf.rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, div_int); - /* Set the decimal part of the mclk division */ - typeof(hw->rx_clkm_div_conf) div = {}; - div.rx_clkm_div_x = x; - div.rx_clkm_div_y = y; - div.rx_clkm_div_z = z; - div.rx_clkm_div_yn1 = yn1; - hw->rx_clkm_div_conf.val = div.val; } /** @@ -333,12 +345,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -366,19 +372,13 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) /** * @brief Configure I2S RX module clock divider - * @note mclk on ESP32 is shared by both TX and RX channel + * @note mclk on ESP32S3 is shared by both TX and RX channel * * @param hw Peripheral I2S hardware instance address. * @param mclk_div The mclk division coefficients */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -474,7 +474,7 @@ static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) } /** - * @brief Congfigure TX chan bit and audio data bit + * @brief Configure TX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -487,7 +487,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int } /** - * @brief Congfigure RX chan bit and audio data bit + * @brief Configure RX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -790,11 +790,11 @@ static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f } /** - * @brief Get I2S TX PDM fp configuration paramater + * @brief Get I2S TX PDM fp configuration parameter * * @param hw Peripheral I2S hardware instance address. * @return - * - fp configuration paramater + * - fp configuration parameter */ static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { @@ -802,11 +802,11 @@ static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) } /** - * @brief Get I2S TX PDM fs configuration paramater + * @brief Get I2S TX PDM fs configuration parameter * * @param hw Peripheral I2S hardware instance address. * @return - * - fs configuration paramater + * - fs configuration parameter */ static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) { @@ -927,7 +927,7 @@ static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) * @brief Configure RX PDM downsample * * @param hw Peripheral I2S hardware instance address. - * @param dsr PDM downsample configuration paramater + * @param dsr PDM downsample configuration parameter */ static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) { @@ -949,7 +949,7 @@ static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) * @brief Configura TX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. - * @param pcm_cfg PCM configuration paramater + * @param pcm_cfg PCM configuration parameter */ static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { @@ -961,7 +961,7 @@ static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_ * @brief Configure RX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. - * @param pcm_cfg PCM configuration paramater + * @param pcm_cfg PCM configuration parameter */ static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { @@ -1133,7 +1133,7 @@ static inline void i2s_ll_tx_pdm_dma_take_mode(i2s_dev_t *hw, bool is_mono, bool * @param is_mono The DMA data only has one slot (mono) or contains two slots (stereo) * @param is_copy Whether the un-selected slot copies the data from the selected one * If not, the un-selected slot will transmit the data from 'conf_single_data' - * @param mask The slot mask to selet the slot + * @param mask The slot mask to select the slot */ static inline void i2s_ll_tx_pdm_slot_mode(i2s_dev_t *hw, bool is_mono, bool is_copy, i2s_pdm_slot_mask_t mask) { diff --git a/components/hal/esp32s3/include/hal/usb_dwc_ll.h b/components/hal/esp32s3/include/hal/usb_dwc_ll.h new file mode 100644 index 000000000000..954a54bf8037 --- /dev/null +++ b/components/hal/esp32s3/include/hal/usb_dwc_ll.h @@ -0,0 +1,993 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/usb_dwc_struct.h" +#include "soc/usb_dwc_cfg.h" +#include "hal/usb_dwc_types.h" +#include "hal/misc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------- Helper Macros ------------------------------ */ + +// Get USB hardware instance +#define USB_DWC_LL_GET_HW(num) (&USB_DWC) + +/* ----------------------------------------------------------------------------- +--------------------------------- DWC Constants -------------------------------- +----------------------------------------------------------------------------- */ + +#define USB_DWC_QTD_LIST_MEM_ALIGN 512 +#define USB_DWC_FRAME_LIST_MEM_ALIGN 512 // The frame list needs to be 512 bytes aligned (contrary to the databook) + +/* ----------------------------------------------------------------------------- +------------------------------- Global Registers ------------------------------- +----------------------------------------------------------------------------- */ + +/* + * Interrupt bit masks of the GINTSTS and GINTMSK registers + */ +#define USB_DWC_LL_INTR_CORE_WKUPINT (1 << 31) +#define USB_DWC_LL_INTR_CORE_SESSREQINT (1 << 30) +#define USB_DWC_LL_INTR_CORE_DISCONNINT (1 << 29) +#define USB_DWC_LL_INTR_CORE_CONIDSTSCHNG (1 << 28) +#define USB_DWC_LL_INTR_CORE_PTXFEMP (1 << 26) +#define USB_DWC_LL_INTR_CORE_HCHINT (1 << 25) +#define USB_DWC_LL_INTR_CORE_PRTINT (1 << 24) +#define USB_DWC_LL_INTR_CORE_RESETDET (1 << 23) +#define USB_DWC_LL_INTR_CORE_FETSUSP (1 << 22) +#define USB_DWC_LL_INTR_CORE_INCOMPIP (1 << 21) +#define USB_DWC_LL_INTR_CORE_INCOMPISOIN (1 << 20) +#define USB_DWC_LL_INTR_CORE_OEPINT (1 << 19) +#define USB_DWC_LL_INTR_CORE_IEPINT (1 << 18) +#define USB_DWC_LL_INTR_CORE_EPMIS (1 << 17) +#define USB_DWC_LL_INTR_CORE_EOPF (1 << 15) +#define USB_DWC_LL_INTR_CORE_ISOOUTDROP (1 << 14) +#define USB_DWC_LL_INTR_CORE_ENUMDONE (1 << 13) +#define USB_DWC_LL_INTR_CORE_USBRST (1 << 12) +#define USB_DWC_LL_INTR_CORE_USBSUSP (1 << 11) +#define USB_DWC_LL_INTR_CORE_ERLYSUSP (1 << 10) +#define USB_DWC_LL_INTR_CORE_GOUTNAKEFF (1 << 7) +#define USB_DWC_LL_INTR_CORE_GINNAKEFF (1 << 6) +#define USB_DWC_LL_INTR_CORE_NPTXFEMP (1 << 5) +#define USB_DWC_LL_INTR_CORE_RXFLVL (1 << 4) +#define USB_DWC_LL_INTR_CORE_SOF (1 << 3) +#define USB_DWC_LL_INTR_CORE_OTGINT (1 << 2) +#define USB_DWC_LL_INTR_CORE_MODEMIS (1 << 1) +#define USB_DWC_LL_INTR_CORE_CURMOD (1 << 0) + +/* + * Bit mask of interrupt generating bits of the the HPRT register. These bits + * are ORd into the USB_DWC_LL_INTR_CORE_PRTINT interrupt. + * + * Note: Some fields of the HPRT are W1C (write 1 clear), this we cannot do a + * simple read and write-back to clear the HPRT interrupt bits. Instead we need + * a W1C mask the non-interrupt related bits + */ +#define USB_DWC_LL_HPRT_W1C_MSK (0x2E) +#define USB_DWC_LL_HPRT_ENA_MSK (0x04) +#define USB_DWC_LL_INTR_HPRT_PRTOVRCURRCHNG (1 << 5) +#define USB_DWC_LL_INTR_HPRT_PRTENCHNG (1 << 3) +#define USB_DWC_LL_INTR_HPRT_PRTCONNDET (1 << 1) + +/* + * Bit mask of channel interrupts (HCINTi and HCINTMSKi registers) + * + * Note: Under Scatter/Gather DMA mode, only the following interrupts can be unmasked + * - DESC_LS_ROLL + * - XCS_XACT_ERR (always unmasked) + * - BNAINTR + * - CHHLTD + * - XFERCOMPL + * The remaining interrupt bits will still be set (when the corresponding event occurs) + * but will not generate an interrupt. Therefore we must proxy through the + * USB_DWC_LL_INTR_CHAN_CHHLTD interrupt to check the other interrupt bits. + */ +#define USB_DWC_LL_INTR_CHAN_DESC_LS_ROLL (1 << 13) +#define USB_DWC_LL_INTR_CHAN_XCS_XACT_ERR (1 << 12) +#define USB_DWC_LL_INTR_CHAN_BNAINTR (1 << 11) +#define USB_DWC_LL_INTR_CHAN_DATATGLERR (1 << 10) +#define USB_DWC_LL_INTR_CHAN_FRMOVRUN (1 << 9) +#define USB_DWC_LL_INTR_CHAN_BBLEER (1 << 8) +#define USB_DWC_LL_INTR_CHAN_XACTERR (1 << 7) +#define USB_DWC_LL_INTR_CHAN_NYET (1 << 6) +#define USB_DWC_LL_INTR_CHAN_ACK (1 << 5) +#define USB_DWC_LL_INTR_CHAN_NAK (1 << 4) +#define USB_DWC_LL_INTR_CHAN_STALL (1 << 3) +#define USB_DWC_LL_INTR_CHAN_AHBERR (1 << 2) +#define USB_DWC_LL_INTR_CHAN_CHHLTD (1 << 1) +#define USB_DWC_LL_INTR_CHAN_XFERCOMPL (1 << 0) + +/* + * QTD (Queue Transfer Descriptor) structure used in Scatter/Gather DMA mode. + * Each QTD describes one transfer. Scatter gather mode will automatically split + * a transfer into multiple MPS packets. Each QTD is 64bits in size + * + * Note: The status information part of the QTD is interpreted differently depending + * on IN or OUT, and ISO or non-ISO + */ +typedef struct { + union { + struct { + uint32_t xfer_size: 17; + uint32_t aqtd_offset: 6; + uint32_t aqtd_valid: 1; + uint32_t reserved_24: 1; + uint32_t intr_cplt: 1; + uint32_t eol: 1; + uint32_t reserved_27: 1; + uint32_t rx_status: 2; + uint32_t reserved_30: 1; + uint32_t active: 1; + } in_non_iso; + struct { + uint32_t xfer_size: 12; + uint32_t reserved_12_24: 13; + uint32_t intr_cplt: 1; + uint32_t reserved_26_27: 2; + uint32_t rx_status: 2; + uint32_t reserved_30: 1; + uint32_t active: 1; + } in_iso; + struct { + uint32_t xfer_size: 17; + uint32_t reserved_17_23: 7; + uint32_t is_setup: 1; + uint32_t intr_cplt: 1; + uint32_t eol: 1; + uint32_t reserved_27: 1; + uint32_t tx_status: 2; + uint32_t reserved_30: 1; + uint32_t active: 1; + } out_non_iso; + struct { + uint32_t xfer_size: 12; + uint32_t reserved_12_24: 13; + uint32_t intr_cplt: 1; + uint32_t eol: 1; + uint32_t reserved_27: 1; + uint32_t tx_status: 2; + uint32_t reserved_30: 1; + uint32_t active: 1; + } out_iso; + uint32_t buffer_status_val; + }; + uint8_t *buffer; +} usb_dwc_ll_dma_qtd_t; + + +/* ----------------------------------------------------------------------------- +------------------------------- Global Registers ------------------------------- +----------------------------------------------------------------------------- */ + +// --------------------------- GAHBCFG Register -------------------------------- + +static inline void usb_dwc_ll_gahbcfg_en_dma_mode(usb_dwc_dev_t *hw) +{ + hw->gahbcfg_reg.dmaen = 1; +} + +static inline void usb_dwc_ll_gahbcfg_en_slave_mode(usb_dwc_dev_t *hw) +{ + hw->gahbcfg_reg.dmaen = 0; +} + +static inline void usb_dwc_ll_gahbcfg_set_hbstlen(usb_dwc_dev_t *hw, uint32_t burst_len) +{ + hw->gahbcfg_reg.hbstlen = burst_len; +} + +static inline void usb_dwc_ll_gahbcfg_en_global_intr(usb_dwc_dev_t *hw) +{ + hw->gahbcfg_reg.glbllntrmsk = 1; +} + +static inline void usb_dwc_ll_gahbcfg_dis_global_intr(usb_dwc_dev_t *hw) +{ + hw->gahbcfg_reg.glbllntrmsk = 0; +} + +// --------------------------- GUSBCFG Register -------------------------------- + +static inline void usb_dwc_ll_gusbcfg_force_host_mode(usb_dwc_dev_t *hw) +{ + hw->gusbcfg_reg.forcehstmode = 1; +} + +static inline void usb_dwc_ll_gusbcfg_dis_hnp_cap(usb_dwc_dev_t *hw) +{ + hw->gusbcfg_reg.hnpcap = 0; +} + +static inline void usb_dwc_ll_gusbcfg_dis_srp_cap(usb_dwc_dev_t *hw) +{ + hw->gusbcfg_reg.srpcap = 0; +} + +static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t tout_cal) +{ + hw->gusbcfg_reg.toutcal = tout_cal; +} + +static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw) +{ +#if (OTG_HSPHY_INTERFACE != 0) + hw->gusbcfg_reg.phyif = 1; // 16 bits interface + hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+ + hw->gusbcfg_reg.physel = 0; // HS PHY +#endif // (OTG_HSPHY_INTERFACE != 0) +} + +// --------------------------- GRSTCTL Register -------------------------------- + +static inline bool usb_dwc_ll_grstctl_is_ahb_idle(usb_dwc_dev_t *hw) +{ + return hw->grstctl_reg.ahbidle; +} + +static inline bool usb_dwc_ll_grstctl_is_dma_req_in_progress(usb_dwc_dev_t *hw) +{ + return hw->grstctl_reg.dmareq; +} + +static inline void usb_dwc_ll_grstctl_flush_nptx_fifo(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.txfnum = 0; //Set the TX FIFO number to 0 to select the non-periodic TX FIFO + hw->grstctl_reg.txfflsh = 1; //Flush the selected TX FIFO + //Wait for the flushing to complete + while (hw->grstctl_reg.txfflsh) { + ; + } +} + +static inline void usb_dwc_ll_grstctl_flush_ptx_fifo(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.txfnum = 1; //Set the TX FIFO number to 1 to select the periodic TX FIFO + hw->grstctl_reg.txfflsh = 1; //FLush the select TX FIFO + //Wait for the flushing to complete + while (hw->grstctl_reg.txfflsh) { + ; + } +} + +static inline void usb_dwc_ll_grstctl_flush_rx_fifo(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.rxfflsh = 1; + //Wait for the flushing to complete + while (hw->grstctl_reg.rxfflsh) { + ; + } +} + +static inline void usb_dwc_ll_grstctl_reset_frame_counter(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.frmcntrrst = 1; +} + +static inline void usb_dwc_ll_grstctl_core_soft_reset(usb_dwc_dev_t *hw) +{ + hw->grstctl_reg.csftrst = 1; +} + +static inline bool usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(usb_dwc_dev_t *hw) +{ + return hw->grstctl_reg.csftrst; +} + +// --------------------------- GINTSTS Register -------------------------------- + +/** + * @brief Reads and clears the global interrupt register + * + * @param hw Start address of the DWC_OTG registers + * @return uint32_t Mask of interrupts + */ +static inline uint32_t usb_dwc_ll_gintsts_read_and_clear_intrs(usb_dwc_dev_t *hw) +{ + usb_dwc_gintsts_reg_t gintsts; + gintsts.val = hw->gintsts_reg.val; + hw->gintsts_reg.val = gintsts.val; //Write back to clear + return gintsts.val; +} + +/** + * @brief Clear specific interrupts + * + * @param hw Start address of the DWC_OTG registers + * @param intr_msk Mask of interrupts to clear + */ +static inline void usb_dwc_ll_gintsts_clear_intrs(usb_dwc_dev_t *hw, uint32_t intr_msk) +{ + //All GINTSTS fields are either W1C or read only. So safe to write directly + hw->gintsts_reg.val = intr_msk; +} + +// --------------------------- GINTMSK Register -------------------------------- + +static inline void usb_dwc_ll_gintmsk_en_intrs(usb_dwc_dev_t *hw, uint32_t intr_mask) +{ + hw->gintmsk_reg.val |= intr_mask; +} + +static inline void usb_dwc_ll_gintmsk_dis_intrs(usb_dwc_dev_t *hw, uint32_t intr_mask) +{ + hw->gintmsk_reg.val &= ~intr_mask; +} + +// --------------------------- GRXFSIZ Register -------------------------------- + +static inline void usb_dwc_ll_grxfsiz_set_fifo_size(usb_dwc_dev_t *hw, uint32_t num_lines) +{ + //Set size in words + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->grxfsiz_reg, rxfdep, num_lines); +} + +// -------------------------- GNPTXFSIZ Register ------------------------------- + +static inline void usb_dwc_ll_gnptxfsiz_set_fifo_size(usb_dwc_dev_t *hw, uint32_t addr, uint32_t num_lines) +{ + usb_dwc_gnptxfsiz_reg_t gnptxfsiz; + gnptxfsiz.val = hw->gnptxfsiz_reg.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(gnptxfsiz, nptxfstaddr, addr); + HAL_FORCE_MODIFY_U32_REG_FIELD(gnptxfsiz, nptxfdep, num_lines); + hw->gnptxfsiz_reg.val = gnptxfsiz.val; +} + +// --------------------------- GSNPSID Register -------------------------------- + +static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw) +{ + return hw->gsnpsid_reg.val; +} + +// --------------------------- GHWCFGx Register -------------------------------- + +/** + * @brief Get the hardware configuration registers of the DWC_OTG controller + * + * The hardware configuration regitsers are read only and indicate the various + * features of the DWC_OTG core. + * + * @param hw Start address of the DWC_OTG registers + * @param[out] ghwcfg1 Hardware configuration registesr 1 + * @param[out] ghwcfg2 Hardware configuration registesr 2 + * @param[out] ghwcfg3 Hardware configuration registesr 3 + * @param[out] ghwcfg4 Hardware configuration registesr 4 + */ +static inline void usb_dwc_ll_ghwcfg_get_hw_config(usb_dwc_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4) +{ + *ghwcfg1 = hw->ghwcfg1_reg.val; + *ghwcfg2 = hw->ghwcfg2_reg.val; + *ghwcfg3 = hw->ghwcfg3_reg.val; + *ghwcfg4 = hw->ghwcfg4_reg.val; +} + +// --------------------------- HPTXFSIZ Register ------------------------------- + +static inline void usb_dwc_ll_hptxfsiz_set_ptx_fifo_size(usb_dwc_dev_t *hw, uint32_t addr, uint32_t num_lines) +{ + usb_dwc_hptxfsiz_reg_t hptxfsiz; + hptxfsiz.val = hw->hptxfsiz_reg.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(hptxfsiz, ptxfstaddr, addr); + HAL_FORCE_MODIFY_U32_REG_FIELD(hptxfsiz, ptxfsize, num_lines); + hw->hptxfsiz_reg.val = hptxfsiz.val; +} + +/* ----------------------------------------------------------------------------- +-------------------------------- Host Registers -------------------------------- +----------------------------------------------------------------------------- */ + +// ----------------------------- HCFG Register --------------------------------- + +static inline void usb_dwc_ll_hcfg_en_perio_sched(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.perschedena = 1; +} + +static inline void usb_dwc_ll_hcfg_dis_perio_sched(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.perschedena = 0; +} + +/** + * Sets the length of the frame list + * + * @param num_entires Number of entries in the frame list + */ +static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw, usb_hal_frame_list_len_t num_entries) +{ + uint32_t frlisten; + switch (num_entries) { + case USB_HAL_FRAME_LIST_LEN_8: + frlisten = 0; + break; + case USB_HAL_FRAME_LIST_LEN_16: + frlisten = 1; + break; + case USB_HAL_FRAME_LIST_LEN_32: + frlisten = 2; + break; + default: //USB_HAL_FRAME_LIST_LEN_64 + frlisten = 3; + break; + } + hw->hcfg_reg.frlisten = frlisten; +} + +static inline void usb_dwc_ll_hcfg_en_scatt_gatt_dma(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.descdma = 1; +} + +static inline void usb_dwc_ll_hcfg_set_fsls_supp_only(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.fslssupp = 1; +} + +static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw) +{ + hw->hcfg_reg.fslspclksel = 1; +} + +/** + * @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA + * + * @param[in] hw Start address of the DWC_OTG registers + * @param[in] speed Speed to initialize the host port at + */ +static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +{ + hw->hcfg_reg.descdma = 1; //Enable scatt/gatt +#if (OTG_HSPHY_INTERFACE == 0) + /* + Indicate to the OTG core what speed the PHY clock is at + Note: It seems like S2/S3 PHY has an implicit 8 divider applied when in LS mode, + so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. + */ + hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only +#endif // (OTG_HSPHY_INTERFACE == 0) + hw->hcfg_reg.perschedena = 0; //Disable perio sched +} + +// ----------------------------- HFIR Register --------------------------------- + +static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +{ +#if (OTG_HSPHY_INTERFACE == 0) + usb_dwc_hfir_reg_t hfir; + hfir.val = hw->hfir_reg.val; + hfir.hfirrldctrl = 0; //Disable dynamic loading + /* + Set frame interval to be equal to 1ms + Note: It seems like our PHY has an implicit 8 divider applied when in LS mode, + so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. + */ + hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS + hw->hfir_reg.val = hfir.val; +#endif // (OTG_HSPHY_INTERFACE == 0) +} + +// ----------------------------- HFNUM Register -------------------------------- + +static inline uint32_t usb_dwc_ll_hfnum_get_frame_time_rem(usb_dwc_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->hfnum_reg, frrem); +} + +static inline uint32_t usb_dwc_ll_hfnum_get_frame_num(usb_dwc_dev_t *hw) +{ + return hw->hfnum_reg.frnum; +} + +// ---------------------------- HPTXSTS Register ------------------------------- + +static inline uint32_t usb_dwc_ll_hptxsts_get_ptxq_top(usb_dwc_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->hptxsts_reg, ptxqtop); +} + +static inline uint32_t usb_dwc_ll_hptxsts_get_ptxq_space_avail(usb_dwc_dev_t *hw) +{ + return hw->hptxsts_reg.ptxqspcavail; +} + +static inline uint32_t usb_dwc_ll_ptxsts_get_ptxf_space_avail(usb_dwc_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->hptxsts_reg, ptxfspcavail); +} + +// ----------------------------- HAINT Register -------------------------------- + +static inline uint32_t usb_dwc_ll_haint_get_chan_intrs(usb_dwc_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->haint_reg, haint); +} + +// --------------------------- HAINTMSK Register ------------------------------- + +static inline void usb_dwc_ll_haintmsk_en_chan_intr(usb_dwc_dev_t *hw, uint32_t mask) +{ + + hw->haintmsk_reg.val |= mask; +} + +static inline void usb_dwc_ll_haintmsk_dis_chan_intr(usb_dwc_dev_t *hw, uint32_t mask) +{ + hw->haintmsk_reg.val &= ~mask; +} + +// --------------------------- HFLBAddr Register ------------------------------- + +/** + * @brief Set the base address of the scheduling frame list + * + * @note For some reason, this address must be 512 bytes aligned or else a bunch of frames will not be scheduled when + * the frame list rolls over. However, according to the databook, there is no mention of the HFLBAddr needing to + * be aligned. + * + * @param hw Start address of the DWC_OTG registers + * @param addr Base address of the scheduling frame list + */ +static inline void usb_dwc_ll_hflbaddr_set_base_addr(usb_dwc_dev_t *hw, uint32_t addr) +{ + hw->hflbaddr_reg.hflbaddr = addr; +} + +/** + * @brief Get the base address of the scheduling frame list + * + * @param hw Start address of the DWC_OTG registers + * @return uint32_t Base address of the scheduling frame list + */ +static inline uint32_t usb_dwc_ll_hflbaddr_get_base_addr(usb_dwc_dev_t *hw) +{ + return hw->hflbaddr_reg.hflbaddr; +} + +// ----------------------------- HPRT Register --------------------------------- + +static inline usb_dwc_speed_t usb_dwc_ll_hprt_get_speed(usb_dwc_dev_t *hw) +{ + return (usb_dwc_speed_t)hw->hprt_reg.prtspd; +} + +static inline uint32_t usb_dwc_ll_hprt_get_test_ctl(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prttstctl; +} + +static inline void usb_dwc_ll_hprt_set_test_ctl(usb_dwc_dev_t *hw, uint32_t test_mode) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prttstctl = test_mode; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline void usb_dwc_ll_hprt_en_pwr(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtpwr = 1; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline void usb_dwc_ll_hprt_dis_pwr(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtpwr = 0; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline uint32_t usb_dwc_ll_hprt_get_pwr_line_status(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtlnsts; +} + +static inline void usb_dwc_ll_hprt_set_port_reset(usb_dwc_dev_t *hw, bool reset) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtrst = reset; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline bool usb_dwc_ll_hprt_get_port_reset(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtrst; +} + +static inline void usb_dwc_ll_hprt_set_port_suspend(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtsusp = 1; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline bool usb_dwc_ll_hprt_get_port_suspend(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtsusp; +} + +static inline void usb_dwc_ll_hprt_set_port_resume(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtres = 1; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline void usb_dwc_ll_hprt_clr_port_resume(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtres = 0; + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_W1C_MSK); +} + +static inline bool usb_dwc_ll_hprt_get_port_resume(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtres; +} + +static inline bool usb_dwc_ll_hprt_get_port_overcur(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtovrcurract; +} + +static inline bool usb_dwc_ll_hprt_get_port_en(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtena; +} + +static inline void usb_dwc_ll_hprt_port_dis(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hprt.prtena = 1; //W1C to disable + //we want to W1C ENA but not W1C the interrupt bits + hw->hprt_reg.val = hprt.val & ((~USB_DWC_LL_HPRT_W1C_MSK) | USB_DWC_LL_HPRT_ENA_MSK); +} + +static inline bool usb_dwc_ll_hprt_get_conn_status(usb_dwc_dev_t *hw) +{ + return hw->hprt_reg.prtconnsts; +} + +static inline uint32_t usb_dwc_ll_hprt_intr_read_and_clear(usb_dwc_dev_t *hw) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + //We want to W1C the interrupt bits but not that ENA + hw->hprt_reg.val = hprt.val & (~USB_DWC_LL_HPRT_ENA_MSK); + //Return only the interrupt bits + return (hprt.val & (USB_DWC_LL_HPRT_W1C_MSK & ~(USB_DWC_LL_HPRT_ENA_MSK))); +} + +static inline void usb_dwc_ll_hprt_intr_clear(usb_dwc_dev_t *hw, uint32_t intr_mask) +{ + usb_dwc_hprt_reg_t hprt; + hprt.val = hw->hprt_reg.val; + hw->hprt_reg.val = ((hprt.val & ~USB_DWC_LL_HPRT_ENA_MSK) & ~USB_DWC_LL_HPRT_W1C_MSK) | intr_mask; +} + +//Per Channel registers + +// --------------------------- HCCHARi Register -------------------------------- + +static inline void usb_dwc_ll_hcchar_enable_chan(volatile usb_dwc_host_chan_regs_t *chan) +{ + chan->hcchar_reg.chena = 1; +} + +static inline bool usb_dwc_ll_hcchar_chan_is_enabled(volatile usb_dwc_host_chan_regs_t *chan) +{ + return chan->hcchar_reg.chena; +} + +static inline void usb_dwc_ll_hcchar_disable_chan(volatile usb_dwc_host_chan_regs_t *chan) +{ + chan->hcchar_reg.chdis = 1; +} + +static inline void usb_dwc_ll_hcchar_set_odd_frame(volatile usb_dwc_host_chan_regs_t *chan) +{ + chan->hcchar_reg.oddfrm = 1; +} + +static inline void usb_dwc_ll_hcchar_set_even_frame(volatile usb_dwc_host_chan_regs_t *chan) +{ + chan->hcchar_reg.oddfrm = 0; +} + +static inline void usb_dwc_ll_hcchar_set_dev_addr(volatile usb_dwc_host_chan_regs_t *chan, uint32_t addr) +{ + chan->hcchar_reg.devaddr = addr; +} + +static inline void usb_dwc_ll_hcchar_set_ep_type(volatile usb_dwc_host_chan_regs_t *chan, usb_dwc_xfer_type_t type) +{ + chan->hcchar_reg.eptype = (uint32_t)type; +} + +//Indicates whether channel is commuunicating with a LS device connected via a FS hub. Setting this bit to 1 will cause +//each packet to be preceded by a PREamble packet +static inline void usb_dwc_ll_hcchar_set_lspddev(volatile usb_dwc_host_chan_regs_t *chan, bool is_ls) +{ + chan->hcchar_reg.lspddev = is_ls; +} + +static inline void usb_dwc_ll_hcchar_set_dir(volatile usb_dwc_host_chan_regs_t *chan, bool is_in) +{ + chan->hcchar_reg.epdir = is_in; +} + +static inline void usb_dwc_ll_hcchar_set_ep_num(volatile usb_dwc_host_chan_regs_t *chan, uint32_t num) +{ + chan->hcchar_reg.epnum = num; +} + +static inline void usb_dwc_ll_hcchar_set_mps(volatile usb_dwc_host_chan_regs_t *chan, uint32_t mps) +{ + chan->hcchar_reg.mps = mps; +} + +static inline void usb_dwc_ll_hcchar_init(volatile usb_dwc_host_chan_regs_t *chan, int dev_addr, int ep_num, int mps, usb_dwc_xfer_type_t type, bool is_in, bool is_ls) +{ + //Sets all persistent fields of the channel over its lifetimez + usb_dwc_ll_hcchar_set_dev_addr(chan, dev_addr); + usb_dwc_ll_hcchar_set_ep_type(chan, type); + usb_dwc_ll_hcchar_set_lspddev(chan, is_ls); + usb_dwc_ll_hcchar_set_dir(chan, is_in); + usb_dwc_ll_hcchar_set_ep_num(chan, ep_num); + usb_dwc_ll_hcchar_set_mps(chan, mps); +} + +// ---------------------------- HCINTi Register -------------------------------- + +static inline uint32_t usb_dwc_ll_hcint_read_and_clear_intrs(volatile usb_dwc_host_chan_regs_t *chan) +{ + usb_dwc_hcint_reg_t hcint; + hcint.val = chan->hcint_reg.val; + chan->hcint_reg.val = hcint.val; + return hcint.val; +} + +// --------------------------- HCINTMSKi Register ------------------------------ + +static inline void usb_dwc_ll_hcintmsk_set_intr_mask(volatile usb_dwc_host_chan_regs_t *chan, uint32_t mask) +{ + chan->hcintmsk_reg.val = mask; +} + +// ---------------------------- HCTSIZi Register ------------------------------- + +static inline void usb_dwc_ll_hctsiz_set_pid(volatile usb_dwc_host_chan_regs_t *chan, uint32_t data_pid) +{ + if (data_pid == 0) { + chan->hctsiz_reg.pid = 0; + } else { + chan->hctsiz_reg.pid = 2; + } +} + +static inline uint32_t usb_dwc_ll_hctsiz_get_pid(volatile usb_dwc_host_chan_regs_t *chan) +{ + if (chan->hctsiz_reg.pid == 0) { + return 0; //DATA0 + } else { + return 1; //DATA1 + } +} + +static inline void usb_dwc_ll_hctsiz_set_qtd_list_len(volatile usb_dwc_host_chan_regs_t *chan, int qtd_list_len) +{ + usb_dwc_hctsiz_reg_t hctsiz; + hctsiz.val = chan->hctsiz_reg.val; + //Set the length of the descriptor list. NTD occupies xfersize[15:8] + hctsiz.xfersize &= ~(0xFF << 8); + hctsiz.xfersize |= ((qtd_list_len - 1) & 0xFF) << 8; + chan->hctsiz_reg.val = hctsiz.val; +} + +static inline void usb_dwc_ll_hctsiz_init(volatile usb_dwc_host_chan_regs_t *chan) +{ + usb_dwc_hctsiz_reg_t hctsiz; + hctsiz.val = chan->hctsiz_reg.val; + hctsiz.dopng = 0; //Don't do ping + /* + Set SCHED_INFO which occupies xfersize[7:0] + It is always set to 0xFF for full speed and not used in Bulk/Ctrl channels + */ + hctsiz.xfersize |= 0xFF; + chan->hctsiz_reg.val = hctsiz.val; +} + +static inline void usb_dwc_ll_hctsiz_set_sched_info(volatile usb_dwc_host_chan_regs_t *chan, int tokens_per_frame, int offset) +{ + // @see USB-OTG databook: Table 5-47 + // This function is relevant only for HS + usb_dwc_hctsiz_reg_t hctsiz; + hctsiz.val = chan->hctsiz_reg.val; + uint8_t sched_info_val; + switch (tokens_per_frame) { + case 1: + offset %= 8; // If the required offset > 8, we must wrap around to SCHED_INFO size = 8 + sched_info_val = 0b00000001; + break; + case 2: + offset %= 4; + sched_info_val = 0b00010001; + break; + case 4: + offset %= 2; + sched_info_val = 0b01010101; + break; + case 8: + offset = 0; + sched_info_val = 0b11111111; + break; + default: + abort(); + break; + } + sched_info_val <<= offset; + hctsiz.xfersize &= ~(0xFF); + hctsiz.xfersize |= sched_info_val; + chan->hctsiz_reg.val = hctsiz.val; +} + +// ---------------------------- HCDMAi Register -------------------------------- + +static inline void usb_dwc_ll_hcdma_set_qtd_list_addr(volatile usb_dwc_host_chan_regs_t *chan, void *dmaaddr, uint32_t qtd_idx) +{ + usb_dwc_hcdma_reg_t hcdma; + /* + Set the base address portion of the field which is dmaaddr[31:9]. This is + the based address of the QTD list and must be 512 bytes aligned + */ + hcdma.dmaaddr = ((uint32_t)dmaaddr) & 0xFFFFFE00; + //Set the current QTD index in the QTD list which is dmaaddr[8:3] + hcdma.dmaaddr |= (qtd_idx & 0x3F) << 3; + //dmaaddr[2:0] is reserved thus doesn't not need to be set + + chan->hcdma_reg.val = hcdma.val; +} + +static inline int usb_dwc_ll_hcdam_get_cur_qtd_idx(usb_dwc_host_chan_regs_t *chan) +{ + //The current QTD index is dmaaddr[8:3] + return (chan->hcdma_reg.dmaaddr >> 3) & 0x3F; +} + +// ---------------------------- HCDMABi Register ------------------------------- + +static inline void *usb_dwc_ll_hcdmab_get_buff_addr(volatile usb_dwc_host_chan_regs_t *chan) +{ + return (void *)chan->hcdmab_reg.hcdmab; +} + +/* ----------------------------------------------------------------------------- +---------------------------- Scatter/Gather DMA QTDs --------------------------- +----------------------------------------------------------------------------- */ + +// ---------------------------- Helper Functions ------------------------------- + +/** + * @brief Get the base address of a channel's register based on the channel's index + * + * @param dev Start address of the DWC_OTG registers + * @param chan_idx The channel's index + * @return usb_dwc_host_chan_regs_t* Pointer to channel's registers + */ +static inline usb_dwc_host_chan_regs_t *usb_dwc_ll_chan_get_regs(usb_dwc_dev_t *dev, int chan_idx) +{ + return &dev->host_chans[chan_idx]; +} + +// ------------------------------ QTD related ---------------------------------- + +#define USB_DWC_LL_QTD_STATUS_SUCCESS 0x0 //If QTD was processed, it indicates the data was transmitted/received successfully +#define USB_DWC_LL_QTD_STATUS_PKTERR 0x1 //Data transmitted/received with errors (CRC/Timeout/Stuff/False EOP/Excessive NAK). +//Note: 0x2 is reserved +#define USB_DWC_LL_QTD_STATUS_BUFFER 0x3 //AHB error occurred. +#define USB_DWC_LL_QTD_STATUS_NOT_EXECUTED 0x4 //QTD as never processed + +/** + * @brief Set a QTD for a non isochronous IN transfer + * + * @param qtd Pointer to the QTD + * @param data_buff Pointer to buffer containing the data to transfer + * @param xfer_len Number of bytes in transfer. Setting 0 will do a zero length IN transfer. + * Non zero length must be multiple of the endpoint's MPS. + * @param hoc Halt on complete (will generate an interrupt and halt the channel) + */ +static inline void usb_dwc_ll_qtd_set_in(usb_dwc_ll_dma_qtd_t *qtd, uint8_t *data_buff, int xfer_len, bool hoc) +{ + qtd->buffer = data_buff; //Set pointer to data buffer + qtd->buffer_status_val = 0; //Reset all flags to zero + qtd->in_non_iso.xfer_size = xfer_len; + if (hoc) { + qtd->in_non_iso.intr_cplt = 1; //We need to set this to distinguish between a halt due to a QTD + qtd->in_non_iso.eol = 1; //Used to halt the channel at this qtd + } + qtd->in_non_iso.active = 1; +} + +/** + * @brief Set a QTD for a non isochronous OUT transfer + * + * @param qtd Pointer to the QTD + * @param data_buff Pointer to buffer containing the data to transfer + * @param xfer_len Number of bytes to transfer. Setting 0 will do a zero length transfer. + * For ctrl setup packets, this should be set to 8. + * @param hoc Halt on complete (will generate an interrupt) + * @param is_setup Indicates whether this is a control transfer setup packet or a normal OUT Data transfer. + * (As per the USB protocol, setup packets cannot be STALLd or NAKd by the device) + */ +static inline void usb_dwc_ll_qtd_set_out(usb_dwc_ll_dma_qtd_t *qtd, uint8_t *data_buff, int xfer_len, bool hoc, bool is_setup) +{ + qtd->buffer = data_buff; //Set pointer to data buffer + qtd->buffer_status_val = 0; //Reset all flags to zero + qtd->out_non_iso.xfer_size = xfer_len; + if (is_setup) { + qtd->out_non_iso.is_setup = 1; + } + if (hoc) { + qtd->in_non_iso.intr_cplt = 1; //We need to set this to distinguish between a halt due to a QTD + qtd->in_non_iso.eol = 1; //Used to halt the channel at this qtd + } + qtd->out_non_iso.active = 1; +} + +/** + * @brief Set a QTD as NULL + * + * This sets the QTD to a value of 0. This is only useful when you need to insert + * blank QTDs into a list of QTDs + * + * @param qtd Pointer to the QTD + */ +static inline void usb_dwc_ll_qtd_set_null(usb_dwc_ll_dma_qtd_t *qtd) +{ + qtd->buffer = NULL; + qtd->buffer_status_val = 0; //Disable qtd by clearing it to zero. Used by interrupt/isoc as an unscheudled frame +} + +/** + * @brief Get the status of a QTD + * + * When a channel gets halted, call this to check whether each QTD was executed successfully + * + * @param qtd Pointer to the QTD + * @param[out] rem_len Number of bytes ramining in the QTD + * @param[out] status Status of the QTD + */ +static inline void usb_dwc_ll_qtd_get_status(usb_dwc_ll_dma_qtd_t *qtd, int *rem_len, int *status) +{ + //Status is the same regardless of IN or OUT + if (qtd->in_non_iso.active) { + //QTD was never processed + *status = USB_DWC_LL_QTD_STATUS_NOT_EXECUTED; + } else { + *status = qtd->in_non_iso.rx_status; + } + *rem_len = qtd->in_non_iso.xfer_size; + //Clear the QTD just for safety + qtd->buffer_status_val = 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/color_types.h b/components/hal/include/hal/color_types.h index 2cdd7d33104e..93c69b323d73 100644 --- a/components/hal/include/hal/color_types.h +++ b/components/hal/include/hal/color_types.h @@ -141,6 +141,15 @@ typedef enum { /*--------------------------------------------------------------- Color Endian ---------------------------------------------------------------*/ +/** + * @brief RAW element order + */ +typedef enum { + COLOR_RAW_ELEMENT_ORDER_BGGR, ///< BGGR order + COLOR_RAW_ELEMENT_ORDER_GBRG, ///< GBRG order + COLOR_RAW_ELEMENT_ORDER_GRBG, ///< GRBG order + COLOR_RAW_ELEMENT_ORDER_RGGB, ///< RGGB order +} color_raw_element_order_t; /** * @brief RGB element order @@ -202,6 +211,16 @@ typedef enum { COLOR_COMPONENT_INVALID, /*!< Invalid color component */ } color_component_t; +/** + * @brief The order of the components per pack in the YUV422 format + */ +typedef enum { + COLOR_YUV422_PACK_ORDER_YUYV, /*!< YUYV */ + COLOR_YUV422_PACK_ORDER_YVYU, /*!< YVYU */ + COLOR_YUV422_PACK_ORDER_UYVY, /*!< UYVY */ + COLOR_YUV422_PACK_ORDER_VYUY, /*!< VYUY */ +} color_yuv422_pack_order_t; + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/huk_hal.h b/components/hal/include/hal/huk_hal.h similarity index 96% rename from components/hal/esp32p4/include/hal/huk_hal.h rename to components/hal/include/hal/huk_hal.h index 796f2b8f9439..e158f1fc664f 100644 --- a/components/hal/esp32p4/include/hal/huk_hal.h +++ b/components/hal/include/hal/huk_hal.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -// The HAL layer for Hardware Unique Key (HUK) Genarator +// The HAL layer for Hardware Unique Key (HUK) Generator #pragma once diff --git a/components/hal/include/hal/isp_types.h b/components/hal/include/hal/isp_types.h index ae7d001f5b32..974c5a3d354b 100644 --- a/components/hal/include/hal/isp_types.h +++ b/components/hal/include/hal/isp_types.h @@ -393,6 +393,31 @@ typedef union { uint32_t val; ///< 32-bit color saturation value } isp_color_saturation_t; +/*--------------------------------------------------------------- + LSC +---------------------------------------------------------------*/ +#if SOC_ISP_LSC_SUPPORTED +#define ISP_LSC_GRAD_RATIO_INT_BITS SOC_ISP_LSC_GRAD_RATIO_INT_BITS +#define ISP_LSC_GRAD_RATIO_DEC_BITS SOC_ISP_LSC_GRAD_RATIO_DEC_BITS +#define ISP_LSC_GRAD_RATIO_RES_BITS SOC_ISP_LSC_GRAD_RATIO_RES_BITS +#else +#define ISP_LSC_GRAD_RATIO_INT_BITS 2 +#define ISP_LSC_GRAD_RATIO_DEC_BITS 8 +#define ISP_LSC_GRAD_RATIO_RES_BITS 22 +#endif + +/** + * @brief LSC gain + */ +typedef union { + struct { + uint32_t decimal:8; ///< Integer part + uint32_t integer:2; ///< Decimal part + uint32_t reserved:ISP_LSC_GRAD_RATIO_RES_BITS; ///< Reserved + }; + uint32_t val; ///< 32-bit gradient ratio value +} isp_lsc_gain_t; + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/key_mgr_hal.h b/components/hal/include/hal/key_mgr_hal.h similarity index 94% rename from components/hal/esp32p4/include/hal/key_mgr_hal.h rename to components/hal/include/hal/key_mgr_hal.h index 3bed3fa3fd13..8a3ca092dcaa 100644 --- a/components/hal/esp32p4/include/hal/key_mgr_hal.h +++ b/components/hal/include/hal/key_mgr_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -37,11 +37,11 @@ void key_mgr_hal_set_key_usage(const esp_key_mgr_key_type_t key_type, const esp_ */ esp_key_mgr_key_usage_t key_mgr_hal_get_key_usage(const esp_key_mgr_key_type_t key_type); -/* @brief Configure the key purpose to be used by the Key Manager for key generator opearation */ +/* @brief Configure the key purpose to be used by the Key Manager for key generator operation */ void key_mgr_hal_set_key_purpose(const esp_key_mgr_key_purpose_t key_purpose); /** - * @bfief Configure the mode which is used by the Key Manager for the generator key deployement process + * @bfief Configure the mode which is used by the Key Manager for the generator key deployment process */ void key_mgr_hal_set_key_generator_mode(const esp_key_mgr_key_generator_mode_t mode); @@ -131,11 +131,11 @@ uint32_t key_mgr_hal_get_date_info(void); /** * @brief Set the Key Manager date information - * Only the least siginificant 28 bits shall be considered + * Only the least significant 28 bits shall be considered */ void key_mgr_hal_set_date_info(const uint32_t date_info); #ifdef __cplusplus } #endif -#endif +#endif /* SOC_KEY_MANAGER_SUPPORTED */ diff --git a/components/hal/include/hal/lcd_types.h b/components/hal/include/hal/lcd_types.h index 1bff0f6472d8..5fbdb1aea27f 100644 --- a/components/hal/include/hal/lcd_types.h +++ b/components/hal/include/hal/lcd_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +48,16 @@ typedef enum { LCD_COLOR_PIXEL_FORMAT_RGB888 = COLOR_PIXEL_RGB888, /*!< 24 bits, 8 bits per R/G/B value */ } lcd_color_rgb_pixel_format_t; +/** + * @brief LCD color format + */ +typedef enum { + LCD_COLOR_FMT_RGB565 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB565), ///< RGB565 + LCD_COLOR_FMT_RGB666 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB666), ///< RGB666 + LCD_COLOR_FMT_RGB888 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB888), ///< RGB888 + LCD_COLOR_FMT_YUV422 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422), ///< YUV422 +} lcd_color_format_t; + /** * @brief LCD color range */ @@ -73,6 +83,17 @@ typedef enum { LCD_YUV_CONV_STD_BT709 = COLOR_CONV_STD_RGB_YUV_BT709, /*!< YUV<->RGB conversion standard: BT.709 */ } lcd_yuv_conv_std_t; + +/** + * @brief YUV422 packing order + */ +typedef enum { + LCD_YUV422_PACK_ORDER_YUYV = COLOR_YUV422_PACK_ORDER_YUYV, /*!< YUYV */ + LCD_YUV422_PACK_ORDER_YVYU = COLOR_YUV422_PACK_ORDER_YVYU, /*!< YVYU */ + LCD_YUV422_PACK_ORDER_UYVY = COLOR_YUV422_PACK_ORDER_UYVY, /*!< UYVY */ + LCD_YUV422_PACK_ORDER_VYUY = COLOR_YUV422_PACK_ORDER_VYUY, /*!< VYUY */ +} lcd_yuv422_pack_order_t; + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/mipi_dsi_hal.h b/components/hal/include/hal/mipi_dsi_hal.h index 7ec69da23eeb..e3e43b2b3bbb 100644 --- a/components/hal/include/hal/mipi_dsi_hal.h +++ b/components/hal/include/hal/mipi_dsi_hal.h @@ -150,7 +150,7 @@ void mipi_dsi_hal_host_gen_read_short_packet(mipi_dsi_hal_context_t *hal, uint8_ * @param color_coding Color coding * @param sub_config Sub configuration */ -void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_rgb_pixel_format_t color_coding, uint32_t sub_config); +void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_format_t color_coding, uint32_t sub_config); /** * @brief Set horizontal timing parameters for DPI diff --git a/components/hal/include/hal/modem_clock_hal.h b/components/hal/include/hal/modem_clock_hal.h index dfc5009741b2..ec04d18d718e 100644 --- a/components/hal/include/hal/modem_clock_hal.h +++ b/components/hal/include/hal/modem_clock_hal.h @@ -29,7 +29,7 @@ void modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain); #endif -void modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable); +void modem_clock_hal_enable_modem_common_fe_clock(modem_clock_hal_context_t *hal, bool enable); void modem_clock_hal_enable_modem_private_fe_clock(modem_clock_hal_context_t *hal, bool enable); #if SOC_BT_SUPPORTED diff --git a/components/hal/include/hal/usb_utmi_hal.h b/components/hal/include/hal/usb_utmi_hal.h new file mode 100644 index 000000000000..dcb859a21c3e --- /dev/null +++ b/components/hal/include/hal/usb_utmi_hal.h @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc_caps.h" +#if (SOC_USB_UTMI_PHY_NUM > 0) +#include "soc/usb_utmi_struct.h" +#include "hal/usb_utmi_ll.h" +#endif // (SOC_USB_UTMI_PHY_NUM > 0) + +#ifdef __cplusplus +extern "C" { +#endif + +#if (SOC_USB_UTMI_PHY_NUM > 0) + +/** + * @brief HAL context type of USB UTMI driver + */ +typedef struct { + usb_utmi_dev_t *dev; +} usb_utmi_hal_context_t; + +/** + * @brief Sets UTMI defaults + * + * Enable clock, reset the peripheral, sets default options (LS support, disconnection detection) + * + * @param[in] hal USB UTMI HAL context + */ +void _usb_utmi_hal_init(usb_utmi_hal_context_t *hal); + +#if SOC_RCC_IS_INDEPENDENT +#define usb_utmi_hal_init(...) _usb_utmi_hal_init(__VA_ARGS__) +#else +// Use a macro to wrap the function, force the caller to use it in a critical section +// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define usb_utmi_hal_init(...) do {(void)__DECLARE_RCC_ATOMIC_ENV; _usb_utmi_hal_init(__VA_ARGS__);} while(0) +#endif + +/** + * @brief Disable UTMI + * + * Disable clock to the peripheral + */ +void _usb_utmi_hal_disable(void); + +#if SOC_RCC_IS_INDEPENDENT +#define usb_utmi_hal_disable(...) _usb_utmi_hal_disable(__VA_ARGS__) +#else +// Use a macro to wrap the function, force the caller to use it in a critical section +// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define usb_utmi_hal_disable(...) do {(void)__DECLARE_RCC_ATOMIC_ENV; _usb_utmi_hal_disable(__VA_ARGS__);} while(0) +#endif + +#endif // (SOC_USB_UTMI_PHY_NUM > 0) + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/usb_wrap_hal.h b/components/hal/include/hal/usb_wrap_hal.h index ceb69f365272..8477b6927d08 100644 --- a/components/hal/include/hal/usb_wrap_hal.h +++ b/components/hal/include/hal/usb_wrap_hal.h @@ -8,17 +8,17 @@ #include #include "soc/soc_caps.h" -#if SOC_USB_OTG_SUPPORTED +#if (SOC_USB_OTG_PERIPH_NUM > 0) #include "soc/usb_wrap_struct.h" #include "hal/usb_wrap_ll.h" -#endif +#endif // (SOC_USB_OTG_PERIPH_NUM > 0) #include "hal/usb_wrap_types.h" #ifdef __cplusplus extern "C" { #endif -#if SOC_USB_OTG_SUPPORTED +#if (SOC_USB_OTG_PERIPH_NUM > 0) /** * @brief HAL context type of USB WRAP driver @@ -89,7 +89,7 @@ static inline void usb_wrap_hal_phy_test_mode_set_signals(usb_wrap_hal_context_t usb_wrap_ll_phy_test_mode_set_signals(hal->dev, vals); } -#endif // SOC_USB_OTG_SUPPORTED +#endif // (SOC_USB_OTG_PERIPH_NUM > 0) #ifdef __cplusplus } diff --git a/components/hal/include/hal/usb_wrap_types.h b/components/hal/include/hal/usb_wrap_types.h index 9d3310fb0654..a8727f0ef8a6 100644 --- a/components/hal/include/hal/usb_wrap_types.h +++ b/components/hal/include/hal/usb_wrap_types.h @@ -13,7 +13,7 @@ extern "C" { #endif -#if SOC_USB_OTG_SUPPORTED +#if (SOC_USB_OTG_PERIPH_NUM > 0) /** * @brief USB WRAP pull up/down resistor override values @@ -46,7 +46,7 @@ typedef struct { bool rx_rcv; /**< Differential receive data from D+ and D- lines */ } usb_wrap_test_mode_vals_t; -#endif // SOC_USB_OTG_SUPPORTED +#endif // (SOC_USB_OTG_PERIPH_NUM > 0) #ifdef __cplusplus } diff --git a/components/hal/mipi_dsi_hal.c b/components/hal/mipi_dsi_hal.c index 06565f7c372e..0a7f4c3c58b2 100644 --- a/components/hal/mipi_dsi_hal.c +++ b/components/hal/mipi_dsi_hal.c @@ -206,10 +206,10 @@ void mipi_dsi_hal_host_gen_read_short_packet(mipi_dsi_hal_context_t *hal, uint8_ while (!mipi_dsi_host_ll_gen_is_read_fifo_empty(hal->host)) { temp = mipi_dsi_host_ll_gen_read_payload_fifo(hal->host); for (int i = 0; i < 4; i++) { - if ((counter + i) < buffer_size) { - receive_buffer[counter + i] = (temp >> (8 * i)) & 0xFF; + if (counter < buffer_size) { + receive_buffer[counter] = (temp >> (8 * i)) & 0xFF; + counter++; } - counter++; } } } @@ -220,7 +220,7 @@ void mipi_dsi_hal_host_gen_read_dcs_command(mipi_dsi_hal_context_t *hal, uint8_t mipi_dsi_hal_host_gen_read_short_packet(hal, vc, MIPI_DSI_DT_DCS_READ_0, header_data, ret_param, param_buf_size); } -void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_rgb_pixel_format_t color_coding, uint32_t sub_config) +void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_format_t color_coding, uint32_t sub_config) { mipi_dsi_host_ll_dpi_set_color_coding(hal->host, color_coding, sub_config); mipi_dsi_brg_ll_set_pixel_format(hal->bridge, color_coding, sub_config); diff --git a/components/hal/test_apps/crypto/README.md b/components/hal/test_apps/crypto/README.md index 4e2c6f4f57a3..3b25adda8abb 100644 --- a/components/hal/test_apps/crypto/README.md +++ b/components/hal/test_apps/crypto/README.md @@ -67,7 +67,8 @@ This contains tests for the following features of the crypto peripherals: - SHA-512/256 - SHA-512/t -> **_NOTE:_** The verification tests for the HMAC and Digital Signature peripherals would get exercised in only in an FPGA environment. +> **_NOTE:_** The verification tests for the HMAC and Digital Signature peripherals would get exercised only by enabling the example config in an FPGA environment. + # Burning the HMAC key The HMAC tests need an HMAC key to be burned in the `BLOCK_KEY3` and `BLOCK_KEY4` of the efuses. As this verification application is independent of the efuse component, the user needs to manually burn the keys and their key purposes using `espefuse.py`. diff --git a/components/hal/test_apps/crypto/main/Kconfig.projbuild b/components/hal/test_apps/crypto/main/Kconfig.projbuild index 051c5bae14bc..ee68e84f19b9 100644 --- a/components/hal/test_apps/crypto/main/Kconfig.projbuild +++ b/components/hal/test_apps/crypto/main/Kconfig.projbuild @@ -1,6 +1,14 @@ menu "Test App Configuration" + config CRYPTO_TEST_APP_ENABLE_FPGA_TESTS + bool "Allow enabling the crypto tests that require burning efuses" + default y if IDF_ENV_FPGA + default n + help + This includes the crypto tests that actually require burning some efuses. + It is better to run these tests on an FPGA to avoid mistakenly burning eFuses. + config CRYPTO_TEST_APP_ENABLE_DS_TESTS bool "Enable DS Peripheral test cases" default y diff --git a/components/hal/test_apps/crypto/main/app_main.c b/components/hal/test_apps/crypto/main/app_main.c index 460445a343a5..87dcee3d8efb 100644 --- a/components/hal/test_apps/crypto/main/app_main.c +++ b/components/hal/test_apps/crypto/main/app_main.c @@ -34,7 +34,7 @@ static void run_all_tests(void) RUN_TEST_GROUP(key_manager); #endif -#if CONFIG_IDF_ENV_FPGA +#if CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS #if CONFIG_SOC_HMAC_SUPPORTED && CONFIG_CRYPTO_TEST_APP_ENABLE_HMAC_TESTS RUN_TEST_GROUP(hmac); @@ -48,7 +48,7 @@ static void run_all_tests(void) RUN_TEST_GROUP(ecdsa) #endif -#endif /* CONFIG_IDF_ENV_FPGA */ +#endif /* CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS */ } static void test_task(void *pvParameters) diff --git a/components/hal/test_apps/crypto/main/key_manager/test_key_manager.c b/components/hal/test_apps/crypto/main/key_manager/test_key_manager.c index ca424eb13213..2def4096e8f5 100644 --- a/components/hal/test_apps/crypto/main/key_manager/test_key_manager.c +++ b/components/hal/test_apps/crypto/main/key_manager/test_key_manager.c @@ -263,7 +263,7 @@ static void key_mgr_test_ecdsa_random_mode(void) TEST_ASSERT_EQUAL(ESP_OK, esp_key_mgr_deactivate_key(key_recovery_info.key_type)); } -#if CONFIG_IDF_ENV_FPGA +#if CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS static void test_xts_aes_key_random_mode(void) { @@ -351,7 +351,7 @@ TEST(key_manager, ecdsa_key_random_deployment) key_mgr_test_ecdsa_random_mode(); } -#if CONFIG_IDF_ENV_FPGA +#if CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS TEST(key_manager, xts_key_random_deployment) { key_mgr_test_xts_aes_128_random_mode(); @@ -367,7 +367,7 @@ TEST_GROUP_RUNNER(key_manager) RUN_TEST_CASE(key_manager, xts_key_ecdh0_deployment); RUN_TEST_CASE(key_manager, ecdsa_key_ecdh0_deployment); RUN_TEST_CASE(key_manager, ecdsa_key_random_deployment); -#if CONFIG_IDF_ENV_FPGA +#if CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS RUN_TEST_CASE(key_manager, xts_key_random_deployment); #endif diff --git a/components/hal/usb_dwc_hal.c b/components/hal/usb_dwc_hal.c index bcc8870ed474..b6f3201b71a4 100644 --- a/components/hal/usb_dwc_hal.c +++ b/components/hal/usb_dwc_hal.c @@ -11,6 +11,7 @@ #include "sdkconfig.h" #include "soc/chip_revision.h" #include "soc/usb_dwc_cfg.h" +#include "soc/usb_dwc_periph.h" #include "hal/usb_dwc_hal.h" #include "hal/usb_dwc_ll.h" #include "hal/efuse_hal.h" @@ -18,14 +19,6 @@ // ------------------------------------------------ Macros and Types --------------------------------------------------- -// TODO: Remove target specific section after support for multiple USB peripherals is implemented -#include "sdkconfig.h" -#if (CONFIG_IDF_TARGET_ESP32P4) -#define USB_BASE USB_DWC_HS -#else -#define USB_BASE USB_DWC -#endif - // ---------------------- Constants ------------------------ #define BENDPOINTADDRESS_NUM_MSK 0x0F //Endpoint number mask of the bEndpointAddress field of an endpoint descriptor @@ -118,10 +111,14 @@ static void set_defaults(usb_dwc_hal_context_t *hal) //GUSBCFG register usb_dwc_ll_gusbcfg_dis_hnp_cap(hal->dev); //Disable HNP usb_dwc_ll_gusbcfg_dis_srp_cap(hal->dev); //Disable SRP -#if (OTG_HSPHY_INTERFACE != 0) - usb_dwc_ll_gusbcfg_set_timeout_cal(hal->dev, 5); // 5 PHY clocks for our HS PHY - usb_dwc_ll_gusbcfg_set_utmi_phy(hal->dev); -#endif // (OTG_HSPHY_INTERFACE != 0) + + // Check if this USB-DWC supports HS PHY, if yes, use it + uint32_t ghwcfg[4]; + usb_dwc_ll_ghwcfg_get_hw_config(hal->dev, &ghwcfg[0], &ghwcfg[1], &ghwcfg[2], &ghwcfg[3]); + if (((usb_dwc_ghwcfg2_reg_t)ghwcfg[1]).hsphytype != 0) { + usb_dwc_ll_gusbcfg_set_timeout_cal(hal->dev, 5); // 5 PHY clocks for our HS PHY + usb_dwc_ll_gusbcfg_set_utmi_phy(hal->dev); + } //Enable interruts usb_dwc_ll_gintmsk_dis_intrs(hal->dev, 0xFFFFFFFF); //Mask all interrupts first usb_dwc_ll_gintmsk_en_intrs(hal->dev, CORE_INTRS_EN_MSK); //Unmask global interrupts @@ -134,7 +131,7 @@ static void set_defaults(usb_dwc_hal_context_t *hal) void usb_dwc_hal_init(usb_dwc_hal_context_t *hal) { //Check if a peripheral is alive by reading the core ID registers - usb_dwc_dev_t *dev = &USB_BASE; + usb_dwc_dev_t *dev = USB_DWC_LL_GET_HW(0); uint32_t core_id = usb_dwc_ll_gsnpsid_get_id(dev); HAL_ASSERT(core_id == CORE_REG_GSNPSID); (void) core_id; //Suppress unused variable warning if asserts are disabled @@ -270,7 +267,7 @@ void usb_dwc_hal_port_enable(usb_dwc_hal_context_t *hal) bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj, void *chan_ctx) { - HAL_ASSERT(hal->flags.fifo_sizes_set); //FIFO sizes should be set befor attempting to allocate a channel + HAL_ASSERT(hal->flags.fifo_sizes_set); //FIFO sizes should be set before attempting to allocate a channel //Attempt to allocate channel if (hal->channels.num_allocd == OTG_NUM_HOST_CHAN) { return false; //Out of free channels diff --git a/components/hal/usb_utmi_hal.c b/components/hal/usb_utmi_hal.c new file mode 100644 index 000000000000..cb7ceb49ba23 --- /dev/null +++ b/components/hal/usb_utmi_hal.c @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/usb_utmi_ll.h" +#include "hal/usb_utmi_hal.h" + +void _usb_utmi_hal_init(usb_utmi_hal_context_t *hal) +{ + hal->dev = &USB_UTMI; + _usb_utmi_ll_enable_bus_clock(true); + _usb_utmi_ll_reset_register(); + + /* + Additional setting to solve missing DCONN event on ESP32P4 (IDF-9953). + + Note: On ESP32P4, the HP_SYSTEM_OTG_SUSPENDM is not connected to 1 by hardware. + For correct detection of the device detaching, internal signal should be set to 1 by the software. + */ + usb_utmi_ll_enable_precise_detection(true); + usb_utmi_ll_configure_ls(hal->dev, true); +} + +void _usb_utmi_hal_disable(void) +{ + _usb_utmi_ll_enable_bus_clock(false); +} diff --git a/components/ieee802154/driver/esp_ieee802154_dev.c b/components/ieee802154/driver/esp_ieee802154_dev.c index 5376f1924110..6ce02905bc49 100644 --- a/components/ieee802154/driver/esp_ieee802154_dev.c +++ b/components/ieee802154/driver/esp_ieee802154_dev.c @@ -161,7 +161,7 @@ uint8_t ieee802154_get_recent_lqi(void) return s_rx_frame_info[s_recent_rx_frame_info_index].lqi; } -IEEE802154_STATIC void set_next_rx_buffer(void) +IEEE802154_STATIC IEEE802154_NOINLINE void set_next_rx_buffer(void) { uint8_t* next_rx_buffer = NULL; uint8_t index = 0; @@ -194,7 +194,7 @@ IEEE802154_STATIC void set_next_rx_buffer(void) ieee802154_ll_set_rx_addr(next_rx_buffer); } -static bool stop_rx(void) +IEEE802154_NOINLINE static bool stop_rx(void) { ieee802154_ll_events events; @@ -210,7 +210,7 @@ static bool stop_rx(void) return true; } -static bool stop_tx_ack(void) +IEEE802154_NOINLINE static bool stop_tx_ack(void) { ieee802154_set_cmd(IEEE802154_CMD_STOP); @@ -221,7 +221,7 @@ static bool stop_tx_ack(void) return true; } -static bool stop_tx(void) +IEEE802154_NOINLINE static bool stop_tx(void) { ieee802154_ll_events events; @@ -245,21 +245,21 @@ static bool stop_tx(void) return true; } -static bool stop_cca(void) +IEEE802154_NOINLINE static bool stop_cca(void) { ieee802154_set_cmd(IEEE802154_CMD_STOP); ieee802154_ll_clear_events(IEEE802154_EVENT_ED_DONE | IEEE802154_EVENT_RX_ABORT); return true; } -static bool stop_tx_cca(void) +IEEE802154_NOINLINE static bool stop_tx_cca(void) { stop_tx(); // in case the transmission already started ieee802154_ll_clear_events(IEEE802154_EVENT_TX_ABORT); return true; } -static bool stop_rx_ack(void) +IEEE802154_NOINLINE static bool stop_rx_ack(void) { ieee802154_ll_events events; @@ -281,7 +281,7 @@ static bool stop_rx_ack(void) return true; } -static bool stop_ed(void) +IEEE802154_NOINLINE static bool stop_ed(void) { ieee802154_set_cmd(IEEE802154_CMD_STOP); @@ -290,7 +290,7 @@ static bool stop_ed(void) return true; } -IEEE802154_STATIC bool stop_current_operation(void) +IEEE802154_NOINLINE IEEE802154_STATIC bool stop_current_operation(void) { event_end_process(); switch (s_ieee802154_state) { @@ -469,11 +469,10 @@ static IRAM_ATTR void isr_handle_ack_rx_done(void) NEEDS_NEXT_OPT(true); } -static IRAM_ATTR void isr_handle_rx_phase_rx_abort(void) +static IRAM_ATTR void isr_handle_rx_phase_rx_abort(ieee802154_ll_rx_abort_reason_t rx_abort_reason) { event_end_process(); uint32_t rx_status = ieee802154_ll_get_rx_status(); - ieee802154_ll_rx_abort_reason_t rx_abort_reason = ieee802154_ll_get_rx_abort_reason(); switch (rx_abort_reason) { case IEEE802154_RX_ABORT_BY_RX_STOP: case IEEE802154_RX_ABORT_BY_TX_ACK_STOP: @@ -508,13 +507,12 @@ static IRAM_ATTR void isr_handle_rx_phase_rx_abort(void) NEEDS_NEXT_OPT(true); } -static IRAM_ATTR void isr_handle_tx_ack_phase_rx_abort(void) +static IRAM_ATTR void isr_handle_tx_ack_phase_rx_abort(ieee802154_ll_rx_abort_reason_t rx_abort_reason) { event_end_process(); #if CONFIG_IEEE802154_TEST uint32_t rx_status = ieee802154_ll_get_rx_status(); #endif - ieee802154_ll_rx_abort_reason_t rx_abort_reason = ieee802154_ll_get_rx_abort_reason(); switch (rx_abort_reason) { case IEEE802154_RX_ABORT_BY_RX_STOP: case IEEE802154_RX_ABORT_BY_TX_ACK_STOP: @@ -553,10 +551,9 @@ static IRAM_ATTR void isr_handle_tx_ack_phase_rx_abort(void) NEEDS_NEXT_OPT(true); } -static IRAM_ATTR void isr_handle_tx_abort(void) +static IRAM_ATTR void isr_handle_tx_abort(ieee802154_ll_tx_abort_reason_t tx_abort_reason) { event_end_process(); - ieee802154_ll_tx_abort_reason_t tx_abort_reason = ieee802154_ll_get_tx_abort_reason(); switch (tx_abort_reason) { case IEEE802154_TX_ABORT_BY_RX_ACK_STOP: case IEEE802154_TX_ABORT_BY_TX_STOP: @@ -632,10 +629,12 @@ IEEE802154_STATIC IRAM_ATTR void ieee802154_exit_critical(void) portEXIT_CRITICAL(&s_ieee802154_spinlock); } -static void ieee802154_isr(void *arg) +IEEE802154_NOINLINE static void ieee802154_isr(void *arg) { ieee802154_enter_critical(); ieee802154_ll_events events = ieee802154_ll_get_events(); + ieee802154_ll_rx_abort_reason_t rx_abort_reason = ieee802154_ll_get_rx_abort_reason(); + ieee802154_ll_tx_abort_reason_t tx_abort_reason = ieee802154_ll_get_tx_abort_reason(); IEEE802154_PROBE(events); @@ -643,7 +642,7 @@ static void ieee802154_isr(void *arg) if (events & IEEE802154_EVENT_RX_ABORT) { // First phase rx abort process, will clear RX_ABORT event in second. - isr_handle_rx_phase_rx_abort(); + isr_handle_rx_phase_rx_abort(rx_abort_reason); } if (events & IEEE802154_EVENT_RX_SFD_DONE) { @@ -701,12 +700,12 @@ static void ieee802154_isr(void *arg) if (events & IEEE802154_EVENT_RX_ABORT) { // Second phase rx abort process, clears RX_ABORT event. - isr_handle_tx_ack_phase_rx_abort(); + isr_handle_tx_ack_phase_rx_abort(rx_abort_reason); events &= (uint16_t)(~IEEE802154_EVENT_RX_ABORT); } if (events & IEEE802154_EVENT_TX_ABORT) { - isr_handle_tx_abort(); + isr_handle_tx_abort(tx_abort_reason); events &= (uint16_t)(~IEEE802154_EVENT_TX_ABORT); } @@ -879,7 +878,7 @@ esp_err_t ieee802154_transmit(const uint8_t *frame, bool cca) return ieee802154_transmit_internal(frame, cca); } -static inline bool is_target_time_expired(uint32_t target, uint32_t now) +IEEE802154_NOINLINE static bool is_target_time_expired(uint32_t target, uint32_t now) { return (((now - target) & (1 << 31)) == 0); } diff --git a/components/ieee802154/driver/esp_ieee802154_pib.c b/components/ieee802154/driver/esp_ieee802154_pib.c index 2c52a6ca8bf4..8654d5cef1e1 100644 --- a/components/ieee802154/driver/esp_ieee802154_pib.c +++ b/components/ieee802154/driver/esp_ieee802154_pib.c @@ -45,7 +45,7 @@ void ieee802154_pib_init(void) set_pending(); } -static uint8_t ieee802154_txpower_convert(int8_t txpower) +IEEE802154_NOINLINE static uint8_t ieee802154_txpower_convert(int8_t txpower) { uint8_t ieee820154_txpower_index = 0; if (txpower >= IEEE802154_TXPOWER_VALUE_MAX) { diff --git a/components/ieee802154/include/esp_ieee802154_types.h b/components/ieee802154/include/esp_ieee802154_types.h index 0b83cf2eed56..8c551f75526a 100644 --- a/components/ieee802154/include/esp_ieee802154_types.h +++ b/components/ieee802154/include/esp_ieee802154_types.h @@ -9,6 +9,8 @@ #include #include +#define US_PER_SYMBLE 16 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/ieee802154/linker.lf b/components/ieee802154/linker.lf index e78d00a5dbc7..8f57bdff951d 100644 --- a/components/ieee802154/linker.lf +++ b/components/ieee802154/linker.lf @@ -44,7 +44,6 @@ entries: esp_ieee802154_dev: ieee802154_receive (noflash) esp_ieee802154_pib: ieee802154_pib_update (noflash) esp_ieee802154_pib: ieee802154_txpower_convert (noflash) - esp_ieee802154_pib: ieee802154_set_panid_addr (noflash) esp_ieee802154_util: ieee802154_channel_to_freq (noflash) esp_ieee802154: esp_ieee802154_transmit_at (noflash) esp_ieee802154: esp_ieee802154_receive_at (noflash) @@ -55,7 +54,6 @@ entries: esp_ieee802154: esp_ieee802154_enh_ack_generator (noflash) esp_ieee802154: esp_ieee802154_get_extended_address (noflash) esp_ieee802154: esp_ieee802154_set_transmit_security (noflash) - esp_ieee802154_pib: ieee802154_pib_get_extended_address (noflash) if OPENTHREAD_LINK_METRICS = y: esp_ieee802154: esp_ieee802154_get_recent_lqi (noflash) diff --git a/components/log/CMakeLists.txt b/components/log/CMakeLists.txt index e162bfb85379..0743b16e724e 100644 --- a/components/log/CMakeLists.txt +++ b/components/log/CMakeLists.txt @@ -1,6 +1,7 @@ idf_build_get_property(target IDF_TARGET) +idf_build_get_property(non_os_build NON_OS_BUILD) -if(BOOTLOADER_BUILD) +if(non_os_build) set(system_target "noos") else() if(${target} STREQUAL "linux") @@ -15,7 +16,7 @@ set(srcs "src/${system_target}/log_timestamp.c" "src/${system_target}/log_lock.c") set(priv_requires "") -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) list(APPEND priv_requires soc hal esp_hw_support) list(APPEND srcs "src/os/log_write.c") diff --git a/components/log/Kconfig.format b/components/log/Kconfig.format index ba0c6286ed8e..e743dabff2e5 100644 --- a/components/log/Kconfig.format +++ b/components/log/Kconfig.format @@ -2,7 +2,7 @@ menu "Format" config LOG_COLORS bool "Color" - default y + default n help Enable ANSI terminal color codes. In order to view these, your terminal program must support ANSI color codes. diff --git a/components/log/include/esp_log.h b/components/log/include/esp_log.h index 8d11d9ca94d5..e2cb068f436b 100644 --- a/components/log/include/esp_log.h +++ b/components/log/include/esp_log.h @@ -101,7 +101,7 @@ void esp_log_writev(esp_log_level_t level, const char* tag, const char* format, esp_rom_printf(LOG_FORMAT(log_tag_letter, format), esp_log_timestamp(), tag, ##__VA_ARGS__); \ }} while(0) -#ifndef BOOTLOADER_BUILD +#ifndef NON_OS_BUILD #if defined(__cplusplus) && (__cplusplus > 201703L) #define ESP_LOGE( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, tag, format __VA_OPT__(,) __VA_ARGS__) #define ESP_LOGW( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN, tag, format __VA_OPT__(,) __VA_ARGS__) @@ -147,7 +147,7 @@ void esp_log_writev(esp_log_level_t level, const char* tag, const char* format, /// macro to output logs at ``ESP_LOG_VERBOSE`` level. @see ``ESP_LOGE`` #define ESP_LOGV( tag, format, ... ) ESP_EARLY_LOGV(tag, format, ##__VA_ARGS__) #endif // !(defined(__cplusplus) && (__cplusplus > 201703L)) -#endif // BOOTLOADER_BUILD +#endif // !NON_OS_BUILD /** runtime macro to output logs at a specified level. * diff --git a/components/log/include/esp_log_buffer.h b/components/log/include/esp_log_buffer.h index d5726f5e2bf7..5453061403b5 100644 --- a/components/log/include/esp_log_buffer.h +++ b/components/log/include/esp_log_buffer.h @@ -13,7 +13,7 @@ extern "C" { #endif -#if !BOOTLOADER_BUILD || __DOXYGEN__ +#if !NON_OS_BUILD || __DOXYGEN__ /** * @brief Logs a buffer of hexadecimal bytes at the specified log level. @@ -173,7 +173,7 @@ static inline void esp_log_buffer_char(const char *tag, const void *buffer, uint } /** @endcond */ -#endif // !BOOTLOADER_BUILD || __DOXYGEN__ +#endif // !NON_OS_BUILD || __DOXYGEN__ #ifdef __cplusplus } diff --git a/components/log/include/esp_log_level.h b/components/log/include/esp_log_level.h index 80aeaa5ac1da..1f10660b992c 100644 --- a/components/log/include/esp_log_level.h +++ b/components/log/include/esp_log_level.h @@ -37,12 +37,12 @@ typedef enum { #endif // !BOOTLOADER_BUILD #endif // LOG_LOCAL_LEVEL -#if BOOTLOADER_BUILD +#ifdef NON_OS_BUILD #define _ESP_LOG_ENABLED(log_level) (LOG_LOCAL_LEVEL >= (log_level)) #define _ESP_LOG_EARLY_ENABLED(log_level) _ESP_LOG_ENABLED(log_level) -#else // !BOOTLOADER_BUILD +#else // !NON_OS_BUILD #if CONFIG_LOG_MASTER_LEVEL #define _ESP_LOG_ENABLED(log_level) (esp_log_get_level_master() >= (log_level) && LOG_LOCAL_LEVEL >= (log_level)) @@ -54,7 +54,7 @@ typedef enum { currently configured min log level are higher than the log level */ #define _ESP_LOG_EARLY_ENABLED(log_level) (LOG_LOCAL_LEVEL >= (log_level) && esp_log_get_default_level() >= (log_level)) -#endif // !BOOTLOADER_BUILD +#endif // !NON_OS_BUILD /** @endcond */ diff --git a/components/log/src/log_timestamp_common.c b/components/log/src/log_timestamp_common.c index ba9521908f5c..7905899da5b4 100644 --- a/components/log/src/log_timestamp_common.c +++ b/components/log/src/log_timestamp_common.c @@ -12,7 +12,7 @@ #include "esp_private/log_timestamp.h" #include "sdkconfig.h" -#if !BOOTLOADER_BUILD +#ifndef NON_OS_BUILD #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -60,7 +60,7 @@ char *esp_log_system_timestamp(void) } return buffer; } -#endif // !BOOTLOADER_BUILD +#endif // !NON_OS_BUILD uint64_t esp_log_timestamp64(bool critical) { diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 231536c39d85..33f87955b22f 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -433,6 +433,20 @@ menu "LWIP" Enabling this option allows DHCP server to support temporary static ARP entries for DHCP Client. This will help the DHCP server to send the DHCP OFFER and DHCP ACK using IP unicast. + config LWIP_DHCPS_ADD_DNS + bool "Always add DNS option in DHCP responses" + default y + depends on LWIP_DHCPS + help + This allows the DNS option to be optional in the DHCP offers, + depending on the server's runtime configuration. + When enabled, the DHCP server will always add the DNS option to DHCP responses. + If a DNS server is not explicitly configured, the server's IP address will be used + as the fallback for the DNS option. + When disabled, the DHCP server will only include the DNS option in responses + if a DNS server has been explicitly configured. + This option will be removed in IDF v6.x + endmenu # DHCPS menuconfig LWIP_AUTOIP @@ -730,8 +744,8 @@ menu "LWIP" int "The maximum number of pbufs queued on OOSEQ per pcb" depends on LWIP_TCP_QUEUE_OOSEQ range 0 12 - default 4 if !SPIRAM_TRY_ALLOCATE_WIFI_LWIP - default 0 if SPIRAM_TRY_ALLOCATE_WIFI_LWIP + default 4 if !(SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) + default 0 if (SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) help If LWIP_TCP_OOSEQ_MAX_PBUFS = 0, TCP will not control the number of OOSEQ pbufs. @@ -787,7 +801,7 @@ menu "LWIP" config LWIP_WND_SCALE bool "Support TCP window scale" - depends on SPIRAM_TRY_ALLOCATE_WIFI_LWIP + depends on (SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) default n help Enable this feature to support TCP window scaling. diff --git a/components/lwip/apps/dhcpserver/dhcpserver.c b/components/lwip/apps/dhcpserver/dhcpserver.c index e6abfd743cf3..8859e52c63bf 100644 --- a/components/lwip/apps/dhcpserver/dhcpserver.c +++ b/components/lwip/apps/dhcpserver/dhcpserver.c @@ -454,18 +454,22 @@ static u8_t *add_offer_options(dhcps_t *dhcps, u8_t *optptr) } } - *optptr++ = DHCP_OPTION_DNS_SERVER; - *optptr++ = 4; if (dhcps_dns_enabled(dhcps->dhcps_dns)) { + *optptr++ = DHCP_OPTION_DNS_SERVER; + *optptr++ = 4; *optptr++ = ip4_addr1(&dhcps->dns_server); *optptr++ = ip4_addr2(&dhcps->dns_server); *optptr++ = ip4_addr3(&dhcps->dns_server); *optptr++ = ip4_addr4(&dhcps->dns_server); +#ifdef CONFIG_LWIP_DHCPS_ADD_DNS }else { + *optptr++ = DHCP_OPTION_DNS_SERVER; + *optptr++ = 4; *optptr++ = ip4_addr1(&ipadd); *optptr++ = ip4_addr2(&ipadd); *optptr++ = ip4_addr3(&ipadd); *optptr++ = ip4_addr4(&ipadd); +#endif /* CONFIG_LWIP_DHCPS_ADD_DNS */ } ip4_addr_t broadcast_addr = { .addr = (ipadd.addr & dhcps->dhcps_mask.addr) | ~dhcps->dhcps_mask.addr }; diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 93cb165b4345..d3f4fe40a7d6 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -61,7 +61,7 @@ if(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE) list(APPEND crt_paths ${custom_bundle_path}) endif() - list(APPEND args --input ${crt_paths} -q) + list(APPEND args --input ${crt_paths} -q --max-certs "${CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS}") get_filename_component(crt_bundle ${bundle_name} @@ -96,7 +96,13 @@ idf_build_get_property(python PYTHON) set(Python3_EXECUTABLE ${python}) # Needed to for include_next includes to work from within mbedtls -include_directories("${COMPONENT_DIR}/port/include") +set(include_dirs "${COMPONENT_DIR}/port/include") + +if(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE) + list(APPEND include_dirs "${COMPONENT_DIR}/esp_crt_bundle/include") +endif() + +include_directories(${include_dirs}) # Needed to for mbedtls_rom includes to work from within mbedtls if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL) diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 3c924631df72..1defa61db57c 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -667,6 +667,14 @@ menu "mbedTLS" help Enable MBEDTLS_SHA512_C adds support for SHA-384 and SHA-512. + config MBEDTLS_SHA3_C + bool "Enable the SHA3 cryptographic hash algorithm" + default n + help + Enabling MBEDTLS_SHA3_C adds support for SHA3. + Enabling this configuration option increases the flash footprint + by almost 4KB. + choice MBEDTLS_TLS_MODE bool "TLS Protocol Role" default MBEDTLS_TLS_SERVER_AND_CLIENT @@ -1103,12 +1111,12 @@ menu "mbedTLS" config MBEDTLS_ECP_FIXED_POINT_OPTIM bool "Enable fixed-point multiplication optimisations" depends on MBEDTLS_ECP_C - default y + default n help This configuration option enables optimizations to speedup (about 3 ~ 4 times) the ECP fixed point multiplication using pre-computed tables in the flash memory. - Disabling this configuration option saves flash footprint (about 29KB if all Elliptic Curve selected) - in the application binary. + Enabling this configuration option increases the flash footprint + (about 29KB if all Elliptic Curve selected) in the application binary. # end of Elliptic Curve options @@ -1192,4 +1200,14 @@ menu "mbedTLS" the flash footprint and hence care must be taken to keep some reserved space for the application binary in flash layout. + config MBEDTLS_FS_IO + bool "Enable functions that use the filesystem" + default y + depends on (VFS_SUPPORT_IO && VFS_SUPPORT_DIR) || IDF_TARGET_LINUX + help + This option enables functions in mbedTLS that use the filesystem. + It uses the default filesystem support for the target, + which is added through vfs component for ESP32 based targets or by + the host system when the target is Linux. + endmenu # mbedTLS diff --git a/components/mbedtls/esp_crt_bundle/esp_crt_bundle.c b/components/mbedtls/esp_crt_bundle/esp_crt_bundle.c index 2da385008778..65f817f7bdd2 100644 --- a/components/mbedtls/esp_crt_bundle/esp_crt_bundle.c +++ b/components/mbedtls/esp_crt_bundle/esp_crt_bundle.c @@ -1,79 +1,211 @@ /* - * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include +#include + +#include "esp_check.h" #include "esp_crt_bundle.h" #include "esp_log.h" -#define BUNDLE_HEADER_OFFSET 2 -#define CRT_HEADER_OFFSET 4 +#include "mbedtls/pk.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1.h" + +/* + Format of certificate bundle: + First, n uint32 "offset" entries, each describing the start of one certificate's data in terms of + bytes from the beginning of the bundle. This offset list is immediately followed by the 1st...n-th + certificate data. Hence, the first offset entry, i.e. the uint32 at the very start of the bundle, + is equal to the size of the offset list in bytes and therefore the # of certificates in the bundle + is [first offset]/sizeof(uint32_t) + [offset of 1st certificate](u32) + [offset of 2nd certificate](u32) + ... + [offset of n-th certificate](u32) + [1st certificate](variable) + ... + [n-th certificate](variable) + + Structure of each certificate: + [length of CN](u16) + [length of key](u16) + [CN](variable) + [key](variable) + + The offset list is used for fast random access to any certificate by index. + For verification, a certificate is looked up by its CN via binary search; for this reason, + the offset list *must* be sorted by CN (ascending) and the first certificate must be the + one with the least CN in the bundle, so that the first offset in the list still refers to the + first certificate after the list (see above). + +*/ + +#define CRT_NAME_LEN_OFFSET 0 //MBEDTLS_PRIVATE(sig_pk))) { - ESP_LOGE(TAG, "Simple compare failed"); - ret = -1; + if (unlikely(!mbedtls_pk_can_do(&pubkey, child->MBEDTLS_PRIVATE(sig_pk)))) { + ESP_LOGE(TAG, "Unsuitable public key"); + ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; goto cleanup; } md_info = mbedtls_md_info_from_type(child->MBEDTLS_PRIVATE(sig_md)); - if ( (ret = mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash )) != 0 ) { - ESP_LOGE(TAG, "Internal mbedTLS error %X", ret); + + if (unlikely(md_info == NULL)) { + ESP_LOGE(TAG, "Unknown message digest"); + ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; goto cleanup; } - if ( (ret = mbedtls_pk_verify_ext( child->MBEDTLS_PRIVATE(sig_pk), child->MBEDTLS_PRIVATE(sig_opts), &parent.pk, - child->MBEDTLS_PRIVATE(sig_md), hash, mbedtls_md_get_size( md_info ), - child->MBEDTLS_PRIVATE(sig).p, child->MBEDTLS_PRIVATE(sig).len )) != 0 ) { + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const unsigned char md_size = mbedtls_md_get_size(md_info); - ESP_LOGE(TAG, "PK verify failed with error %X", ret); + if ((ret = mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash)) != 0) { + ESP_LOGE(TAG, "MD failed with error 0x%x", -ret); + goto cleanup; + } + + if (unlikely((ret = mbedtls_pk_verify_ext(child->MBEDTLS_PRIVATE(sig_pk), child->MBEDTLS_PRIVATE(sig_opts), &pubkey, + child->MBEDTLS_PRIVATE(sig_md), hash, md_size, + child->MBEDTLS_PRIVATE(sig).p, child->MBEDTLS_PRIVATE(sig).len)) != 0)) { + ESP_LOGE(TAG, "PK verify failed with error 0x%x", -ret); goto cleanup; } -cleanup: - mbedtls_x509_crt_free(&parent); +cleanup: + mbedtls_pk_free(&pubkey); return ret; } +static cert_t esp_crt_find_cert(const unsigned char* const issuer, const size_t issuer_len) +{ + if (unlikely(issuer == NULL || issuer_len == 0)) { + return NULL; + } + + int start = 0; + int end = esp_crt_get_certcount(s_crt_bundle) - 1; + int middle = (start + end) / 2; + + cert_t cert = NULL; + size_t cert_name_len = 0; + + /* Look for the certificate using binary search on subject name */ + while (start <= end) { + cert = esp_crt_get_cert(s_crt_bundle, middle); + cert_name_len = esp_crt_get_name_len(cert); + + // Issuers are in DER encoding, with lengths encoded in the content; if valid DER, differing lengths + // are reflected in differing content. + // Still, we won't try to memcmp beyond the given length: + int cmp_res = memcmp(issuer, esp_crt_get_name(cert), MIN(issuer_len, cert_name_len)); + + if (unlikely(cmp_res == 0)) { + return cert; + } else if (cmp_res < 0) { + end = middle - 1; + } else { + start = middle + 1; + } + middle = (start + end) / 2; + } + + return NULL; +} + /* This callback is called for every certificate in the chain. If the chain * is proper each intermediate certificate is validated through its parent @@ -81,9 +213,9 @@ static int esp_crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_k * only verify the first untrusted link in the chain is signed by the * root certificate in the trusted bundle */ -int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_t *flags) +int esp_crt_verify_callback(void *buf, mbedtls_x509_crt* const crt, const int depth, uint32_t* const flags) { - mbedtls_x509_crt *child = crt; + const mbedtls_x509_crt* const child = crt; /* It's OK for a trusted cert to have a weak signature hash alg. as we already trust this certificate */ @@ -94,120 +226,119 @@ int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_ } - if (s_crt_bundle.crts == NULL) { + if (unlikely(s_crt_bundle == NULL)) { ESP_LOGE(TAG, "No certificates in bundle"); return MBEDTLS_ERR_X509_FATAL_ERROR; } - ESP_LOGD(TAG, "%d certificates in bundle", s_crt_bundle.num_certs); + ESP_LOGD(TAG, "%" PRIu16 " certificates in bundle", (uint16_t)esp_crt_get_certcount(s_crt_bundle)); - size_t name_len = 0; - const uint8_t *crt_name; + cert_t cert = esp_crt_find_cert(child->issuer_raw.p, child->issuer_raw.len); - bool crt_found = false; - int start = 0; - int end = s_crt_bundle.num_certs - 1; - int middle = (end - start) / 2; + if (likely(cert != NULL)) { - /* Look for the certificate using binary search on subject name */ - while (start <= end) { - name_len = s_crt_bundle.crts[middle][0] << 8 | s_crt_bundle.crts[middle][1]; - crt_name = s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET; + const int ret = esp_crt_check_signature(child, esp_crt_get_key(cert), esp_crt_get_key_len(cert)); - int cmp_res = memcmp(child->issuer_raw.p, crt_name, name_len ); - if (cmp_res == 0) { - crt_found = true; - break; - } else if (cmp_res < 0) { - end = middle - 1; + if (likely(ret == 0)) { + ESP_LOGI(TAG, "Certificate validated"); + *flags = 0; + return 0; } else { - start = middle + 1; + ESP_LOGE(TAG, "Certificate matched but signature verification failed"); +#if (CONFIG_LOG_DEFAULT_LEVEL_DEBUG || CONFIG_LOG_DEFAULT_LEVEL_VERBOSE) + char *cert_name = malloc((esp_crt_get_name_len(cert) + 1) * sizeof(char)); + if (cert_name) { + memcpy(cert_name, esp_crt_get_name(cert), esp_crt_get_name_len(cert)); + cert_name[esp_crt_get_name_len(cert)] = '\0'; + ESP_LOGE(TAG, "Certificate matched with %s but signature verification failed", cert_name); + free(cert_name); + } +#endif } - middle = (start + end) / 2; - } - - int ret = MBEDTLS_ERR_X509_FATAL_ERROR; - if (crt_found) { - size_t key_len = s_crt_bundle.crts[middle][2] << 8 | s_crt_bundle.crts[middle][3]; - ret = esp_crt_check_signature(child, s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET + name_len, key_len); - } - if (ret == 0) { - ESP_LOGI(TAG, "Certificate validated"); - *flags = 0; - return 0; + } else { + ESP_LOGI(TAG, "No matching trusted root certificate found"); } ESP_LOGE(TAG, "Failed to verify certificate"); - return MBEDTLS_ERR_X509_FATAL_ERROR; + return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED; } - -/* Initialize the bundle into an array so we can do binary search for certs, - the bundle generated by the python utility is already presorted by subject name +/** + * @brief Perform some consistency checks on the user-provided bundle data to try and make sure + * it actually is a certificate bundle. + * + * @param x509_bundle pointer to the bundle data + * @param bundle_size size of bundle data + * @return true the given bundle data is consistent + * @return false the given bundle data is invalid */ -static esp_err_t esp_crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_size) +static bool esp_crt_check_bundle(const uint8_t* const x509_bundle, const size_t bundle_size) { - if (bundle_size < BUNDLE_HEADER_OFFSET + CRT_HEADER_OFFSET) { - ESP_LOGE(TAG, "Invalid certificate bundle"); - return ESP_ERR_INVALID_ARG; + if (unlikely(x509_bundle == NULL || bundle_size <= (sizeof(uint32_t) + CRT_HEADER_SIZE))) { + // Bundle is too small for even one offset and one certificate + return false; } - uint16_t num_certs = (x509_bundle[0] << 8) | x509_bundle[1]; - if (num_certs > CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS) { - ESP_LOGE(TAG, "No. of certs in the certificate bundle = %d exceeds\n" - "Max allowed certificates in the certificate bundle = %d\n" - "Please update the menuconfig option with appropriate value", num_certs, CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS); - return ESP_ERR_INVALID_ARG; + // Pointer to the first offset entry + const uint32_t* offsets = (const uint32_t*)x509_bundle; + + if (unlikely(offsets[0] == 0 || (offsets[0] % sizeof(uint32_t)) != 0)) { + // First offset is invalid. + // The first certificate must start after N uint32_t offset values. + return false; } - const uint8_t **crts = calloc(num_certs, sizeof(x509_bundle)); - if (crts == NULL) { - ESP_LOGE(TAG, "Unable to allocate memory for bundle"); - return ESP_ERR_NO_MEM; + if (unlikely(offsets[0] >= bundle_size)) { + // First cert starts beyond end of bundle + return false; } - const uint8_t *cur_crt; - /* This is the maximum region that is allowed to access */ - const uint8_t *bundle_end = x509_bundle + bundle_size; - cur_crt = x509_bundle + BUNDLE_HEADER_OFFSET; + const uint32_t num_certs = esp_crt_get_certcount(x509_bundle); + + if (unlikely(num_certs > CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS)) { + ESP_LOGE(TAG, "Cert bundle certificates exceed max allowed certificates"); + return false; + } - for (int i = 0; i < num_certs; i++) { - crts[i] = cur_crt; - if (cur_crt + CRT_HEADER_OFFSET > bundle_end) { - ESP_LOGE(TAG, "Invalid certificate bundle"); - free(crts); - return ESP_ERR_INVALID_ARG; + // Check all offsets for consistency with certificate data + for (uint32_t i = 0; i < num_certs - 1; ++i) { + const uint32_t off = offsets[i]; + cert_t cert = x509_bundle + off; + // The next offset in the list must point to right after the current cert + const uint32_t expected_next_offset = off + esp_crt_get_len(cert); + + if (unlikely(offsets[i + 1] != expected_next_offset || expected_next_offset >= bundle_size)) { + return false; } - size_t name_len = cur_crt[0] << 8 | cur_crt[1]; - size_t key_len = cur_crt[2] << 8 | cur_crt[3]; - cur_crt = cur_crt + CRT_HEADER_OFFSET + name_len + key_len; } - if (cur_crt > bundle_end) { - ESP_LOGE(TAG, "Invalid certificate bundle"); - free(crts); + // All checks passed. + return true; +} + +/* + the bundle generated by the python utility is already presorted by subject name + */ +static esp_err_t esp_crt_bundle_init(const uint8_t* const x509_bundle, const size_t bundle_size) +{ + if (likely(esp_crt_check_bundle(x509_bundle, bundle_size))) { + s_crt_bundle = x509_bundle; + return ESP_OK; + } else { return ESP_ERR_INVALID_ARG; } - - /* The previous crt bundle is only updated when initialization of the - * current crt_bundle is successful */ - /* Free previous crt_bundle */ - free(s_crt_bundle.crts); - s_crt_bundle.num_certs = num_certs; - s_crt_bundle.crts = crts; - return ESP_OK; } esp_err_t esp_crt_bundle_attach(void *conf) { esp_err_t ret = ESP_OK; // If no bundle has been set by the user then use the bundle embedded in the binary - if (s_crt_bundle.crts == NULL) { + if (s_crt_bundle == NULL) { ret = esp_crt_bundle_init(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start); } - if (ret != ESP_OK) { + if (unlikely(ret != ESP_OK)) { ESP_LOGE(TAG, "Failed to attach bundle"); return ret; } @@ -218,8 +349,7 @@ esp_err_t esp_crt_bundle_attach(void *conf) * cacert_ptr passes non-NULL check during handshake */ mbedtls_ssl_config *ssl_conf = (mbedtls_ssl_config *)conf; - mbedtls_x509_crt_init(&s_dummy_crt); - mbedtls_ssl_conf_ca_chain(ssl_conf, &s_dummy_crt, NULL); + mbedtls_ssl_conf_ca_chain(ssl_conf, (mbedtls_x509_crt*)&s_dummy_crt, NULL); mbedtls_ssl_conf_verify(ssl_conf, esp_crt_verify_callback, NULL); } @@ -228,8 +358,7 @@ esp_err_t esp_crt_bundle_attach(void *conf) void esp_crt_bundle_detach(mbedtls_ssl_config *conf) { - free(s_crt_bundle.crts); - s_crt_bundle.crts = NULL; + s_crt_bundle = NULL; if (conf) { mbedtls_ssl_conf_verify(conf, NULL, NULL); } @@ -239,3 +368,8 @@ esp_err_t esp_crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size) { return esp_crt_bundle_init(x509_bundle, bundle_size); } + +bool esp_crt_bundle_in_use(const mbedtls_x509_crt* ca_chain) +{ + return ((ca_chain == &s_dummy_crt) ? true : false); +} diff --git a/components/mbedtls/esp_crt_bundle/gen_crt_bundle.py b/components/mbedtls/esp_crt_bundle/gen_crt_bundle.py index 0211514a4609..2e5bca544b19 100755 --- a/components/mbedtls/esp_crt_bundle/gen_crt_bundle.py +++ b/components/mbedtls/esp_crt_bundle/gen_crt_bundle.py @@ -8,18 +8,16 @@ # The bundle will have the format: number of certificates; crt 1 subject name length; crt 1 public key length; # crt 1 subject name; crt 1 public key; crt 2... # -# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - -from __future__ import with_statement - import argparse import csv import os import re import struct import sys -from io import open + +DEFAULT_CERT_BUNDLE_MAX_CERTS = 200 try: from cryptography import x509 @@ -54,9 +52,6 @@ def __init__(self): self.certificates = [] self.compressed_crts = [] - if os.path.isfile(ca_bundle_bin_file): - os.remove(ca_bundle_bin_file) - def add_from_path(self, crts_path): found = False @@ -116,11 +111,21 @@ def add_from_der(self, crt_str): self.certificates.append(x509.load_der_x509_certificate(crt_str, default_backend())) status('Successfully added 1 certificate') - def create_bundle(self): + def create_bundle(self, max_certs=DEFAULT_CERT_BUNDLE_MAX_CERTS): + if max_certs < len(self.certificates): + critical(f'No. of certs in the certificate bundle = {len(self.certificates)} exceeds\n \ + Max allowed certificates in the certificate bundle = {max_certs} \ + Please update the menuconfig option with appropriate value') + raise ValueError + # Sort certificates in order to do binary search when looking up certificates self.certificates = sorted(self.certificates, key=lambda cert: cert.subject.public_bytes(default_backend())) - bundle = struct.pack('>H', len(self.certificates)) + # List of offsets in bytes from the start of the bundle to each certificate inside + offsets = [] + len_offsets = 4 * len(self.certificates) # final size of the offsets list + + bundle = b'' for crt in self.certificates: """ Read the public key as DER format """ @@ -132,12 +137,18 @@ def create_bundle(self): name_len = len(sub_name_der) key_len = len(pub_key_der) - len_data = struct.pack('>HH', name_len, key_len) + len_data = struct.pack(' #include "esp_mbedtls_dynamic_impl.h" +#include "sdkconfig.h" + +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif #define COUNTER_SIZE (8) #define CACHE_IV_SIZE (16) @@ -532,7 +537,18 @@ void esp_mbedtls_free_cacert(mbedtls_ssl_context *ssl) if (ssl->MBEDTLS_PRIVATE(conf)->MBEDTLS_PRIVATE(ca_chain)) { mbedtls_ssl_config *conf = (mbedtls_ssl_config * )mbedtls_ssl_context_get_config(ssl); +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + /* In case of mbedtls certificate bundle, we attach a "static const" + * dummy cert, thus we need to avoid the write operations (memset()) + * performed by `mbedtls_x509_crt_free()` + */ + if (!esp_crt_bundle_in_use(conf->MBEDTLS_PRIVATE(ca_chain))) { + mbedtls_x509_crt_free(conf->MBEDTLS_PRIVATE(ca_chain)); + } +#else mbedtls_x509_crt_free(conf->MBEDTLS_PRIVATE(ca_chain)); +#endif + conf->MBEDTLS_PRIVATE(ca_chain) = NULL; } } diff --git a/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.h b/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.h index 72641b3a5495..ad7a716be588 100644 --- a/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.h +++ b/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.h @@ -24,6 +24,7 @@ #include "mbedtls/ssl.h" #include "mbedtls/platform.h" #include "esp_log.h" +#include "sdkconfig.h" #define TRACE_CHECK(_fn, _state) \ ({ \ diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index b057d09ec4e3..d1413571db78 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -901,7 +901,13 @@ * * Enable functions that use the filesystem. */ +#if CONFIG_MBEDTLS_FS_IO #define MBEDTLS_FS_IO +#else +#undef MBEDTLS_FS_IO +#undef MBEDTLS_PSA_ITS_FILE_C +#undef MBEDTLS_PSA_CRYPTO_STORAGE_C +#endif #ifndef CONFIG_IDF_TARGET_LINUX /** @@ -2554,6 +2560,21 @@ #undef MBEDTLS_SHA512_C #endif +/** + * \def MBEDTLS_SHA3_C + * + * Enable the SHA3 cryptographic hash algorithm. + * + * Module: library/sha3.c + * + * This module adds support for SHA3. + */ +#ifdef CONFIG_MBEDTLS_SHA3_C +#define MBEDTLS_SHA3_C +#else +#undef MBEDTLS_SHA3_C +#endif + /** * \def MBEDTLS_SSL_CACHE_C * diff --git a/components/mbedtls/test_apps/.build-test-rules.yml b/components/mbedtls/test_apps/.build-test-rules.yml index f33fabc474c3..0e72c8d3dc48 100644 --- a/components/mbedtls/test_apps/.build-test-rules.yml +++ b/components/mbedtls/test_apps/.build-test-rules.yml @@ -7,5 +7,6 @@ components/mbedtls/test_apps: - if: CONFIG_NAME == "ecdsa_sign" and SOC_ECDSA_SUPPORTED != 1 depends_components: - efuse - depends_filepatterns: - - components/mbedtls/port/ecdsa/* + - mbedtls + - esp_security + - esp_mm diff --git a/components/mbedtls/test_apps/main/crts/server_cert_bundle b/components/mbedtls/test_apps/main/crts/server_cert_bundle index 0b7f09aa06da..5a0a2f139f52 100644 Binary files a/components/mbedtls/test_apps/main/crts/server_cert_bundle and b/components/mbedtls/test_apps/main/crts/server_cert_bundle differ diff --git a/components/mbedtls/test_apps/main/test_aes.c b/components/mbedtls/test_apps/main/test_aes.c index 5ac71e82ec90..c73256e8d724 100644 --- a/components/mbedtls/test_apps/main/test_aes.c +++ b/components/mbedtls/test_apps/main/test_aes.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -67,7 +67,7 @@ static const uint8_t iv[] = { print(as_c_array(plain)) ct = encryptor.update(plain) + encryptor.finalize() - print("Chipertext: {}".format(as_c_array(ct))) + print("Ciphertext: {}".format(as_c_array(ct))) */ TEST_CASE("mbedtls CBC AES-256 test", "[aes]") { @@ -85,11 +85,11 @@ TEST_CASE("mbedtls CBC AES-256 test", "[aes]") memcpy(nonce, iv, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -100,19 +100,19 @@ TEST_CASE("mbedtls CBC AES-256 test", "[aes]") memset(decryptedtext, 0x0, SZ); // Encrypt - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, ciphertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - 32, 32); // Decrypt memcpy(nonce, iv, 16); mbedtls_aes_setkey_dec(&ctx, key_256, 256); - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, ciphertext, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -134,11 +134,11 @@ TEST_CASE("mbedtls CBC AES-256 DMA buffer align test", "[aes]") memcpy(nonce, iv, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -149,19 +149,19 @@ TEST_CASE("mbedtls CBC AES-256 DMA buffer align test", "[aes]") memset(decryptedtext, 0x0, SZ); // Encrypt - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, ciphertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - 32, 32); // Decrypt memcpy(nonce, iv, 16); mbedtls_aes_setkey_dec(&ctx, key_256, 256); - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, ciphertext, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -183,11 +183,11 @@ TEST_CASE("mbedtls CTR AES-256 test", "[aes]") memcpy(nonce, iv, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -198,19 +198,19 @@ TEST_CASE("mbedtls CTR AES-256 test", "[aes]") memset(decryptedtext, 0x0, SZ); // Encrypt - mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, plaintext, chipertext); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, plaintext, ciphertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - 32, 32); // Decrypt nc_off = 0; memcpy(nonce, iv, 16); - mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, chipertext, decryptedtext); + mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, ciphertext, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -231,11 +231,11 @@ TEST_CASE("mbedtls OFB AES-256 test", "[aes]") memcpy(nonce, iv, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -246,19 +246,19 @@ TEST_CASE("mbedtls OFB AES-256 test", "[aes]") memset(decryptedtext, 0x0, SZ); // Encrypt - mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, plaintext, chipertext); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, plaintext, ciphertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - 32, 32); // Decrypt nc_off = 0; memcpy(nonce, iv, 16); - mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, chipertext, decryptedtext); + mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, ciphertext, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -278,11 +278,11 @@ TEST_CASE("mbedtls CFB-8 AES-256 test", "[aes]") memcpy(nonce, iv, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -293,18 +293,18 @@ TEST_CASE("mbedtls CFB-8 AES-256 test", "[aes]") memset(decryptedtext, 0x0, SZ); // Encrypt - mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, ciphertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - 32, 32); // Decrypt memcpy(nonce, iv, 16); - mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext); + mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, ciphertext, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -325,11 +325,11 @@ TEST_CASE("mbedtls CFB-128 AES-256 test", "[aes]") memcpy(nonce, iv, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -340,19 +340,19 @@ TEST_CASE("mbedtls CFB-128 AES-256 test", "[aes]") memset(decryptedtext, 0x0, SZ); // Encrypt - mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, SZ, &nc_off, nonce, plaintext, chipertext); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, SZ, &nc_off, nonce, plaintext, ciphertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - 32, 32); // Decrypt nc_off = 0; memcpy(nonce, iv, 16); - mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, SZ, &nc_off, nonce, chipertext, decryptedtext); + mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, SZ, &nc_off, nonce, ciphertext, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -401,11 +401,11 @@ static void aes_ctr_stream_test(void) memset(key, 0x44, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -419,7 +419,7 @@ static void aes_ctr_stream_test(void) for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) { ESP_LOGD("test", "bytes_to_process %d", bytes_to_process); memset(nonce, 0xEE, 16); - memset(chipertext, 0x0, SZ); + memset(ciphertext, 0x0, SZ); memset(decryptedtext, 0x0, SZ); size_t offset = 0; @@ -429,12 +429,12 @@ static void aes_ctr_stream_test(void) size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process; mbedtls_aes_crypt_ctr(&ctx, length, &offset, nonce, - stream_block, plaintext + idx, chipertext + idx ); + stream_block, plaintext + idx, ciphertext + idx ); } ESP_LOG_BUFFER_HEXDUMP("expected", expected_cipher, SZ, ESP_LOG_DEBUG); - ESP_LOG_BUFFER_HEXDUMP("actual ", chipertext, SZ, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("actual ", ciphertext, SZ, ESP_LOG_DEBUG); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, ciphertext, SZ); // Decrypt memset(nonce, 0xEE, 16); @@ -444,7 +444,7 @@ static void aes_ctr_stream_test(void) // Limit length of last call to avoid exceeding buffer size size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process; mbedtls_aes_crypt_ctr(&ctx, length, &offset, nonce, - stream_block, chipertext + idx, decryptedtext + idx ); + stream_block, ciphertext + idx, decryptedtext + idx ); } ESP_LOG_BUFFER_HEXDUMP("decrypted", decryptedtext, SZ, ESP_LOG_DEBUG); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); @@ -452,7 +452,7 @@ static void aes_ctr_stream_test(void) mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -505,11 +505,11 @@ TEST_CASE("mbedtls OFB stream test", "[aes]") memset(key, 0x44, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -529,10 +529,10 @@ TEST_CASE("mbedtls OFB stream test", "[aes]") for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { // Limit length of last call to avoid exceeding buffer size size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; - mbedtls_aes_crypt_ofb(&ctx, length, &offset, iv, plaintext + idx, chipertext + idx); + mbedtls_aes_crypt_ofb(&ctx, length, &offset, iv, plaintext + idx, ciphertext + idx); } - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, ciphertext, SZ); // Decrypt memset(iv, 0xEE, 16); @@ -541,14 +541,14 @@ TEST_CASE("mbedtls OFB stream test", "[aes]") for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { // Limit length of last call to avoid exceeding buffer size size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process; - mbedtls_aes_crypt_ofb(&ctx, length, &offset, iv, chipertext + idx, decryptedtext + idx); + mbedtls_aes_crypt_ofb(&ctx, length, &offset, iv, ciphertext + idx, decryptedtext + idx); } TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); } mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -595,11 +595,11 @@ TEST_CASE("mbedtls CFB8 stream test", "[aes]") memset(key, 0x44, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -616,16 +616,16 @@ TEST_CASE("mbedtls CFB8 stream test", "[aes]") for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { // Limit length of last call to avoid exceeding buffer size size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; - mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_ENCRYPT, length, iv, plaintext + idx, chipertext + idx); + mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_ENCRYPT, length, iv, plaintext + idx, ciphertext + idx); } - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, ciphertext, SZ); memset(iv, 0xEE, 16); for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { // Limit length of last call to avoid exceeding buffer size size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; - mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_DECRYPT, length, iv, chipertext + idx, decryptedtext + idx); + mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_DECRYPT, length, iv, ciphertext + idx, decryptedtext + idx); } TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); @@ -633,7 +633,7 @@ TEST_CASE("mbedtls CFB8 stream test", "[aes]") mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -680,11 +680,11 @@ TEST_CASE("mbedtls CFB128 stream test", "[aes]") memset(key, 0x44, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -703,24 +703,24 @@ TEST_CASE("mbedtls CFB128 stream test", "[aes]") for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { // Limit length of last call to avoid exceeding buffer size size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; - mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, length, &offset, iv, plaintext + idx, chipertext + idx); + mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, length, &offset, iv, plaintext + idx, ciphertext + idx); } - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, ciphertext, SZ); offset = 0; memset(iv, 0xEE, 16); for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { // Limit length of last call to avoid exceeding buffer size size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; - mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, length, &offset, iv, chipertext + idx, decryptedtext + idx); + mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, length, &offset, iv, ciphertext + idx, decryptedtext + idx); } TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -804,11 +804,11 @@ TEST_CASE("mbedtls OFB, chained DMA descriptors", "[aes]") memcpy(nonce, iv, 16); // allocate internal memory - uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -819,20 +819,20 @@ TEST_CASE("mbedtls OFB, chained DMA descriptors", "[aes]") memset(decryptedtext, 0x0, SZ); // Encrypt - mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, plaintext, chipertext); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, plaintext, ciphertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - 32, 32); // Decrypt nc_off = 0; memcpy(nonce, iv, 16); - mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, chipertext, decryptedtext); + mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, ciphertext, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -858,11 +858,11 @@ void aes_ctr_alignment_test(uint32_t input_buf_caps, uint32_t output_buf_caps) memset(key, 0x1E, 16); // allocate memory according the requested caps - uint8_t *chipertext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, output_buf_caps); + uint8_t *ciphertext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, output_buf_caps); uint8_t *plaintext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, input_buf_caps); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(decryptedtext); @@ -877,14 +877,14 @@ void aes_ctr_alignment_test(uint32_t input_buf_caps, uint32_t output_buf_caps) // Encrypt with input buffer in external ram offset = 0; memset(nonce, 0x2F, 16); - mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, plaintext + i, chipertext + i); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_ctr_end, chipertext + i + SZ - 32, 32); + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, plaintext + i, ciphertext + i); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_ctr_end, ciphertext + i + SZ - 32, 32); // Decrypt offset = 0; memset(nonce, 0x2F, 16); // Decrypt with input buffer in instruction memory, the crypto DMA can't access this - mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext + i, decryptedtext); + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, ciphertext + i, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); @@ -892,7 +892,7 @@ void aes_ctr_alignment_test(uint32_t input_buf_caps, uint32_t output_buf_caps) mbedtls_aes_free(&ctx); free(plaintext); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -1483,10 +1483,10 @@ void aes_ext_flash_ctr_test(uint32_t output_buf_caps) memset(nonce, 0x2F, 16); memset(key, 0x1E, 16); - uint8_t *chipertext = heap_caps_malloc(SZ, output_buf_caps); + uint8_t *ciphertext = heap_caps_malloc(SZ, output_buf_caps); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(ciphertext); TEST_ASSERT_NOT_NULL(decryptedtext); mbedtls_aes_init(&ctx); @@ -1497,19 +1497,19 @@ void aes_ext_flash_ctr_test(uint32_t output_buf_caps) // Encrypt with input buffer in external flash offset = 0; memset(nonce, 0x2F, 16); - mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, long_input, chipertext); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_long_input_end, chipertext + SZ - 32, 32); + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, long_input, ciphertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_long_input_end, ciphertext + SZ - 32, 32); // Decrypt offset = 0; memset(nonce, 0x2F, 16); // Decrypt with input buffer in external flash, the crypto DMA can't access this - mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext, decryptedtext); + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, ciphertext, decryptedtext); TEST_ASSERT_EQUAL_HEX8_ARRAY(long_input, decryptedtext, SZ); mbedtls_aes_free(&ctx); - free(chipertext); + free(ciphertext); free(decryptedtext); } @@ -1540,7 +1540,8 @@ static void __attribute__((unused)) aes_ctr_stream_test_task(void *pv) vTaskDelete(NULL); } -#if CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK +#if CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK && !CONFIG_IDF_TARGET_ESP32H2 +// Not enough rtc memory for test on H2 TEST_CASE("mbedtls AES stack in RTC RAM", "[mbedtls]") { @@ -1561,9 +1562,9 @@ TEST_CASE("mbedtls AES stack in RTC RAM", "[mbedtls]") vSemaphoreDelete(done_sem); } -#endif //CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK +#endif //CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK && !CONFIG_IDF_TARGET_ESP32H2 -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC +#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM && CONFIG_SPIRAM_USE_MALLOC TEST_CASE("mbedtls AES stack in PSRAM", "[mbedtls]") { @@ -1585,4 +1586,4 @@ TEST_CASE("mbedtls AES stack in PSRAM", "[mbedtls]") vSemaphoreDelete(done_sem); } -#endif //CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC +#endif //CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM && CONFIG_SPIRAM_USE_MALLOC diff --git a/components/mbedtls/test_apps/main/test_esp_crt_bundle.c b/components/mbedtls/test_apps/main/test_esp_crt_bundle.c index 777af0425bdd..4b4ae1f927b0 100644 --- a/components/mbedtls/test_apps/main/test_esp_crt_bundle.c +++ b/components/mbedtls/test_apps/main/test_esp_crt_bundle.c @@ -6,8 +6,9 @@ * * SPDX-License-Identifier: Apache-2.0 * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2019-2024 Espressif Systems (Shanghai) CO LTD */ +#include #include "esp_err.h" #include "esp_log.h" @@ -41,6 +42,7 @@ extern const uint8_t server_cert_chain_pem_end[] asm("_binary_server_cert_chai extern const uint8_t server_pk_start[] asm("_binary_prvtkey_pem_start"); extern const uint8_t server_pk_end[] asm("_binary_prvtkey_pem_end"); +// `server_cert_bundle_corrupt` is created by generating the cert bundle using `server_root.pem` extern const uint8_t server_cert_bundle_start[] asm("_binary_server_cert_bundle_start"); extern const uint8_t server_cert_bundle_end[] asm("_binary_server_cert_bundle_end"); @@ -272,7 +274,7 @@ void client_task(void *pvParameters) goto exit; } - /* Test with default crt bundle that doesnt contain the ca crt */ + /* Test with default crt bundle that does not contain the ca crt */ ESP_LOGI(TAG, "Connecting to %s:%s...", SERVER_ADDRESS, SERVER_PORT); if ((ret = mbedtls_net_connect(&client.client_fd, SERVER_ADDRESS, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret); @@ -300,7 +302,7 @@ void client_task(void *pvParameters) } else { ESP_LOGE(TAG, "Certificate verification failed!"); } - TEST_ASSERT(res == ESP_CRT_VALIDATE_FAIL); + TEST_ASSERT_EQUAL(ESP_CRT_VALIDATE_FAIL, res); // Reset session before new connection mbedtls_ssl_close_notify(&client.ssl); @@ -338,7 +340,7 @@ void client_task(void *pvParameters) } else { ESP_LOGE(TAG, "Certificate verification failed!"); } - TEST_ASSERT(res == ESP_CRT_VALIDATE_OK); + TEST_ASSERT_EQUAL(ESP_CRT_VALIDATE_OK, res); // Reset session before new connection mbedtls_ssl_close_notify(&client.ssl); @@ -406,7 +408,7 @@ TEST_CASE("custom certificate bundle - weak hash", "[mbedtls]") mbedtls_x509_crt_init( &crt ); mbedtls_x509_crt_parse(&crt, bad_md_crt_pem_start, bad_md_crt_pem_end - bad_md_crt_pem_start); - TEST_ASSERT(mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL) == 0); + TEST_ASSERT_EQUAL(0, mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL)); mbedtls_x509_crt_free(&crt); @@ -426,62 +428,119 @@ TEST_CASE("custom certificate bundle - wrong signature", "[mbedtls]") /* esp32.com cert chain where 1 byte in the signature is changed */ printf("Testing certificate with wrong signature\n"); mbedtls_x509_crt_parse(&crt, wrong_sig_crt_pem_start, wrong_sig_crt_pem_end - wrong_sig_crt_pem_start); - TEST_ASSERT(mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL) != 0); + TEST_ASSERT_NOT_EQUAL(0, mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL)); mbedtls_x509_crt_free(&crt); mbedtls_x509_crt_init( &crt ); /* the correct esp32.com cert chain*/ printf("Testing certificate with correct signature\n"); mbedtls_x509_crt_parse(&crt, correct_sig_crt_pem_start, correct_sig_crt_pem_end - correct_sig_crt_pem_start); - TEST_ASSERT(mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL) == 0); + TEST_ASSERT_EQUAL(0, mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL)); mbedtls_x509_crt_free(&crt); esp_crt_bundle_detach(NULL); } -TEST_CASE("custom certificate bundle init API - bound checking", "[mbedtls]") +TEST_CASE("custom certificate bundle init API - bound checking - NULL certificate bundle", "[mbedtls]") { + esp_err_t esp_ret; + + /* The API should fail when NULL is passed as the bundle */ + esp_ret = esp_crt_bundle_set(NULL, 0); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ret); +} - uint8_t test_bundle[256] = {0}; +TEST_CASE("custom certificate bundle init API - bound checking - Invalid size of certificate bundle", "[mbedtls]") +{ + uint8_t test_bundle[1024] = {0}; esp_err_t esp_ret; + /* The API should fail with bundle size given as 1 */ esp_ret = esp_crt_bundle_set(test_bundle, 1); - TEST_ASSERT( esp_ret == ESP_ERR_INVALID_ARG); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ret); +} + +TEST_CASE("custom certificate bundle init API - bound checking - Invalid first certificate offset", "[mbedtls]") +{ + uint8_t test_bundle[1024] = {0}; + esp_err_t esp_ret; + + /* Check that the esp_crt_bundle_set API will not accept + * the first offset to be invalid */ + + /* The first certificate must start after N uint32_t offset values, + * thus, it cannot start from the 0th position */ + test_bundle[0] = 0; + esp_ret = esp_crt_bundle_set(test_bundle, sizeof(test_bundle)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ret); + + /* The first certificate must start after N uint32_t offset values, thus, + * the offset from where the it would start should be divisible by sizeof(uint32_t) */ + test_bundle[0] = 1; + esp_ret = esp_crt_bundle_set(test_bundle, sizeof(test_bundle)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ret); + + /* Check that the esp_crt_bundle_set API will not accept a bundle + * which in which the first cert starts beyond end of bundle*/ + uint8_t *dummy_test_bundle = test_bundle + sizeof(uint32_t); + + esp_ret = esp_crt_bundle_set(dummy_test_bundle, sizeof(test_bundle)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ret); +} + +TEST_CASE("custom certificate bundle init API - bound checking - Certificates count overflow", "[mbedtls]") +{ + uint8_t test_bundle[1024] = {0}; + esp_err_t esp_ret; + + memset(test_bundle, 0, sizeof(test_bundle)); /* Check that the esp_crt_bundle_set API will not accept a bundle * which has more no. of certs than configured in * CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS */ + *((uint32_t*) test_bundle) = ((CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS + 1) * sizeof(uint32_t)); - uint8_t rand; - esp_fill_random(&rand, 1); - test_bundle[0] = rand; + esp_ret = esp_crt_bundle_set(test_bundle, sizeof(test_bundle)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ret); - /* Make sure that the number of certs will always be greater than - * CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS */ - test_bundle[1] = rand + CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS; + esp_crt_bundle_detach(NULL); +} + +TEST_CASE("custom certificate bundle init API - bound checking - Incorrect certificate offset", "[mbedtls]") +{ + uint8_t test_bundle[1024] = {0}; + esp_err_t esp_ret; + + memset(test_bundle, 0, sizeof(test_bundle)); + + /* Check that the esp_crt_bundle_set API will not accept a bundle where + all offsets are not consistent with certificate data */ + + /* + | offset 1 | offset 2 | Cert 1 name len | Cert 1 key len | Cert 1 name | Cert 1 key | Cert 2 name len | ..... | + | ----- offsets ----- | + | ---------------------- Certificate 1 ---------------------- | + | ---- Certificate 2 ---- | + */ + + *((uint32_t*) &test_bundle[0]) = (2 * sizeof(uint32_t)); + *((uint16_t*) &test_bundle[8]) = 2; // Cert 1 name len + *((uint16_t*) &test_bundle[10]) = 4; // Cert 1 key len + + /* Correct offset of certificate 2 should be + = 2 * sizeof(uint32_t) (Offsets of 2 certs) + 2 * sizeof(uint16_t) (Cert name and len) + 2 (Cert 1 name len) + 4 (Cert 1 key len); + = 18 + */ + *((uint32_t*) &test_bundle[4]) = 16; // Incorrect certificate 2 offset esp_ret = esp_crt_bundle_set(test_bundle, sizeof(test_bundle)); - TEST_ASSERT( esp_ret == ESP_ERR_INVALID_ARG); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ret); - /* The API should fail with bundle_size < BUNDLE_HEADER_OFFSET (2) + CRT_HEADER_OFFSET (4) */ - test_bundle[0] = 0; - test_bundle[1] = 1; /* set num_certs = 1 */ - esp_ret = esp_crt_bundle_set(test_bundle, 5); - TEST_ASSERT(esp_ret == ESP_ERR_INVALID_ARG); - - /* Cert number is greater than actual certs present, The API should fail */ - /* Actual No. of certs present in bundle = 1, setting num_certs to 5 */ - test_bundle[1] = 5; /* num_certs */ - test_bundle[3] = 5; /* cert_1_name_len */ - test_bundle[5] = 10; /* cert_1_pub_key_len */ - /* Actual bundle size becomes BUNDLE_HEADER_OFFSET (2) + CRT_HEADER_OFFSET (4) + cert_1_name_len(5) + cert_1_pub_key_len(10) - * i.e. 21 bytes */ - esp_ret = esp_crt_bundle_set(test_bundle, 21); - TEST_ASSERT(esp_ret == ESP_ERR_INVALID_ARG); - - /* The API should fail if bundle_size < BUNDLE_HEADER_OFFSET (2) + CRT_HEADER_OFFSET (4) + cert_1_name_len(5) + cert_1_pub_key_len(10) */ - esp_ret = esp_crt_bundle_set(test_bundle, 20); - TEST_ASSERT(esp_ret == ESP_ERR_INVALID_ARG); + /* Check that the esp_crt_bundle_set API will not accept a bundle where + all offsets are not consistency with certificate data and the certificate + offsets exceeds the bundle size */ + *((uint32_t*) &test_bundle[4]) = sizeof(test_bundle) + 1; // Offset exceeds the test_bundle size - esp_crt_bundle_detach(NULL); + esp_ret = esp_crt_bundle_set(test_bundle, sizeof(test_bundle)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ret); } diff --git a/components/mbedtls/test_apps/main/test_mbedtls_sha.c b/components/mbedtls/test_apps/main/test_mbedtls_sha.c index 003b35db8b5a..5b6d71e2f3b8 100644 --- a/components/mbedtls/test_apps/main/test_mbedtls_sha.c +++ b/components/mbedtls/test_apps/main/test_mbedtls_sha.c @@ -563,7 +563,8 @@ TEST_CASE("mbedtls SHA256 PSRAM DMA large buffer", "[hw_crypto]") #endif //CONFIG_SPIRAM_USE_MALLOC -#if CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK +#if CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK && !CONFIG_IDF_TARGET_ESP32H2 +// Not enough rtc memory for test on H2 TEST_CASE("mbedtls SHA stack in RTC RAM", "[mbedtls]") { @@ -587,7 +588,7 @@ TEST_CASE("mbedtls SHA stack in RTC RAM", "[mbedtls]") #endif //CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC +#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM && CONFIG_SPIRAM_USE_MALLOC TEST_CASE("mbedtls SHA stack in PSRAM", "[mbedtls]") { @@ -609,4 +610,4 @@ TEST_CASE("mbedtls SHA stack in PSRAM", "[mbedtls]") vSemaphoreDelete(done_sem); } -#endif //CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC +#endif //CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM && CONFIG_SPIRAM_USE_MALLOC diff --git a/components/mbedtls/test_apps/pytest_mbedtls_ut.py b/components/mbedtls/test_apps/pytest_mbedtls_ut.py index f7b1437f5a7b..3614c8dcaa2a 100644 --- a/components/mbedtls/test_apps/pytest_mbedtls_ut.py +++ b/components/mbedtls/test_apps/pytest_mbedtls_ut.py @@ -27,6 +27,7 @@ def test_mbedtls_esp32_compiler_perf_opt(dut: Dut) -> None: @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c3 +@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -43,6 +44,7 @@ def test_mbedtls_aes_no_hw(dut: Dut) -> None: @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c5 +@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/mbedtls/test_apps/sdkconfig.ci.psram_all_ext b/components/mbedtls/test_apps/sdkconfig.ci.psram_all_ext index ad3452cf7b86..cd0e64116c8b 100644 --- a/components/mbedtls/test_apps/sdkconfig.ci.psram_all_ext +++ b/components/mbedtls/test_apps/sdkconfig.ci.psram_all_ext @@ -1,4 +1,4 @@ CONFIG_SPIRAM=y CONFIG_ESP_INT_WDT_TIMEOUT_MS=800 -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 diff --git a/components/mbedtls/test_apps/sdkconfig.ci.psram_all_ext_esp32p4_200m b/components/mbedtls/test_apps/sdkconfig.ci.psram_all_ext_esp32p4_200m index 1c29e19bb931..6ed71c76e361 100644 --- a/components/mbedtls/test_apps/sdkconfig.ci.psram_all_ext_esp32p4_200m +++ b/components/mbedtls/test_apps/sdkconfig.ci.psram_all_ext_esp32p4_200m @@ -1,7 +1,7 @@ CONFIG_IDF_TARGET="esp32p4" CONFIG_SPIRAM=y CONFIG_ESP_INT_WDT_TIMEOUT_MS=800 -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 CONFIG_IDF_EXPERIMENTAL_FEATURES=y diff --git a/components/newlib/CMakeLists.txt b/components/newlib/CMakeLists.txt index 0d05270881d4..c0af7ac692e9 100644 --- a/components/newlib/CMakeLists.txt +++ b/components/newlib/CMakeLists.txt @@ -1,4 +1,5 @@ idf_build_get_property(target IDF_TARGET) +idf_build_get_property(non_os_build NON_OS_BUILD) if(${target} STREQUAL "linux") return() # This component is not supported by the POSIX/Linux simulator @@ -6,7 +7,7 @@ endif() set(include_dirs "platform_include") -if(BOOTLOADER_BUILD) +if(non_os_build) # Bootloader builds need the platform_include directory (for assert.h), but nothing else idf_component_register(INCLUDE_DIRS platform_include) return() diff --git a/components/newlib/sbom.yml b/components/newlib/sbom.yml index f0fee8725557..496cb10c30b2 100644 --- a/components/newlib/sbom.yml +++ b/components/newlib/sbom.yml @@ -4,3 +4,6 @@ cpe: cpe:2.3:a:newlib_project:newlib:{}:*:*:*:*:*:*:* supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' originator: 'Organization: Red Hat Incorporated' description: An open-source C standard library implementation with additional features and patches from Espressif. +cve-exclude-list: + - cve: CVE-2024-30949 + reason: A vulnerability was discovered in the gettimeofday system call implementation within the RISC-V libgloss component of Newlib. ESP-IDF does not link against libgloss for RISC-V, hence the issue is not directly applicable. Still, the relevant fix has been patched through https://github.com/espressif/newlib-esp32/commit/047ba47013c2656a1e7838dc86cbc75aeeaa67a7 diff --git a/components/nvs_flash/host_test/nvs_host_test/CMakeLists.txt b/components/nvs_flash/host_test/nvs_host_test/CMakeLists.txt index 658d311f49f9..4234d2bcd002 100644 --- a/components/nvs_flash/host_test/nvs_host_test/CMakeLists.txt +++ b/components/nvs_flash/host_test/nvs_host_test/CMakeLists.txt @@ -5,4 +5,19 @@ set(COMPONENTS main) # This test app doesn't require FreeRTOS, using mock instead list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") +idf_build_set_property(COMPILE_DEFINITIONS "NO_DEBUG_STORAGE" APPEND) project(nvs_host_test) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/coverage_report/index.html" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + COMMAND gcovr --root $ENV{IDF_PATH}/components/nvs_flash --html-details + --exclude ${CMAKE_CURRENT_SOURCE_DIR}/managed_components/* + -o ${CMAKE_CURRENT_BINARY_DIR}/coverage_report/index.html ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generate coverage report" + ) + +add_custom_target(coverage + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + DEPENDS "coverage_report/index.html" + ) diff --git a/components/nvs_flash/host_test/nvs_host_test/README.md b/components/nvs_flash/host_test/nvs_host_test/README.md index 37c142df16d5..d7915b01228d 100644 --- a/components/nvs_flash/host_test/nvs_host_test/README.md +++ b/components/nvs_flash/host_test/nvs_host_test/README.md @@ -1,2 +1,31 @@ | Supported Targets | Linux | | ----------------- | ----- | + +# To build +Navigate to the host test folder and run the IDF build command for linux target + +``` +cd $IDF_PATH +. ./export.sh +cd components/nvs_flash/host_test/nvs_host_test +idf.py --preview set-target linux +idf.py build +``` + +# To run tests locally +Navigate to the IDF root directory and run the binary from there. This ensures all calls to relative paths from test cases are resolved correctly. +This is limitation of ci pipeline as it was not possible to specify the working directory of the host tests. + +``` +cd $IDF_PATH +./components/nvs_flash/host_test/nvs_host_test/build/nvs_host_test.elf +``` + +# To create coverage report +After running the tests, the coverage report can be generated following way. + +``` +cd components/nvs_flash/host_test/nvs_host_test +idf.py build coverage +open ./build/coverage_report/index.html +``` \ No newline at end of file diff --git a/components/nvs_flash/host_test/nvs_host_test/main/CMakeLists.txt b/components/nvs_flash/host_test/nvs_host_test/main/CMakeLists.txt index 27959af8ee29..d7260af4850b 100644 --- a/components/nvs_flash/host_test/nvs_host_test/main/CMakeLists.txt +++ b/components/nvs_flash/host_test/nvs_host_test/main/CMakeLists.txt @@ -12,6 +12,9 @@ idf_component_register(SRCS "test_nvs.cpp" REQUIRES nvs_flash PRIV_REQUIRES spi_flash) +target_compile_options(${COMPONENT_LIB} PUBLIC --coverage) +target_link_libraries(${COMPONENT_LIB} PUBLIC --coverage) + if(CMAKE_C_COMPILER_ID MATCHES "Clang") target_compile_options(${COMPONENT_LIB} PRIVATE -std=gnu++20) endif() diff --git a/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp b/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp index afc3dc5a74c6..431e8892037c 100644 --- a/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp +++ b/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp @@ -3742,7 +3742,7 @@ TEST_CASE("check and read data from partition generated via manufacturing utilit } } -TEST_CASE("nvs multiple write with same key but different types", "[nvs][xxx]") +TEST_CASE("nvs multiple write with same key but different types", "[nvs]") { PartitionEmulationFixture f(0, 10); diff --git a/components/nvs_flash/nvs_partition_tool/nvs_check.py b/components/nvs_flash/nvs_partition_tool/nvs_check.py index b6a4da3abafd..ca2cd4680a40 100644 --- a/components/nvs_flash/nvs_partition_tool/nvs_check.py +++ b/components/nvs_flash/nvs_partition_tool/nvs_check.py @@ -22,6 +22,22 @@ def check_partition_size(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> bool: + """ Checks if the partition is large enough and has enough pages + """ + if len(nvs_partition.raw_data) / 0x1000 < 3: + nvs_log.info( + nvs_log.yellow( + 'NVS Partition size must be at least 0x3000 (4kiB * 3 pages == 12kiB)!' + ) + ) + return False + if len(nvs_partition.raw_data) % 0x1000 != 0: + nvs_log.info( + nvs_log.yellow( + 'NVS Partition size must be a multiple of 0x1000 (4kiB)!' + ) + ) + return False if len(nvs_partition.pages) < 3: nvs_log.info( nvs_log.yellow( @@ -83,16 +99,22 @@ def check_page_crc(nvs_page: NVS_Page, nvs_log: NVS_Logger) -> bool: return False -def identify_entry_duplicates(entry: NVS_Entry, seen_written_entires: Dict[str, List[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]: +def identify_entry_duplicates(entry: NVS_Entry, entry_dict: Dict[str, List[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]: + """Identifies and logs written entries + + Part 1 of duplicate entry check mechanism + """ if entry.state == 'Written': - if entry.key in seen_written_entires: - seen_written_entires[entry.key].append(entry) + if entry.key in entry_dict: + entry_dict[entry.key].append(entry) else: - seen_written_entires[entry.key] = [entry] - return seen_written_entires + entry_dict[entry.key] = [entry] + return entry_dict def check_page_entries(nvs_page: NVS_Page, nvs_log: NVS_Logger) -> Dict[str, List[NVS_Entry]]: + """Checks entries in the given page (entry state, children CRC32, entry type, span and gathers blobs and namespaces) + """ seen_written_entires: Dict[str, List[NVS_Entry]] = {} for entry in nvs_page.entries: @@ -203,6 +225,11 @@ def check_page_entries(nvs_page: NVS_Page, nvs_log: NVS_Logger) -> Dict[str, Lis def filter_namespaces_fake_duplicates(duplicate_entries_dict: Dict[str, List[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]: + """Takes a dictionary of entries (as written) and returns a new dictionary with "fake" duplicates, + where entries which have the same key but under different namespaces are filtered out + + Use `filter_entry_duplicates()` to properly filter out all duplicates + """ new_duplicate_entries_dict: Dict[str, List[NVS_Entry]] = {} for key, duplicate_entries in duplicate_entries_dict.items(): seen_entries: List[NVS_Entry] = [] @@ -237,6 +264,11 @@ def filter_namespaces_fake_duplicates(duplicate_entries_dict: Dict[str, List[NVS def filter_blob_related_duplicates(duplicate_entries_dict: Dict[str, List[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]: + """Takes a dictionary of entries (as written) and returns a new dictionary with "fake" duplicates, + where entries related to blob index and blob data under the same namespace are filtered out + + Use `filter_entry_duplicates()` to properly filter out all duplicates + """ new_duplicate_entries_dict: Dict[str, List[NVS_Entry]] = {} for key, duplicate_entries in duplicate_entries_dict.items(): seen_blob_index: List[NVS_Entry] = [] @@ -298,9 +330,19 @@ def filter_blob_related_duplicates(duplicate_entries_dict: Dict[str, List[NVS_En return new_duplicate_entries_dict -def filter_entry_duplicates(seen_written_entires: Dict[str, List[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]: - duplicate_entries_list = {key: v for key, v in seen_written_entires.items() if len(v) > 1} +def filter_entry_duplicates(entries: Dict[str, List[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]: + """Takes a dictionary of (seen written) entries and outputs a new dictionary with "fake" duplicates filtered out, keeping only real duplicates in + + (i.e. duplicate keys under different namespaces and blob index and blob data having the same key under the same namespace are allowed + and should be filtered out) + + Part 2 of duplicate entry check mechanism + """ + # Only keep seen written entries which have been observerd multiple times (duplicates) + duplicate_entries_list = {key: v for key, v in entries.items() if len(v) > 1} + # Filter out "fake" duplicates 1 (duplicate keys under different namespaces are allowed) duplicate_entries_list_1 = filter_namespaces_fake_duplicates(duplicate_entries_list) + # Filter out "fake" duplicates 2 (blob index and blob data are allowed to have the same key even in the same namespace) duplicate_entries_list_2 = filter_blob_related_duplicates(duplicate_entries_list_1) return duplicate_entries_list_2 @@ -341,6 +383,8 @@ def print_entry_duplicates(duplicate_entries_list: Dict[str, List[NVS_Entry]], n def assemble_blobs(nvs_log: NVS_Logger) -> None: + """Assembles blob data from blob chunks + """ for chunk in blob_chunks: # chunk: NVS_Entry parent = blobs.get( @@ -361,6 +405,8 @@ def assemble_blobs(nvs_log: NVS_Logger) -> None: def check_blob_data(nvs_log: NVS_Logger) -> None: + """Checks blob data for missing chunks or data + """ for blob_key in blobs: blob_index = blobs[blob_key][0] blob_chunks = blobs[blob_key][1:] @@ -395,6 +441,8 @@ def check_blobs(nvs_log: NVS_Logger) -> None: def check_namespaces(nvs_log: NVS_Logger) -> None: + """Checks namespaces (entries using undefined namespace indexes, unused namespaces) + """ # Undefined namespace index check for used_ns in used_namespaces: key = found_namespaces.pop(used_ns, None) @@ -415,6 +463,9 @@ def check_namespaces(nvs_log: NVS_Logger) -> None: def reset_global_variables() -> None: + """Global variables need to be cleared out before calling `integrity_check()` multiple times from a script + (e.g. when running tests) to avoid incorrect output + """ global used_namespaces, found_namespaces, blobs, blob_chunks used_namespaces = {} found_namespaces = {} @@ -423,6 +474,8 @@ def reset_global_variables() -> None: def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None: + """Function for multi-stage integrity check of a NVS partition + """ # Partition size check check_partition_size(nvs_partition, nvs_log) @@ -431,18 +484,19 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None: seen_written_entires_all: Dict[str, List[NVS_Entry]] = {} + # Loop through all pages in the partition for page in nvs_partition.pages: # page: NVS_Page - # Print page header + # Print a page header if page.header['status'] == 'Empty': - # Check if page is truly empty + # Check if a page is truly empty check_empty_page_content(page, nvs_log) else: - # Check page header CRC32 + # Check a page header CRC32 check_page_crc(page, nvs_log) - # Check all entries + # Check all entries in a page seen_written_entires = check_page_entries(page, nvs_log) # Collect all seen written entries diff --git a/components/nvs_flash/nvs_partition_tool/nvs_parser.py b/components/nvs_flash/nvs_partition_tool/nvs_parser.py index 29b610b33b2e..a4bb3dae5700 100644 --- a/components/nvs_flash/nvs_partition_tool/nvs_parser.py +++ b/components/nvs_flash/nvs_partition_tool/nvs_parser.py @@ -64,8 +64,9 @@ def __init__(self, name: str, raw_data: bytearray): f'Given partition data is not aligned to page size ({len(raw_data)} % {nvs_const.page_size} = {len(raw_data)%nvs_const.page_size})' ) - # Divide partition into pages self.name = name + self.raw_data = raw_data + # Divide partition into pages self.pages = [] for i in range(0, len(raw_data), nvs_const.page_size): self.pages.append(NVS_Page(raw_data[i: i + nvs_const.page_size], i)) diff --git a/components/nvs_flash/nvs_partition_tool/test_nvs_gen_check.py b/components/nvs_flash/nvs_partition_tool/test_nvs_gen_check.py index 380943b481d1..5463abef6061 100644 --- a/components/nvs_flash/nvs_partition_tool/test_nvs_gen_check.py +++ b/components/nvs_flash/nvs_partition_tool/test_nvs_gen_check.py @@ -201,13 +201,20 @@ def setup_bad_mixed_same_key_different_page(nvs_obj: NVS) -> None: data_type = prim_types[i % len(prim_types)] nvs_partition_gen.write_entry(nvs_obj, f'test_{i}', 'data', data_type, str(i)) # Conflicting keys under "abcd" namespace - 6 duplicates nvs_partition_gen.write_entry(nvs_obj, 'lorem_string_key', 'data', 'string', 'abc') # Conflicting key for string - 7th duplicate - nvs_partition_gen.write_entry(nvs_obj, 'storage', 'namespace', '', '') # Conflicting namespace - 8th duplicate + + # Create new duplicates of storage namespace with an unsafe version of write_namespace function + nvs_obj.write_namespace_unsafe('storage') # Conflicting namespace - 8th duplicate (the function is only for testing) + nvs_partition_gen.write_entry(nvs_obj, 'storage2', 'namespace', '', '') # New namespace, ignored nvs_partition_gen.write_entry(nvs_obj, 'lorem_string_key', 'data', 'string', 'abc') # Should be ignored as is under different "storage2" namespace nvs_partition_gen.write_entry(nvs_obj, 'lorem_string', 'data', 'string', 'abc') # 3 conflicting keys under "storage2" namespace - 9th duplicate nvs_partition_gen.write_entry(nvs_obj, 'lorem_string', 'data', 'string', 'def') nvs_partition_gen.write_entry(nvs_obj, 'lorem_string', 'data', 'string', '123') + # This no longer (nvs generator version >= 0.1.5) creates a duplicate namespace entry, only changes + # the current used namespace index + nvs_partition_gen.write_entry(nvs_obj, 'storage', 'namespace', '', '') + def setup_bad_same_key_primitive(nvs_obj: NVS) -> None: nvs_partition_gen.write_entry(nvs_obj, 'storage', 'namespace', '', '') diff --git a/components/nvs_flash/test_nvs_host/Makefile b/components/nvs_flash/test_nvs_host/Makefile deleted file mode 100644 index 3ddb65185fba..000000000000 --- a/components/nvs_flash/test_nvs_host/Makefile +++ /dev/null @@ -1,113 +0,0 @@ -TEST_PROGRAM=test_nvs -all: $(TEST_PROGRAM) - -SOURCE_FILES = \ - $(addprefix ../src/, \ - nvs_types.cpp \ - nvs_api.cpp \ - nvs_page.cpp \ - nvs_pagemanager.cpp \ - nvs_storage.cpp \ - nvs_item_hash_list.cpp \ - nvs_handle_simple.cpp \ - nvs_handle_locked.cpp \ - nvs_partition_manager.cpp \ - nvs_partition.cpp \ - nvs_encrypted_partition.cpp \ - nvs_cxx_api.cpp \ - nvs_platform.cpp \ - ) \ - spi_flash_emulation.cpp \ - test_compressed_enum_table.cpp \ - test_spi_flash_emulation.cpp \ - test_intrusive_list.cpp \ - test_nvs.cpp \ - test_nvs_partition.cpp \ - test_partition_manager.cpp \ - test_partition_linux.cpp \ - main.cpp - -SOURCE_FILES_C = ../../esp_rom/linux/esp_rom_crc.c esp_err_check_mock.c - -ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1) -COMPILER := clang -else -COMPILER := gcc -endif - -CPPFLAGS += -I../private_include -I../include -I../src -I../../heap/include -I../../esp_rom/include -I../../esp_rom/include/linux -I../../esp_rom/linux/include/linux -I../../log/include -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../esp_partition/include -I ../../hal/include -I ../../xtensa/include -I ../../soc/linux/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb -CFLAGS += -fprofile-arcs -ftest-coverage -DLINUX_TARGET -DLINUX_HOST_LEGACY_TEST -CXXFLAGS += -std=c++11 -Wall -Werror -DLINUX_TARGET -DLINUX_HOST_LEGACY_TEST -LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage - -ifeq ($(shell uname -s),Linux) -LDFLAGS += -lbsd -endif - -ifeq ($(COMPILER),clang) -CFLAGS += -fsanitize=address -CXXFLAGS += -fsanitize=address -LDFLAGS += -fsanitize=address -endif - -OBJ_FILES = $(SOURCE_FILES:.cpp=.o) -OBJ_FILES_C = $(SOURCE_FILES_C:.c=.o) - -COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) -MBEDTLS_LIB := ../../mbedtls/mbedtls/library/libmbedcrypto.a - -$(OBJ_FILES): %.o: %.cpp -$(OBJ_FILES_C): %.c: %.c - -$(MBEDTLS_LIB): - $(MAKE) -C ../../mbedtls/mbedtls/ lib - -$(TEST_PROGRAM): $(OBJ_FILES) $(OBJ_FILES_C) $(MBEDTLS_LIB) | clean-coverage - g++ -o $@ $^ $(LDFLAGS) - -$(OUTPUT_DIR): - mkdir -p $(OUTPUT_DIR) - -test: $(TEST_PROGRAM) - ./$(TEST_PROGRAM) -d yes exclude:[long] - -long-test: $(TEST_PROGRAM) - ./$(TEST_PROGRAM) -d yes - -$(COVERAGE_FILES): $(TEST_PROGRAM) long-test - -coverage.info: $(COVERAGE_FILES) - find ../src/ -name "*.gcno" -exec gcov -r -pb {} + - lcov --capture --directory ../src --no-external --output-file coverage.info - -coverage_report: coverage.info - genhtml coverage.info --output-directory coverage_report - @echo "Coverage report is in coverage_report/index.html" - -clean-coverage: - rm -f $(COVERAGE_FILES) *.gcov - rm -rf coverage_report/ - rm -f coverage.info - -clean: clean-coverage - $(MAKE) -C ../../mbedtls/mbedtls/ clean - rm -f $(OBJ_FILES) $(OBJ_FILES_C) $(TEST_PROGRAM) - rm -f ../nvs_partition_generator/partition_single_page.bin - rm -f ../nvs_partition_generator/partition_multipage_blob.bin - rm -f ../nvs_partition_generator/partition_encrypted.bin - rm -f ../nvs_partition_generator/partition_encrypted_hmac.bin - rm -f ../nvs_partition_generator/partition_encrypted_using_keygen.bin - rm -f ../nvs_partition_generator/partition_encrypted_using_keyfile.bin - rm -f ../nvs_partition_generator/partition_encrypted_using_keygen_hmac.bin - rm -f ../nvs_partition_generator/partition_decrypted.bin - rm -f ../nvs_partition_generator/partition_decrypted_hmac.bin - rm -f ../nvs_partition_generator/partition_encoded.bin - rm -f ../nvs_partition_generator/Test-1-partition-encrypted-hmac.bin - rm -f ../nvs_partition_generator/Test-1-partition-encrypted.bin - rm -f ../nvs_partition_generator/Test-1-partition.bin - rm -f ../../../tools/mass_mfg/samples/sample_values_multipage_blob_created.csv - rm -f ../../../tools/mass_mfg/samples/sample_values_singlepage_blob_created.csv - - - -.PHONY: clean clean-coverage all test long-test diff --git a/components/nvs_flash/test_nvs_host/README.md b/components/nvs_flash/test_nvs_host/README.md deleted file mode 100644 index bad5b08cd875..000000000000 --- a/components/nvs_flash/test_nvs_host/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Build - -```bash -make -j 6 -``` - -# Run -* Run particular test case: -```bash -./test_nvs "" - -``` -* Run all quick tests: -```bash -./test_nvs -d yes exclude:[long] -``` - -* Run all tests (takes several hours) -```bash -./test_nvs -d yes -``` - diff --git a/components/nvs_flash/test_nvs_host/main.cpp b/components/nvs_flash/test_nvs_host/main.cpp deleted file mode 100644 index 0c7c351f437f..000000000000 --- a/components/nvs_flash/test_nvs_host/main.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define CATCH_CONFIG_MAIN -#include "catch.hpp" diff --git a/components/nvs_flash/test_nvs_host/sdkconfig.h b/components/nvs_flash/test_nvs_host/sdkconfig.h deleted file mode 100644 index 7a49e28578c1..000000000000 --- a/components/nvs_flash/test_nvs_host/sdkconfig.h +++ /dev/null @@ -1,6 +0,0 @@ -#define CONFIG_NVS_ENCRYPTION 1 -#define CONFIG_LOG_DEFAULT_LEVEL 3 -#define CONFIG_LOG_MAXIMUM_LEVEL 3 -#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 -#define CONFIG_IDF_TARGET_LINUX 1 -#define CONFIG_NVS_ASSERT_ERROR_CHECK 1 diff --git a/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp b/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp deleted file mode 100644 index fc153edf30f5..000000000000 --- a/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "esp_partition.h" -#include "spi_flash_emulation.h" -#include "spi_flash_mmap.h" - -static SpiFlashEmulator* s_emulator = nullptr; - -void spi_flash_emulator_set(SpiFlashEmulator* e) -{ - s_emulator = e; -} - -esp_err_t esp_partition_erase_range(const esp_partition_t* partition, - size_t offset, size_t size) -{ - if (!s_emulator) { - return ESP_ERR_FLASH_OP_TIMEOUT; - } - - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - if (size % sec_size != 0) { - return ESP_ERR_INVALID_SIZE; - } - - if (offset % sec_size != 0) { - return ESP_ERR_INVALID_ARG; - } - - size_t start_sector = offset / sec_size; - size_t num_sectors = size / sec_size; - for (size_t sector = start_sector; sector < (start_sector + num_sectors); sector++) { - if (!s_emulator->erase(sector)) { - return ESP_ERR_FLASH_OP_FAIL; - } - } - - return ESP_OK; -} - -esp_err_t esp_partition_read(const esp_partition_t* partition, - size_t src_offset, void* dst, size_t size) -{ - if (!s_emulator) { - return ESP_ERR_FLASH_OP_TIMEOUT; - } - - if (!s_emulator->read(reinterpret_cast(dst), src_offset, size)) { - return ESP_ERR_FLASH_OP_FAIL; - } - - return ESP_OK; -} - -esp_err_t esp_partition_read_raw(const esp_partition_t* partition, - size_t src_offset, void* dst, size_t size) -{ - if (!s_emulator) { - return ESP_ERR_FLASH_OP_TIMEOUT; - } - - if (!s_emulator->read(reinterpret_cast(dst), src_offset, size)) { - return ESP_ERR_FLASH_OP_FAIL; - } - - return ESP_OK; -} - -esp_err_t esp_partition_write(const esp_partition_t* partition, - size_t dst_offset, const void* src, size_t size) -{ - if (!s_emulator) { - return ESP_ERR_FLASH_OP_TIMEOUT; - } - - if (!s_emulator->write(dst_offset, reinterpret_cast(src), size)) { - return ESP_ERR_FLASH_OP_FAIL; - } - - return ESP_OK; -} - -esp_err_t esp_partition_write_raw(const esp_partition_t* partition, - size_t dst_offset, const void* src, size_t size) -{ - if (!s_emulator) { - return ESP_ERR_FLASH_OP_TIMEOUT; - } - - if (!s_emulator->write(dst_offset, reinterpret_cast(src), size)) { - return ESP_ERR_FLASH_OP_FAIL; - } - - return ESP_OK; -} - -// timing data for ESP8266, 160MHz CPU frequency, 80MHz flash frequency -// all values in microseconds -// values are for block sizes starting at 4 bytes and going up to 4096 bytes -static size_t readTimes[] = {7, 5, 6, 7, 11, 18, 32, 60, 118, 231, 459}; -static size_t writeTimes[] = {19, 23, 35, 57, 106, 205, 417, 814, 1622, 3200, 6367}; -static size_t blockEraseTime = 37142; - - -static size_t timeInterp(uint32_t bytes, size_t* lut) -{ - const int lut_size = sizeof(readTimes)/sizeof(readTimes[0]); - int lz = __builtin_clz(bytes / 4); - int log_size = 32 - lz; - size_t x2 = 1 << (log_size + 2); - size_t y2 = lut[std::min(log_size, lut_size - 1)]; - size_t x1 = 1 << (log_size + 1); - size_t y1 = lut[log_size - 1]; - return (bytes - x1) * (y2 - y1) / (x2 - x1) + y1; -} - -size_t SpiFlashEmulator::getReadOpTime(uint32_t bytes) -{ - return timeInterp(bytes, readTimes); -} - -size_t SpiFlashEmulator::getWriteOpTime(uint32_t bytes) -{ - return timeInterp(bytes, writeTimes); -} - -size_t SpiFlashEmulator::getEraseOpTime() -{ - return blockEraseTime; -} diff --git a/components/nvs_flash/test_nvs_host/spi_flash_emulation.h b/components/nvs_flash/test_nvs_host/spi_flash_emulation.h deleted file mode 100644 index 13db5ef17e3d..000000000000 --- a/components/nvs_flash/test_nvs_host/spi_flash_emulation.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef spi_flash_emulation_h -#define spi_flash_emulation_h - -#include -#include -#include -#include -#include "esp_partition.h" -#include "catch.hpp" - -class SpiFlashEmulator; - -void spi_flash_emulator_set(SpiFlashEmulator*); - -class SpiFlashEmulator -{ -public: - SpiFlashEmulator(size_t sectorCount) : mUpperSectorBound(sectorCount) - { - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - mData.resize(sectorCount * sec_size / 4, 0xffffffff); - mEraseCnt.resize(sectorCount); - spi_flash_emulator_set(this); - } - - SpiFlashEmulator(const char *filename) - { - load(filename); - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - // At least one page should be free, hence we create mData of size of 2 sectors. - mData.resize(mData.size() + sec_size / 4, 0xffffffff); - mUpperSectorBound = mData.size() * 4 / sec_size; - spi_flash_emulator_set(this); - } - - ~SpiFlashEmulator() - { - spi_flash_emulator_set(nullptr); - } - - bool read(uint32_t* dest, size_t srcAddr, size_t size) const - { - if (srcAddr % 4 != 0 || - size % 4 != 0 || - srcAddr + size > mData.size() * 4) { - return false; - } - - copy(begin(mData) + srcAddr / 4, begin(mData) + (srcAddr + size) / 4, dest); - - ++mReadOps; - mReadBytes += size; - mTotalTime += getReadOpTime(static_cast(size)); - return true; - } - - bool write(size_t dstAddr, const uint32_t* src, size_t size) - { - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - uint32_t sectorNumber = dstAddr/sec_size; - if (sectorNumber < mLowerSectorBound || sectorNumber >= mUpperSectorBound) { - WARN("invalid flash operation detected: erase sector=" << sectorNumber); - return false; - } - - if (dstAddr % 4 != 0 || - size % 4 != 0 || - dstAddr + size > mData.size() * 4) { - return false; - } - - for (size_t i = 0; i < size / 4; ++i) { - if (mFailCountdown != SIZE_MAX && mFailCountdown-- == 0) { - return false; - } - - uint32_t sv = src[i]; - size_t pos = dstAddr / 4 + i; - uint32_t& dv = mData[pos]; - - if (((~dv) & sv) != 0) { // are we trying to set some 0 bits to 1? - WARN("invalid flash operation detected: dst=" << dstAddr << " size=" << size << " i=" << i); - return false; - } - - dv = sv; - } - ++mWriteOps; - mWriteBytes += size; - mTotalTime += getWriteOpTime(static_cast(size)); - return true; - } - - bool erase(size_t sectorNumber) - { - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - size_t offset = sectorNumber * sec_size / 4; - if (offset > mData.size()) { - return false; - } - - if (sectorNumber < mLowerSectorBound || sectorNumber >= mUpperSectorBound) { - WARN("invalid flash operation detected: erase sector=" << sectorNumber); - return false; - } - - if (mFailCountdown != SIZE_MAX && mFailCountdown-- == 0) { - return false; - } - - std::fill_n(begin(mData) + offset, sec_size / 4, 0xffffffff); - - ++mEraseOps; - mEraseCnt[sectorNumber]++; - mTotalTime += getEraseOpTime(); - return true; - } - - void randomize(uint32_t seed) - { - std::random_device rd; - std::mt19937 gen(rd()); - gen.seed(seed); - std::generate_n(mData.data(), mData.size(), gen); - } - - size_t size() const - { - return mData.size() * 4; - } - - const uint32_t* words() const - { - return mData.data(); - } - - const uint8_t* bytes() const - { - return reinterpret_cast(mData.data()); - } - - void load(const char* filename) - { - const uint32_t sector_size = esp_partition_get_main_flash_sector_size(); - size_t sec_size = sector_size; - FILE* f = fopen(filename, "rb"); - fseek(f, 0, SEEK_END); - off_t size = ftell(f); - assert(size % sec_size == 0); - mData.resize(size / sizeof(uint32_t)); - fseek(f, 0, SEEK_SET); - auto s = fread(mData.data(), sec_size, size / sec_size, f); - assert(s == static_cast(size / sec_size)); - fclose(f); - } - - void save(const char* filename) - { - const uint32_t sector_size = esp_partition_get_main_flash_sector_size(); - size_t sec_size = sector_size; - FILE* f = fopen(filename, "wb"); - auto n_sectors = mData.size() * sizeof(uint32_t) / sec_size; - auto s = fwrite(mData.data(), sec_size, n_sectors, f); - assert(s == n_sectors); - fclose(f); - } - - void clearStats() - { - mReadBytes = 0; - mWriteBytes = 0; - mEraseOps = 0; - mReadOps = 0; - mWriteOps = 0; - mTotalTime = 0; - } - - size_t getReadOps() const - { - return mReadOps; - } - size_t getWriteOps() const - { - return mWriteOps; - } - size_t getEraseOps() const - { - return mEraseOps; - } - size_t getReadBytes() const - { - return mReadBytes; - } - size_t getWriteBytes() const - { - return mWriteBytes; - } - size_t getTotalTime() const - { - return mTotalTime; - } - - void setBounds(uint32_t lowerSector, uint32_t upperSector) { - mLowerSectorBound = lowerSector; - mUpperSectorBound = upperSector; - } - - void failAfter(uint32_t count) { - mFailCountdown = count; - } - - size_t getSectorEraseCount(uint32_t sector) const { - return mEraseCnt[sector]; - } - -protected: - static size_t getReadOpTime(uint32_t bytes); - static size_t getWriteOpTime(uint32_t bytes); - static size_t getEraseOpTime(); - - - std::vector mData; - std::vector mEraseCnt; - - mutable size_t mReadOps = 0; - mutable size_t mWriteOps = 0; - mutable size_t mReadBytes = 0; - mutable size_t mWriteBytes = 0; - mutable size_t mEraseOps = 0; - mutable size_t mTotalTime = 0; - size_t mLowerSectorBound = 0; - size_t mUpperSectorBound = 0; - - size_t mFailCountdown = SIZE_MAX; - -}; - - - -#endif /* spi_flash_emulation_h */ diff --git a/components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp b/components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp deleted file mode 100644 index 8e9781637fb3..000000000000 --- a/components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "catch.hpp" -#include "compressed_enum_table.hpp" -#include - -TEST_CASE("test if CompressedEnumTable works as expected", "[enumtable]") -{ - - enum class TEnum1 : uint32_t { - ZERO = 0, - ONE = 1, - TWO = 2, - THREE = 3, - }; - CompressedEnumTable table; - memset(table.data(), 0xff, table.byteSize()); - TEnum1 tmp; - for (size_t i = 0; i < table.count(); ++i) { - CHECK(table.get(i, &tmp) == ESP_OK); - CHECK(tmp == TEnum1::THREE); - } - - CHECK(table.set(0, TEnum1::ONE) == ESP_OK); - CHECK(table.set(1, TEnum1::TWO) == ESP_OK); - CHECK(table.set(2, TEnum1::ZERO) == ESP_OK); - CHECK(table.set(3, TEnum1::ONE) == ESP_OK); - CHECK(table.set(4, TEnum1::TWO) == ESP_OK); - CHECK(table.set(5, TEnum1::ZERO) == ESP_OK); - CHECK(table.set(6, TEnum1::ONE) == ESP_OK); - CHECK(table.set(7, TEnum1::TWO) == ESP_OK); - CHECK(table.set(8, TEnum1::ZERO) == ESP_OK); - CHECK(table.set(9, TEnum1::ZERO) == ESP_OK); - CHECK(table.set(10, TEnum1::ONE) == ESP_OK); - CHECK(table.set(11, TEnum1::TWO) == ESP_OK); -// table.set(12, ... - CHECK(table.set(13, TEnum1::ZERO) == ESP_OK); - CHECK(table.set(14, TEnum1::ONE) == ESP_OK); - CHECK(table.set(15, TEnum1::TWO) == ESP_OK); - - // b10010011100100001001001001001001 - // h 9 3 9 0 9 2 4 9 - - CHECK(table.data()[0] == 0x93909249); -} diff --git a/components/nvs_flash/test_nvs_host/test_fixtures.hpp b/components/nvs_flash/test_nvs_host/test_fixtures.hpp deleted file mode 100644 index 4ca5720dc52a..000000000000 --- a/components/nvs_flash/test_nvs_host/test_fixtures.hpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "nvs_partition.hpp" -#include "nvs_encrypted_partition.hpp" -#include "spi_flash_emulation.h" -#include "spi_flash_mmap.h" -#include "nvs.h" - -class PartitionEmulation : public nvs::Partition { -public: - PartitionEmulation(SpiFlashEmulator *spi_flash_emulator, - uint32_t address, - uint32_t size, - const char *partition_name = NVS_DEFAULT_PART_NAME) - : partition_name(partition_name), flash_emu(spi_flash_emulator), address(address), size(size) - { - assert(partition_name); - assert(flash_emu); - assert(size); - readonly = false; - } - - const char *get_partition_name() override - { - return partition_name; - } - - esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override - { - if (!flash_emu->read(reinterpret_cast(dst), src_offset, size)) { - return ESP_ERR_FLASH_OP_FAIL; - } - - return ESP_OK; - } - - esp_err_t read(size_t src_offset, void* dst, size_t size) override - { - if (!flash_emu->read(reinterpret_cast(dst), src_offset, size)) { - return ESP_ERR_FLASH_OP_FAIL; - } - - return ESP_OK; - } - - esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override - { - if (!flash_emu->write(dst_offset, reinterpret_cast(src), size)) { - return ESP_ERR_FLASH_OP_FAIL; - } - - return ESP_OK; - } - - esp_err_t write(size_t dst_offset, const void* src, size_t size) override - { - if (!flash_emu->write(dst_offset, reinterpret_cast(src), size)) { - return ESP_ERR_FLASH_OP_FAIL; - } - - return ESP_OK; - } - - esp_err_t erase_range(size_t dst_offset, size_t size) override - { - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - if (size % sec_size != 0) { - return ESP_ERR_INVALID_SIZE; - } - - if (dst_offset % sec_size != 0) { - return ESP_ERR_INVALID_ARG; - } - - size_t start_sector = dst_offset / sec_size; - size_t num_sectors = size / sec_size; - for (size_t sector = start_sector; sector < (start_sector + num_sectors); sector++) { - if (!flash_emu->erase(sector)) { - return ESP_ERR_FLASH_OP_FAIL; - } - } - - return ESP_OK; - } - - uint32_t get_address() override - { - return address; - } - - uint32_t get_size() override - { - return size; - } - - bool get_readonly() override - { - return readonly; - } - -private: - const char *partition_name; - - SpiFlashEmulator *flash_emu; - - uint32_t address; - - uint32_t size; - - bool readonly; -}; - -struct PartitionEmulationFixture { - PartitionEmulationFixture(uint32_t start_sector = 0, - uint32_t sector_size = 1, - const char *partition_name = NVS_DEFAULT_PART_NAME) - : emu(start_sector + sector_size), - part(&emu, start_sector * esp_partition_get_main_flash_sector_size(), sector_size * esp_partition_get_main_flash_sector_size(), partition_name) { - } - - ~PartitionEmulationFixture() { } - - SpiFlashEmulator emu; - - PartitionEmulation part; -}; - -struct EncryptedPartitionFixture { - EncryptedPartitionFixture(nvs_sec_cfg_t *cfg, - uint32_t start_sector = 0, - uint32_t sector_size = 1, - const char *partition_name = NVS_DEFAULT_PART_NAME) - : esp_partition(), emu(start_sector + sector_size), - part(&esp_partition) { - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - esp_partition.address = start_sector * sec_size; - esp_partition.size = sector_size * sec_size; - strncpy(esp_partition.label, partition_name, PART_NAME_MAX_SIZE); - assert(part.init(cfg) == ESP_OK); - } - - ~EncryptedPartitionFixture() { } - - esp_partition_t esp_partition; - - SpiFlashEmulator emu; - - nvs::NVSEncryptedPartition part; -}; diff --git a/components/nvs_flash/test_nvs_host/test_intrusive_list.cpp b/components/nvs_flash/test_nvs_host/test_intrusive_list.cpp deleted file mode 100644 index dea63f3c3358..000000000000 --- a/components/nvs_flash/test_nvs_host/test_intrusive_list.cpp +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "catch.hpp" -#include -#include -#include "intrusive_list.h" - -struct TestNode : public intrusive_list_node { - TestNode(const char* name_ = "", int num_ = 0) : num(num_) - { - strncpy(name, name_, sizeof(name) - 1); - name[sizeof(name) - 1] = 0; - } - char name[32]; - int num; -}; - -typedef intrusive_list TestList; - - -TEST_CASE("can add items to the list", "[list]") -{ - TestList list; - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - - list.push_back(&n1); - REQUIRE(list.begin()->num == 1); - REQUIRE(list.front().num == 1); - REQUIRE(list.back().num == 1); - list.push_front(&n2); - REQUIRE(list.begin()->num == 2); - REQUIRE(list.front().num == 2); - REQUIRE(list.back().num == 1); - - list.insert(list.begin(), &n3); - REQUIRE(list.begin()->num == 3); - REQUIRE(list.front().num == 3); - REQUIRE(list.back().num == 1); - - - auto second = ++list.begin(); - REQUIRE(second->num == 2); - - second++; - REQUIRE(second->num == 1); -} - -TEST_CASE("can iterate over items", "[list]") -{ - TestList list; - - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - - - list.push_back(&n1); - list.push_back(&n2); - list.push_back(&n3); - - int val = 1; - for (auto it = std::begin(list); it != std::end(list); ++it) { - REQUIRE(it->num == val); - ++val; - } -} - -TEST_CASE("iterator's prefix and postfix increments and decrements behave as expected", "[list]") -{ - TestList list; - - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - - - list.push_back(&n1); - list.push_back(&n2); - list.push_back(&n3); - - auto it = std::begin(list); - REQUIRE((++it)->num == 2); - REQUIRE(it++->num == 2); - REQUIRE((--it)->num == 2); - REQUIRE(it--->num == 2); -} - -TEST_CASE("can pop_front from the list", "[list]") -{ - TestList list; - - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - - list.push_back(&n1); - list.push_back(&n2); - list.push_back(&n3); - - list.pop_front(); - list.pop_front(); - list.pop_front(); - - REQUIRE(std::begin(list) == std::end(list)); -} - - -TEST_CASE("can erase first item in the list", "[list]") -{ - TestList list; - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - - list.push_back(&n1); - list.push_back(&n2); - list.push_back(&n3); - - list.erase(std::begin(list)); - - REQUIRE(list.front().num == 2); - REQUIRE(list.back().num == 3); -} - - -TEST_CASE("can erase last item in the list", "[list]") -{ - TestList list; - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - - list.push_back(&n1); - list.push_back(&n2); - list.push_back(&n3); - - list.erase(&list.back()); - - REQUIRE(list.front().num == 1); - REQUIRE(list.back().num == 2); -} - -TEST_CASE("can erase item in the middle of the list", "[list]") -{ - TestList list; - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - - list.push_back(&n1); - list.push_back(&n2); - list.push_back(&n3); - - list.erase(++std::begin(list)); - - REQUIRE(list.front().num == 1); - REQUIRE(list.back().num == 3); -} - -TEST_CASE("can erase all items in the list", "[list]") -{ - TestList list; - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - - list.push_back(&n1); - list.push_back(&n2); - list.push_back(&n3); - - list.erase(std::begin(list)); - list.erase(std::begin(list)); - list.erase(std::begin(list)); - REQUIRE(std::begin(list) == std::end(list)); -} - - -TEST_CASE("can erase all items in the list using clear method", "[list]") -{ - TestList list; - TestNode n1("one", 1); - TestNode n2("two", 2); - TestNode n3("three", 3); - TestNode n4("four", 4); - TestNode n5("five", 5); - TestNode n6("six", 6); - - - list.push_back(&n1); - list.push_back(&n2); - list.insert(++list.begin(), &n3); - list.insert(++list.begin(), &n4); - list.push_front(&n5); - list.insert(list.begin(), &n6); - - list.clear(); - - REQUIRE(std::begin(list) == std::end(list)); -} diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp deleted file mode 100644 index 06d312e4831a..000000000000 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ /dev/null @@ -1,1251 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "catch.hpp" -#include "nvs.hpp" -#include "nvs_test_api.h" -#include "sdkconfig.h" -#include "spi_flash_emulation.h" -#include "nvs_partition_manager.hpp" -#include "nvs_partition.hpp" -#include "mbedtls/aes.h" -#include "mbedtls/md.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "test_fixtures.hpp" - -#define TEST_ESP_ERR(rc, res) CHECK((rc) == (res)) -#define TEST_ESP_OK(rc) CHECK((rc) == ESP_OK) - -stringstream s_perf; - -bool memeq(void *a, size_t a_len, void *b, size_t b_len) -{ - if (a_len != b_len) { - return false; - } - return memcmp(a, b, a_len) == 0; -} - -static void check_nvs_part_gen_args(SpiFlashEmulator *spi_flash_emulator, - char const *part_name, - int size, - char const *filename, - bool is_encr, - nvs_sec_cfg_t *xts_cfg) -{ - nvs_handle_t handle; - - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - esp_partition_t esp_part; - esp_part.encrypted = false; // we're not testing generic flash encryption here, only the legacy NVS encryption - esp_part.address = 0; - esp_part.size = size * sec_size; - strncpy(esp_part.label, part_name, PART_NAME_MAX_SIZE); - unique_ptr part; - - if (is_encr) { - nvs::NVSEncryptedPartition *enc_part = new (std::nothrow) nvs::NVSEncryptedPartition(&esp_part); - REQUIRE(enc_part != nullptr); - TEST_ESP_OK(enc_part->init(xts_cfg)); - part.reset(enc_part); - } else { - part.reset(new PartitionEmulation(spi_flash_emulator, 0, size, part_name)); - } - - TEST_ESP_OK( nvs::NVSPartitionManager::get_instance()->init_custom(part.get(), 0, size) ); - - TEST_ESP_OK( nvs_open_from_partition(part_name, "dummyNamespace", NVS_READONLY, &handle)); - uint8_t u8v; - TEST_ESP_OK( nvs_get_u8(handle, "dummyU8Key", &u8v)); - CHECK(u8v == 127); - int8_t i8v; - TEST_ESP_OK( nvs_get_i8(handle, "dummyI8Key", &i8v)); - CHECK(i8v == -128); - uint16_t u16v; - TEST_ESP_OK( nvs_get_u16(handle, "dummyU16Key", &u16v)); - CHECK(u16v == 32768); - uint32_t u32v; - TEST_ESP_OK( nvs_get_u32(handle, "dummyU32Key", &u32v)); - CHECK(u32v == 4294967295); - int32_t i32v; - TEST_ESP_OK( nvs_get_i32(handle, "dummyI32Key", &i32v)); - CHECK(i32v == -2147483648); - - char string_buf[256]; - const char test_str[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" - "Fusce quis risus justo.\n" - "Suspendisse egestas in nisi sit amet auctor.\n" - "Pellentesque rhoncus dictum sodales.\n" - "In justo erat, viverra at interdum eget, interdum vel dui."; - size_t str_len = sizeof(test_str); - TEST_ESP_OK( nvs_get_str(handle, "dummyStringKey", string_buf, &str_len)); - CHECK(strncmp(string_buf, test_str, str_len) == 0); - - char buf[64] = {0}; - uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; - size_t buflen = 64; - int j; - TEST_ESP_OK( nvs_get_blob(handle, "dummyHex2BinKey", buf, &buflen)); - CHECK(memeq(buf, buflen, hexdata, sizeof(hexdata))); - - uint8_t base64data[] = {'1', '2', '3', 'a', 'b', 'c'}; - TEST_ESP_OK( nvs_get_blob(handle, "dummyBase64Key", buf, &buflen)); - CHECK(memeq(buf, buflen, base64data, sizeof(base64data))); - - buflen = 64; - uint8_t hexfiledata[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; - TEST_ESP_OK( nvs_get_blob(handle, "hexFileKey", buf, &buflen)); - CHECK(memeq(buf, buflen, hexfiledata, sizeof(hexfiledata))); - - buflen = 64; - const char strfiledata[64] = "abcdefghijklmnopqrstuvwxyz"; - TEST_ESP_OK( nvs_get_str(handle, "stringFileKey", buf, &buflen)); - CHECK(strcmp(buf, strfiledata) == 0); - - char bin_data[5200]; - size_t bin_len = sizeof(bin_data); - char binfiledata[5200]; - ifstream file; - file.open(filename); - file.read(binfiledata,5200); - size_t binfile_len = file.gcount(); - TEST_ESP_OK( nvs_get_blob(handle, "binFileKey", bin_data, &bin_len)); - CHECK(memeq(bin_data, bin_len, binfiledata, binfile_len)); - - file.close(); - - nvs_close(handle); - - TEST_ESP_OK(nvs_flash_deinit_partition(part_name)); -} - -static void check_nvs_part_gen_args_mfg(SpiFlashEmulator *spi_flash_emulator, - char const *part_name, - int size, - char const *filename, - bool is_encr, - nvs_sec_cfg_t *xts_cfg) -{ - nvs_handle_t handle; - - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - esp_partition_t esp_part; - esp_part.encrypted = false; // we're not testing generic flash encryption here, only the legacy NVS encryption - esp_part.address = 0; - esp_part.size = size * sec_size; - strncpy(esp_part.label, part_name, PART_NAME_MAX_SIZE); - unique_ptr part; - - if (is_encr) { - nvs::NVSEncryptedPartition *enc_part = new (std::nothrow) nvs::NVSEncryptedPartition(&esp_part); - REQUIRE(enc_part != nullptr); - TEST_ESP_OK(enc_part->init(xts_cfg)); - part.reset(enc_part); - } else { - part.reset(new PartitionEmulation(spi_flash_emulator, 0, size, part_name)); - } - - TEST_ESP_OK( nvs::NVSPartitionManager::get_instance()->init_custom(part.get(), 0, size) ); - - TEST_ESP_OK( nvs_open_from_partition(part_name, "dummyNamespace", NVS_READONLY, &handle)); - uint8_t u8v; - TEST_ESP_OK( nvs_get_u8(handle, "dummyU8Key", &u8v)); - CHECK(u8v == 127); - int8_t i8v; - TEST_ESP_OK( nvs_get_i8(handle, "dummyI8Key", &i8v)); - CHECK(i8v == -128); - uint16_t u16v; - TEST_ESP_OK( nvs_get_u16(handle, "dummyU16Key", &u16v)); - CHECK(u16v == 32768); - uint32_t u32v; - TEST_ESP_OK( nvs_get_u32(handle, "dummyU32Key", &u32v)); - CHECK(u32v == 4294967295); - int32_t i32v; - TEST_ESP_OK( nvs_get_i32(handle, "dummyI32Key", &i32v)); - CHECK(i32v == -2147483648); - - char buf[64] = {0}; - size_t buflen = 64; - TEST_ESP_OK( nvs_get_str(handle, "dummyStringKey", buf, &buflen)); - CHECK(strncmp(buf, "0A:0B:0C:0D:0E:0F", buflen) == 0); - - uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; - buflen = 64; - int j; - TEST_ESP_OK( nvs_get_blob(handle, "dummyHex2BinKey", buf, &buflen)); - CHECK(memeq(buf, buflen, hexdata, sizeof(hexdata))); - - uint8_t base64data[] = {'1', '2', '3', 'a', 'b', 'c'}; - TEST_ESP_OK( nvs_get_blob(handle, "dummyBase64Key", buf, &buflen)); - CHECK(memeq(buf, buflen, base64data, sizeof(base64data))); - - buflen = 64; - uint8_t hexfiledata[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; - TEST_ESP_OK( nvs_get_blob(handle, "hexFileKey", buf, &buflen)); - CHECK(memeq(buf, buflen, hexfiledata, sizeof(hexfiledata))); - - buflen = 64; - const char strfiledata[64] = "abcdefghijklmnopqrstuvwxyz"; - TEST_ESP_OK( nvs_get_str(handle, "stringFileKey", buf, &buflen)); - CHECK(strcmp(buf, strfiledata) == 0); - - char bin_data[5200]; - size_t bin_len = sizeof(bin_data); - char binfiledata[5200]; - ifstream file; - file.open(filename); - file.read(binfiledata,5200); - size_t binfile_len = file.gcount(); - TEST_ESP_OK( nvs_get_blob(handle, "binFileKey", bin_data, &bin_len)); - CHECK(memeq(bin_data, bin_len, binfiledata, binfile_len)); - - file.close(); - - nvs_close(handle); - - TEST_ESP_OK(nvs_flash_deinit_partition(part_name)); -} - -#if CONFIG_NVS_ENCRYPTION -TEST_CASE("check underlying xts code for 32-byte size sector encryption", "[nvs]") -{ - auto toHex = [](char ch) { - if(ch >= '0' && ch <= '9') - return ch - '0'; - else if(ch >= 'a' && ch <= 'f') - return ch - 'a' + 10; - else if(ch >= 'A' && ch <= 'F') - return ch - 'A' + 10; - else - return 0; - }; - - auto toHexByte = [toHex](char* c) { - return 16 * toHex(c[0]) + toHex(c[1]); - }; - - auto toHexStream = [toHexByte](char* src, uint8_t* dest) { - uint32_t cnt =0; - char* p = src; - while(*p != '\0' && *(p + 1) != '\0') - { - dest[cnt++] = toHexByte(p); p += 2; - } - }; - - uint8_t eky_hex[2 * NVS_KEY_SIZE]; - uint8_t ptxt_hex[nvs::Page::ENTRY_SIZE], ctxt_hex[nvs::Page::ENTRY_SIZE], ba_hex[16]; - mbedtls_aes_xts_context ectx[1]; - mbedtls_aes_xts_context dctx[1]; - - char eky[][2 * NVS_KEY_SIZE + 1] = { - "0000000000000000000000000000000000000000000000000000000000000000", - "1111111111111111111111111111111111111111111111111111111111111111" - }; - char tky[][2 * NVS_KEY_SIZE + 1] = { - "0000000000000000000000000000000000000000000000000000000000000000", - "2222222222222222222222222222222222222222222222222222222222222222" - }; - char blk_addr[][2*16 + 1] = { - "00000000000000000000000000000000", - "33333333330000000000000000000000" - }; - - char ptxt[][2 * nvs::Page::ENTRY_SIZE + 1] = { - "0000000000000000000000000000000000000000000000000000000000000000", - "4444444444444444444444444444444444444444444444444444444444444444" - }; - char ctxt[][2 * nvs::Page::ENTRY_SIZE + 1] = { - "d456b4fc2e620bba6ffbed27b956c9543454dd49ebd8d8ee6f94b65cbe158f73", - "e622334f184bbce129a25b2ac76b3d92abf98e22df5bdd15af471f3db8946a85" - }; - - mbedtls_aes_xts_init(ectx); - mbedtls_aes_xts_init(dctx); - - for(uint8_t cnt = 0; cnt < sizeof(eky)/sizeof(eky[0]); cnt++) { - toHexStream(eky[cnt], eky_hex); - toHexStream(tky[cnt], &eky_hex[NVS_KEY_SIZE]); - toHexStream(ptxt[cnt], ptxt_hex); - toHexStream(ctxt[cnt], ctxt_hex); - toHexStream(blk_addr[cnt], ba_hex); - - CHECK(!mbedtls_aes_xts_setkey_enc(ectx, eky_hex, 2 * NVS_KEY_SIZE * 8)); - CHECK(!mbedtls_aes_xts_setkey_enc(dctx, eky_hex, 2 * NVS_KEY_SIZE * 8)); - - CHECK(!mbedtls_aes_crypt_xts(ectx, MBEDTLS_AES_ENCRYPT, nvs::Page::ENTRY_SIZE, ba_hex, ptxt_hex, ptxt_hex)); - - CHECK(!memcmp(ptxt_hex, ctxt_hex, nvs::Page::ENTRY_SIZE)); - } -} - -TEST_CASE("test nvs apis with encryption enabled", "[nvs]") -{ - nvs_handle_t handle_1; - const uint32_t NVS_FLASH_SECTOR = 6; - const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - - nvs_sec_cfg_t xts_cfg; - for(int count = 0; count < NVS_KEY_SIZE; count++) { - xts_cfg.eky[count] = 0x11; - xts_cfg.tky[count] = 0x22; - } - EncryptedPartitionFixture fixture(&xts_cfg, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN); - fixture.emu.randomize(100); - fixture.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); - - for (uint16_t i = NVS_FLASH_SECTOR; i - init_custom(&fixture.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); - - TEST_ESP_ERR(nvs_open("namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); - - TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); - TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); - TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789)); - - nvs_handle_t handle_2; - TEST_ESP_OK(nvs_open("namespace2", NVS_READWRITE, &handle_2)); - TEST_ESP_OK(nvs_set_i32(handle_2, "foo", 0x3456789a)); - const char* str = "value 0123456789abcdef0123456789abcdef"; - TEST_ESP_OK(nvs_set_str(handle_2, "key", str)); - - int32_t v1; - TEST_ESP_OK(nvs_get_i32(handle_1, "foo", &v1)); - CHECK(0x23456789 == v1); - - int32_t v2; - TEST_ESP_OK(nvs_get_i32(handle_2, "foo", &v2)); - CHECK(0x3456789a == v2); - - char buf[strlen(str) + 1]; - size_t buf_len = sizeof(buf); - - size_t buf_len_needed; - TEST_ESP_OK(nvs_get_str(handle_2, "key", NULL, &buf_len_needed)); - CHECK(buf_len_needed == buf_len); - - size_t buf_len_short = buf_len - 1; - TEST_ESP_ERR(ESP_ERR_NVS_INVALID_LENGTH, nvs_get_str(handle_2, "key", buf, &buf_len_short)); - CHECK(buf_len_short == buf_len); - - size_t buf_len_long = buf_len + 1; - TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len_long)); - CHECK(buf_len_long == buf_len); - - TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len)); - - CHECK(0 == strcmp(buf, str)); - nvs_close(handle_1); - nvs_close(handle_2); - TEST_ESP_OK(nvs_flash_deinit()); -} - -TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled", "[nvs_part_gen]") -{ - int status; - int childpid = fork(); - if (childpid == 0) { - exit(execlp("cp", " cp", - "-rf", - "../nvs_partition_generator/testdata", - ".", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../nvs_partition_generator/sample_multipage_blob.csv", - "partition_encrypted.bin", - "0x4000", - "--inputkey", - "../nvs_partition_generator/testdata/sample_encryption_keys.bin", - "--outdir", - "../nvs_partition_generator", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - } - } - - SpiFlashEmulator emu("../nvs_partition_generator/partition_encrypted.bin"); - - nvs_sec_cfg_t cfg; - for (int count = 0; count < NVS_KEY_SIZE; count++) { - cfg.eky[count] = 0x11; - cfg.tky[count] = 0x22; - } - - check_nvs_part_gen_args(&emu, NVS_DEFAULT_PART_NAME, 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin", true, &cfg); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("rm", " rm", - "-rf", - "testdata", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - -} - -TEST_CASE("test decrypt functionality for encrypted data", "[nvs_part_gen]") -{ - - //retrieving the temporary test data - int status = system("cp -rf ../nvs_partition_generator/testdata ."); - CHECK(status == 0); - - //encoding data from sample_multipage_blob.csv - status = system("python ../nvs_partition_generator/nvs_partition_gen.py generate ../nvs_partition_generator/sample_multipage_blob.csv partition_encoded.bin 0x5000 --outdir ../nvs_partition_generator"); - CHECK(status == 0); - - //encrypting data from sample_multipage_blob.csv - status = system("python ../nvs_partition_generator/nvs_partition_gen.py encrypt ../nvs_partition_generator/sample_multipage_blob.csv partition_encrypted.bin 0x5000 --inputkey ../nvs_partition_generator/testdata/sample_encryption_keys.bin --outdir ../nvs_partition_generator"); - CHECK(status == 0); - - //encrypting data from sample_multipage_blob.csv (hmac-based scheme) - status = system("python ../nvs_partition_generator/nvs_partition_gen.py encrypt ../nvs_partition_generator/sample_multipage_blob.csv partition_encrypted_hmac.bin 0x5000 --keygen --key_protect_hmac --kp_hmac_inputkey ../nvs_partition_generator/testdata/sample_hmac_key.bin --outdir ../nvs_partition_generator"); - CHECK(status == 0); - - //decrypting data from partition_encrypted.bin - status = system("python ../nvs_partition_generator/nvs_partition_gen.py decrypt ../nvs_partition_generator/partition_encrypted.bin ../nvs_partition_generator/testdata/sample_encryption_keys.bin ../nvs_partition_generator/partition_decrypted.bin"); - CHECK(status == 0); - - status = system("diff ../nvs_partition_generator/partition_decrypted.bin ../nvs_partition_generator/partition_encoded.bin"); - CHECK(status == 0); - - //decrypting data from partition_encrypted_hmac.bin - status = system("python ../nvs_partition_generator/nvs_partition_gen.py decrypt ../nvs_partition_generator/partition_encrypted_hmac.bin ../nvs_partition_generator/testdata/sample_encryption_keys_hmac.bin ../nvs_partition_generator/partition_decrypted_hmac.bin"); - CHECK(status == 0); - - status = system("diff ../nvs_partition_generator/partition_decrypted_hmac.bin ../nvs_partition_generator/partition_encoded.bin"); - CHECK(status == 0); - - CHECK(WEXITSTATUS(status) == 0); - - - //cleaning up the temporary test data - status = system("rm -rf testdata"); - CHECK(status == 0); - -} - -TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled using keygen", "[nvs_part_gen]") -{ - int childpid = fork(); - int status; - - if (childpid == 0) { - exit(execlp("cp", " cp", - "-rf", - "../nvs_partition_generator/testdata", - ".", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - - if (childpid == 0) { - exit(execlp("rm", " rm", - "-rf", - "../nvs_partition_generator/keys", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../nvs_partition_generator/sample_multipage_blob.csv", - "partition_encrypted_using_keygen.bin", - "0x4000", - "--keygen", - "--outdir", - "../nvs_partition_generator", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - } - } - - - DIR *dir; - struct dirent *file; - char *filename; - char *files; - char *file_ext; - - dir = opendir("../nvs_partition_generator/keys"); - while ((file = readdir(dir)) != NULL) { - filename = file->d_name; - files = strrchr(filename, '.'); - if (files != NULL) { - file_ext = files + 1; - if (strncmp(file_ext, "bin", 3) == 0) { - break; - } - } - } - - std::string encr_file = std::string("../nvs_partition_generator/keys/") + std::string(filename); - SpiFlashEmulator emu("../nvs_partition_generator/partition_encrypted_using_keygen.bin"); - - char buffer[64]; - FILE *fp; - - fp = fopen(encr_file.c_str(), "rb"); - fread(buffer, sizeof(buffer), 1, fp); - - fclose(fp); - - nvs_sec_cfg_t cfg; - - for (int count = 0; count < NVS_KEY_SIZE; count++) { - cfg.eky[count] = buffer[count] & 255; - cfg.tky[count] = buffer[count + 32] & 255; - } - - check_nvs_part_gen_args(&emu, NVS_DEFAULT_PART_NAME, 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin", true, &cfg); - -} - -TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled using inputkey", "[nvs_part_gen]") -{ - int childpid = fork(); - int status; - - DIR *dir; - struct dirent *file; - char *filename; - char *files; - char *file_ext; - - dir = opendir("../nvs_partition_generator/keys"); - while ((file = readdir(dir)) != NULL) { - filename = file->d_name; - files = strrchr(filename, '.'); - if (files != NULL) { - file_ext = files + 1; - if (strncmp(file_ext, "bin", 3) == 0) { - break; - } - } - } - - std::string encr_file = std::string("../nvs_partition_generator/keys/") + std::string(filename); - - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../nvs_partition_generator/sample_multipage_blob.csv", - "partition_encrypted_using_keyfile.bin", - "0x4000", - "--inputkey", - encr_file.c_str(), - "--outdir", - "../nvs_partition_generator", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - } - - SpiFlashEmulator emu("../nvs_partition_generator/partition_encrypted_using_keyfile.bin"); - - char buffer[64]; - FILE *fp; - - fp = fopen(encr_file.c_str(), "rb"); - fread(buffer, sizeof(buffer), 1, fp); - - fclose(fp); - - nvs_sec_cfg_t cfg; - - for (int count = 0; count < NVS_KEY_SIZE; count++) { - cfg.eky[count] = buffer[count] & 255; - cfg.tky[count] = buffer[count + 32] & 255; - } - - check_nvs_part_gen_args(&emu, NVS_DEFAULT_PART_NAME, 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin", true, &cfg); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("rm", " rm", - "-rf", - "../nvs_partition_generator/keys", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - - if (childpid == 0) { - exit(execlp("rm", " rm", - "-rf", - "testdata", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - } - } - -} - -static void compute_nvs_keys_with_hmac(nvs_sec_cfg_t *cfg, void *hmac_key) -{ - unsigned char key_bytes[32] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 }; - if (hmac_key != NULL){ - memcpy(key_bytes, hmac_key, 32); - } - - unsigned char ekey_seed[32], tkey_seed[32]; - - for (unsigned int i = 0; i < sizeof(ekey_seed); i+=4) { - ekey_seed[i] = 0x5A; - ekey_seed[i + 1] = 0x5A; - ekey_seed[i + 2] = 0xBE; - ekey_seed[i + 3] = 0xAE; - } - - for (unsigned int i = 0; i < sizeof(tkey_seed); i+=4) { - tkey_seed[i] = 0xA5; - tkey_seed[i + 1] = 0xA5; - tkey_seed[i + 2] = 0xDE; - tkey_seed[i + 3] = 0xCE; - } - - const mbedtls_md_type_t alg = MBEDTLS_MD_SHA256; - - mbedtls_md_context_t ctx; - mbedtls_md_init(&ctx); - - const mbedtls_md_info_t *info = mbedtls_md_info_from_type(alg); - mbedtls_md_setup(&ctx, info, 1); - mbedtls_md_hmac_starts(&ctx, key_bytes, sizeof(key_bytes)); - - mbedtls_md_hmac_update(&ctx, ekey_seed, sizeof(ekey_seed)); - mbedtls_md_hmac_finish(&ctx, cfg->eky); - - mbedtls_md_hmac_reset(&ctx); - mbedtls_md_hmac_update(&ctx, tkey_seed, sizeof(tkey_seed)); - mbedtls_md_hmac_finish(&ctx, cfg->tky); - - assert(memcmp(cfg->eky, cfg->tky, NVS_KEY_SIZE)); - - mbedtls_md_free(&ctx); -} - -TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled using keygen (user-provided HMAC-key)", "[nvs_part_gen]") -{ - int childpid = fork(); - int status; - - if (childpid == 0) { - exit(execlp("cp", " cp", - "-rf", - "../nvs_partition_generator/testdata", - ".", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - - if (childpid == 0) { - exit(execlp("rm", " rm", - "-rf", - "../nvs_partition_generator/keys", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../nvs_partition_generator/sample_multipage_blob.csv", - "partition_encrypted_using_keygen_hmac.bin", - "0x4000", - "--keygen", - "--key_protect_hmac", - "--kp_hmac_inputkey", - "../nvs_partition_generator/testdata/sample_hmac_key.bin", - "--outdir", - "../nvs_partition_generator", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - } - } - - SpiFlashEmulator emu("../nvs_partition_generator/partition_encrypted_using_keygen_hmac.bin"); - - nvs_sec_cfg_t cfg; - compute_nvs_keys_with_hmac(&cfg, NULL); - - check_nvs_part_gen_args(&emu, NVS_DEFAULT_PART_NAME, 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin", true, &cfg); - -} - -TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled using keygen (dynamically generated HMAC-key)", "[nvs_part_gen]") -{ - int childpid = fork(); - int status; - - if (childpid == 0) { - exit(execlp("cp", " cp", - "-rf", - "../nvs_partition_generator/testdata", - ".", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - - if (childpid == 0) { - exit(execlp("rm", " rm", - "-rf", - "../nvs_partition_generator/keys", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../nvs_partition_generator/sample_multipage_blob.csv", - "partition_encrypted_using_keygen_hmac.bin", - "0x4000", - "--keygen", - "--key_protect_hmac", - "--kp_hmac_keygen", - "--outdir", - "../nvs_partition_generator", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - } - } - - - DIR *dir; - struct dirent *file; - char *filename; - char *files; - char *file_ext; - char *hmac_key_file; - - dir = opendir("../nvs_partition_generator/keys"); - while ((file = readdir(dir)) != NULL) { - filename = file->d_name; - file_ext = NULL; - files = strrchr(filename, '.'); - if (files != NULL) { - file_ext = files + 1; - if (strncmp(file_ext, "bin", 3) != 0) { - continue; - } - } - if (strstr(filename, "hmac") != NULL) { - hmac_key_file = filename; - } - } - - std::string hmac_key_path = std::string("../nvs_partition_generator/keys/") + std::string(hmac_key_file); - SpiFlashEmulator emu("../nvs_partition_generator/partition_encrypted_using_keygen_hmac.bin"); - - char hmac_key_buf[32]; - FILE *fp; - fp = fopen(hmac_key_path.c_str(), "rb"); - fread(hmac_key_buf, sizeof(hmac_key_buf), 1, fp); - fclose(fp); - - nvs_sec_cfg_t cfg; - compute_nvs_keys_with_hmac(&cfg, hmac_key_buf); - - check_nvs_part_gen_args(&emu, NVS_DEFAULT_PART_NAME, 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin", true, &cfg); - -} - -TEST_CASE("check and read data from partition generated via manufacturing utility with encryption enabled using sample inputkey", "[mfg_gen]") -{ - int childpid = fork(); - int status; - - if (childpid == 0) { - exit(execlp("bash", " bash", - "-c", - "rm -rf ../../../tools/mass_mfg/host_test | \ - cp -rf ../../../tools/mass_mfg/testdata mfg_testdata | \ - cp -rf ../nvs_partition_generator/testdata . | \ - mkdir -p ../../../tools/mass_mfg/host_test", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../../../tools/mass_mfg/mfg_gen.py", - "generate", - "../../../tools/mass_mfg/samples/sample_config.csv", - "../../../tools/mass_mfg/samples/sample_values_multipage_blob.csv", - "Test", - "0x4000", - "--outdir", - "../../../tools/mass_mfg/host_test", - "--version", - "2", - "--inputkey", - "mfg_testdata/sample_encryption_keys.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../../../tools/mass_mfg/host_test/csv/Test-1.csv", - "../nvs_partition_generator/Test-1-partition-encrypted.bin", - "0x4000", - "--version", - "2", - "--inputkey", - "testdata/sample_encryption_keys.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - - } - - } - - SpiFlashEmulator emu1("../../../tools/mass_mfg/host_test/bin/Test-1.bin"); - - nvs_sec_cfg_t cfg; - for (int count = 0; count < NVS_KEY_SIZE; count++) { - cfg.eky[count] = 0x11; - cfg.tky[count] = 0x22; - } - - check_nvs_part_gen_args_mfg(&emu1, NVS_DEFAULT_PART_NAME, 4, "mfg_testdata/sample_multipage_blob.bin", true, &cfg); - - SpiFlashEmulator emu2("../nvs_partition_generator/Test-1-partition-encrypted.bin"); - - check_nvs_part_gen_args_mfg(&emu2, NVS_DEFAULT_PART_NAME, 4, "testdata/sample_multipage_blob.bin", true, &cfg); - - - childpid = fork(); - if (childpid == 0) { - exit(execlp("bash", " bash", - "-c", - "rm -rf ../../../tools/mass_mfg/host_test | \ - rm -rf mfg_testdata | \ - rm -rf testdata", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - -} - -TEST_CASE("check and read data from partition generated via manufacturing utility with encryption enabled using new generated key", "[mfg_gen]") -{ - int childpid = fork(); - int status; - - if (childpid == 0) { - exit(execlp("bash", " bash", - "-c", - "rm -rf ../../../tools/mass_mfg/host_test | \ - cp -rf ../../../tools/mass_mfg/testdata mfg_testdata | \ - cp -rf ../nvs_partition_generator/testdata . | \ - mkdir -p ../../../tools/mass_mfg/host_test", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../../../tools/mass_mfg/mfg_gen.py", - "generate-key", - "--outdir", - "../../../tools/mass_mfg/host_test", - "--keyfile", - "encr_keys_host_test.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../../../tools/mass_mfg/mfg_gen.py", - "generate", - "../../../tools/mass_mfg/samples/sample_config.csv", - "../../../tools/mass_mfg/samples/sample_values_multipage_blob.csv", - "Test", - "0x4000", - "--outdir", - "../../../tools/mass_mfg/host_test", - "--version", - "2", - "--inputkey", - "../../../tools/mass_mfg/host_test/keys/encr_keys_host_test.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../../../tools/mass_mfg/host_test/csv/Test-1.csv", - "../nvs_partition_generator/Test-1-partition-encrypted.bin", - "0x4000", - "--version", - "2", - "--inputkey", - "../../../tools/mass_mfg/host_test/keys/encr_keys_host_test.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - - } - - } - - } - - SpiFlashEmulator emu1("../../../tools/mass_mfg/host_test/bin/Test-1.bin"); - - char buffer[64]; - FILE *fp; - - fp = fopen("../../../tools/mass_mfg/host_test/keys/encr_keys_host_test.bin", "rb"); - fread(buffer, sizeof(buffer), 1, fp); - - fclose(fp); - - nvs_sec_cfg_t cfg; - - for (int count = 0; count < NVS_KEY_SIZE; count++) { - cfg.eky[count] = buffer[count] & 255; - cfg.tky[count] = buffer[count + 32] & 255; - } - - check_nvs_part_gen_args_mfg(&emu1, NVS_DEFAULT_PART_NAME, 4, "mfg_testdata/sample_multipage_blob.bin", true, &cfg); - - SpiFlashEmulator emu2("../nvs_partition_generator/Test-1-partition-encrypted.bin"); - - check_nvs_part_gen_args_mfg(&emu2, NVS_DEFAULT_PART_NAME, 4, "testdata/sample_multipage_blob.bin", true, &cfg); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("bash", " bash", - "-c", - "rm -rf keys | \ - rm -rf mfg_testdata | \ - rm -rf testdata | \ - rm -rf ../../../tools/mass_mfg/host_test", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - -} - -TEST_CASE("check and read data from partition generated via manufacturing utility with encryption enabled using new generated key (user-provided HMAC-key)", "[mfg_gen]") -{ - int childpid = fork(); - int status; - - if (childpid == 0) { - exit(execlp("bash", " bash", - "-c", - "rm -rf ../../../tools/mass_mfg/host_test | \ - cp -rf ../../../tools/mass_mfg/testdata mfg_testdata | \ - cp -rf ../nvs_partition_generator/testdata . | \ - mkdir -p ../../../tools/mass_mfg/host_test", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../../../tools/mass_mfg/mfg_gen.py", - "generate", - "../../../tools/mass_mfg/samples/sample_config.csv", - "../../../tools/mass_mfg/samples/sample_values_multipage_blob.csv", - "Test", - "0x4000", - "--version", - "2", - "--keygen", - "--key_protect_hmac", - "--kp_hmac_inputkey", - "mfg_testdata/sample_hmac_key.bin", - "--outdir", - "../../../tools/mass_mfg/host_test",NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../../../tools/mass_mfg/host_test/csv/Test-1.csv", - "../nvs_partition_generator/Test-1-partition-encrypted-hmac.bin", - "0x4000", - "--version", - "2", - "--keygen", - "--key_protect_hmac", - "--kp_hmac_inputkey", - "mfg_testdata/sample_hmac_key.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - - } - - } - - SpiFlashEmulator emu1("../../../tools/mass_mfg/host_test/bin/Test-1.bin"); - - nvs_sec_cfg_t cfg; - compute_nvs_keys_with_hmac(&cfg, NULL); - - check_nvs_part_gen_args_mfg(&emu1, NVS_DEFAULT_PART_NAME, 4, "mfg_testdata/sample_multipage_blob.bin", true, &cfg); - - SpiFlashEmulator emu2("../nvs_partition_generator/Test-1-partition-encrypted-hmac.bin"); - - check_nvs_part_gen_args_mfg(&emu2, NVS_DEFAULT_PART_NAME, 4, "testdata/sample_multipage_blob.bin", true, &cfg); - - - childpid = fork(); - if (childpid == 0) { - exit(execlp("bash", " bash", - "-c", - "rm -rf ../../../tools/mass_mfg/host_test | \ - rm -rf mfg_testdata | \ - rm -rf testdata", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - -} - -TEST_CASE("check and read data from partition generated via manufacturing utility with encryption enabled using new generated key (dynamically generated HMAC-key)", "[mfg_gen]") -{ - int childpid = fork(); - int status; - - if (childpid == 0) { - exit(execlp("bash", " bash", - "-c", - "rm -rf ../../../tools/mass_mfg/host_test | \ - cp -rf ../../../tools/mass_mfg/testdata mfg_testdata | \ - cp -rf ../nvs_partition_generator/testdata . | \ - mkdir -p ../../../tools/mass_mfg/host_test", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../../../tools/mass_mfg/mfg_gen.py", - "generate-key", - "--outdir", - "../../../tools/mass_mfg/host_test", - "--key_protect_hmac", - "--kp_hmac_keygen", - "--kp_hmac_keyfile", - "hmac_key_host_test.bin", - "--keyfile", - "encr_keys_host_test.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../../../tools/mass_mfg/mfg_gen.py", - "generate", - "../../../tools/mass_mfg/samples/sample_config.csv", - "../../../tools/mass_mfg/samples/sample_values_multipage_blob.csv", - "Test", - "0x4000", - "--outdir", - "../../../tools/mass_mfg/host_test", - "--version", - "2", - "--inputkey", - "../../../tools/mass_mfg/host_test/keys/encr_keys_host_test.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("python", "python", - "../nvs_partition_generator/nvs_partition_gen.py", - "encrypt", - "../../../tools/mass_mfg/host_test/csv/Test-1.csv", - "../nvs_partition_generator/Test-1-partition-encrypted-hmac.bin", - "0x4000", - "--version", - "2", - "--inputkey", - "../../../tools/mass_mfg/host_test/keys/encr_keys_host_test.bin", NULL)); - - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - - } - - } - - } - - - SpiFlashEmulator emu1("../../../tools/mass_mfg/host_test/bin/Test-1.bin"); - - char hmac_key_buf[32]; - FILE *fp; - - fp = fopen("../../../tools/mass_mfg/host_test/keys/hmac_key_host_test.bin", "rb"); - fread(hmac_key_buf, sizeof(hmac_key_buf), 1, fp); - - fclose(fp); - - nvs_sec_cfg_t cfg; - compute_nvs_keys_with_hmac(&cfg, hmac_key_buf); - - check_nvs_part_gen_args_mfg(&emu1, NVS_DEFAULT_PART_NAME, 4, "mfg_testdata/sample_multipage_blob.bin", true, &cfg); - - SpiFlashEmulator emu2("../nvs_partition_generator/Test-1-partition-encrypted-hmac.bin"); - - check_nvs_part_gen_args_mfg(&emu2, NVS_DEFAULT_PART_NAME, 4, "testdata/sample_multipage_blob.bin", true, &cfg); - - childpid = fork(); - if (childpid == 0) { - exit(execlp("bash", " bash", - "-c", - "rm -rf keys | \ - rm -rf mfg_testdata | \ - rm -rf testdata | \ - rm -rf ../../../tools/mass_mfg/host_test", NULL)); - } else { - CHECK(childpid > 0); - waitpid(childpid, &status, 0); - CHECK(WEXITSTATUS(status) == 0); - - } - -} - -#endif diff --git a/components/nvs_flash/test_nvs_host/test_nvs_partition.cpp b/components/nvs_flash/test_nvs_host/test_nvs_partition.cpp deleted file mode 100644 index d394f525aac5..000000000000 --- a/components/nvs_flash/test_nvs_host/test_nvs_partition.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "catch.hpp" -#include -#include -#include "nvs_test_api.h" -#include "nvs_handle_simple.hpp" -#include "nvs_partition.hpp" -#include "spi_flash_emulation.h" -#include "test_fixtures.hpp" -#include - -TEST_CASE("encrypted partition read size must be item size", "[nvs]") -{ - char foo [32] = { }; - nvs_sec_cfg_t xts_cfg; - for (int count = 0; count < NVS_KEY_SIZE; count++) { - xts_cfg.eky[count] = 0x11; - xts_cfg.tky[count] = 0x22; - } - EncryptedPartitionFixture fix(&xts_cfg); - - CHECK(fix.part.read(0, foo, sizeof (foo) - 1) == ESP_ERR_INVALID_SIZE); -} - -TEST_CASE("encrypted partition write size must be mod item size", "[nvs]") -{ - char foo [64] = { }; - nvs_sec_cfg_t xts_cfg; - for (int count = 0; count < NVS_KEY_SIZE; count++) { - xts_cfg.eky[count] = 0x11; - xts_cfg.tky[count] = 0x22; - } - EncryptedPartitionFixture fix(&xts_cfg); - - CHECK(fix.part.write(0, foo, sizeof (foo) - 1) == ESP_ERR_INVALID_SIZE); - CHECK(fix.part.write(0, foo, sizeof (foo) / 2) == ESP_OK); - CHECK(fix.part.write(sizeof(foo) / 2, foo, sizeof (foo)) == ESP_OK); -} diff --git a/components/nvs_flash/test_nvs_host/test_partition_manager.cpp b/components/nvs_flash/test_nvs_host/test_partition_manager.cpp deleted file mode 100644 index cc86e5182c79..000000000000 --- a/components/nvs_flash/test_nvs_host/test_partition_manager.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "catch.hpp" -#include -#include -#include "nvs_test_api.h" -#include "nvs_handle_simple.hpp" -#include "nvs_partition_manager.hpp" -#include "spi_flash_emulation.h" -#include "nvs_test_api.h" -#include "test_fixtures.hpp" -#include "esp_partition.h" - -/* -TEST_CASE("Partition manager initializes multiple partitions", "[partition_mgr]") -{ - const uint32_t NVS_FLASH_SECTOR = 6; - const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - SpiFlashEmulator emu(10); - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - PartitionEmulation part_0(&emu, NVS_FLASH_SECTOR * sec_size, NVS_FLASH_SECTOR_COUNT_MIN * sec_size, "test1"); - PartitionEmulation part_1(&emu, NVS_FLASH_SECTOR * sec_size, NVS_FLASH_SECTOR_COUNT_MIN * sec_size, "test2"); - - REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&part_0, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) - == ESP_OK); - // TODO: why does this work, actually? same sectors used as above - REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&part_1, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) - == ESP_OK); - nvs::Storage *storage1 = nvs::NVSPartitionManager::get_instance()->lookup_storage_from_name("test1"); - REQUIRE(storage1 != nullptr); - nvs::Storage *storage2 = nvs::NVSPartitionManager::get_instance()->lookup_storage_from_name("test2"); - REQUIRE(storage2 != nullptr); - - CHECK(storage1 != storage2); - REQUIRE(nvs::NVSPartitionManager::get_instance()->deinit_partition(part_0.get_partition_name()) == ESP_OK); - REQUIRE(nvs::NVSPartitionManager::get_instance()->deinit_partition(part_1.get_partition_name()) == ESP_OK); -} -*/ diff --git a/components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp b/components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp deleted file mode 100644 index 46fae9f3c008..000000000000 --- a/components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "catch.hpp" -#include "esp_partition.h" -#include "spi_flash_emulation.h" -#include "spi_flash_mmap.h" -#include - -template -bool range_empty_n(Tit it_begin, size_t n) -{ - return std::all_of(it_begin, it_begin + n, bind(std::equal_to(), std::placeholders::_1, 0xffffffff)); -} - -struct FlashEmuFixture { - FlashEmuFixture(size_t sectors) : esp_part(), emu(sectors) { } - - esp_partition_t esp_part; - SpiFlashEmulator emu; -}; - -TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]") -{ - FlashEmuFixture f(4); - - uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - uint8_t sector[sec_size]; - - for (int i = 0; i < 4; ++i) { - CHECK(esp_partition_read(&f.esp_part, 0, sector, sizeof(sector)) == ESP_OK); - for (auto v: sector) { - CHECK(v == 0xff); - } - } -} - -TEST_CASE("invalid writes are checked", "[spi_flash_emu]") -{ - FlashEmuFixture f(1); - - uint32_t val = 0; - CHECK(esp_partition_write(&f.esp_part, 0, &val, 4) == ESP_OK); - val = 1; - CHECK(esp_partition_write(&f.esp_part, 0, &val, 4) == ESP_ERR_FLASH_OP_FAIL); -} - - -TEST_CASE("out of bounds writes fail", "[spi_flash_emu]") -{ - FlashEmuFixture f(4); - uint32_t vals[8]; - std::fill_n(vals, 8, 0); - CHECK(esp_partition_write(&f.esp_part, 0, &vals, sizeof(vals)) == ESP_OK); - - CHECK(esp_partition_write(&f.esp_part, 4*4096 - sizeof(vals), &vals, sizeof(vals)) == ESP_OK); - - CHECK(esp_partition_write(&f.esp_part, 4*4096 - sizeof(vals) + 4, &vals, sizeof(vals)) == ESP_ERR_FLASH_OP_FAIL); -} - -TEST_CASE("after erase the sector is set to 0xff", "[spi_flash_emu]") -{ - FlashEmuFixture f(4); - uint32_t val1 = 0xab00cd12; - CHECK(esp_partition_write(&f.esp_part, 0, &val1, sizeof(val1)) == ESP_OK); - uint32_t val2 = 0x5678efab; - CHECK(esp_partition_write(&f.esp_part, 4096 - 4, &val2, sizeof(val2)) == ESP_OK); - - CHECK(f.emu.words()[0] == val1); - CHECK(range_empty_n(f.emu.words() + 1, 4096 / 4 - 2)); - CHECK(f.emu.words()[4096 / 4 - 1] == val2); - - uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - CHECK(esp_partition_erase_range(&f.esp_part, 0, sec_size) == ESP_OK); - - CHECK(f.emu.words()[0] == 0xffffffff); - CHECK(range_empty_n(f.emu.words() + 1, 4096 / 4 - 2)); - CHECK(f.emu.words()[4096 / 4 - 1] == 0xffffffff); -} - -TEST_CASE("EMU raw read function works", "[spi_flash_emu]") -{ - FlashEmuFixture f(4); - uint32_t value = 0xdeadbeef; - uint32_t read_value = 0; - CHECK(esp_partition_write(&f.esp_part, 0, &value, sizeof(value)) == ESP_OK); - - CHECK(esp_partition_read_raw(&f.esp_part, 0, &read_value, sizeof(read_value)) == ESP_OK); - - CHECK(read_value == 0xdeadbeef); -} - -TEST_CASE("EMU raw write function works", "[spi_flash_emu]") -{ - FlashEmuFixture f(4); - uint32_t value = 0xdeadbeef; - uint32_t read_value = 0; - CHECK(esp_partition_write_raw(&f.esp_part, 0, &value, sizeof(value)) == ESP_OK); - - CHECK(esp_partition_read(&f.esp_part, 0, &read_value, sizeof(read_value)) == ESP_OK); - - CHECK(read_value == 0xdeadbeef); -} - -TEST_CASE("read/write/erase operation times are calculated correctly", "[spi_flash_emu]") -{ - FlashEmuFixture f(1); - uint8_t data[512]; - esp_partition_read(&f.esp_part, 0, data, 4); - CHECK(f.emu.getTotalTime() == 7); - CHECK(f.emu.getReadOps() == 1); - CHECK(f.emu.getReadBytes() == 4); - f.emu.clearStats(); - esp_partition_read(&f.esp_part, 0, data, 8); - CHECK(f.emu.getTotalTime() == 5); - CHECK(f.emu.getReadOps() == 1); - CHECK(f.emu.getReadBytes() == 8); - f.emu.clearStats(); - esp_partition_read(&f.esp_part, 0, data, 16); - CHECK(f.emu.getTotalTime() == 6); - CHECK(f.emu.getReadOps() == 1); - CHECK(f.emu.getReadBytes() == 16); - f.emu.clearStats(); - esp_partition_read(&f.esp_part, 0, data, 128); - CHECK(f.emu.getTotalTime() == 18); - CHECK(f.emu.getReadOps() == 1); - CHECK(f.emu.getReadBytes() == 128); - f.emu.clearStats(); - esp_partition_read(&f.esp_part, 0, data, 256); - CHECK(f.emu.getTotalTime() == 32); - f.emu.clearStats(); - esp_partition_read(&f.esp_part, 0, data, (128+256)/2); - CHECK(f.emu.getTotalTime() == (18+32)/2); - f.emu.clearStats(); - - esp_partition_write(&f.esp_part, 0, data, 4); - CHECK(f.emu.getTotalTime() == 19); - CHECK(f.emu.getWriteOps() == 1); - CHECK(f.emu.getWriteBytes() == 4); - f.emu.clearStats(); - CHECK(f.emu.getWriteOps() == 0); - CHECK(f.emu.getWriteBytes() == 0); - esp_partition_write(&f.esp_part, 0, data, 8); - CHECK(f.emu.getTotalTime() == 23); - f.emu.clearStats(); - esp_partition_write(&f.esp_part, 0, data, 16); - CHECK(f.emu.getTotalTime() == 35); - CHECK(f.emu.getWriteOps() == 1); - CHECK(f.emu.getWriteBytes() == 16); - f.emu.clearStats(); - esp_partition_write(&f.esp_part, 0, data, 128); - CHECK(f.emu.getTotalTime() == 205); - f.emu.clearStats(); - esp_partition_write(&f.esp_part, 0, data, 256); - CHECK(f.emu.getTotalTime() == 417); - f.emu.clearStats(); - esp_partition_write(&f.esp_part, 0, data, (128+256)/2); - CHECK(f.emu.getTotalTime() == (205+417)/2); - f.emu.clearStats(); - - const uint32_t sec_size = esp_partition_get_main_flash_sector_size(); - esp_partition_erase_range(&f.esp_part, 0, sec_size); - CHECK(f.emu.getEraseOps() == 1); - CHECK(f.emu.getTotalTime() == 37142); -} - -TEST_CASE("data is randomized predictably", "[spi_flash_emu]") -{ - SpiFlashEmulator emu1(3); - emu1.randomize(0x12345678); - - SpiFlashEmulator emu2(3); - emu2.randomize(0x12345678); - - CHECK(std::equal(emu1.bytes(), emu1.bytes() + emu1.size(), emu2.bytes())); -} diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index 06e0b5e19d33..66119f65aa40 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -15,7 +15,6 @@ if(CONFIG_OPENTHREAD_ENABLED) set(private_include_dirs "openthread/examples/platforms" - "openthread/include/openthread" "openthread/src" "openthread/src/core" "openthread/src/lib" @@ -140,6 +139,19 @@ if(CONFIG_OPENTHREAD_ENABLED) list(APPEND exclude_srcs "src/port/esp_openthread_radio.c" "src/port/esp_openthread_sleep.c") + elseif(CONFIG_OPENTHREAD_RADIO_154_NONE) + list(APPEND exclude_srcs + "src/port/esp_openthread_radio_spinel.cpp" + "src/port/esp_spi_spinel_interface.cpp" + "src/port/esp_uart_spinel_interface.cpp" + "src/port/esp_openthread_radio.c" + "src/port/esp_openthread_sleep.c" + ) + endif() + + if(NOT CONFIG_OPENTHREAD_RADIO_TREL) + list(APPEND exclude_srcs + "src/port/esp_openthread_trel.c") endif() if(CONFIG_OPENTHREAD_BORDER_ROUTER) @@ -156,6 +168,13 @@ if(CONFIG_OPENTHREAD_ENABLED) if(CONFIG_OPENTHREAD_NCP_VENDOR_HOOK) list(APPEND src_dirs "src/ncp") + if(CONFIG_OPENTHREAD_RCP_UART) + list(APPEND exclude_srcs + "src/ncp/esp_openthread_ncp_spi.cpp") + elseif(CONFIG_OPENTHREAD_RCP_SPI) + list(APPEND exclude_srcs + "src/ncp/esp_openthread_ncp_hdlc.cpp") + endif() endif() if(NOT CONFIG_OPENTHREAD_DNS64_CLIENT) @@ -252,6 +271,10 @@ idf_component_register(SRC_DIRS "${src_dirs}" PRIV_REQUIRES console esp_event esp_partition esp_timer ieee802154 mbedtls nvs_flash) +if(CONFIG_OPENTHREAD_RADIO_TREL) + idf_component_optional_requires(PRIVATE espressif__mdns) +endif() + if(CONFIG_OPENTHREAD_ENABLED OR CONFIG_OPENTHREAD_SPINEL_ONLY) if(CONFIG_OPENTHREAD_RADIO) set(CONFIG_FILE_TYPE "radio") diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 160084fbcb74..d344f5961529 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -101,7 +101,7 @@ menu "OpenThread" default 5 if OPENTHREAD_LOG_LEVEL_DEBG choice OPENTHREAD_RADIO_TYPE - prompt "Config the Thread radio type" + prompt "Config the Thread radio type with 15.4 link" depends on OPENTHREAD_ENABLED default OPENTHREAD_RADIO_NATIVE if SOC_IEEE802154_SUPPORTED default OPENTHREAD_RADIO_SPINEL_UART @@ -124,8 +124,26 @@ menu "OpenThread" help Select this to connect to a Radio Co-Processor via SPI. + config OPENTHREAD_RADIO_154_NONE + bool "Disable the Thread radio based on 15.4 link" + help + Select this to disable the Thread radio based on 15.4 link. endchoice + config OPENTHREAD_RADIO_TREL + bool "Enable Thread Radio Encapsulation Link (TREL)" + depends on EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET + default n + help + Select this option to enable Thread Radio Encapsulation Link. + + config OPENTHREAD_TREL_PORT + int "The port of openthread trel service" + depends on OPENTHREAD_RADIO_TREL + default 12390 + help + Configure the port number of TREL service. + choice OPENTHREAD_DEVICE_TYPE prompt "Config the Thread device type" depends on OPENTHREAD_ENABLED diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index 03095940194c..debc464066dc 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -46,6 +46,7 @@ typedef enum { OPENTHREAD_EVENT_SET_DNS_SERVER, /*!< OpenThread stack set DNS server >*/ OPENTHREAD_EVENT_PUBLISH_MESHCOP_E, /*!< OpenThread stack start to publish meshcop-e service >*/ OPENTHREAD_EVENT_REMOVE_MESHCOP_E, /*!< OpenThread stack start to remove meshcop-e service >*/ + OPENTHREAD_EVENT_DATASET_CHANGED, /*!< OpenThread dataset changed >*/ } esp_openthread_event_t; /** @@ -63,6 +64,24 @@ typedef struct { otDeviceRole current_role; /*!< Current Thread role */ } esp_openthread_role_changed_event_t; +/** + * @brief OpenThread dataset type + * + */ +typedef enum { + OPENTHREAD_ACTIVE_DATASET, /*!< Active dataset */ + OPENTHREAD_PENDING_DATASET, /*!< Pending dataset */ +} esp_openthread_dataset_type_t; + +/** + * @brief OpenThread dataset changed event data + * + */ +typedef struct { + esp_openthread_dataset_type_t type; /*!< Dataset type */ + otOperationalDataset new_dataset; /*!< New dataset */ +} esp_openthread_dataset_changed_event_t; + /** * This structure represents a context for a select() based mainloop. * @@ -117,6 +136,7 @@ typedef enum { RADIO_MODE_NATIVE = 0x0, /*!< Use the native 15.4 radio */ RADIO_MODE_UART_RCP, /*!< UART connection to a 15.4 capable radio co-processor (RCP) */ RADIO_MODE_SPI_RCP, /*!< SPI connection to a 15.4 capable radio co-processor (RCP) */ + RADIO_MODE_TREL, /*!< Use the Thread Radio Encapsulation Link (TREL) */ RADIO_MODE_MAX, /*!< Using for parameter check */ } esp_openthread_radio_mode_t; diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index aa8882f2341d..ec9480150594 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -203,28 +203,40 @@ #define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + * + * Define to 1 to enable Backbone Router support. + * + */ +#ifndef OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#define OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 1 +#endif + +#endif // CONFIG_OPENTHREAD_BORDER_ROUTER + /** * @def OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE * * Set to 1 to enable support for Thread Radio Encapsulation Link (TREL). * */ -#ifndef OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE -#define OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE 0 -#endif +#if CONFIG_OPENTHREAD_RADIO_TREL +#define OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE 1 +#endif // CONFIG_OPENTHREAD_RADIO_TREL /** - * @def OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + * @def OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE * - * Define to 1 to enable Backbone Router support. + * Set to 1 to enable support for IEEE802.15.4 radio link. * */ -#ifndef OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE -#define OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 1 +#if !CONFIG_OPENTHREAD_RADIO_154_NONE +#define OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE 1 +#else +#define OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE 0 #endif -#endif // CONFIG_OPENTHREAD_BORDER_ROUTER - #if !CONFIG_OPENTHREAD_RADIO_NATIVE /** * @def OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT diff --git a/components/openthread/src/esp_openthread_dns64.c b/components/openthread/src/esp_openthread_dns64.c index 79faa1ad9228..86d8b5fb0e53 100644 --- a/components/openthread/src/esp_openthread_dns64.c +++ b/components/openthread/src/esp_openthread_dns64.c @@ -75,7 +75,7 @@ static void dns_found_handler(const char *name, const ip_addr_t *ipaddr, void *c { dns_resolve_entry_t *resolve_entry = (dns_resolve_entry_t *)callback_arg; if (resolve_entry && resolve_entry->found) { - if (lwip_strnicmp(name, resolve_entry->name, sizeof(resolve_entry->name)) == 0) { + if (ipaddr && lwip_strnicmp(name, resolve_entry->name, sizeof(resolve_entry->name)) == 0) { ip_addr_t ipaddr_copy = *ipaddr; ip6_addr_t nat64_prefix; if (ipaddr_copy.type == IPADDR_TYPE_V4 && esp_openthread_get_nat64_prefix(&nat64_prefix) == ESP_OK) { diff --git a/components/openthread/src/ncp/esp_openthread_ncp.cpp b/components/openthread/src/ncp/esp_openthread_ncp.cpp index 7e5127f869c8..eefeda501713 100644 --- a/components/openthread/src/ncp/esp_openthread_ncp.cpp +++ b/components/openthread/src/ncp/esp_openthread_ncp.cpp @@ -4,12 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "sdkconfig.h" #include "esp_ieee802154.h" #include "esp_openthread_ncp.h" #include "ncp_base.hpp" -#if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK - #if CONFIG_OPENTHREAD_RCP_UART #include "utils/uart.h" #endif @@ -107,5 +106,3 @@ otError NcpBase::VendorSetPropertyHandler(spinel_prop_key_t aPropKey) } // namespace Ncp } // namespace ot - -#endif // #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK diff --git a/components/openthread/src/ncp/esp_openthread_ncp_hdlc.cpp b/components/openthread/src/ncp/esp_openthread_ncp_hdlc.cpp index 0e8a3dbb8883..6b86b6d9359b 100644 --- a/components/openthread/src/ncp/esp_openthread_ncp_hdlc.cpp +++ b/components/openthread/src/ncp/esp_openthread_ncp_hdlc.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,8 +7,6 @@ #include "common/new.hpp" #include "ncp_hdlc.hpp" -#if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK - namespace ot { namespace Ncp { @@ -29,5 +27,3 @@ extern "C" void otNcpHdlcInit(otInstance *aInstance, otNcpHdlcSendCallback aSend } // namespace Ncp } // namespace ot - -#endif // #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK diff --git a/components/openthread/src/ncp/esp_openthread_ncp_spi.cpp b/components/openthread/src/ncp/esp_openthread_ncp_spi.cpp new file mode 100644 index 000000000000..d85c918aad86 --- /dev/null +++ b/components/openthread/src/ncp/esp_openthread_ncp_spi.cpp @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common/new.hpp" +#include "ncp_spi.hpp" + +namespace ot { +namespace Ncp { + +static OT_DEFINE_ALIGNED_VAR(sNcpRaw, sizeof(NcpSpi), uint64_t); + +extern "C" void otNcpSpiInit(otInstance *aInstance) +{ + NcpSpi *ncpSpi = nullptr; + Instance *instance = static_cast(aInstance); + + ncpSpi = new (&sNcpRaw) NcpSpi(instance); + + if (ncpSpi == nullptr || ncpSpi != NcpBase::GetNcpInstance()) + { + OT_ASSERT(false); + } +} + +} // namespace Ncp +} // namespace ot diff --git a/components/openthread/src/port/esp_openthread_radio.c b/components/openthread/src/port/esp_openthread_radio.c index 4276809c5285..f87cb682914c 100644 --- a/components/openthread/src/port/esp_openthread_radio.c +++ b/components/openthread/src/port/esp_openthread_radio.c @@ -7,7 +7,6 @@ #include #include "esp_openthread_radio.h" -#include "error.h" #include "esp_err.h" #include "sdkconfig.h" #include "esp_check.h" @@ -25,6 +24,7 @@ #include "rom/ets_sys.h" #include "openthread-core-config.h" +#include "openthread/error.h" #include "openthread/link.h" #include "openthread/platform/diag.h" #include "openthread/platform/radio.h" @@ -412,7 +412,8 @@ void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) { - esp_ieee802154_energy_detect(aScanDuration); + esp_ieee802154_set_channel(aScanChannel); + esp_ieee802154_energy_detect(aScanDuration * US_PER_MS / US_PER_SYMBLE); return OT_ERROR_NONE; } diff --git a/components/openthread/src/port/esp_openthread_radio_spinel.cpp b/components/openthread/src/port/esp_openthread_radio_spinel.cpp index 3d566b05e9a8..b851c5608b51 100644 --- a/components/openthread/src/port/esp_openthread_radio_spinel.cpp +++ b/components/openthread/src/port/esp_openthread_radio_spinel.cpp @@ -6,7 +6,6 @@ #include "esp_openthread_radio.h" -#include "link_raw.h" #include "sdkconfig.h" #include "esp_check.h" #include "esp_err.h" diff --git a/components/openthread/src/port/esp_openthread_state.c b/components/openthread/src/port/esp_openthread_state.c index 6dbe1016705d..7d04cba9f527 100644 --- a/components/openthread/src/port/esp_openthread_state.c +++ b/components/openthread/src/port/esp_openthread_state.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -80,6 +80,21 @@ static void handle_ot_role_change(otInstance* instance) s_previous_role = role; } +static void handle_ot_dataset_change(esp_openthread_dataset_type_t type, otInstance *instance) +{ + esp_openthread_dataset_changed_event_t event_data; + event_data.type = type; + memset(&event_data.new_dataset, 0, sizeof(event_data.new_dataset)); + if (type == OPENTHREAD_ACTIVE_DATASET) { + (void)otDatasetGetActive(instance, &event_data.new_dataset); + } else if (type == OPENTHREAD_PENDING_DATASET) { + (void)otDatasetGetPending(instance, &event_data.new_dataset); + } + if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_DATASET_CHANGED, &event_data, sizeof(event_data), 0) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post dataset changed event"); + } +} + static void ot_state_change_callback(otChangedFlags changed_flags, void* ctx) { OT_UNUSED_VARIABLE(ctx); @@ -99,6 +114,14 @@ static void ot_state_change_callback(otChangedFlags changed_flags, void* ctx) if (changed_flags & OT_CHANGED_THREAD_NETIF_STATE) { handle_ot_netif_state_change(instance); } + + if (changed_flags & OT_CHANGED_ACTIVE_DATASET) { + handle_ot_dataset_change(OPENTHREAD_ACTIVE_DATASET, instance); + } + + if (changed_flags & OT_CHANGED_PENDING_DATASET) { + handle_ot_dataset_change(OPENTHREAD_PENDING_DATASET, instance); + } } esp_err_t esp_openthread_state_event_init(otInstance* instance) diff --git a/components/openthread/src/port/esp_openthread_trel.c b/components/openthread/src/port/esp_openthread_trel.c new file mode 100644 index 000000000000..8424a7631d43 --- /dev/null +++ b/components/openthread/src/port/esp_openthread_trel.c @@ -0,0 +1,352 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_err.h" +#include "esp_netif_types.h" +#include "lwip/ip6_addr.h" +#include "sdkconfig.h" +#include "common/code_utils.hpp" +#include "openthread/error.h" +#include "esp_check.h" +#include "esp_event.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "mdns.h" +#include "esp_netif_ip_addr.h" +#include "esp_openthread.h" +#include "esp_openthread_border_router.h" +#include "esp_openthread_common_macro.h" +#include "esp_openthread_lock.h" +#include "esp_openthread_radio.h" +#include "esp_openthread_task_queue.h" +#include "lwip/pbuf.h" +#include "lwip/tcpip.h" +#include "lwip/udp.h" +#include "openthread/trel.h" +#include "openthread/platform/diag.h" + +static esp_netif_t *s_trel_netif = NULL; +static otPlatTrelCounters s_trel_counters; + +#define TREL_MDNS_TYPE "_trel" +#define TREL_MDNS_PROTO "_udp" + +typedef struct { + uint16_t port; + struct udp_pcb *trel_pcb; +} ot_trel_t; + +typedef struct { + struct pbuf *p; +} ot_trel_recv_task_t; + +typedef struct { + struct udp_pcb *pcb; + const uint8_t *payload; + uint16_t length; + ip_addr_t peer_addr; + uint16_t peer_port; +} ot_trel_send_task_t; + +static ot_trel_t s_ot_trel = {CONFIG_OPENTHREAD_TREL_PORT, NULL}; +static bool s_is_service_registered = false; + +static void trel_browse_notifier(mdns_result_t *result) +{ + while (result) { + if (result->addr && result->addr->addr.type == IPADDR_TYPE_V6) { + otPlatTrelPeerInfo info; + uint8_t trel_txt[1024] = {0}; + uint16_t trel_txt_len = 0; + size_t index = 0; + while (index < result->txt_count) { + trel_txt[trel_txt_len++] = strlen(result->txt[index].key) + result->txt_value_len[index] + 1; + memcpy((trel_txt + trel_txt_len), (void *)result->txt[index].key, strlen(result->txt[index].key)); + trel_txt_len += (strlen(result->txt[index].key)); + trel_txt[trel_txt_len++] = '='; + memcpy((trel_txt + trel_txt_len), (void *)result->txt[index].value, result->txt_value_len[index]); + trel_txt_len += result->txt_value_len[index]; + index++; + } + if (!s_trel_netif) { + s_trel_netif = result->esp_netif; + } + info.mTxtData = trel_txt; + info.mTxtLength = trel_txt_len; + info.mSockAddr.mPort = result->port; + memcpy(info.mSockAddr.mAddress.mFields.m32, result->addr->addr.u_addr.ip6.addr, OT_IP6_ADDRESS_SIZE); + info.mRemoved = (result->ttl == 0); + ESP_LOGI(OT_PLAT_LOG_TAG, "%s TREL peer: address: %s, port:%d", info.mRemoved ? "Remove" : "Found", ip6addr_ntoa(((ip6_addr_t*)(&result->addr->addr.u_addr.ip6))), info.mSockAddr.mPort); + esp_openthread_task_switching_lock_acquire(portMAX_DELAY); + otPlatTrelHandleDiscoveredPeerInfo(esp_openthread_get_instance(), &info); + esp_openthread_task_switching_lock_release(); + } + result = result->next; + } +} + +static void trel_recv_task(void *ctx) +{ + struct pbuf *recv_buf = (struct pbuf *)ctx; + uint8_t *data_buf = (uint8_t *)recv_buf->payload; + uint8_t *data_buf_to_free = NULL; + uint16_t length = recv_buf->len; + + if (recv_buf->next != NULL) { + data_buf = (uint8_t *)malloc(recv_buf->tot_len); + if (data_buf != NULL) { + length = recv_buf->tot_len; + data_buf_to_free = data_buf; + pbuf_copy_partial(recv_buf, data_buf, recv_buf->tot_len, 0); + } else { + ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to allocate data buf when receiving Thread TREL message"); + ExitNow(); + } + } + otPlatTrelHandleReceived(esp_openthread_get_instance(), data_buf, length); + +exit: + if (data_buf_to_free) { + free(data_buf_to_free); + } + pbuf_free(recv_buf); +} + +static void handle_trel_udp_recv(void *ctx, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, uint16_t port) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Receive from %s:%d", ip6addr_ntoa(&(addr->u_addr.ip6)), port); + if (esp_openthread_task_queue_post(trel_recv_task, p) != ESP_OK) { + ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to receive OpenThread TREL message"); + } +} + +static esp_err_t ot_new_trel(void *ctx) +{ + ot_trel_t *task = (ot_trel_t *)ctx; + + task->trel_pcb = udp_new(); + ESP_RETURN_ON_FALSE(task->trel_pcb != NULL, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG, "Failed to create a new UDP pcb"); + udp_bind(task->trel_pcb, IP6_ADDR_ANY, task->port); + udp_recv(task->trel_pcb, handle_trel_udp_recv, NULL); + return ESP_OK; +} + +void otPlatTrelEnable(otInstance *aInstance, uint16_t *aUdpPort) +{ + *aUdpPort = s_ot_trel.port; + esp_openthread_task_switching_lock_release(); + esp_err_t err = esp_netif_tcpip_exec(ot_new_trel, &s_ot_trel); + if (err != ESP_OK) { + ESP_LOGE(OT_PLAT_LOG_TAG, "Fail to create trel udp"); + } + mdns_browse_new(TREL_MDNS_TYPE, TREL_MDNS_PROTO, trel_browse_notifier); + esp_openthread_task_switching_lock_acquire(portMAX_DELAY); +} + +static void trel_send_task(void *ctx) +{ + err_t err = ERR_OK; + struct pbuf *send_buf = NULL; + ot_trel_send_task_t *task = (ot_trel_send_task_t *)ctx; + + task->pcb = s_ot_trel.trel_pcb; + task->pcb->ttl = UDP_TTL; + task->pcb->netif_idx = esp_netif_get_netif_impl_index(s_trel_netif); + task->peer_addr.u_addr.ip6.zone = 0; + task->peer_addr.type = IPADDR_TYPE_V6; + task->pcb->flags = (task->pcb->flags & (~UDP_FLAGS_MULTICAST_LOOP)); + task->pcb->local_port = s_ot_trel.port; + send_buf = pbuf_alloc(PBUF_TRANSPORT, task->length, PBUF_RAM); + if (send_buf == NULL) { + ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to allocate data buf when sending Thread TREL message"); + ExitNow(); + } + memcpy(send_buf->payload, task->payload, task->length); + err = udp_sendto_if(task->pcb, send_buf, &task->peer_addr, task->peer_port, netif_get_by_index(task->pcb->netif_idx)); + if(err != ERR_OK) { + ESP_LOGE(OT_PLAT_LOG_TAG, "Fail to send trel msg to %s:%d %d (%d)", ip6addr_ntoa(&(task->peer_addr.u_addr.ip6)), task->peer_port, task->pcb->netif_idx, err); + } +exit: + pbuf_free(send_buf); + free(task); +} + +void otPlatTrelSend(otInstance *aInstance, + const uint8_t *aUdpPayload, + uint16_t aUdpPayloadLen, + const otSockAddr *aDestSockAddr) +{ + if (!s_trel_netif) { + ESP_LOGE(OT_PLAT_LOG_TAG, "None Thread TREL interface"); + return; + } + ot_trel_send_task_t *task = (ot_trel_send_task_t *)malloc(sizeof(ot_trel_send_task_t)); + if (task == NULL) { + ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to allocate buf for Thread TREL"); + return; + } + memcpy(task->peer_addr.u_addr.ip6.addr, aDestSockAddr->mAddress.mFields.m32, OT_IP6_ADDRESS_SIZE); + task->peer_port = aDestSockAddr->mPort; + ESP_LOGD(OT_PLAT_LOG_TAG, "send trel msg to %s:%d", ip6addr_ntoa(&(task->peer_addr.u_addr.ip6)), task->peer_port); + task->payload = aUdpPayload; + task->length = aUdpPayloadLen; + esp_openthread_task_switching_lock_release(); + tcpip_callback(trel_send_task, task); + esp_openthread_task_switching_lock_acquire(portMAX_DELAY); +} + +void otPlatTrelRegisterService(otInstance *aInstance, uint16_t aPort, const uint8_t *aTxtData, uint8_t aTxtLength) +{ + esp_err_t ret = ESP_OK; + + esp_openthread_task_switching_lock_release(); + if (s_is_service_registered) { + mdns_service_remove(TREL_MDNS_TYPE, TREL_MDNS_PROTO); + } + mdns_service_add(NULL, TREL_MDNS_TYPE, TREL_MDNS_PROTO, aPort, NULL, 0); + s_is_service_registered = true; + uint16_t index = 0; + while (index < aTxtLength) { + const uint8_t *item_header = aTxtData + index + 1; + uint8_t item_len = aTxtData[index]; + + char key[UINT8_MAX + 1]; + for (uint16_t i = 0; i < item_len; i++) { + if (item_header[i] == '=') { + ESP_GOTO_ON_FALSE(i != 0, ESP_FAIL, exit, OT_PLAT_LOG_TAG, "Wrong format of _trel._udp txt key"); + key[i] = '\0'; + uint16_t value_len = item_len - i - 1; + ESP_GOTO_ON_FALSE(value_len != 0, ESP_FAIL, exit, OT_PLAT_LOG_TAG, "Wrong format of _trel._udp txt value"); + mdns_service_txt_item_set_with_explicit_value_len(TREL_MDNS_TYPE, TREL_MDNS_PROTO, key, (const char *)item_header + i + 1, value_len); + break; + } + key[i] = item_header[i]; + } + index += item_len + 1; + } +exit: + if (ret != ESP_OK) { + ESP_LOGE(OT_PLAT_LOG_TAG, "Registered TREL service with some errors"); + } + esp_openthread_task_switching_lock_acquire(portMAX_DELAY); +} + +void otPlatTrelResetCounters(otInstance *aInstance) +{ + memset(&s_trel_counters, 0, sizeof(otPlatTrelCounters)); +} + +static void trel_disable_task(void *ctx) +{ + struct udp_pcb *pcb = (struct udp_pcb *)ctx; + udp_remove(pcb); +} + +void otPlatTrelDisable(otInstance *aInstance) +{ + esp_openthread_task_switching_lock_release(); + if (s_ot_trel.trel_pcb) { + tcpip_callback(trel_disable_task, s_ot_trel.trel_pcb); + } + mdns_service_remove(TREL_MDNS_TYPE, TREL_MDNS_PROTO); + s_is_service_registered = false; + mdns_browse_delete(TREL_MDNS_TYPE, TREL_MDNS_PROTO); + esp_openthread_task_switching_lock_acquire(portMAX_DELAY); + s_ot_trel.trel_pcb = NULL; +} + +const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance) +{ + return &s_trel_counters; +} + +// TODO: TZ-1169 +OT_TOOL_WEAK otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatRadioSetTransmitPower`"); + return OT_ERROR_NOT_IMPLEMENTED; +} + +OT_TOOL_WEAK otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatRadioGetTransmitPower`"); + return OT_ERROR_NOT_IMPLEMENTED; +} + +OT_TOOL_WEAK bool otPlatRadioGetPromiscuous(otInstance *aInstance) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatRadioGetPromiscuous`"); + return false; +} + +OT_TOOL_WEAK otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatRadioSetCcaEnergyDetectThreshold`"); + return OT_ERROR_NOT_IMPLEMENTED; +} + +OT_TOOL_WEAK otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatRadioGetCcaEnergyDetectThreshold`"); + return OT_ERROR_NOT_IMPLEMENTED; +} + +OT_TOOL_WEAK void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatRadioGetIeeeEui64`"); +} + +OT_TOOL_WEAK otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatRadioGetTransmitBuffer`"); + return NULL; +} + +#if CONFIG_OPENTHREAD_DIAG + +OT_TOOL_WEAK void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatDiagSetOutputCallback`"); +} + +OT_TOOL_WEAK void otPlatDiagModeSet(bool mode) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatDiagModeSet`"); +} + +OT_TOOL_WEAK bool otPlatDiagModeGet(void) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatDiagModeGet`"); + return false; +} + +OT_TOOL_WEAK void otPlatDiagTxPowerSet(int8_t tx_power) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatDiagTxPowerSet`"); +} + +OT_TOOL_WEAK void otPlatDiagChannelSet(uint8_t channel) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatDiagChannelSet`"); +} + +OT_TOOL_WEAK void otPlatDiagAlarmCallback(otInstance *aInstance) +{ + ESP_LOGD(OT_PLAT_LOG_TAG, "Running in TREL mode and not support `otPlatDiagAlarmCallback`"); +} + +#endif // CONFIG_OPENTHREAD_DIAG + +OT_TOOL_WEAK esp_err_t esp_openthread_radio_init(const esp_openthread_platform_config_t *config) +{ + ESP_LOGI(OT_PLAT_LOG_TAG, "Running in TREL mode"); + return ESP_OK; +} + +OT_TOOL_WEAK void esp_openthread_radio_deinit(void) +{ + ESP_LOGI(OT_PLAT_LOG_TAG, "Running in TREL mode"); +} diff --git a/components/openthread/src/port/esp_spi_spinel_interface.cpp b/components/openthread/src/port/esp_spi_spinel_interface.cpp index e19acd915277..61d6cfab2fa1 100644 --- a/components/openthread/src/port/esp_spi_spinel_interface.cpp +++ b/components/openthread/src/port/esp_spi_spinel_interface.cpp @@ -6,7 +6,7 @@ #include "esp_spi_spinel_interface.hpp" -#include "error.h" +#include "openthread/error.h" #include "esp_check.h" #include "esp_openthread_common_macro.h" #include "esp_rom_sys.h" diff --git a/components/partition_table/CMakeLists.txt b/components/partition_table/CMakeLists.txt index d5844374b0d8..26b8229bc75d 100644 --- a/components/partition_table/CMakeLists.txt +++ b/components/partition_table/CMakeLists.txt @@ -1,4 +1,6 @@ idf_build_get_property(target IDF_TARGET) +idf_build_get_property(non_os_build NON_OS_BUILD) + set(priv_req) if(NOT ${target} STREQUAL "linux") list(APPEND priv_req esptool_py) @@ -6,7 +8,7 @@ endif() idf_component_register(PRIV_REQUIRES ${priv_req}) -if(BOOTLOADER_BUILD) +if(non_os_build) return() endif() diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index cce5b78e9168..6c6592b326cf 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -7,11 +7,8 @@ # See https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html # for explanation of partition table structure and uses. # -# SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - -from __future__ import division, print_function, unicode_literals - import argparse import binascii import errno @@ -36,8 +33,12 @@ APP_TYPE = 0x00 DATA_TYPE = 0x01 +BOOTLOADER_TYPE = 0x02 +PARTITION_TABLE_TYPE = 0x03 TYPES = { + 'bootloader': BOOTLOADER_TYPE, + 'partition_table': PARTITION_TABLE_TYPE, 'app': APP_TYPE, 'data': DATA_TYPE, } @@ -56,6 +57,14 @@ def get_ptype_as_int(ptype): # Keep this map in sync with esp_partition_subtype_t enum in esp_partition.h SUBTYPES = { + BOOTLOADER_TYPE: { + # 'primary': 0x00, # The tool does not allow to define this partition yet. + 'ota': 0x01, + }, + PARTITION_TABLE_TYPE: { + # 'primary': 0x00, # The tool does not allow to define this partition yet. + 'ota': 0x01, + }, APP_TYPE: { 'factory': 0x00, 'test': 0x20, @@ -90,6 +99,8 @@ def get_subtype_as_int(ptype, subtype): ALIGNMENT = { APP_TYPE: 0x10000, DATA_TYPE: 0x1000, + BOOTLOADER_TYPE: 0x1000, + PARTITION_TABLE_TYPE: 0x1000, } @@ -110,7 +121,7 @@ def get_alignment_size_for_type(ptype): else: # For no secure boot enabled case, app partition must be 4K aligned (min. flash erase size) return 0x1000 - # No specific size alignement requirement as such + # No specific size alignment requirement as such return 0x1 @@ -119,6 +130,10 @@ def get_partition_type(ptype): return APP_TYPE if ptype == 'data': return DATA_TYPE + if ptype == 'bootloader': + return BOOTLOADER_TYPE + if ptype == 'partition_table': + return PARTITION_TABLE_TYPE raise InputError('Invalid partition type') diff --git a/components/partition_table/project_include.cmake b/components/partition_table/project_include.cmake index 7778af115583..ddd6230db376 100644 --- a/components/partition_table/project_include.cmake +++ b/components/partition_table/project_include.cmake @@ -4,8 +4,9 @@ set(PARTITION_TABLE_CHECK_SIZES_TOOL_PATH "${CMAKE_CURRENT_LIST_DIR}/check_sizes idf_build_get_property(build_dir BUILD_DIR) idf_build_set_property(PARTITION_TABLE_BIN_PATH "${build_dir}/partition_table/partition-table.bin") +idf_build_get_property(non_os_build NON_OS_BUILD) -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) # Set PARTITION_CSV_PATH to the configured partition CSV file # absolute path if(CONFIG_PARTITION_TABLE_CUSTOM) diff --git a/components/sdmmc/include/sd_protocol_defs.h b/components/sdmmc/include/sd_protocol_defs.h index a1b6a8ec0222..8eb52ca6b0ab 100644 --- a/components/sdmmc/include/sd_protocol_defs.h +++ b/components/sdmmc/include/sd_protocol_defs.h @@ -108,6 +108,7 @@ extern "C" { #define MMC_R1_CURRENT_STATE_POS (9) #define MMC_R1_CURRENT_STATE_MASK (0x1E00)/* card current state */ #define MMC_R1_CURRENT_STATE_TRAN (4) +#define MMC_R1_CURRENT_STATE_STATUS(status) (((status) & MMC_R1_CURRENT_STATE_MASK) >> MMC_R1_CURRENT_STATE_POS) /* SPI mode R1 response type bits */ #define SD_SPI_R1_IDLE_STATE (1<<0) @@ -424,7 +425,7 @@ extern "C" { * * 67 45 23 01 ef cd ab 89 * - * MMC_RSP_BITS will extact bits as follows: + * MMC_RSP_BITS will extract bits as follows: * * start=0 len=4 -> result=0x00000007 * start=0 len=12 -> result=0x00000567 diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index fb18a9d69629..a281323ce6e4 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -264,7 +264,22 @@ esp_err_t sdmmc_send_cmd_set_relative_addr(sdmmc_card_t* card, uint16_t* out_rca if (err != ESP_OK) { return err; } - *out_rca = (card->is_mmc) ? mmc_rca : SD_R6_RCA(cmd.response); + + if (card->is_mmc) { + *out_rca = mmc_rca; + } else { + uint16_t response_rca = SD_R6_RCA(cmd.response); + if (response_rca == 0) { + // Try to get another RCA value if RCA value in the previous response was 0x0000 + // The value 0x0000 is reserved to set all cards into the Stand-by State with CMD7 + err = sdmmc_send_cmd(card, &cmd); + if (err != ESP_OK) { + return err; + } + response_rca = SD_R6_RCA(cmd.response); + } + *out_rca = response_rca; + } return ESP_OK; } @@ -444,6 +459,11 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, return err; } +static bool sdmmc_ready_for_data(uint32_t status) +{ + return (status & MMC_R1_READY_FOR_DATA) && (MMC_R1_CURRENT_STATE_STATUS(status) == MMC_R1_CURRENT_STATE_TRAN); +} + esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, size_t start_block, size_t block_count, size_t buffer_len) { @@ -469,18 +489,26 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, } else { cmd.arg = start_block * block_size; } + + uint32_t status = 0; esp_err_t err = sdmmc_send_cmd(card, &cmd); + esp_err_t err_cmd13 = sdmmc_send_cmd_send_status(card, &status); + if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err); + if (err_cmd13 == ESP_OK) { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, status 0x%" PRIx32, __func__, err, status); + } else { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, failed to get status (0x%x)", __func__, err, err_cmd13); + } return err; } - uint32_t status = 0; + size_t count = 0; int64_t yield_delay_us = 100 * 1000; // initially 100ms int64_t t0 = esp_timer_get_time(); int64_t t1 = 0; /* SD mode: wait for the card to become idle based on R1 status */ - while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) { + while (!host_is_spi(card) && !sdmmc_ready_for_data(status)) { t1 = esp_timer_get_time(); if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) { ESP_LOGE(TAG, "write sectors dma - timeout"); @@ -591,18 +619,26 @@ esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst, } else { cmd.arg = start_block * block_size; } + + uint32_t status = 0; esp_err_t err = sdmmc_send_cmd(card, &cmd); + esp_err_t err_cmd13 = sdmmc_send_cmd_send_status(card, &status); + if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err); + if (err_cmd13 == ESP_OK) { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, status 0x%" PRIx32, __func__, err, status); + } else { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, failed to get status (0x%x)", __func__, err, err_cmd13); + } return err; } - uint32_t status = 0; + size_t count = 0; int64_t yield_delay_us = 100 * 1000; // initially 100ms int64_t t0 = esp_timer_get_time(); int64_t t1 = 0; /* SD mode: wait for the card to become idle based on R1 status */ - while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) { + while (!host_is_spi(card) && !sdmmc_ready_for_data(status)) { t1 = esp_timer_get_time(); if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) { ESP_LOGE(TAG, "read sectors dma - timeout"); diff --git a/components/sdmmc/sdmmc_mmc.c b/components/sdmmc/sdmmc_mmc.c index e3f44bc865b5..23f18272f416 100644 --- a/components/sdmmc/sdmmc_mmc.c +++ b/components/sdmmc/sdmmc_mmc.c @@ -272,8 +272,8 @@ esp_err_t sdmmc_init_mmc_check_ext_csd(sdmmc_card_t* card) ESP_LOGE(TAG, "%s: send_status returned 0x%x", __func__, err); goto out; } - status = ((status & MMC_R1_CURRENT_STATE_MASK) >> MMC_R1_CURRENT_STATE_POS); - if (status != MMC_R1_CURRENT_STATE_TRAN) { + + if (MMC_R1_CURRENT_STATE_STATUS(status) != MMC_R1_CURRENT_STATE_TRAN) { ESP_LOGE(TAG, "%s: card not in transfer state", __func__); err = ESP_ERR_INVALID_STATE; goto out; diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index 765cde298b77..032467798f51 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -47,6 +47,10 @@ if(CONFIG_SOC_EMAC_SUPPORTED) list(APPEND srcs "${target_folder}/emac_periph.c") endif() +if(CONFIG_SOC_ETM_SUPPORTED) + list(APPEND srcs "${target_folder}/etm_periph.c") +endif() + if(CONFIG_SOC_GDMA_SUPPORTED) list(APPEND srcs "${target_folder}/gdma_periph.c") endif() @@ -142,10 +146,7 @@ if(CONFIG_SOC_IEEE802154_SUPPORTED) endif() if(CONFIG_SOC_USB_OTG_SUPPORTED) - if(NOT ${target} STREQUAL "esp32p4") - list(APPEND srcs "${target_folder}/usb_periph.c" - "${target_folder}/usb_dwc_periph.c") - endif() + list(APPEND srcs "${target_folder}/usb_dwc_periph.c") endif() if(CONFIG_SOC_DAC_SUPPORTED) diff --git a/components/soc/esp32/i2s_periph.c b/components/soc/esp32/i2s_periph.c index 83c2920af6cf..9f06c85f4039 100644 --- a/components/soc/esp32/i2s_periph.c +++ b/components/soc/esp32/i2s_periph.c @@ -29,7 +29,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sig = I2S0I_DATA_IN15_IDX, .irq = ETS_I2S0_INTR_SOURCE, - .module = PERIPH_I2S0_MODULE, }, { .mck_out_sig = -1, // Unavailable @@ -49,6 +48,5 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sig = I2S1I_DATA_IN15_IDX, .irq = ETS_I2S1_INTR_SOURCE, - .module = PERIPH_I2S1_MODULE, } }; diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index f6f4b25e22cb..625599f4a674 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -483,6 +483,10 @@ config SOC_LEDC_SUPPORT_HS_MODE bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 8 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index bb35d3718a57..4189522ce145 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -241,6 +241,7 @@ #define SOC_LEDC_SUPPORT_APB_CLOCK (1) #define SOC_LEDC_SUPPORT_REF_TICK (1) #define SOC_LEDC_SUPPORT_HS_MODE (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (8) #define SOC_LEDC_TIMER_BIT_WIDTH (20) diff --git a/components/soc/esp32/register/soc/spi_struct.h b/components/soc/esp32/register/soc/spi_struct.h index 36fe885c73dd..320df8e94894 100644 --- a/components/soc/esp32/register/soc/spi_struct.h +++ b/components/soc/esp32/register/soc/spi_struct.h @@ -488,177 +488,7 @@ typedef volatile struct spi_dev_s { uint32_t dma_outlink_dscr_bf1; /*The content of current out descriptor data buffer pointer.*/ uint32_t dma_rx_status; /*spi dma read data from memory status.*/ uint32_t dma_tx_status; /*spi dma write data to memory status.*/ - uint32_t reserved_150; - uint32_t reserved_154; - uint32_t reserved_158; - uint32_t reserved_15c; - uint32_t reserved_160; - uint32_t reserved_164; - uint32_t reserved_168; - uint32_t reserved_16c; - uint32_t reserved_170; - uint32_t reserved_174; - uint32_t reserved_178; - uint32_t reserved_17c; - uint32_t reserved_180; - uint32_t reserved_184; - uint32_t reserved_188; - uint32_t reserved_18c; - uint32_t reserved_190; - uint32_t reserved_194; - uint32_t reserved_198; - uint32_t reserved_19c; - uint32_t reserved_1a0; - uint32_t reserved_1a4; - uint32_t reserved_1a8; - uint32_t reserved_1ac; - uint32_t reserved_1b0; - uint32_t reserved_1b4; - uint32_t reserved_1b8; - uint32_t reserved_1bc; - uint32_t reserved_1c0; - uint32_t reserved_1c4; - uint32_t reserved_1c8; - uint32_t reserved_1cc; - uint32_t reserved_1d0; - uint32_t reserved_1d4; - uint32_t reserved_1d8; - uint32_t reserved_1dc; - uint32_t reserved_1e0; - uint32_t reserved_1e4; - uint32_t reserved_1e8; - uint32_t reserved_1ec; - uint32_t reserved_1f0; - uint32_t reserved_1f4; - uint32_t reserved_1f8; - uint32_t reserved_1fc; - uint32_t reserved_200; - uint32_t reserved_204; - uint32_t reserved_208; - uint32_t reserved_20c; - uint32_t reserved_210; - uint32_t reserved_214; - uint32_t reserved_218; - uint32_t reserved_21c; - uint32_t reserved_220; - uint32_t reserved_224; - uint32_t reserved_228; - uint32_t reserved_22c; - uint32_t reserved_230; - uint32_t reserved_234; - uint32_t reserved_238; - uint32_t reserved_23c; - uint32_t reserved_240; - uint32_t reserved_244; - uint32_t reserved_248; - uint32_t reserved_24c; - uint32_t reserved_250; - uint32_t reserved_254; - uint32_t reserved_258; - uint32_t reserved_25c; - uint32_t reserved_260; - uint32_t reserved_264; - uint32_t reserved_268; - uint32_t reserved_26c; - uint32_t reserved_270; - uint32_t reserved_274; - uint32_t reserved_278; - uint32_t reserved_27c; - uint32_t reserved_280; - uint32_t reserved_284; - uint32_t reserved_288; - uint32_t reserved_28c; - uint32_t reserved_290; - uint32_t reserved_294; - uint32_t reserved_298; - uint32_t reserved_29c; - uint32_t reserved_2a0; - uint32_t reserved_2a4; - uint32_t reserved_2a8; - uint32_t reserved_2ac; - uint32_t reserved_2b0; - uint32_t reserved_2b4; - uint32_t reserved_2b8; - uint32_t reserved_2bc; - uint32_t reserved_2c0; - uint32_t reserved_2c4; - uint32_t reserved_2c8; - uint32_t reserved_2cc; - uint32_t reserved_2d0; - uint32_t reserved_2d4; - uint32_t reserved_2d8; - uint32_t reserved_2dc; - uint32_t reserved_2e0; - uint32_t reserved_2e4; - uint32_t reserved_2e8; - uint32_t reserved_2ec; - uint32_t reserved_2f0; - uint32_t reserved_2f4; - uint32_t reserved_2f8; - uint32_t reserved_2fc; - uint32_t reserved_300; - uint32_t reserved_304; - uint32_t reserved_308; - uint32_t reserved_30c; - uint32_t reserved_310; - uint32_t reserved_314; - uint32_t reserved_318; - uint32_t reserved_31c; - uint32_t reserved_320; - uint32_t reserved_324; - uint32_t reserved_328; - uint32_t reserved_32c; - uint32_t reserved_330; - uint32_t reserved_334; - uint32_t reserved_338; - uint32_t reserved_33c; - uint32_t reserved_340; - uint32_t reserved_344; - uint32_t reserved_348; - uint32_t reserved_34c; - uint32_t reserved_350; - uint32_t reserved_354; - uint32_t reserved_358; - uint32_t reserved_35c; - uint32_t reserved_360; - uint32_t reserved_364; - uint32_t reserved_368; - uint32_t reserved_36c; - uint32_t reserved_370; - uint32_t reserved_374; - uint32_t reserved_378; - uint32_t reserved_37c; - uint32_t reserved_380; - uint32_t reserved_384; - uint32_t reserved_388; - uint32_t reserved_38c; - uint32_t reserved_390; - uint32_t reserved_394; - uint32_t reserved_398; - uint32_t reserved_39c; - uint32_t reserved_3a0; - uint32_t reserved_3a4; - uint32_t reserved_3a8; - uint32_t reserved_3ac; - uint32_t reserved_3b0; - uint32_t reserved_3b4; - uint32_t reserved_3b8; - uint32_t reserved_3bc; - uint32_t reserved_3c0; - uint32_t reserved_3c4; - uint32_t reserved_3c8; - uint32_t reserved_3cc; - uint32_t reserved_3d0; - uint32_t reserved_3d4; - uint32_t reserved_3d8; - uint32_t reserved_3dc; - uint32_t reserved_3e0; - uint32_t reserved_3e4; - uint32_t reserved_3e8; - uint32_t reserved_3ec; - uint32_t reserved_3f0; - uint32_t reserved_3f4; - uint32_t reserved_3f8; + uint32_t reserved_150[171]; union { struct { uint32_t date: 28; /*SPI register version.*/ @@ -667,6 +497,7 @@ typedef volatile struct spi_dev_s { uint32_t val; } date; } spi_dev_t; + extern spi_dev_t SPI0; /* SPI0 IS FOR INTERNAL USE*/ extern spi_dev_t SPI1; extern spi_dev_t SPI2; diff --git a/components/soc/esp32/spi_periph.c b/components/soc/esp32/spi_periph.c index 934fcde61c99..5ff8450533cc 100644 --- a/components/soc/esp32/spi_periph.c +++ b/components/soc/esp32/spi_periph.c @@ -31,7 +31,6 @@ const spi_signal_conn_t spi_periph_signal[3] = { .spics0_iomux_pin = MSPI_IOMUX_PIN_NUM_CS0, .irq = ETS_SPI1_INTR_SOURCE, .irq_dma = ETS_SPI1_DMA_INTR_SOURCE, - .module = PERIPH_SPI_MODULE, .func = MSPI_FUNC_NUM, .hw = &SPI1 }, { @@ -55,7 +54,6 @@ const spi_signal_conn_t spi_periph_signal[3] = { .spics0_iomux_pin = HSPI_IOMUX_PIN_NUM_CS, .irq = ETS_SPI2_INTR_SOURCE, .irq_dma = ETS_SPI2_DMA_INTR_SOURCE, - .module = PERIPH_HSPI_MODULE, .func = HSPI_FUNC_NUM, .hw = &SPI2 }, { @@ -79,7 +77,6 @@ const spi_signal_conn_t spi_periph_signal[3] = { .spics0_iomux_pin = VSPI_IOMUX_PIN_NUM_CS, .irq = ETS_SPI3_INTR_SOURCE, .irq_dma = ETS_SPI3_DMA_INTR_SOURCE, - .module = PERIPH_VSPI_MODULE, .func = VSPI_FUNC_NUM, .hw = &SPI3 } diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 4ece6275e653..6bf5970c6c57 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -383,6 +383,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 6 diff --git a/components/soc/esp32c2/include/soc/dport_access.h b/components/soc/esp32c2/include/soc/dport_access.h index 5a847ca48423..e499a791bdd6 100644 --- a/components/soc/esp32c2/include/soc/dport_access.h +++ b/components/soc/esp32c2/include/soc/dport_access.h @@ -8,8 +8,7 @@ #define _DPORT_ACCESS_H_ #include -#include "soc.h" -#include "uart_reg.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32c2/include/soc/interrupt_reg.h b/components/soc/esp32c2/include/soc/interrupt_reg.h index 749a2e921671..d02c2d5c20ce 100644 --- a/components/soc/esp32c2/include/soc/interrupt_reg.h +++ b/components/soc/esp32c2/include/soc/interrupt_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "interrupt_core0_reg.h" +#include "soc/interrupt_core0_reg.h" #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG INTERRUPT_CORE0_CPU_INT_THRESH_REG #define INTERRUPT_PRIO_REG(n) (INTERRUPT_CORE0_CPU_INT_PRI_0_REG + (n)*4) diff --git a/components/soc/esp32c2/include/soc/soc.h b/components/soc/esp32c2/include/soc/soc.h index a57b15794aec..a24a2b197e67 100644 --- a/components/soc/esp32c2/include/soc/soc.h +++ b/components/soc/esp32c2/include/soc/soc.h @@ -12,7 +12,7 @@ #endif #include "esp_bit_defs.h" -#include "reg_base.h" +#include "soc/reg_base.h" #define PRO_CPU_NUM (0) diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 7e93ba622663..83b6c936e675 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -170,6 +170,7 @@ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (6) #define SOC_LEDC_TIMER_BIT_WIDTH (14) #define SOC_LEDC_SUPPORT_FADE_STOP (1) diff --git a/components/soc/esp32c2/include/soc/apb_saradc_reg.h b/components/soc/esp32c2/register/soc/apb_saradc_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/apb_saradc_reg.h rename to components/soc/esp32c2/register/soc/apb_saradc_reg.h diff --git a/components/soc/esp32c2/include/soc/apb_saradc_struct.h b/components/soc/esp32c2/register/soc/apb_saradc_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/apb_saradc_struct.h rename to components/soc/esp32c2/register/soc/apb_saradc_struct.h diff --git a/components/soc/esp32c2/include/soc/assist_debug_reg.h b/components/soc/esp32c2/register/soc/assist_debug_reg.h similarity index 95% rename from components/soc/esp32c2/include/soc/assist_debug_reg.h rename to components/soc/esp32c2/register/soc/assist_debug_reg.h index 2734f5e29848..bee2070557c6 100644 --- a/components/soc/esp32c2/include/soc/assist_debug_reg.h +++ b/components/soc/esp32c2/register/soc/assist_debug_reg.h @@ -15,14 +15,14 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_INTR_ENA_REG (DR_REG_ASSIST_DEBUG_BASE + 0x0) /** ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA : R/W; bitpos: [0]; default: 0; - * enbale sp underlow monitor + * enable sp underflow monitor */ #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA (BIT(0)) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA_M (ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA_V << ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA_S) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA_V 0x00000001U #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA_S 0 /** ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_ENA : R/W; bitpos: [1]; default: 0; - * enbale sp overflow monitor + * enable sp overflow monitor */ #define ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_ENA (BIT(1)) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_ENA_M (ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_ENA_V << ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_ENA_S) @@ -34,14 +34,14 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_INTR_RAW_REG (DR_REG_ASSIST_DEBUG_BASE + 0x4) /** ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RAW : RO; bitpos: [0]; default: 0; - * sp underlow monitor interrupt status register + * sp underflow monitor interrupt status register */ #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RAW (BIT(0)) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RAW_M (ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RAW_V << ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RAW_S) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RAW_V 0x00000001U #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RAW_S 0 /** ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RAW : RO; bitpos: [1]; default: 0; - * sp overflow monitor interupt status register + * sp overflow monitor interrupt status register */ #define ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RAW (BIT(1)) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RAW_M (ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RAW_V << ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RAW_S) @@ -53,14 +53,14 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_INTR_RLS_REG (DR_REG_ASSIST_DEBUG_BASE + 0x8) /** ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RLS : R/W; bitpos: [0]; default: 0; - * enbale sp underlow monitor interrupt + * enable sp underflow monitor interrupt */ #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RLS (BIT(0)) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RLS_M (ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RLS_V << ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RLS_S) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RLS_V 0x00000001U #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_RLS_S 0 /** ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RLS : R/W; bitpos: [1]; default: 0; - * enbale sp overflow monitor interrupt + * enable sp overflow monitor interrupt */ #define ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RLS (BIT(1)) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RLS_M (ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RLS_V << ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_RLS_S) @@ -72,7 +72,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_INTR_CLR_REG (DR_REG_ASSIST_DEBUG_BASE + 0xc) /** ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_CLR : WT; bitpos: [0]; default: 0; - * clr sp underlow monitor interrupt + * clr sp underflow monitor interrupt */ #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_CLR (BIT(0)) #define ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_CLR_M (ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_CLR_V << ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_CLR_S) @@ -91,7 +91,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_SP_MIN_REG (DR_REG_ASSIST_DEBUG_BASE + 0x10) /** ASSIST_DEBUG_CORE_0_SP_MIN : R/W; bitpos: [31:0]; default: 0; - * core0 sp region configuration regsiter + * core0 sp region configuration register */ #define ASSIST_DEBUG_CORE_0_SP_MIN 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_0_SP_MIN_M (ASSIST_DEBUG_CORE_0_SP_MIN_V << ASSIST_DEBUG_CORE_0_SP_MIN_S) @@ -115,7 +115,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_SP_PC_REG (DR_REG_ASSIST_DEBUG_BASE + 0x18) /** ASSIST_DEBUG_CORE_0_SP_PC : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ #define ASSIST_DEBUG_CORE_0_SP_PC 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_0_SP_PC_M (ASSIST_DEBUG_CORE_0_SP_PC_V << ASSIST_DEBUG_CORE_0_SP_PC_S) @@ -142,7 +142,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGEN_S 1 /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG (DR_REG_ASSIST_DEBUG_BASE + 0x20) /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC : RO; bitpos: [31:0]; default: 0; @@ -154,7 +154,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_S 0 /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP_REG (DR_REG_ASSIST_DEBUG_BASE + 0x24) /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP : RO; bitpos: [31:0]; default: 0; diff --git a/components/soc/esp32c2/include/soc/ecc_mult_reg.h b/components/soc/esp32c2/register/soc/ecc_mult_reg.h similarity index 99% rename from components/soc/esp32c2/include/soc/ecc_mult_reg.h rename to components/soc/esp32c2/register/soc/ecc_mult_reg.h index 906a91b7af77..cb4bf5797b90 100644 --- a/components/soc/esp32c2/include/soc/ecc_mult_reg.h +++ b/components/soc/esp32c2/register/soc/ecc_mult_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32c2/include/soc/efuse_reg.h b/components/soc/esp32c2/register/soc/efuse_reg.h similarity index 99% rename from components/soc/esp32c2/include/soc/efuse_reg.h rename to components/soc/esp32c2/register/soc/efuse_reg.h index 6f13f2a2bae8..8471fef930a2 100644 --- a/components/soc/esp32c2/include/soc/efuse_reg.h +++ b/components/soc/esp32c2/register/soc/efuse_reg.h @@ -7,7 +7,7 @@ #include #include "soc/soc.h" -#include "efuse_defs.h" +#include "soc/efuse_defs.h" #ifdef __cplusplus extern "C" { #endif @@ -896,7 +896,7 @@ extern "C" { #define EFUSE_CLK_EN_S 16 /** EFUSE_CONF_REG register - * eFuse operation mode configuraiton register + * eFuse operation mode configuration register */ #define EFUSE_CONF_REG (DR_REG_EFUSE_BASE + 0x8c) /** EFUSE_OP_CODE : R/W; bitpos: [15:0]; default: 0; diff --git a/components/soc/esp32c2/include/soc/efuse_struct.h b/components/soc/esp32c2/register/soc/efuse_struct.h similarity index 99% rename from components/soc/esp32c2/include/soc/efuse_struct.h rename to components/soc/esp32c2/register/soc/efuse_struct.h index c30ded3f9c92..fa1800be944a 100644 --- a/components/soc/esp32c2/include/soc/efuse_struct.h +++ b/components/soc/esp32c2/register/soc/efuse_struct.h @@ -745,7 +745,7 @@ typedef union { } efuse_clk_reg_t; /** Type of conf register - * eFuse operation mode configuraiton register + * eFuse operation mode configuration register */ typedef union { struct { diff --git a/components/soc/esp32c2/include/soc/extmem_reg.h b/components/soc/esp32c2/register/soc/extmem_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/extmem_reg.h rename to components/soc/esp32c2/register/soc/extmem_reg.h diff --git a/components/soc/esp32c2/include/soc/gdma_reg.h b/components/soc/esp32c2/register/soc/gdma_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/gdma_reg.h rename to components/soc/esp32c2/register/soc/gdma_reg.h diff --git a/components/soc/esp32c2/include/soc/gdma_struct.h b/components/soc/esp32c2/register/soc/gdma_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/gdma_struct.h rename to components/soc/esp32c2/register/soc/gdma_struct.h diff --git a/components/soc/esp32c2/include/soc/gpio_reg.h b/components/soc/esp32c2/register/soc/gpio_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/gpio_reg.h rename to components/soc/esp32c2/register/soc/gpio_reg.h diff --git a/components/soc/esp32c2/include/soc/gpio_struct.h b/components/soc/esp32c2/register/soc/gpio_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/gpio_struct.h rename to components/soc/esp32c2/register/soc/gpio_struct.h diff --git a/components/soc/esp32c2/include/soc/i2c_reg.h b/components/soc/esp32c2/register/soc/i2c_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/i2c_reg.h rename to components/soc/esp32c2/register/soc/i2c_reg.h diff --git a/components/soc/esp32c2/include/soc/i2c_struct.h b/components/soc/esp32c2/register/soc/i2c_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/i2c_struct.h rename to components/soc/esp32c2/register/soc/i2c_struct.h diff --git a/components/soc/esp32c2/include/soc/interrupt_core0_reg.h b/components/soc/esp32c2/register/soc/interrupt_core0_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/interrupt_core0_reg.h rename to components/soc/esp32c2/register/soc/interrupt_core0_reg.h diff --git a/components/soc/esp32c2/include/soc/io_mux_reg.h b/components/soc/esp32c2/register/soc/io_mux_reg.h similarity index 99% rename from components/soc/esp32c2/include/soc/io_mux_reg.h rename to components/soc/esp32c2/register/soc/io_mux_reg.h index b54614e4778d..7a59d046f7ff 100644 --- a/components/soc/esp32c2/include/soc/io_mux_reg.h +++ b/components/soc/esp32c2/register/soc/io_mux_reg.h @@ -7,7 +7,7 @@ #define _SOC_IO_MUX_REG_H_ #pragma once -#include "soc.h" +#include "soc/soc.h" /* The following are the bit fields for PERIPHS_IO_MUX_x_U registers */ /* Output enable in sleep mode */ diff --git a/components/soc/esp32c2/include/soc/ledc_reg.h b/components/soc/esp32c2/register/soc/ledc_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/ledc_reg.h rename to components/soc/esp32c2/register/soc/ledc_reg.h diff --git a/components/soc/esp32c2/include/soc/ledc_struct.h b/components/soc/esp32c2/register/soc/ledc_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/ledc_struct.h rename to components/soc/esp32c2/register/soc/ledc_struct.h diff --git a/components/soc/esp32c2/include/soc/modem_clkrst_reg.h b/components/soc/esp32c2/register/soc/modem_clkrst_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/modem_clkrst_reg.h rename to components/soc/esp32c2/register/soc/modem_clkrst_reg.h diff --git a/components/soc/esp32c2/include/soc/reg_base.h b/components/soc/esp32c2/register/soc/reg_base.h similarity index 97% rename from components/soc/esp32c2/include/soc/reg_base.h rename to components/soc/esp32c2/register/soc/reg_base.h index b410fbb3f3d2..34b56a9d95b8 100644 --- a/components/soc/esp32c2/include/soc/reg_base.h +++ b/components/soc/esp32c2/register/soc/reg_base.h @@ -43,5 +43,5 @@ #define DR_REG_I2C_MST_BASE 0x6004E800 #define DR_REG_XTS_AES_BASE 0x600CC000 -/* For backward compatability with the older register name */ +/* For backward compatibility with the older register name */ #define DR_REG_AES_XTS_BASE DR_REG_XTS_AES_BASE diff --git a/components/soc/esp32c2/include/soc/rtc_cntl_reg.h b/components/soc/esp32c2/register/soc/rtc_cntl_reg.h similarity index 99% rename from components/soc/esp32c2/include/soc/rtc_cntl_reg.h rename to components/soc/esp32c2/register/soc/rtc_cntl_reg.h index e5ce9bff061b..2a9a5659f7f6 100644 --- a/components/soc/esp32c2/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32c2/register/soc/rtc_cntl_reg.h @@ -9,7 +9,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define RTC_CNTL_TIME0_REG RTC_CNTL_TIME_LOW0_REG #define RTC_CNTL_TIME1_REG RTC_CNTL_TIME_HIGH0_REG @@ -1144,7 +1144,7 @@ RO CPU.*/ #define RTC_CNTL_SWD_AUTO_FEED_EN_V 0x1 #define RTC_CNTL_SWD_AUTO_FEED_EN_S 31 /* RTC_CNTL_SWD_DISABLE : ;bitpos:[30] ;default: 1'b0 ; */ -/*description: disabel SWD.*/ +/*description: disable SWD.*/ #define RTC_CNTL_SWD_DISABLE (BIT(30)) #define RTC_CNTL_SWD_DISABLE_M (BIT(30)) #define RTC_CNTL_SWD_DISABLE_V 0x1 diff --git a/components/soc/esp32c2/include/soc/rtc_cntl_struct.h b/components/soc/esp32c2/register/soc/rtc_cntl_struct.h similarity index 99% rename from components/soc/esp32c2/include/soc/rtc_cntl_struct.h rename to components/soc/esp32c2/register/soc/rtc_cntl_struct.h index 89a7820dc27a..5252040c3f0c 100644 --- a/components/soc/esp32c2/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32c2/register/soc/rtc_cntl_struct.h @@ -399,7 +399,7 @@ typedef volatile struct rtc_cntl_dev_s{ uint32_t swd_signal_width : 10; /*adjust signal width send to swd*/ uint32_t swd_rst_flag_clr : 1; /*reset swd reset flag*/ uint32_t swd_feed : 1; /*Sw feed swd*/ - uint32_t swd_disable : 1; /*disabel SWD*/ + uint32_t swd_disable : 1; /*disable SWD*/ uint32_t swd_auto_feed_en : 1; /*automatically feed swd when int comes*/ }; uint32_t val; diff --git a/components/soc/esp32c2/include/soc/sensitive_reg.h b/components/soc/esp32c2/register/soc/sensitive_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/sensitive_reg.h rename to components/soc/esp32c2/register/soc/sensitive_reg.h diff --git a/components/soc/esp32c2/include/soc/sensitive_struct.h b/components/soc/esp32c2/register/soc/sensitive_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/sensitive_struct.h rename to components/soc/esp32c2/register/soc/sensitive_struct.h diff --git a/components/soc/esp32c2/include/soc/spi_mem_reg.h b/components/soc/esp32c2/register/soc/spi_mem_reg.h similarity index 99% rename from components/soc/esp32c2/include/soc/spi_mem_reg.h rename to components/soc/esp32c2/register/soc/spi_mem_reg.h index bd22f94efb10..8eeb65b014f4 100644 --- a/components/soc/esp32c2/include/soc/spi_mem_reg.h +++ b/components/soc/esp32c2/register/soc/spi_mem_reg.h @@ -7,7 +7,7 @@ #define _SOC_SPI_MEM_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif @@ -94,15 +94,15 @@ he bit will be cleared once the operation done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_DP_S 21 /* SPI_MEM_FLASH_RES : R/W/SC ;bitpos:[20] ;default: 1'b0 ; */ /*description: This bit combined with reg_resandres bit releases Flash from the power-down stat -e or high performance mode and obtains the devices ID. The bit will be cleared o -nce the operation done.1: enable 0: disable..*/ +e or high performance mode and obtains the devices ID. The bit will be cleared once +the operation done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_RES (BIT(20)) #define SPI_MEM_FLASH_RES_M (BIT(20)) #define SPI_MEM_FLASH_RES_V 0x1 #define SPI_MEM_FLASH_RES_S 20 /* SPI_MEM_FLASH_HPM : R/W/SC ;bitpos:[19] ;default: 1'b0 ; */ -/*description: Drive Flash into high performance mode. The bit will be cleared once the operat -ion done.1: enable 0: disable..*/ +/*description: Drive Flash into high performance mode. The bit will be cleared once the operation +done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_HPM (BIT(19)) #define SPI_MEM_FLASH_HPM_M (BIT(19)) #define SPI_MEM_FLASH_HPM_V 0x1 @@ -123,8 +123,8 @@ peration done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_PE_V 0x1 #define SPI_MEM_FLASH_PE_S 17 /* SPI_MEM_MSPI_ST : RO ;bitpos:[7:4] ;default: 4'b0 ; */ -/*description: The current status of SPI1 slave FSM: mspi_st. 0: idle state, 1: preparation sta -te, 2: send command state, 3: send address state, 4: wait state, 5: read data st +/*description: The current status of SPI1 slave FSM: mspi_st. 0: idle state, 1: preparation +state, 2: send command state, 3: send address state, 4: wait state, 5: read data st ate, 6:write data state, 7: done state, 8: read data end state..*/ #define SPI_MEM_MSPI_ST 0x0000000F #define SPI_MEM_MSPI_ST_M ((SPI_MEM_MSPI_ST_V)<<(SPI_MEM_MSPI_ST_S)) @@ -213,14 +213,14 @@ UT AND SPI_MEM_FREAD_DOUT. 1: enable 0: disable..*/ #define SPI_MEM_FASTRD_MODE_V 0x1 #define SPI_MEM_FASTRD_MODE_S 13 /* SPI_MEM_TX_CRC_EN : R/W ;bitpos:[11] ;default: 1'b0 ; */ -/*description: For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disabl +/*description: For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disable e.*/ #define SPI_MEM_TX_CRC_EN (BIT(11)) #define SPI_MEM_TX_CRC_EN_M (BIT(11)) #define SPI_MEM_TX_CRC_EN_V 0x1 #define SPI_MEM_TX_CRC_EN_S 11 /* SPI_MEM_FCS_CRC_EN : R/W ;bitpos:[10] ;default: 1'b0 ; */ -/*description: For SPI1, initialize crc32 module before writing encrypted data to flash. Activ +/*description: For SPI1, initialize crc32 module before writing encrypted data to flash. Active e low..*/ #define SPI_MEM_FCS_CRC_EN (BIT(10)) #define SPI_MEM_FCS_CRC_EN_M (BIT(10)) @@ -262,7 +262,7 @@ e low..*/ /* SPI_MEM_CLK_MODE : R/W ;bitpos:[1:0] ;default: 2'h0 ; */ /*description: SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delaye d one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inacti -ve 3: SPI clock is alwasy on..*/ +ve 3: SPI clock is always on..*/ #define SPI_MEM_CLK_MODE 0x00000003 #define SPI_MEM_CLK_MODE_M ((SPI_MEM_CLK_MODE_V)<<(SPI_MEM_CLK_MODE_S)) #define SPI_MEM_CLK_MODE_V 0x3 @@ -822,7 +822,7 @@ out, status_in[15:0] is valid when two bytes of data are read out), SUS/SUS1/SUS #define SPI_MEM_FLASH_PES_EN_S 5 /* SPI_MEM_PES_PER_EN : R/W ;bitpos:[4] ;default: 1'b0 ; */ /*description: Set this bit to enable PES end triggers PER transfer option. If this bit is 0, a -pplication should send PER after PES is done..*/ +application should send PER after PES is done..*/ #define SPI_MEM_PES_PER_EN (BIT(4)) #define SPI_MEM_PES_PER_EN_M (BIT(4)) #define SPI_MEM_PES_PER_EN_V 0x1 @@ -844,8 +844,8 @@ resume command is sent..*/ #define SPI_MEM_FLASH_PER_WAIT_EN_V 0x1 #define SPI_MEM_FLASH_PER_WAIT_EN_S 2 /* SPI_MEM_FLASH_PES : R/W/SC ;bitpos:[1] ;default: 1'b0 ; */ -/*description: program erase suspend bit, program erase suspend operation will be triggered whe -n the bit is set. The bit will be cleared once the operation done.1: enable 0: d +/*description: program erase suspend bit, program erase suspend operation will be triggered when +the bit is set. The bit will be cleared once the operation done.1: enable 0: d isable..*/ #define SPI_MEM_FLASH_PES (BIT(1)) #define SPI_MEM_FLASH_PES_M (BIT(1)) @@ -1148,7 +1148,7 @@ ut with the spi_clk high edge ,6: output with the spi_clk low edge.*/ #define SPI_MEM_INT_RAW_REG(i) (REG_SPI_MEM_BASE(i) + 0xC8) /* SPI_MEM_BROWN_OUT_INT_RAW : R/WTC/SS ;bitpos:[5] ;default: 1'b0 ; */ /*description: The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that -chip is loosing power and RTC module sends out brown out close flash request to +chip is losing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others..*/ #define SPI_MEM_BROWN_OUT_INT_RAW (BIT(5)) diff --git a/components/soc/esp32c2/include/soc/spi_mem_struct.h b/components/soc/esp32c2/register/soc/spi_mem_struct.h similarity index 99% rename from components/soc/esp32c2/include/soc/spi_mem_struct.h rename to components/soc/esp32c2/register/soc/spi_mem_struct.h index c2cc1c5010af..230c292b4b29 100644 --- a/components/soc/esp32c2/include/soc/spi_mem_struct.h +++ b/components/soc/esp32c2/register/soc/spi_mem_struct.h @@ -64,7 +64,7 @@ typedef volatile struct spi_mem_dev_s{ } ctrl; union { struct { - uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on.*/ + uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is always on.*/ uint32_t cs_hold_dly_res : 10; /*After RES/DP/HPM command is sent, SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 512) SPI_CLK cycles.*/ uint32_t reserved2 : 18; /*reserved*/ uint32_t rxfifo_rst : 1; /*SPI0 RX FIFO reset signal.*/ @@ -322,7 +322,7 @@ typedef volatile struct spi_mem_dev_s{ uint32_t wpe_end : 1; /*The raw bit for SPI_MEM_WPE_END_INT interrupt. 1: Triggered when WRSR/PP/SE/BE/CE is sent and flash is already idle. 0: Others.*/ uint32_t slv_st_end : 1; /*The raw bit for SPI_MEM_SLV_ST_END_INT interrupt. 1: Triggered when spi1_slv_st is changed from non idle state to idle state. It means that SPI_CS raises high. 0: Others*/ uint32_t mst_st_end : 1; /*The raw bit for SPI_MEM_MST_ST_END_INT interrupt. 1: Triggered when spi1_mst_st is changed from non idle state to idle state. 0: Others.*/ - uint32_t brown_out : 1; /*The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is loosing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others.*/ + uint32_t brown_out : 1; /*The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is losing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others.*/ uint32_t reserved6 : 26; /*reserved*/ }; uint32_t val; diff --git a/components/soc/esp32c2/include/soc/spi_reg.h b/components/soc/esp32c2/register/soc/spi_reg.h similarity index 99% rename from components/soc/esp32c2/include/soc/spi_reg.h rename to components/soc/esp32c2/register/soc/spi_reg.h index eaa92535e1ec..29293c94699a 100644 --- a/components/soc/esp32c2/include/soc/spi_reg.h +++ b/components/soc/esp32c2/register/soc/spi_reg.h @@ -159,7 +159,7 @@ e, the FSPI bus signals are output. Can be configured in CONF state..*/ #define SPI_CLOCK_REG(i) (REG_SPI_BASE(i) + 0xC) /* SPI_CLK_EQU_SYSCLK : R/W ;bitpos:[31] ;default: 1'b1 ; */ -/*description: In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from syst +/*description: In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from syst em clock. Can be configured in CONF state..*/ #define SPI_CLK_EQU_SYSCLK (BIT(31)) #define SPI_CLK_EQU_SYSCLK_M (BIT(31)) @@ -196,15 +196,15 @@ e 0. Can be configured in CONF state..*/ #define SPI_USER_REG(i) (REG_SPI_BASE(i) + 0x10) /* SPI_USR_COMMAND : R/W ;bitpos:[31] ;default: 1'b1 ; */ -/*description: This bit enable the command phase of an operation. Can be configured in CONF sta -te..*/ +/*description: This bit enable the command phase of an operation. Can be configured in CONF +state..*/ #define SPI_USR_COMMAND (BIT(31)) #define SPI_USR_COMMAND_M (BIT(31)) #define SPI_USR_COMMAND_V 0x1 #define SPI_USR_COMMAND_S 31 /* SPI_USR_ADDR : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: This bit enable the address phase of an operation. Can be configured in CONF sta -te..*/ +/*description: This bit enable the address phase of an operation. Can be configured in CONF +state..*/ #define SPI_USR_ADDR (BIT(30)) #define SPI_USR_ADDR_M (BIT(30)) #define SPI_USR_ADDR_V 0x1 @@ -392,7 +392,7 @@ n be configured in CONF state..*/ #define SPI_USR_COMMAND_BITLEN_S 28 /* SPI_MST_REMPTY_ERR_END_EN : R/W ;bitpos:[27] ;default: 1'b1 ; */ /*description: 1: SPI transfer is ended when SPI TX AFIFO read empty error is valid in GP-SPI m -aster FD/HD-mode. 0: SPI transfer is not ended when SPI TX AFIFO read empty erro +aster FD/HD-mode. 0: SPI transfer is not ended when SPI TX AFIFO read empty error r is valid in GP-SPI master FD/HD-mode..*/ #define SPI_MST_REMPTY_ERR_END_EN (BIT(27)) #define SPI_MST_REMPTY_ERR_END_EN_M (BIT(27)) @@ -1113,7 +1113,7 @@ AFIFO read-empty error when SPI outputs data in master mode. 0: Others..*/ #define SPI_SLV_CMD_ERR_INT_RAW_V 0x1 #define SPI_SLV_CMD_ERR_INT_RAW_S 16 /* SPI_SLV_BUF_ADDR_ERR_INT_RAW : R/WTC/SS ;bitpos:[15] ;default: 1'b0 ; */ -/*description: The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data addres +/*description: The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data address s of the current SPI slave mode CPU controlled FD, Wr_BUF or Rd_BUF transmission is bigger than 63. 0: Others..*/ #define SPI_SLV_BUF_ADDR_ERR_INT_RAW (BIT(15)) @@ -1684,7 +1684,7 @@ dge 0: output data at tsck posedge.*/ /* SPI_CLK_MODE : R/W ;bitpos:[1:0] ;default: 2'b0 ; */ /*description: SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delaye d one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inacti -ve 3: SPI clock is alwasy on. Can be configured in CONF state..*/ +ve 3: SPI clock is always on. Can be configured in CONF state..*/ #define SPI_CLK_MODE 0x00000003 #define SPI_CLK_MODE_M ((SPI_CLK_MODE_V)<<(SPI_CLK_MODE_S)) #define SPI_CLK_MODE_V 0x3 diff --git a/components/soc/esp32c2/include/soc/spi_struct.h b/components/soc/esp32c2/register/soc/spi_struct.h similarity index 99% rename from components/soc/esp32c2/include/soc/spi_struct.h rename to components/soc/esp32c2/register/soc/spi_struct.h index da359da84507..08920a09e6a8 100644 --- a/components/soc/esp32c2/include/soc/spi_struct.h +++ b/components/soc/esp32c2/register/soc/spi_struct.h @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" typedef volatile struct spi_dev_s{ union { @@ -58,7 +58,7 @@ typedef volatile struct spi_dev_s{ uint32_t clkcnt_n : 6; /*In the master mode it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1). Can be configured in CONF state.*/ uint32_t clkdiv_pre : 4; /*In the master mode it is pre-divider of spi_clk. Can be configured in CONF state.*/ uint32_t reserved22 : 9; /*reserved*/ - uint32_t clk_equ_sysclk : 1; /*In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system clock. Can be configured in CONF state.*/ + uint32_t clk_equ_sysclk : 1; /*In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system clock. Can be configured in CONF state.*/ }; uint32_t val; } clock; @@ -366,7 +366,7 @@ typedef volatile struct spi_dev_s{ uint32_t reserved_dc; union { struct { - uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on. Can be configured in CONF state.*/ + uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is always on. Can be configured in CONF state.*/ uint32_t clk_mode_13 : 1; /*{CPOL, CPHA},1: support spi clk mode 1 and 3, first edge output data B[0]/B[7]. 0: support spi clk mode 0 and 2, first edge output data B[1]/B[6].*/ uint32_t rsck_data_out : 1; /*It saves half a cycle when tsck is the same as rsck. 1: output data at rsck posedge 0: output data at tsck posedge */ uint32_t reserved4 : 4; /*reserved*/ diff --git a/components/soc/esp32c2/include/soc/syscon_reg.h b/components/soc/esp32c2/register/soc/syscon_reg.h similarity index 99% rename from components/soc/esp32c2/include/soc/syscon_reg.h rename to components/soc/esp32c2/register/soc/syscon_reg.h index 9c4f8b5e610a..fbbf7706bcbb 100644 --- a/components/soc/esp32c2/include/soc/syscon_reg.h +++ b/components/soc/esp32c2/register/soc/syscon_reg.h @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define SYSCON_SYSCLK_CONF_REG (DR_REG_SYSCON_BASE + 0x0) /* SYSCON_RST_TICK_CNT : R/W ;bitpos:[12] ;default: 1'b0 ; */ diff --git a/components/soc/esp32c2/include/soc/syscon_struct.h b/components/soc/esp32c2/register/soc/syscon_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/syscon_struct.h rename to components/soc/esp32c2/register/soc/syscon_struct.h diff --git a/components/soc/esp32c2/include/soc/system_reg.h b/components/soc/esp32c2/register/soc/system_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/system_reg.h rename to components/soc/esp32c2/register/soc/system_reg.h diff --git a/components/soc/esp32c2/include/soc/system_struct.h b/components/soc/esp32c2/register/soc/system_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/system_struct.h rename to components/soc/esp32c2/register/soc/system_struct.h diff --git a/components/soc/esp32c2/include/soc/systimer_reg.h b/components/soc/esp32c2/register/soc/systimer_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/systimer_reg.h rename to components/soc/esp32c2/register/soc/systimer_reg.h diff --git a/components/soc/esp32c2/include/soc/systimer_struct.h b/components/soc/esp32c2/register/soc/systimer_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/systimer_struct.h rename to components/soc/esp32c2/register/soc/systimer_struct.h diff --git a/components/soc/esp32c2/include/soc/timer_group_reg.h b/components/soc/esp32c2/register/soc/timer_group_reg.h similarity index 100% rename from components/soc/esp32c2/include/soc/timer_group_reg.h rename to components/soc/esp32c2/register/soc/timer_group_reg.h diff --git a/components/soc/esp32c2/include/soc/timer_group_struct.h b/components/soc/esp32c2/register/soc/timer_group_struct.h similarity index 100% rename from components/soc/esp32c2/include/soc/timer_group_struct.h rename to components/soc/esp32c2/register/soc/timer_group_struct.h diff --git a/components/soc/esp32c2/include/soc/uart_reg.h b/components/soc/esp32c2/register/soc/uart_reg.h similarity index 99% rename from components/soc/esp32c2/include/soc/uart_reg.h rename to components/soc/esp32c2/register/soc/uart_reg.h index 0f105fa0b2fb..70413882e779 100644 --- a/components/soc/esp32c2/include/soc/uart_reg.h +++ b/components/soc/esp32c2/register/soc/uart_reg.h @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0) /* UART_RXFIFO_RD_BYTE : RO ;bitpos:[7:0] ;default: 8'b0 ; */ @@ -92,7 +92,7 @@ NULL characters, after all data in Tx-FIFO are sent..*/ #define UART_SW_XOFF_INT_RAW_V 0x1 #define UART_SW_XOFF_INT_RAW_S 10 /* UART_SW_XON_INT_RAW : R/WTC/SS ;bitpos:[9] ;default: 1'b0 ; */ -/*description: This interrupt raw bit turns to high level when receiver recevies Xon char when +/*description: This interrupt raw bit turns to high level when receiver receives Xon char when uart_sw_flow_con_en is set to 1..*/ #define UART_SW_XON_INT_RAW (BIT(9)) #define UART_SW_XON_INT_RAW_M (BIT(9)) @@ -205,7 +205,7 @@ t to 1..*/ #define UART_TX_DONE_INT_ST_V 0x1 #define UART_TX_DONE_INT_ST_S 14 /* UART_TX_BRK_IDLE_DONE_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_en +/*description: This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_en a is set to 1..*/ #define UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) #define UART_TX_BRK_IDLE_DONE_INT_ST_M (BIT(13)) @@ -744,7 +744,7 @@ ansmitter's 11th bit to 0..*/ #define UART_IRDA_DPLX_V 0x1 #define UART_IRDA_DPLX_S 9 /* UART_TXD_BRK : R/W ;bitpos:[8] ;default: 1'b0 ; */ -/*description: Set this bit to enbale transmitter to send NULL when the process of sending dat +/*description: Set this bit to enable transmitter to send NULL when the process of sending dat a is done..*/ #define UART_TXD_BRK (BIT(8)) #define UART_TXD_BRK_M (BIT(8)) @@ -791,7 +791,7 @@ ware flow control..*/ #define UART_CONF1_REG(i) (REG_UART_BASE(i) + 0x24) /* UART_RX_TOUT_EN : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: This is the enble bit for uart receiver's timeout function..*/ +/*description: This is the enable bit for uart receiver's timeout function..*/ #define UART_RX_TOUT_EN (BIT(21)) #define UART_RX_TOUT_EN_M (BIT(21)) #define UART_RX_TOUT_EN_V 0x1 @@ -840,7 +840,7 @@ se. It is used in baud rate-detect process..*/ #define UART_HIGHPULSE_REG(i) (REG_UART_BASE(i) + 0x2C) /* UART_HIGHPULSE_MIN_CNT : RO ;bitpos:[11:0] ;default: 12'hfff ; */ -/*description: This register stores the value of the maxinum duration time for the high level +/*description: This register stores the value of the maximum duration time for the high level pulse. It is used in baud rate-detect process..*/ #define UART_HIGHPULSE_MIN_CNT 0x00000FFF #define UART_HIGHPULSE_MIN_CNT_M ((UART_HIGHPULSE_MIN_CNT_V)<<(UART_HIGHPULSE_MIN_CNT_S)) @@ -898,7 +898,7 @@ t process..*/ #define UART_SLEEP_CONF_REG(i) (REG_UART_BASE(i) + 0x38) /* UART_ACTIVE_THRESHOLD : R/W ;bitpos:[9:0] ;default: 10'hf0 ; */ /*description: The uart is activated from light sleeping mode when the input rxd edge changes m -ore times than this register value..*/ +or times than this register value..*/ #define UART_ACTIVE_THRESHOLD 0x000003FF #define UART_ACTIVE_THRESHOLD_M ((UART_ACTIVE_THRESHOLD_V)<<(UART_ACTIVE_THRESHOLD_S)) #define UART_ACTIVE_THRESHOLD_V 0x3FF @@ -951,8 +951,8 @@ of sending data is done. It is active when txd_brk is set to 1..*/ #define UART_TX_IDLE_NUM_V 0x3FF #define UART_TX_IDLE_NUM_S 10 /* UART_RX_IDLE_THRHD : R/W ;bitpos:[9:0] ;default: 10'h100 ; */ -/*description: It will produce frame end signal when receiver takes more time to receive one by -te data than this register value..*/ +/*description: It will produce frame end signal when receiver takes more time to receive one byte +data than this register value..*/ #define UART_RX_IDLE_THRHD 0x000003FF #define UART_RX_IDLE_THRHD_M ((UART_RX_IDLE_THRHD_V)<<(UART_RX_IDLE_THRHD_S)) #define UART_RX_IDLE_THRHD_V 0x3FF @@ -1066,7 +1066,7 @@ akes more time to receive one byte with rx_tout_en set to 1..*/ #define UART_RX_TOUT_THRHD_V 0x3FF #define UART_RX_TOUT_THRHD_S 16 /* UART_RX_FLOW_THRHD : R/W ;bitpos:[15:7] ;default: 9'h0 ; */ -/*description: This register is used to configure the maximum amount of data that can be receiv +/*description: This register is used to configure the maximum amount of data that can be receive ed when hardware flow control works..*/ #define UART_RX_FLOW_THRHD 0x000001FF #define UART_RX_FLOW_THRHD_M ((UART_RX_FLOW_THRHD_V)<<(UART_RX_FLOW_THRHD_S)) diff --git a/components/soc/esp32c2/include/soc/uart_struct.h b/components/soc/esp32c2/register/soc/uart_struct.h similarity index 98% rename from components/soc/esp32c2/include/soc/uart_struct.h rename to components/soc/esp32c2/register/soc/uart_struct.h index 64c4504e39de..8cc5bdbc8761 100644 --- a/components/soc/esp32c2/include/soc/uart_struct.h +++ b/components/soc/esp32c2/register/soc/uart_struct.h @@ -29,7 +29,7 @@ typedef volatile struct uart_dev_s { uint32_t cts_chg : 1; /*This interrupt raw bit turns to high level when receiver detects the edge change of CTSn signal.*/ uint32_t brk_det : 1; /*This interrupt raw bit turns to high level when receiver detects a 0 after the stop bit.*/ uint32_t rxfifo_tout : 1; /*This interrupt raw bit turns to high level when receiver takes more time than rx_tout_thrhd to receive a byte.*/ - uint32_t sw_xon : 1; /*This interrupt raw bit turns to high level when receiver recevies Xon char when uart_sw_flow_con_en is set to 1.*/ + uint32_t sw_xon : 1; /*This interrupt raw bit turns to high level when receiver receives Xon char when uart_sw_flow_con_en is set to 1.*/ uint32_t sw_xoff : 1; /*This interrupt raw bit turns to high level when receiver receives Xoff char when uart_sw_flow_con_en is set to 1.*/ uint32_t glitch_det : 1; /*This interrupt raw bit turns to high level when receiver detects a glitch in the middle of a start bit.*/ uint32_t tx_brk_done : 1; /*This interrupt raw bit turns to high level when transmitter completes sending NULL characters, after all data in Tx-FIFO are sent.*/ @@ -59,7 +59,7 @@ typedef volatile struct uart_dev_s { uint32_t sw_xoff : 1; /*This is the status bit for sw_xoff_int_raw when sw_xoff_int_ena is set to 1.*/ uint32_t glitch_det : 1; /*This is the status bit for glitch_det_int_raw when glitch_det_int_ena is set to 1.*/ uint32_t tx_brk_done : 1; /*This is the status bit for tx_brk_done_int_raw when tx_brk_done_int_ena is set to 1.*/ - uint32_t tx_brk_idle_done : 1; /*This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena is set to 1.*/ + uint32_t tx_brk_idle_done : 1; /*This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena is set to 1.*/ uint32_t tx_done : 1; /*This is the status bit for tx_done_int_raw when tx_done_int_ena is set to 1.*/ uint32_t rs485_parity_err : 1; /*This is the status bit for rs485_parity_err_int_raw when rs485_parity_int_ena is set to 1.*/ uint32_t rs485_frm_err : 1; /*This is the status bit for rs485_frm_err_int_raw when rs485_fm_err_int_ena is set to 1.*/ @@ -162,7 +162,7 @@ typedef volatile struct uart_dev_s { uint32_t stop_bit_num : 2; /*This register is used to set the length of stop bit.*/ uint32_t sw_rts : 1; /*This register is used to configure the software rts signal which is used in software flow control.*/ uint32_t sw_dtr : 1; /*This register is used to configure the software dtr signal which is used in software flow control.*/ - uint32_t txd_brk : 1; /*Set this bit to enbale transmitter to send NULL when the process of sending data is done.*/ + uint32_t txd_brk : 1; /*Set this bit to enable transmitter to send NULL when the process of sending data is done.*/ uint32_t irda_dplx : 1; /*Set this bit to enable IrDA loopback mode.*/ uint32_t irda_tx_en : 1; /*This is the start enable bit for IrDA transmitter.*/ uint32_t irda_wctl : 1; /*1'h1: The IrDA transmitter's 11th bit is the same as 10th bit. 1'h0: Set IrDA transmitter's 11th bit to 0.*/ @@ -194,7 +194,7 @@ typedef volatile struct uart_dev_s { uint32_t dis_rx_dat_ovf : 1; /*Disable UART Rx data overflow detect. */ uint32_t rx_tout_flow_dis : 1; /*Set this bit to stop accumulating idle_cnt when hardware flow control works.*/ uint32_t rx_flow_en : 1; /*This is the flow enable bit for UART receiver.*/ - uint32_t rx_tout_en : 1; /*This is the enble bit for uart receiver's timeout function.*/ + uint32_t rx_tout_en : 1; /*This is the enable bit for uart receiver's timeout function.*/ uint32_t reserved22 : 10; }; uint32_t val; @@ -208,7 +208,7 @@ typedef volatile struct uart_dev_s { } lowpulse; union { struct { - uint32_t min_cnt : 12; /*This register stores the value of the maxinum duration time for the high level pulse. It is used in baud rate-detect process.*/ + uint32_t min_cnt : 12; /*This register stores the value of the maximum duration time for the high level pulse. It is used in baud rate-detect process.*/ uint32_t reserved12 : 20; /*Reserved*/ }; uint32_t val; diff --git a/components/soc/esp32c2/include/soc/xts_aes_reg.h b/components/soc/esp32c2/register/soc/xts_aes_reg.h similarity index 98% rename from components/soc/esp32c2/include/soc/xts_aes_reg.h rename to components/soc/esp32c2/register/soc/xts_aes_reg.h index 9845d0b05829..6a6e64539c5a 100644 --- a/components/soc/esp32c2/include/soc/xts_aes_reg.h +++ b/components/soc/esp32c2/register/soc/xts_aes_reg.h @@ -119,7 +119,7 @@ extern "C" { #define XTS_AES_DATE_V 0x3FFFFFFFU #define XTS_AES_DATE_S 0 -/* For backward compatability with the older register names */ +/* For backward compatibility with the older register names */ #define AES_XTS_PLAIN_BASE XTS_AES_PLAIN_MEM #define AES_XTS_SIZE_REG XTS_AES_LINESIZE_REG #define AES_XTS_DESTINATION_REG XTS_AES_DESTINATION_REG diff --git a/components/soc/esp32c2/spi_periph.c b/components/soc/esp32c2/spi_periph.c index 5ae7aed529fc..b270a925236d 100644 --- a/components/soc/esp32c2/spi_periph.c +++ b/components/soc/esp32c2/spi_periph.c @@ -33,7 +33,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = -1, .irq = -1, .irq_dma = -1, - .module = -1, .hw = NULL, .func = -1, }, { @@ -57,7 +56,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, .irq = ETS_SPI2_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_SPI2_MODULE, .hw = &GPSPI2, .func = SPI2_FUNC_NUM, } diff --git a/components/soc/esp32c3/i2s_periph.c b/components/soc/esp32c3/i2s_periph.c index ec14aa72a26d..dfb1ba6df82f 100644 --- a/components/soc/esp32c3/i2s_periph.c +++ b/components/soc/esp32c3/i2s_periph.c @@ -29,7 +29,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_out_sigs[1] = I2SO_SD1_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, - .irq = ETS_I2S1_INTR_SOURCE, - .module = PERIPH_I2S1_MODULE, + .irq = ETS_I2S0_INTR_SOURCE, } }; diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 8ef4c16e6950..fd1b0f21b441 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -527,6 +527,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 6 diff --git a/components/soc/esp32c3/include/soc/dport_access.h b/components/soc/esp32c3/include/soc/dport_access.h index 5a847ca48423..e499a791bdd6 100644 --- a/components/soc/esp32c3/include/soc/dport_access.h +++ b/components/soc/esp32c3/include/soc/dport_access.h @@ -8,8 +8,7 @@ #define _DPORT_ACCESS_H_ #include -#include "soc.h" -#include "uart_reg.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32c3/include/soc/interrupt_reg.h b/components/soc/esp32c3/include/soc/interrupt_reg.h index 749a2e921671..d02c2d5c20ce 100644 --- a/components/soc/esp32c3/include/soc/interrupt_reg.h +++ b/components/soc/esp32c3/include/soc/interrupt_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "interrupt_core0_reg.h" +#include "soc/interrupt_core0_reg.h" #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG INTERRUPT_CORE0_CPU_INT_THRESH_REG #define INTERRUPT_PRIO_REG(n) (INTERRUPT_CORE0_CPU_INT_PRI_0_REG + (n)*4) diff --git a/components/soc/esp32c3/include/soc/interrupts.h b/components/soc/esp32c3/include/soc/interrupts.h index f332295c4f10..661ec7fc8210 100644 --- a/components/soc/esp32c3/include/soc/interrupts.h +++ b/components/soc/esp32c3/include/soc/interrupts.h @@ -35,7 +35,7 @@ typedef enum { ETS_GPIO_NMI_SOURCE, /**< interrupt of GPIO, NMI*/ ETS_SPI1_INTR_SOURCE, /**< interrupt of SPI1, level, SPI1 is for flash read/write, do not use this*/ ETS_SPI2_INTR_SOURCE, /**< interrupt of SPI2, level*/ - ETS_I2S1_INTR_SOURCE, /**< interrupt of I2S1, level*/ + ETS_I2S0_INTR_SOURCE, /**< interrupt of I2S0, level*/ ETS_UART0_INTR_SOURCE, /**< interrupt of UART0, level*/ ETS_UART1_INTR_SOURCE, /**< interrupt of UART1, level*/ ETS_LEDC_INTR_SOURCE, /**< interrupt of LED PWM, level*/ @@ -51,7 +51,7 @@ typedef enum { ETS_TG0_WDT_LEVEL_INTR_SOURCE, /**< interrupt of TIMER_GROUP0, WATCH DOG, level*/ ETS_TG1_T0_LEVEL_INTR_SOURCE, /**< interrupt of TIMER_GROUP1, TIMER0, level*/ ETS_TG1_WDT_LEVEL_INTR_SOURCE, /**< interrupt of TIMER_GROUP1, WATCHDOG, level*/ - ETS_CACHE_IA_INTR_SOURCE, /**< interrupt of Cache Invalied Access, LEVEL*/ + ETS_CACHE_IA_INTR_SOURCE, /**< interrupt of Cache Invalid Access, LEVEL*/ ETS_SYSTIMER_TARGET0_INTR_SOURCE, /**< interrupt of system timer 0 */ ETS_SYSTIMER_TARGET1_INTR_SOURCE, /**< interrupt of system timer 1 */ ETS_SYSTIMER_TARGET2_INTR_SOURCE, /**< interrupt of system timer 2 */ diff --git a/components/soc/esp32c3/include/soc/periph_defs.h b/components/soc/esp32c3/include/soc/periph_defs.h index 063e4f950617..708ec23a835e 100644 --- a/components/soc/esp32c3/include/soc/periph_defs.h +++ b/components/soc/esp32c3/include/soc/periph_defs.h @@ -18,7 +18,7 @@ typedef enum { PERIPH_UART1_MODULE, PERIPH_USB_DEVICE_MODULE, PERIPH_I2C0_MODULE, - PERIPH_I2S1_MODULE, + PERIPH_I2S0_MODULE, PERIPH_TIMG0_MODULE, PERIPH_TIMG1_MODULE, PERIPH_UHCI0_MODULE, diff --git a/components/soc/esp32c3/include/soc/soc.h b/components/soc/esp32c3/include/soc/soc.h index d661c4eb126d..1b47dd70fb1b 100644 --- a/components/soc/esp32c3/include/soc/soc.h +++ b/components/soc/esp32c3/include/soc/soc.h @@ -12,7 +12,7 @@ #endif #include "esp_bit_defs.h" -#include "reg_base.h" +#include "soc/reg_base.h" #define PRO_CPU_NUM (0) diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 74c25ccd4d07..ab7f7b9317f7 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -223,6 +223,7 @@ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_APB_CLOCK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (6) #define SOC_LEDC_TIMER_BIT_WIDTH (14) #define SOC_LEDC_SUPPORT_FADE_STOP (1) diff --git a/components/soc/esp32c3/interrupts.c b/components/soc/esp32c3/interrupts.c index 27775f61881a..2a0d74de6ac6 100644 --- a/components/soc/esp32c3/interrupts.c +++ b/components/soc/esp32c3/interrupts.c @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/interrupts.h" @@ -35,7 +27,7 @@ const char *const esp_isr_names[] = { [17] = "GPIO_NMI", [18] = "SPI1", [19] = "SPI2", - [20] = "I2S1", + [20] = "I2S0", [21] = "UART0", [22] = "UART1", [23] = "LEDC", diff --git a/components/soc/esp32c3/include/soc/apb_ctrl_reg.h b/components/soc/esp32c3/register/soc/apb_ctrl_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/apb_ctrl_reg.h rename to components/soc/esp32c3/register/soc/apb_ctrl_reg.h index cb1966505e8d..f7fb4f1ba97b 100644 --- a/components/soc/esp32c3/include/soc/apb_ctrl_reg.h +++ b/components/soc/esp32c3/register/soc/apb_ctrl_reg.h @@ -11,7 +11,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define APB_CTRL_SYSCLK_CONF_REG (DR_REG_APB_CTRL_BASE + 0x000) /* APB_CTRL_RST_TICK_CNT : R/W ;bitpos:[12] ;default: 1'b0 ; */ /*description: */ diff --git a/components/soc/esp32c3/include/soc/apb_ctrl_struct.h b/components/soc/esp32c3/register/soc/apb_ctrl_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/apb_ctrl_struct.h rename to components/soc/esp32c3/register/soc/apb_ctrl_struct.h diff --git a/components/soc/esp32c3/include/soc/apb_saradc_reg.h b/components/soc/esp32c3/register/soc/apb_saradc_reg.h similarity index 97% rename from components/soc/esp32c3/include/soc/apb_saradc_reg.h rename to components/soc/esp32c3/register/soc/apb_saradc_reg.h index 69785ca84da6..87deea2d3e97 100644 --- a/components/soc/esp32c3/include/soc/apb_saradc_reg.h +++ b/components/soc/esp32c3/register/soc/apb_saradc_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_APB_SARADC_REG_H_ #define _SOC_APB_SARADC_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define APB_SARADC_CTRL_REG (DR_REG_APB_SARADC_BASE + 0x000) /* APB_SARADC_WAIT_ARB_CYCLE : R/W ;bitpos:[31:30] ;default: 2'd1 ; */ /*description: wait arbit signal stable after sar_done*/ diff --git a/components/soc/esp32c3/include/soc/apb_saradc_struct.h b/components/soc/esp32c3/register/soc/apb_saradc_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/apb_saradc_struct.h rename to components/soc/esp32c3/register/soc/apb_saradc_struct.h diff --git a/components/soc/esp32c3/include/soc/assist_debug_reg.h b/components/soc/esp32c3/register/soc/assist_debug_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/assist_debug_reg.h rename to components/soc/esp32c3/register/soc/assist_debug_reg.h index 2b13d1f5f416..615964bd7400 100644 --- a/components/soc/esp32c3/include/soc/assist_debug_reg.h +++ b/components/soc/esp32c3/register/soc/assist_debug_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_ASSIST_DEBUG_REG_H_ #define _SOC_ASSIST_DEBUG_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define ASSIST_DEBUG_CORE_0_INTR_ENA_REG (DR_REG_ASSIST_DEBUG_BASE + 0x000) /* ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ /*description: */ diff --git a/components/soc/esp32c3/include/soc/efuse_reg.h b/components/soc/esp32c3/register/soc/efuse_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/efuse_reg.h rename to components/soc/esp32c3/register/soc/efuse_reg.h index 4d6781c976b6..39db7b9abb46 100644 --- a/components/soc/esp32c3/include/soc/efuse_reg.h +++ b/components/soc/esp32c3/register/soc/efuse_reg.h @@ -7,7 +7,7 @@ #include #include "soc/soc.h" -#include "efuse_defs.h" +#include "soc/efuse_defs.h" #ifdef __cplusplus extern "C" { #endif @@ -2376,7 +2376,7 @@ extern "C" { #define EFUSE_CLK_EN_S 16 /** EFUSE_CONF_REG register - * eFuse operation mode configuraiton register; + * eFuse operation mode configuration register; */ #define EFUSE_CONF_REG (DR_REG_EFUSE_BASE + 0x1cc) /** EFUSE_OP_CODE : R/W; bitpos: [15:0]; default: 0; diff --git a/components/soc/esp32c3/include/soc/efuse_struct.h b/components/soc/esp32c3/register/soc/efuse_struct.h similarity index 99% rename from components/soc/esp32c3/include/soc/efuse_struct.h rename to components/soc/esp32c3/register/soc/efuse_struct.h index 99f8c39ec576..f12563cebd0e 100644 --- a/components/soc/esp32c3/include/soc/efuse_struct.h +++ b/components/soc/esp32c3/register/soc/efuse_struct.h @@ -2015,7 +2015,7 @@ typedef union { } efuse_clk_reg_t; /** Type of conf register - * eFuse operation mode configuraiton register; + * eFuse operation mode configuration register; */ typedef union { struct { diff --git a/components/soc/esp32c3/include/soc/extmem_reg.h b/components/soc/esp32c3/register/soc/extmem_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/extmem_reg.h rename to components/soc/esp32c3/register/soc/extmem_reg.h index 71ab60f6400f..7a94ea7e66ba 100644 --- a/components/soc/esp32c3/include/soc/extmem_reg.h +++ b/components/soc/esp32c3/register/soc/extmem_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_EXTMEM_REG_H_ #define _SOC_EXTMEM_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define EXTMEM_ICACHE_CTRL_REG (DR_REG_EXTMEM_BASE + 0x000) /* EXTMEM_ICACHE_ENABLE : R/W ;bitpos:[0] ;default: 1'b0 ; */ /*description: The bit is used to activate the data cache. 0: disable 1: enable*/ diff --git a/components/soc/esp32c3/include/soc/gdma_reg.h b/components/soc/esp32c3/register/soc/gdma_reg.h similarity index 100% rename from components/soc/esp32c3/include/soc/gdma_reg.h rename to components/soc/esp32c3/register/soc/gdma_reg.h diff --git a/components/soc/esp32c3/include/soc/gdma_struct.h b/components/soc/esp32c3/register/soc/gdma_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/gdma_struct.h rename to components/soc/esp32c3/register/soc/gdma_struct.h diff --git a/components/soc/esp32c3/include/soc/gpio_reg.h b/components/soc/esp32c3/register/soc/gpio_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/gpio_reg.h rename to components/soc/esp32c3/register/soc/gpio_reg.h index a674277f9940..b92e195e36de 100644 --- a/components/soc/esp32c3/include/soc/gpio_reg.h +++ b/components/soc/esp32c3/register/soc/gpio_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_GPIO_REG_H_ #define _SOC_GPIO_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define GPIO_PIN_CONFIG_MSB 12 #define GPIO_PIN_CONFIG_LSB 11 #define GPIO_PIN_CONFIG_MASK 0x00001800 diff --git a/components/soc/esp32c3/include/soc/gpio_sd_reg.h b/components/soc/esp32c3/register/soc/gpio_sd_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/gpio_sd_reg.h rename to components/soc/esp32c3/register/soc/gpio_sd_reg.h index 3c72df5d4040..57d66a44c0c2 100644 --- a/components/soc/esp32c3/include/soc/gpio_sd_reg.h +++ b/components/soc/esp32c3/register/soc/gpio_sd_reg.h @@ -6,7 +6,7 @@ #pragma once -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32c3/include/soc/gpio_sd_struct.h b/components/soc/esp32c3/register/soc/gpio_sd_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/gpio_sd_struct.h rename to components/soc/esp32c3/register/soc/gpio_sd_struct.h diff --git a/components/soc/esp32c3/include/soc/gpio_struct.h b/components/soc/esp32c3/register/soc/gpio_struct.h similarity index 94% rename from components/soc/esp32c3/include/soc/gpio_struct.h rename to components/soc/esp32c3/register/soc/gpio_struct.h index 45f5e55412c7..1fbb0779b477 100644 --- a/components/soc/esp32c3/include/soc/gpio_struct.h +++ b/components/soc/esp32c3/register/soc/gpio_struct.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_GPIO_STRUCT_H_ #define _SOC_GPIO_STRUCT_H_ #include diff --git a/components/soc/esp32c3/include/soc/i2c_reg.h b/components/soc/esp32c3/register/soc/i2c_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/i2c_reg.h rename to components/soc/esp32c3/register/soc/i2c_reg.h index 6a45d008276d..03ec35dad0f7 100644 --- a/components/soc/esp32c3/include/soc/i2c_reg.h +++ b/components/soc/esp32c3/register/soc/i2c_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_I2C_REG_H_ #define _SOC_I2C_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define I2C_SCL_LOW_PERIOD_REG(i) (REG_I2C_BASE(i) + 0x0) /* I2C_SCL_LOW_PERIOD : R/W ;bitpos:[8:0] ;default: 9'b0 ; */ diff --git a/components/soc/esp32c3/include/soc/i2c_struct.h b/components/soc/esp32c3/register/soc/i2c_struct.h similarity index 99% rename from components/soc/esp32c3/include/soc/i2c_struct.h rename to components/soc/esp32c3/register/soc/i2c_struct.h index 1009fedd6e07..eb32d5a9cf98 100644 --- a/components/soc/esp32c3/include/soc/i2c_struct.h +++ b/components/soc/esp32c3/register/soc/i2c_struct.h @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" typedef volatile struct i2c_dev_s { union { diff --git a/components/soc/esp32c3/include/soc/i2s_reg.h b/components/soc/esp32c3/register/soc/i2s_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/i2s_reg.h rename to components/soc/esp32c3/register/soc/i2s_reg.h index 2b3ed91f6106..7412fe1a13d1 100644 --- a/components/soc/esp32c3/include/soc/i2s_reg.h +++ b/components/soc/esp32c3/register/soc/i2s_reg.h @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define I2S_INT_RAW_REG(i) (REG_I2S_BASE(i) + 0x000c) /* I2S_TX_HUNG_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ /*description: The raw interrupt status bit for the i2s_tx_hung_int interrupt*/ @@ -280,7 +280,7 @@ extern "C" { #define I2S_TX_LEFT_ALIGN_S 15 /* I2S_TX_STOP_EN : R/W ;bitpos:[13] ;default: 1'h1 ; */ /*description: Set this bit to stop disable output BCK signal and WS signal - when tx FIFO is emtpy*/ + when tx FIFO is empty*/ #define I2S_TX_STOP_EN (BIT(13)) #define I2S_TX_STOP_EN_M (BIT(13)) #define I2S_TX_STOP_EN_V 0x1 diff --git a/components/soc/esp32c3/include/soc/i2s_struct.h b/components/soc/esp32c3/register/soc/i2s_struct.h similarity index 99% rename from components/soc/esp32c3/include/soc/i2s_struct.h rename to components/soc/esp32c3/register/soc/i2s_struct.h index e0c10e91e977..29093ad2d97e 100644 --- a/components/soc/esp32c3/include/soc/i2s_struct.h +++ b/components/soc/esp32c3/register/soc/i2s_struct.h @@ -95,7 +95,7 @@ typedef volatile struct i2s_dev_s { uint32_t tx_mono_fst_vld: 1; /*1: The first channel data value is valid in I2S TX mono mode. 0: The second channel data value is valid in I2S TX mono mode.*/ uint32_t tx_pcm_conf: 2; /*I2S TX compress/decompress configuration bit. & 0 (atol): A-Law decompress 1 (ltoa) : A-Law compress 2 (utol) : u-Law decompress 3 (ltou) : u-Law compress. &*/ uint32_t tx_pcm_bypass: 1; /*Set this bit to bypass Compress/Decompress module for transmitted data.*/ - uint32_t tx_stop_en: 1; /*Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy*/ + uint32_t tx_stop_en: 1; /*Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty*/ uint32_t reserved14: 1; uint32_t tx_left_align: 1; /*1: I2S TX left alignment mode. 0: I2S TX right alignment mode.*/ uint32_t tx_24_fill_en: 1; /*1: Sent 32 bits in 24 channel bits mode. 0: Sent 24 bits in 24 channel bits mode*/ diff --git a/components/soc/esp32c3/include/soc/interrupt_core0_reg.h b/components/soc/esp32c3/register/soc/interrupt_core0_reg.h similarity index 97% rename from components/soc/esp32c3/include/soc/interrupt_core0_reg.h rename to components/soc/esp32c3/register/soc/interrupt_core0_reg.h index f606cdafcafb..5f7c63c52019 100644 --- a/components/soc/esp32c3/include/soc/interrupt_core0_reg.h +++ b/components/soc/esp32c3/register/soc/interrupt_core0_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_INTERRUPT_CORE0_REG_H_ #define _SOC_INTERRUPT_CORE0_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define DR_REG_INTERRUPT_CORE0_BASE DR_REG_INTERRUPT_BASE @@ -182,13 +174,13 @@ extern "C" { #define INTERRUPT_CORE0_SPI_INTR_2_MAP_V 0x1F #define INTERRUPT_CORE0_SPI_INTR_2_MAP_S 0 -#define INTERRUPT_CORE0_I2S1_INT_MAP_REG (DR_REG_INTERRUPT_CORE0_BASE + 0x050) -/* INTERRUPT_CORE0_I2S1_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd0 ; */ +#define INTERRUPT_CORE0_I2S_INT_MAP_REG (DR_REG_INTERRUPT_CORE0_BASE + 0x050) +/* INTERRUPT_CORE0_I2S_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd0 ; */ /*description: */ -#define INTERRUPT_CORE0_I2S1_INT_MAP 0x0000001F -#define INTERRUPT_CORE0_I2S1_INT_MAP_M ((INTERRUPT_CORE0_I2S1_INT_MAP_V)<<(INTERRUPT_CORE0_I2S1_INT_MAP_S)) -#define INTERRUPT_CORE0_I2S1_INT_MAP_V 0x1F -#define INTERRUPT_CORE0_I2S1_INT_MAP_S 0 +#define INTERRUPT_CORE0_I2S_INT_MAP 0x0000001F +#define INTERRUPT_CORE0_I2S_INT_MAP_M ((INTERRUPT_CORE0_I2S_INT_MAP_V)<<(INTERRUPT_CORE0_I2S_INT_MAP_S)) +#define INTERRUPT_CORE0_I2S_INT_MAP_V 0x1F +#define INTERRUPT_CORE0_I2S_INT_MAP_S 0 #define INTERRUPT_CORE0_UART_INTR_MAP_REG (DR_REG_INTERRUPT_CORE0_BASE + 0x054) /* INTERRUPT_CORE0_UART_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd0 ; */ diff --git a/components/soc/esp32c3/include/soc/io_mux_reg.h b/components/soc/esp32c3/register/soc/io_mux_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/io_mux_reg.h rename to components/soc/esp32c3/register/soc/io_mux_reg.h index f5abe8ee5e81..a85a3434dd04 100644 --- a/components/soc/esp32c3/include/soc/io_mux_reg.h +++ b/components/soc/esp32c3/register/soc/io_mux_reg.h @@ -6,7 +6,7 @@ #ifndef _SOC_IO_MUX_REG_H_ #define _SOC_IO_MUX_REG_H_ -#include "soc.h" +#include "soc/soc.h" /* The following are the bit fields for PERIPHS_IO_MUX_x_U registers */ /* Output enable in sleep mode */ diff --git a/components/soc/esp32c3/include/soc/ledc_reg.h b/components/soc/esp32c3/register/soc/ledc_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/ledc_reg.h rename to components/soc/esp32c3/register/soc/ledc_reg.h index 0cc9334130b2..c956e9e7dadc 100644 --- a/components/soc/esp32c3/include/soc/ledc_reg.h +++ b/components/soc/esp32c3/register/soc/ledc_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_LEDC_REG_H_ #define _SOC_LEDC_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define LEDC_LSCH0_CONF0_REG (DR_REG_LEDC_BASE + 0x0000) /* LEDC_OVF_CNT_RESET_LSCH0 : WO ;bitpos:[16] ;default: 1'b0 ; */ /*description: */ diff --git a/components/soc/esp32c3/include/soc/ledc_struct.h b/components/soc/esp32c3/register/soc/ledc_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/ledc_struct.h rename to components/soc/esp32c3/register/soc/ledc_struct.h diff --git a/components/soc/esp32c3/include/soc/nrx_reg.h b/components/soc/esp32c3/register/soc/nrx_reg.h similarity index 67% rename from components/soc/esp32c3/include/soc/nrx_reg.h rename to components/soc/esp32c3/register/soc/nrx_reg.h index d80cb2a1785b..16e6e148497e 100644 --- a/components/soc/esp32c3/include/soc/nrx_reg.h +++ b/components/soc/esp32c3/register/soc/nrx_reg.h @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/soc/esp32c3/include/soc/reg_base.h b/components/soc/esp32c3/register/soc/reg_base.h similarity index 97% rename from components/soc/esp32c3/include/soc/reg_base.h rename to components/soc/esp32c3/register/soc/reg_base.h index 4ec808f0ab97..cf38bd9dbda9 100644 --- a/components/soc/esp32c3/include/soc/reg_base.h +++ b/components/soc/esp32c3/register/soc/reg_base.h @@ -46,5 +46,5 @@ #define DR_REG_USB_SERIAL_JTAG_BASE 0x60043000 #define DR_REG_XTS_AES_BASE 0x600CC000 -/* For backward compatability with the older register names */ +/* For backward compatibility with the older register names */ #define DR_REG_AES_XTS_BASE DR_REG_XTS_AES_BASE diff --git a/components/soc/esp32c3/include/soc/rmt_reg.h b/components/soc/esp32c3/register/soc/rmt_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/rmt_reg.h rename to components/soc/esp32c3/register/soc/rmt_reg.h index 106fc786495b..1ac39c2af352 100644 --- a/components/soc/esp32c3/include/soc/rmt_reg.h +++ b/components/soc/esp32c3/register/soc/rmt_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32c3/include/soc/rmt_struct.h b/components/soc/esp32c3/register/soc/rmt_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/rmt_struct.h rename to components/soc/esp32c3/register/soc/rmt_struct.h diff --git a/components/soc/esp32c3/include/soc/rtc_cntl_reg.h b/components/soc/esp32c3/register/soc/rtc_cntl_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/rtc_cntl_reg.h rename to components/soc/esp32c3/register/soc/rtc_cntl_reg.h index 433ca196b3c7..e67f6ed93d8a 100644 --- a/components/soc/esp32c3/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32c3/register/soc/rtc_cntl_reg.h @@ -9,7 +9,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define RTC_CNTL_TIME0_REG RTC_CNTL_TIME_LOW0_REG #define RTC_CNTL_TIME1_REG RTC_CNTL_TIME_HIGH0_REG @@ -567,7 +567,7 @@ extern "C" { #define RTC_CNTL_BBPLL_CAL_INT_ENA_V 0x1 #define RTC_CNTL_BBPLL_CAL_INT_ENA_S 20 /* RTC_CNTL_GLITCH_DET_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ -/*description: enbale gitch det interrupt*/ +/*description: enable gitch det interrupt*/ #define RTC_CNTL_GLITCH_DET_INT_ENA (BIT(19)) #define RTC_CNTL_GLITCH_DET_INT_ENA_M (BIT(19)) #define RTC_CNTL_GLITCH_DET_INT_ENA_V 0x1 @@ -1712,7 +1712,7 @@ extern "C" { #define RTC_CNTL_SWD_AUTO_FEED_EN_V 0x1 #define RTC_CNTL_SWD_AUTO_FEED_EN_S 31 /* RTC_CNTL_SWD_DISABLE : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: disabel SWD*/ +/*description: disable SWD*/ #define RTC_CNTL_SWD_DISABLE (BIT(30)) #define RTC_CNTL_SWD_DISABLE_M (BIT(30)) #define RTC_CNTL_SWD_DISABLE_V 0x1 @@ -2138,7 +2138,7 @@ extern "C" { #define RTC_CNTL_XTAL32K_RESTART_WAIT_V 0xFFFF #define RTC_CNTL_XTAL32K_RESTART_WAIT_S 4 /* RTC_CNTL_XTAL32K_RETURN_WAIT : R/W ;bitpos:[3:0] ;default: 4'h0 ; */ -/*description: cycles to wait to return noral xtal 32k*/ +/*description: cycles to wait to return normal xtal 32k*/ #define RTC_CNTL_XTAL32K_RETURN_WAIT 0x0000000F #define RTC_CNTL_XTAL32K_RETURN_WAIT_M ((RTC_CNTL_XTAL32K_RETURN_WAIT_V)<<(RTC_CNTL_XTAL32K_RETURN_WAIT_S)) #define RTC_CNTL_XTAL32K_RETURN_WAIT_V 0xF @@ -2192,7 +2192,7 @@ extern "C" { #define RTC_CNTL_BBPLL_CAL_INT_ENA_W1TS_V 0x1 #define RTC_CNTL_BBPLL_CAL_INT_ENA_W1TS_S 20 /* RTC_CNTL_GLITCH_DET_INT_ENA_W1TS : WO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: enbale gitch det interrupt*/ +/*description: enable gitch det interrupt*/ #define RTC_CNTL_GLITCH_DET_INT_ENA_W1TS (BIT(19)) #define RTC_CNTL_GLITCH_DET_INT_ENA_W1TS_M (BIT(19)) #define RTC_CNTL_GLITCH_DET_INT_ENA_W1TS_V 0x1 @@ -2248,7 +2248,7 @@ extern "C" { #define RTC_CNTL_BBPLL_CAL_INT_ENA_W1TC_V 0x1 #define RTC_CNTL_BBPLL_CAL_INT_ENA_W1TC_S 20 /* RTC_CNTL_GLITCH_DET_INT_ENA_W1TC : WO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: enbale gitch det interrupt*/ +/*description: enable gitch det interrupt*/ #define RTC_CNTL_GLITCH_DET_INT_ENA_W1TC (BIT(19)) #define RTC_CNTL_GLITCH_DET_INT_ENA_W1TC_M (BIT(19)) #define RTC_CNTL_GLITCH_DET_INT_ENA_W1TC_V 0x1 diff --git a/components/soc/esp32c3/include/soc/rtc_cntl_struct.h b/components/soc/esp32c3/register/soc/rtc_cntl_struct.h similarity index 99% rename from components/soc/esp32c3/include/soc/rtc_cntl_struct.h rename to components/soc/esp32c3/register/soc/rtc_cntl_struct.h index 8b6bd3ad5090..5c57701f695c 100644 --- a/components/soc/esp32c3/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32c3/register/soc/rtc_cntl_struct.h @@ -195,7 +195,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t rtc_swd: 1; /*enable super watch dog interrupt*/ uint32_t rtc_xtal32k_dead: 1; /*enable xtal32k_dead interrupt*/ uint32_t reserved17: 2; /*enable touch timeout interrupt*/ - uint32_t rtc_glitch_det: 1; /*enbale gitch det interrupt*/ + uint32_t rtc_glitch_det: 1; /*enable gitch det interrupt*/ uint32_t rtc_bbpll_cal: 1; uint32_t reserved21: 11; }; @@ -498,7 +498,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t swd_signal_width:10; /*adjust signal width send to swd*/ uint32_t swd_rst_flag_clr: 1; /*reset swd reset flag*/ uint32_t swd_feed: 1; /*Sw feed swd*/ - uint32_t swd_disable: 1; /*disabel SWD*/ + uint32_t swd_disable: 1; /*disable SWD*/ uint32_t swd_auto_feed_en: 1; /*automatically feed swd when int comes*/ }; uint32_t val; @@ -591,7 +591,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t xtal32k_clk_factor; /*xtal 32k watch dog backup clock factor*/ union { struct { - uint32_t xtal32k_return_wait: 4; /*cycles to wait to return noral xtal 32k*/ + uint32_t xtal32k_return_wait: 4; /*cycles to wait to return normal xtal 32k*/ uint32_t xtal32k_restart_wait:16; /*cycles to wait to repower on xtal 32k*/ uint32_t xtal32k_wdt_timeout: 8; /*If no clock detected for this amount of time*/ uint32_t xtal32k_stable_thres: 4; /*if restarted xtal32k period is smaller than this*/ @@ -647,7 +647,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t rtc_swd_w1ts: 1; /*enable super watch dog interrupt*/ uint32_t rtc_xtal32k_dead_w1ts: 1; /*enable xtal32k_dead interrupt*/ uint32_t reserved17: 2; - uint32_t rtc_glitch_det_w1ts: 1; /*enbale gitch det interrupt*/ + uint32_t rtc_glitch_det_w1ts: 1; /*enable gitch det interrupt*/ uint32_t rtc_bbpll_cal_w1ts: 1; uint32_t reserved21: 11; }; @@ -666,7 +666,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t rtc_swd_w1tc: 1; /*enable super watch dog interrupt*/ uint32_t rtc_xtal32k_dead_w1tc: 1; /*enable xtal32k_dead interrupt*/ uint32_t reserved17: 2; - uint32_t rtc_glitch_det_w1tc: 1; /*enbale gitch det interrupt*/ + uint32_t rtc_glitch_det_w1tc: 1; /*enable gitch det interrupt*/ uint32_t rtc_bbpll_cal_w1tc: 1; uint32_t reserved21: 11; }; diff --git a/components/soc/esp32c3/include/soc/rtc_i2c_reg.h b/components/soc/esp32c3/register/soc/rtc_i2c_reg.h similarity index 97% rename from components/soc/esp32c3/include/soc/rtc_i2c_reg.h rename to components/soc/esp32c3/register/soc/rtc_i2c_reg.h index 52bdefc0e56e..eba7d42df633 100644 --- a/components/soc/esp32c3/include/soc/rtc_i2c_reg.h +++ b/components/soc/esp32c3/register/soc/rtc_i2c_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_RTC_I2C_REG_H_ #define _SOC_RTC_I2C_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define RTC_I2C_SCL_LOW_PERIOD_REG (DR_REG_RTC_I2C_BASE + 0x0000) /* RTC_I2C_SCL_LOW_PERIOD : R/W ;bitpos:[19:0] ;default: 20'h100 ; */ /*description: time period that scl = 0*/ diff --git a/components/soc/esp32c3/include/soc/rtc_i2c_struct.h b/components/soc/esp32c3/register/soc/rtc_i2c_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/rtc_i2c_struct.h rename to components/soc/esp32c3/register/soc/rtc_i2c_struct.h diff --git a/components/soc/esp32c3/include/soc/sensitive_reg.h b/components/soc/esp32c3/register/soc/sensitive_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/sensitive_reg.h rename to components/soc/esp32c3/register/soc/sensitive_reg.h index e1ce7d93ef7e..089d9c4aa4af 100644 --- a/components/soc/esp32c3/include/soc/sensitive_reg.h +++ b/components/soc/esp32c3/register/soc/sensitive_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SENSITIVE_REG_H_ #define _SOC_SENSITIVE_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define SENSITIVE_ROM_TABLE_LOCK_REG (DR_REG_SENSITIVE_BASE + 0x000) /* SENSITIVE_ROM_TABLE_LOCK : R/W ;bitpos:[0] ;default: 1'b0 ; */ /*description: */ @@ -1316,12 +1308,12 @@ extern "C" { #define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_RWBT_M ((SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_RWBT_V)<<(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_RWBT_S)) #define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_RWBT_V 0x3 #define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_RWBT_S 22 -/* SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S1 : R/W ;bitpos:[15:14] ;default: ~2'b0 ; */ +/* SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S0 : R/W ;bitpos:[15:14] ;default: ~2'b0 ; */ /*description: */ -#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S1 0x00000003 -#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S1_M ((SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S1_V)<<(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S1_S)) -#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S1_V 0x3 -#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S1_S 14 +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S0 0x00000003 +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S0_M ((SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S0_V)<<(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S0_S)) +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S0_V 0x3 +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S0_S 14 /* SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_CAN : R/W ;bitpos:[11:10] ;default: ~2'b0 ; */ /*description: */ #define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_CAN 0x00000003 @@ -1582,12 +1574,12 @@ extern "C" { #define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_RWBT_M ((SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_RWBT_V)<<(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_RWBT_S)) #define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_RWBT_V 0x3 #define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_RWBT_S 22 -/* SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S1 : R/W ;bitpos:[15:14] ;default: ~2'b0 ; */ +/* SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S0 : R/W ;bitpos:[15:14] ;default: ~2'b0 ; */ /*description: */ -#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S1 0x00000003 -#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S1_M ((SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S1_V)<<(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S1_S)) -#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S1_V 0x3 -#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S1_S 14 +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S0 0x00000003 +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S0_M ((SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S0_V)<<(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S0_S)) +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S0_V 0x3 +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S0_S 14 /* SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_CAN : R/W ;bitpos:[11:10] ;default: ~2'b0 ; */ /*description: */ #define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_CAN 0x00000003 @@ -2160,12 +2152,12 @@ extern "C" { #define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_RWBT_M ((SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_RWBT_V)<<(SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_RWBT_S)) #define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_RWBT_V 0x3 #define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_RWBT_S 22 -/* SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S1 : R/W ;bitpos:[15:14] ;default: ~2'b0 ; */ +/* SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S0 : R/W ;bitpos:[15:14] ;default: ~2'b0 ; */ /*description: */ -#define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S1 0x00000003 -#define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S1_M ((SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S1_V)<<(SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S1_S)) -#define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S1_V 0x3 -#define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S1_S 14 +#define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S0 0x00000003 +#define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S0_M ((SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S0_V)<<(SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S0_S)) +#define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S0_V 0x3 +#define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_I2S0_S 14 /* SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_CAN : R/W ;bitpos:[11:10] ;default: ~2'b0 ; */ /*description: */ #define SENSITIVE_BACKUP_BUS_PMS_CONSTRAIN_CAN 0x00000003 diff --git a/components/soc/esp32c3/include/soc/sensitive_struct.h b/components/soc/esp32c3/register/soc/sensitive_struct.h similarity index 98% rename from components/soc/esp32c3/include/soc/sensitive_struct.h rename to components/soc/esp32c3/register/soc/sensitive_struct.h index ba860e45cd74..a7adaca7b893 100644 --- a/components/soc/esp32c3/include/soc/sensitive_struct.h +++ b/components/soc/esp32c3/register/soc/sensitive_struct.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SENSITIVE_STRUCT_H_ #define _SOC_SENSITIVE_STRUCT_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" typedef volatile struct sensitive_dev_s { union { @@ -591,7 +583,7 @@ typedef volatile struct sensitive_dev_s { uint32_t reserved6 : 4; uint32_t reg_core_0_pif_pms_constrain_world_0_can: 2; /*core_0_pif_pms_constrain_world_0_can*/ uint32_t reserved12 : 2; - uint32_t reg_core_0_pif_pms_constrain_world_0_i2s1: 2; /*core_0_pif_pms_constrain_world_0_i2s1*/ + uint32_t reg_core_0_pif_pms_constrain_world_0_i2s0: 2; /*core_0_pif_pms_constrain_world_0_i2s0*/ uint32_t reserved16 : 6; uint32_t reg_core_0_pif_pms_constrain_world_0_rwbt: 2; /*core_0_pif_pms_constrain_world_0_rwbt*/ uint32_t reserved24 : 2; @@ -669,7 +661,7 @@ typedef volatile struct sensitive_dev_s { uint32_t reserved6 : 4; uint32_t reg_core_0_pif_pms_constrain_world_1_can: 2; /*core_0_pif_pms_constrain_world_1_can*/ uint32_t reserved12 : 2; - uint32_t reg_core_0_pif_pms_constrain_world_1_i2s1: 2; /*core_0_pif_pms_constrain_world_1_i2s1*/ + uint32_t reg_core_0_pif_pms_constrain_world_1_i2s0: 2; /*core_0_pif_pms_constrain_world_1_i2s0*/ uint32_t reserved16 : 6; uint32_t reg_core_0_pif_pms_constrain_world_1_rwbt: 2; /*core_0_pif_pms_constrain_world_1_rwbt*/ uint32_t reserved24 : 2; @@ -906,7 +898,7 @@ typedef volatile struct sensitive_dev_s { uint32_t reserved6 : 4; uint32_t reg_backup_bus_pms_constrain_can: 2; /*backup_bus_pms_constrain_can*/ uint32_t reserved12 : 2; - uint32_t reg_backup_bus_pms_constrain_i2s1: 2; /*backup_bus_pms_constrain_i2s1*/ + uint32_t reg_backup_bus_pms_constrain_i2s0: 2; /*backup_bus_pms_constrain_i2s0*/ uint32_t reserved16 : 6; uint32_t reg_backup_bus_pms_constrain_rwbt: 2; /*backup_bus_pms_constrain_rwbt*/ uint32_t reserved24 : 2; diff --git a/components/soc/esp32c3/include/soc/spi_mem_reg.h b/components/soc/esp32c3/register/soc/spi_mem_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/spi_mem_reg.h rename to components/soc/esp32c3/register/soc/spi_mem_reg.h index fcf3e292481f..22d6b26377e7 100644 --- a/components/soc/esp32c3/include/soc/spi_mem_reg.h +++ b/components/soc/esp32c3/register/soc/spi_mem_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SPI_MEM_REG_H_ #define _SOC_SPI_MEM_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define SPI_MEM_CMD_REG(i) (REG_SPI_MEM_BASE(i) + 0x000) /* SPI_MEM_FLASH_READ : R/W/SC ;bitpos:[31] ;default: 1'b0 ; */ /*description: Read flash enable. Read flash operation will be triggered when @@ -270,7 +262,7 @@ extern "C" { #define SPI_MEM_CS_HOLD_DLY_RES_S 2 /* SPI_MEM_CLK_MODE : R/W ;bitpos:[1:0] ;default: 2'h0 ; */ /*description: SPI clock mode bits. 0: SPI clock is off when CS inactive 1: - SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on.*/ + SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is always on.*/ #define SPI_MEM_CLK_MODE 0x00000003 #define SPI_MEM_CLK_MODE_M ((SPI_MEM_CLK_MODE_V)<<(SPI_MEM_CLK_MODE_S)) #define SPI_MEM_CLK_MODE_V 0x3 diff --git a/components/soc/esp32c3/include/soc/spi_mem_struct.h b/components/soc/esp32c3/register/soc/spi_mem_struct.h similarity index 99% rename from components/soc/esp32c3/include/soc/spi_mem_struct.h rename to components/soc/esp32c3/register/soc/spi_mem_struct.h index d816a9a290ad..95a0aae1ecf0 100644 --- a/components/soc/esp32c3/include/soc/spi_mem_struct.h +++ b/components/soc/esp32c3/register/soc/spi_mem_struct.h @@ -63,7 +63,7 @@ typedef volatile struct spi_mem_dev_s { } ctrl; union { struct { - uint32_t clk_mode: 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on.*/ + uint32_t clk_mode: 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is always on.*/ uint32_t cs_hold_dly_res: 10; /*After RES/DP/HPM command is sent SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 512) SPI_CLK cycles.*/ uint32_t reserved2: 18; /*reserved*/ uint32_t rxfifo_rst: 1; /*SPI0 RX FIFO reset signal.*/ diff --git a/components/soc/esp32c3/include/soc/spi_reg.h b/components/soc/esp32c3/register/soc/spi_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/spi_reg.h rename to components/soc/esp32c3/register/soc/spi_reg.h index 361f58ba5c55..e8e9fec283f2 100644 --- a/components/soc/esp32c3/include/soc/spi_reg.h +++ b/components/soc/esp32c3/register/soc/spi_reg.h @@ -6,7 +6,7 @@ #ifndef _SOC_SPI_REG_H_ #define _SOC_SPI_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { @@ -138,7 +138,7 @@ be configured in CONF state..*/ #define SPI_CLOCK_REG(i) (REG_SPI_BASE(i) + 0xC) /* SPI_CLK_EQU_SYSCLK : R/W ;bitpos:[31] ;default: 1'b1 ; */ -/*description: In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from syst +/*description: In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from syst em clock. Can be configured in CONF state..*/ #define SPI_CLK_EQU_SYSCLK (BIT(31)) #define SPI_CLK_EQU_SYSCLK_M (BIT(31)) @@ -175,15 +175,15 @@ e 0. Can be configured in CONF state..*/ #define SPI_USER_REG(i) (REG_SPI_BASE(i) + 0x10) /* SPI_USR_COMMAND : R/W ;bitpos:[31] ;default: 1'b1 ; */ -/*description: This bit enable the command phase of an operation. Can be configured in CONF sta -te..*/ +/*description: This bit enable the command phase of an operation. Can be configured in CONF +state..*/ #define SPI_USR_COMMAND (BIT(31)) #define SPI_USR_COMMAND_M (BIT(31)) #define SPI_USR_COMMAND_V 0x1 #define SPI_USR_COMMAND_S 31 /* SPI_USR_ADDR : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: This bit enable the address phase of an operation. Can be configured in CONF sta -te..*/ +/*description: This bit enable the address phase of an operation. Can be configured in CONF +state..*/ #define SPI_USR_ADDR (BIT(30)) #define SPI_USR_ADDR_M (BIT(30)) #define SPI_USR_ADDR_V 0x1 @@ -357,7 +357,7 @@ n be configured in CONF state..*/ #define SPI_USR_COMMAND_BITLEN_S 28 /* SPI_MST_REMPTY_ERR_END_EN : R/W ;bitpos:[27] ;default: 1'b1 ; */ /*description: 1: SPI transfer is ended when SPI TX AFIFO read empty error is valid in GP-SPI m -aster FD/HD-mode. 0: SPI transfer is not ended when SPI TX AFIFO read empty erro +aster FD/HD-mode. 0: SPI transfer is not ended when SPI TX AFIFO read empty error r is valid in GP-SPI master FD/HD-mode..*/ #define SPI_MST_REMPTY_ERR_END_EN (BIT(27)) #define SPI_MST_REMPTY_ERR_END_EN_M (BIT(27)) @@ -927,7 +927,7 @@ AFIFO read-empty error when SPI outputs data in master mode. 0: Others..*/ #define SPI_SLV_CMD_ERR_INT_RAW_V 0x1 #define SPI_SLV_CMD_ERR_INT_RAW_S 16 /* SPI_SLV_BUF_ADDR_ERR_INT_RAW : R/W/WTC/SS ;bitpos:[15] ;default: 1'b0 ; */ -/*description: The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data addres +/*description: The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data address s of the current SPI slave mode CPU controlled FD, Wr_BUF or Rd_BUF transmission is bigger than 63. 0: Others..*/ #define SPI_SLV_BUF_ADDR_ERR_INT_RAW (BIT(15)) @@ -1370,7 +1370,7 @@ dge 0: output data at tsck posedge .*/ /* SPI_CLK_MODE : R/W ;bitpos:[1:0] ;default: 2'b0 ; */ /*description: SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delaye d one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inacti -ve 3: SPI clock is alwasy on. Can be configured in CONF state..*/ +ve 3: SPI clock is always on. Can be configured in CONF state..*/ #define SPI_CLK_MODE 0x00000003 #define SPI_CLK_MODE_M ((SPI_CLK_MODE_V)<<(SPI_CLK_MODE_S)) #define SPI_CLK_MODE_V 0x3 diff --git a/components/soc/esp32c3/include/soc/spi_struct.h b/components/soc/esp32c3/register/soc/spi_struct.h similarity index 99% rename from components/soc/esp32c3/include/soc/spi_struct.h rename to components/soc/esp32c3/register/soc/spi_struct.h index 8cb6a7ee97ab..88d7476caf98 100644 --- a/components/soc/esp32c3/include/soc/spi_struct.h +++ b/components/soc/esp32c3/register/soc/spi_struct.h @@ -55,7 +55,7 @@ typedef volatile struct spi_dev_s { uint32_t clkcnt_n : 6; /*In the master mode it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1). Can be configured in CONF state.*/ uint32_t clkdiv_pre : 4; /*In the master mode it is pre-divider of spi_clk. Can be configured in CONF state.*/ uint32_t reserved22 : 9; /*reserved*/ - uint32_t clk_equ_sysclk : 1; /*In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system clock. Can be configured in CONF state.*/ + uint32_t clk_equ_sysclk : 1; /*In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system clock. Can be configured in CONF state.*/ }; uint32_t val; } clock; @@ -317,7 +317,7 @@ typedef volatile struct spi_dev_s { uint32_t reserved_dc; union { struct { - uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on. Can be configured in CONF state.*/ + uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is always on. Can be configured in CONF state.*/ uint32_t clk_mode_13 : 1; /*{CPOL, CPHA},1: support spi clk mode 1 and 3, first edge output data B[0]/B[7]. 0: support spi clk mode 0 and 2, first edge output data B[1]/B[6].*/ uint32_t rsck_data_out : 1; /*It saves half a cycle when tsck is the same as rsck. 1: output data at rsck posedge 0: output data at tsck posedge */ uint32_t reserved4 : 4; /*reserved*/ diff --git a/components/soc/esp32c3/include/soc/syscon_reg.h b/components/soc/esp32c3/register/soc/syscon_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/syscon_reg.h rename to components/soc/esp32c3/register/soc/syscon_reg.h index e61f84eda350..1aff9a57484d 100644 --- a/components/soc/esp32c3/include/soc/syscon_reg.h +++ b/components/soc/esp32c3/register/soc/syscon_reg.h @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define SYSCON_SYSCLK_CONF_REG (DR_REG_SYSCON_BASE + 0x000) /* SYSCON_RST_TICK_CNT : R/W ;bitpos:[12] ;default: 1'b0 ; */ /*description: */ @@ -206,7 +206,7 @@ extern "C" { #define SYSTEM_MACPWR_RST BIT(8) #define SYSTEM_RW_BTMAC_RST BIT(9) /* Bluetooth MAC */ #define SYSTEM_RW_BTLP_RST BIT(10) /* Bluetooth Low Power Module */ -#define SYSTEM_RW_BTMAC_REG_RST BIT(11) /* Bluetooth MAC Regsiters */ +#define SYSTEM_RW_BTMAC_REG_RST BIT(11) /* Bluetooth MAC Registers */ #define SYSTEM_RW_BTLP_REG_RST BIT(12) /* Bluetooth Low Power Registers */ #define SYSTEM_BTBB_REG_RST BIT(13) /* Bluetooth Baseband Registers */ diff --git a/components/soc/esp32c3/include/soc/syscon_struct.h b/components/soc/esp32c3/register/soc/syscon_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/syscon_struct.h rename to components/soc/esp32c3/register/soc/syscon_struct.h diff --git a/components/soc/esp32c3/include/soc/system_reg.h b/components/soc/esp32c3/register/soc/system_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/system_reg.h rename to components/soc/esp32c3/register/soc/system_reg.h index 7bcb904214df..b82ae4184405 100644 --- a/components/soc/esp32c3/include/soc/system_reg.h +++ b/components/soc/esp32c3/register/soc/system_reg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define SYSTEM_CPU_PERI_CLK_EN_REG (DR_REG_SYSTEM_BASE + 0x000) /* SYSTEM_CLK_EN_DEDICATED_GPIO : R/W ;bitpos:[7] ;default: 1'b0 ; */ /*description: */ @@ -134,12 +134,12 @@ extern "C" { #define SYSTEM_SPI2_DMA_CLK_EN_M (BIT(22)) #define SYSTEM_SPI2_DMA_CLK_EN_V 0x1 #define SYSTEM_SPI2_DMA_CLK_EN_S 22 -/* SYSTEM_I2S1_CLK_EN : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/* SYSTEM_I2S0_CLK_EN : R/W ;bitpos:[21] ;default: 1'b0 ; */ /*description: */ -#define SYSTEM_I2S1_CLK_EN (BIT(21)) -#define SYSTEM_I2S1_CLK_EN_M (BIT(21)) -#define SYSTEM_I2S1_CLK_EN_V 0x1 -#define SYSTEM_I2S1_CLK_EN_S 21 +#define SYSTEM_I2S0_CLK_EN (BIT(21)) +#define SYSTEM_I2S0_CLK_EN_M (BIT(21)) +#define SYSTEM_I2S0_CLK_EN_V 0x1 +#define SYSTEM_I2S0_CLK_EN_S 21 /* SYSTEM_PWM1_CLK_EN : R/W ;bitpos:[20] ;default: 1'b0 ; */ /*description: */ #define SYSTEM_PWM1_CLK_EN (BIT(20)) @@ -236,12 +236,6 @@ extern "C" { #define SYSTEM_UART1_CLK_EN_M (BIT(5)) #define SYSTEM_UART1_CLK_EN_V 0x1 #define SYSTEM_UART1_CLK_EN_S 5 -/* SYSTEM_I2S0_CLK_EN : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define SYSTEM_I2S0_CLK_EN (BIT(4)) -#define SYSTEM_I2S0_CLK_EN_M (BIT(4)) -#define SYSTEM_I2S0_CLK_EN_V 0x1 -#define SYSTEM_I2S0_CLK_EN_S 4 /* SYSTEM_WDG_CLK_EN : R/W ;bitpos:[3] ;default: 1'b1 ; */ /*description: */ #define SYSTEM_WDG_CLK_EN (BIT(3)) @@ -384,12 +378,12 @@ extern "C" { #define SYSTEM_SPI2_DMA_RST_M (BIT(22)) #define SYSTEM_SPI2_DMA_RST_V 0x1 #define SYSTEM_SPI2_DMA_RST_S 22 -/* SYSTEM_I2S1_RST : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/* SYSTEM_I2S0_RST : R/W ;bitpos:[21] ;default: 1'b0 ; */ /*description: */ -#define SYSTEM_I2S1_RST (BIT(21)) -#define SYSTEM_I2S1_RST_M (BIT(21)) -#define SYSTEM_I2S1_RST_V 0x1 -#define SYSTEM_I2S1_RST_S 21 +#define SYSTEM_I2S0_RST (BIT(21)) +#define SYSTEM_I2S0_RST_M (BIT(21)) +#define SYSTEM_I2S0_RST_V 0x1 +#define SYSTEM_I2S0_RST_S 21 /* SYSTEM_PWM1_RST : R/W ;bitpos:[20] ;default: 1'b0 ; */ /*description: */ #define SYSTEM_PWM1_RST (BIT(20)) @@ -486,12 +480,6 @@ extern "C" { #define SYSTEM_UART1_RST_M (BIT(5)) #define SYSTEM_UART1_RST_V 0x1 #define SYSTEM_UART1_RST_S 5 -/* SYSTEM_I2S0_RST : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define SYSTEM_I2S0_RST (BIT(4)) -#define SYSTEM_I2S0_RST_M (BIT(4)) -#define SYSTEM_I2S0_RST_V 0x1 -#define SYSTEM_I2S0_RST_S 4 /* SYSTEM_WDG_RST : R/W ;bitpos:[3] ;default: 1'b0 ; */ /*description: */ #define SYSTEM_WDG_RST (BIT(3)) diff --git a/components/soc/esp32c3/include/soc/system_struct.h b/components/soc/esp32c3/register/soc/system_struct.h similarity index 99% rename from components/soc/esp32c3/include/soc/system_struct.h rename to components/soc/esp32c3/register/soc/system_struct.h index f4cb995aa224..66e0ccaa19fa 100644 --- a/components/soc/esp32c3/include/soc/system_struct.h +++ b/components/soc/esp32c3/register/soc/system_struct.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" typedef volatile struct system_dev_s { union { @@ -54,7 +54,7 @@ typedef volatile struct system_dev_s { uint32_t reg_spi01_clk_en : 1; /*reg_spi01_clk_en*/ uint32_t reg_uart_clk_en : 1; /*reg_uart_clk_en*/ uint32_t reg_wdg_clk_en : 1; /*reg_wdg_clk_en*/ - uint32_t reg_i2s0_clk_en : 1; /*reg_i2s0_clk_en*/ + uint32_t reserved_04 : 1; /*reserved*/ uint32_t reg_uart1_clk_en : 1; /*reg_uart1_clk_en*/ uint32_t reg_spi2_clk_en : 1; /*reg_spi2_clk_en*/ uint32_t reg_i2c_ext0_clk_en : 1; /*reg_i2c_ext0_clk_en*/ @@ -71,7 +71,7 @@ typedef volatile struct system_dev_s { uint32_t reg_i2c_ext1_clk_en : 1; /*reg_i2c_ext1_clk_en*/ uint32_t reg_can_clk_en : 1; /*reg_can_clk_en*/ uint32_t reg_pwm1_clk_en : 1; /*reg_pwm1_clk_en*/ - uint32_t reg_i2s1_clk_en : 1; /*reg_i2s1_clk_en*/ + uint32_t reg_i2s0_clk_en : 1; /*reg_i2s0_clk_en*/ uint32_t reg_spi2_dma_clk_en : 1; /*reg_spi2_dma_clk_en*/ uint32_t reg_usb_device_clk_en : 1; /*reg_usb_device_clk_en*/ uint32_t reg_uart_mem_clk_en : 1; /*reg_uart_mem_clk_en*/ @@ -108,7 +108,7 @@ typedef volatile struct system_dev_s { uint32_t reg_spi01_rst : 1; /*reg_spi01_rst*/ uint32_t reg_uart_rst : 1; /*reg_uart_rst*/ uint32_t reg_wdg_rst : 1; /*reg_wdg_rst*/ - uint32_t reg_i2s0_rst : 1; /*reg_i2s0_rst*/ + uint32_t reserved_04 : 1; /*reserved*/ uint32_t reg_uart1_rst : 1; /*reg_uart1_rst*/ uint32_t reg_spi2_rst : 1; /*reg_spi2_rst*/ uint32_t reg_i2c_ext0_rst : 1; /*reg_i2c_ext0_rst*/ @@ -125,7 +125,7 @@ typedef volatile struct system_dev_s { uint32_t reg_i2c_ext1_rst : 1; /*reg_i2c_ext1_rst*/ uint32_t reg_can_rst : 1; /*reg_can_rst*/ uint32_t reg_pwm1_rst : 1; /*reg_pwm1_rst*/ - uint32_t reg_i2s1_rst : 1; /*reg_i2s1_rst*/ + uint32_t reg_i2s0_rst : 1; /*reg_i2s0_rst*/ uint32_t reg_spi2_dma_rst : 1; /*reg_spi2_dma_rst*/ uint32_t reg_usb_device_rst : 1; /*reg_usb_device_rst*/ uint32_t reg_uart_mem_rst : 1; /*reg_uart_mem_rst*/ diff --git a/components/soc/esp32c3/include/soc/systimer_reg.h b/components/soc/esp32c3/register/soc/systimer_reg.h similarity index 97% rename from components/soc/esp32c3/include/soc/systimer_reg.h rename to components/soc/esp32c3/register/soc/systimer_reg.h index 4e9f64fffa8d..55316915df15 100644 --- a/components/soc/esp32c3/include/soc/systimer_reg.h +++ b/components/soc/esp32c3/register/soc/systimer_reg.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32c3/include/soc/systimer_struct.h b/components/soc/esp32c3/register/soc/systimer_struct.h similarity index 94% rename from components/soc/esp32c3/include/soc/systimer_struct.h rename to components/soc/esp32c3/register/soc/systimer_struct.h index 47e7b7d30c28..cf10afab1c34 100644 --- a/components/soc/esp32c3/include/soc/systimer_struct.h +++ b/components/soc/esp32c3/register/soc/systimer_struct.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32c3/include/soc/timer_group_reg.h b/components/soc/esp32c3/register/soc/timer_group_reg.h similarity index 100% rename from components/soc/esp32c3/include/soc/timer_group_reg.h rename to components/soc/esp32c3/register/soc/timer_group_reg.h diff --git a/components/soc/esp32c3/include/soc/timer_group_struct.h b/components/soc/esp32c3/register/soc/timer_group_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/timer_group_struct.h rename to components/soc/esp32c3/register/soc/timer_group_struct.h diff --git a/components/soc/esp32c3/include/soc/twai_struct.h b/components/soc/esp32c3/register/soc/twai_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/twai_struct.h rename to components/soc/esp32c3/register/soc/twai_struct.h diff --git a/components/soc/esp32c3/include/soc/uart_reg.h b/components/soc/esp32c3/register/soc/uart_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/uart_reg.h rename to components/soc/esp32c3/register/soc/uart_reg.h index a0d6c72735bd..c26bab99382f 100644 --- a/components/soc/esp32c3/include/soc/uart_reg.h +++ b/components/soc/esp32c3/register/soc/uart_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_UART_REG_H_ #define _SOC_UART_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0) /* UART_RXFIFO_RD_BYTE : RO ;bitpos:[7:0] ;default: 8'b0 ; */ /*description: UART $n accesses FIFO via this register.*/ @@ -99,7 +91,7 @@ extern "C" { #define UART_SW_XOFF_INT_RAW_V 0x1 #define UART_SW_XOFF_INT_RAW_S 10 /* UART_SW_XON_INT_RAW : R/WTC/SS ;bitpos:[9] ;default: 1'b0 ; */ -/*description: This interrupt raw bit turns to high level when receiver recevies +/*description: This interrupt raw bit turns to high level when receiver receives Xon char when uart_sw_flow_con_en is set to 1.*/ #define UART_SW_XON_INT_RAW (BIT(9)) #define UART_SW_XON_INT_RAW_M (BIT(9)) @@ -212,7 +204,7 @@ extern "C" { #define UART_TX_DONE_INT_ST_V 0x1 #define UART_TX_DONE_INT_ST_S 14 /* UART_TX_BRK_IDLE_DONE_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena +/*description: This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena is set to 1.*/ #define UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) #define UART_TX_BRK_IDLE_DONE_INT_ST_M (BIT(13)) @@ -751,7 +743,7 @@ extern "C" { #define UART_IRDA_DPLX_V 0x1 #define UART_IRDA_DPLX_S 9 /* UART_TXD_BRK : R/W ;bitpos:[8] ;default: 1'b0 ; */ -/*description: Set this bit to enbale transmitter to send NULL when the process +/*description: Set this bit to enable transmitter to send NULL when the process of sending data is done.*/ #define UART_TXD_BRK (BIT(8)) #define UART_TXD_BRK_M (BIT(8)) @@ -798,7 +790,7 @@ extern "C" { #define UART_CONF1_REG(i) (REG_UART_BASE(i) + 0x24) /* UART_RX_TOUT_EN : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: This is the enble bit for uart receiver's timeout function.*/ +/*description: This is the enable bit for uart receiver's timeout function.*/ #define UART_RX_TOUT_EN (BIT(21)) #define UART_RX_TOUT_EN_M (BIT(21)) #define UART_RX_TOUT_EN_V 0x1 @@ -847,7 +839,7 @@ extern "C" { #define UART_HIGHPULSE_REG(i) (REG_UART_BASE(i) + 0x2C) /* UART_HIGHPULSE_MIN_CNT : RO ;bitpos:[11:0] ;default: 12'hFFF ; */ -/*description: This register stores the value of the maxinum duration time +/*description: This register stores the value of the maximum duration time for the high level pulse. It is used in baud rate-detect process.*/ #define UART_HIGHPULSE_MIN_CNT 0x00000FFF #define UART_HIGHPULSE_MIN_CNT_M ((UART_HIGHPULSE_MIN_CNT_V)<<(UART_HIGHPULSE_MIN_CNT_S)) diff --git a/components/soc/esp32c3/include/soc/uart_struct.h b/components/soc/esp32c3/register/soc/uart_struct.h similarity index 98% rename from components/soc/esp32c3/include/soc/uart_struct.h rename to components/soc/esp32c3/register/soc/uart_struct.h index b14191f3ff0a..8c76d475fb2c 100644 --- a/components/soc/esp32c3/include/soc/uart_struct.h +++ b/components/soc/esp32c3/register/soc/uart_struct.h @@ -28,7 +28,7 @@ typedef volatile struct uart_dev_s { uint32_t cts_chg: 1; /*This interrupt raw bit turns to high level when receiver detects the edge change of CTSn signal.*/ uint32_t brk_det: 1; /*This interrupt raw bit turns to high level when receiver detects a 0 after the stop bit.*/ uint32_t rxfifo_tout: 1; /*This interrupt raw bit turns to high level when receiver takes more time than rx_tout_thrhd to receive a byte.*/ - uint32_t sw_xon: 1; /*This interrupt raw bit turns to high level when receiver recevies Xon char when uart_sw_flow_con_en is set to 1.*/ + uint32_t sw_xon: 1; /*This interrupt raw bit turns to high level when receiver receives Xon char when uart_sw_flow_con_en is set to 1.*/ uint32_t sw_xoff: 1; /*This interrupt raw bit turns to high level when receiver receives Xoff char when uart_sw_flow_con_en is set to 1.*/ uint32_t glitch_det: 1; /*This interrupt raw bit turns to high level when receiver detects a glitch in the middle of a start bit.*/ uint32_t tx_brk_done: 1; /*This interrupt raw bit turns to high level when transmitter completes sending NULL characters after all data in Tx-FIFO are sent.*/ @@ -58,7 +58,7 @@ typedef volatile struct uart_dev_s { uint32_t sw_xoff: 1; /*This is the status bit for sw_xoff_int_raw when sw_xoff_int_ena is set to 1.*/ uint32_t glitch_det: 1; /*This is the status bit for glitch_det_int_raw when glitch_det_int_ena is set to 1.*/ uint32_t tx_brk_done: 1; /*This is the status bit for tx_brk_done_int_raw when tx_brk_done_int_ena is set to 1.*/ - uint32_t tx_brk_idle_done: 1; /*This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena is set to 1.*/ + uint32_t tx_brk_idle_done: 1; /*This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena is set to 1.*/ uint32_t tx_done: 1; /*This is the status bit for tx_done_int_raw when tx_done_int_ena is set to 1.*/ uint32_t rs485_parity_err: 1; /*This is the status bit for rs485_parity_err_int_raw when rs485_parity_int_ena is set to 1.*/ uint32_t rs485_frm_err: 1; /*This is the status bit for rs485_frm_err_int_raw when rs485_fm_err_int_ena is set to 1.*/ @@ -161,7 +161,7 @@ typedef volatile struct uart_dev_s { uint32_t stop_bit_num: 2; /*This register is used to set the length of stop bit.*/ uint32_t sw_rts: 1; /*This register is used to configure the software rts signal which is used in software flow control.*/ uint32_t sw_dtr: 1; /*This register is used to configure the software dtr signal which is used in software flow control.*/ - uint32_t txd_brk: 1; /*Set this bit to enbale transmitter to send NULL when the process of sending data is done.*/ + uint32_t txd_brk: 1; /*Set this bit to enable transmitter to send NULL when the process of sending data is done.*/ uint32_t irda_dplx: 1; /*Set this bit to enable IrDA loopback mode.*/ uint32_t irda_tx_en: 1; /*This is the start enable bit for IrDA transmitter.*/ uint32_t irda_wctl: 1; /*1'h1: The IrDA transmitter's 11th bit is the same as 10th bit. 1'h0: Set IrDA transmitter's 11th bit to 0.*/ @@ -193,7 +193,7 @@ typedef volatile struct uart_dev_s { uint32_t dis_rx_dat_ovf: 1; /*Disable UART Rx data overflow detect.*/ uint32_t rx_tout_flow_dis: 1; /*Set this bit to stop accumulating idle_cnt when hardware flow control works.*/ uint32_t rx_flow_en: 1; /*This is the flow enable bit for UART receiver.*/ - uint32_t rx_tout_en: 1; /*This is the enble bit for uart receiver's timeout function.*/ + uint32_t rx_tout_en: 1; /*This is the enable bit for uart receiver's timeout function.*/ uint32_t reserved22: 10; }; uint32_t val; @@ -207,7 +207,7 @@ typedef volatile struct uart_dev_s { } lowpulse; union { struct { - uint32_t min_cnt: 12; /*This register stores the value of the maxinum duration time for the high level pulse. It is used in baud rate-detect process.*/ + uint32_t min_cnt: 12; /*This register stores the value of the maximum duration time for the high level pulse. It is used in baud rate-detect process.*/ uint32_t reserved12: 20; /*Reserved*/ }; uint32_t val; diff --git a/components/soc/esp32c3/include/soc/uhci_reg.h b/components/soc/esp32c3/register/soc/uhci_reg.h similarity index 97% rename from components/soc/esp32c3/include/soc/uhci_reg.h rename to components/soc/esp32c3/register/soc/uhci_reg.h index 3a41dedb8008..f387de7963ac 100644 --- a/components/soc/esp32c3/include/soc/uhci_reg.h +++ b/components/soc/esp32c3/register/soc/uhci_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_UHCI_REG_H_ #define _SOC_UHCI_REG_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define UHCI_CONF0_REG(i) (REG_UHCI_BASE(i) + 0x0) /* UHCI_UART_RX_BRK_EOF_EN : R/W ;bitpos:[12] ;default: 1'b0 ; */ /*description: If this bit is set to 1 UHCI will end payload receive process diff --git a/components/soc/esp32c3/include/soc/uhci_struct.h b/components/soc/esp32c3/register/soc/uhci_struct.h similarity index 100% rename from components/soc/esp32c3/include/soc/uhci_struct.h rename to components/soc/esp32c3/register/soc/uhci_struct.h diff --git a/components/soc/esp32c3/include/soc/usb_serial_jtag_reg.h b/components/soc/esp32c3/register/soc/usb_serial_jtag_reg.h similarity index 99% rename from components/soc/esp32c3/include/soc/usb_serial_jtag_reg.h rename to components/soc/esp32c3/register/soc/usb_serial_jtag_reg.h index f4cf387fe6c7..6d908baec1b9 100644 --- a/components/soc/esp32c3/include/soc/usb_serial_jtag_reg.h +++ b/components/soc/esp32c3/register/soc/usb_serial_jtag_reg.h @@ -1,9 +1,9 @@ - -/** Copyright 2021 Espressif Systems (Shanghai) Co. Ltd. - * SPDX-License-Identifier: Apache-2.0 +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 */ - #pragma once #include @@ -155,7 +155,7 @@ extern "C" { #define USB_SERIAL_JTAG_TEST_ENABLE_V 0x00000001 #define USB_SERIAL_JTAG_TEST_ENABLE_S 0 /* USB_SERIAL_JTAG_TEST_USB_OE : R/W; bitpos: [1]; default: 0; - * USB pad oen in + * USB pad one in * test */ #define USB_SERIAL_JTAG_TEST_USB_OE (BIT(1)) diff --git a/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32c3/register/soc/usb_serial_jtag_struct.h similarity index 96% rename from components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h rename to components/soc/esp32c3/register/soc/usb_serial_jtag_struct.h index c1cfced04bbf..98b15060a425 100644 --- a/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32c3/register/soc/usb_serial_jtag_struct.h @@ -1,16 +1,8 @@ -// Copyright 2021 Espressif Systems (Shanghai) Co. Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_USB_SERIAL_JTAG_STRUCT_H_ #define _SOC_USB_SERIAL_JTAG_STRUCT_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" typedef volatile struct usb_serial_jtag_dev_s { union { diff --git a/components/soc/esp32c3/include/soc/xts_aes_reg.h b/components/soc/esp32c3/register/soc/xts_aes_reg.h similarity index 98% rename from components/soc/esp32c3/include/soc/xts_aes_reg.h rename to components/soc/esp32c3/register/soc/xts_aes_reg.h index 9845d0b05829..6a6e64539c5a 100644 --- a/components/soc/esp32c3/include/soc/xts_aes_reg.h +++ b/components/soc/esp32c3/register/soc/xts_aes_reg.h @@ -119,7 +119,7 @@ extern "C" { #define XTS_AES_DATE_V 0x3FFFFFFFU #define XTS_AES_DATE_S 0 -/* For backward compatability with the older register names */ +/* For backward compatibility with the older register names */ #define AES_XTS_PLAIN_BASE XTS_AES_PLAIN_MEM #define AES_XTS_SIZE_REG XTS_AES_LINESIZE_REG #define AES_XTS_DESTINATION_REG XTS_AES_DESTINATION_REG diff --git a/components/soc/esp32c3/spi_periph.c b/components/soc/esp32c3/spi_periph.c index 5ae7aed529fc..b270a925236d 100644 --- a/components/soc/esp32c3/spi_periph.c +++ b/components/soc/esp32c3/spi_periph.c @@ -33,7 +33,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = -1, .irq = -1, .irq_dma = -1, - .module = -1, .hw = NULL, .func = -1, }, { @@ -57,7 +56,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, .irq = ETS_SPI2_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_SPI2_MODULE, .hw = &GPSPI2, .func = SPI2_FUNC_NUM, } diff --git a/components/soc/esp32c5/etm_periph.c b/components/soc/esp32c5/etm_periph.c new file mode 100644 index 000000000000..7b268c443a55 --- /dev/null +++ b/components/soc/esp32c5/etm_periph.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/etm_periph.h" +#include "soc/soc_etm_reg.h" + +/** + * ETM Registers to be saved during sleep retention + * - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG +*/ +#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1) + +static const regdma_entries_config_t etm_regdma_entries[] = { + // backup stage: save the status of enabled channels + // restore stage: store the enabled channels + [0] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00), + SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, + [1] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01), + SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [2] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02), + SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, +}; + +const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { + [0] = { + .module = SLEEP_RETENTION_MODULE_ETM0, + .regdma_entry_array = etm_regdma_entries, + .array_size = ARRAY_SIZE(etm_regdma_entries) + }, +}; diff --git a/components/soc/esp32c5/i2c_periph.c b/components/soc/esp32c5/i2c_periph.c index 5cc53907f946..bd702887f88e 100644 --- a/components/soc/esp32c5/i2c_periph.c +++ b/components/soc/esp32c5/i2c_periph.c @@ -40,3 +40,32 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = { .irq = ETS_LP_I2C_INTR_SOURCE, }, }; + +// I2C sleep retention entries +// I2C registers require set the reg_update bit to make the configuration take effect + +/* I2C Registers Context + Include: I2C_SCL_LOW_PERIOD_REG / + I2C_CTR_REG / I2C_TO_REG / I2C_SLAVE_ADDR_REG / I2C_FIFO_CONF_REG + I2C_INT_ENA_REG / I2C_SDA_HOLD_REG / I2C_SDA_SAMPLE_REG / I2C_SCL_START_HOLD_REG + I2C_SCL_RSTART_SETUP_REG / I2C_SCL_STOP_HOLD_REG / I2C_SCL_STOP_SETUP_REG /I2C_FILTER_CFG_REG / I2C_CLK_CONF_REG / I2C_SCL_ST_TIME_OUT_REG / I2C_SCL_MAIN_ST_TIME_OUT_REG / I2C_SCL_SP_CONF_REG / I2C_SCL_STRETCH_CONF_REG +*/ +#define I2C0_RETENTION_REGS_CNT 18 +#define I2C0_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(0) +static const uint32_t i2c0_regs_map[4] = {0xc03f345b, 0x3, 0, 0}; +static const regdma_entries_config_t i2c0_regs_retention[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_REGS_CNT, 0, 0, i2c0_regs_map[0], i2c0_regs_map[1], i2c0_regs_map[2], i2c0_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(0), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(0), 0x0, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(0), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(0), 0x0, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM] = { + {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention), SLEEP_RETENTION_MODULE_I2C0}, +}; diff --git a/components/soc/esp32c5/i2s_periph.c b/components/soc/esp32c5/i2s_periph.c index dbd1fdc816b4..9866cc978925 100644 --- a/components/soc/esp32c5/i2s_periph.c +++ b/components/soc/esp32c5/i2s_periph.c @@ -5,6 +5,7 @@ */ #include "soc/i2s_periph.h" +#include "soc/i2s_reg.h" #include "soc/gpio_sig_map.h" /* @@ -29,7 +30,44 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_out_sigs[1] = I2SO_SD1_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, - .irq = ETS_I2S1_INTR_SOURCE, - .module = -1, + .irq = ETS_I2S0_INTR_SOURCE, } }; + +/** + * I2S Registers to be saved during sleep retention + * - I2S_RX_CONF_REG + * - I2S_TX_CONF_REG + * - I2S_RX_CONF1_REG + * - I2S_TX_CONF1_REG + * - I2S_TX_PCM2PDM_CONF_REG + * - I2S_TX_PCM2PDM_CONF1_REG + * - I2S_RX_TDM_CTRL_REG + * - I2S_TX_TDM_CTRL_REG + * - I2S_RXEOF_NUM_REG + * - I2S_ETM_CONF_REG +*/ +#define I2S_RETENTION_REGS_CNT 10 +#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG(i) +static const uint32_t i2s_regs_map[4] = {0x12360f, 0x0, 0x0, 0x0}; +#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \ + /* Save/restore the register values */ \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \ + REGDMA_I2S_LINK(0x00), \ + I2S_RETENTION_REGS_BASE(i2s_port), \ + I2S_RETENTION_REGS_BASE(i2s_port), \ + I2S_RETENTION_REGS_CNT, 0, 0, \ + i2s_regs_map[0], i2s_regs_map[1], \ + i2s_regs_map[2], i2s_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2)}, \ +}; + +static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(0); + +const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = { + [0] = { + .retention_module = SLEEP_RETENTION_MODULE_I2S0, + .entry_array = i2s0_regs_retention, + .array_size = ARRAY_SIZE(i2s0_regs_retention) + }, +}; diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index de44eb10f05b..e1ceec5368d1 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -463,6 +463,10 @@ config SOC_ETM_CHANNELS_PER_GROUP int default 50 +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_GPIO_PORT int default 1 @@ -615,6 +619,10 @@ config SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH bool default y +config SOC_I2C_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_LP_I2C_NUM int default 1 @@ -675,6 +683,10 @@ config SOC_I2S_TDM_FULL_DATA_WIDTH bool default y +config SOC_I2S_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK bool default y @@ -683,6 +695,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 6 @@ -707,6 +723,10 @@ config SOC_LEDC_FADE_PARAMS_BIT_WIDTH int default 10 +config SOC_LEDC_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MMU_PERIPH_NUM int default 1 @@ -747,6 +767,10 @@ config SOC_PCNT_SUPPORT_STEP_NOTIFY bool default y +config SOC_PCNT_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_RMT_GROUPS int default 1 @@ -903,6 +927,10 @@ config SOC_PARLIO_TX_SIZE_BY_DMA bool default y +config SOC_PARLIO_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MPI_MEM_BLOCKS_NUM int default 4 @@ -999,6 +1027,10 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool default y +config SOC_SPI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_SPI_SUPPORT_CLK_XTAL bool default y @@ -1151,6 +1183,14 @@ config SOC_EFUSE_ECDSA_KEY bool default y +config SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY + bool + default y + +config SOC_KEY_MANAGER_FE_KEY_DEPLOY + bool + default y + config SOC_SECURE_BOOT_V2_ECC bool default y @@ -1395,6 +1435,14 @@ config SOC_TEMPERATURE_SENSOR_INTR_SUPPORT bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + bool + default y + +config SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN + bool + default y + config SOC_WIFI_HW_TSF bool default y diff --git a/components/soc/esp32c5/include/soc/interrupts.h b/components/soc/esp32c5/include/soc/interrupts.h index f4411dfc34bf..5eb272ae64f4 100644 --- a/components/soc/esp32c5/include/soc/interrupts.h +++ b/components/soc/esp32c5/include/soc/interrupts.h @@ -58,7 +58,7 @@ typedef enum { ETS_HP_APM_M4_INTR_SOURCE, ETS_LP_APM0_INTR_SOURCE, ETS_MSPI_INTR_SOURCE, - ETS_I2S1_INTR_SOURCE, /**< interrupt of I2S1, level*/ + ETS_I2S0_INTR_SOURCE, /**< interrupt of I2S0, level*/ ETS_UHCI0_INTR_SOURCE, /**< interrupt of UHCI0, level*/ ETS_UART0_INTR_SOURCE, /**< interrupt of UART0, level*/ ETS_UART1_INTR_SOURCE, /**< interrupt of UART1, level*/ diff --git a/components/soc/esp32c5/include/soc/regi2c_saradc.h b/components/soc/esp32c5/include/soc/regi2c_saradc.h index 120d51fc20d2..7fa3ff460262 100644 --- a/components/soc/esp32c5/include/soc/regi2c_saradc.h +++ b/components/soc/esp32c5/include/soc/regi2c_saradc.h @@ -81,3 +81,19 @@ #define ADC_SARADC2_EN_TOUT_ADDR 0x8 #define ADC_SARADC2_EN_TOUT_ADDR_MSB 0x2 #define ADC_SARADC2_EN_TOUT_ADDR_LSB 0x2 + +#define POWER_GLITCH_DREF_VDET_PERIF 11 +#define POWER_GLITCH_DREF_VDET_PERIF_MSB 2 +#define POWER_GLITCH_DREF_VDET_PERIF_LSB 0 + +#define POWER_GLITCH_DREF_VDET_VDDPST 11 +#define POWER_GLITCH_DREF_VDET_VDDPST_MSB 6 +#define POWER_GLITCH_DREF_VDET_VDDPST_LSB 4 + +#define POWER_GLITCH_DREF_VDET_XTAL 12 +#define POWER_GLITCH_DREF_VDET_XTAL_MSB 2 +#define POWER_GLITCH_DREF_VDET_XTAL_LSB 0 + +#define POWER_GLITCH_DREF_VDET_PLL 12 +#define POWER_GLITCH_DREF_VDET_PLL_MSB 6 +#define POWER_GLITCH_DREF_VDET_PLL_LSB 4 diff --git a/components/soc/esp32c5/include/soc/reset_reasons.h b/components/soc/esp32c5/include/soc/reset_reasons.h index f86a798e289d..8822b2573a54 100644 --- a/components/soc/esp32c5/include/soc/reset_reasons.h +++ b/components/soc/esp32c5/include/soc/reset_reasons.h @@ -23,7 +23,6 @@ extern "C" { #endif -// TODO: [ESP32C5] IDF-8660 Check reset reasons for MP version /** * @brief Naming conventions: RESET_REASON_{reset level}_{reset reason} * @note refer to TRM: chapter diff --git a/components/soc/esp32c5/include/soc/retention_periph_defs.h b/components/soc/esp32c5/include/soc/retention_periph_defs.h index 6fd2cdda6cc9..2396ca2c13e0 100644 --- a/components/soc/esp32c5/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c5/include/soc/retention_periph_defs.h @@ -15,6 +15,7 @@ extern "C" { typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_MIN = 0, + SLEEP_RETENTION_MODULE_NULL = SLEEP_RETENTION_MODULE_MIN, /* This module is for all peripherals that can't survive from PD_TOP to call init only. Shouldn't have any dependency. */ /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2, @@ -36,6 +37,13 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_RMT0 = 13, SLEEP_RETENTION_MODULE_UART0 = 14, SLEEP_RETENTION_MODULE_UART1 = 15, + SLEEP_RETENTION_MODULE_I2S0 = 16, + SLEEP_RETENTION_MODULE_ETM0 = 17, + SLEEP_RETENTION_MODULE_TEMP_SENSOR = 18, + SLEEP_RETENTION_MODULE_PARLIO0 = 19, + SLEEP_RETENTION_MODULE_GPSPI2 = 20, + SLEEP_RETENTION_MODULE_LEDC = 21, + SLEEP_RETENTION_MODULE_PCNT0 = 22, /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -48,6 +56,8 @@ typedef enum periph_retention_module { } periph_retention_module_t; typedef enum periph_retention_module_bitmap { + SLEEP_RETENTION_MODULE_BM_NULL = BIT(SLEEP_RETENTION_MODULE_NULL), + /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM), @@ -74,6 +84,13 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0), SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0), SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), + SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), + SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), + SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR), + SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0), + SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2), + SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC), + SLEEP_RETENTION_MODULE_BM_PCNT0 = BIT(SLEEP_RETENTION_MODULE_PCNT0), SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), @@ -94,6 +111,14 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_RMT0 \ | SLEEP_RETENTION_MODULE_BM_UART0 \ | SLEEP_RETENTION_MODULE_BM_UART1 \ + | SLEEP_RETENTION_MODULE_BM_I2S0 \ + | SLEEP_RETENTION_MODULE_BM_ETM0 \ + | SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \ + | SLEEP_RETENTION_MODULE_BM_PARLIO0 \ + | SLEEP_RETENTION_MODULE_BM_GPSPI2 \ + | SLEEP_RETENTION_MODULE_BM_LEDC \ + | SLEEP_RETENTION_MODULE_BM_PCNT0 \ + | SLEEP_RETENTION_MODULE_BM_NULL \ ) #ifdef __cplusplus } diff --git a/components/soc/esp32c5/include/soc/soc.h b/components/soc/esp32c5/include/soc/soc.h index 7134121e4b50..23fae74732fe 100644 --- a/components/soc/esp32c5/include/soc/soc.h +++ b/components/soc/esp32c5/include/soc/soc.h @@ -12,7 +12,7 @@ #endif #include "esp_bit_defs.h" -#include "reg_base.h" +#include "soc/reg_base.h" #define PRO_CPU_NUM (0) @@ -21,7 +21,7 @@ #define REG_I2S_BASE(i) (DR_REG_I2S_BASE) // only one I2S on C5 #define REG_TIMG_BASE(i) (DR_REG_TIMERG0_BASE + (i) * 0x1000) // TIMERG0 and TIMERG1 #define REG_SPI_MEM_BASE(i) (DR_REG_SPIMEM0_BASE + (i) * 0x1000) // SPIMEM0 and SPIMEM1 -#define REG_SPI_BASE(i) (DR_REG_GPSPI2_BASE) // only one GPSPI on C5 +#define REG_SPI_BASE(i) (DR_REG_SPI2_BASE) // only one GPSPI on C5 #define REG_I2C_BASE(i) (DR_REG_I2C_BASE) // only one I2C on C5 #define REG_MCPWM_BASE(i) (DR_REG_MCPWM_BASE) // only one MCPWM on C5 #define REG_TWAI_BASE(i) (DR_REG_TWAI0_BASE + (i) * 0x2000) // TWAI0 and TWAI1 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 1fde2ac0a32b..928e92e844ad 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -191,6 +191,7 @@ /*-------------------------- ETM CAPS --------------------------------------*/ #define SOC_ETM_GROUPS 1U // Number of ETM groups #define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C5 has 1 GPIO peripheral @@ -265,7 +266,7 @@ #define SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS (1) #define SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH (1) -// #define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) // TODO: IDF-9693 +#define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- LP_I2C CAPS -------------------------------------*/ // ESP32-C5 has 1 LP_I2C @@ -288,16 +289,19 @@ #define SOC_I2S_PDM_MAX_TX_LINES (2) #define SOC_I2S_SUPPORTS_TDM (1) #define SOC_I2S_TDM_FULL_DATA_WIDTH (1) /*!< No limitation to data bit width when using multiple slots */ +#define SOC_I2S_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up I2S registers before sleep */ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (6) #define SOC_LEDC_TIMER_BIT_WIDTH (20) #define SOC_LEDC_SUPPORT_FADE_STOP (1) #define SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED (1) #define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16) #define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10) +#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- MMU CAPS ----------------------------------------*/ #define SOC_MMU_PERIPH_NUM (1U) @@ -319,6 +323,7 @@ #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 #define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1 #define SOC_PCNT_SUPPORT_STEP_NOTIFY 1 +#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ @@ -368,6 +373,7 @@ #define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */ #define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */ #define SOC_PARLIO_TX_SIZE_BY_DMA 1 /*!< Transaction length is controlled by DMA instead of indicated by register */ +#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */ /*--------------------------- MPI CAPS ---------------------------------------*/ #define SOC_MPI_MEM_BLOCKS_NUM (4) @@ -419,6 +425,7 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 +#define SOC_SPI_SUPPORT_SLEEP_RETENTION 1 #define SOC_SPI_SUPPORT_CLK_XTAL 1 #define SOC_SPI_SUPPORT_CLK_PLL_F160M 1 #define SOC_SPI_SUPPORT_CLK_RC_FAST 1 @@ -493,6 +500,10 @@ // #define SOC_EFUSE_DIS_ICACHE 1 #define SOC_EFUSE_ECDSA_KEY 1 +/*-------------------------- Key Manager CAPS----------------------------*/ +#define SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY 1 /*!< Key manager responsible to deploy ECDSA key */ +#define SOC_KEY_MANAGER_FE_KEY_DEPLOY 1 /*!< Key manager responsible to deploy Flash Encryption key */ + /*-------------------------- Secure Boot CAPS----------------------------*/ #define SOC_SECURE_BOOT_V2_ECC 1 #define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3 @@ -589,6 +600,8 @@ #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) #define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1) +#define SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION (1) +#define SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN (1) /*------------------------------------ WI-FI CAPS ------------------------------------*/ #define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ diff --git a/components/soc/esp32c5/include/soc/system_reg.h b/components/soc/esp32c5/include/soc/system_reg.h index 06daf4471320..939bf695f0bd 100644 --- a/components/soc/esp32c5/include/soc/system_reg.h +++ b/components/soc/esp32c5/include/soc/system_reg.h @@ -7,6 +7,6 @@ #include "soc/hp_system_reg.h" // TODO: IDF-5720 -#include "intpri_reg.h" +#include "soc/intpri_reg.h" #define SYSTEM_CPU_INTR_FROM_CPU_0_REG INTPRI_CPU_INTR_FROM_CPU_0_REG #define SYSTEM_CPU_INTR_FROM_CPU_0 INTPRI_CPU_INTR_FROM_CPU_0 diff --git a/components/soc/esp32c5/interrupts.c b/components/soc/esp32c5/interrupts.c index eb4a89c989e5..23421b66278b 100644 --- a/components/soc/esp32c5/interrupts.c +++ b/components/soc/esp32c5/interrupts.c @@ -50,7 +50,7 @@ const char *const esp_isr_names[] = { [ETS_HP_APM_M4_INTR_SOURCE] = "HP_APM_M4", [ETS_LP_APM0_INTR_SOURCE] = "LP_APM0", [ETS_MSPI_INTR_SOURCE] = "MSPI", - [ETS_I2S1_INTR_SOURCE] = "I2S1", + [ETS_I2S0_INTR_SOURCE] = "I2S0", [ETS_UHCI0_INTR_SOURCE] = "UHCI0", [ETS_UART0_INTR_SOURCE] = "UART0", [ETS_UART1_INTR_SOURCE] = "UART1", diff --git a/components/soc/esp32c5/ledc_periph.c b/components/soc/esp32c5/ledc_periph.c index fa64b659225d..1279e25dce72 100644 --- a/components/soc/esp32c5/ledc_periph.c +++ b/components/soc/esp32c5/ledc_periph.c @@ -15,3 +15,152 @@ const ledc_signal_conn_t ledc_periph_signal[1] = { .sig_out0_idx = LEDC_LS_SIG_OUT0_IDX, } }; + +/** + * LEDC registers to be saved for sleep retention + * + * channel: + * LEDC_CHx_CONF0_REG, LEDC_CHx_HPOINT_REG, LEDC_CHx_DUTY_R_REG -> LEDC_CHx_DUTY_REG, + * LEDC_CHx_GAMMA_CONF_REG, LEDC_CHx_GAMMA_RANGEi_REG + * + * timer: + * LEDC_TIMERn_CONF_REG, LEDC_TIMERn_CMP_REG, + * + * common: + * LEDC_INT_ENA_REG, + * LEDC_EVT_TASK_EN0_REG, LEDC_EVT_TASK_EN1_REG, LEDC_EVT_TASK_EN2_REG, + * LEDC_CONF_REG, + * + * Note 1: Gamma parameter registers are backuped and restored. But we won't start a fade automatically after wake-up. + * Instead, we will only start a PWM with a fixed duty cycle, the same value as before entering the sleep. + * + * Note 2: For timer/channel registers to get synced, update bits need to be set + * + * Note 3: Gamma RAM registers R/W relies both APB and function clock, therefore, retention requires the existence of function clock + */ +#define LEDC_COMMON_RETENTION_REGS_CNT 5 +#define LEDC_COMMON_RETENTION_REGS_BASE (DR_REG_LEDC_BASE + 0xc8) +static const uint32_t ledc_common_regs_map[4] = {0x1c00001, 0x400, 0x0, 0x0}; +static const regdma_entries_config_t ledc_common_regdma_entries[] = { + // If a fade is in process, the DUTY_CHNG_END_CHx intr bit is enabled, however, we don't want it to be restored after wake-up (no fade after wake-up). + // Therefore, we can set it to 0 before backup the LEDC_INT_ENA_REG. + [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x00), + LEDC_INT_ENA_REG, 0, + (LEDC_DUTY_CHNG_END_CH0_INT_ENA_M | LEDC_DUTY_CHNG_END_CH1_INT_ENA_M | LEDC_DUTY_CHNG_END_CH2_INT_ENA_M | LEDC_DUTY_CHNG_END_CH3_INT_ENA_M | LEDC_DUTY_CHNG_END_CH4_INT_ENA_M | LEDC_DUTY_CHNG_END_CH5_INT_ENA_M), 0, 1), + .owner = LEDC_RETENTION_ENTRY }, + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x01), + LEDC_COMMON_RETENTION_REGS_BASE, LEDC_COMMON_RETENTION_REGS_BASE, + LEDC_COMMON_RETENTION_REGS_CNT, 0, 0, + ledc_common_regs_map[0], ledc_common_regs_map[1], + ledc_common_regs_map[2], ledc_common_regs_map[3]), + .owner = LEDC_RETENTION_ENTRY }, +}; + +#define LEDC_TIMER_RETENTION_ENTRIES(timer) { \ + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_CONF_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_TIMER##timer##_CMP_REG, LEDC_TIMER##timer##_CMP_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_PARA_UP, \ + LEDC_TIMER##timer##_PARA_UP_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +#define LEDC_CHANNEL_RETENTION_REGS_CNT 2 +static const uint32_t ledc_channel_regs_map[4] = {0x3, 0x0, 0x0, 0x0}; +static const uint32_t ledc_channel_gamma_regs_map[4] = {0xffff, 0x0, 0x0, 0x0}; +#define LEDC_CHANNEL_RETENTION_ENTRIES(chan) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_CH##chan##_CONF0_REG, LEDC_CH##chan##_CONF0_REG, \ + LEDC_CHANNEL_RETENTION_REGS_CNT, 0, 0, \ + ledc_channel_regs_map[0], ledc_channel_regs_map[1], \ + ledc_channel_regs_map[2], ledc_channel_regs_map[3]), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_CH##chan##_DUTY_R_REG, LEDC_CH##chan##_DUTY_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_CH##chan##_CONF1_REG, LEDC_DUTY_START_CH##chan, \ + LEDC_DUTY_START_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x03), \ + LEDC_CH##chan##_CONF0_REG, LEDC_PARA_UP_CH##chan, \ + LEDC_PARA_UP_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x04), \ + LEDC_CH##chan##_GAMMA_CONF_REG, LEDC_CH##chan##_GAMMA_CONF_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [5] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x05), \ + LEDC_CH##chan##_GAMMA_RANGE0_REG, LEDC_CH##chan##_GAMMA_RANGE0_REG, \ + SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX, 0, 0, \ + ledc_channel_gamma_regs_map[0], ledc_channel_gamma_regs_map[1], \ + ledc_channel_gamma_regs_map[2], ledc_channel_gamma_regs_map[3]), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +static const regdma_entries_config_t ledc_timer0_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_timer1_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_timer2_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_timer3_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(3); + +static const regdma_entries_config_t ledc_channel0_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_channel1_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_channel2_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_channel3_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(3); +static const regdma_entries_config_t ledc_channel4_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(4); +static const regdma_entries_config_t ledc_channel5_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(5); + +const ledc_reg_retention_info_t ledc_reg_retention_info = { + .common = { + .regdma_entry_array = ledc_common_regdma_entries, + .array_size = ARRAY_SIZE(ledc_common_regdma_entries), + }, + .timer[0] = { + .regdma_entry_array = ledc_timer0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer0_regdma_entries), + }, + .timer[1] = { + .regdma_entry_array = ledc_timer1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer1_regdma_entries), + }, + .timer[2] = { + .regdma_entry_array = ledc_timer2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer2_regdma_entries), + }, + .timer[3] = { + .regdma_entry_array = ledc_timer3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer3_regdma_entries), + }, + .channel[0] = { + .regdma_entry_array = ledc_channel0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel0_regdma_entries), + }, + .channel[1] = { + .regdma_entry_array = ledc_channel1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel1_regdma_entries), + }, + .channel[2] = { + .regdma_entry_array = ledc_channel2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel2_regdma_entries), + }, + .channel[3] = { + .regdma_entry_array = ledc_channel3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel3_regdma_entries), + }, + .channel[4] = { + .regdma_entry_array = ledc_channel4_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel4_regdma_entries), + }, + .channel[5] = { + .regdma_entry_array = ledc_channel5_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel5_regdma_entries), + }, + .module_id = SLEEP_RETENTION_MODULE_LEDC, +}; diff --git a/components/soc/esp32c5/parlio_periph.c b/components/soc/esp32c5/parlio_periph.c index 142e461cf17b..bd17bfceb119 100644 --- a/components/soc/esp32c5/parlio_periph.c +++ b/components/soc/esp32c5/parlio_periph.c @@ -48,3 +48,31 @@ const parlio_signal_conn_t parlio_periph_signals = { }, }, }; + +/** + * PARLIO Registers to be saved during sleep retention + * - Tx Configuration registers, e.g.: PARL_IO_TX_DATA_CFG_REG, PARL_IO_TX_GENRL_CFG_REG + * - Rx Configuration registers, e.g.: PARL_IO_RX_MODE_CFG_REG, PARL_IO_RX_DATA_CFG_REG, PARL_IO_RX_GENRL_CFG_REG + * - CLK Configuration registers, e.g.: PARL_IO_RX_CLK_CFG_REG, PARL_IO_TX_CLK_CFG_REG + * - Interrupt enable registers, e.g.: PARL_IO_INT_ENA_REG +*/ +#define PARLIO_RETENTION_REGS_CNT 8 +#define PARLIO_RETENTION_REGS_BASE (DR_REG_PARL_IO_BASE + 0x0) +static const uint32_t parlio_regs_map[4] = {0x60457, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t parlio_regs_retention[] = { + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PARLIO_LINK(0x00), \ + PARLIO_RETENTION_REGS_BASE, PARLIO_RETENTION_REGS_BASE, \ + PARLIO_RETENTION_REGS_CNT, 0, 0, \ + parlio_regs_map[0], parlio_regs_map[1], \ + parlio_regs_map[2], parlio_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; +const parlio_reg_retention_info_t parlio_reg_retention_info[SOC_PARLIO_GROUPS] = { + [0] = { + .regdma_entry_array = parlio_regs_retention, + .array_size = ARRAY_SIZE(parlio_regs_retention), + .retention_module = SLEEP_RETENTION_MODULE_PARLIO0 + }, +}; diff --git a/components/soc/esp32c5/pcnt_periph.c b/components/soc/esp32c5/pcnt_periph.c index 162db5aa27b3..c96644dae1d6 100644 --- a/components/soc/esp32c5/pcnt_periph.c +++ b/components/soc/esp32c5/pcnt_periph.c @@ -6,6 +6,7 @@ #include "soc/pcnt_periph.h" #include "soc/gpio_sig_map.h" +#include "soc/pcnt_reg.h" const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { @@ -68,3 +69,31 @@ const pcnt_signal_conn_t pcnt_periph_signals = { } } }; + +/** + * PCNT Registers to be saved during sleep retention + * - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG... + * - Step Configuration registers, e.g.: PCNT_U0_CHANGE_CONF_REG, PCNT_U1_CHANGE_CONF_REG, PCNT_U2_CHANGE_CONF_REG, PCNT_U3_CHANGE_CONF_REG + * - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG +*/ +#define PCNT_RETENTION_REGS_CNT 18 +#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0) +static const uint32_t pcnt_regs_map[4] = {0x1f040fff, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t pcnt_regs_retention[] = { + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \ + PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \ + PCNT_RETENTION_REGS_CNT, 0, 0, \ + pcnt_regs_map[0], pcnt_regs_map[1], \ + pcnt_regs_map[2], pcnt_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = { + [0] = { + .regdma_entry_array = pcnt_regs_retention, + .array_size = ARRAY_SIZE(pcnt_regs_retention), + .retention_module = SLEEP_RETENTION_MODULE_PCNT0 + }, +}; diff --git a/components/soc/esp32c5/register/soc/.gitkeep b/components/soc/esp32c5/register/soc/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/soc/esp32c5/include/soc/aes_reg.h b/components/soc/esp32c5/register/soc/aes_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/aes_reg.h rename to components/soc/esp32c5/register/soc/aes_reg.h diff --git a/components/soc/esp32c5/include/soc/aes_struct.h b/components/soc/esp32c5/register/soc/aes_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/aes_struct.h rename to components/soc/esp32c5/register/soc/aes_struct.h diff --git a/components/soc/esp32c5/include/soc/ahb_dma_reg.h b/components/soc/esp32c5/register/soc/ahb_dma_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/ahb_dma_reg.h rename to components/soc/esp32c5/register/soc/ahb_dma_reg.h diff --git a/components/soc/esp32c5/include/soc/ahb_dma_struct.h b/components/soc/esp32c5/register/soc/ahb_dma_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/ahb_dma_struct.h rename to components/soc/esp32c5/register/soc/ahb_dma_struct.h diff --git a/components/soc/esp32c5/include/soc/apb_saradc_reg.h b/components/soc/esp32c5/register/soc/apb_saradc_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/apb_saradc_reg.h rename to components/soc/esp32c5/register/soc/apb_saradc_reg.h diff --git a/components/soc/esp32c5/include/soc/apb_saradc_struct.h b/components/soc/esp32c5/register/soc/apb_saradc_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/apb_saradc_struct.h rename to components/soc/esp32c5/register/soc/apb_saradc_struct.h diff --git a/components/soc/esp32c5/include/soc/assist_debug_reg.h b/components/soc/esp32c5/register/soc/assist_debug_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/assist_debug_reg.h rename to components/soc/esp32c5/register/soc/assist_debug_reg.h diff --git a/components/soc/esp32c5/include/soc/assist_debug_struct.h b/components/soc/esp32c5/register/soc/assist_debug_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/assist_debug_struct.h rename to components/soc/esp32c5/register/soc/assist_debug_struct.h diff --git a/components/soc/esp32c5/include/soc/bitscrambler_reg.h b/components/soc/esp32c5/register/soc/bitscrambler_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/bitscrambler_reg.h rename to components/soc/esp32c5/register/soc/bitscrambler_reg.h diff --git a/components/soc/esp32c5/include/soc/bitscrambler_struct.h b/components/soc/esp32c5/register/soc/bitscrambler_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/bitscrambler_struct.h rename to components/soc/esp32c5/register/soc/bitscrambler_struct.h diff --git a/components/soc/esp32c5/include/soc/cache_reg.h b/components/soc/esp32c5/register/soc/cache_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/cache_reg.h rename to components/soc/esp32c5/register/soc/cache_reg.h diff --git a/components/soc/esp32c5/include/soc/cache_struct.h b/components/soc/esp32c5/register/soc/cache_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/cache_struct.h rename to components/soc/esp32c5/register/soc/cache_struct.h diff --git a/components/soc/esp32c5/include/soc/ds_reg.h b/components/soc/esp32c5/register/soc/ds_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/ds_reg.h rename to components/soc/esp32c5/register/soc/ds_reg.h diff --git a/components/soc/esp32c5/include/soc/ds_struct.h b/components/soc/esp32c5/register/soc/ds_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/ds_struct.h rename to components/soc/esp32c5/register/soc/ds_struct.h diff --git a/components/soc/esp32c5/include/soc/ecc_mult_reg.h b/components/soc/esp32c5/register/soc/ecc_mult_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/ecc_mult_reg.h rename to components/soc/esp32c5/register/soc/ecc_mult_reg.h diff --git a/components/soc/esp32c5/include/soc/ecc_mult_struct.h b/components/soc/esp32c5/register/soc/ecc_mult_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/ecc_mult_struct.h rename to components/soc/esp32c5/register/soc/ecc_mult_struct.h diff --git a/components/soc/esp32c5/include/soc/ecdsa_reg.h b/components/soc/esp32c5/register/soc/ecdsa_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/ecdsa_reg.h rename to components/soc/esp32c5/register/soc/ecdsa_reg.h diff --git a/components/soc/esp32c5/include/soc/ecdsa_struct.h b/components/soc/esp32c5/register/soc/ecdsa_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/ecdsa_struct.h rename to components/soc/esp32c5/register/soc/ecdsa_struct.h diff --git a/components/soc/esp32c5/include/soc/efuse_reg.h b/components/soc/esp32c5/register/soc/efuse_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/efuse_reg.h rename to components/soc/esp32c5/register/soc/efuse_reg.h diff --git a/components/soc/esp32c5/include/soc/efuse_struct.h b/components/soc/esp32c5/register/soc/efuse_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/efuse_struct.h rename to components/soc/esp32c5/register/soc/efuse_struct.h diff --git a/components/soc/esp32c5/include/soc/gpio_reg.h b/components/soc/esp32c5/register/soc/gpio_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/gpio_reg.h rename to components/soc/esp32c5/register/soc/gpio_reg.h diff --git a/components/soc/esp32c5/include/soc/gpio_struct.h b/components/soc/esp32c5/register/soc/gpio_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/gpio_struct.h rename to components/soc/esp32c5/register/soc/gpio_struct.h diff --git a/components/soc/esp32c5/include/soc/hmac_reg.h b/components/soc/esp32c5/register/soc/hmac_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/hmac_reg.h rename to components/soc/esp32c5/register/soc/hmac_reg.h diff --git a/components/soc/esp32c5/include/soc/hmac_struct.h b/components/soc/esp32c5/register/soc/hmac_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/hmac_struct.h rename to components/soc/esp32c5/register/soc/hmac_struct.h diff --git a/components/soc/esp32c5/include/soc/hp_apm_reg.h b/components/soc/esp32c5/register/soc/hp_apm_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/hp_apm_reg.h rename to components/soc/esp32c5/register/soc/hp_apm_reg.h diff --git a/components/soc/esp32c5/include/soc/hp_apm_struct.h b/components/soc/esp32c5/register/soc/hp_apm_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/hp_apm_struct.h rename to components/soc/esp32c5/register/soc/hp_apm_struct.h diff --git a/components/soc/esp32c5/include/soc/hp_system_reg.h b/components/soc/esp32c5/register/soc/hp_system_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/hp_system_reg.h rename to components/soc/esp32c5/register/soc/hp_system_reg.h diff --git a/components/soc/esp32c5/include/soc/hp_system_struct.h b/components/soc/esp32c5/register/soc/hp_system_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/hp_system_struct.h rename to components/soc/esp32c5/register/soc/hp_system_struct.h diff --git a/components/soc/esp32c5/include/soc/huk_reg.h b/components/soc/esp32c5/register/soc/huk_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/huk_reg.h rename to components/soc/esp32c5/register/soc/huk_reg.h diff --git a/components/soc/esp32c5/include/soc/huk_struct.h b/components/soc/esp32c5/register/soc/huk_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/huk_struct.h rename to components/soc/esp32c5/register/soc/huk_struct.h diff --git a/components/soc/esp32c5/include/soc/i2c_ana_mst_reg.h b/components/soc/esp32c5/register/soc/i2c_ana_mst_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/i2c_ana_mst_reg.h rename to components/soc/esp32c5/register/soc/i2c_ana_mst_reg.h diff --git a/components/soc/esp32c5/include/soc/i2c_reg.h b/components/soc/esp32c5/register/soc/i2c_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/i2c_reg.h rename to components/soc/esp32c5/register/soc/i2c_reg.h diff --git a/components/soc/esp32c5/include/soc/i2c_struct.h b/components/soc/esp32c5/register/soc/i2c_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/i2c_struct.h rename to components/soc/esp32c5/register/soc/i2c_struct.h diff --git a/components/soc/esp32c5/include/soc/i2s_reg.h b/components/soc/esp32c5/register/soc/i2s_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/i2s_reg.h rename to components/soc/esp32c5/register/soc/i2s_reg.h diff --git a/components/soc/esp32c5/include/soc/i2s_struct.h b/components/soc/esp32c5/register/soc/i2s_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/i2s_struct.h rename to components/soc/esp32c5/register/soc/i2s_struct.h diff --git a/components/soc/esp32c5/include/soc/ieee802154_reg.h b/components/soc/esp32c5/register/soc/ieee802154_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/ieee802154_reg.h rename to components/soc/esp32c5/register/soc/ieee802154_reg.h diff --git a/components/soc/esp32c5/include/soc/ieee802154_struct.h b/components/soc/esp32c5/register/soc/ieee802154_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/ieee802154_struct.h rename to components/soc/esp32c5/register/soc/ieee802154_struct.h diff --git a/components/soc/esp32c5/include/soc/interrupt_matrix_reg.h b/components/soc/esp32c5/register/soc/interrupt_matrix_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/interrupt_matrix_reg.h rename to components/soc/esp32c5/register/soc/interrupt_matrix_reg.h diff --git a/components/soc/esp32c5/include/soc/interrupt_matrix_struct.h b/components/soc/esp32c5/register/soc/interrupt_matrix_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/interrupt_matrix_struct.h rename to components/soc/esp32c5/register/soc/interrupt_matrix_struct.h diff --git a/components/soc/esp32c5/include/soc/intpri_reg.h b/components/soc/esp32c5/register/soc/intpri_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/intpri_reg.h rename to components/soc/esp32c5/register/soc/intpri_reg.h diff --git a/components/soc/esp32c5/include/soc/intpri_struct.h b/components/soc/esp32c5/register/soc/intpri_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/intpri_struct.h rename to components/soc/esp32c5/register/soc/intpri_struct.h diff --git a/components/soc/esp32c5/include/soc/io_mux_reg.h b/components/soc/esp32c5/register/soc/io_mux_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/io_mux_reg.h rename to components/soc/esp32c5/register/soc/io_mux_reg.h diff --git a/components/soc/esp32c5/include/soc/io_mux_struct.h b/components/soc/esp32c5/register/soc/io_mux_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/io_mux_struct.h rename to components/soc/esp32c5/register/soc/io_mux_struct.h diff --git a/components/soc/esp32c5/include/soc/keymng_reg.h b/components/soc/esp32c5/register/soc/keymng_reg.h similarity index 90% rename from components/soc/esp32c5/include/soc/keymng_reg.h rename to components/soc/esp32c5/register/soc/keymng_reg.h index 48324b814cb2..66ab3903733d 100644 --- a/components/soc/esp32c5/include/soc/keymng_reg.h +++ b/components/soc/esp32c5/register/soc/keymng_reg.h @@ -147,6 +147,22 @@ extern "C" { #define KEYMNG_USE_EFUSE_KEY_M (KEYMNG_USE_EFUSE_KEY_V << KEYMNG_USE_EFUSE_KEY_S) #define KEYMNG_USE_EFUSE_KEY_V 0x0000001FU #define KEYMNG_USE_EFUSE_KEY_S 0 + +/* KEYMNG_USE_EFUSE_KEY_ECDSA : R/W ;bitpos:[0] ;default: 1'd0 ; */ +/*description: Set this bit to choose efuse key instead of key manager deployed key for ecdsa.*/ +#define KEYMNG_USE_EFUSE_KEY_ECDSA (BIT(0)) +#define KEYMNG_USE_EFUSE_KEY_ECDSA_M ((KEYMNG_USE_EFUSE_KEY_ECDSA_V)<<(KEYMNG_USE_EFUSE_KEY_ECDSA_S)) +#define KEYMNG_USE_EFUSE_KEY_ECDSA_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_ECDSA_S 0 + +/* KEYMNG_USE_EFUSE_KEY_FLASH : R/W ;bitpos:[1] ;default: 1'd0 ; */ +/*description: Set this bit to choose efuse key instead of key manager deployed key for flash.*/ +#define KEYMNG_USE_EFUSE_KEY_FLASH (BIT(1)) +#define KEYMNG_USE_EFUSE_KEY_FLASH_M ((KEYMNG_USE_EFUSE_KEY_FLASH_V)<<(KEYMNG_USE_EFUSE_KEY_FLASH_S)) +#define KEYMNG_USE_EFUSE_KEY_FLASH_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_FLASH_S 1 + + /** KEYMNG_RND_SWITCH_CYCLE : R/W; bitpos: [9:5]; default: 15; * The core clock cycle number to sample one rng input data. Please set it bigger than * the clock cycle ratio: T_rng/T_km @@ -191,6 +207,23 @@ extern "C" { #define KEYMNG_USE_EFUSE_KEY_LOCK_M (KEYMNG_USE_EFUSE_KEY_LOCK_V << KEYMNG_USE_EFUSE_KEY_LOCK_S) #define KEYMNG_USE_EFUSE_KEY_LOCK_V 0x0000001FU #define KEYMNG_USE_EFUSE_KEY_LOCK_S 0 + +/* KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA : R/W1 ;bitpos:[0] ;default: 1'd0 ; */ +/*description: Write 1 to lock reg_use_efuse_key for esdsa*/ + +#define KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA (BIT(0)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_M ((KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_V)<<(KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_S)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_S 0 + +/* KEYMNG_USE_EFUSE_KEY_LOCK_FLASH : R/W1 ;bitpos:[1] ;default: 1'd0 ; */ +/*description: Write 1 to lock reg_use_efuse_key for FLASH*/ + +#define KEYMNG_USE_EFUSE_KEY_LOCK_FLASH (BIT(1)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_M ((KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_V)<<(KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_S)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_S 1 + /** KEYMNG_RND_SWITCH_CYCLE_LOCK : R/W1; bitpos: [5]; default: 0; * Write 1 to lock reg_rnd_switch_cycle. */ diff --git a/components/soc/esp32c5/include/soc/keymng_struct.h b/components/soc/esp32c5/register/soc/keymng_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/keymng_struct.h rename to components/soc/esp32c5/register/soc/keymng_struct.h diff --git a/components/soc/esp32c5/include/soc/ledc_reg.h b/components/soc/esp32c5/register/soc/ledc_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/ledc_reg.h rename to components/soc/esp32c5/register/soc/ledc_reg.h diff --git a/components/soc/esp32c5/include/soc/ledc_struct.h b/components/soc/esp32c5/register/soc/ledc_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/ledc_struct.h rename to components/soc/esp32c5/register/soc/ledc_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_analog_peri_reg.h b/components/soc/esp32c5/register/soc/lp_analog_peri_reg.h similarity index 97% rename from components/soc/esp32c5/include/soc/lp_analog_peri_reg.h rename to components/soc/esp32c5/register/soc/lp_analog_peri_reg.h index edc9199d436f..13fd8e80e160 100644 --- a/components/soc/esp32c5/include/soc/lp_analog_peri_reg.h +++ b/components/soc/esp32c5/register/soc/lp_analog_peri_reg.h @@ -129,6 +129,11 @@ extern "C" { #define LP_ANA_ANA_FIB_ENA_V 0xFFFFFFFFU #define LP_ANA_ANA_FIB_ENA_S 0 +#define LP_ANA_ANA_FIB_PWR_GLITCH_ENA 0x0000000FU +#define LP_ANA_ANA_FIB_PWR_GLITCH_ENA_M (LP_ANA_ANA_FIB_PWR_GLITCH_ENA_V << LP_ANA_ANA_FIB_PWR_GLITCH_ENA_S) +#define LP_ANA_ANA_FIB_PWR_GLITCH_ENA_V 0x0000000FU +#define LP_ANA_ANA_FIB_PWR_GLITCH_ENA_S 2 + /** LP_ANA_INT_RAW_REG register * interrpt raw register */ diff --git a/components/soc/esp32c5/include/soc/lp_analog_peri_struct.h b/components/soc/esp32c5/register/soc/lp_analog_peri_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_analog_peri_struct.h rename to components/soc/esp32c5/register/soc/lp_analog_peri_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_aon_reg.h b/components/soc/esp32c5/register/soc/lp_aon_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_aon_reg.h rename to components/soc/esp32c5/register/soc/lp_aon_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_aon_struct.h b/components/soc/esp32c5/register/soc/lp_aon_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_aon_struct.h rename to components/soc/esp32c5/register/soc/lp_aon_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_apm0_reg.h b/components/soc/esp32c5/register/soc/lp_apm0_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_apm0_reg.h rename to components/soc/esp32c5/register/soc/lp_apm0_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_apm0_struct.h b/components/soc/esp32c5/register/soc/lp_apm0_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_apm0_struct.h rename to components/soc/esp32c5/register/soc/lp_apm0_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_apm_reg.h b/components/soc/esp32c5/register/soc/lp_apm_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_apm_reg.h rename to components/soc/esp32c5/register/soc/lp_apm_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_apm_struct.h b/components/soc/esp32c5/register/soc/lp_apm_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_apm_struct.h rename to components/soc/esp32c5/register/soc/lp_apm_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_clkrst_reg.h b/components/soc/esp32c5/register/soc/lp_clkrst_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_clkrst_reg.h rename to components/soc/esp32c5/register/soc/lp_clkrst_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_clkrst_struct.h b/components/soc/esp32c5/register/soc/lp_clkrst_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_clkrst_struct.h rename to components/soc/esp32c5/register/soc/lp_clkrst_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_gpio_reg.h b/components/soc/esp32c5/register/soc/lp_gpio_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_gpio_reg.h rename to components/soc/esp32c5/register/soc/lp_gpio_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_gpio_struct.h b/components/soc/esp32c5/register/soc/lp_gpio_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_gpio_struct.h rename to components/soc/esp32c5/register/soc/lp_gpio_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_i2c_ana_mst_reg.h b/components/soc/esp32c5/register/soc/lp_i2c_ana_mst_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_i2c_ana_mst_reg.h rename to components/soc/esp32c5/register/soc/lp_i2c_ana_mst_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_i2c_ana_mst_struct.h b/components/soc/esp32c5/register/soc/lp_i2c_ana_mst_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_i2c_ana_mst_struct.h rename to components/soc/esp32c5/register/soc/lp_i2c_ana_mst_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_i2c_reg.h b/components/soc/esp32c5/register/soc/lp_i2c_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_i2c_reg.h rename to components/soc/esp32c5/register/soc/lp_i2c_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_i2c_struct.h b/components/soc/esp32c5/register/soc/lp_i2c_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_i2c_struct.h rename to components/soc/esp32c5/register/soc/lp_i2c_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_iomux_reg.h b/components/soc/esp32c5/register/soc/lp_iomux_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_iomux_reg.h rename to components/soc/esp32c5/register/soc/lp_iomux_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_iomux_struct.h b/components/soc/esp32c5/register/soc/lp_iomux_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_iomux_struct.h rename to components/soc/esp32c5/register/soc/lp_iomux_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_tee_reg.h b/components/soc/esp32c5/register/soc/lp_tee_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_tee_reg.h rename to components/soc/esp32c5/register/soc/lp_tee_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_tee_struct.h b/components/soc/esp32c5/register/soc/lp_tee_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_tee_struct.h rename to components/soc/esp32c5/register/soc/lp_tee_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_timer_reg.h b/components/soc/esp32c5/register/soc/lp_timer_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_timer_reg.h rename to components/soc/esp32c5/register/soc/lp_timer_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_timer_struct.h b/components/soc/esp32c5/register/soc/lp_timer_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_timer_struct.h rename to components/soc/esp32c5/register/soc/lp_timer_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_uart_reg.h b/components/soc/esp32c5/register/soc/lp_uart_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_uart_reg.h rename to components/soc/esp32c5/register/soc/lp_uart_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_uart_struct.h b/components/soc/esp32c5/register/soc/lp_uart_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_uart_struct.h rename to components/soc/esp32c5/register/soc/lp_uart_struct.h diff --git a/components/soc/esp32c5/include/soc/lp_wdt_reg.h b/components/soc/esp32c5/register/soc/lp_wdt_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_wdt_reg.h rename to components/soc/esp32c5/register/soc/lp_wdt_reg.h diff --git a/components/soc/esp32c5/include/soc/lp_wdt_struct.h b/components/soc/esp32c5/register/soc/lp_wdt_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lp_wdt_struct.h rename to components/soc/esp32c5/register/soc/lp_wdt_struct.h diff --git a/components/soc/esp32c5/include/soc/lpperi_reg.h b/components/soc/esp32c5/register/soc/lpperi_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/lpperi_reg.h rename to components/soc/esp32c5/register/soc/lpperi_reg.h diff --git a/components/soc/esp32c5/include/soc/lpperi_struct.h b/components/soc/esp32c5/register/soc/lpperi_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/lpperi_struct.h rename to components/soc/esp32c5/register/soc/lpperi_struct.h diff --git a/components/soc/esp32c5/include/soc/mcpwm_reg.h b/components/soc/esp32c5/register/soc/mcpwm_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/mcpwm_reg.h rename to components/soc/esp32c5/register/soc/mcpwm_reg.h diff --git a/components/soc/esp32c5/include/soc/mcpwm_struct.h b/components/soc/esp32c5/register/soc/mcpwm_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/mcpwm_struct.h rename to components/soc/esp32c5/register/soc/mcpwm_struct.h diff --git a/components/soc/esp32c5/include/soc/mem_monitor_reg.h b/components/soc/esp32c5/register/soc/mem_monitor_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/mem_monitor_reg.h rename to components/soc/esp32c5/register/soc/mem_monitor_reg.h diff --git a/components/soc/esp32c5/include/soc/mem_monitor_struct.h b/components/soc/esp32c5/register/soc/mem_monitor_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/mem_monitor_struct.h rename to components/soc/esp32c5/register/soc/mem_monitor_struct.h diff --git a/components/soc/esp32c5/include/soc/parl_io_reg.h b/components/soc/esp32c5/register/soc/parl_io_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/parl_io_reg.h rename to components/soc/esp32c5/register/soc/parl_io_reg.h diff --git a/components/soc/esp32c5/include/soc/parl_io_struct.h b/components/soc/esp32c5/register/soc/parl_io_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/parl_io_struct.h rename to components/soc/esp32c5/register/soc/parl_io_struct.h diff --git a/components/soc/esp32c5/include/soc/pau_reg.h b/components/soc/esp32c5/register/soc/pau_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/pau_reg.h rename to components/soc/esp32c5/register/soc/pau_reg.h diff --git a/components/soc/esp32c5/include/soc/pau_struct.h b/components/soc/esp32c5/register/soc/pau_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/pau_struct.h rename to components/soc/esp32c5/register/soc/pau_struct.h diff --git a/components/soc/esp32c5/include/soc/pcnt_reg.h b/components/soc/esp32c5/register/soc/pcnt_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/pcnt_reg.h rename to components/soc/esp32c5/register/soc/pcnt_reg.h diff --git a/components/soc/esp32c5/include/soc/pcnt_struct.h b/components/soc/esp32c5/register/soc/pcnt_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/pcnt_struct.h rename to components/soc/esp32c5/register/soc/pcnt_struct.h diff --git a/components/soc/esp32c5/include/soc/pcr_reg.h b/components/soc/esp32c5/register/soc/pcr_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/pcr_reg.h rename to components/soc/esp32c5/register/soc/pcr_reg.h diff --git a/components/soc/esp32c5/include/soc/pcr_struct.h b/components/soc/esp32c5/register/soc/pcr_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/pcr_struct.h rename to components/soc/esp32c5/register/soc/pcr_struct.h diff --git a/components/soc/esp32c5/include/soc/pmu_reg.h b/components/soc/esp32c5/register/soc/pmu_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/pmu_reg.h rename to components/soc/esp32c5/register/soc/pmu_reg.h diff --git a/components/soc/esp32c5/include/soc/pmu_struct.h b/components/soc/esp32c5/register/soc/pmu_struct.h similarity index 99% rename from components/soc/esp32c5/include/soc/pmu_struct.h rename to components/soc/esp32c5/register/soc/pmu_struct.h index 67f6269fc32f..ad7fc03d016e 100644 --- a/components/soc/esp32c5/include/soc/pmu_struct.h +++ b/components/soc/esp32c5/register/soc/pmu_struct.h @@ -11,7 +11,7 @@ extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #include "soc/pmu_reg.h" typedef union { diff --git a/components/soc/esp32c5/include/soc/pvt_reg.h b/components/soc/esp32c5/register/soc/pvt_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/pvt_reg.h rename to components/soc/esp32c5/register/soc/pvt_reg.h diff --git a/components/soc/esp32c5/include/soc/pvt_struct.h b/components/soc/esp32c5/register/soc/pvt_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/pvt_struct.h rename to components/soc/esp32c5/register/soc/pvt_struct.h diff --git a/components/soc/esp32c5/include/soc/reg_base.h b/components/soc/esp32c5/register/soc/reg_base.h similarity index 98% rename from components/soc/esp32c5/include/soc/reg_base.h rename to components/soc/esp32c5/register/soc/reg_base.h index 6197746bbd7a..b2516ec71caa 100644 --- a/components/soc/esp32c5/include/soc/reg_base.h +++ b/components/soc/esp32c5/register/soc/reg_base.h @@ -40,7 +40,7 @@ * */ #define DR_REG_AHB_DMA_BASE 0x60080000 -#define DR_REG_GPSPI2_BASE 0x60081000 +#define DR_REG_SPI2_BASE 0x60081000 #define DR_REG_BITSCRAMBLER_BASE 0x60082000 #define DR_REG_KEYMNG_BASE 0x60087000 #define DR_REG_AES_BASE 0x60088000 diff --git a/components/soc/esp32c5/include/soc/rmt_reg.h b/components/soc/esp32c5/register/soc/rmt_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/rmt_reg.h rename to components/soc/esp32c5/register/soc/rmt_reg.h diff --git a/components/soc/esp32c5/include/soc/rmt_struct.h b/components/soc/esp32c5/register/soc/rmt_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/rmt_struct.h rename to components/soc/esp32c5/register/soc/rmt_struct.h diff --git a/components/soc/esp32c5/include/soc/rsa_reg.h b/components/soc/esp32c5/register/soc/rsa_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/rsa_reg.h rename to components/soc/esp32c5/register/soc/rsa_reg.h diff --git a/components/soc/esp32c5/include/soc/rsa_struct.h b/components/soc/esp32c5/register/soc/rsa_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/rsa_struct.h rename to components/soc/esp32c5/register/soc/rsa_struct.h diff --git a/components/soc/esp32c5/include/soc/sha_reg.h b/components/soc/esp32c5/register/soc/sha_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/sha_reg.h rename to components/soc/esp32c5/register/soc/sha_reg.h diff --git a/components/soc/esp32c5/include/soc/sha_struct.h b/components/soc/esp32c5/register/soc/sha_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/sha_struct.h rename to components/soc/esp32c5/register/soc/sha_struct.h diff --git a/components/soc/esp32c5/include/soc/soc_etm_reg.h b/components/soc/esp32c5/register/soc/soc_etm_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/soc_etm_reg.h rename to components/soc/esp32c5/register/soc/soc_etm_reg.h diff --git a/components/soc/esp32c5/include/soc/soc_etm_struct.h b/components/soc/esp32c5/register/soc/soc_etm_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/soc_etm_struct.h rename to components/soc/esp32c5/register/soc/soc_etm_struct.h diff --git a/components/soc/esp32c5/include/soc/spi1_mem_reg.h b/components/soc/esp32c5/register/soc/spi1_mem_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/spi1_mem_reg.h rename to components/soc/esp32c5/register/soc/spi1_mem_reg.h diff --git a/components/soc/esp32c5/include/soc/spi1_mem_struct.h b/components/soc/esp32c5/register/soc/spi1_mem_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/spi1_mem_struct.h rename to components/soc/esp32c5/register/soc/spi1_mem_struct.h diff --git a/components/soc/esp32c5/include/soc/spi_mem_c_reg.h b/components/soc/esp32c5/register/soc/spi_mem_c_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/spi_mem_c_reg.h rename to components/soc/esp32c5/register/soc/spi_mem_c_reg.h diff --git a/components/soc/esp32c5/include/soc/spi_mem_c_struct.h b/components/soc/esp32c5/register/soc/spi_mem_c_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/spi_mem_c_struct.h rename to components/soc/esp32c5/register/soc/spi_mem_c_struct.h diff --git a/components/soc/esp32c5/include/soc/spi_reg.h b/components/soc/esp32c5/register/soc/spi_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/spi_reg.h rename to components/soc/esp32c5/register/soc/spi_reg.h diff --git a/components/soc/esp32c5/include/soc/spi_struct.h b/components/soc/esp32c5/register/soc/spi_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/spi_struct.h rename to components/soc/esp32c5/register/soc/spi_struct.h diff --git a/components/soc/esp32c5/include/soc/systimer_reg.h b/components/soc/esp32c5/register/soc/systimer_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/systimer_reg.h rename to components/soc/esp32c5/register/soc/systimer_reg.h diff --git a/components/soc/esp32c5/include/soc/systimer_struct.h b/components/soc/esp32c5/register/soc/systimer_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/systimer_struct.h rename to components/soc/esp32c5/register/soc/systimer_struct.h diff --git a/components/soc/esp32c5/include/soc/tee_reg.h b/components/soc/esp32c5/register/soc/tee_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/tee_reg.h rename to components/soc/esp32c5/register/soc/tee_reg.h diff --git a/components/soc/esp32c5/include/soc/tee_struct.h b/components/soc/esp32c5/register/soc/tee_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/tee_struct.h rename to components/soc/esp32c5/register/soc/tee_struct.h diff --git a/components/soc/esp32c5/include/soc/timer_group_reg.h b/components/soc/esp32c5/register/soc/timer_group_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/timer_group_reg.h rename to components/soc/esp32c5/register/soc/timer_group_reg.h diff --git a/components/soc/esp32c5/include/soc/timer_group_struct.h b/components/soc/esp32c5/register/soc/timer_group_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/timer_group_struct.h rename to components/soc/esp32c5/register/soc/timer_group_struct.h diff --git a/components/soc/esp32c5/include/soc/trace_reg.h b/components/soc/esp32c5/register/soc/trace_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/trace_reg.h rename to components/soc/esp32c5/register/soc/trace_reg.h diff --git a/components/soc/esp32c5/include/soc/trace_struct.h b/components/soc/esp32c5/register/soc/trace_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/trace_struct.h rename to components/soc/esp32c5/register/soc/trace_struct.h diff --git a/components/soc/esp32c5/include/soc/twaifd_reg.h b/components/soc/esp32c5/register/soc/twaifd_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/twaifd_reg.h rename to components/soc/esp32c5/register/soc/twaifd_reg.h diff --git a/components/soc/esp32c5/include/soc/twaifd_struct.h b/components/soc/esp32c5/register/soc/twaifd_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/twaifd_struct.h rename to components/soc/esp32c5/register/soc/twaifd_struct.h diff --git a/components/soc/esp32c5/include/soc/uart_reg.h b/components/soc/esp32c5/register/soc/uart_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/uart_reg.h rename to components/soc/esp32c5/register/soc/uart_reg.h diff --git a/components/soc/esp32c5/include/soc/uart_struct.h b/components/soc/esp32c5/register/soc/uart_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/uart_struct.h rename to components/soc/esp32c5/register/soc/uart_struct.h diff --git a/components/soc/esp32c5/include/soc/uhci_reg.h b/components/soc/esp32c5/register/soc/uhci_reg.h similarity index 100% rename from components/soc/esp32c5/include/soc/uhci_reg.h rename to components/soc/esp32c5/register/soc/uhci_reg.h diff --git a/components/soc/esp32c5/include/soc/uhci_struct.h b/components/soc/esp32c5/register/soc/uhci_struct.h similarity index 100% rename from components/soc/esp32c5/include/soc/uhci_struct.h rename to components/soc/esp32c5/register/soc/uhci_struct.h diff --git a/components/soc/esp32c5/include/soc/usb_serial_jtag_reg.h b/components/soc/esp32c5/register/soc/usb_serial_jtag_reg.h similarity index 99% rename from components/soc/esp32c5/include/soc/usb_serial_jtag_reg.h rename to components/soc/esp32c5/register/soc/usb_serial_jtag_reg.h index 5a8b1d4a06ff..255d08ed4bb9 100644 --- a/components/soc/esp32c5/include/soc/usb_serial_jtag_reg.h +++ b/components/soc/esp32c5/register/soc/usb_serial_jtag_reg.h @@ -653,7 +653,7 @@ extern "C" { #define USB_SERIAL_JTAG_TEST_ENABLE_V 0x00000001U #define USB_SERIAL_JTAG_TEST_ENABLE_S 0 /** USB_SERIAL_JTAG_TEST_USB_OE : R/W; bitpos: [1]; default: 0; - * USB pad one in test + * USB pad oen in test */ #define USB_SERIAL_JTAG_TEST_USB_OE (BIT(1)) #define USB_SERIAL_JTAG_TEST_USB_OE_M (USB_SERIAL_JTAG_TEST_USB_OE_V << USB_SERIAL_JTAG_TEST_USB_OE_S) diff --git a/components/soc/esp32c5/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32c5/register/soc/usb_serial_jtag_struct.h similarity index 99% rename from components/soc/esp32c5/include/soc/usb_serial_jtag_struct.h rename to components/soc/esp32c5/register/soc/usb_serial_jtag_struct.h index 21e8d68b2099..603db37ff623 100644 --- a/components/soc/esp32c5/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32c5/register/soc/usb_serial_jtag_struct.h @@ -130,7 +130,7 @@ typedef union { */ uint32_t test_enable:1; /** test_usb_oe : R/W; bitpos: [1]; default: 0; - * USB pad one in test + * USB pad oen in test */ uint32_t test_usb_oe:1; /** test_tx_dp : R/W; bitpos: [2]; default: 0; diff --git a/components/soc/esp32c5/rmt_periph.c b/components/soc/esp32c5/rmt_periph.c index 87c00ebd260c..aa92c87aea32 100644 --- a/components/soc/esp32c5/rmt_periph.c +++ b/components/soc/esp32c5/rmt_periph.c @@ -60,6 +60,7 @@ static const regdma_entries_config_t rmt_regdma_entries[] = { const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = { [0] = { + .module = SLEEP_RETENTION_MODULE_RMT0, .regdma_entry_array = rmt_regdma_entries, .array_size = ARRAY_SIZE(rmt_regdma_entries) }, diff --git a/components/soc/esp32c5/spi_periph.c b/components/soc/esp32c5/spi_periph.c index dc15ae60eaa1..67fa9fdcb95d 100644 --- a/components/soc/esp32c5/spi_periph.c +++ b/components/soc/esp32c5/spi_periph.c @@ -13,29 +13,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { { // MSPI has dedicated iomux pins - .spiclk_out = -1, - .spiclk_in = -1, - .spid_out = -1, - .spiq_out = -1, - .spiwp_out = -1, - .spihd_out = -1, - .spid_in = -1, - .spiq_in = -1, - .spiwp_in = -1, - .spihd_in = -1, - .spics_out = {-1}, - .spics_in = -1, - .spiclk_iomux_pin = -1, - .spid_iomux_pin = -1, - .spiq_iomux_pin = -1, - .spiwp_iomux_pin = -1, - .spihd_iomux_pin = -1, - .spics0_iomux_pin = -1, - .irq = -1, - .irq_dma = -1, - .module = -1, - .hw = NULL, - .func = -1, }, { .spiclk_out = FSPICLK_OUT_IDX, .spiclk_in = FSPICLK_IN_IDX, @@ -57,8 +34,50 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, .irq = ETS_GPSPI2_INTR_SOURCE, .irq_dma = -1, - .module = -1, .hw = &GPSPI2, .func = SPI2_FUNC_NUM, }, }; + +/** + * Backup registers in Light sleep: (total cnt 12) + * + * cmd + * addr + * ctrl + * clock + * user + * user1 + * user2 + * ms_dlen + * misc + * dma_conf + * dma_int_ena + * slave + */ +#define SPI_RETENTION_REGS_CNT 12 +static const uint32_t spi_regs_map[4] = {0x31ff, 0x1000000, 0x0, 0x0}; +#define SPI_REG_RETENTION_ENTRIES(num) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GPSPI_LINK(0), \ + REG_SPI_BASE(num), REG_SPI_BASE(num), \ + SPI_RETENTION_REGS_CNT, 0, 0, \ + spi_regs_map[0], spi_regs_map[1], \ + spi_regs_map[2], spi_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + /* Additional interrupt setting is required by idf SPI drivers after register recovered */ \ + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_GPSPI_LINK(1), \ + SPI_DMA_INT_SET_REG(num), \ + SPI_TRANS_DONE_INT_SET | SPI_DMA_SEG_TRANS_DONE_INT_SET , \ + UINT32_MAX, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t spi2_regs_retention[] = SPI_REG_RETENTION_ENTRIES(2); // '2' for GPSPI2 + +const spi_reg_retention_info_t spi_reg_retention_info[SOC_SPI_PERIPH_NUM - 1] = { // '-1' to except mspi + { + .module_id = SLEEP_RETENTION_MODULE_GPSPI2, + .entry_array = spi2_regs_retention, + .array_size = ARRAY_SIZE(spi2_regs_retention), + }, +}; diff --git a/components/soc/esp32c5/temperature_sensor_periph.c b/components/soc/esp32c5/temperature_sensor_periph.c index b0b6cfef7eb7..45410347bda7 100644 --- a/components/soc/esp32c5/temperature_sensor_periph.c +++ b/components/soc/esp32c5/temperature_sensor_periph.c @@ -4,7 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" +#include "soc/apb_saradc_reg.h" const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ @@ -14,3 +17,24 @@ const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_S { 1, 11, -30, 50, 2}, { 2, 10, -40, 20, 3}, }; + +// Temperature sensor sleep retention entries +// Temperature sensor registers require set the reg_update bit to make the configuration take effect + +/* Temperature sensor Registers Context + Include: APB_SARADC_INT_ENA_REG / + APB_SARADC_APB_TSENS_CTRL_REG / APB_SARADC_TSENS_CTRL2_REG / APB_TSENS_WAKE_REG / APB_TSENS_SAMPLE_REG +*/ +#define TEMPERATURE_SENSOR_RETENTION_REGS_CNT 5 +#define TEMPERATURE_SENSOR_RETENTION_MAP_BASE APB_SARADC_INT_ENA_REG +static const uint32_t temperature_sensor_regs_map[4] = {0x6c1, 0, 0, 0}; +static const regdma_entries_config_t temperature_sensor_regs_entries[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TSENS_LINK(0x00), TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_REGS_CNT, 0, 0, temperature_sensor_regs_map[0], temperature_sensor_regs_map[1], temperature_sensor_regs_map[2], temperature_sensor_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const temperature_sensor_reg_ctx_link_t temperature_sensor_regs_retention = { + .link_list = temperature_sensor_regs_entries, + .link_num = ARRAY_SIZE(temperature_sensor_regs_entries), + .module_id = SLEEP_RETENTION_MODULE_TEMP_SENSOR, +}; diff --git a/components/soc/esp32c5/uart_periph.c b/components/soc/esp32c5/uart_periph.c index 733cde884b91..b98467fc4b9c 100644 --- a/components/soc/esp32c5/uart_periph.c +++ b/components/soc/esp32c5/uart_periph.c @@ -150,10 +150,12 @@ static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTI const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { [0] = { + .module = SLEEP_RETENTION_MODULE_UART0, .regdma_entry_array = uart0_regdma_entries, .array_size = ARRAY_SIZE(uart0_regdma_entries), }, [1] = { + .module = SLEEP_RETENTION_MODULE_UART1, .regdma_entry_array = uart1_regdma_entries, .array_size = ARRAY_SIZE(uart1_regdma_entries), }, diff --git a/components/soc/esp32c6/etm_periph.c b/components/soc/esp32c6/etm_periph.c new file mode 100644 index 000000000000..7b268c443a55 --- /dev/null +++ b/components/soc/esp32c6/etm_periph.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/etm_periph.h" +#include "soc/soc_etm_reg.h" + +/** + * ETM Registers to be saved during sleep retention + * - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG +*/ +#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1) + +static const regdma_entries_config_t etm_regdma_entries[] = { + // backup stage: save the status of enabled channels + // restore stage: store the enabled channels + [0] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00), + SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, + [1] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01), + SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [2] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02), + SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, +}; + +const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { + [0] = { + .module = SLEEP_RETENTION_MODULE_ETM0, + .regdma_entry_array = etm_regdma_entries, + .array_size = ARRAY_SIZE(etm_regdma_entries) + }, +}; diff --git a/components/soc/esp32c6/i2c_periph.c b/components/soc/esp32c6/i2c_periph.c index 217714447441..c2a39d3c9c66 100644 --- a/components/soc/esp32c6/i2c_periph.c +++ b/components/soc/esp32c6/i2c_periph.c @@ -50,7 +50,7 @@ static const regdma_entries_config_t i2c0_regs_retention[] = { [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(0), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \ .owner = ENTRY(0) | ENTRY(2) }, \ [2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(0), 0x0, I2C_FSM_RST_M, 1, 0), \ - .owner = ENTRY(0) | ENTRY(2) }, \ + .owner = ENTRY(0) | ENTRY(2) }, \ [3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(0), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \ .owner = ENTRY(0) | ENTRY(2) }, \ [4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(0), 0x0, I2C_CONF_UPGATE_M, 1, 0), \ @@ -58,5 +58,5 @@ static const regdma_entries_config_t i2c0_regs_retention[] = { }; const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM] = { - {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention)}, + {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention), SLEEP_RETENTION_MODULE_I2C0}, }; diff --git a/components/soc/esp32c6/i2s_periph.c b/components/soc/esp32c6/i2s_periph.c index cb0a6a14ff6e..fb1cea5bb1fa 100644 --- a/components/soc/esp32c6/i2s_periph.c +++ b/components/soc/esp32c6/i2s_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/i2s_periph.h" +#include "soc/i2s_reg.h" #include "soc/gpio_sig_map.h" /* @@ -29,7 +30,44 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_out_sigs[1] = I2SO_SD1_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, - .irq = ETS_I2S1_INTR_SOURCE, - .module = PERIPH_I2S1_MODULE, + .irq = ETS_I2S0_INTR_SOURCE, } }; + +/** + * I2S Registers to be saved during sleep retention + * - I2S_RX_CONF_REG + * - I2S_TX_CONF_REG + * - I2S_RX_CONF1_REG + * - I2S_TX_CONF1_REG + * - I2S_TX_PCM2PDM_CONF_REG + * - I2S_TX_PCM2PDM_CONF1_REG + * - I2S_RX_TDM_CTRL_REG + * - I2S_TX_TDM_CTRL_REG + * - I2S_RXEOF_NUM_REG + * - I2S_ETM_CONF_REG +*/ +#define I2S_RETENTION_REGS_CNT 10 +#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG(i) +static const uint32_t i2s_regs_map[4] = {0x12330f, 0x0, 0x0, 0x0}; +#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \ + /* Save/restore the register values */ \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \ + REGDMA_I2S_LINK(0x00), \ + I2S_RETENTION_REGS_BASE(i2s_port), \ + I2S_RETENTION_REGS_BASE(i2s_port), \ + I2S_RETENTION_REGS_CNT, 0, 0, \ + i2s_regs_map[0], i2s_regs_map[1], \ + i2s_regs_map[2], i2s_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2)}, \ +}; + +static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(0); + +const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = { + [0] = { + .retention_module = SLEEP_RETENTION_MODULE_I2S0, + .entry_array = i2s0_regs_retention, + .array_size = ARRAY_SIZE(i2s0_regs_retention) + }, +}; diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 47dc43d9d5be..a7626d57a7d5 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -459,6 +459,10 @@ config SOC_ETM_CHANNELS_PER_GROUP int default 50 +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_GPIO_PORT int default 1 @@ -671,6 +675,10 @@ config SOC_I2S_SUPPORTS_TDM bool default y +config SOC_I2S_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK bool default y @@ -679,6 +687,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 6 @@ -703,6 +715,10 @@ config SOC_LEDC_FADE_PARAMS_BIT_WIDTH int default 10 +config SOC_LEDC_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MMU_PAGE_SIZE_CONFIGURABLE bool default y @@ -763,6 +779,10 @@ config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE bool default y +config SOC_PCNT_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_RMT_GROUPS int default 1 @@ -899,6 +919,10 @@ config SOC_PARLIO_TX_RX_SHARE_INTERRUPT bool default y +config SOC_PARLIO_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MPI_MEM_BLOCKS_NUM int default 4 @@ -987,6 +1011,10 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool default y +config SOC_SPI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_SPI_SUPPORT_CLK_XTAL bool default y @@ -1167,6 +1195,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS bool default y +config SOC_TWAI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_EFUSE_DIS_DOWNLOAD_ICACHE bool default y @@ -1451,6 +1483,14 @@ config SOC_TEMPERATURE_SENSOR_SUPPORT_ETM bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + bool + default y + +config SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN + bool + default y + config SOC_RNG_CLOCK_IS_INDEPENDENT bool default y @@ -1542,3 +1582,7 @@ config SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR config SOC_LP_CORE_SUPPORT_ETM bool default y + +config SOC_DEBUG_HAVE_OCD_STUB_BINS + bool + default y diff --git a/components/soc/esp32c6/include/soc/dport_access.h b/components/soc/esp32c6/include/soc/dport_access.h index 000b58c36a1c..54eb8a0a3523 100644 --- a/components/soc/esp32c6/include/soc/dport_access.h +++ b/components/soc/esp32c6/include/soc/dport_access.h @@ -9,7 +9,6 @@ #include #include "soc.h" -#include "uart_reg.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32c6/include/soc/interrupts.h b/components/soc/esp32c6/include/soc/interrupts.h index 8eb941cf8378..0d1fbc0f41ba 100644 --- a/components/soc/esp32c6/include/soc/interrupts.h +++ b/components/soc/esp32c6/include/soc/interrupts.h @@ -56,7 +56,7 @@ typedef enum { ETS_HP_APM_M3_INTR_SOURCE, ETS_LP_APM0_INTR_SOURCE, ETS_MSPI_INTR_SOURCE, - ETS_I2S1_INTR_SOURCE, /**< interrupt of I2S1, level*/ + ETS_I2S0_INTR_SOURCE, /**< interrupt of I2S0, level*/ ETS_UHCI0_INTR_SOURCE, /**< interrupt of UHCI0, level*/ ETS_UART0_INTR_SOURCE, /**< interrupt of UART0, level*/ ETS_UART1_INTR_SOURCE, /**< interrupt of UART1, level*/ diff --git a/components/soc/esp32c6/include/soc/periph_defs.h b/components/soc/esp32c6/include/soc/periph_defs.h index 3fefbbd326cf..65cb21953cb4 100644 --- a/components/soc/esp32c6/include/soc/periph_defs.h +++ b/components/soc/esp32c6/include/soc/periph_defs.h @@ -19,7 +19,7 @@ typedef enum { PERIPH_UART1_MODULE, PERIPH_USB_DEVICE_MODULE, PERIPH_I2C0_MODULE, - PERIPH_I2S1_MODULE, + PERIPH_I2S0_MODULE, PERIPH_TIMG0_MODULE, PERIPH_TIMG1_MODULE, PERIPH_UHCI0_MODULE, diff --git a/components/soc/esp32c6/include/soc/retention_periph_defs.h b/components/soc/esp32c6/include/soc/retention_periph_defs.h index a1dee8299ab7..13140b7a4bdf 100644 --- a/components/soc/esp32c6/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c6/include/soc/retention_periph_defs.h @@ -15,6 +15,7 @@ extern "C" { typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_MIN = 0, + SLEEP_RETENTION_MODULE_NULL = SLEEP_RETENTION_MODULE_MIN, /* This module is for all peripherals that can't survive from PD_TOP to call init only. Shouldn't have any dependency. */ /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2, @@ -36,6 +37,15 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_RMT0 = 13, SLEEP_RETENTION_MODULE_UART0 = 14, SLEEP_RETENTION_MODULE_UART1 = 15, + SLEEP_RETENTION_MODULE_I2S0 = 16, + SLEEP_RETENTION_MODULE_ETM0 = 17, + SLEEP_RETENTION_MODULE_TEMP_SENSOR = 18, + SLEEP_RETENTION_MODULE_TWAI0 = 19, + SLEEP_RETENTION_MODULE_TWAI1 = 20, + SLEEP_RETENTION_MODULE_PARLIO0 = 21, + SLEEP_RETENTION_MODULE_GPSPI2 = 22, + SLEEP_RETENTION_MODULE_LEDC = 23, + SLEEP_RETENTION_MODULE_PCNT0 = 24, /* Modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -47,6 +57,8 @@ typedef enum periph_retention_module { } periph_retention_module_t; typedef enum periph_retention_module_bitmap { + SLEEP_RETENTION_MODULE_BM_NULL = BIT(SLEEP_RETENTION_MODULE_NULL), + /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM), @@ -68,6 +80,15 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0), SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0), SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), + SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), + SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), + SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR), + SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0), + SLEEP_RETENTION_MODULE_BM_TWAI1 = BIT(SLEEP_RETENTION_MODULE_TWAI1), + SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0), + SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2), + SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC), + SLEEP_RETENTION_MODULE_BM_PCNT0 = BIT(SLEEP_RETENTION_MODULE_PCNT0), /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC), SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB), @@ -90,6 +111,16 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_RMT0 \ | SLEEP_RETENTION_MODULE_BM_UART0 \ | SLEEP_RETENTION_MODULE_BM_UART1 \ + | SLEEP_RETENTION_MODULE_BM_I2S0 \ + | SLEEP_RETENTION_MODULE_BM_ETM0 \ + | SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \ + | SLEEP_RETENTION_MODULE_BM_TWAI0 \ + | SLEEP_RETENTION_MODULE_BM_TWAI1 \ + | SLEEP_RETENTION_MODULE_BM_PARLIO0 \ + | SLEEP_RETENTION_MODULE_BM_GPSPI2 \ + | SLEEP_RETENTION_MODULE_BM_LEDC \ + | SLEEP_RETENTION_MODULE_BM_PCNT0 \ + | SLEEP_RETENTION_MODULE_BM_NULL \ ) #ifdef __cplusplus diff --git a/components/soc/esp32c6/include/soc/soc.h b/components/soc/esp32c6/include/soc/soc.h index 6778a1764bce..afd44da86c4b 100644 --- a/components/soc/esp32c6/include/soc/soc.h +++ b/components/soc/esp32c6/include/soc/soc.h @@ -12,7 +12,7 @@ #endif #include "esp_bit_defs.h" -#include "reg_base.h" +#include "soc/reg_base.h" #define PRO_CPU_NUM (0) diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index b997a19b9097..0750f12c3fb0 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -178,6 +178,7 @@ /*-------------------------- ETM CAPS --------------------------------------*/ #define SOC_ETM_GROUPS 1U // Number of ETM groups #define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C6 has 1 GPIO peripheral @@ -273,16 +274,19 @@ #define SOC_I2S_SUPPORTS_PDM_TX (1) #define SOC_I2S_PDM_MAX_TX_LINES (2) #define SOC_I2S_SUPPORTS_TDM (1) +#define SOC_I2S_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up I2S registers before sleep */ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (6) #define SOC_LEDC_TIMER_BIT_WIDTH (20) #define SOC_LEDC_SUPPORT_FADE_STOP (1) #define SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED (1) #define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16) #define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10) +#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- MMU CAPS ----------------------------------------*/ #define SOC_MMU_PAGE_SIZE_CONFIGURABLE (1) @@ -304,6 +308,7 @@ #define SOC_PCNT_CHANNELS_PER_UNIT 2 #define SOC_PCNT_THRES_POINT_PER_UNIT 2 #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 +#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ @@ -347,6 +352,7 @@ #define SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH 16 /*!< Number of data lines of the TX unit */ #define SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH 16 /*!< Number of data lines of the RX unit */ #define SOC_PARLIO_TX_RX_SHARE_INTERRUPT 1 /*!< TX and RX unit share the same interrupt source number */ +#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */ /*--------------------------- MPI CAPS ---------------------------------------*/ #define SOC_MPI_MEM_BLOCKS_NUM (4) @@ -394,6 +400,7 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 +#define SOC_SPI_SUPPORT_SLEEP_RETENTION 1 #define SOC_SPI_SUPPORT_CLK_XTAL 1 #define SOC_SPI_SUPPORT_CLK_PLL_F80M 1 #define SOC_SPI_SUPPORT_CLK_RC_FAST 1 @@ -454,11 +461,12 @@ #define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- TWAI CAPS ---------------------------------------*/ -#define SOC_TWAI_CONTROLLER_NUM 2 -#define SOC_TWAI_CLK_SUPPORT_XTAL 1 -#define SOC_TWAI_BRP_MIN 2 -#define SOC_TWAI_BRP_MAX 32768 -#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_CONTROLLER_NUM 2 +#define SOC_TWAI_CLK_SUPPORT_XTAL 1 +#define SOC_TWAI_BRP_MIN 2 +#define SOC_TWAI_BRP_MAX 32768 +#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- eFuse CAPS----------------------------*/ #define SOC_EFUSE_DIS_DOWNLOAD_ICACHE 1 @@ -572,6 +580,8 @@ #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) #define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_ETM (1) +#define SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION (1) +#define SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN (1) /*--------------------------------- RNG CAPS --------------------------------------------*/ #define SOC_RNG_CLOCK_IS_INDEPENDENT (1) @@ -609,3 +619,6 @@ /*------------------------------------- ULP CAPS -------------------------------------*/ #define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ + +/*------------------------------------- DEBUG CAPS -------------------------------------*/ +#define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) diff --git a/components/soc/esp32c6/include/soc/system_reg.h b/components/soc/esp32c6/include/soc/system_reg.h index 4ed6ac2ac25c..17cf94805edd 100644 --- a/components/soc/esp32c6/include/soc/system_reg.h +++ b/components/soc/esp32c6/include/soc/system_reg.h @@ -7,6 +7,6 @@ #include "soc/hp_system_reg.h" // TODO: IDF-5720 -#include "intpri_reg.h" +#include "soc/intpri_reg.h" #define SYSTEM_CPU_INTR_FROM_CPU_0_REG INTPRI_CPU_INTR_FROM_CPU_0_REG #define SYSTEM_CPU_INTR_FROM_CPU_0 INTPRI_CPU_INTR_FROM_CPU_0 diff --git a/components/soc/esp32c6/interrupts.c b/components/soc/esp32c6/interrupts.c index 075a674041e8..c3a8e0eef9ab 100644 --- a/components/soc/esp32c6/interrupts.c +++ b/components/soc/esp32c6/interrupts.c @@ -48,7 +48,7 @@ const char *const esp_isr_names[] = { [38] = "HP_APM_M3", [39] = "LP_APM0", [40] = "MSPI", - [41] = "I2S1", + [41] = "I2S0", [42] = "UHCI0", [43] = "UART0", [44] = "UART1", diff --git a/components/soc/esp32c6/ledc_periph.c b/components/soc/esp32c6/ledc_periph.c index b150f9bc991e..e20f002e5a30 100644 --- a/components/soc/esp32c6/ledc_periph.c +++ b/components/soc/esp32c6/ledc_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,3 +15,141 @@ const ledc_signal_conn_t ledc_periph_signal[1] = { .sig_out0_idx = LEDC_LS_SIG_OUT0_IDX, } }; + +/** + * LEDC registers to be saved for sleep retention + * + * channel: + * LEDC_CHx_CONF0_REG, LEDC_CHx_HPOINT_REG, LEDC_CHx_DUTY_R_REG -> LEDC_CHx_DUTY_REG, + * + * timer: + * LEDC_TIMERn_CONF_REG, LEDC_TIMERn_CMP_REG, + * + * common: + * LEDC_INT_ENA_REG, + * LEDC_EVT_TASK_EN0_REG, LEDC_EVT_TASK_EN1_REG, LEDC_EVT_TASK_EN2_REG, + * LEDC_CONF_REG, + * + * Note 1: Gamma feature is hard to do hardware retention, will consider to use software to do the backup and restore. + * We won't start a fade automatically after wake-up. + * Instead, we will only start a PWM with a fixed duty cycle, the same value as before entering the sleep. + * + * Note 2: For timer/channel registers to get synced, update bits need to be set + * + * Note 3: Retention backup/restore does not rely on LEDC function clock enabled + */ +#define LEDC_COMMON_RETENTION_REGS_CNT 5 +#define LEDC_COMMON_RETENTION_REGS_BASE (DR_REG_LEDC_BASE + 0xc8) +static const uint32_t ledc_common_regs_map[4] = {0x1, 0x1c00000, 0x400, 0x0}; +static const regdma_entries_config_t ledc_common_regdma_entries[] = { + // If a fade is in process, the DUTY_CHNG_END_CHx intr bit is enabled, however, we don't want it to be restored after wake-up (no fade after wake-up). + // Therefore, we can set it to 0 before backup the LEDC_INT_ENA_REG. + [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x00), + LEDC_INT_ENA_REG, 0, + (LEDC_DUTY_CHNG_END_CH0_INT_ENA_M | LEDC_DUTY_CHNG_END_CH1_INT_ENA_M | LEDC_DUTY_CHNG_END_CH2_INT_ENA_M | LEDC_DUTY_CHNG_END_CH3_INT_ENA_M | LEDC_DUTY_CHNG_END_CH4_INT_ENA_M | LEDC_DUTY_CHNG_END_CH5_INT_ENA_M), 0, 1), + .owner = LEDC_RETENTION_ENTRY }, + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x01), + LEDC_COMMON_RETENTION_REGS_BASE, LEDC_COMMON_RETENTION_REGS_BASE, + LEDC_COMMON_RETENTION_REGS_CNT, 0, 0, + ledc_common_regs_map[0], ledc_common_regs_map[1], + ledc_common_regs_map[2], ledc_common_regs_map[3]), + .owner = LEDC_RETENTION_ENTRY }, +}; + +#define LEDC_TIMER_RETENTION_ENTRIES(timer) { \ + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_CONF_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_TIMER##timer##_CMP_REG, LEDC_TIMER##timer##_CMP_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_PARA_UP, \ + LEDC_TIMER##timer##_PARA_UP_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +#define LEDC_CHANNEL_RETENTION_REGS_CNT 2 +static const uint32_t ledc_channel_regs_map[4] = {0x3, 0x0, 0x0, 0x0}; +#define LEDC_CHANNEL_RETENTION_ENTRIES(chan) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_CH##chan##_CONF0_REG, LEDC_CH##chan##_CONF0_REG, \ + LEDC_CHANNEL_RETENTION_REGS_CNT, 0, 0, \ + ledc_channel_regs_map[0], ledc_channel_regs_map[1], \ + ledc_channel_regs_map[2], ledc_channel_regs_map[3]), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_CH##chan##_DUTY_R_REG, LEDC_CH##chan##_DUTY_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_CH##chan##_CONF1_REG, LEDC_DUTY_START_CH##chan, \ + LEDC_DUTY_START_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x03), \ + LEDC_CH##chan##_CONF0_REG, LEDC_PARA_UP_CH##chan, \ + LEDC_PARA_UP_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +static const regdma_entries_config_t ledc_timer0_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_timer1_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_timer2_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_timer3_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(3); + +static const regdma_entries_config_t ledc_channel0_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_channel1_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_channel2_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_channel3_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(3); +static const regdma_entries_config_t ledc_channel4_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(4); +static const regdma_entries_config_t ledc_channel5_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(5); + +const ledc_reg_retention_info_t ledc_reg_retention_info = { + .common = { + .regdma_entry_array = ledc_common_regdma_entries, + .array_size = ARRAY_SIZE(ledc_common_regdma_entries), + }, + .timer[0] = { + .regdma_entry_array = ledc_timer0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer0_regdma_entries), + }, + .timer[1] = { + .regdma_entry_array = ledc_timer1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer1_regdma_entries), + }, + .timer[2] = { + .regdma_entry_array = ledc_timer2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer2_regdma_entries), + }, + .timer[3] = { + .regdma_entry_array = ledc_timer3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer3_regdma_entries), + }, + .channel[0] = { + .regdma_entry_array = ledc_channel0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel0_regdma_entries), + }, + .channel[1] = { + .regdma_entry_array = ledc_channel1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel1_regdma_entries), + }, + .channel[2] = { + .regdma_entry_array = ledc_channel2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel2_regdma_entries), + }, + .channel[3] = { + .regdma_entry_array = ledc_channel3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel3_regdma_entries), + }, + .channel[4] = { + .regdma_entry_array = ledc_channel4_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel4_regdma_entries), + }, + .channel[5] = { + .regdma_entry_array = ledc_channel5_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel5_regdma_entries), + }, + .module_id = SLEEP_RETENTION_MODULE_LEDC, +}; diff --git a/components/soc/esp32c6/parlio_periph.c b/components/soc/esp32c6/parlio_periph.c index 40ac06320c27..f060ee1a9ed4 100644 --- a/components/soc/esp32c6/parlio_periph.c +++ b/components/soc/esp32c6/parlio_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,3 +64,29 @@ const parlio_signal_conn_t parlio_periph_signals = { }, }, }; + +/** + * PARLIO Registers to be saved during sleep retention + * - Configuration registers, e.g.: PARL_IO_RX_CFG0_REG, PARL_IO_RX_CFG1_REG, PARL_IO_TX_CFG0_REG, PARL_IO_TX_CFG1_REG, PARL_IO_CLK_REG + * - Interrupt enable registers, e.g.: PARL_IO_INT_ENA_REG +*/ +#define PARLIO_RETENTION_REGS_CNT 6 +#define PARLIO_RETENTION_REGS_BASE (DR_REG_PARL_IO_BASE + 0x0) +static const uint32_t parlio_regs_map[4] = {0x2f, 0x0, 0x100, 0x0}; +static const regdma_entries_config_t parlio_regs_retention[] = { + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PARLIO_LINK(0x00), \ + PARLIO_RETENTION_REGS_BASE, PARLIO_RETENTION_REGS_BASE, \ + PARLIO_RETENTION_REGS_CNT, 0, 0, \ + parlio_regs_map[0], parlio_regs_map[1], \ + parlio_regs_map[2], parlio_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; +const parlio_reg_retention_info_t parlio_reg_retention_info[SOC_PARLIO_GROUPS] = { + [0] = { + .regdma_entry_array = parlio_regs_retention, + .array_size = ARRAY_SIZE(parlio_regs_retention), + .retention_module = SLEEP_RETENTION_MODULE_PARLIO0 + }, +}; diff --git a/components/soc/esp32c6/pcnt_periph.c b/components/soc/esp32c6/pcnt_periph.c index b2b440245b75..14c52fc0d623 100644 --- a/components/soc/esp32c6/pcnt_periph.c +++ b/components/soc/esp32c6/pcnt_periph.c @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/pcnt_periph.h" #include "soc/gpio_sig_map.h" +#include "soc/pcnt_reg.h" const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { @@ -64,3 +65,30 @@ const pcnt_signal_conn_t pcnt_periph_signals = { } } }; + +/** + * PCNT Registers to be saved during sleep retention + * - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG... + * - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG +*/ +#define PCNT_RETENTION_REGS_CNT 14 +#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0) +static const uint32_t pcnt_regs_map[4] = {0x1040fff, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t pcnt_regs_retention[] = { + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \ + PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \ + PCNT_RETENTION_REGS_CNT, 0, 0, \ + pcnt_regs_map[0], pcnt_regs_map[1], \ + pcnt_regs_map[2], pcnt_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = { + [0] = { + .regdma_entry_array = pcnt_regs_retention, + .array_size = ARRAY_SIZE(pcnt_regs_retention), + .retention_module = SLEEP_RETENTION_MODULE_PCNT0 + }, +}; diff --git a/components/soc/esp32c6/register/soc/.gitkeep b/components/soc/esp32c6/register/soc/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/soc/esp32c6/include/soc/aes_reg.h b/components/soc/esp32c6/register/soc/aes_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/aes_reg.h rename to components/soc/esp32c6/register/soc/aes_reg.h diff --git a/components/soc/esp32c6/include/soc/aes_struct.h b/components/soc/esp32c6/register/soc/aes_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/aes_struct.h rename to components/soc/esp32c6/register/soc/aes_struct.h diff --git a/components/soc/esp32c6/include/soc/apb_saradc_reg.h b/components/soc/esp32c6/register/soc/apb_saradc_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/apb_saradc_reg.h rename to components/soc/esp32c6/register/soc/apb_saradc_reg.h diff --git a/components/soc/esp32c6/include/soc/apb_saradc_struct.h b/components/soc/esp32c6/register/soc/apb_saradc_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/apb_saradc_struct.h rename to components/soc/esp32c6/register/soc/apb_saradc_struct.h diff --git a/components/soc/esp32c6/include/soc/assist_debug_reg.h b/components/soc/esp32c6/register/soc/assist_debug_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/assist_debug_reg.h rename to components/soc/esp32c6/register/soc/assist_debug_reg.h index 8e0426dc6f57..d2b947d9466a 100644 --- a/components/soc/esp32c6/include/soc/assist_debug_reg.h +++ b/components/soc/esp32c6/register/soc/assist_debug_reg.h @@ -92,7 +92,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_ENA_V 0x00000001U #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_ENA_S 10 /** ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor enbale + * DBUS busy monitor enable */ #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA (BIT(11)) #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_M (ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_V << ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_S) @@ -270,7 +270,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_RLS_V 0x00000001U #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_RLS_S 10 /** ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor interrupt enbale + * DBUS busy monitor interrupt enable */ #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS (BIT(11)) #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS_M (ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS_V << ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS_S) @@ -491,7 +491,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_SP_MIN_REG (DR_REG_ASSIST_DEBUG_BASE + 0x38) /** ASSIST_DEBUG_CORE_0_SP_MIN : R/W; bitpos: [31:0]; default: 0; - * core0 sp region configuration regsiter + * core0 sp region configuration register */ #define ASSIST_DEBUG_CORE_0_SP_MIN 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_0_SP_MIN_M (ASSIST_DEBUG_CORE_0_SP_MIN_V << ASSIST_DEBUG_CORE_0_SP_MIN_S) @@ -515,7 +515,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_SP_PC_REG (DR_REG_ASSIST_DEBUG_BASE + 0x40) /** ASSIST_DEBUG_CORE_0_SP_PC : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ #define ASSIST_DEBUG_CORE_0_SP_PC 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_0_SP_PC_M (ASSIST_DEBUG_CORE_0_SP_PC_V << ASSIST_DEBUG_CORE_0_SP_PC_S) @@ -542,7 +542,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGEN_S 1 /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG (DR_REG_ASSIST_DEBUG_BASE + 0x48) /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC : RO; bitpos: [31:0]; default: 0; @@ -554,7 +554,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_S 0 /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP_REG (DR_REG_ASSIST_DEBUG_BASE + 0x4c) /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP : RO; bitpos: [31:0]; default: 0; diff --git a/components/soc/esp32c6/include/soc/assist_debug_struct.h b/components/soc/esp32c6/register/soc/assist_debug_struct.h similarity index 98% rename from components/soc/esp32c6/include/soc/assist_debug_struct.h rename to components/soc/esp32c6/register/soc/assist_debug_struct.h index 24c28c33efa8..9838880bc8c4 100644 --- a/components/soc/esp32c6/include/soc/assist_debug_struct.h +++ b/components/soc/esp32c6/register/soc/assist_debug_struct.h @@ -61,7 +61,7 @@ typedef union { */ uint32_t core_0_iram0_exception_monitor_ena:1; /** core_0_dram0_exception_monitor_ena : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor enbale + * DBUS busy monitor enable */ uint32_t core_0_dram0_exception_monitor_ena:1; uint32_t reserved_12:20; @@ -205,7 +205,7 @@ typedef union { typedef union { struct { /** core_0_sp_min : R/W; bitpos: [31:0]; default: 0; - * core0 sp region configuration regsiter + * core0 sp region configuration register */ uint32_t core_0_sp_min:32; }; @@ -231,7 +231,7 @@ typedef union { typedef union { struct { /** core_0_sp_pc : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ uint32_t core_0_sp_pc:32; }; @@ -348,7 +348,7 @@ typedef union { */ uint32_t core_0_iram0_exception_monitor_rls:1; /** core_0_dram0_exception_monitor_rls : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor interrupt enbale + * DBUS busy monitor interrupt enable */ uint32_t core_0_dram0_exception_monitor_rls:1; uint32_t reserved_12:20; @@ -415,7 +415,7 @@ typedef union { } assist_debug_core_0_intr_clr_reg_t; -/** Group: pc reording configuration register */ +/** Group: pc recording configuration register */ /** Type of core_0_rcd_en register * record enable configuration register */ @@ -435,9 +435,9 @@ typedef union { } assist_debug_core_0_rcd_en_reg_t; -/** Group: pc reording status register */ +/** Group: pc recording status register */ /** Type of core_0_rcd_pdebugpc register - * record status regsiter + * record status register */ typedef union { struct { @@ -450,7 +450,7 @@ typedef union { } assist_debug_core_0_rcd_pdebugpc_reg_t; /** Type of core_0_rcd_pdebugsp register - * record status regsiter + * record status register */ typedef union { struct { @@ -463,7 +463,7 @@ typedef union { } assist_debug_core_0_rcd_pdebugsp_reg_t; -/** Group: exception monitor regsiter */ +/** Group: exception monitor register */ /** Type of core_0_iram0_exception_monitor_0 register * exception monitor status register0 */ diff --git a/components/soc/esp32c6/include/soc/clint_reg.h b/components/soc/esp32c6/register/soc/clint_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/clint_reg.h rename to components/soc/esp32c6/register/soc/clint_reg.h diff --git a/components/soc/esp32c6/include/soc/ds_reg.h b/components/soc/esp32c6/register/soc/ds_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/ds_reg.h rename to components/soc/esp32c6/register/soc/ds_reg.h diff --git a/components/soc/esp32c6/include/soc/ds_struct.h b/components/soc/esp32c6/register/soc/ds_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/ds_struct.h rename to components/soc/esp32c6/register/soc/ds_struct.h diff --git a/components/soc/esp32c6/include/soc/ecc_mult_reg.h b/components/soc/esp32c6/register/soc/ecc_mult_reg.h similarity index 98% rename from components/soc/esp32c6/include/soc/ecc_mult_reg.h rename to components/soc/esp32c6/register/soc/ecc_mult_reg.h index dca2cc1206a9..00846e8ed63b 100644 --- a/components/soc/esp32c6/include/soc/ecc_mult_reg.h +++ b/components/soc/esp32c6/register/soc/ecc_mult_reg.h @@ -64,7 +64,7 @@ extern "C" { */ #define ECC_MULT_CONF_REG (DR_REG_ECC_MULT_BASE + 0x1c) /** ECC_MULT_START : R/W/SC; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECC Accelerator. This bit will be self-cleared after + * Write 1 to start calculation of ECC Accelerator. This bit will be self-cleared after * the caculatrion is done. */ #define ECC_MULT_START (BIT(0)) diff --git a/components/soc/esp32c6/include/soc/ecc_mult_struct.h b/components/soc/esp32c6/register/soc/ecc_mult_struct.h similarity index 97% rename from components/soc/esp32c6/include/soc/ecc_mult_struct.h rename to components/soc/esp32c6/register/soc/ecc_mult_struct.h index c120fb068de7..89665324365f 100644 --- a/components/soc/esp32c6/include/soc/ecc_mult_struct.h +++ b/components/soc/esp32c6/register/soc/ecc_mult_struct.h @@ -77,7 +77,7 @@ typedef union { typedef union { struct { /** start : R/W/SC; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECC Accelerator. This bit will be self-cleared after + * Write 1 to start calculation of ECC Accelerator. This bit will be self-cleared after * the caculatrion is done. */ uint32_t start:1; diff --git a/components/soc/esp32c6/include/soc/efuse_reg.h b/components/soc/esp32c6/register/soc/efuse_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/efuse_reg.h rename to components/soc/esp32c6/register/soc/efuse_reg.h index 882041ac4137..b91b0b0ff0ed 100644 --- a/components/soc/esp32c6/include/soc/efuse_reg.h +++ b/components/soc/esp32c6/register/soc/efuse_reg.h @@ -7,7 +7,7 @@ #include #include "soc/soc.h" -#include "efuse_defs.h" +#include "soc/efuse_defs.h" #ifdef __cplusplus extern "C" { #endif @@ -264,14 +264,14 @@ extern "C" { #define EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_V 0x00000001U #define EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_S 20 /** EFUSE_USB_DREFH : RO; bitpos: [22:21]; default: 0; - * Represents the single-end input threhold vrefh, 1.76 V to 2 V with step of 80 mV. + * Represents the single-end input threshold vrefh, 1.76 V to 2 V with step of 80 mV. */ #define EFUSE_USB_DREFH 0x00000003U #define EFUSE_USB_DREFH_M (EFUSE_USB_DREFH_V << EFUSE_USB_DREFH_S) #define EFUSE_USB_DREFH_V 0x00000003U #define EFUSE_USB_DREFH_S 21 /** EFUSE_USB_DREFL : RO; bitpos: [24:23]; default: 0; - * Represents the single-end input threhold vrefl, 1.76 V to 2 V with step of 80 mV. + * Represents the single-end input threshold vrefl, 1.76 V to 2 V with step of 80 mV. */ #define EFUSE_USB_DREFL 0x00000003U #define EFUSE_USB_DREFL_M (EFUSE_USB_DREFL_V << EFUSE_USB_DREFL_S) @@ -2390,7 +2390,7 @@ extern "C" { #define EFUSE_CLK_EN_S 16 /** EFUSE_CONF_REG register - * eFuse operation mode configuraiton register + * eFuse operation mode configuration register */ #define EFUSE_CONF_REG (DR_REG_EFUSE_BASE + 0x1cc) /** EFUSE_OP_CODE : R/W; bitpos: [15:0]; default: 0; diff --git a/components/soc/esp32c6/include/soc/efuse_struct.h b/components/soc/esp32c6/register/soc/efuse_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/efuse_struct.h rename to components/soc/esp32c6/register/soc/efuse_struct.h index e6971b4d5836..c92f02208c4b 100644 --- a/components/soc/esp32c6/include/soc/efuse_struct.h +++ b/components/soc/esp32c6/register/soc/efuse_struct.h @@ -239,11 +239,11 @@ typedef union { */ uint32_t dis_download_manual_encrypt:1; /** usb_drefh : RO; bitpos: [22:21]; default: 0; - * Represents the single-end input threhold vrefh, 1.76 V to 2 V with step of 80 mV. + * Represents the single-end input threshold vrefh, 1.76 V to 2 V with step of 80 mV. */ uint32_t usb_drefh:2; /** usb_drefl : RO; bitpos: [24:23]; default: 0; - * Represents the single-end input threhold vrefl, 1.76 V to 2 V with step of 80 mV. + * Represents the single-end input threshold vrefl, 1.76 V to 2 V with step of 80 mV. */ uint32_t usb_drefl:2; /** usb_exchg_pins : RO; bitpos: [25]; default: 0; @@ -2024,7 +2024,7 @@ typedef union { } efuse_clk_reg_t; /** Type of conf register - * eFuse operation mode configuraiton register + * eFuse operation mode configuration register */ typedef union { struct { diff --git a/components/soc/esp32c6/include/soc/extmem_reg.h b/components/soc/esp32c6/register/soc/extmem_reg.h similarity index 98% rename from components/soc/esp32c6/include/soc/extmem_reg.h rename to components/soc/esp32c6/register/soc/extmem_reg.h index a9cb6935862f..08a9daf433c0 100644 --- a/components/soc/esp32c6/include/soc/extmem_reg.h +++ b/components/soc/esp32c6/register/soc/extmem_reg.h @@ -243,8 +243,8 @@ ould be used together with CACHE_LOCK_ADDR_REG.*/ #define EXTMEM_L1_CACHE_SYNC_DONE_S 4 /* EXTMEM_L1_CACHE_WRITEBACK_INVALIDATE_ENA : R/W/SC ;bitpos:[3] ;default: 1'h0 ; */ /*description: The bit is used to enable writeback-invalidate operation. It will be cleared by -hardware after writeback-invalidate operation done. Note that this bit and the o -ther sync-bits (invalidate_ena, clean_ena, writeback_ena) are mutually exclusive +hardware after writeback-invalidate operation done. Note that this bit and the +other sync-bits (invalidate_ena, clean_ena, writeback_ena) are mutually exclusive , that is, those bits can not be set to 1 at the same time..*/ #define EXTMEM_L1_CACHE_WRITEBACK_INVALIDATE_ENA (BIT(3)) #define EXTMEM_L1_CACHE_WRITEBACK_INVALIDATE_ENA_M (BIT(3)) @@ -262,16 +262,16 @@ those bits can not be set to 1 at the same time..*/ /* EXTMEM_L1_CACHE_CLEAN_ENA : R/W/SC ;bitpos:[1] ;default: 1'h0 ; */ /*description: The bit is used to enable clean operation. It will be cleared by hardware after clean operation done. Note that this bit and the other sync-bits (invalidate_ena -, writeback_ena, writeback_invalidate_ena) are mutually exclusive, that is, thos -e bits can not be set to 1 at the same time..*/ +, writeback_ena, writeback_invalidate_ena) are mutually exclusive, that is, those +bits can not be set to 1 at the same time..*/ #define EXTMEM_L1_CACHE_CLEAN_ENA (BIT(1)) #define EXTMEM_L1_CACHE_CLEAN_ENA_M (BIT(1)) #define EXTMEM_L1_CACHE_CLEAN_ENA_V 0x1 #define EXTMEM_L1_CACHE_CLEAN_ENA_S 1 /* EXTMEM_L1_CACHE_INVALIDATE_ENA : R/W/SC ;bitpos:[0] ;default: 1'h1 ; */ /*description: The bit is used to enable invalidate operation. It will be cleared by hardware a -fter invalidate operation done. Note that this bit and the other sync-bits (clea -n_ena, writeback_ena, writeback_invalidate_ena) are mutually exclusive, that is, +after invalidate operation done. Note that this bit and the other sync-bits (clean_ena, +writeback_ena, writeback_invalidate_ena) are mutually exclusive, that is, those bits can not be set to 1 at the same time..*/ #define EXTMEM_L1_CACHE_INVALIDATE_ENA (BIT(0)) #define EXTMEM_L1_CACHE_INVALIDATE_ENA_M (BIT(0)) @@ -452,15 +452,15 @@ SCT1_ADDR and L1_CACHE_AUTOLOAD_SCT1_ENA..*/ #define EXTMEM_L1_CACHE_ACS_CNT_INT_CLR_REG (DR_REG_EXTMEM_BASE + 0x15C) /* EXTMEM_L1_DBUS_OVF_INT_CLR : WT ;bitpos:[5] ;default: 1'b0 ; */ -/*description: The bit is used to clear counters overflow interrupt and counters in L1-DCache d -ue to bus1 accesses L1-DCache..*/ +/*description: The bit is used to clear counters overflow interrupt and counters in L1-DCache due +to bus1 accesses L1-DCache..*/ #define EXTMEM_L1_DBUS_OVF_INT_CLR (BIT(5)) #define EXTMEM_L1_DBUS_OVF_INT_CLR_M (BIT(5)) #define EXTMEM_L1_DBUS_OVF_INT_CLR_V 0x1 #define EXTMEM_L1_DBUS_OVF_INT_CLR_S 5 /* EXTMEM_L1_IBUS_OVF_INT_CLR : WT ;bitpos:[4] ;default: 1'b0 ; */ -/*description: The bit is used to clear counters overflow interrupt and counters in L1-DCache d -ue to bus0 accesses L1-DCache..*/ +/*description: The bit is used to clear counters overflow interrupt and counters in L1-DCache due +to bus0 accesses L1-DCache..*/ #define EXTMEM_L1_IBUS_OVF_INT_CLR (BIT(4)) #define EXTMEM_L1_IBUS_OVF_INT_CLR_M (BIT(4)) #define EXTMEM_L1_IBUS_OVF_INT_CLR_V 0x1 @@ -526,8 +526,8 @@ o cpu accesses L1-DCache..*/ #define EXTMEM_L1_CACHE_ACS_FAIL_INT_ST_REG (DR_REG_EXTMEM_BASE + 0x174) /* EXTMEM_L1_CACHE_FAIL_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: The bit indicates the interrupt status of access fail that occurs in L1-DCache d -ue to cpu accesses L1-DCache..*/ +/*description: The bit indicates the interrupt status of access fail that occurs in L1-DCache due +to cpu accesses L1-DCache..*/ #define EXTMEM_L1_CACHE_FAIL_INT_ST (BIT(4)) #define EXTMEM_L1_CACHE_FAIL_INT_ST_M (BIT(4)) #define EXTMEM_L1_CACHE_FAIL_INT_ST_V 0x1 @@ -740,7 +740,7 @@ ror occurs..*/ #define EXTMEM_L1_CACHE_SYNC_ERR_INT_ST_V 0x1 #define EXTMEM_L1_CACHE_SYNC_ERR_INT_ST_S 13 /* EXTMEM_L1_CACHE_PLD_ERR_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: The bit indicates the status of the interrupt of L1-Cache preload-operation erro +/*description: The bit indicates the status of the interrupt of L1-Cache preload-operation error r..*/ #define EXTMEM_L1_CACHE_PLD_ERR_INT_ST (BIT(11)) #define EXTMEM_L1_CACHE_PLD_ERR_INT_ST_M (BIT(11)) @@ -778,7 +778,7 @@ load-operation is done..*/ #define EXTMEM_L1_CACHE_SYNC_RST_CTRL_REG (DR_REG_EXTMEM_BASE + 0x238) /* EXTMEM_L1_CACHE_SYNC_RST : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: set this bit to reset sync-logic inside L1-Cache. Recommend that this should onl +/*description: set this bit to reset sync-logic inside L1-Cache. Recommend that this should only y be used to initialize sync-logic when some fatal error of sync-logic occurs..*/ #define EXTMEM_L1_CACHE_SYNC_RST (BIT(4)) #define EXTMEM_L1_CACHE_SYNC_RST_M (BIT(4)) @@ -808,7 +808,7 @@ rks in L1-Cache..*/ #define EXTMEM_L1_UNALLOCATE_BUFFER_CLEAR_REG (DR_REG_EXTMEM_BASE + 0x244) /* EXTMEM_L1_CACHE_UNALLOC_CLR : R/W ;bitpos:[4] ;default: 1'b0 ; */ /*description: The bit is used to clear the unallocate request buffer of l1 cache where the una -llocate request is responsed but not completed..*/ +llocate request is responded but not completed..*/ #define EXTMEM_L1_CACHE_UNALLOC_CLR (BIT(4)) #define EXTMEM_L1_CACHE_UNALLOC_CLR_M (BIT(4)) #define EXTMEM_L1_CACHE_UNALLOC_CLR_V 0x1 @@ -823,7 +823,7 @@ th the others fields inside this register..*/ #define EXTMEM_L1_CACHE_MEM_OBJECT_V 0x1 #define EXTMEM_L1_CACHE_MEM_OBJECT_S 10 /* EXTMEM_L1_CACHE_TAG_OBJECT : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: Set this bit to set L1-Cache tag memory as object. This bit should be onehot wit +/*description: Set this bit to set L1-Cache tag memory as object. This bit should be onehot with h the others fields inside this register..*/ #define EXTMEM_L1_CACHE_TAG_OBJECT (BIT(4)) #define EXTMEM_L1_CACHE_TAG_OBJECT_M (BIT(4)) @@ -841,8 +841,8 @@ h the others fields inside this register..*/ #define EXTMEM_L1_CACHE_VADDR_REG (DR_REG_EXTMEM_BASE + 0x250) /* EXTMEM_L1_CACHE_VADDR : R/W ;bitpos:[31:0] ;default: 32'h40000000 ; */ -/*description: Those bits stores the virtual address which will decide where inside the specifi -ed tag memory object will be accessed..*/ +/*description: Those bits stores the virtual address which will decide where inside the specified +tag memory object will be accessed..*/ #define EXTMEM_L1_CACHE_VADDR 0xFFFFFFFF #define EXTMEM_L1_CACHE_VADDR_M ((EXTMEM_L1_CACHE_VADDR_V)<<(EXTMEM_L1_CACHE_VADDR_S)) #define EXTMEM_L1_CACHE_VADDR_V 0xFFFFFFFF diff --git a/components/soc/esp32h2/include/soc/extmem_struct.h b/components/soc/esp32c6/register/soc/extmem_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/extmem_struct.h rename to components/soc/esp32c6/register/soc/extmem_struct.h index d309e09235e4..d43c5fcee3d7 100644 --- a/components/soc/esp32h2/include/soc/extmem_struct.h +++ b/components/soc/esp32c6/register/soc/extmem_struct.h @@ -5115,12 +5115,12 @@ typedef union { struct { /** l1_icache0_unalloc_clr : HRO; bitpos: [0]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache0 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_icache0_unalloc_clr:1; /** l1_icache1_unalloc_clr : HRO; bitpos: [1]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache1 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_icache1_unalloc_clr:1; /** l1_icache2_unalloc_clr : HRO; bitpos: [2]; default: 0; @@ -5133,7 +5133,7 @@ typedef union { uint32_t l1_icache3_unalloc_clr:1; /** l1_cache_unalloc_clr : R/W; bitpos: [4]; default: 0; * The bit is used to clear the unallocate request buffer of l1 cache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_cache_unalloc_clr:1; uint32_t reserved_5:27; @@ -5149,7 +5149,7 @@ typedef union { uint32_t reserved_0:5; /** l2_cache_unalloc_clr : HRO; bitpos: [5]; default: 0; * The bit is used to clear the unallocate request buffer of l2 icache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l2_cache_unalloc_clr:1; uint32_t reserved_6:26; diff --git a/components/soc/esp32c6/include/soc/gdma_reg.h b/components/soc/esp32c6/register/soc/gdma_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/gdma_reg.h rename to components/soc/esp32c6/register/soc/gdma_reg.h diff --git a/components/soc/esp32c6/include/soc/gdma_struct.h b/components/soc/esp32c6/register/soc/gdma_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/gdma_struct.h rename to components/soc/esp32c6/register/soc/gdma_struct.h diff --git a/components/soc/esp32c6/include/soc/gpio_ext_reg.h b/components/soc/esp32c6/register/soc/gpio_ext_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/gpio_ext_reg.h rename to components/soc/esp32c6/register/soc/gpio_ext_reg.h diff --git a/components/soc/esp32c6/include/soc/gpio_ext_struct.h b/components/soc/esp32c6/register/soc/gpio_ext_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/gpio_ext_struct.h rename to components/soc/esp32c6/register/soc/gpio_ext_struct.h diff --git a/components/soc/esp32c6/include/soc/gpio_reg.h b/components/soc/esp32c6/register/soc/gpio_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/gpio_reg.h rename to components/soc/esp32c6/register/soc/gpio_reg.h diff --git a/components/soc/esp32c6/include/soc/gpio_struct.h b/components/soc/esp32c6/register/soc/gpio_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/gpio_struct.h rename to components/soc/esp32c6/register/soc/gpio_struct.h diff --git a/components/soc/esp32c6/include/soc/hardware_lock_reg.h b/components/soc/esp32c6/register/soc/hardware_lock_reg.h similarity index 93% rename from components/soc/esp32c6/include/soc/hardware_lock_reg.h rename to components/soc/esp32c6/register/soc/hardware_lock_reg.h index a9fbfb8cb06b..a80313138c48 100644 --- a/components/soc/esp32c6/include/soc/hardware_lock_reg.h +++ b/components/soc/esp32c6/register/soc/hardware_lock_reg.h @@ -12,7 +12,7 @@ extern "C" { #endif /** ATOMIC_ADDR_LOCK_REG register - * hardware lock regsiter + * hardware lock register */ #define ATOMIC_ADDR_LOCK_REG (DR_REG_ATOMIC_BASE + 0x0) /** ATOMIC_LOCK : R/W; bitpos: [1:0]; default: 0; @@ -24,7 +24,7 @@ extern "C" { #define ATOMIC_LOCK_S 0 /** ATOMIC_LR_ADDR_REG register - * gloable lr address regsiter + * gloable lr address register */ #define ATOMIC_LR_ADDR_REG (DR_REG_ATOMIC_BASE + 0x4) /** ATOMIC_GLOABLE_LR_ADDR : R/W; bitpos: [31:0]; default: 0; @@ -36,7 +36,7 @@ extern "C" { #define ATOMIC_GLOABLE_LR_ADDR_S 0 /** ATOMIC_LR_VALUE_REG register - * gloable lr value regsiter + * gloable lr value register */ #define ATOMIC_LR_VALUE_REG (DR_REG_ATOMIC_BASE + 0x8) /** ATOMIC_GLOABLE_LR_VALUE : R/W; bitpos: [31:0]; default: 0; @@ -48,11 +48,11 @@ extern "C" { #define ATOMIC_GLOABLE_LR_VALUE_S 0 /** ATOMIC_LOCK_STATUS_REG register - * lock status regsiter + * lock status register */ #define ATOMIC_LOCK_STATUS_REG (DR_REG_ATOMIC_BASE + 0xc) /** ATOMIC_LOCK_STATUS : RO; bitpos: [1:0]; default: 0; - * read hareware lock status for debug + * read hardware lock status for debug */ #define ATOMIC_LOCK_STATUS 0x00000003U #define ATOMIC_LOCK_STATUS_M (ATOMIC_LOCK_STATUS_V << ATOMIC_LOCK_STATUS_S) diff --git a/components/soc/esp32c6/include/soc/hardware_lock_struct.h b/components/soc/esp32c6/register/soc/hardware_lock_struct.h similarity index 92% rename from components/soc/esp32c6/include/soc/hardware_lock_struct.h rename to components/soc/esp32c6/register/soc/hardware_lock_struct.h index 0430212e50df..cbea0bebea03 100644 --- a/components/soc/esp32c6/include/soc/hardware_lock_struct.h +++ b/components/soc/esp32c6/register/soc/hardware_lock_struct.h @@ -12,7 +12,7 @@ extern "C" { /** Group: configuration registers */ /** Type of addr_lock register - * hardware lock regsiter + * hardware lock register */ typedef union { struct { @@ -26,7 +26,7 @@ typedef union { } atomic_addr_lock_reg_t; /** Type of lr_addr register - * gloable lr address regsiter + * gloable lr address register */ typedef union { struct { @@ -39,7 +39,7 @@ typedef union { } atomic_lr_addr_reg_t; /** Type of lr_value register - * gloable lr value regsiter + * gloable lr value register */ typedef union { struct { @@ -52,12 +52,12 @@ typedef union { } atomic_lr_value_reg_t; /** Type of lock_status register - * lock status regsiter + * lock status register */ typedef union { struct { /** lock_status : RO; bitpos: [1:0]; default: 0; - * read hareware lock status for debug + * read hardware lock status for debug */ uint32_t lock_status:2; uint32_t reserved_2:30; diff --git a/components/soc/esp32c6/include/soc/hinf_reg.h b/components/soc/esp32c6/register/soc/hinf_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/hinf_reg.h rename to components/soc/esp32c6/register/soc/hinf_reg.h diff --git a/components/soc/esp32c6/include/soc/hinf_struct.h b/components/soc/esp32c6/register/soc/hinf_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/hinf_struct.h rename to components/soc/esp32c6/register/soc/hinf_struct.h diff --git a/components/soc/esp32c6/include/soc/hmac_reg.h b/components/soc/esp32c6/register/soc/hmac_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/hmac_reg.h rename to components/soc/esp32c6/register/soc/hmac_reg.h diff --git a/components/soc/esp32c6/include/soc/hmac_struct.h b/components/soc/esp32c6/register/soc/hmac_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/hmac_struct.h rename to components/soc/esp32c6/register/soc/hmac_struct.h diff --git a/components/soc/esp32c6/include/soc/host_reg.h b/components/soc/esp32c6/register/soc/host_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/host_reg.h rename to components/soc/esp32c6/register/soc/host_reg.h diff --git a/components/soc/esp32c6/include/soc/host_struct.h b/components/soc/esp32c6/register/soc/host_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/host_struct.h rename to components/soc/esp32c6/register/soc/host_struct.h diff --git a/components/soc/esp32c6/include/soc/hp_apm_reg.h b/components/soc/esp32c6/register/soc/hp_apm_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/hp_apm_reg.h rename to components/soc/esp32c6/register/soc/hp_apm_reg.h diff --git a/components/soc/esp32c6/include/soc/hp_apm_struct.h b/components/soc/esp32c6/register/soc/hp_apm_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/hp_apm_struct.h rename to components/soc/esp32c6/register/soc/hp_apm_struct.h diff --git a/components/soc/esp32c6/include/soc/hp_system_reg.h b/components/soc/esp32c6/register/soc/hp_system_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/hp_system_reg.h rename to components/soc/esp32c6/register/soc/hp_system_reg.h index 898d0fb0e590..f32f280f237e 100644 --- a/components/soc/esp32c6/include/soc/hp_system_reg.h +++ b/components/soc/esp32c6/register/soc/hp_system_reg.h @@ -78,7 +78,7 @@ extern "C" { * 0: anti-DPA disable. 1~3: anti-DPA enable with different security level. The larger * the number, the stronger the ability to resist DPA attacks and the higher the * security level, but it will increase the computational overhead of the hardware - * crypto-accelerators. Only avaliable if HP_SYSTEM_SEC_DPA_CFG_SEL is 0. + * crypto-accelerators. Only available if HP_SYSTEM_SEC_DPA_CFG_SEL is 0. */ #define HP_SYSTEM_SEC_DPA_LEVEL 0x00000003U #define HP_SYSTEM_SEC_DPA_LEVEL_M (HP_SYSTEM_SEC_DPA_LEVEL_V << HP_SYSTEM_SEC_DPA_LEVEL_S) diff --git a/components/soc/esp32c6/include/soc/hp_system_struct.h b/components/soc/esp32c6/register/soc/hp_system_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/hp_system_struct.h rename to components/soc/esp32c6/register/soc/hp_system_struct.h index b174aa4290a8..20b8eac2f883 100644 --- a/components/soc/esp32c6/include/soc/hp_system_struct.h +++ b/components/soc/esp32c6/register/soc/hp_system_struct.h @@ -70,7 +70,7 @@ typedef union { * 0: anti-DPA disable. 1~3: anti-DPA enable with different security level. The larger * the number, the stronger the ability to resist DPA attacks and the higher the * security level, but it will increase the computational overhead of the hardware - * crypto-accelerators. Only avaliable if HP_SYSTEM_SEC_DPA_CFG_SEL is 0. + * crypto-accelerators. Only available if HP_SYSTEM_SEC_DPA_CFG_SEL is 0. */ uint32_t sec_dpa_level:2; /** sec_dpa_cfg_sel : R/W; bitpos: [2]; default: 0; diff --git a/components/soc/esp32c6/include/soc/i2c_ana_mst_reg.h b/components/soc/esp32c6/register/soc/i2c_ana_mst_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/i2c_ana_mst_reg.h rename to components/soc/esp32c6/register/soc/i2c_ana_mst_reg.h diff --git a/components/soc/esp32c6/include/soc/i2c_reg.h b/components/soc/esp32c6/register/soc/i2c_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/i2c_reg.h rename to components/soc/esp32c6/register/soc/i2c_reg.h diff --git a/components/soc/esp32c6/include/soc/i2c_struct.h b/components/soc/esp32c6/register/soc/i2c_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/i2c_struct.h rename to components/soc/esp32c6/register/soc/i2c_struct.h diff --git a/components/soc/esp32c6/include/soc/i2s_reg.h b/components/soc/esp32c6/register/soc/i2s_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/i2s_reg.h rename to components/soc/esp32c6/register/soc/i2s_reg.h index 89fd5eb84444..4f259c1131c9 100644 --- a/components/soc/esp32c6/include/soc/i2s_reg.h +++ b/components/soc/esp32c6/register/soc/i2s_reg.h @@ -361,7 +361,7 @@ extern "C" { #define I2S_TX_PCM_BYPASS_V 0x00000001U #define I2S_TX_PCM_BYPASS_S 12 /** I2S_TX_STOP_EN : R/W; bitpos: [13]; default: 1; - * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty */ #define I2S_TX_STOP_EN (BIT(13)) #define I2S_TX_STOP_EN_M (I2S_TX_STOP_EN_V << I2S_TX_STOP_EN_S) diff --git a/components/soc/esp32c6/include/soc/i2s_struct.h b/components/soc/esp32c6/register/soc/i2s_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/i2s_struct.h rename to components/soc/esp32c6/register/soc/i2s_struct.h index f7b7f069ad96..b7629e4c9890 100644 --- a/components/soc/esp32c6/include/soc/i2s_struct.h +++ b/components/soc/esp32c6/register/soc/i2s_struct.h @@ -494,7 +494,7 @@ typedef union { */ uint32_t tx_pcm_bypass:1; /** tx_stop_en : R/W; bitpos: [13]; default: 1; - * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty */ uint32_t tx_stop_en:1; uint32_t reserved_14:1; diff --git a/components/soc/esp32c6/include/soc/ieee802154_reg.h b/components/soc/esp32c6/register/soc/ieee802154_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/ieee802154_reg.h rename to components/soc/esp32c6/register/soc/ieee802154_reg.h diff --git a/components/soc/esp32c6/include/soc/ieee802154_struct.h b/components/soc/esp32c6/register/soc/ieee802154_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/ieee802154_struct.h rename to components/soc/esp32c6/register/soc/ieee802154_struct.h diff --git a/components/soc/esp32c6/include/soc/interrupt_matrix_reg.h b/components/soc/esp32c6/register/soc/interrupt_matrix_reg.h similarity index 98% rename from components/soc/esp32c6/include/soc/interrupt_matrix_reg.h rename to components/soc/esp32c6/register/soc/interrupt_matrix_reg.h index d5af256a4d05..a2e729de2b7b 100644 --- a/components/soc/esp32c6/include/soc/interrupt_matrix_reg.h +++ b/components/soc/esp32c6/register/soc/interrupt_matrix_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -502,17 +502,17 @@ extern "C" { #define INTMTX_CORE0_MSPI_INTR_MAP_V 0x0000001FU #define INTMTX_CORE0_MSPI_INTR_MAP_S 0 -/** INTMTX_CORE0_I2S1_INTR_MAP_REG register +/** INTMTX_CORE0_I2S_INTR_MAP_REG register * register description */ -#define INTMTX_CORE0_I2S1_INTR_MAP_REG (DR_REG_INTERRUPT_MATRIX_BASE + 0xa4) -/** INTMTX_CORE0_I2S1_INTR_MAP : R/W; bitpos: [4:0]; default: 0; +#define INTMTX_CORE0_I2S_INTR_MAP_REG (DR_REG_INTERRUPT_MATRIX_BASE + 0xa4) +/** INTMTX_CORE0_I2S_INTR_MAP : R/W; bitpos: [4:0]; default: 0; * Need add description */ -#define INTMTX_CORE0_I2S1_INTR_MAP 0x0000001FU -#define INTMTX_CORE0_I2S1_INTR_MAP_M (INTMTX_CORE0_I2S1_INTR_MAP_V << INTMTX_CORE0_I2S1_INTR_MAP_S) -#define INTMTX_CORE0_I2S1_INTR_MAP_V 0x0000001FU -#define INTMTX_CORE0_I2S1_INTR_MAP_S 0 +#define INTMTX_CORE0_I2S_INTR_MAP 0x0000001FU +#define INTMTX_CORE0_I2S_INTR_MAP_M (INTMTX_CORE0_I2S_INTR_MAP_V << INTMTX_CORE0_I2S_INTR_MAP_S) +#define INTMTX_CORE0_I2S_INTR_MAP_V 0x0000001FU +#define INTMTX_CORE0_I2S_INTR_MAP_S 0 /** INTMTX_CORE0_UHCI0_INTR_MAP_REG register * register description diff --git a/components/soc/esp32c6/include/soc/interrupt_matrix_struct.h b/components/soc/esp32c6/register/soc/interrupt_matrix_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/interrupt_matrix_struct.h rename to components/soc/esp32c6/register/soc/interrupt_matrix_struct.h index 4af30c94933f..89d4859ad670 100644 --- a/components/soc/esp32c6/include/soc/interrupt_matrix_struct.h +++ b/components/soc/esp32c6/register/soc/interrupt_matrix_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -585,19 +585,19 @@ typedef union { uint32_t val; } interrupt_matrix_mspi_intr_map_reg_t; -/** Type of i2s1_intr_map register +/** Type of i2s_intr_map register * register description */ typedef union { struct { - /** i2s1_intr_map : R/W; bitpos: [4:0]; default: 0; + /** i2s_intr_map : R/W; bitpos: [4:0]; default: 0; * Need add description */ - uint32_t i2s1_intr_map:5; + uint32_t i2s_intr_map:5; uint32_t reserved_5:27; }; uint32_t val; -} interrupt_matrix_i2s1_intr_map_reg_t; +} interrupt_matrix_i2s_intr_map_reg_t; /** Type of uhci0_intr_map register * register description @@ -1199,7 +1199,7 @@ typedef struct interrupt_matrix_dev_t { volatile interrupt_matrix_hp_apm_m3_intr_map_reg_t hp_apm_m3_intr_map; volatile interrupt_matrix_lp_apm0_intr_map_reg_t lp_apm0_intr_map; volatile interrupt_matrix_mspi_intr_map_reg_t mspi_intr_map; - volatile interrupt_matrix_i2s1_intr_map_reg_t i2s1_intr_map; + volatile interrupt_matrix_i2s_intr_map_reg_t i2s_intr_map; volatile interrupt_matrix_uhci0_intr_map_reg_t uhci0_intr_map; volatile interrupt_matrix_uart0_intr_map_reg_t uart0_intr_map; volatile interrupt_matrix_uart1_intr_map_reg_t uart1_intr_map; diff --git a/components/soc/esp32c6/include/soc/intpri_reg.h b/components/soc/esp32c6/register/soc/intpri_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/intpri_reg.h rename to components/soc/esp32c6/register/soc/intpri_reg.h diff --git a/components/soc/esp32c6/include/soc/intpri_struct.h b/components/soc/esp32c6/register/soc/intpri_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/intpri_struct.h rename to components/soc/esp32c6/register/soc/intpri_struct.h diff --git a/components/soc/esp32c6/include/soc/io_mux_reg.h b/components/soc/esp32c6/register/soc/io_mux_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/io_mux_reg.h rename to components/soc/esp32c6/register/soc/io_mux_reg.h index 698a2b5785b3..0adf0203ef14 100644 --- a/components/soc/esp32c6/include/soc/io_mux_reg.h +++ b/components/soc/esp32c6/register/soc/io_mux_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "soc.h" +#include "soc/soc.h" /* The following are the bit fields for PERIPHS_IO_MUX_x_U registers */ /* Output enable in sleep mode */ diff --git a/components/soc/esp32c6/include/soc/ledc_reg.h b/components/soc/esp32c6/register/soc/ledc_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/ledc_reg.h rename to components/soc/esp32c6/register/soc/ledc_reg.h diff --git a/components/soc/esp32c6/include/soc/ledc_struct.h b/components/soc/esp32c6/register/soc/ledc_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/ledc_struct.h rename to components/soc/esp32c6/register/soc/ledc_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_analog_peri_reg.h b/components/soc/esp32c6/register/soc/lp_analog_peri_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_analog_peri_reg.h rename to components/soc/esp32c6/register/soc/lp_analog_peri_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_analog_peri_struct.h b/components/soc/esp32c6/register/soc/lp_analog_peri_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_analog_peri_struct.h rename to components/soc/esp32c6/register/soc/lp_analog_peri_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_aon_reg.h b/components/soc/esp32c6/register/soc/lp_aon_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_aon_reg.h rename to components/soc/esp32c6/register/soc/lp_aon_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_aon_struct.h b/components/soc/esp32c6/register/soc/lp_aon_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_aon_struct.h rename to components/soc/esp32c6/register/soc/lp_aon_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_apm0_reg.h b/components/soc/esp32c6/register/soc/lp_apm0_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_apm0_reg.h rename to components/soc/esp32c6/register/soc/lp_apm0_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_apm0_struct.h b/components/soc/esp32c6/register/soc/lp_apm0_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_apm0_struct.h rename to components/soc/esp32c6/register/soc/lp_apm0_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_apm_reg.h b/components/soc/esp32c6/register/soc/lp_apm_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_apm_reg.h rename to components/soc/esp32c6/register/soc/lp_apm_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_apm_struct.h b/components/soc/esp32c6/register/soc/lp_apm_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_apm_struct.h rename to components/soc/esp32c6/register/soc/lp_apm_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_clkrst_reg.h b/components/soc/esp32c6/register/soc/lp_clkrst_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_clkrst_reg.h rename to components/soc/esp32c6/register/soc/lp_clkrst_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_clkrst_struct.h b/components/soc/esp32c6/register/soc/lp_clkrst_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_clkrst_struct.h rename to components/soc/esp32c6/register/soc/lp_clkrst_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_i2c_ana_mst_reg.h b/components/soc/esp32c6/register/soc/lp_i2c_ana_mst_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_i2c_ana_mst_reg.h rename to components/soc/esp32c6/register/soc/lp_i2c_ana_mst_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_i2c_ana_mst_struct.h b/components/soc/esp32c6/register/soc/lp_i2c_ana_mst_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_i2c_ana_mst_struct.h rename to components/soc/esp32c6/register/soc/lp_i2c_ana_mst_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_i2c_reg.h b/components/soc/esp32c6/register/soc/lp_i2c_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_i2c_reg.h rename to components/soc/esp32c6/register/soc/lp_i2c_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_i2c_struct.h b/components/soc/esp32c6/register/soc/lp_i2c_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_i2c_struct.h rename to components/soc/esp32c6/register/soc/lp_i2c_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_io_reg.h b/components/soc/esp32c6/register/soc/lp_io_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_io_reg.h rename to components/soc/esp32c6/register/soc/lp_io_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_io_struct.h b/components/soc/esp32c6/register/soc/lp_io_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_io_struct.h rename to components/soc/esp32c6/register/soc/lp_io_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_tee_reg.h b/components/soc/esp32c6/register/soc/lp_tee_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_tee_reg.h rename to components/soc/esp32c6/register/soc/lp_tee_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_tee_struct.h b/components/soc/esp32c6/register/soc/lp_tee_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_tee_struct.h rename to components/soc/esp32c6/register/soc/lp_tee_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_timer_reg.h b/components/soc/esp32c6/register/soc/lp_timer_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_timer_reg.h rename to components/soc/esp32c6/register/soc/lp_timer_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_timer_struct.h b/components/soc/esp32c6/register/soc/lp_timer_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_timer_struct.h rename to components/soc/esp32c6/register/soc/lp_timer_struct.h diff --git a/components/soc/esp32c6/include/soc/lp_uart_reg.h b/components/soc/esp32c6/register/soc/lp_uart_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/lp_uart_reg.h rename to components/soc/esp32c6/register/soc/lp_uart_reg.h index b67fa1b59e80..017abf55f8e0 100644 --- a/components/soc/esp32c6/include/soc/lp_uart_reg.h +++ b/components/soc/esp32c6/register/soc/lp_uart_reg.h @@ -100,7 +100,7 @@ extern "C" { #define LP_UART_RXFIFO_TOUT_INT_RAW_V 0x00000001U #define LP_UART_RXFIFO_TOUT_INT_RAW_S 8 /** LP_UART_SW_XON_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ #define LP_UART_SW_XON_INT_RAW (BIT(9)) @@ -261,7 +261,7 @@ extern "C" { #define LP_UART_TX_BRK_DONE_INT_ST_V 0x00000001U #define LP_UART_TX_BRK_DONE_INT_ST_S 12 /** LP_UART_TX_BRK_IDLE_DONE_INT_ST : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ #define LP_UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) @@ -671,7 +671,7 @@ extern "C" { #define LP_UART_STOP_BIT_NUM_V 0x00000003U #define LP_UART_STOP_BIT_NUM_S 4 /** LP_UART_TXD_BRK : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ #define LP_UART_TXD_BRK (BIT(6)) @@ -1151,7 +1151,7 @@ extern "C" { */ #define LP_UART_TOUT_CONF_SYNC_REG (DR_REG_LP_UART_BASE + 0x64) /** LP_UART_RX_TOUT_EN : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ #define LP_UART_RX_TOUT_EN (BIT(0)) #define LP_UART_RX_TOUT_EN_M (LP_UART_RX_TOUT_EN_V << LP_UART_RX_TOUT_EN_S) diff --git a/components/soc/esp32c6/include/soc/lp_uart_struct.h b/components/soc/esp32c6/register/soc/lp_uart_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/lp_uart_struct.h rename to components/soc/esp32c6/register/soc/lp_uart_struct.h index 122c7d920a95..bc9993276f34 100644 --- a/components/soc/esp32c6/include/soc/lp_uart_struct.h +++ b/components/soc/esp32c6/register/soc/lp_uart_struct.h @@ -49,7 +49,7 @@ typedef union { typedef union { struct { /** rx_tout_en : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ uint32_t rx_tout_en:1; /** rx_tout_flow_dis : R/W; bitpos: [1]; default: 0; @@ -120,7 +120,7 @@ typedef union { */ uint32_t rxfifo_tout:1; /** sw_xon : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ uint32_t sw_xon:1; @@ -224,7 +224,7 @@ typedef union { */ uint32_t tx_brk_done:1; /** tx_brk_idle_done : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ uint32_t tx_brk_idle_done:1; @@ -466,7 +466,7 @@ typedef union { */ uint32_t stop_bit_num:2; /** txd_brk : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ uint32_t txd_brk:1; @@ -1115,7 +1115,7 @@ typedef struct lp_uart_dev_t { volatile lp_uart_id_reg_t id; } lp_uart_dev_t; -// We map the LP_UART instance to the uart_dev_t struct for convinience of using the same HAL/LL. See soc/uart_struct.h +// We map the LP_UART instance to the uart_dev_t struct for convenience of using the same HAL/LL. See soc/uart_struct.h // extern lp_uart_dev_t LP_UART; #ifndef __cplusplus diff --git a/components/soc/esp32c6/include/soc/lp_wdt_reg.h b/components/soc/esp32c6/register/soc/lp_wdt_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_wdt_reg.h rename to components/soc/esp32c6/register/soc/lp_wdt_reg.h diff --git a/components/soc/esp32c6/include/soc/lp_wdt_struct.h b/components/soc/esp32c6/register/soc/lp_wdt_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lp_wdt_struct.h rename to components/soc/esp32c6/register/soc/lp_wdt_struct.h diff --git a/components/soc/esp32c6/include/soc/lpperi_reg.h b/components/soc/esp32c6/register/soc/lpperi_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/lpperi_reg.h rename to components/soc/esp32c6/register/soc/lpperi_reg.h diff --git a/components/soc/esp32c6/include/soc/lpperi_struct.h b/components/soc/esp32c6/register/soc/lpperi_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/lpperi_struct.h rename to components/soc/esp32c6/register/soc/lpperi_struct.h diff --git a/components/soc/esp32c6/include/soc/mcpwm_reg.h b/components/soc/esp32c6/register/soc/mcpwm_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/mcpwm_reg.h rename to components/soc/esp32c6/register/soc/mcpwm_reg.h index 4eacabbc9c5e..4de6f5b9f7fd 100644 --- a/components/soc/esp32c6/include/soc/mcpwm_reg.h +++ b/components/soc/esp32c6/register/soc/mcpwm_reg.h @@ -894,7 +894,7 @@ extern "C" { #define MCPWM_DB0_RED_S 0 /** MCPWM_CARRIER0_CFG_REG register - * Carrier enable and configuratoin + * Carrier enable and configuration */ #define MCPWM_CARRIER0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x64) /** MCPWM_CHOPPER0_EN : R/W; bitpos: [0]; default: 0; @@ -1575,7 +1575,7 @@ extern "C" { #define MCPWM_DB1_RED_S 0 /** MCPWM_CARRIER1_CFG_REG register - * Carrier enable and configuratoin + * Carrier enable and configuration */ #define MCPWM_CARRIER1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x9c) /** MCPWM_CHOPPER1_EN : R/W; bitpos: [0]; default: 0; @@ -2256,7 +2256,7 @@ extern "C" { #define MCPWM_DB2_RED_S 0 /** MCPWM_CARRIER2_CFG_REG register - * Carrier enable and configuratoin + * Carrier enable and configuration */ #define MCPWM_CARRIER2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xd4) /** MCPWM_CHOPPER2_EN : R/W; bitpos: [0]; default: 0; @@ -2621,7 +2621,7 @@ extern "C" { #define MCPWM_CAP0_MODE_V 0x00000003U #define MCPWM_CAP0_MODE_S 1 /** MCPWM_CAP0_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + + * Value of prescaling on positive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + * 1 */ #define MCPWM_CAP0_PRESCALE 0x000000FFU @@ -2664,7 +2664,7 @@ extern "C" { #define MCPWM_CAP1_MODE_V 0x00000003U #define MCPWM_CAP1_MODE_S 1 /** MCPWM_CAP1_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + + * Value of prescaling on positive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + * 1 */ #define MCPWM_CAP1_PRESCALE 0x000000FFU @@ -2707,7 +2707,7 @@ extern "C" { #define MCPWM_CAP2_MODE_V 0x00000003U #define MCPWM_CAP2_MODE_S 1 /** MCPWM_CAP2_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + + * Value of prescaling on positive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + * 1 */ #define MCPWM_CAP2_PRESCALE 0x000000FFU diff --git a/components/soc/esp32c6/include/soc/mcpwm_struct.h b/components/soc/esp32c6/register/soc/mcpwm_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/mcpwm_struct.h rename to components/soc/esp32c6/register/soc/mcpwm_struct.h index 1a91a623f6bc..5fe75f3c99e0 100644 --- a/components/soc/esp32c6/include/soc/mcpwm_struct.h +++ b/components/soc/esp32c6/register/soc/mcpwm_struct.h @@ -462,7 +462,7 @@ typedef union { } mcpwm_dt_red_cfg_reg_t; /** Type of carrier_cfg register - * Carrier enable and configuratoin + * Carrier enable and configuration */ typedef union { struct { @@ -734,7 +734,7 @@ typedef union { */ uint32_t capn_mode:2; /** capn_prescale : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAPn. Prescale value = PWM_CAP0_PRESCALE + + * Value of prescaling on positive edge of CAPn. Prescale value = PWM_CAP0_PRESCALE + * 1 */ uint32_t capn_prescale:8; diff --git a/components/soc/esp32c6/include/soc/mem_monitor_reg.h b/components/soc/esp32c6/register/soc/mem_monitor_reg.h similarity index 98% rename from components/soc/esp32c6/include/soc/mem_monitor_reg.h rename to components/soc/esp32c6/register/soc/mem_monitor_reg.h index fccde61ad72b..b75a52af2122 100644 --- a/components/soc/esp32c6/include/soc/mem_monitor_reg.h +++ b/components/soc/esp32c6/register/soc/mem_monitor_reg.h @@ -12,7 +12,7 @@ extern "C" { #endif /** MEM_MONITOR_LOG_SETTING_REG register - * log config regsiter + * log config register */ #define MEM_MONITOR_LOG_SETTING_REG (DR_REG_MEM_MONITOR_BASE + 0x0) /** MEM_MONITOR_LOG_ENA : R/W; bitpos: [2:0]; default: 0; @@ -39,7 +39,7 @@ extern "C" { #define MEM_MONITOR_LOG_MEM_LOOP_ENABLE_S 7 /** MEM_MONITOR_LOG_CHECK_DATA_REG register - * check data regsiter + * check data register */ #define MEM_MONITOR_LOG_CHECK_DATA_REG (DR_REG_MEM_MONITOR_BASE + 0x4) /** MEM_MONITOR_LOG_CHECK_DATA : R/W; bitpos: [31:0]; default: 0; @@ -64,7 +64,7 @@ extern "C" { #define MEM_MONITOR_LOG_DATA_MASK_S 0 /** MEM_MONITOR_LOG_MIN_REG register - * log boundary regsiter + * log boundary register */ #define MEM_MONITOR_LOG_MIN_REG (DR_REG_MEM_MONITOR_BASE + 0xc) /** MEM_MONITOR_LOG_MIN : R/W; bitpos: [31:0]; default: 0; @@ -76,7 +76,7 @@ extern "C" { #define MEM_MONITOR_LOG_MIN_S 0 /** MEM_MONITOR_LOG_MAX_REG register - * log boundary regsiter + * log boundary register */ #define MEM_MONITOR_LOG_MAX_REG (DR_REG_MEM_MONITOR_BASE + 0x10) /** MEM_MONITOR_LOG_MAX : R/W; bitpos: [31:0]; default: 0; diff --git a/components/soc/esp32c6/include/soc/mem_monitor_struct.h b/components/soc/esp32c6/register/soc/mem_monitor_struct.h similarity index 98% rename from components/soc/esp32c6/include/soc/mem_monitor_struct.h rename to components/soc/esp32c6/register/soc/mem_monitor_struct.h index 6fd735edf544..862959b9494c 100644 --- a/components/soc/esp32c6/include/soc/mem_monitor_struct.h +++ b/components/soc/esp32c6/register/soc/mem_monitor_struct.h @@ -12,7 +12,7 @@ extern "C" { /** Group: configuration registers */ /** Type of log_setting register - * log config regsiter + * log config register */ typedef union { struct { @@ -35,7 +35,7 @@ typedef union { } mem_monitor_log_setting_reg_t; /** Type of log_check_data register - * check data regsiter + * check data register */ typedef union { struct { @@ -63,7 +63,7 @@ typedef union { } mem_monitor_log_data_mask_reg_t; /** Type of log_min register - * log boundary regsiter + * log boundary register */ typedef union { struct { @@ -76,7 +76,7 @@ typedef union { } mem_monitor_log_min_reg_t; /** Type of log_max register - * log boundary regsiter + * log boundary register */ typedef union { struct { diff --git a/components/soc/esp32c6/include/soc/otp_debug_reg.h b/components/soc/esp32c6/register/soc/otp_debug_reg.h similarity index 91% rename from components/soc/esp32c6/include/soc/otp_debug_reg.h rename to components/soc/esp32c6/register/soc/otp_debug_reg.h index 6d0e84c69f1a..49d1754d4f5b 100644 --- a/components/soc/esp32c6/include/soc/otp_debug_reg.h +++ b/components/soc/esp32c6/register/soc/otp_debug_reg.h @@ -12,7 +12,7 @@ extern "C" { #endif /** OTP_DEBUG_WR_DIS_REG register - * Otp debuger block0 data register1. + * Otp debugger block0 data register1. */ #define OTP_DEBUG_WR_DIS_REG (DR_REG_OTP_DEBUG_BASE + 0x0) /** OTP_DEBUG_BLOCK0_WR_DIS : RO; bitpos: [31:0]; default: 0; @@ -24,7 +24,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_WR_DIS_S 0 /** OTP_DEBUG_BLK0_BACKUP1_W1_REG register - * Otp debuger block0 data register2. + * Otp debugger block0 data register2. */ #define OTP_DEBUG_BLK0_BACKUP1_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x4) /** OTP_DEBUG_BLOCK0_BACKUP1_W1 : RO; bitpos: [31:0]; default: 0; @@ -36,7 +36,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP1_W1_S 0 /** OTP_DEBUG_BLK0_BACKUP1_W2_REG register - * Otp debuger block0 data register3. + * Otp debugger block0 data register3. */ #define OTP_DEBUG_BLK0_BACKUP1_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x8) /** OTP_DEBUG_BLOCK0_BACKUP1_W2 : RO; bitpos: [31:0]; default: 0; @@ -48,7 +48,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP1_W2_S 0 /** OTP_DEBUG_BLK0_BACKUP1_W3_REG register - * Otp debuger block0 data register4. + * Otp debugger block0 data register4. */ #define OTP_DEBUG_BLK0_BACKUP1_W3_REG (DR_REG_OTP_DEBUG_BASE + 0xc) /** OTP_DEBUG_BLOCK0_BACKUP1_W3 : RO; bitpos: [31:0]; default: 0; @@ -60,7 +60,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP1_W3_S 0 /** OTP_DEBUG_BLK0_BACKUP1_W4_REG register - * Otp debuger block0 data register5. + * Otp debugger block0 data register5. */ #define OTP_DEBUG_BLK0_BACKUP1_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x10) /** OTP_DEBUG_BLOCK0_BACKUP1_W4 : RO; bitpos: [31:0]; default: 0; @@ -72,7 +72,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP1_W4_S 0 /** OTP_DEBUG_BLK0_BACKUP1_W5_REG register - * Otp debuger block0 data register6. + * Otp debugger block0 data register6. */ #define OTP_DEBUG_BLK0_BACKUP1_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x14) /** OTP_DEBUG_BLOCK0_BACKUP1_W5 : RO; bitpos: [31:0]; default: 0; @@ -84,7 +84,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP1_W5_S 0 /** OTP_DEBUG_BLK0_BACKUP2_W1_REG register - * Otp debuger block0 data register7. + * Otp debugger block0 data register7. */ #define OTP_DEBUG_BLK0_BACKUP2_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x18) /** OTP_DEBUG_BLOCK0_BACKUP2_W1 : RO; bitpos: [31:0]; default: 0; @@ -96,7 +96,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP2_W1_S 0 /** OTP_DEBUG_BLK0_BACKUP2_W2_REG register - * Otp debuger block0 data register8. + * Otp debugger block0 data register8. */ #define OTP_DEBUG_BLK0_BACKUP2_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x1c) /** OTP_DEBUG_BLOCK0_BACKUP2_W2 : RO; bitpos: [31:0]; default: 0; @@ -108,7 +108,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP2_W2_S 0 /** OTP_DEBUG_BLK0_BACKUP2_W3_REG register - * Otp debuger block0 data register9. + * Otp debugger block0 data register9. */ #define OTP_DEBUG_BLK0_BACKUP2_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x20) /** OTP_DEBUG_BLOCK0_BACKUP2_W3 : RO; bitpos: [31:0]; default: 0; @@ -120,7 +120,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP2_W3_S 0 /** OTP_DEBUG_BLK0_BACKUP2_W4_REG register - * Otp debuger block0 data register10. + * Otp debugger block0 data register10. */ #define OTP_DEBUG_BLK0_BACKUP2_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x24) /** OTP_DEBUG_BLOCK0_BACKUP2_W4 : RO; bitpos: [31:0]; default: 0; @@ -132,7 +132,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP2_W4_S 0 /** OTP_DEBUG_BLK0_BACKUP2_W5_REG register - * Otp debuger block0 data register11. + * Otp debugger block0 data register11. */ #define OTP_DEBUG_BLK0_BACKUP2_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x28) /** OTP_DEBUG_BLOCK0_BACKUP2_W5 : RO; bitpos: [31:0]; default: 0; @@ -144,7 +144,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP2_W5_S 0 /** OTP_DEBUG_BLK0_BACKUP3_W1_REG register - * Otp debuger block0 data register12. + * Otp debugger block0 data register12. */ #define OTP_DEBUG_BLK0_BACKUP3_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x2c) /** OTP_DEBUG_BLOCK0_BACKUP3_W1 : RO; bitpos: [31:0]; default: 0; @@ -156,7 +156,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP3_W1_S 0 /** OTP_DEBUG_BLK0_BACKUP3_W2_REG register - * Otp debuger block0 data register13. + * Otp debugger block0 data register13. */ #define OTP_DEBUG_BLK0_BACKUP3_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x30) /** OTP_DEBUG_BLOCK0_BACKUP3_W2 : RO; bitpos: [31:0]; default: 0; @@ -168,7 +168,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP3_W2_S 0 /** OTP_DEBUG_BLK0_BACKUP3_W3_REG register - * Otp debuger block0 data register14. + * Otp debugger block0 data register14. */ #define OTP_DEBUG_BLK0_BACKUP3_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x34) /** OTP_DEBUG_BLOCK0_BACKUP3_W3 : RO; bitpos: [31:0]; default: 0; @@ -180,7 +180,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP3_W3_S 0 /** OTP_DEBUG_BLK0_BACKUP3_W4_REG register - * Otp debuger block0 data register15. + * Otp debugger block0 data register15. */ #define OTP_DEBUG_BLK0_BACKUP3_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x38) /** OTP_DEBUG_BLOCK0_BACKUP3_W4 : RO; bitpos: [31:0]; default: 0; @@ -192,7 +192,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP3_W4_S 0 /** OTP_DEBUG_BLK0_BACKUP3_W5_REG register - * Otp debuger block0 data register16. + * Otp debugger block0 data register16. */ #define OTP_DEBUG_BLK0_BACKUP3_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x3c) /** OTP_DEBUG_BLOCK0_BACKUP3_W5 : RO; bitpos: [31:0]; default: 0; @@ -204,7 +204,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP3_W5_S 0 /** OTP_DEBUG_BLK0_BACKUP4_W1_REG register - * Otp debuger block0 data register17. + * Otp debugger block0 data register17. */ #define OTP_DEBUG_BLK0_BACKUP4_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x40) /** OTP_DEBUG_BLOCK0_BACKUP4_W1 : RO; bitpos: [31:0]; default: 0; @@ -216,7 +216,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP4_W1_S 0 /** OTP_DEBUG_BLK0_BACKUP4_W2_REG register - * Otp debuger block0 data register18. + * Otp debugger block0 data register18. */ #define OTP_DEBUG_BLK0_BACKUP4_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x44) /** OTP_DEBUG_BLOCK0_BACKUP4_W2 : RO; bitpos: [31:0]; default: 0; @@ -228,7 +228,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP4_W2_S 0 /** OTP_DEBUG_BLK0_BACKUP4_W3_REG register - * Otp debuger block0 data register19. + * Otp debugger block0 data register19. */ #define OTP_DEBUG_BLK0_BACKUP4_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x48) /** OTP_DEBUG_BLOCK0_BACKUP4_W3 : RO; bitpos: [31:0]; default: 0; @@ -240,7 +240,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP4_W3_S 0 /** OTP_DEBUG_BLK0_BACKUP4_W4_REG register - * Otp debuger block0 data register20. + * Otp debugger block0 data register20. */ #define OTP_DEBUG_BLK0_BACKUP4_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x4c) /** OTP_DEBUG_BLOCK0_BACKUP4_W4 : RO; bitpos: [31:0]; default: 0; @@ -252,7 +252,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP4_W4_S 0 /** OTP_DEBUG_BLK0_BACKUP4_W5_REG register - * Otp debuger block0 data register21. + * Otp debugger block0 data register21. */ #define OTP_DEBUG_BLK0_BACKUP4_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x50) /** OTP_DEBUG_BLOCK0_BACKUP4_W5 : RO; bitpos: [31:0]; default: 0; @@ -264,7 +264,7 @@ extern "C" { #define OTP_DEBUG_BLOCK0_BACKUP4_W5_S 0 /** OTP_DEBUG_BLK1_W1_REG register - * Otp debuger block1 data register1. + * Otp debugger block1 data register1. */ #define OTP_DEBUG_BLK1_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x54) /** OTP_DEBUG_BLOCK1_W1 : RO; bitpos: [31:0]; default: 0; @@ -276,7 +276,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W1_S 0 /** OTP_DEBUG_BLK1_W2_REG register - * Otp debuger block1 data register2. + * Otp debugger block1 data register2. */ #define OTP_DEBUG_BLK1_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x58) /** OTP_DEBUG_BLOCK1_W2 : RO; bitpos: [31:0]; default: 0; @@ -288,7 +288,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W2_S 0 /** OTP_DEBUG_BLK1_W3_REG register - * Otp debuger block1 data register3. + * Otp debugger block1 data register3. */ #define OTP_DEBUG_BLK1_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x5c) /** OTP_DEBUG_BLOCK1_W3 : RO; bitpos: [31:0]; default: 0; @@ -300,7 +300,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W3_S 0 /** OTP_DEBUG_BLK1_W4_REG register - * Otp debuger block1 data register4. + * Otp debugger block1 data register4. */ #define OTP_DEBUG_BLK1_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x60) /** OTP_DEBUG_BLOCK1_W4 : RO; bitpos: [31:0]; default: 0; @@ -312,7 +312,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W4_S 0 /** OTP_DEBUG_BLK1_W5_REG register - * Otp debuger block1 data register5. + * Otp debugger block1 data register5. */ #define OTP_DEBUG_BLK1_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x64) /** OTP_DEBUG_BLOCK1_W5 : RO; bitpos: [31:0]; default: 0; @@ -324,7 +324,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W5_S 0 /** OTP_DEBUG_BLK1_W6_REG register - * Otp debuger block1 data register6. + * Otp debugger block1 data register6. */ #define OTP_DEBUG_BLK1_W6_REG (DR_REG_OTP_DEBUG_BASE + 0x68) /** OTP_DEBUG_BLOCK1_W6 : RO; bitpos: [31:0]; default: 0; @@ -336,7 +336,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W6_S 0 /** OTP_DEBUG_BLK1_W7_REG register - * Otp debuger block1 data register7. + * Otp debugger block1 data register7. */ #define OTP_DEBUG_BLK1_W7_REG (DR_REG_OTP_DEBUG_BASE + 0x6c) /** OTP_DEBUG_BLOCK1_W7 : RO; bitpos: [31:0]; default: 0; @@ -348,7 +348,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W7_S 0 /** OTP_DEBUG_BLK1_W8_REG register - * Otp debuger block1 data register8. + * Otp debugger block1 data register8. */ #define OTP_DEBUG_BLK1_W8_REG (DR_REG_OTP_DEBUG_BASE + 0x70) /** OTP_DEBUG_BLOCK1_W8 : RO; bitpos: [31:0]; default: 0; @@ -360,7 +360,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W8_S 0 /** OTP_DEBUG_BLK1_W9_REG register - * Otp debuger block1 data register9. + * Otp debugger block1 data register9. */ #define OTP_DEBUG_BLK1_W9_REG (DR_REG_OTP_DEBUG_BASE + 0x74) /** OTP_DEBUG_BLOCK1_W9 : RO; bitpos: [31:0]; default: 0; @@ -372,7 +372,7 @@ extern "C" { #define OTP_DEBUG_BLOCK1_W9_S 0 /** OTP_DEBUG_BLK2_W1_REG register - * Otp debuger block2 data register1. + * Otp debugger block2 data register1. */ #define OTP_DEBUG_BLK2_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x78) /** OTP_DEBUG_BLOCK2_W1 : RO; bitpos: [31:0]; default: 0; @@ -384,7 +384,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W1_S 0 /** OTP_DEBUG_BLK2_W2_REG register - * Otp debuger block2 data register2. + * Otp debugger block2 data register2. */ #define OTP_DEBUG_BLK2_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x7c) /** OTP_DEBUG_BLOCK2_W2 : RO; bitpos: [31:0]; default: 0; @@ -396,7 +396,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W2_S 0 /** OTP_DEBUG_BLK2_W3_REG register - * Otp debuger block2 data register3. + * Otp debugger block2 data register3. */ #define OTP_DEBUG_BLK2_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x80) /** OTP_DEBUG_BLOCK2_W3 : RO; bitpos: [31:0]; default: 0; @@ -408,7 +408,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W3_S 0 /** OTP_DEBUG_BLK2_W4_REG register - * Otp debuger block2 data register4. + * Otp debugger block2 data register4. */ #define OTP_DEBUG_BLK2_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x84) /** OTP_DEBUG_BLOCK2_W4 : RO; bitpos: [31:0]; default: 0; @@ -420,7 +420,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W4_S 0 /** OTP_DEBUG_BLK2_W5_REG register - * Otp debuger block2 data register5. + * Otp debugger block2 data register5. */ #define OTP_DEBUG_BLK2_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x88) /** OTP_DEBUG_BLOCK2_W5 : RO; bitpos: [31:0]; default: 0; @@ -432,7 +432,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W5_S 0 /** OTP_DEBUG_BLK2_W6_REG register - * Otp debuger block2 data register6. + * Otp debugger block2 data register6. */ #define OTP_DEBUG_BLK2_W6_REG (DR_REG_OTP_DEBUG_BASE + 0x8c) /** OTP_DEBUG_BLOCK2_W6 : RO; bitpos: [31:0]; default: 0; @@ -444,7 +444,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W6_S 0 /** OTP_DEBUG_BLK2_W7_REG register - * Otp debuger block2 data register7. + * Otp debugger block2 data register7. */ #define OTP_DEBUG_BLK2_W7_REG (DR_REG_OTP_DEBUG_BASE + 0x90) /** OTP_DEBUG_BLOCK2_W7 : RO; bitpos: [31:0]; default: 0; @@ -456,7 +456,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W7_S 0 /** OTP_DEBUG_BLK2_W8_REG register - * Otp debuger block2 data register8. + * Otp debugger block2 data register8. */ #define OTP_DEBUG_BLK2_W8_REG (DR_REG_OTP_DEBUG_BASE + 0x94) /** OTP_DEBUG_BLOCK2_W8 : RO; bitpos: [31:0]; default: 0; @@ -468,7 +468,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W8_S 0 /** OTP_DEBUG_BLK2_W9_REG register - * Otp debuger block2 data register9. + * Otp debugger block2 data register9. */ #define OTP_DEBUG_BLK2_W9_REG (DR_REG_OTP_DEBUG_BASE + 0x98) /** OTP_DEBUG_BLOCK2_W9 : RO; bitpos: [31:0]; default: 0; @@ -480,7 +480,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W9_S 0 /** OTP_DEBUG_BLK2_W10_REG register - * Otp debuger block2 data register10. + * Otp debugger block2 data register10. */ #define OTP_DEBUG_BLK2_W10_REG (DR_REG_OTP_DEBUG_BASE + 0x9c) /** OTP_DEBUG_BLOCK2_W10 : RO; bitpos: [31:0]; default: 0; @@ -492,7 +492,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W10_S 0 /** OTP_DEBUG_BLK2_W11_REG register - * Otp debuger block2 data register11. + * Otp debugger block2 data register11. */ #define OTP_DEBUG_BLK2_W11_REG (DR_REG_OTP_DEBUG_BASE + 0xa0) /** OTP_DEBUG_BLOCK2_W11 : RO; bitpos: [31:0]; default: 0; @@ -504,7 +504,7 @@ extern "C" { #define OTP_DEBUG_BLOCK2_W11_S 0 /** OTP_DEBUG_BLK3_W1_REG register - * Otp debuger block3 data register1. + * Otp debugger block3 data register1. */ #define OTP_DEBUG_BLK3_W1_REG (DR_REG_OTP_DEBUG_BASE + 0xa4) /** OTP_DEBUG_BLOCK3_W1 : RO; bitpos: [31:0]; default: 0; @@ -516,7 +516,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W1_S 0 /** OTP_DEBUG_BLK3_W2_REG register - * Otp debuger block3 data register2. + * Otp debugger block3 data register2. */ #define OTP_DEBUG_BLK3_W2_REG (DR_REG_OTP_DEBUG_BASE + 0xa8) /** OTP_DEBUG_BLOCK3_W2 : RO; bitpos: [31:0]; default: 0; @@ -528,7 +528,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W2_S 0 /** OTP_DEBUG_BLK3_W3_REG register - * Otp debuger block3 data register3. + * Otp debugger block3 data register3. */ #define OTP_DEBUG_BLK3_W3_REG (DR_REG_OTP_DEBUG_BASE + 0xac) /** OTP_DEBUG_BLOCK3_W3 : RO; bitpos: [31:0]; default: 0; @@ -540,7 +540,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W3_S 0 /** OTP_DEBUG_BLK3_W4_REG register - * Otp debuger block3 data register4. + * Otp debugger block3 data register4. */ #define OTP_DEBUG_BLK3_W4_REG (DR_REG_OTP_DEBUG_BASE + 0xb0) /** OTP_DEBUG_BLOCK3_W4 : RO; bitpos: [31:0]; default: 0; @@ -552,7 +552,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W4_S 0 /** OTP_DEBUG_BLK3_W5_REG register - * Otp debuger block3 data register5. + * Otp debugger block3 data register5. */ #define OTP_DEBUG_BLK3_W5_REG (DR_REG_OTP_DEBUG_BASE + 0xb4) /** OTP_DEBUG_BLOCK3_W5 : RO; bitpos: [31:0]; default: 0; @@ -564,7 +564,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W5_S 0 /** OTP_DEBUG_BLK3_W6_REG register - * Otp debuger block3 data register6. + * Otp debugger block3 data register6. */ #define OTP_DEBUG_BLK3_W6_REG (DR_REG_OTP_DEBUG_BASE + 0xb8) /** OTP_DEBUG_BLOCK3_W6 : RO; bitpos: [31:0]; default: 0; @@ -576,7 +576,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W6_S 0 /** OTP_DEBUG_BLK3_W7_REG register - * Otp debuger block3 data register7. + * Otp debugger block3 data register7. */ #define OTP_DEBUG_BLK3_W7_REG (DR_REG_OTP_DEBUG_BASE + 0xbc) /** OTP_DEBUG_BLOCK3_W7 : RO; bitpos: [31:0]; default: 0; @@ -588,7 +588,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W7_S 0 /** OTP_DEBUG_BLK3_W8_REG register - * Otp debuger block3 data register8. + * Otp debugger block3 data register8. */ #define OTP_DEBUG_BLK3_W8_REG (DR_REG_OTP_DEBUG_BASE + 0xc0) /** OTP_DEBUG_BLOCK3_W8 : RO; bitpos: [31:0]; default: 0; @@ -600,7 +600,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W8_S 0 /** OTP_DEBUG_BLK3_W9_REG register - * Otp debuger block3 data register9. + * Otp debugger block3 data register9. */ #define OTP_DEBUG_BLK3_W9_REG (DR_REG_OTP_DEBUG_BASE + 0xc4) /** OTP_DEBUG_BLOCK3_W9 : RO; bitpos: [31:0]; default: 0; @@ -612,7 +612,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W9_S 0 /** OTP_DEBUG_BLK3_W10_REG register - * Otp debuger block3 data register10. + * Otp debugger block3 data register10. */ #define OTP_DEBUG_BLK3_W10_REG (DR_REG_OTP_DEBUG_BASE + 0xc8) /** OTP_DEBUG_BLOCK3_W10 : RO; bitpos: [31:0]; default: 0; @@ -624,7 +624,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W10_S 0 /** OTP_DEBUG_BLK3_W11_REG register - * Otp debuger block3 data register11. + * Otp debugger block3 data register11. */ #define OTP_DEBUG_BLK3_W11_REG (DR_REG_OTP_DEBUG_BASE + 0xcc) /** OTP_DEBUG_BLOCK3_W11 : RO; bitpos: [31:0]; default: 0; @@ -636,7 +636,7 @@ extern "C" { #define OTP_DEBUG_BLOCK3_W11_S 0 /** OTP_DEBUG_BLK4_W1_REG register - * Otp debuger block4 data register1. + * Otp debugger block4 data register1. */ #define OTP_DEBUG_BLK4_W1_REG (DR_REG_OTP_DEBUG_BASE + 0xd0) /** OTP_DEBUG_BLOCK4_W1 : RO; bitpos: [31:0]; default: 0; @@ -648,7 +648,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W1_S 0 /** OTP_DEBUG_BLK4_W2_REG register - * Otp debuger block4 data register2. + * Otp debugger block4 data register2. */ #define OTP_DEBUG_BLK4_W2_REG (DR_REG_OTP_DEBUG_BASE + 0xd4) /** OTP_DEBUG_BLOCK4_W2 : RO; bitpos: [31:0]; default: 0; @@ -660,7 +660,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W2_S 0 /** OTP_DEBUG_BLK4_W3_REG register - * Otp debuger block4 data register3. + * Otp debugger block4 data register3. */ #define OTP_DEBUG_BLK4_W3_REG (DR_REG_OTP_DEBUG_BASE + 0xd8) /** OTP_DEBUG_BLOCK4_W3 : RO; bitpos: [31:0]; default: 0; @@ -672,7 +672,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W3_S 0 /** OTP_DEBUG_BLK4_W4_REG register - * Otp debuger block4 data register4. + * Otp debugger block4 data register4. */ #define OTP_DEBUG_BLK4_W4_REG (DR_REG_OTP_DEBUG_BASE + 0xdc) /** OTP_DEBUG_BLOCK4_W4 : RO; bitpos: [31:0]; default: 0; @@ -684,7 +684,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W4_S 0 /** OTP_DEBUG_BLK4_W5_REG register - * Otp debuger block4 data register5. + * Otp debugger block4 data register5. */ #define OTP_DEBUG_BLK4_W5_REG (DR_REG_OTP_DEBUG_BASE + 0xe0) /** OTP_DEBUG_BLOCK4_W5 : RO; bitpos: [31:0]; default: 0; @@ -696,7 +696,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W5_S 0 /** OTP_DEBUG_BLK4_W6_REG register - * Otp debuger block4 data register6. + * Otp debugger block4 data register6. */ #define OTP_DEBUG_BLK4_W6_REG (DR_REG_OTP_DEBUG_BASE + 0xe4) /** OTP_DEBUG_BLOCK4_W6 : RO; bitpos: [31:0]; default: 0; @@ -708,7 +708,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W6_S 0 /** OTP_DEBUG_BLK4_W7_REG register - * Otp debuger block4 data register7. + * Otp debugger block4 data register7. */ #define OTP_DEBUG_BLK4_W7_REG (DR_REG_OTP_DEBUG_BASE + 0xe8) /** OTP_DEBUG_BLOCK4_W7 : RO; bitpos: [31:0]; default: 0; @@ -720,7 +720,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W7_S 0 /** OTP_DEBUG_BLK4_W8_REG register - * Otp debuger block4 data register8. + * Otp debugger block4 data register8. */ #define OTP_DEBUG_BLK4_W8_REG (DR_REG_OTP_DEBUG_BASE + 0xec) /** OTP_DEBUG_BLOCK4_W8 : RO; bitpos: [31:0]; default: 0; @@ -732,7 +732,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W8_S 0 /** OTP_DEBUG_BLK4_W9_REG register - * Otp debuger block4 data register9. + * Otp debugger block4 data register9. */ #define OTP_DEBUG_BLK4_W9_REG (DR_REG_OTP_DEBUG_BASE + 0xf0) /** OTP_DEBUG_BLOCK4_W9 : RO; bitpos: [31:0]; default: 0; @@ -744,7 +744,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W9_S 0 /** OTP_DEBUG_BLK4_W10_REG register - * Otp debuger block4 data registe10. + * Otp debugger block4 data registe10. */ #define OTP_DEBUG_BLK4_W10_REG (DR_REG_OTP_DEBUG_BASE + 0xf4) /** OTP_DEBUG_BLOCK4_W10 : RO; bitpos: [31:0]; default: 0; @@ -756,7 +756,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W10_S 0 /** OTP_DEBUG_BLK4_W11_REG register - * Otp debuger block4 data register11. + * Otp debugger block4 data register11. */ #define OTP_DEBUG_BLK4_W11_REG (DR_REG_OTP_DEBUG_BASE + 0xf8) /** OTP_DEBUG_BLOCK4_W11 : RO; bitpos: [31:0]; default: 0; @@ -768,7 +768,7 @@ extern "C" { #define OTP_DEBUG_BLOCK4_W11_S 0 /** OTP_DEBUG_BLK5_W1_REG register - * Otp debuger block5 data register1. + * Otp debugger block5 data register1. */ #define OTP_DEBUG_BLK5_W1_REG (DR_REG_OTP_DEBUG_BASE + 0xfc) /** OTP_DEBUG_BLOCK5_W1 : RO; bitpos: [31:0]; default: 0; @@ -780,7 +780,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W1_S 0 /** OTP_DEBUG_BLK5_W2_REG register - * Otp debuger block5 data register2. + * Otp debugger block5 data register2. */ #define OTP_DEBUG_BLK5_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x100) /** OTP_DEBUG_BLOCK5_W2 : RO; bitpos: [31:0]; default: 0; @@ -792,7 +792,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W2_S 0 /** OTP_DEBUG_BLK5_W3_REG register - * Otp debuger block5 data register3. + * Otp debugger block5 data register3. */ #define OTP_DEBUG_BLK5_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x104) /** OTP_DEBUG_BLOCK5_W3 : RO; bitpos: [31:0]; default: 0; @@ -804,7 +804,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W3_S 0 /** OTP_DEBUG_BLK5_W4_REG register - * Otp debuger block5 data register4. + * Otp debugger block5 data register4. */ #define OTP_DEBUG_BLK5_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x108) /** OTP_DEBUG_BLOCK5_W4 : RO; bitpos: [31:0]; default: 0; @@ -816,7 +816,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W4_S 0 /** OTP_DEBUG_BLK5_W5_REG register - * Otp debuger block5 data register5. + * Otp debugger block5 data register5. */ #define OTP_DEBUG_BLK5_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x10c) /** OTP_DEBUG_BLOCK5_W5 : RO; bitpos: [31:0]; default: 0; @@ -828,7 +828,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W5_S 0 /** OTP_DEBUG_BLK5_W6_REG register - * Otp debuger block5 data register6. + * Otp debugger block5 data register6. */ #define OTP_DEBUG_BLK5_W6_REG (DR_REG_OTP_DEBUG_BASE + 0x110) /** OTP_DEBUG_BLOCK5_W6 : RO; bitpos: [31:0]; default: 0; @@ -840,7 +840,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W6_S 0 /** OTP_DEBUG_BLK5_W7_REG register - * Otp debuger block5 data register7. + * Otp debugger block5 data register7. */ #define OTP_DEBUG_BLK5_W7_REG (DR_REG_OTP_DEBUG_BASE + 0x114) /** OTP_DEBUG_BLOCK5_W7 : RO; bitpos: [31:0]; default: 0; @@ -852,7 +852,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W7_S 0 /** OTP_DEBUG_BLK5_W8_REG register - * Otp debuger block5 data register8. + * Otp debugger block5 data register8. */ #define OTP_DEBUG_BLK5_W8_REG (DR_REG_OTP_DEBUG_BASE + 0x118) /** OTP_DEBUG_BLOCK5_W8 : RO; bitpos: [31:0]; default: 0; @@ -864,7 +864,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W8_S 0 /** OTP_DEBUG_BLK5_W9_REG register - * Otp debuger block5 data register9. + * Otp debugger block5 data register9. */ #define OTP_DEBUG_BLK5_W9_REG (DR_REG_OTP_DEBUG_BASE + 0x11c) /** OTP_DEBUG_BLOCK5_W9 : RO; bitpos: [31:0]; default: 0; @@ -876,7 +876,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W9_S 0 /** OTP_DEBUG_BLK5_W10_REG register - * Otp debuger block5 data register10. + * Otp debugger block5 data register10. */ #define OTP_DEBUG_BLK5_W10_REG (DR_REG_OTP_DEBUG_BASE + 0x120) /** OTP_DEBUG_BLOCK5_W10 : RO; bitpos: [31:0]; default: 0; @@ -888,7 +888,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W10_S 0 /** OTP_DEBUG_BLK5_W11_REG register - * Otp debuger block5 data register11. + * Otp debugger block5 data register11. */ #define OTP_DEBUG_BLK5_W11_REG (DR_REG_OTP_DEBUG_BASE + 0x124) /** OTP_DEBUG_BLOCK5_W11 : RO; bitpos: [31:0]; default: 0; @@ -900,7 +900,7 @@ extern "C" { #define OTP_DEBUG_BLOCK5_W11_S 0 /** OTP_DEBUG_BLK6_W1_REG register - * Otp debuger block6 data register1. + * Otp debugger block6 data register1. */ #define OTP_DEBUG_BLK6_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x128) /** OTP_DEBUG_BLOCK6_W1 : RO; bitpos: [31:0]; default: 0; @@ -912,7 +912,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W1_S 0 /** OTP_DEBUG_BLK6_W2_REG register - * Otp debuger block6 data register2. + * Otp debugger block6 data register2. */ #define OTP_DEBUG_BLK6_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x12c) /** OTP_DEBUG_BLOCK6_W2 : RO; bitpos: [31:0]; default: 0; @@ -924,7 +924,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W2_S 0 /** OTP_DEBUG_BLK6_W3_REG register - * Otp debuger block6 data register3. + * Otp debugger block6 data register3. */ #define OTP_DEBUG_BLK6_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x130) /** OTP_DEBUG_BLOCK6_W3 : RO; bitpos: [31:0]; default: 0; @@ -936,7 +936,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W3_S 0 /** OTP_DEBUG_BLK6_W4_REG register - * Otp debuger block6 data register4. + * Otp debugger block6 data register4. */ #define OTP_DEBUG_BLK6_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x134) /** OTP_DEBUG_BLOCK6_W4 : RO; bitpos: [31:0]; default: 0; @@ -948,7 +948,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W4_S 0 /** OTP_DEBUG_BLK6_W5_REG register - * Otp debuger block6 data register5. + * Otp debugger block6 data register5. */ #define OTP_DEBUG_BLK6_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x138) /** OTP_DEBUG_BLOCK6_W5 : RO; bitpos: [31:0]; default: 0; @@ -960,7 +960,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W5_S 0 /** OTP_DEBUG_BLK6_W6_REG register - * Otp debuger block6 data register6. + * Otp debugger block6 data register6. */ #define OTP_DEBUG_BLK6_W6_REG (DR_REG_OTP_DEBUG_BASE + 0x13c) /** OTP_DEBUG_BLOCK6_W6 : RO; bitpos: [31:0]; default: 0; @@ -972,7 +972,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W6_S 0 /** OTP_DEBUG_BLK6_W7_REG register - * Otp debuger block6 data register7. + * Otp debugger block6 data register7. */ #define OTP_DEBUG_BLK6_W7_REG (DR_REG_OTP_DEBUG_BASE + 0x140) /** OTP_DEBUG_BLOCK6_W7 : RO; bitpos: [31:0]; default: 0; @@ -984,7 +984,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W7_S 0 /** OTP_DEBUG_BLK6_W8_REG register - * Otp debuger block6 data register8. + * Otp debugger block6 data register8. */ #define OTP_DEBUG_BLK6_W8_REG (DR_REG_OTP_DEBUG_BASE + 0x144) /** OTP_DEBUG_BLOCK6_W8 : RO; bitpos: [31:0]; default: 0; @@ -996,7 +996,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W8_S 0 /** OTP_DEBUG_BLK6_W9_REG register - * Otp debuger block6 data register9. + * Otp debugger block6 data register9. */ #define OTP_DEBUG_BLK6_W9_REG (DR_REG_OTP_DEBUG_BASE + 0x148) /** OTP_DEBUG_BLOCK6_W9 : RO; bitpos: [31:0]; default: 0; @@ -1008,7 +1008,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W9_S 0 /** OTP_DEBUG_BLK6_W10_REG register - * Otp debuger block6 data register10. + * Otp debugger block6 data register10. */ #define OTP_DEBUG_BLK6_W10_REG (DR_REG_OTP_DEBUG_BASE + 0x14c) /** OTP_DEBUG_BLOCK6_W10 : RO; bitpos: [31:0]; default: 0; @@ -1020,7 +1020,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W10_S 0 /** OTP_DEBUG_BLK6_W11_REG register - * Otp debuger block6 data register11. + * Otp debugger block6 data register11. */ #define OTP_DEBUG_BLK6_W11_REG (DR_REG_OTP_DEBUG_BASE + 0x150) /** OTP_DEBUG_BLOCK6_W11 : RO; bitpos: [31:0]; default: 0; @@ -1032,7 +1032,7 @@ extern "C" { #define OTP_DEBUG_BLOCK6_W11_S 0 /** OTP_DEBUG_BLK7_W1_REG register - * Otp debuger block7 data register1. + * Otp debugger block7 data register1. */ #define OTP_DEBUG_BLK7_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x154) /** OTP_DEBUG_BLOCK7_W1 : RO; bitpos: [31:0]; default: 0; @@ -1044,7 +1044,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W1_S 0 /** OTP_DEBUG_BLK7_W2_REG register - * Otp debuger block7 data register2. + * Otp debugger block7 data register2. */ #define OTP_DEBUG_BLK7_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x158) /** OTP_DEBUG_BLOCK7_W2 : RO; bitpos: [31:0]; default: 0; @@ -1056,7 +1056,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W2_S 0 /** OTP_DEBUG_BLK7_W3_REG register - * Otp debuger block7 data register3. + * Otp debugger block7 data register3. */ #define OTP_DEBUG_BLK7_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x15c) /** OTP_DEBUG_BLOCK7_W3 : RO; bitpos: [31:0]; default: 0; @@ -1068,7 +1068,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W3_S 0 /** OTP_DEBUG_BLK7_W4_REG register - * Otp debuger block7 data register4. + * Otp debugger block7 data register4. */ #define OTP_DEBUG_BLK7_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x160) /** OTP_DEBUG_BLOCK7_W4 : RO; bitpos: [31:0]; default: 0; @@ -1080,7 +1080,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W4_S 0 /** OTP_DEBUG_BLK7_W5_REG register - * Otp debuger block7 data register5. + * Otp debugger block7 data register5. */ #define OTP_DEBUG_BLK7_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x164) /** OTP_DEBUG_BLOCK7_W5 : RO; bitpos: [31:0]; default: 0; @@ -1092,7 +1092,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W5_S 0 /** OTP_DEBUG_BLK7_W6_REG register - * Otp debuger block7 data register6. + * Otp debugger block7 data register6. */ #define OTP_DEBUG_BLK7_W6_REG (DR_REG_OTP_DEBUG_BASE + 0x168) /** OTP_DEBUG_BLOCK7_W6 : RO; bitpos: [31:0]; default: 0; @@ -1104,7 +1104,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W6_S 0 /** OTP_DEBUG_BLK7_W7_REG register - * Otp debuger block7 data register7. + * Otp debugger block7 data register7. */ #define OTP_DEBUG_BLK7_W7_REG (DR_REG_OTP_DEBUG_BASE + 0x16c) /** OTP_DEBUG_BLOCK7_W7 : RO; bitpos: [31:0]; default: 0; @@ -1116,7 +1116,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W7_S 0 /** OTP_DEBUG_BLK7_W8_REG register - * Otp debuger block7 data register8. + * Otp debugger block7 data register8. */ #define OTP_DEBUG_BLK7_W8_REG (DR_REG_OTP_DEBUG_BASE + 0x170) /** OTP_DEBUG_BLOCK7_W8 : RO; bitpos: [31:0]; default: 0; @@ -1128,7 +1128,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W8_S 0 /** OTP_DEBUG_BLK7_W9_REG register - * Otp debuger block7 data register9. + * Otp debugger block7 data register9. */ #define OTP_DEBUG_BLK7_W9_REG (DR_REG_OTP_DEBUG_BASE + 0x174) /** OTP_DEBUG_BLOCK7_W9 : RO; bitpos: [31:0]; default: 0; @@ -1140,7 +1140,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W9_S 0 /** OTP_DEBUG_BLK7_W10_REG register - * Otp debuger block7 data register10. + * Otp debugger block7 data register10. */ #define OTP_DEBUG_BLK7_W10_REG (DR_REG_OTP_DEBUG_BASE + 0x178) /** OTP_DEBUG_BLOCK7_W10 : RO; bitpos: [31:0]; default: 0; @@ -1152,7 +1152,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W10_S 0 /** OTP_DEBUG_BLK7_W11_REG register - * Otp debuger block7 data register11. + * Otp debugger block7 data register11. */ #define OTP_DEBUG_BLK7_W11_REG (DR_REG_OTP_DEBUG_BASE + 0x17c) /** OTP_DEBUG_BLOCK7_W11 : RO; bitpos: [31:0]; default: 0; @@ -1164,7 +1164,7 @@ extern "C" { #define OTP_DEBUG_BLOCK7_W11_S 0 /** OTP_DEBUG_BLK8_W1_REG register - * Otp debuger block8 data register1. + * Otp debugger block8 data register1. */ #define OTP_DEBUG_BLK8_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x180) /** OTP_DEBUG_BLOCK8_W1 : RO; bitpos: [31:0]; default: 0; @@ -1176,7 +1176,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W1_S 0 /** OTP_DEBUG_BLK8_W2_REG register - * Otp debuger block8 data register2. + * Otp debugger block8 data register2. */ #define OTP_DEBUG_BLK8_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x184) /** OTP_DEBUG_BLOCK8_W2 : RO; bitpos: [31:0]; default: 0; @@ -1188,7 +1188,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W2_S 0 /** OTP_DEBUG_BLK8_W3_REG register - * Otp debuger block8 data register3. + * Otp debugger block8 data register3. */ #define OTP_DEBUG_BLK8_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x188) /** OTP_DEBUG_BLOCK8_W3 : RO; bitpos: [31:0]; default: 0; @@ -1200,7 +1200,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W3_S 0 /** OTP_DEBUG_BLK8_W4_REG register - * Otp debuger block8 data register4. + * Otp debugger block8 data register4. */ #define OTP_DEBUG_BLK8_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x18c) /** OTP_DEBUG_BLOCK8_W4 : RO; bitpos: [31:0]; default: 0; @@ -1212,7 +1212,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W4_S 0 /** OTP_DEBUG_BLK8_W5_REG register - * Otp debuger block8 data register5. + * Otp debugger block8 data register5. */ #define OTP_DEBUG_BLK8_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x190) /** OTP_DEBUG_BLOCK8_W5 : RO; bitpos: [31:0]; default: 0; @@ -1224,7 +1224,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W5_S 0 /** OTP_DEBUG_BLK8_W6_REG register - * Otp debuger block8 data register6. + * Otp debugger block8 data register6. */ #define OTP_DEBUG_BLK8_W6_REG (DR_REG_OTP_DEBUG_BASE + 0x194) /** OTP_DEBUG_BLOCK8_W6 : RO; bitpos: [31:0]; default: 0; @@ -1236,7 +1236,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W6_S 0 /** OTP_DEBUG_BLK8_W7_REG register - * Otp debuger block8 data register7. + * Otp debugger block8 data register7. */ #define OTP_DEBUG_BLK8_W7_REG (DR_REG_OTP_DEBUG_BASE + 0x198) /** OTP_DEBUG_BLOCK8_W7 : RO; bitpos: [31:0]; default: 0; @@ -1248,7 +1248,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W7_S 0 /** OTP_DEBUG_BLK8_W8_REG register - * Otp debuger block8 data register8. + * Otp debugger block8 data register8. */ #define OTP_DEBUG_BLK8_W8_REG (DR_REG_OTP_DEBUG_BASE + 0x19c) /** OTP_DEBUG_BLOCK8_W8 : RO; bitpos: [31:0]; default: 0; @@ -1260,7 +1260,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W8_S 0 /** OTP_DEBUG_BLK8_W9_REG register - * Otp debuger block8 data register9. + * Otp debugger block8 data register9. */ #define OTP_DEBUG_BLK8_W9_REG (DR_REG_OTP_DEBUG_BASE + 0x1a0) /** OTP_DEBUG_BLOCK8_W9 : RO; bitpos: [31:0]; default: 0; @@ -1272,7 +1272,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W9_S 0 /** OTP_DEBUG_BLK8_W10_REG register - * Otp debuger block8 data register10. + * Otp debugger block8 data register10. */ #define OTP_DEBUG_BLK8_W10_REG (DR_REG_OTP_DEBUG_BASE + 0x1a4) /** OTP_DEBUG_BLOCK8_W10 : RO; bitpos: [31:0]; default: 0; @@ -1284,7 +1284,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W10_S 0 /** OTP_DEBUG_BLK8_W11_REG register - * Otp debuger block8 data register11. + * Otp debugger block8 data register11. */ #define OTP_DEBUG_BLK8_W11_REG (DR_REG_OTP_DEBUG_BASE + 0x1a8) /** OTP_DEBUG_BLOCK8_W11 : RO; bitpos: [31:0]; default: 0; @@ -1296,7 +1296,7 @@ extern "C" { #define OTP_DEBUG_BLOCK8_W11_S 0 /** OTP_DEBUG_BLK9_W1_REG register - * Otp debuger block9 data register1. + * Otp debugger block9 data register1. */ #define OTP_DEBUG_BLK9_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x1ac) /** OTP_DEBUG_BLOCK9_W1 : RO; bitpos: [31:0]; default: 0; @@ -1308,7 +1308,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W1_S 0 /** OTP_DEBUG_BLK9_W2_REG register - * Otp debuger block9 data register2. + * Otp debugger block9 data register2. */ #define OTP_DEBUG_BLK9_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x1b0) /** OTP_DEBUG_BLOCK9_W2 : RO; bitpos: [31:0]; default: 0; @@ -1320,7 +1320,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W2_S 0 /** OTP_DEBUG_BLK9_W3_REG register - * Otp debuger block9 data register3. + * Otp debugger block9 data register3. */ #define OTP_DEBUG_BLK9_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x1b4) /** OTP_DEBUG_BLOCK9_W3 : RO; bitpos: [31:0]; default: 0; @@ -1332,7 +1332,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W3_S 0 /** OTP_DEBUG_BLK9_W4_REG register - * Otp debuger block9 data register4. + * Otp debugger block9 data register4. */ #define OTP_DEBUG_BLK9_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x1b8) /** OTP_DEBUG_BLOCK9_W4 : RO; bitpos: [31:0]; default: 0; @@ -1344,7 +1344,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W4_S 0 /** OTP_DEBUG_BLK9_W5_REG register - * Otp debuger block9 data register5. + * Otp debugger block9 data register5. */ #define OTP_DEBUG_BLK9_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x1bc) /** OTP_DEBUG_BLOCK9_W5 : RO; bitpos: [31:0]; default: 0; @@ -1356,7 +1356,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W5_S 0 /** OTP_DEBUG_BLK9_W6_REG register - * Otp debuger block9 data register6. + * Otp debugger block9 data register6. */ #define OTP_DEBUG_BLK9_W6_REG (DR_REG_OTP_DEBUG_BASE + 0x1c0) /** OTP_DEBUG_BLOCK9_W6 : RO; bitpos: [31:0]; default: 0; @@ -1368,7 +1368,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W6_S 0 /** OTP_DEBUG_BLK9_W7_REG register - * Otp debuger block9 data register7. + * Otp debugger block9 data register7. */ #define OTP_DEBUG_BLK9_W7_REG (DR_REG_OTP_DEBUG_BASE + 0x1c4) /** OTP_DEBUG_BLOCK9_W7 : RO; bitpos: [31:0]; default: 0; @@ -1380,7 +1380,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W7_S 0 /** OTP_DEBUG_BLK9_W8_REG register - * Otp debuger block9 data register8. + * Otp debugger block9 data register8. */ #define OTP_DEBUG_BLK9_W8_REG (DR_REG_OTP_DEBUG_BASE + 0x1c8) /** OTP_DEBUG_BLOCK9_W8 : RO; bitpos: [31:0]; default: 0; @@ -1392,7 +1392,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W8_S 0 /** OTP_DEBUG_BLK9_W9_REG register - * Otp debuger block9 data register9. + * Otp debugger block9 data register9. */ #define OTP_DEBUG_BLK9_W9_REG (DR_REG_OTP_DEBUG_BASE + 0x1cc) /** OTP_DEBUG_BLOCK9_W9 : RO; bitpos: [31:0]; default: 0; @@ -1404,7 +1404,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W9_S 0 /** OTP_DEBUG_BLK9_W10_REG register - * Otp debuger block9 data register10. + * Otp debugger block9 data register10. */ #define OTP_DEBUG_BLK9_W10_REG (DR_REG_OTP_DEBUG_BASE + 0x1d0) /** OTP_DEBUG_BLOCK9_W10 : RO; bitpos: [31:0]; default: 0; @@ -1416,7 +1416,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W10_S 0 /** OTP_DEBUG_BLK9_W11_REG register - * Otp debuger block9 data register11. + * Otp debugger block9 data register11. */ #define OTP_DEBUG_BLK9_W11_REG (DR_REG_OTP_DEBUG_BASE + 0x1d4) /** OTP_DEBUG_BLOCK9_W11 : RO; bitpos: [31:0]; default: 0; @@ -1428,7 +1428,7 @@ extern "C" { #define OTP_DEBUG_BLOCK9_W11_S 0 /** OTP_DEBUG_BLK10_W1_REG register - * Otp debuger block10 data register1. + * Otp debugger block10 data register1. */ #define OTP_DEBUG_BLK10_W1_REG (DR_REG_OTP_DEBUG_BASE + 0x1d8) /** OTP_DEBUG_BLOCK10_W1 : RO; bitpos: [31:0]; default: 0; @@ -1440,7 +1440,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W1_S 0 /** OTP_DEBUG_BLK10_W2_REG register - * Otp debuger block10 data register2. + * Otp debugger block10 data register2. */ #define OTP_DEBUG_BLK10_W2_REG (DR_REG_OTP_DEBUG_BASE + 0x1dc) /** OTP_DEBUG_BLOCK10_W2 : RO; bitpos: [31:0]; default: 0; @@ -1452,7 +1452,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W2_S 0 /** OTP_DEBUG_BLK10_W3_REG register - * Otp debuger block10 data register3. + * Otp debugger block10 data register3. */ #define OTP_DEBUG_BLK10_W3_REG (DR_REG_OTP_DEBUG_BASE + 0x1e0) /** OTP_DEBUG_BLOCK10_W3 : RO; bitpos: [31:0]; default: 0; @@ -1464,7 +1464,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W3_S 0 /** OTP_DEBUG_BLK10_W4_REG register - * Otp debuger block10 data register4. + * Otp debugger block10 data register4. */ #define OTP_DEBUG_BLK10_W4_REG (DR_REG_OTP_DEBUG_BASE + 0x1e4) /** OTP_DEBUG_BLOCK10_W4 : RO; bitpos: [31:0]; default: 0; @@ -1476,7 +1476,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W4_S 0 /** OTP_DEBUG_BLK10_W5_REG register - * Otp debuger block10 data register5. + * Otp debugger block10 data register5. */ #define OTP_DEBUG_BLK10_W5_REG (DR_REG_OTP_DEBUG_BASE + 0x1e8) /** OTP_DEBUG_BLOCK10_W5 : RO; bitpos: [31:0]; default: 0; @@ -1488,7 +1488,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W5_S 0 /** OTP_DEBUG_BLK10_W6_REG register - * Otp debuger block10 data register6. + * Otp debugger block10 data register6. */ #define OTP_DEBUG_BLK10_W6_REG (DR_REG_OTP_DEBUG_BASE + 0x1ec) /** OTP_DEBUG_BLOCK10_W6 : RO; bitpos: [31:0]; default: 0; @@ -1500,7 +1500,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W6_S 0 /** OTP_DEBUG_BLK10_W7_REG register - * Otp debuger block10 data register7. + * Otp debugger block10 data register7. */ #define OTP_DEBUG_BLK10_W7_REG (DR_REG_OTP_DEBUG_BASE + 0x1f0) /** OTP_DEBUG_BLOCK10_W7 : RO; bitpos: [31:0]; default: 0; @@ -1512,7 +1512,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W7_S 0 /** OTP_DEBUG_BLK10_W8_REG register - * Otp debuger block10 data register8. + * Otp debugger block10 data register8. */ #define OTP_DEBUG_BLK10_W8_REG (DR_REG_OTP_DEBUG_BASE + 0x1f4) /** OTP_DEBUG_BLOCK10_W8 : RO; bitpos: [31:0]; default: 0; @@ -1524,7 +1524,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W8_S 0 /** OTP_DEBUG_BLK10_W9_REG register - * Otp debuger block10 data register9. + * Otp debugger block10 data register9. */ #define OTP_DEBUG_BLK10_W9_REG (DR_REG_OTP_DEBUG_BASE + 0x1f8) /** OTP_DEBUG_BLOCK10_W9 : RO; bitpos: [31:0]; default: 0; @@ -1536,7 +1536,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W9_S 0 /** OTP_DEBUG_BLK10_W10_REG register - * Otp debuger block10 data register10. + * Otp debugger block10 data register10. */ #define OTP_DEBUG_BLK10_W10_REG (DR_REG_OTP_DEBUG_BASE + 0x1fc) /** OTP_DEBUG_BLOCK19_W10 : RO; bitpos: [31:0]; default: 0; @@ -1548,7 +1548,7 @@ extern "C" { #define OTP_DEBUG_BLOCK19_W10_S 0 /** OTP_DEBUG_BLK10_W11_REG register - * Otp debuger block10 data register11. + * Otp debugger block10 data register11. */ #define OTP_DEBUG_BLK10_W11_REG (DR_REG_OTP_DEBUG_BASE + 0x200) /** OTP_DEBUG_BLOCK10_W11 : RO; bitpos: [31:0]; default: 0; @@ -1560,7 +1560,7 @@ extern "C" { #define OTP_DEBUG_BLOCK10_W11_S 0 /** OTP_DEBUG_CLK_REG register - * Otp debuger clk_en configuration register. + * Otp debugger clk_en configuration register. */ #define OTP_DEBUG_CLK_REG (DR_REG_OTP_DEBUG_BASE + 0x204) /** OTP_DEBUG_CLK_EN : R/W; bitpos: [0]; default: 0; diff --git a/components/soc/esp32c6/include/soc/otp_debug_struct.h b/components/soc/esp32c6/register/soc/otp_debug_struct.h similarity index 89% rename from components/soc/esp32c6/include/soc/otp_debug_struct.h rename to components/soc/esp32c6/register/soc/otp_debug_struct.h index 5b0737475f7d..8ed1fe280296 100644 --- a/components/soc/esp32c6/include/soc/otp_debug_struct.h +++ b/components/soc/esp32c6/register/soc/otp_debug_struct.h @@ -12,7 +12,7 @@ extern "C" { /** Group: OTP_DEBUG Block0 Write Disable Data */ /** Type of wr_dis register - * Otp debuger block0 data register1. + * Otp debugger block0 data register1. */ typedef union { struct { @@ -27,7 +27,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup1 Word1 Data */ /** Type of blk0_backup1_w1 register - * Otp debuger block0 data register2. + * Otp debugger block0 data register2. */ typedef union { struct { @@ -42,7 +42,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup1 Word2 Data */ /** Type of blk0_backup1_w2 register - * Otp debuger block0 data register3. + * Otp debugger block0 data register3. */ typedef union { struct { @@ -57,7 +57,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup1 Word3 Data */ /** Type of blk0_backup1_w3 register - * Otp debuger block0 data register4. + * Otp debugger block0 data register4. */ typedef union { struct { @@ -72,7 +72,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup1 Word4 Data */ /** Type of blk0_backup1_w4 register - * Otp debuger block0 data register5. + * Otp debugger block0 data register5. */ typedef union { struct { @@ -87,7 +87,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup1 Word5 Data */ /** Type of blk0_backup1_w5 register - * Otp debuger block0 data register6. + * Otp debugger block0 data register6. */ typedef union { struct { @@ -102,7 +102,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup2 Word1 Data */ /** Type of blk0_backup2_w1 register - * Otp debuger block0 data register7. + * Otp debugger block0 data register7. */ typedef union { struct { @@ -117,7 +117,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup2 Word2 Data */ /** Type of blk0_backup2_w2 register - * Otp debuger block0 data register8. + * Otp debugger block0 data register8. */ typedef union { struct { @@ -132,7 +132,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup2 Word3 Data */ /** Type of blk0_backup2_w3 register - * Otp debuger block0 data register9. + * Otp debugger block0 data register9. */ typedef union { struct { @@ -147,7 +147,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup2 Word4 Data */ /** Type of blk0_backup2_w4 register - * Otp debuger block0 data register10. + * Otp debugger block0 data register10. */ typedef union { struct { @@ -162,7 +162,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup2 Word5 Data */ /** Type of blk0_backup2_w5 register - * Otp debuger block0 data register11. + * Otp debugger block0 data register11. */ typedef union { struct { @@ -177,7 +177,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup3 Word1 Data */ /** Type of blk0_backup3_w1 register - * Otp debuger block0 data register12. + * Otp debugger block0 data register12. */ typedef union { struct { @@ -192,7 +192,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup3 Word2 Data */ /** Type of blk0_backup3_w2 register - * Otp debuger block0 data register13. + * Otp debugger block0 data register13. */ typedef union { struct { @@ -207,7 +207,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup3 Word3 Data */ /** Type of blk0_backup3_w3 register - * Otp debuger block0 data register14. + * Otp debugger block0 data register14. */ typedef union { struct { @@ -222,7 +222,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup3 Word4 Data */ /** Type of blk0_backup3_w4 register - * Otp debuger block0 data register15. + * Otp debugger block0 data register15. */ typedef union { struct { @@ -237,7 +237,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup3 Word5 Data */ /** Type of blk0_backup3_w5 register - * Otp debuger block0 data register16. + * Otp debugger block0 data register16. */ typedef union { struct { @@ -252,7 +252,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup4 Word1 Data */ /** Type of blk0_backup4_w1 register - * Otp debuger block0 data register17. + * Otp debugger block0 data register17. */ typedef union { struct { @@ -267,7 +267,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup4 Word2 Data */ /** Type of blk0_backup4_w2 register - * Otp debuger block0 data register18. + * Otp debugger block0 data register18. */ typedef union { struct { @@ -282,7 +282,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup4 Word3 Data */ /** Type of blk0_backup4_w3 register - * Otp debuger block0 data register19. + * Otp debugger block0 data register19. */ typedef union { struct { @@ -297,7 +297,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup4 Word4 Data */ /** Type of blk0_backup4_w4 register - * Otp debuger block0 data register20. + * Otp debugger block0 data register20. */ typedef union { struct { @@ -312,7 +312,7 @@ typedef union { /** Group: OTP_DEBUG Block0 Backup4 Word5 Data */ /** Type of blk0_backup4_w5 register - * Otp debuger block0 data register21. + * Otp debugger block0 data register21. */ typedef union { struct { @@ -327,7 +327,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word1 Data */ /** Type of blk1_w1 register - * Otp debuger block1 data register1. + * Otp debugger block1 data register1. */ typedef union { struct { @@ -342,7 +342,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word2 Data */ /** Type of blk1_w2 register - * Otp debuger block1 data register2. + * Otp debugger block1 data register2. */ typedef union { struct { @@ -357,7 +357,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word3 Data */ /** Type of blk1_w3 register - * Otp debuger block1 data register3. + * Otp debugger block1 data register3. */ typedef union { struct { @@ -372,7 +372,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word4 Data */ /** Type of blk1_w4 register - * Otp debuger block1 data register4. + * Otp debugger block1 data register4. */ typedef union { struct { @@ -387,7 +387,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word5 Data */ /** Type of blk1_w5 register - * Otp debuger block1 data register5. + * Otp debugger block1 data register5. */ typedef union { struct { @@ -402,7 +402,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word6 Data */ /** Type of blk1_w6 register - * Otp debuger block1 data register6. + * Otp debugger block1 data register6. */ typedef union { struct { @@ -417,7 +417,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word7 Data */ /** Type of blk1_w7 register - * Otp debuger block1 data register7. + * Otp debugger block1 data register7. */ typedef union { struct { @@ -432,7 +432,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word8 Data */ /** Type of blk1_w8 register - * Otp debuger block1 data register8. + * Otp debugger block1 data register8. */ typedef union { struct { @@ -447,7 +447,7 @@ typedef union { /** Group: OTP_DEBUG Block1 Word9 Data */ /** Type of blk1_w9 register - * Otp debuger block1 data register9. + * Otp debugger block1 data register9. */ typedef union { struct { @@ -462,7 +462,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word1 Data */ /** Type of blk2_w1 register - * Otp debuger block2 data register1. + * Otp debugger block2 data register1. */ typedef union { struct { @@ -477,7 +477,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word2 Data */ /** Type of blk2_w2 register - * Otp debuger block2 data register2. + * Otp debugger block2 data register2. */ typedef union { struct { @@ -492,7 +492,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word3 Data */ /** Type of blk2_w3 register - * Otp debuger block2 data register3. + * Otp debugger block2 data register3. */ typedef union { struct { @@ -507,7 +507,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word4 Data */ /** Type of blk2_w4 register - * Otp debuger block2 data register4. + * Otp debugger block2 data register4. */ typedef union { struct { @@ -522,7 +522,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word5 Data */ /** Type of blk2_w5 register - * Otp debuger block2 data register5. + * Otp debugger block2 data register5. */ typedef union { struct { @@ -537,7 +537,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word6 Data */ /** Type of blk2_w6 register - * Otp debuger block2 data register6. + * Otp debugger block2 data register6. */ typedef union { struct { @@ -552,7 +552,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word7 Data */ /** Type of blk2_w7 register - * Otp debuger block2 data register7. + * Otp debugger block2 data register7. */ typedef union { struct { @@ -567,7 +567,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word8 Data */ /** Type of blk2_w8 register - * Otp debuger block2 data register8. + * Otp debugger block2 data register8. */ typedef union { struct { @@ -582,7 +582,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word9 Data */ /** Type of blk2_w9 register - * Otp debuger block2 data register9. + * Otp debugger block2 data register9. */ typedef union { struct { @@ -597,7 +597,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word10 Data */ /** Type of blk2_w10 register - * Otp debuger block2 data register10. + * Otp debugger block2 data register10. */ typedef union { struct { @@ -612,7 +612,7 @@ typedef union { /** Group: OTP_DEBUG Block2 Word11 Data */ /** Type of blk2_w11 register - * Otp debuger block2 data register11. + * Otp debugger block2 data register11. */ typedef union { struct { @@ -625,7 +625,7 @@ typedef union { } otp_debug_blk2_w11_reg_t; /** Type of blk10_w11 register - * Otp debuger block10 data register11. + * Otp debugger block10 data register11. */ typedef union { struct { @@ -640,7 +640,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word1 Data */ /** Type of blk3_w1 register - * Otp debuger block3 data register1. + * Otp debugger block3 data register1. */ typedef union { struct { @@ -655,7 +655,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word2 Data */ /** Type of blk3_w2 register - * Otp debuger block3 data register2. + * Otp debugger block3 data register2. */ typedef union { struct { @@ -670,7 +670,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word3 Data */ /** Type of blk3_w3 register - * Otp debuger block3 data register3. + * Otp debugger block3 data register3. */ typedef union { struct { @@ -685,7 +685,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word4 Data */ /** Type of blk3_w4 register - * Otp debuger block3 data register4. + * Otp debugger block3 data register4. */ typedef union { struct { @@ -700,7 +700,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word5 Data */ /** Type of blk3_w5 register - * Otp debuger block3 data register5. + * Otp debugger block3 data register5. */ typedef union { struct { @@ -715,7 +715,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word6 Data */ /** Type of blk3_w6 register - * Otp debuger block3 data register6. + * Otp debugger block3 data register6. */ typedef union { struct { @@ -730,7 +730,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word7 Data */ /** Type of blk3_w7 register - * Otp debuger block3 data register7. + * Otp debugger block3 data register7. */ typedef union { struct { @@ -745,7 +745,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word8 Data */ /** Type of blk3_w8 register - * Otp debuger block3 data register8. + * Otp debugger block3 data register8. */ typedef union { struct { @@ -760,7 +760,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word9 Data */ /** Type of blk3_w9 register - * Otp debuger block3 data register9. + * Otp debugger block3 data register9. */ typedef union { struct { @@ -775,7 +775,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word10 Data */ /** Type of blk3_w10 register - * Otp debuger block3 data register10. + * Otp debugger block3 data register10. */ typedef union { struct { @@ -790,7 +790,7 @@ typedef union { /** Group: OTP_DEBUG Block3 Word11 Data */ /** Type of blk3_w11 register - * Otp debuger block3 data register11. + * Otp debugger block3 data register11. */ typedef union { struct { @@ -805,7 +805,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word1 Data */ /** Type of blk4_w1 register - * Otp debuger block4 data register1. + * Otp debugger block4 data register1. */ typedef union { struct { @@ -820,7 +820,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word2 Data */ /** Type of blk4_w2 register - * Otp debuger block4 data register2. + * Otp debugger block4 data register2. */ typedef union { struct { @@ -835,7 +835,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word3 Data */ /** Type of blk4_w3 register - * Otp debuger block4 data register3. + * Otp debugger block4 data register3. */ typedef union { struct { @@ -850,7 +850,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word4 Data */ /** Type of blk4_w4 register - * Otp debuger block4 data register4. + * Otp debugger block4 data register4. */ typedef union { struct { @@ -865,7 +865,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word5 Data */ /** Type of blk4_w5 register - * Otp debuger block4 data register5. + * Otp debugger block4 data register5. */ typedef union { struct { @@ -880,7 +880,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word6 Data */ /** Type of blk4_w6 register - * Otp debuger block4 data register6. + * Otp debugger block4 data register6. */ typedef union { struct { @@ -895,7 +895,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word7 Data */ /** Type of blk4_w7 register - * Otp debuger block4 data register7. + * Otp debugger block4 data register7. */ typedef union { struct { @@ -910,7 +910,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word8 Data */ /** Type of blk4_w8 register - * Otp debuger block4 data register8. + * Otp debugger block4 data register8. */ typedef union { struct { @@ -925,7 +925,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word9 Data */ /** Type of blk4_w9 register - * Otp debuger block4 data register9. + * Otp debugger block4 data register9. */ typedef union { struct { @@ -940,7 +940,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word10 Data */ /** Type of blk4_w10 register - * Otp debuger block4 data registe10. + * Otp debugger block4 data registe10. */ typedef union { struct { @@ -955,7 +955,7 @@ typedef union { /** Group: OTP_DEBUG Block4 Word11 Data */ /** Type of blk4_w11 register - * Otp debuger block4 data register11. + * Otp debugger block4 data register11. */ typedef union { struct { @@ -970,7 +970,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word1 Data */ /** Type of blk5_w1 register - * Otp debuger block5 data register1. + * Otp debugger block5 data register1. */ typedef union { struct { @@ -985,7 +985,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word2 Data */ /** Type of blk5_w2 register - * Otp debuger block5 data register2. + * Otp debugger block5 data register2. */ typedef union { struct { @@ -1000,7 +1000,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word3 Data */ /** Type of blk5_w3 register - * Otp debuger block5 data register3. + * Otp debugger block5 data register3. */ typedef union { struct { @@ -1015,7 +1015,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word4 Data */ /** Type of blk5_w4 register - * Otp debuger block5 data register4. + * Otp debugger block5 data register4. */ typedef union { struct { @@ -1030,7 +1030,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word5 Data */ /** Type of blk5_w5 register - * Otp debuger block5 data register5. + * Otp debugger block5 data register5. */ typedef union { struct { @@ -1045,7 +1045,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word6 Data */ /** Type of blk5_w6 register - * Otp debuger block5 data register6. + * Otp debugger block5 data register6. */ typedef union { struct { @@ -1060,7 +1060,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word7 Data */ /** Type of blk5_w7 register - * Otp debuger block5 data register7. + * Otp debugger block5 data register7. */ typedef union { struct { @@ -1075,7 +1075,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word8 Data */ /** Type of blk5_w8 register - * Otp debuger block5 data register8. + * Otp debugger block5 data register8. */ typedef union { struct { @@ -1090,7 +1090,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word9 Data */ /** Type of blk5_w9 register - * Otp debuger block5 data register9. + * Otp debugger block5 data register9. */ typedef union { struct { @@ -1105,7 +1105,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word10 Data */ /** Type of blk5_w10 register - * Otp debuger block5 data register10. + * Otp debugger block5 data register10. */ typedef union { struct { @@ -1120,7 +1120,7 @@ typedef union { /** Group: OTP_DEBUG Block5 Word11 Data */ /** Type of blk5_w11 register - * Otp debuger block5 data register11. + * Otp debugger block5 data register11. */ typedef union { struct { @@ -1135,7 +1135,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word1 Data */ /** Type of blk6_w1 register - * Otp debuger block6 data register1. + * Otp debugger block6 data register1. */ typedef union { struct { @@ -1150,7 +1150,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word2 Data */ /** Type of blk6_w2 register - * Otp debuger block6 data register2. + * Otp debugger block6 data register2. */ typedef union { struct { @@ -1165,7 +1165,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word3 Data */ /** Type of blk6_w3 register - * Otp debuger block6 data register3. + * Otp debugger block6 data register3. */ typedef union { struct { @@ -1180,7 +1180,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word4 Data */ /** Type of blk6_w4 register - * Otp debuger block6 data register4. + * Otp debugger block6 data register4. */ typedef union { struct { @@ -1195,7 +1195,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word5 Data */ /** Type of blk6_w5 register - * Otp debuger block6 data register5. + * Otp debugger block6 data register5. */ typedef union { struct { @@ -1210,7 +1210,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word6 Data */ /** Type of blk6_w6 register - * Otp debuger block6 data register6. + * Otp debugger block6 data register6. */ typedef union { struct { @@ -1225,7 +1225,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word7 Data */ /** Type of blk6_w7 register - * Otp debuger block6 data register7. + * Otp debugger block6 data register7. */ typedef union { struct { @@ -1240,7 +1240,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word8 Data */ /** Type of blk6_w8 register - * Otp debuger block6 data register8. + * Otp debugger block6 data register8. */ typedef union { struct { @@ -1255,7 +1255,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word9 Data */ /** Type of blk6_w9 register - * Otp debuger block6 data register9. + * Otp debugger block6 data register9. */ typedef union { struct { @@ -1270,7 +1270,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word10 Data */ /** Type of blk6_w10 register - * Otp debuger block6 data register10. + * Otp debugger block6 data register10. */ typedef union { struct { @@ -1285,7 +1285,7 @@ typedef union { /** Group: OTP_DEBUG Block6 Word11 Data */ /** Type of blk6_w11 register - * Otp debuger block6 data register11. + * Otp debugger block6 data register11. */ typedef union { struct { @@ -1300,7 +1300,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word1 Data */ /** Type of blk7_w1 register - * Otp debuger block7 data register1. + * Otp debugger block7 data register1. */ typedef union { struct { @@ -1315,7 +1315,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word2 Data */ /** Type of blk7_w2 register - * Otp debuger block7 data register2. + * Otp debugger block7 data register2. */ typedef union { struct { @@ -1330,7 +1330,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word3 Data */ /** Type of blk7_w3 register - * Otp debuger block7 data register3. + * Otp debugger block7 data register3. */ typedef union { struct { @@ -1345,7 +1345,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word4 Data */ /** Type of blk7_w4 register - * Otp debuger block7 data register4. + * Otp debugger block7 data register4. */ typedef union { struct { @@ -1360,7 +1360,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word5 Data */ /** Type of blk7_w5 register - * Otp debuger block7 data register5. + * Otp debugger block7 data register5. */ typedef union { struct { @@ -1375,7 +1375,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word6 Data */ /** Type of blk7_w6 register - * Otp debuger block7 data register6. + * Otp debugger block7 data register6. */ typedef union { struct { @@ -1390,7 +1390,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word7 Data */ /** Type of blk7_w7 register - * Otp debuger block7 data register7. + * Otp debugger block7 data register7. */ typedef union { struct { @@ -1405,7 +1405,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word8 Data */ /** Type of blk7_w8 register - * Otp debuger block7 data register8. + * Otp debugger block7 data register8. */ typedef union { struct { @@ -1420,7 +1420,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word9 Data */ /** Type of blk7_w9 register - * Otp debuger block7 data register9. + * Otp debugger block7 data register9. */ typedef union { struct { @@ -1435,7 +1435,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word10 Data */ /** Type of blk7_w10 register - * Otp debuger block7 data register10. + * Otp debugger block7 data register10. */ typedef union { struct { @@ -1450,7 +1450,7 @@ typedef union { /** Group: OTP_DEBUG Block7 Word11 Data */ /** Type of blk7_w11 register - * Otp debuger block7 data register11. + * Otp debugger block7 data register11. */ typedef union { struct { @@ -1465,7 +1465,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word1 Data */ /** Type of blk8_w1 register - * Otp debuger block8 data register1. + * Otp debugger block8 data register1. */ typedef union { struct { @@ -1480,7 +1480,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word2 Data */ /** Type of blk8_w2 register - * Otp debuger block8 data register2. + * Otp debugger block8 data register2. */ typedef union { struct { @@ -1495,7 +1495,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word3 Data */ /** Type of blk8_w3 register - * Otp debuger block8 data register3. + * Otp debugger block8 data register3. */ typedef union { struct { @@ -1510,7 +1510,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word4 Data */ /** Type of blk8_w4 register - * Otp debuger block8 data register4. + * Otp debugger block8 data register4. */ typedef union { struct { @@ -1525,7 +1525,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word5 Data */ /** Type of blk8_w5 register - * Otp debuger block8 data register5. + * Otp debugger block8 data register5. */ typedef union { struct { @@ -1540,7 +1540,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word6 Data */ /** Type of blk8_w6 register - * Otp debuger block8 data register6. + * Otp debugger block8 data register6. */ typedef union { struct { @@ -1555,7 +1555,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word7 Data */ /** Type of blk8_w7 register - * Otp debuger block8 data register7. + * Otp debugger block8 data register7. */ typedef union { struct { @@ -1570,7 +1570,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word8 Data */ /** Type of blk8_w8 register - * Otp debuger block8 data register8. + * Otp debugger block8 data register8. */ typedef union { struct { @@ -1585,7 +1585,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word9 Data */ /** Type of blk8_w9 register - * Otp debuger block8 data register9. + * Otp debugger block8 data register9. */ typedef union { struct { @@ -1600,7 +1600,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word10 Data */ /** Type of blk8_w10 register - * Otp debuger block8 data register10. + * Otp debugger block8 data register10. */ typedef union { struct { @@ -1615,7 +1615,7 @@ typedef union { /** Group: OTP_DEBUG Block8 Word11 Data */ /** Type of blk8_w11 register - * Otp debuger block8 data register11. + * Otp debugger block8 data register11. */ typedef union { struct { @@ -1630,7 +1630,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word1 Data */ /** Type of blk9_w1 register - * Otp debuger block9 data register1. + * Otp debugger block9 data register1. */ typedef union { struct { @@ -1645,7 +1645,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word2 Data */ /** Type of blk9_w2 register - * Otp debuger block9 data register2. + * Otp debugger block9 data register2. */ typedef union { struct { @@ -1660,7 +1660,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word3 Data */ /** Type of blk9_w3 register - * Otp debuger block9 data register3. + * Otp debugger block9 data register3. */ typedef union { struct { @@ -1675,7 +1675,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word4 Data */ /** Type of blk9_w4 register - * Otp debuger block9 data register4. + * Otp debugger block9 data register4. */ typedef union { struct { @@ -1690,7 +1690,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word5 Data */ /** Type of blk9_w5 register - * Otp debuger block9 data register5. + * Otp debugger block9 data register5. */ typedef union { struct { @@ -1705,7 +1705,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word6 Data */ /** Type of blk9_w6 register - * Otp debuger block9 data register6. + * Otp debugger block9 data register6. */ typedef union { struct { @@ -1720,7 +1720,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word7 Data */ /** Type of blk9_w7 register - * Otp debuger block9 data register7. + * Otp debugger block9 data register7. */ typedef union { struct { @@ -1735,7 +1735,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word8 Data */ /** Type of blk9_w8 register - * Otp debuger block9 data register8. + * Otp debugger block9 data register8. */ typedef union { struct { @@ -1750,7 +1750,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word9 Data */ /** Type of blk9_w9 register - * Otp debuger block9 data register9. + * Otp debugger block9 data register9. */ typedef union { struct { @@ -1765,7 +1765,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word10 Data */ /** Type of blk9_w10 register - * Otp debuger block9 data register10. + * Otp debugger block9 data register10. */ typedef union { struct { @@ -1780,7 +1780,7 @@ typedef union { /** Group: OTP_DEBUG Block9 Word11 Data */ /** Type of blk9_w11 register - * Otp debuger block9 data register11. + * Otp debugger block9 data register11. */ typedef union { struct { @@ -1795,7 +1795,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word1 Data */ /** Type of blk10_w1 register - * Otp debuger block10 data register1. + * Otp debugger block10 data register1. */ typedef union { struct { @@ -1810,7 +1810,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word2 Data */ /** Type of blk10_w2 register - * Otp debuger block10 data register2. + * Otp debugger block10 data register2. */ typedef union { struct { @@ -1825,7 +1825,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word3 Data */ /** Type of blk10_w3 register - * Otp debuger block10 data register3. + * Otp debugger block10 data register3. */ typedef union { struct { @@ -1840,7 +1840,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word4 Data */ /** Type of blk10_w4 register - * Otp debuger block10 data register4. + * Otp debugger block10 data register4. */ typedef union { struct { @@ -1855,7 +1855,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word5 Data */ /** Type of blk10_w5 register - * Otp debuger block10 data register5. + * Otp debugger block10 data register5. */ typedef union { struct { @@ -1870,7 +1870,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word6 Data */ /** Type of blk10_w6 register - * Otp debuger block10 data register6. + * Otp debugger block10 data register6. */ typedef union { struct { @@ -1885,7 +1885,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word7 Data */ /** Type of blk10_w7 register - * Otp debuger block10 data register7. + * Otp debugger block10 data register7. */ typedef union { struct { @@ -1900,7 +1900,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word8 Data */ /** Type of blk10_w8 register - * Otp debuger block10 data register8. + * Otp debugger block10 data register8. */ typedef union { struct { @@ -1915,7 +1915,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word9 Data */ /** Type of blk10_w9 register - * Otp debuger block10 data register9. + * Otp debugger block10 data register9. */ typedef union { struct { @@ -1930,7 +1930,7 @@ typedef union { /** Group: OTP_DEBUG Block10 Word10 Data */ /** Type of blk10_w10 register - * Otp debuger block10 data register10. + * Otp debugger block10 data register10. */ typedef union { struct { @@ -1945,7 +1945,7 @@ typedef union { /** Group: OTP_DEBUG Clock_en Configuration Register */ /** Type of clk register - * Otp debuger clk_en configuration register. + * Otp debugger clk_en configuration register. */ typedef union { struct { @@ -1959,7 +1959,7 @@ typedef union { } otp_debug_clk_reg_t; -/** Group: OTP_DEBUG Apb2otp Enable Singal */ +/** Group: OTP_DEBUG Apb2otp Enable Signal */ /** Type of apb2otp_en register * Otp_debuger apb2otp enable configuration register. */ diff --git a/components/soc/esp32c6/include/soc/parl_io_reg.h b/components/soc/esp32c6/register/soc/parl_io_reg.h similarity index 98% rename from components/soc/esp32c6/include/soc/parl_io_reg.h rename to components/soc/esp32c6/register/soc/parl_io_reg.h index 7377e9788b30..191656298c4a 100644 --- a/components/soc/esp32c6/include/soc/parl_io_reg.h +++ b/components/soc/esp32c6/register/soc/parl_io_reg.h @@ -31,7 +31,7 @@ extern "C" { #define PARL_IO_RX_START_V 0x00000001U #define PARL_IO_RX_START_S 1 /** PARL_IO_RX_DATA_BYTELEN : R/W; bitpos: [17:2]; default: 0; - * Configures rx receieved data byte length. + * Configures rx received data byte length. */ #define PARL_IO_RX_DATA_BYTELEN 0x0000FFFFU #define PARL_IO_RX_DATA_BYTELEN_M (PARL_IO_RX_DATA_BYTELEN_V << PARL_IO_RX_DATA_BYTELEN_S) @@ -251,7 +251,7 @@ extern "C" { #define PARL_IO_TX_READY_S 31 /** PARL_IO_INT_ENA_REG register - * Parallel IO interrupt enable singal configuration register. + * Parallel IO interrupt enable signal configuration register. */ #define PARL_IO_INT_ENA_REG (DR_REG_PARL_IO_BASE + 0x14) /** PARL_IO_TX_FIFO_REMPTY_INT_ENA : R/W; bitpos: [0]; default: 0; @@ -277,7 +277,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_ENA_S 2 /** PARL_IO_INT_RAW_REG register - * Parallel IO interrupt raw singal status register. + * Parallel IO interrupt raw signal status register. */ #define PARL_IO_INT_RAW_REG (DR_REG_PARL_IO_BASE + 0x18) /** PARL_IO_TX_FIFO_REMPTY_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; @@ -303,7 +303,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_RAW_S 2 /** PARL_IO_INT_ST_REG register - * Parallel IO interrupt singal status register. + * Parallel IO interrupt signal status register. */ #define PARL_IO_INT_ST_REG (DR_REG_PARL_IO_BASE + 0x1c) /** PARL_IO_TX_FIFO_REMPTY_INT_ST : RO; bitpos: [0]; default: 0; @@ -329,7 +329,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_ST_S 2 /** PARL_IO_INT_CLR_REG register - * Parallel IO interrupt clear singal configuration register. + * Parallel IO interrupt clear signal configuration register. */ #define PARL_IO_INT_CLR_REG (DR_REG_PARL_IO_BASE + 0x20) /** PARL_IO_TX_FIFO_REMPTY_INT_CLR : WT; bitpos: [0]; default: 0; diff --git a/components/soc/esp32c6/include/soc/parl_io_struct.h b/components/soc/esp32c6/register/soc/parl_io_struct.h similarity index 97% rename from components/soc/esp32c6/include/soc/parl_io_struct.h rename to components/soc/esp32c6/register/soc/parl_io_struct.h index 816a7de3ef1a..e0000ebc56ba 100644 --- a/components/soc/esp32c6/include/soc/parl_io_struct.h +++ b/components/soc/esp32c6/register/soc/parl_io_struct.h @@ -26,7 +26,7 @@ typedef union { */ uint32_t rx_start:1; /** rx_data_bytelen : R/W; bitpos: [17:2]; default: 0; - * Configures rx receieved data byte length. + * Configures rx received data byte length. */ uint32_t rx_data_bytelen:16; /** rx_sw_en : R/W; bitpos: [18]; default: 0; @@ -213,7 +213,7 @@ typedef union { /** Group: PARL_IO Interrupt Configuration and Status */ /** Type of int_ena register - * Parallel IO interrupt enable singal configuration register. + * Parallel IO interrupt enable signal configuration register. */ typedef union { struct { @@ -235,7 +235,7 @@ typedef union { } parl_io_int_ena_reg_t; /** Type of int_raw register - * Parallel IO interrupt raw singal status register. + * Parallel IO interrupt raw signal status register. */ typedef union { struct { @@ -257,7 +257,7 @@ typedef union { } parl_io_int_raw_reg_t; /** Type of int_st register - * Parallel IO interrupt singal status register. + * Parallel IO interrupt signal status register. */ typedef union { struct { @@ -279,7 +279,7 @@ typedef union { } parl_io_int_st_reg_t; /** Type of int_clr register - * Parallel IO interrupt clear singal configuration register. + * Parallel IO interrupt clear signal configuration register. */ typedef union { struct { diff --git a/components/soc/esp32c6/include/soc/pau_reg.h b/components/soc/esp32c6/register/soc/pau_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/pau_reg.h rename to components/soc/esp32c6/register/soc/pau_reg.h diff --git a/components/soc/esp32c6/include/soc/pau_struct.h b/components/soc/esp32c6/register/soc/pau_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/pau_struct.h rename to components/soc/esp32c6/register/soc/pau_struct.h diff --git a/components/soc/esp32c6/include/soc/pcnt_reg.h b/components/soc/esp32c6/register/soc/pcnt_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/pcnt_reg.h rename to components/soc/esp32c6/register/soc/pcnt_reg.h diff --git a/components/soc/esp32c6/include/soc/pcnt_struct.h b/components/soc/esp32c6/register/soc/pcnt_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/pcnt_struct.h rename to components/soc/esp32c6/register/soc/pcnt_struct.h diff --git a/components/soc/esp32c6/include/soc/pcr_reg.h b/components/soc/esp32c6/register/soc/pcr_reg.h similarity index 98% rename from components/soc/esp32c6/include/soc/pcr_reg.h rename to components/soc/esp32c6/register/soc/pcr_reg.h index 35a77baaab4e..466b25f0201b 100644 --- a/components/soc/esp32c6/include/soc/pcr_reg.h +++ b/components/soc/esp32c6/register/soc/pcr_reg.h @@ -201,7 +201,7 @@ extern "C" { #define PCR_MSPI_CLK_CONF_REG (DR_REG_PCR_BASE + 0x1c) /** PCR_MSPI_FAST_LS_DIV_NUM : R/W; bitpos: [7:0]; default: 0; * Set as one within (0,1,2) to generate div1(default)/div2/div4 of low-speed - * clock-source to drive clk_mspi_fast. Only avaiable whe the clck-source is a + * clock-source to drive clk_mspi_fast. Only available when the clck-source is a * low-speed clock-source such as XTAL/FOSC. */ #define PCR_MSPI_FAST_LS_DIV_NUM 0x000000FFU @@ -210,7 +210,7 @@ extern "C" { #define PCR_MSPI_FAST_LS_DIV_NUM_S 0 /** PCR_MSPI_FAST_HS_DIV_NUM : R/W; bitpos: [15:8]; default: 3; * Set as one within (3,4,5) to generate div4(default)/div5/div6 of high-speed - * clock-source to drive clk_mspi_fast. Only avaiable whe the clck-source is a + * clock-source to drive clk_mspi_fast. Only available when the clck-source is a * high-speed clock-source such as SPLL. */ #define PCR_MSPI_FAST_HS_DIV_NUM 0x000000FFU @@ -1163,7 +1163,7 @@ extern "C" { #define PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM_V 0x0000000FU #define PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM_S 0 /** PCR_PVT_MONITOR_FUNC_CLK_SEL : R/W; bitpos: [20]; default: 0; - * set this field to select clock-source. 0: XTAL, 1(default): 160MHz drived by SPLL + * set this field to select clock-source. 0: XTAL, 1(default): 160MHz driven by SPLL * divided by 3. */ #define PCR_PVT_MONITOR_FUNC_CLK_SEL (BIT(20)) @@ -1666,8 +1666,8 @@ extern "C" { */ #define PCR_CPU_FREQ_CONF_REG (DR_REG_PCR_BASE + 0x118) /** PCR_CPU_LS_DIV_NUM : R/W; bitpos: [7:0]; default: 0; - * Set as one within (0,1,3) to generate clk_cpu drived by clk_hproot. The clk_cpu is - * div1(default)/div2/div4 of clk_hproot. This field is only avaliable for low-speed + * Set as one within (0,1,3) to generate clk_cpu driven by clk_hproot. The clk_cpu is + * div1(default)/div2/div4 of clk_hproot. This field is only available for low-speed * clock-source such as XTAL/FOSC, and should be used together with PCR_AHB_LS_DIV_NUM. */ #define PCR_CPU_LS_DIV_NUM 0x000000FFU @@ -1675,8 +1675,8 @@ extern "C" { #define PCR_CPU_LS_DIV_NUM_V 0x000000FFU #define PCR_CPU_LS_DIV_NUM_S 0 /** PCR_CPU_HS_DIV_NUM : R/W; bitpos: [15:8]; default: 0; - * Set as one within (0,1,3) to generate clk_cpu drived by clk_hproot. The clk_cpu is - * div1(default)/div2/div4 of clk_hproot. This field is only avaliable for high-speed + * Set as one within (0,1,3) to generate clk_cpu driven by clk_hproot. The clk_cpu is + * div1(default)/div2/div4 of clk_hproot. This field is only available for high-speed * clock-source such as SPLL, and should be used together with PCR_AHB_HS_DIV_NUM. */ #define PCR_CPU_HS_DIV_NUM 0x000000FFU @@ -1685,7 +1685,7 @@ extern "C" { #define PCR_CPU_HS_DIV_NUM_S 8 /** PCR_CPU_HS_120M_FORCE : R/W; bitpos: [16]; default: 0; * Given that PCR_CPU_HS_DIV_NUM is 0, set this field as 1 to force clk_cpu at 120MHz. - * Only avaliable when PCR_CPU_HS_DIV_NUM is 0 and clk_cpu is driven by SPLL. + * Only available when PCR_CPU_HS_DIV_NUM is 0 and clk_cpu is driven by SPLL. */ #define PCR_CPU_HS_120M_FORCE (BIT(16)) #define PCR_CPU_HS_120M_FORCE_M (PCR_CPU_HS_120M_FORCE_V << PCR_CPU_HS_120M_FORCE_S) @@ -1697,8 +1697,8 @@ extern "C" { */ #define PCR_AHB_FREQ_CONF_REG (DR_REG_PCR_BASE + 0x11c) /** PCR_AHB_LS_DIV_NUM : R/W; bitpos: [7:0]; default: 0; - * Set as one within (0,1,3,7) to generate clk_ahb drived by clk_hproot. The clk_ahb - * is div1(default)/div2/div4/div8 of clk_hproot. This field is only avaliable for + * Set as one within (0,1,3,7) to generate clk_ahb driven by clk_hproot. The clk_ahb + * is div1(default)/div2/div4/div8 of clk_hproot. This field is only available for * low-speed clock-source such as XTAL/FOSC, and should be used together with * PCR_CPU_LS_DIV_NUM. */ @@ -1707,8 +1707,8 @@ extern "C" { #define PCR_AHB_LS_DIV_NUM_V 0x000000FFU #define PCR_AHB_LS_DIV_NUM_S 0 /** PCR_AHB_HS_DIV_NUM : R/W; bitpos: [15:8]; default: 3; - * Set as one within (3,7,15) to generate clk_ahb drived by clk_hproot. The clk_ahb is - * div4(default)/div8/div16 of clk_hproot. This field is only avaliable for high-speed + * Set as one within (3,7,15) to generate clk_ahb driven by clk_hproot. The clk_ahb is + * div4(default)/div8/div16 of clk_hproot. This field is only available for high-speed * clock-source such as SPLL, and should be used together with PCR_CPU_HS_DIV_NUM. */ #define PCR_AHB_HS_DIV_NUM 0x000000FFU @@ -1734,7 +1734,7 @@ extern "C" { #define PCR_APB_DECREASE_DIV_NUM_V 0x000000FFU #define PCR_APB_DECREASE_DIV_NUM_S 0 /** PCR_APB_DIV_NUM : R/W; bitpos: [15:8]; default: 0; - * Set as one within (0,1,3) to generate clk_apb drived by clk_ahb. The clk_apb is + * Set as one within (0,1,3) to generate clk_apb driven by clk_ahb. The clk_apb is * div1(default)/div2/div4 of clk_ahb. */ #define PCR_APB_DIV_NUM 0x000000FFU @@ -1766,56 +1766,56 @@ extern "C" { */ #define PCR_PLL_DIV_CLK_EN_REG (DR_REG_PCR_BASE + 0x128) /** PCR_PLL_240M_CLK_EN : R/W; bitpos: [0]; default: 1; - * This field is used to open 240 MHz clock (div2 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 240 MHz clock (div2 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_240M_CLK_EN (BIT(0)) #define PCR_PLL_240M_CLK_EN_M (PCR_PLL_240M_CLK_EN_V << PCR_PLL_240M_CLK_EN_S) #define PCR_PLL_240M_CLK_EN_V 0x00000001U #define PCR_PLL_240M_CLK_EN_S 0 /** PCR_PLL_160M_CLK_EN : R/W; bitpos: [1]; default: 1; - * This field is used to open 160 MHz clock (div3 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 160 MHz clock (div3 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_160M_CLK_EN (BIT(1)) #define PCR_PLL_160M_CLK_EN_M (PCR_PLL_160M_CLK_EN_V << PCR_PLL_160M_CLK_EN_S) #define PCR_PLL_160M_CLK_EN_V 0x00000001U #define PCR_PLL_160M_CLK_EN_S 1 /** PCR_PLL_120M_CLK_EN : R/W; bitpos: [2]; default: 1; - * This field is used to open 120 MHz clock (div4 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 120 MHz clock (div4 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_120M_CLK_EN (BIT(2)) #define PCR_PLL_120M_CLK_EN_M (PCR_PLL_120M_CLK_EN_V << PCR_PLL_120M_CLK_EN_S) #define PCR_PLL_120M_CLK_EN_V 0x00000001U #define PCR_PLL_120M_CLK_EN_S 2 /** PCR_PLL_80M_CLK_EN : R/W; bitpos: [3]; default: 1; - * This field is used to open 80 MHz clock (div6 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 80 MHz clock (div6 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_80M_CLK_EN (BIT(3)) #define PCR_PLL_80M_CLK_EN_M (PCR_PLL_80M_CLK_EN_V << PCR_PLL_80M_CLK_EN_S) #define PCR_PLL_80M_CLK_EN_V 0x00000001U #define PCR_PLL_80M_CLK_EN_S 3 /** PCR_PLL_48M_CLK_EN : R/W; bitpos: [4]; default: 1; - * This field is used to open 48 MHz clock (div10 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 48 MHz clock (div10 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_48M_CLK_EN (BIT(4)) #define PCR_PLL_48M_CLK_EN_M (PCR_PLL_48M_CLK_EN_V << PCR_PLL_48M_CLK_EN_S) #define PCR_PLL_48M_CLK_EN_V 0x00000001U #define PCR_PLL_48M_CLK_EN_S 4 /** PCR_PLL_40M_CLK_EN : R/W; bitpos: [5]; default: 1; - * This field is used to open 40 MHz clock (div12 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 40 MHz clock (div12 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_40M_CLK_EN (BIT(5)) #define PCR_PLL_40M_CLK_EN_M (PCR_PLL_40M_CLK_EN_V << PCR_PLL_40M_CLK_EN_S) #define PCR_PLL_40M_CLK_EN_V 0x00000001U #define PCR_PLL_40M_CLK_EN_S 5 /** PCR_PLL_20M_CLK_EN : R/W; bitpos: [6]; default: 1; - * This field is used to open 20 MHz clock (div24 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 20 MHz clock (div24 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_20M_CLK_EN (BIT(6)) #define PCR_PLL_20M_CLK_EN_M (PCR_PLL_20M_CLK_EN_V << PCR_PLL_20M_CLK_EN_S) diff --git a/components/soc/esp32c6/include/soc/pcr_struct.h b/components/soc/esp32c6/register/soc/pcr_struct.h similarity index 97% rename from components/soc/esp32c6/include/soc/pcr_struct.h rename to components/soc/esp32c6/register/soc/pcr_struct.h index f31e632d865b..ee74db8ff14b 100644 --- a/components/soc/esp32c6/include/soc/pcr_struct.h +++ b/components/soc/esp32c6/register/soc/pcr_struct.h @@ -176,13 +176,13 @@ typedef union { struct { /** mspi_fast_ls_div_num : R/W; bitpos: [7:0]; default: 0; * Set as one within (0,1,2) to generate div1(default)/div2/div4 of low-speed - * clock-source to drive clk_mspi_fast. Only avaiable whe the clck-source is a + * clock-source to drive clk_mspi_fast. Only available when the clck-source is a * low-speed clock-source such as XTAL/FOSC. */ uint32_t mspi_fast_ls_div_num:8; /** mspi_fast_hs_div_num : R/W; bitpos: [15:8]; default: 3; * Set as one within (3,4,5) to generate div4(default)/div5/div6 of high-speed - * clock-source to drive clk_mspi_fast. Only avaiable whe the clck-source is a + * clock-source to drive clk_mspi_fast. Only available when the clck-source is a * high-speed clock-source such as SPLL. */ uint32_t mspi_fast_hs_div_num:8; @@ -1033,7 +1033,7 @@ typedef union { uint32_t pvt_monitor_func_clk_div_num:4; uint32_t reserved_4:16; /** pvt_monitor_func_clk_sel : R/W; bitpos: [20]; default: 0; - * set this field to select clock-source. 0: XTAL, 1(default): 160MHz drived by SPLL + * set this field to select clock-source. 0: XTAL, 1(default): 160MHz driven by SPLL * divided by 3. */ uint32_t pvt_monitor_func_clk_sel:1; @@ -1499,20 +1499,20 @@ typedef union { typedef union { struct { /** cpu_ls_div_num : R/W; bitpos: [7:0]; default: 0; - * Set as one within (0,1,3) to generate clk_cpu drived by clk_hproot. The clk_cpu is - * div1(default)/div2/div4 of clk_hproot. This field is only avaliable for low-speed + * Set as one within (0,1,3) to generate clk_cpu driven by clk_hproot. The clk_cpu is + * div1(default)/div2/div4 of clk_hproot. This field is only available for low-speed * clock-source such as XTAL/FOSC, and should be used together with PCR_AHB_LS_DIV_NUM. */ uint32_t cpu_ls_div_num:8; /** cpu_hs_div_num : R/W; bitpos: [15:8]; default: 0; - * Set as one within (0,1,3) to generate clk_cpu drived by clk_hproot. The clk_cpu is - * div1(default)/div2/div4 of clk_hproot. This field is only avaliable for high-speed + * Set as one within (0,1,3) to generate clk_cpu driven by clk_hproot. The clk_cpu is + * div1(default)/div2/div4 of clk_hproot. This field is only available for high-speed * clock-source such as SPLL, and should be used together with PCR_AHB_HS_DIV_NUM. */ uint32_t cpu_hs_div_num:8; /** cpu_hs_120m_force : R/W; bitpos: [16]; default: 0; * Given that PCR_CPU_HS_DIV_NUM is 0, set this field as 1 to force clk_cpu at 120MHz. - * Only avaliable when PCR_CPU_HS_DIV_NUM is 0 and clk_cpu is driven by SPLL. + * Only available when PCR_CPU_HS_DIV_NUM is 0 and clk_cpu is driven by SPLL. */ uint32_t cpu_hs_120m_force:1; uint32_t reserved_17:15; @@ -1526,15 +1526,15 @@ typedef union { typedef union { struct { /** ahb_ls_div_num : R/W; bitpos: [7:0]; default: 0; - * Set as one within (0,1,3,7) to generate clk_ahb drived by clk_hproot. The clk_ahb - * is div1(default)/div2/div4/div8 of clk_hproot. This field is only avaliable for + * Set as one within (0,1,3,7) to generate clk_ahb driven by clk_hproot. The clk_ahb + * is div1(default)/div2/div4/div8 of clk_hproot. This field is only available for * low-speed clock-source such as XTAL/FOSC, and should be used together with * PCR_CPU_LS_DIV_NUM. */ uint32_t ahb_ls_div_num:8; /** ahb_hs_div_num : R/W; bitpos: [15:8]; default: 3; - * Set as one within (3,7,15) to generate clk_ahb drived by clk_hproot. The clk_ahb is - * div4(default)/div8/div16 of clk_hproot. This field is only avaliable for high-speed + * Set as one within (3,7,15) to generate clk_ahb driven by clk_hproot. The clk_ahb is + * div4(default)/div8/div16 of clk_hproot. This field is only available for high-speed * clock-source such as SPLL, and should be used together with PCR_CPU_HS_DIV_NUM. */ uint32_t ahb_hs_div_num:8; @@ -1559,7 +1559,7 @@ typedef union { */ uint32_t apb_decrease_div_num:8; /** apb_div_num : R/W; bitpos: [15:8]; default: 0; - * Set as one within (0,1,3) to generate clk_apb drived by clk_ahb. The clk_apb is + * Set as one within (0,1,3) to generate clk_apb driven by clk_ahb. The clk_apb is * div1(default)/div2/div4 of clk_ahb. */ uint32_t apb_div_num:8; @@ -1574,38 +1574,38 @@ typedef union { typedef union { struct { /** pll_240m_clk_en : R/W; bitpos: [0]; default: 1; - * This field is used to open 240 MHz clock (div2 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 240 MHz clock (div2 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_240m_clk_en:1; /** pll_160m_clk_en : R/W; bitpos: [1]; default: 1; - * This field is used to open 160 MHz clock (div3 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 160 MHz clock (div3 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_160m_clk_en:1; /** pll_120m_clk_en : R/W; bitpos: [2]; default: 1; - * This field is used to open 120 MHz clock (div4 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 120 MHz clock (div4 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_120m_clk_en:1; /** pll_80m_clk_en : R/W; bitpos: [3]; default: 1; - * This field is used to open 80 MHz clock (div6 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 80 MHz clock (div6 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_80m_clk_en:1; /** pll_48m_clk_en : R/W; bitpos: [4]; default: 1; - * This field is used to open 48 MHz clock (div10 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 48 MHz clock (div10 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_48m_clk_en:1; /** pll_40m_clk_en : R/W; bitpos: [5]; default: 1; - * This field is used to open 40 MHz clock (div12 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 40 MHz clock (div12 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_40m_clk_en:1; /** pll_20m_clk_en : R/W; bitpos: [6]; default: 1; - * This field is used to open 20 MHz clock (div24 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 20 MHz clock (div24 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_20m_clk_en:1; uint32_t reserved_7:25; diff --git a/components/soc/esp32c6/include/soc/plic_reg.h b/components/soc/esp32c6/register/soc/plic_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/plic_reg.h rename to components/soc/esp32c6/register/soc/plic_reg.h diff --git a/components/soc/esp32c6/include/soc/pmu_reg.h b/components/soc/esp32c6/register/soc/pmu_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/pmu_reg.h rename to components/soc/esp32c6/register/soc/pmu_reg.h diff --git a/components/soc/esp32c6/include/soc/pmu_struct.h b/components/soc/esp32c6/register/soc/pmu_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/pmu_struct.h rename to components/soc/esp32c6/register/soc/pmu_struct.h index 5d0631189555..db545cfbc58f 100644 --- a/components/soc/esp32c6/include/soc/pmu_struct.h +++ b/components/soc/esp32c6/register/soc/pmu_struct.h @@ -11,7 +11,7 @@ extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #include "soc/pmu_reg.h" typedef union { diff --git a/components/soc/esp32c6/include/soc/reg_base.h b/components/soc/esp32c6/register/soc/reg_base.h similarity index 100% rename from components/soc/esp32c6/include/soc/reg_base.h rename to components/soc/esp32c6/register/soc/reg_base.h diff --git a/components/soc/esp32c6/include/soc/rmt_reg.h b/components/soc/esp32c6/register/soc/rmt_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/rmt_reg.h rename to components/soc/esp32c6/register/soc/rmt_reg.h diff --git a/components/soc/esp32c6/include/soc/rmt_struct.h b/components/soc/esp32c6/register/soc/rmt_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/rmt_struct.h rename to components/soc/esp32c6/register/soc/rmt_struct.h diff --git a/components/soc/esp32c6/include/soc/rsa_reg.h b/components/soc/esp32c6/register/soc/rsa_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/rsa_reg.h rename to components/soc/esp32c6/register/soc/rsa_reg.h diff --git a/components/soc/esp32c6/include/soc/rsa_struct.h b/components/soc/esp32c6/register/soc/rsa_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/rsa_struct.h rename to components/soc/esp32c6/register/soc/rsa_struct.h diff --git a/components/soc/esp32c6/include/soc/sha_reg.h b/components/soc/esp32c6/register/soc/sha_reg.h similarity index 98% rename from components/soc/esp32c6/include/soc/sha_reg.h rename to components/soc/esp32c6/register/soc/sha_reg.h index 265f510472a8..46955176e5af 100644 --- a/components/soc/esp32c6/include/soc/sha_reg.h +++ b/components/soc/esp32c6/register/soc/sha_reg.h @@ -156,7 +156,7 @@ extern "C" { #define SHA_DATE_S 0 /** SHA_H_MEM register - * Sha H memory which contains intermediate hash or finial hash. + * Sha H memory which contains intermediate hash or final hash. */ #define SHA_H_MEM (DR_REG_SHA_BASE + 0x40) #define SHA_H_MEM_SIZE_BYTES 64 diff --git a/components/soc/esp32c6/include/soc/sha_struct.h b/components/soc/esp32c6/register/soc/sha_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/sha_struct.h rename to components/soc/esp32c6/register/soc/sha_struct.h diff --git a/components/soc/esp32c6/include/soc/slc_reg.h b/components/soc/esp32c6/register/soc/slc_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/slc_reg.h rename to components/soc/esp32c6/register/soc/slc_reg.h diff --git a/components/soc/esp32c6/include/soc/slc_struct.h b/components/soc/esp32c6/register/soc/slc_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/slc_struct.h rename to components/soc/esp32c6/register/soc/slc_struct.h diff --git a/components/soc/esp32c6/include/soc/soc_etm_reg.h b/components/soc/esp32c6/register/soc/soc_etm_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/soc_etm_reg.h rename to components/soc/esp32c6/register/soc/soc_etm_reg.h diff --git a/components/soc/esp32c6/include/soc/soc_etm_struct.h b/components/soc/esp32c6/register/soc/soc_etm_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/soc_etm_struct.h rename to components/soc/esp32c6/register/soc/soc_etm_struct.h diff --git a/components/soc/esp32c6/include/soc/spi_mem_reg.h b/components/soc/esp32c6/register/soc/spi_mem_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/spi_mem_reg.h rename to components/soc/esp32c6/register/soc/spi_mem_reg.h index 81a136b87033..56ada6dc461d 100644 --- a/components/soc/esp32c6/include/soc/spi_mem_reg.h +++ b/components/soc/esp32c6/register/soc/spi_mem_reg.h @@ -98,8 +98,8 @@ he bit will be cleared once the operation done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_DP_S 21 /* SPI_MEM_FLASH_RES : R/W/SC ;bitpos:[20] ;default: 1'b0 ; */ /*description: This bit combined with reg_resandres bit releases Flash from the power-down stat -e or high performance mode and obtains the devices ID. The bit will be cleared o -nce the operation done.1: enable 0: disable..*/ +e or high performance mode and obtains the devices ID. The bit will be cleared once + the operation done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_RES (BIT(20)) #define SPI_MEM_FLASH_RES_M (BIT(20)) #define SPI_MEM_FLASH_RES_V 0x1 @@ -128,9 +128,9 @@ peration done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_PE_V 0x1 #define SPI_MEM_FLASH_PE_S 17 /* SPI_MEM_SLV_ST : RO ;bitpos:[7:4] ;default: 4'b0 ; */ -/*description: The current status of SPI0 slave FSM: mspi_st. 0: idle state, 1: preparation sta -te, 2: send command state, 3: send address state, 4: wait state, 5: read data st -ate, 6:write data state, 7: done state, 8: read data end state..*/ +/*description: The current status of SPI0 slave FSM: mspi_st. 0: idle state, 1: preparation state, +2: send command state, 3: send address state, 4: wait state, 5: read data state +, 6:write data state, 7: done state, 8: read data end state..*/ #define SPI_MEM_SLV_ST 0x0000000F #define SPI_MEM_SLV_ST_M ((SPI_MEM_SLV_ST_V)<<(SPI_MEM_SLV_ST_S)) #define SPI_MEM_SLV_ST_V 0xF @@ -162,7 +162,7 @@ lways 1. 0: Others..*/ #define SPI_MEM_DATA_IE_ALWAYS_ON_V 0x1 #define SPI_MEM_DATA_IE_ALWAYS_ON_S 31 /* SPI_MEM_DQS_IE_ALWAYS_ON : HRO ;bitpos:[30] ;default: 1'b0 ; */ -/*description: When accesses to flash, 1: the IE signals of pads connected to SPI_DQS are alway +/*description: When accesses to flash, 1: the IE signals of pads connected to SPI_DQS are always s 1. 0: Others..*/ #define SPI_MEM_DQS_IE_ALWAYS_ON (BIT(30)) #define SPI_MEM_DQS_IE_ALWAYS_ON_M (BIT(30)) @@ -234,14 +234,14 @@ UT and SPI_MEM_FREAD_DOUT. 1: enable 0: disable..*/ #define SPI_MEM_FASTRD_MODE_V 0x1 #define SPI_MEM_FASTRD_MODE_S 13 /* SPI_MEM_TX_CRC_EN : HRO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disabl +/*description: For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disable e.*/ #define SPI_MEM_TX_CRC_EN (BIT(11)) #define SPI_MEM_TX_CRC_EN_M (BIT(11)) #define SPI_MEM_TX_CRC_EN_V 0x1 #define SPI_MEM_TX_CRC_EN_S 11 /* SPI_MEM_FCS_CRC_EN : HRO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: For SPI1, initialize crc32 module before writing encrypted data to flash. Activ +/*description: For SPI1, initialize crc32 module before writing encrypted data to flash. Active e low..*/ #define SPI_MEM_FCS_CRC_EN (BIT(10)) #define SPI_MEM_FCS_CRC_EN_M (BIT(10)) @@ -397,7 +397,7 @@ y the real AXI read data back. 0: When ARSIZE 0~1, MSPI reply SLV_ERR..*/ /* SPI_MEM_CLK_MODE : R/W ;bitpos:[1:0] ;default: 2'h0 ; */ /*description: SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delaye d one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inacti -ve 3: SPI clock is alwasy on..*/ +ve 3: SPI clock is always on..*/ #define SPI_MEM_CLK_MODE 0x00000003 #define SPI_MEM_CLK_MODE_M ((SPI_MEM_CLK_MODE_V)<<(SPI_MEM_CLK_MODE_S)) #define SPI_MEM_CLK_MODE_V 0x3 @@ -427,8 +427,8 @@ whether there is an ECC region or not..*/ #define SPI_MEM_SPLIT_TRANS_EN_V 0x1 #define SPI_MEM_SPLIT_TRANS_EN_S 24 /* SPI_MEM_ECC_16TO18_BYTE_EN : HRO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: Set this bit to enable SPI0 and SPI1 ECC 16 bytes data with 2 ECC bytes mode whe -n accesses flash..*/ +/*description: Set this bit to enable SPI0 and SPI1 ECC 16 bytes data with 2 ECC bytes mode when + accesses flash..*/ #define SPI_MEM_ECC_16TO18_BYTE_EN (BIT(14)) #define SPI_MEM_ECC_16TO18_BYTE_EN_M (BIT(14)) #define SPI_MEM_ECC_16TO18_BYTE_EN_V 0x1 @@ -808,8 +808,8 @@ he register value shall be (bit_num-1)..*/ #define SPI_MEM_SRAM_RDUMMY_CYCLELEN_V 0x3F #define SPI_MEM_SRAM_RDUMMY_CYCLELEN_S 6 /* SPI_MEM_CACHE_SRAM_USR_RCMD : HRO ;bitpos:[5] ;default: 1'b1 ; */ -/*description: For SPI0, In the external RAM mode cache read external RAM for user define comma -nd..*/ +/*description: For SPI0, In the external RAM mode cache read external RAM for user define command +..*/ #define SPI_MEM_CACHE_SRAM_USR_RCMD (BIT(5)) #define SPI_MEM_CACHE_SRAM_USR_RCMD_M (BIT(5)) #define SPI_MEM_CACHE_SRAM_USR_RCMD_V 0x1 @@ -1016,7 +1016,7 @@ e for sram..*/ #define SPI_MEM_SRAM_CLK_REG(i) (REG_SPI_MEM_BASE(i) + 0x50) /* SPI_MEM_SCLK_EQU_SYSCLK : HRO ;bitpos:[31] ;default: 1'b0 ; */ -/*description: For SPI0 external RAM interface, 1: spi_mem_clk is eqaul to system 0: spi_mem_c +/*description: For SPI0 external RAM interface, 1: spi_mem_clk is equal to system 0: spi_mem_c lk is divided from system clock..*/ #define SPI_MEM_SCLK_EQU_SYSCLK (BIT(31)) #define SPI_MEM_SCLK_EQU_SYSCLK_M (BIT(31)) @@ -1274,7 +1274,7 @@ out, status_in[15:0] is valid when two bytes of data are read out), SUS/SUS1/SUS #define SPI_MEM_FLASH_PES_EN_S 5 /* SPI_MEM_PES_PER_EN : R/W ;bitpos:[4] ;default: 1'b0 ; */ /*description: Set this bit to enable PES end triggers PER transfer option. If this bit is 0, a -pplication should send PER after PES is done..*/ +application should send PER after PES is done..*/ #define SPI_MEM_PES_PER_EN (BIT(4)) #define SPI_MEM_PES_PER_EN_M (BIT(4)) #define SPI_MEM_PES_PER_EN_V 0x1 @@ -1296,8 +1296,8 @@ resume command is sent..*/ #define SPI_MEM_FLASH_PER_WAIT_EN_V 0x1 #define SPI_MEM_FLASH_PER_WAIT_EN_S 2 /* SPI_MEM_FLASH_PES : R/W/SC ;bitpos:[1] ;default: 1'b0 ; */ -/*description: program erase suspend bit, program erase suspend operation will be triggered whe -n the bit is set. The bit will be cleared once the operation done.1: enable 0: d +/*description: program erase suspend bit, program erase suspend operation will be triggered when +the bit is set. The bit will be cleared once the operation done.1: enable 0: d isable..*/ #define SPI_MEM_FLASH_PES (BIT(1)) #define SPI_MEM_FLASH_PES_M (BIT(1)) @@ -1541,7 +1541,7 @@ mmand is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles #define SPI_MEM_INT_RAW_REG(i) (REG_SPI_MEM_BASE(i) + 0xC8) /* SPI_MEM_BROWN_OUT_INT_RAW : R/WTC/SS ;bitpos:[10] ;default: 1'b0 ; */ /*description: The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that -chip is loosing power and RTC module sends out brown out close flash request to +chip is losing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others..*/ #define SPI_MEM_BROWN_OUT_INT_RAW (BIT(10)) @@ -1584,9 +1584,9 @@ et and SPI_SMEM_ECC_ERR_INT_EN is cleared, this bit is triggered when the error his bit is triggered when the error times of SPI0/1 ECC read external RAM are eq ual or bigger than SPI_MEM_ECC_ERR_INT_NUM. When SPI_FMEM_ECC_ERR_INT_EN and SP I_SMEM_ECC_ERR_INT_EN are set, this bit is triggered when the total error times -of SPI0/1 ECC read external RAM and flash are equal or bigger than SPI_MEM_ECC_E -RR_INT_NUM. When SPI_FMEM_ECC_ERR_INT_EN and SPI_SMEM_ECC_ERR_INT_EN are cleare -d, this bit will not be triggered..*/ +of SPI0/1 ECC read external RAM and flash are equal or bigger than SPI_MEM_ECC_ERR_INT_NUM. +When SPI_FMEM_ECC_ERR_INT_EN and SPI_SMEM_ECC_ERR_INT_EN are cleared, +this bit will not be triggered..*/ #define SPI_MEM_ECC_ERR_INT_RAW (BIT(5)) #define SPI_MEM_ECC_ERR_INT_RAW_M (BIT(5)) #define SPI_MEM_ECC_ERR_INT_RAW_V 0x1 @@ -2376,8 +2376,8 @@ and RDATA_AFIFO are empty and spi0_mst_st is IDLE..*/ #define SPI_MEM_ALL_FIFO_EMPTY_V 0x1 #define SPI_MEM_ALL_FIFO_EMPTY_S 26 /* SPI_MEM_AXI_ERR_ADDR : R/SS/WTC ;bitpos:[25:0] ;default: 26'h0 ; */ -/*description: This bits show the first AXI write/read invalid error or AXI write flash error a -ddress. It is cleared by when SPI_MEM_AXI_WADDR_ERR_INT_CLR, SPI_MEM_AXI_WR_FLAS +/*description: This bits show the first AXI write/read invalid error or AXI write flash error +address. It is cleared by when SPI_MEM_AXI_WADDR_ERR_INT_CLR, SPI_MEM_AXI_WR_FLAS H_ERR_IN_CLR or SPI_MEM_AXI_RADDR_ERR_IN_CLR bit is set..*/ #define SPI_MEM_AXI_ERR_ADDR 0x03FFFFFF #define SPI_MEM_AXI_ERR_ADDR_M ((SPI_MEM_AXI_ERR_ADDR_V)<<(SPI_MEM_AXI_ERR_ADDR_S)) @@ -2684,7 +2684,7 @@ ations..*/ #define SPI_MEM_SMEM_TIMING_CALI_V 0x1 #define SPI_MEM_SMEM_TIMING_CALI_S 1 /* SPI_MEM_SMEM_TIMING_CLK_ENA : HRO ;bitpos:[0] ;default: 1'b1 ; */ -/*description: For sram, the bit is used to enable timing adjust clock for all reading operatio +/*description: For sram, the bit is used to enable timing adjust clock for all reading operation ns..*/ #define SPI_MEM_SMEM_TIMING_CLK_ENA (BIT(0)) #define SPI_MEM_SMEM_TIMING_CLK_ENA_M (BIT(0)) @@ -2942,8 +2942,8 @@ SPI core clock cycles..*/ #define SPI_MEM_SMEM_CS_HOLD_DELAY_V 0x3F #define SPI_MEM_SMEM_CS_HOLD_DELAY_S 25 /* SPI_MEM_SMEM_ECC_16TO18_BYTE_EN : HRO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: Set this bit to enable SPI0 and SPI1 ECC 16 bytes data with 2 ECC bytes mode whe -n accesses external RAM..*/ +/*description: Set this bit to enable SPI0 and SPI1 ECC 16 bytes data with 2 ECC bytes mode when +accesses external RAM..*/ #define SPI_MEM_SMEM_ECC_16TO18_BYTE_EN (BIT(16)) #define SPI_MEM_SMEM_ECC_16TO18_BYTE_EN_M (BIT(16)) #define SPI_MEM_SMEM_ECC_16TO18_BYTE_EN_V 0x1 diff --git a/components/soc/esp32c6/include/soc/spi_mem_struct.h b/components/soc/esp32c6/register/soc/spi_mem_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/spi_mem_struct.h rename to components/soc/esp32c6/register/soc/spi_mem_struct.h index 9e2f7c1d3bae..74588ee0277a 100644 --- a/components/soc/esp32c6/include/soc/spi_mem_struct.h +++ b/components/soc/esp32c6/register/soc/spi_mem_struct.h @@ -69,7 +69,7 @@ typedef volatile struct spi_mem_dev_s { } ctrl; union { struct { - uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on.*/ + uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is always on.*/ uint32_t cs_hold_dly_res : 10; /*After RES/DP/HPM command is sent, SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 512) SPI_CLK cycles.*/ uint32_t reserved2 : 9; /*reserved*/ uint32_t reg_ar_size0_1_support_en : 1; /*1: MSPI supports ARSIZE 0~3. When ARSIZE =0~2, MSPI read address is 4*n and reply the real AXI read data back. 0: When ARSIZE 0~1, MSPI reply SLV_ERR.*/ @@ -271,7 +271,7 @@ typedef volatile struct spi_mem_dev_s { uint32_t sclkcnt_h : 8; /*For SPI0 external RAM interface, it must be floor((spi_mem_clkcnt_N+1)/2-1).*/ uint32_t sclkcnt_n : 8; /*For SPI0 external RAM interface, it is the divider of spi_mem_clk. So spi_mem_clk frequency is system/(spi_mem_clkcnt_N+1)*/ uint32_t reserved24 : 7; /*reserved*/ - uint32_t sclk_equ_sysclk : 1; /*For SPI0 external RAM interface, 1: spi_mem_clk is eqaul to system 0: spi_mem_clk is divided from system clock.*/ + uint32_t sclk_equ_sysclk : 1; /*For SPI0 external RAM interface, 1: spi_mem_clk is equal to system 0: spi_mem_clk is divided from system clock.*/ }; uint32_t val; } sram_clk; @@ -388,7 +388,7 @@ typedef volatile struct spi_mem_dev_s { uint32_t axi_raddr_err : 1; /*The raw bit for SPI_MEM_AXI_RADDR_ERR_INT interrupt. 1: Triggered when AXI read address is invalid by compared to MMU configuration. 0: Others.*/ uint32_t axi_wr_flash_err : 1; /*The raw bit for SPI_MEM_AXI_WR_FALSH_ERR_INT interrupt. 1: Triggered when AXI write flash request is received. 0: Others.*/ uint32_t axi_waddr_err : 1; /*The raw bit for SPI_MEM_AXI_WADDR_ERR_INT interrupt. 1: Triggered when AXI write address is invalid by compared to MMU configuration. 0: Others.*/ - uint32_t brown_out : 1; /*The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is loosing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others.*/ + uint32_t brown_out : 1; /*The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is losing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others.*/ uint32_t reserved11 : 21; /*reserved*/ }; uint32_t val; @@ -1025,7 +1025,7 @@ typedef volatile struct spi_mem_dev_s { } mmu_power_ctrl; union { struct { - uint32_t reg_crypt_security_level : 3; /*Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1-7: The bigger the number is, the more secure the cryption is. (Note that the performance of cryption will decrease together with this number increasing)*/ + uint32_t reg_crypt_security_level : 3; /*Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1-7: The bigger the number is, the more secure the cryption is. (Note that the performance of cryption will decrease together with this number increasing)*/ uint32_t reg_crypt_calc_d_dpa_en : 1; /*Only available when SPI_CRYPT_SECURITY_LEVEL is not 0. 1: Enable DPA in the calculation that using key 1 or key 2. 0: Enable DPA only in the calculation that using key 1.*/ uint32_t reg_crypt_dpa_selectister : 1; /*1: MSPI XTS DPA clock gate is controlled by SPI_CRYPT_CALC_D_DPA_EN and SPI_CRYPT_SECURITY_LEVEL. 0: Controlled by efuse bits.*/ uint32_t reserved5 : 27; /*reserved*/ diff --git a/components/soc/esp32c6/include/soc/spi_reg.h b/components/soc/esp32c6/register/soc/spi_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/spi_reg.h rename to components/soc/esp32c6/register/soc/spi_reg.h index 544b54abd1f6..8da5868eaacb 100644 --- a/components/soc/esp32c6/include/soc/spi_reg.h +++ b/components/soc/esp32c6/register/soc/spi_reg.h @@ -221,7 +221,7 @@ extern "C" { #define SPI_CLKDIV_PRE_V 0x0000000FU #define SPI_CLKDIV_PRE_S 18 /** SPI_CLK_EQU_SYSCLK : R/W; bitpos: [31]; default: 1; - * In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system + * In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system * clock. Can be configured in CONF state. */ #define SPI_CLK_EQU_SYSCLK (BIT(31)) @@ -1944,7 +1944,7 @@ extern "C" { /** SPI_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. Can be configured in CONF state. + * SPI clock is always on. Can be configured in CONF state. */ #define SPI_CLK_MODE 0x00000003U #define SPI_CLK_MODE_M (SPI_CLK_MODE_V << SPI_CLK_MODE_S) diff --git a/components/soc/esp32c6/include/soc/spi_struct.h b/components/soc/esp32c6/register/soc/spi_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/spi_struct.h rename to components/soc/esp32c6/register/soc/spi_struct.h index 14b6be86c14e..52076bb16c8f 100644 --- a/components/soc/esp32c6/include/soc/spi_struct.h +++ b/components/soc/esp32c6/register/soc/spi_struct.h @@ -511,7 +511,7 @@ typedef union { /** clk_mode : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. Can be configured in CONF state. + * SPI clock is always on. Can be configured in CONF state. */ uint32_t clk_mode:2; /** clk_mode_13 : R/W; bitpos: [2]; default: 0; @@ -624,7 +624,7 @@ typedef union { uint32_t clkdiv_pre:4; uint32_t reserved_22:9; /** clk_equ_sysclk : R/W; bitpos: [31]; default: 1; - * In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system + * In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system * clock. Can be configured in CONF state. */ uint32_t clk_equ_sysclk:1; diff --git a/components/soc/esp32c6/include/soc/systimer_reg.h b/components/soc/esp32c6/register/soc/systimer_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/systimer_reg.h rename to components/soc/esp32c6/register/soc/systimer_reg.h diff --git a/components/soc/esp32c6/include/soc/systimer_struct.h b/components/soc/esp32c6/register/soc/systimer_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/systimer_struct.h rename to components/soc/esp32c6/register/soc/systimer_struct.h diff --git a/components/soc/esp32c6/include/soc/tee_reg.h b/components/soc/esp32c6/register/soc/tee_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/tee_reg.h rename to components/soc/esp32c6/register/soc/tee_reg.h diff --git a/components/soc/esp32c6/include/soc/tee_struct.h b/components/soc/esp32c6/register/soc/tee_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/tee_struct.h rename to components/soc/esp32c6/register/soc/tee_struct.h diff --git a/components/soc/esp32c6/include/soc/timer_group_reg.h b/components/soc/esp32c6/register/soc/timer_group_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/timer_group_reg.h rename to components/soc/esp32c6/register/soc/timer_group_reg.h diff --git a/components/soc/esp32c6/include/soc/timer_group_struct.h b/components/soc/esp32c6/register/soc/timer_group_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/timer_group_struct.h rename to components/soc/esp32c6/register/soc/timer_group_struct.h diff --git a/components/soc/esp32h2/include/soc/trace_reg.h b/components/soc/esp32c6/register/soc/trace_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/trace_reg.h rename to components/soc/esp32c6/register/soc/trace_reg.h index a5c3eda9dc77..b363fbd1f8eb 100644 --- a/components/soc/esp32h2/include/soc/trace_reg.h +++ b/components/soc/esp32c6/register/soc/trace_reg.h @@ -154,7 +154,7 @@ extern "C" { #define TRACE_TRIGGER_OFF_V 0x00000001U #define TRACE_TRIGGER_OFF_S 1 /** TRACE_MEM_LOOP : R/W; bitpos: [2]; default: 1; - * if this reg is 1, trace will loop wrtie trace_mem. If is 0, when mem_current_addr + * if this reg is 1, trace will loop write trace_mem. If is 0, when mem_current_addr * at mem_end_addr, it will stop at the mem_end_addr */ #define TRACE_MEM_LOOP (BIT(2)) diff --git a/components/soc/esp32c6/include/soc/trace_struct.h b/components/soc/esp32c6/register/soc/trace_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/trace_struct.h rename to components/soc/esp32c6/register/soc/trace_struct.h index 3b8330b6b0eb..e5bb04d46d5e 100644 --- a/components/soc/esp32c6/include/soc/trace_struct.h +++ b/components/soc/esp32c6/register/soc/trace_struct.h @@ -156,7 +156,7 @@ typedef union { */ uint32_t trigger_off:1; /** mem_loop : R/W; bitpos: [2]; default: 1; - * if this reg is 1, trace will loop wrtie trace_mem. If is 0, when mem_current_addr + * if this reg is 1, trace will loop write trace_mem. If is 0, when mem_current_addr * at mem_end_addr, it will stop at the mem_end_addr */ uint32_t mem_loop:1; diff --git a/components/soc/esp32c6/include/soc/twai_reg.h b/components/soc/esp32c6/register/soc/twai_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/twai_reg.h rename to components/soc/esp32c6/register/soc/twai_reg.h diff --git a/components/soc/esp32c6/include/soc/twai_struct.h b/components/soc/esp32c6/register/soc/twai_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/twai_struct.h rename to components/soc/esp32c6/register/soc/twai_struct.h diff --git a/components/soc/esp32c6/include/soc/uart_reg.h b/components/soc/esp32c6/register/soc/uart_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/uart_reg.h rename to components/soc/esp32c6/register/soc/uart_reg.h index abac8d92b197..d85004fcc1de 100644 --- a/components/soc/esp32c6/include/soc/uart_reg.h +++ b/components/soc/esp32c6/register/soc/uart_reg.h @@ -100,7 +100,7 @@ extern "C" { #define UART_RXFIFO_TOUT_INT_RAW_V 0x00000001U #define UART_RXFIFO_TOUT_INT_RAW_S 8 /** UART_SW_XON_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ #define UART_SW_XON_INT_RAW (BIT(9)) @@ -285,7 +285,7 @@ extern "C" { #define UART_TX_BRK_DONE_INT_ST_V 0x00000001U #define UART_TX_BRK_DONE_INT_ST_S 12 /** UART_TX_BRK_IDLE_DONE_INT_ST : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ #define UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) @@ -760,7 +760,7 @@ extern "C" { #define UART_STOP_BIT_NUM_V 0x00000003U #define UART_STOP_BIT_NUM_S 4 /** UART_TXD_BRK : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ #define UART_TXD_BRK (BIT(6)) @@ -1326,7 +1326,7 @@ extern "C" { */ #define UART_TOUT_CONF_SYNC_REG(i) (REG_UART_BASE(i) + 0x64) /** UART_RX_TOUT_EN : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ #define UART_RX_TOUT_EN (BIT(0)) #define UART_RX_TOUT_EN_M (UART_RX_TOUT_EN_V << UART_RX_TOUT_EN_S) @@ -1450,7 +1450,7 @@ extern "C" { */ #define UART_HIGHPULSE_REG(i) (REG_UART_BASE(i) + 0x80) /** UART_HIGHPULSE_MIN_CNT : RO; bitpos: [11:0]; default: 4095; - * This register stores the value of the maxinum duration time for the high level + * This register stores the value of the maximum duration time for the high level * pulse. It is used in baud rate-detect process. */ #define UART_HIGHPULSE_MIN_CNT 0x00000FFFU diff --git a/components/soc/esp32c6/include/soc/uart_struct.h b/components/soc/esp32c6/register/soc/uart_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/uart_struct.h rename to components/soc/esp32c6/register/soc/uart_struct.h index 674af37135c4..05d3b740d1f6 100644 --- a/components/soc/esp32c6/include/soc/uart_struct.h +++ b/components/soc/esp32c6/register/soc/uart_struct.h @@ -49,7 +49,7 @@ typedef union { typedef union { struct { /** rx_tout_en : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ uint32_t rx_tout_en:1; /** rx_tout_flow_dis : R/W; bitpos: [1]; default: 0; @@ -120,7 +120,7 @@ typedef union { */ uint32_t rxfifo_tout:1; /** sw_xon : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ uint32_t sw_xon:1; @@ -238,7 +238,7 @@ typedef union { */ uint32_t tx_brk_done:1; /** tx_brk_idle_done : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ uint32_t tx_brk_idle_done:1; @@ -515,7 +515,7 @@ typedef union { */ uint32_t stop_bit_num:2; /** txd_brk : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ uint32_t txd_brk:1; @@ -1170,7 +1170,7 @@ typedef union { typedef union { struct { /** highpulse_min_cnt : RO; bitpos: [11:0]; default: 4095; - * This register stores the value of the maxinum duration time for the high level + * This register stores the value of the maximum duration time for the high level * pulse. It is used in baud rate-detect process. */ uint32_t highpulse_min_cnt:12; diff --git a/components/soc/esp32c6/include/soc/uhci_reg.h b/components/soc/esp32c6/register/soc/uhci_reg.h similarity index 100% rename from components/soc/esp32c6/include/soc/uhci_reg.h rename to components/soc/esp32c6/register/soc/uhci_reg.h diff --git a/components/soc/esp32c6/include/soc/uhci_struct.h b/components/soc/esp32c6/register/soc/uhci_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/uhci_struct.h rename to components/soc/esp32c6/register/soc/uhci_struct.h diff --git a/components/soc/esp32h2/include/soc/usb_serial_jtag_reg.h b/components/soc/esp32c6/register/soc/usb_serial_jtag_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/usb_serial_jtag_reg.h rename to components/soc/esp32c6/register/soc/usb_serial_jtag_reg.h index eb4b8a1e039a..e188eea91118 100644 --- a/components/soc/esp32h2/include/soc/usb_serial_jtag_reg.h +++ b/components/soc/esp32c6/register/soc/usb_serial_jtag_reg.h @@ -1144,7 +1144,7 @@ extern "C" { #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_RESET_RD_V 0x00000001U #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_RESET_RD_S 3 /** USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY : RO; bitpos: [4]; default: 1; - * CDC_ACM OUTOUT async FIFO empty signal in read clock domain. + * CDC_ACM OUTPUT async FIFO empty signal in read clock domain. */ #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY (BIT(4)) #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_M (USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_V << USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_S) diff --git a/components/soc/esp32c6/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32c6/register/soc/usb_serial_jtag_struct.h similarity index 100% rename from components/soc/esp32c6/include/soc/usb_serial_jtag_struct.h rename to components/soc/esp32c6/register/soc/usb_serial_jtag_struct.h diff --git a/components/soc/esp32c6/include/soc/xts_aes_reg.h b/components/soc/esp32c6/register/soc/xts_aes_reg.h similarity index 98% rename from components/soc/esp32c6/include/soc/xts_aes_reg.h rename to components/soc/esp32c6/register/soc/xts_aes_reg.h index 5d7d7e0b8186..6e7cba263a76 100644 --- a/components/soc/esp32c6/include/soc/xts_aes_reg.h +++ b/components/soc/esp32c6/register/soc/xts_aes_reg.h @@ -32,7 +32,7 @@ s. Please do not use this field..*/ #define XTS_AES_DESTINATION_REG(i) (REG_SPI_MEM_BASE(i) + 0x344) /* XTS_AES_DESTINATION : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: This bit stores the destination parameter which will be used in manual encryptio +/*description: This bit stores the destination parameter which will be used in manual encryption n calculation. 0: flash(default), 1: psram(reserved). Only default value can be used..*/ #define XTS_AES_DESTINATION (BIT(0)) @@ -54,7 +54,7 @@ size parameter..*/ /* XTS_AES_TRIGGER : WT ;bitpos:[0] ;default: 1'b0 ; */ /*description: Set this bit to trigger the process of manual encryption calculation. This actio n should only be asserted when manual encryption status is 0. After this action, - manual encryption status becomes 1. After calculation is done, manual encryptio + manual encryption status becomes 1. After calculation is done, manual encryption n status becomes 2..*/ #define XTS_AES_TRIGGER (BIT(0)) #define XTS_AES_TRIGGER_M (BIT(0)) @@ -115,7 +115,7 @@ ing key 1..*/ #define XTS_AES_CRYPT_CALC_D_DPA_EN_V 0x1 #define XTS_AES_CRYPT_CALC_D_DPA_EN_S 3 /* XTS_AES_CRYPT_SECURITY_LEVEL : R/W ;bitpos:[2:0] ;default: 3'd7 ; */ -/*description: Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1- +/*description: Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1- 7: The bigger the number is, the more secure the cryption is. (Note that the per formance of cryption will decrease together with this number increasing).*/ #define XTS_AES_CRYPT_SECURITY_LEVEL 0x00000007 diff --git a/components/soc/esp32c6/rmt_periph.c b/components/soc/esp32c6/rmt_periph.c index 7ca8a5ddcbd6..c08da463f299 100644 --- a/components/soc/esp32c6/rmt_periph.c +++ b/components/soc/esp32c6/rmt_periph.c @@ -60,6 +60,7 @@ static const regdma_entries_config_t rmt_regdma_entries[] = { const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = { [0] = { + .module = SLEEP_RETENTION_MODULE_RMT0, .regdma_entry_array = rmt_regdma_entries, .array_size = ARRAY_SIZE(rmt_regdma_entries) }, diff --git a/components/soc/esp32c6/spi_periph.c b/components/soc/esp32c6/spi_periph.c index ea10937f582a..1a3696a27fd7 100644 --- a/components/soc/esp32c6/spi_periph.c +++ b/components/soc/esp32c6/spi_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,29 +13,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { { // MSPI has dedicated iomux pins - .spiclk_out = -1, - .spiclk_in = -1, - .spid_out = -1, - .spiq_out = -1, - .spiwp_out = -1, - .spihd_out = -1, - .spid_in = -1, - .spiq_in = -1, - .spiwp_in = -1, - .spihd_in = -1, - .spics_out = {-1}, - .spics_in = -1, - .spiclk_iomux_pin = -1, - .spid_iomux_pin = -1, - .spiq_iomux_pin = -1, - .spiwp_iomux_pin = -1, - .spihd_iomux_pin = -1, - .spics0_iomux_pin = -1, - .irq = -1, - .irq_dma = -1, - .module = -1, - .hw = NULL, - .func = -1, }, { .spiclk_out = FSPICLK_OUT_IDX, .spiclk_in = FSPICLK_IN_IDX, @@ -57,8 +34,51 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, .irq = ETS_GSPI2_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_SPI2_MODULE, .hw = &GPSPI2, .func = SPI2_FUNC_NUM, } }; + + +/** + * Backup registers in Light sleep: (total cnt 12) + * + * cmd + * addr + * ctrl + * clock + * user + * user1 + * user2 + * ms_dlen + * misc + * dma_conf + * dma_int_ena + * slave + */ +#define SPI_RETENTION_REGS_CNT 12 +static const uint32_t spi_regs_map[4] = {0x31ff, 0x1000000, 0x0, 0x0}; +#define SPI_REG_RETENTION_ENTRIES(num) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GPSPI_LINK(0), \ + REG_SPI_BASE(num), REG_SPI_BASE(num), \ + SPI_RETENTION_REGS_CNT, 0, 0, \ + spi_regs_map[0], spi_regs_map[1], \ + spi_regs_map[2], spi_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + /* Additional interrupt setting is required by idf SPI drivers after register recovered */ \ + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_GPSPI_LINK(1), \ + SPI_DMA_INT_SET_REG(num), \ + SPI_TRANS_DONE_INT_SET | SPI_DMA_SEG_TRANS_DONE_INT_SET , \ + UINT32_MAX, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t spi2_regs_retention[] = SPI_REG_RETENTION_ENTRIES(2); // '2' for GPSPI2 + +const spi_reg_retention_info_t spi_reg_retention_info[SOC_SPI_PERIPH_NUM - 1] = { // '-1' to except mspi + { + .module_id = SLEEP_RETENTION_MODULE_GPSPI2, + .entry_array = spi2_regs_retention, + .array_size = ARRAY_SIZE(spi2_regs_retention), + }, +}; diff --git a/components/soc/esp32c6/temperature_sensor_periph.c b/components/soc/esp32c6/temperature_sensor_periph.c index f5ad36f5a9f1..b1a189fe9b46 100644 --- a/components/soc/esp32c6/temperature_sensor_periph.c +++ b/components/soc/esp32c6/temperature_sensor_periph.c @@ -1,10 +1,13 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" +#include "soc/apb_saradc_reg.h" const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ @@ -14,3 +17,24 @@ const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_S { 1, 11, -30, 50, 2}, { 2, 10, -40, 20, 3}, }; + +// Temperature sensor sleep retention entries +// Temperature sensor registers require set the reg_update bit to make the configuration take effect + +/* Temperature sensor Registers Context + Include: APB_SARADC_INT_ENA_REG / + APB_SARADC_APB_TSENS_CTRL_REG / APB_SARADC_TSENS_CTRL2_REG / APB_TSENS_WAKE_REG / APB_TSENS_SAMPLE_REG +*/ +#define TEMPERATURE_SENSOR_RETENTION_REGS_CNT 5 +#define TEMPERATURE_SENSOR_RETENTION_MAP_BASE APB_SARADC_INT_ENA_REG +static const uint32_t temperature_sensor_regs_map[4] = {0x6c1, 0, 0, 0}; +static const regdma_entries_config_t temperature_sensor_regs_entries[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TSENS_LINK(0x00), TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_REGS_CNT, 0, 0, temperature_sensor_regs_map[0], temperature_sensor_regs_map[1], temperature_sensor_regs_map[2], temperature_sensor_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const temperature_sensor_reg_ctx_link_t temperature_sensor_regs_retention = { + .link_list = temperature_sensor_regs_entries, + .link_num = ARRAY_SIZE(temperature_sensor_regs_entries), + .module_id = SLEEP_RETENTION_MODULE_TEMP_SENSOR, +}; diff --git a/components/soc/esp32c6/twai_periph.c b/components/soc/esp32c6/twai_periph.c index 712102bf145f..3066be7bf8d3 100644 --- a/components/soc/esp32c6/twai_periph.c +++ b/components/soc/esp32c6/twai_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/twai_periph.h" +#include "soc/twai_reg.h" #include "soc/gpio_sig_map.h" const twai_controller_signal_conn_t twai_controller_periph_signals = { @@ -29,3 +30,49 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = { } } }; + +/** + * TWAI Registers to be saved during sleep retention + * - TWAI_MODE_REG + * - TWAI_INTERRUPT_ENABLE_REG + * - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG + * - TWAI_ERR_WARNING_LIMIT_REG + * - TWAI_RX_ERR_CNT_REG + * - TWAI_TX_ERR_CNT_REG + * - TWAI_DATA_x_REG + * - TWAI_CLOCK_DIVIDER_REG + * - TWAI_SW_STANDBY_CFG_REG + * - TWAI_HW_CFG_REG + * - TWAI_HW_STANDBY_CNT_REG + * - TWAI_IDLE_INTR_CNT_REG + * - TWAI_ECO_CFG_REG + * - TWAI_TIMESTAMP_PRESCALER_REG + * - TWAI_TIMESTAMP_CFG_REG +*/ +#define TWAI_RETENTION_REGS_CNT 28 +#define TWAI_RETENTION_REGS_BASE(i) REG_TWAI_BASE(i) +static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0}; +#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \ + TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \ + TWAI_RETENTION_REGS_CNT, 0, 0, \ + twai_regs_map[0], twai_regs_map[1], \ + twai_regs_map[2], twai_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t twai1_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(1); + +const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = { + [0] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI0, + .entry_array = twai0_regs_retention, + .array_size = ARRAY_SIZE(twai0_regs_retention) + }, + [1] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI1, + .entry_array = twai1_regs_retention, + .array_size = ARRAY_SIZE(twai1_regs_retention) + }, +}; diff --git a/components/soc/esp32c6/uart_periph.c b/components/soc/esp32c6/uart_periph.c index 22c7f99d1197..287e394df3bb 100644 --- a/components/soc/esp32c6/uart_periph.c +++ b/components/soc/esp32c6/uart_periph.c @@ -151,10 +151,12 @@ static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTI const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { [0] = { + .module = SLEEP_RETENTION_MODULE_UART0, .regdma_entry_array = uart0_regdma_entries, .array_size = ARRAY_SIZE(uart0_regdma_entries), }, [1] = { + .module = SLEEP_RETENTION_MODULE_UART1, .regdma_entry_array = uart1_regdma_entries, .array_size = ARRAY_SIZE(uart1_regdma_entries), }, diff --git a/components/soc/esp32c61/etm_periph.c b/components/soc/esp32c61/etm_periph.c new file mode 100644 index 000000000000..7b268c443a55 --- /dev/null +++ b/components/soc/esp32c61/etm_periph.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/etm_periph.h" +#include "soc/soc_etm_reg.h" + +/** + * ETM Registers to be saved during sleep retention + * - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG +*/ +#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1) + +static const regdma_entries_config_t etm_regdma_entries[] = { + // backup stage: save the status of enabled channels + // restore stage: store the enabled channels + [0] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00), + SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, + [1] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01), + SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [2] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02), + SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, +}; + +const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { + [0] = { + .module = SLEEP_RETENTION_MODULE_ETM0, + .regdma_entry_array = etm_regdma_entries, + .array_size = ARRAY_SIZE(etm_regdma_entries) + }, +}; diff --git a/components/soc/esp32c61/i2c_periph.c b/components/soc/esp32c61/i2c_periph.c index cc11ee808f5d..f86531948d26 100644 --- a/components/soc/esp32c61/i2c_periph.c +++ b/components/soc/esp32c61/i2c_periph.c @@ -21,3 +21,32 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = { .irq = ETS_I2C_EXT0_INTR_SOURCE, }, }; + +// I2C sleep retention entries +// I2C registers require set the reg_update bit to make the configuration take effect + +/* I2C Registers Context + Include: I2C_SCL_LOW_PERIOD_REG / + I2C_CTR_REG / I2C_TO_REG / I2C_SLAVE_ADDR_REG / I2C_FIFO_CONF_REG + I2C_INT_ENA_REG / I2C_SDA_HOLD_REG / I2C_SDA_SAMPLE_REG / I2C_SCL_START_HOLD_REG + I2C_SCL_RSTART_SETUP_REG / I2C_SCL_STOP_HOLD_REG / I2C_SCL_STOP_SETUP_REG /I2C_FILTER_CFG_REG / I2C_CLK_CONF_REG / I2C_SCL_ST_TIME_OUT_REG / I2C_SCL_MAIN_ST_TIME_OUT_REG / I2C_SCL_SP_CONF_REG / I2C_SCL_STRETCH_CONF_REG +*/ +#define I2C0_RETENTION_REGS_CNT 18 +#define I2C0_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG +static const uint32_t i2c0_regs_map[4] = {0xc03f345b, 0x3, 0, 0}; +static const regdma_entries_config_t i2c0_regs_retention[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_REGS_CNT, 0, 0, i2c0_regs_map[0], i2c0_regs_map[1], i2c0_regs_map[2], i2c0_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG, I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG, 0x0, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG, I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG, 0x0, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM] = { + {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention), SLEEP_RETENTION_MODULE_I2C0}, +}; diff --git a/components/soc/esp32c61/i2s_periph.c b/components/soc/esp32c61/i2s_periph.c new file mode 100644 index 000000000000..f7f815d157d4 --- /dev/null +++ b/components/soc/esp32c61/i2s_periph.c @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/i2s_periph.h" +#include "soc/gpio_sig_map.h" + +/* + Bunch of constants for every I2S peripheral: GPIO signals, irqs, hw addr of registers etc +*/ +const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { + { + .mck_out_sig = I2S_MCLK_OUT_IDX, + .mck_in_sig = I2S_MCLK_IN_IDX, + + .m_tx_bck_sig = I2SO_BCK_OUT_IDX, + .m_rx_bck_sig = I2SI_BCK_OUT_IDX, + .m_tx_ws_sig = I2SO_WS_OUT_IDX, + .m_rx_ws_sig = I2SI_WS_OUT_IDX, + + .s_tx_bck_sig = I2SO_BCK_IN_IDX, + .s_rx_bck_sig = I2SI_BCK_IN_IDX, + .s_tx_ws_sig = I2SO_WS_IN_IDX, + .s_rx_ws_sig = I2SI_WS_IN_IDX, + + .data_out_sigs[0] = I2SO_SD_OUT_IDX, + .data_out_sigs[1] = I2SO_SD1_OUT_IDX, + .data_in_sig = I2SI_SD_IN_IDX, + + .irq = ETS_I2S0_INTR_SOURCE, + } +}; diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 2572350a6438..184218444db8 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -55,6 +55,10 @@ config SOC_EFUSE_SUPPORTED bool default y +config SOC_I2S_SUPPORTED + bool + default y + config SOC_GPSPI_SUPPORTED bool default y @@ -131,6 +135,10 @@ config SOC_REG_I2C_SUPPORTED bool default y +config SOC_ETM_SUPPORTED + bool + default y + config SOC_PAU_SUPPORTED bool default y @@ -267,6 +275,10 @@ config SOC_GDMA_PAIRS_PER_GROUP_MAX int default 2 +config SOC_GDMA_SUPPORT_ETM + bool + default y + config SOC_GDMA_SUPPORT_SLEEP_RETENTION bool default y @@ -279,6 +291,10 @@ config SOC_ETM_CHANNELS_PER_GROUP int default 50 +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_GPIO_PORT int default 1 @@ -295,6 +311,10 @@ config SOC_GPIO_SUPPORT_PIN_HYS_FILTER bool default y +config SOC_GPIO_SUPPORT_ETM + bool + default y + config SOC_GPIO_SUPPORT_RTC_INDEPENDENT bool default y @@ -423,6 +443,58 @@ config SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH bool default y +config SOC_I2C_SUPPORT_SLEEP_RETENTION + bool + default y + +config SOC_I2S_NUM + int + default 1 + +config SOC_I2S_HW_VERSION_2 + bool + default y + +config SOC_I2S_SUPPORTS_ETM + bool + default y + +config SOC_I2S_SUPPORTS_TX_SYNC_CNT + bool + default y + +config SOC_I2S_SUPPORTS_XTAL + bool + default y + +config SOC_I2S_SUPPORTS_PLL_F160M + bool + default y + +config SOC_I2S_SUPPORTS_PLL_F120M + bool + default y + +config SOC_I2S_SUPPORTS_PCM + bool + default y + +config SOC_I2S_SUPPORTS_PDM + bool + default y + +config SOC_I2S_SUPPORTS_PDM_TX + bool + default y + +config SOC_I2S_PDM_MAX_TX_LINES + int + default 2 + +config SOC_I2S_SUPPORTS_TDM + bool + default y + config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK bool default y @@ -431,6 +503,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 6 @@ -455,6 +531,10 @@ config SOC_LEDC_FADE_PARAMS_BIT_WIDTH int default 10 +config SOC_LEDC_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MMU_PAGE_SIZE_CONFIGURABLE bool default y @@ -555,6 +635,10 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool default y +config SOC_SPI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_SPI_SUPPORT_CLK_XTAL bool default y @@ -651,6 +735,10 @@ config SOC_SYSTIMER_ALARM_MISS_COMPENSATE bool default y +config SOC_SYSTIMER_SUPPORT_ETM + bool + default y + config SOC_LP_TIMER_BIT_WIDTH_LO int default 32 @@ -687,6 +775,10 @@ config SOC_TIMER_SUPPORT_SLEEP_RETENTION bool default y +config SOC_TIMER_SUPPORT_ETM + bool + default y + config SOC_MWDT_SUPPORT_SLEEP_RETENTION bool default y @@ -975,6 +1067,10 @@ config SOC_BLE_SUPPORTED bool default y +config SOC_BLE_MESH_SUPPORTED + bool + default y + config SOC_ESP_NIMBLE_CONTROLLER bool default y diff --git a/components/soc/esp32c61/include/soc/clk_tree_defs.h b/components/soc/esp32c61/include/soc/clk_tree_defs.h index dcc5c77717c3..2795d49981bb 100644 --- a/components/soc/esp32c61/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c61/include/soc/clk_tree_defs.h @@ -120,6 +120,7 @@ typedef enum { SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or OSC_SLOW by configuring soc_rtc_slow_clk_src_t */ // For digital domain: peripherals, WIFI, BLE SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from PLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */ + SOC_MOD_CLK_PLL_F120M, /*!< PLL_F120M_CLK is derived from PLL (clock gating + fixed divider of 4), it has a fixed frequency of 120MHz */ SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from PLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */ SOC_MOD_CLK_SPLL, /*!< SPLL is from the main XTAL oscillator frequency multipliers, it has a "fixed" frequency of 480MHz */ SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ @@ -213,13 +214,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of I2S */ -#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, I2S_CLK_SRC_EXTERNAL} +#define SOC_I2S_CLKS {I2S_CLK_SRC_PLL_120M, SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, I2S_CLK_SRC_EXTERNAL} /** * @brief I2S clock source enum */ typedef enum { I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default source clock */ + I2S_CLK_SRC_PLL_120M = SOC_MOD_CLK_PLL_F120M, /*!< Select PLL_F120M as the source clock */ I2S_CLK_SRC_PLL_160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ I2S_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ I2S_CLK_SRC_EXTERNAL = -1, /*!< Select external clock as source clock */ diff --git a/components/soc/esp32c61/include/soc/dport_access.h b/components/soc/esp32c61/include/soc/dport_access.h index 85bdb9e6b8f4..feacddca4682 100644 --- a/components/soc/esp32c61/include/soc/dport_access.h +++ b/components/soc/esp32c61/include/soc/dport_access.h @@ -9,7 +9,6 @@ #include #include "soc.h" -#include "uart_reg.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32c61/include/soc/interrupts.h b/components/soc/esp32c61/include/soc/interrupts.h index 105f5f78341d..e74342e6e9c4 100644 --- a/components/soc/esp32c61/include/soc/interrupts.h +++ b/components/soc/esp32c61/include/soc/interrupts.h @@ -53,7 +53,7 @@ typedef enum { ETS_HP_APM_M2_INTR_SOURCE, ETS_HP_APM_M3_INTR_SOURCE, ETS_MSPI_INTR_SOURCE, - ETS_I2S1_INTR_SOURCE, + ETS_I2S0_INTR_SOURCE, ETS_UART0_INTR_SOURCE, ETS_UART1_INTR_SOURCE, ETS_UART2_INTR_SOURCE, diff --git a/components/soc/esp32c61/include/soc/regi2c_saradc.h b/components/soc/esp32c61/include/soc/regi2c_saradc.h index c7137f3bb007..0a80bbbc539f 100644 --- a/components/soc/esp32c61/include/soc/regi2c_saradc.h +++ b/components/soc/esp32c61/include/soc/regi2c_saradc.h @@ -18,41 +18,39 @@ #define I2C_SAR_ADC 0X69 #define I2C_SAR_ADC_HOSTID 0 -#define ADC_SAR1_ENCAL_GND_ADDR 0x7 -#define ADC_SAR1_ENCAL_GND_ADDR_MSB 5 -#define ADC_SAR1_ENCAL_GND_ADDR_LSB 5 -#define ADC_SAR2_ENCAL_GND_ADDR 0x7 -#define ADC_SAR2_ENCAL_GND_ADDR_MSB 7 -#define ADC_SAR2_ENCAL_GND_ADDR_LSB 7 + +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR 0x0 +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB 0x7 +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB 0x0 #define ADC_SAR1_INITIAL_CODE_HIGH_ADDR 0x1 #define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3 #define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0 -#define ADC_SAR1_INITIAL_CODE_LOW_ADDR 0x0 -#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB 0x7 -#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB 0x0 +#define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2 +#define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2 +#define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0 -#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR 0x4 -#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3 -#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0 +#define ADC_SAR1_DREF_ADDR 0x2 +#define ADC_SAR1_DREF_ADDR_MSB 0x6 +#define ADC_SAR1_DREF_ADDR_LSB 0x4 #define ADC_SAR2_INITIAL_CODE_LOW_ADDR 0x3 #define ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB 0x7 #define ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB 0x0 -#define ADC_SAR1_DREF_ADDR 0x2 -#define ADC_SAR1_DREF_ADDR_MSB 0x6 -#define ADC_SAR1_DREF_ADDR_LSB 0x4 +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR 0x4 +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3 +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0 #define ADC_SAR2_DREF_ADDR 0x5 #define ADC_SAR2_DREF_ADDR_MSB 0x6 #define ADC_SAR2_DREF_ADDR_LSB 0x4 -#define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2 -#define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2 -#define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0 +#define I2C_SARADC_TSENS_DAC 0x6 +#define I2C_SARADC_TSENS_DAC_MSB 3 +#define I2C_SARADC_TSENS_DAC_LSB 0 #define ADC_SARADC_DTEST_RTC_ADDR 0x7 #define ADC_SARADC_DTEST_RTC_ADDR_MSB 1 @@ -70,10 +68,31 @@ #define ADC_SARADC1_ENCAL_REF_ADDR_MSB 4 #define ADC_SARADC1_ENCAL_REF_ADDR_LSB 4 +#define ADC_SAR1_ENCAL_GND_ADDR 0x7 +#define ADC_SAR1_ENCAL_GND_ADDR_MSB 5 +#define ADC_SAR1_ENCAL_GND_ADDR_LSB 5 + #define ADC_SARADC2_ENCAL_REF_ADDR 0x7 #define ADC_SARADC2_ENCAL_REF_ADDR_MSB 6 #define ADC_SARADC2_ENCAL_REF_ADDR_LSB 6 -#define I2C_SARADC_TSENS_DAC 0x6 -#define I2C_SARADC_TSENS_DAC_MSB 3 -#define I2C_SARADC_TSENS_DAC_LSB 0 +#define ADC_SAR2_ENCAL_GND_ADDR 0x7 +#define ADC_SAR2_ENCAL_GND_ADDR_MSB 7 +#define ADC_SAR2_ENCAL_GND_ADDR_LSB 7 + + +#define POWER_GLITCH_DREF_VDET_PERIF 11 +#define POWER_GLITCH_DREF_VDET_PERIF_MSB 2 +#define POWER_GLITCH_DREF_VDET_PERIF_LSB 0 + +#define POWER_GLITCH_DREF_VDET_VDDPST 11 +#define POWER_GLITCH_DREF_VDET_VDDPST_MSB 6 +#define POWER_GLITCH_DREF_VDET_VDDPST_LSB 4 + +#define POWER_GLITCH_DREF_VDET_PLLBB 12 +#define POWER_GLITCH_DREF_VDET_PLLBB_MSB 2 +#define POWER_GLITCH_DREF_VDET_PLLBB_LSB 0 + +#define POWER_GLITCH_DREF_VDET_PLL 12 +#define POWER_GLITCH_DREF_VDET_PLL_MSB 6 +#define POWER_GLITCH_DREF_VDET_PLL_LSB 4 diff --git a/components/soc/esp32c61/include/soc/retention_periph_defs.h b/components/soc/esp32c61/include/soc/retention_periph_defs.h index 5bc404860b7a..4c6a134f222a 100644 --- a/components/soc/esp32c61/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c61/include/soc/retention_periph_defs.h @@ -15,6 +15,7 @@ extern "C" { typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_MIN = 0, + SLEEP_RETENTION_MODULE_NULL = SLEEP_RETENTION_MODULE_MIN, /* This module is for all peripherals that can't survive from PD_TOP to call init only. Shouldn't have any dependency. */ /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2, @@ -33,6 +34,9 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_I2C0 = 12, SLEEP_RETENTION_MODULE_UART0 = 14, SLEEP_RETENTION_MODULE_UART1 = 15, + SLEEP_RETENTION_MODULE_ETM0 = 16, + SLEEP_RETENTION_MODULE_GPSPI2 = 17, + SLEEP_RETENTION_MODULE_LEDC = 18, /* Modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -44,6 +48,8 @@ typedef enum periph_retention_module { } periph_retention_module_t; typedef enum periph_retention_module_bitmap { + SLEEP_RETENTION_MODULE_BM_NULL = BIT(SLEEP_RETENTION_MODULE_NULL), + /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM), @@ -62,6 +68,9 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0), SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), + SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), + SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2), + SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC), /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC), SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB), @@ -81,6 +90,10 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_I2C0 \ | SLEEP_RETENTION_MODULE_BM_UART0 \ | SLEEP_RETENTION_MODULE_BM_UART1 \ + | SLEEP_RETENTION_MODULE_BM_ETM0 \ + | SLEEP_RETENTION_MODULE_BM_GPSPI2 \ + | SLEEP_RETENTION_MODULE_BM_LEDC \ + | SLEEP_RETENTION_MODULE_BM_NULL \ ) #ifdef __cplusplus diff --git a/components/soc/esp32c61/include/soc/soc.h b/components/soc/esp32c61/include/soc/soc.h index cd1b6e7537f5..ca6ee32e0319 100644 --- a/components/soc/esp32c61/include/soc/soc.h +++ b/components/soc/esp32c61/include/soc/soc.h @@ -12,7 +12,7 @@ #endif #include "esp_bit_defs.h" -#include "reg_base.h" +#include "soc/reg_base.h" #define PRO_CPU_NUM (0) diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index bf1fab84d338..4b4c36f3e7be 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -33,7 +33,7 @@ #define SOC_SUPPORTS_SECURE_DL_MODE 1 #define SOC_EFUSE_KEY_PURPOSE_FIELD 1 #define SOC_EFUSE_SUPPORTED 1 -// \#define SOC_I2S_SUPPORTED 1 //TODO: [ESP32C61] IDF-9312, IDF-9313 +#define SOC_I2S_SUPPORTED 1 #define SOC_GPSPI_SUPPORTED 1 #define SOC_I2C_SUPPORTED 1 #define SOC_LEDC_SUPPORTED 1 @@ -56,7 +56,7 @@ // \#define SOC_RNG_SUPPORTED 1 //TODO: [ESP32C61] IDF-9236 #define SOC_MODEM_CLOCK_SUPPORTED 1 #define SOC_REG_I2C_SUPPORTED 1 -// \#define SOC_ETM_SUPPORTED 0 +#define SOC_ETM_SUPPORTED 1 // \#define SOC_SDIO_SLAVE_SUPPORTED 0 #define SOC_PAU_SUPPORTED 1 #define SOC_LIGHT_SLEEP_SUPPORTED 1 @@ -148,12 +148,13 @@ #define SOC_AHB_GDMA_VERSION 2U #define SOC_GDMA_NUM_GROUPS_MAX 1U #define SOC_GDMA_PAIRS_PER_GROUP_MAX 2 -// \#define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule TODO: IDF-9964 +#define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- ETM CAPS --------------------------------------*/ #define SOC_ETM_GROUPS 1U // Number of ETM groups #define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C61 has 1 GPIO peripheral @@ -163,7 +164,7 @@ #define SOC_GPIO_SUPPORT_PIN_HYS_FILTER 1 // GPIO peripheral has the ETM extension -// \#define SOC_GPIO_SUPPORT_ETM 1 //TODO: [ESP32C61] IDF-9318 +#define SOC_GPIO_SUPPORT_ETM 1 // Target has the full LP IO subsystem // On ESP32-C61, Digital IOs have their own registers to control pullup/down capability, independent of LP registers. @@ -228,27 +229,33 @@ #define SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE (1) #define SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS (1) #define SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH (1) +#define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) // /*-------------------------- I2S CAPS ----------------------------------------*/ -// #define SOC_I2S_NUM (1U) -// #define SOC_I2S_HW_VERSION_2 (1) -// #define SOC_I2S_SUPPORTS_XTAL (1) -// #define SOC_I2S_SUPPORTS_PLL_F160M (1) -// #define SOC_I2S_SUPPORTS_PCM (1) -// #define SOC_I2S_SUPPORTS_PDM (1) -// #define SOC_I2S_SUPPORTS_PDM_TX (1) -// #define SOC_I2S_PDM_MAX_TX_LINES (2) -// #define SOC_I2S_SUPPORTS_TDM (1) +#define SOC_I2S_NUM (1U) +#define SOC_I2S_HW_VERSION_2 (1) +#define SOC_I2S_SUPPORTS_ETM (1) +#define SOC_I2S_SUPPORTS_TX_SYNC_CNT (1) +#define SOC_I2S_SUPPORTS_XTAL (1) +#define SOC_I2S_SUPPORTS_PLL_F160M (1) +#define SOC_I2S_SUPPORTS_PLL_F120M (1) +#define SOC_I2S_SUPPORTS_PCM (1) +#define SOC_I2S_SUPPORTS_PDM (1) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_PDM_MAX_TX_LINES (2) +#define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (6) #define SOC_LEDC_TIMER_BIT_WIDTH (20) #define SOC_LEDC_SUPPORT_FADE_STOP (1) #define SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED (1) #define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16) #define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10) +#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- MMU CAPS ----------------------------------------*/ #define SOC_MMU_PAGE_SIZE_CONFIGURABLE (1) @@ -303,6 +310,7 @@ #define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 +#define SOC_SPI_SUPPORT_SLEEP_RETENTION 1 #define SOC_SPI_SUPPORT_CLK_XTAL 1 #define SOC_SPI_SUPPORT_CLK_PLL 1 #define SOC_SPI_SUPPORT_CLK_RC_FAST 1 @@ -338,7 +346,7 @@ #define SOC_SYSTIMER_SUPPORT_RC_FAST 1 // Systimer can use RC_FAST clock source #define SOC_SYSTIMER_INT_LEVEL 1 // Systimer peripheral uses level interrupt #define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current) -// #define SOC_SYSTIMER_SUPPORT_ETM 1 // Systimer comparator can generate ETM event +#define SOC_SYSTIMER_SUPPORT_ETM 1 // Systimer comparator can generate ETM event /*-------------------------- LP_TIMER CAPS ----------------------------------*/ #define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part @@ -352,7 +360,7 @@ #define SOC_TIMER_GROUP_SUPPORT_XTAL (1) #define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1) #define SOC_TIMER_SUPPORT_SLEEP_RETENTION (1) -// #define SOC_TIMER_SUPPORT_ETM (1) +#define SOC_TIMER_SUPPORT_ETM (1) /*--------------------------- WATCHDOG CAPS ---------------------------------------*/ // #define SOC_MWDT_SUPPORT_XTAL (1) @@ -473,7 +481,7 @@ /*---------------------------------- Bluetooth CAPS ----------------------------------*/ #define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */ -// #define SOC_BLE_MESH_SUPPORTED (1) /*!< Support BLE MESH */ +#define SOC_BLE_MESH_SUPPORTED (1) /*!< Support BLE MESH */ #define SOC_ESP_NIMBLE_CONTROLLER (1) /*!< Support BLE EMBEDDED controller V1 */ #define SOC_BLE_50_SUPPORTED (1) /*!< Support Bluetooth 5.0 */ #define SOC_BLE_DEVICE_PRIVACY_SUPPORTED (1) /*!< Support BLE device privacy mode */ diff --git a/components/soc/esp32c61/include/soc/system_reg.h b/components/soc/esp32c61/include/soc/system_reg.h index 4577fecbeb79..690bb496eb83 100644 --- a/components/soc/esp32c61/include/soc/system_reg.h +++ b/components/soc/esp32c61/include/soc/system_reg.h @@ -6,6 +6,6 @@ #include "soc/hp_system_reg.h" -#include "intpri_reg.h" +#include "soc/intpri_reg.h" #define SYSTEM_CPU_INTR_FROM_CPU_0_REG INTPRI_CPU_INTR_FROM_CPU_0_REG #define SYSTEM_CPU_INTR_FROM_CPU_0 INTPRI_CPU_INTR_FROM_CPU_0 diff --git a/components/soc/esp32c61/ld/esp32c61.peripherals.ld b/components/soc/esp32c61/ld/esp32c61.peripherals.ld index 6d5ca8d8c3b8..8490671b17bd 100644 --- a/components/soc/esp32c61/ld/esp32c61.peripherals.ld +++ b/components/soc/esp32c61/ld/esp32c61.peripherals.ld @@ -15,7 +15,7 @@ PROVIDE ( LEDC_GAMMA_RAM = 0x60007400 ); PROVIDE ( TIMERG0 = 0x60008000 ); PROVIDE ( TIMERG1 = 0x60009000 ); PROVIDE ( SYSTIMER = 0x6000A000 ); -PROVIDE ( I2S = 0x6000C000 ); +PROVIDE ( I2S0 = 0x6000C000 ); PROVIDE ( ADC = 0x6000E000 ); PROVIDE ( USB_SERIAL_JTAG = 0x6000F000 ); PROVIDE ( INTMTX = 0x60010000 ); @@ -29,6 +29,8 @@ PROVIDE ( ECC = 0x6008B000 ); PROVIDE ( ECDSA = 0x6008E000 ); PROVIDE ( IO_MUX = 0x60090000 ); PROVIDE ( GPIO = 0x60091000 ); +PROVIDE ( GPIO_EXT = 0x60091e00 ); +PROVIDE ( GPIO_ETM = 0x60091f18 ); PROVIDE ( TCM_MEM_MONITOR = 0x60092000 ); PROVIDE ( PAU = 0x60093000 ); PROVIDE ( HP_SYSTEM = 0x60095000 ); diff --git a/components/soc/esp32c61/ledc_periph.c b/components/soc/esp32c61/ledc_periph.c index 867e469ac4eb..3fed785c2713 100644 --- a/components/soc/esp32c61/ledc_periph.c +++ b/components/soc/esp32c61/ledc_periph.c @@ -15,3 +15,152 @@ const ledc_signal_conn_t ledc_periph_signal[1] = { .sig_out0_idx = LEDC_LS_SIG_OUT0_IDX, } }; + +/** + * LEDC registers to be saved for sleep retention + * + * channel: + * LEDC_CHx_CONF0_REG, LEDC_CHx_HPOINT_REG, LEDC_CHx_DUTY_R_REG -> LEDC_CHx_DUTY_REG, + * LEDC_CHx_GAMMA_CONF_REG, LEDC_CHx_GAMMA_RANGEi_REG + * + * timer: + * LEDC_TIMERn_CONF_REG, LEDC_TIMERn_CMP_REG, + * + * common: + * LEDC_INT_ENA_REG, + * LEDC_EVT_TASK_EN0_REG, LEDC_EVT_TASK_EN1_REG, LEDC_EVT_TASK_EN2_REG, + * LEDC_CONF_REG, + * + * Note 1: Gamma parameter registers are backuped and restored. But we won't start a fade automatically after wake-up. + * Instead, we will only start a PWM with a fixed duty cycle, the same value as before entering the sleep. + * + * Note 2: For timer/channel registers to get synced, update bits need to be set + * + * Note 3: Gamma RAM registers R/W relies both APB and function clock, therefore, retention requires the existence of function clock + */ +#define LEDC_COMMON_RETENTION_REGS_CNT 5 +#define LEDC_COMMON_RETENTION_REGS_BASE (DR_REG_LEDC_BASE + 0xc8) +static const uint32_t ledc_common_regs_map[4] = {0x1c00001, 0x400, 0x0, 0x0}; +static const regdma_entries_config_t ledc_common_regdma_entries[] = { + // If a fade is in process, the DUTY_CHNG_END_CHx intr bit is enabled, however, we don't want it to be restored after wake-up (no fade after wake-up). + // Therefore, we can set it to 0 before backup the LEDC_INT_ENA_REG. + [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x00), + LEDC_INT_ENA_REG, 0, + (LEDC_DUTY_CHNG_END_CH0_INT_ENA_M | LEDC_DUTY_CHNG_END_CH1_INT_ENA_M | LEDC_DUTY_CHNG_END_CH2_INT_ENA_M | LEDC_DUTY_CHNG_END_CH3_INT_ENA_M | LEDC_DUTY_CHNG_END_CH4_INT_ENA_M | LEDC_DUTY_CHNG_END_CH5_INT_ENA_M), 0, 1), + .owner = LEDC_RETENTION_ENTRY }, + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x01), + LEDC_COMMON_RETENTION_REGS_BASE, LEDC_COMMON_RETENTION_REGS_BASE, + LEDC_COMMON_RETENTION_REGS_CNT, 0, 0, + ledc_common_regs_map[0], ledc_common_regs_map[1], + ledc_common_regs_map[2], ledc_common_regs_map[3]), + .owner = LEDC_RETENTION_ENTRY }, +}; + +#define LEDC_TIMER_RETENTION_ENTRIES(timer) { \ + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_CONF_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_TIMER##timer##_CMP_REG, LEDC_TIMER##timer##_CMP_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_PARA_UP, \ + LEDC_TIMER##timer##_PARA_UP_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +#define LEDC_CHANNEL_RETENTION_REGS_CNT 2 +static const uint32_t ledc_channel_regs_map[4] = {0x3, 0x0, 0x0, 0x0}; +static const uint32_t ledc_channel_gamma_regs_map[4] = {0xffff, 0x0, 0x0, 0x0}; +#define LEDC_CHANNEL_RETENTION_ENTRIES(chan) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_CH##chan##_CONF0_REG, LEDC_CH##chan##_CONF0_REG, \ + LEDC_CHANNEL_RETENTION_REGS_CNT, 0, 0, \ + ledc_channel_regs_map[0], ledc_channel_regs_map[1], \ + ledc_channel_regs_map[2], ledc_channel_regs_map[3]), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_CH##chan##_DUTY_R_REG, LEDC_CH##chan##_DUTY_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_CH##chan##_CONF1_REG, LEDC_DUTY_START_CH##chan, \ + LEDC_DUTY_START_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x03), \ + LEDC_CH##chan##_CONF0_REG, LEDC_PARA_UP_CH##chan, \ + LEDC_PARA_UP_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x04), \ + LEDC_CH##chan##_GAMMA_CONF_REG, LEDC_CH##chan##_GAMMA_CONF_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [5] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x05), \ + LEDC_CH##chan##_GAMMA_RANGE0_REG, LEDC_CH##chan##_GAMMA_RANGE0_REG, \ + SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX, 0, 0, \ + ledc_channel_gamma_regs_map[0], ledc_channel_gamma_regs_map[1], \ + ledc_channel_gamma_regs_map[2], ledc_channel_gamma_regs_map[3]), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +static const regdma_entries_config_t ledc_timer0_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_timer1_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_timer2_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_timer3_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(3); + +static const regdma_entries_config_t ledc_channel0_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_channel1_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_channel2_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_channel3_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(3); +static const regdma_entries_config_t ledc_channel4_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(4); +static const regdma_entries_config_t ledc_channel5_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(5); + +const ledc_reg_retention_info_t ledc_reg_retention_info = { + .common = { + .regdma_entry_array = ledc_common_regdma_entries, + .array_size = ARRAY_SIZE(ledc_common_regdma_entries), + }, + .timer[0] = { + .regdma_entry_array = ledc_timer0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer0_regdma_entries), + }, + .timer[1] = { + .regdma_entry_array = ledc_timer1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer1_regdma_entries), + }, + .timer[2] = { + .regdma_entry_array = ledc_timer2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer2_regdma_entries), + }, + .timer[3] = { + .regdma_entry_array = ledc_timer3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer3_regdma_entries), + }, + .channel[0] = { + .regdma_entry_array = ledc_channel0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel0_regdma_entries), + }, + .channel[1] = { + .regdma_entry_array = ledc_channel1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel1_regdma_entries), + }, + .channel[2] = { + .regdma_entry_array = ledc_channel2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel2_regdma_entries), + }, + .channel[3] = { + .regdma_entry_array = ledc_channel3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel3_regdma_entries), + }, + .channel[4] = { + .regdma_entry_array = ledc_channel4_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel4_regdma_entries), + }, + .channel[5] = { + .regdma_entry_array = ledc_channel5_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel5_regdma_entries), + }, + .module_id = SLEEP_RETENTION_MODULE_LEDC, +}; diff --git a/components/soc/esp32c61/register/soc/.gitkeep b/components/soc/esp32c61/register/soc/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/soc/esp32c61/include/soc/ahb_dma_reg.h b/components/soc/esp32c61/register/soc/ahb_dma_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/ahb_dma_reg.h rename to components/soc/esp32c61/register/soc/ahb_dma_reg.h diff --git a/components/soc/esp32c61/include/soc/ahb_dma_struct.h b/components/soc/esp32c61/register/soc/ahb_dma_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/ahb_dma_struct.h rename to components/soc/esp32c61/register/soc/ahb_dma_struct.h diff --git a/components/soc/esp32c61/include/soc/apb_saradc_reg.h b/components/soc/esp32c61/register/soc/apb_saradc_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/apb_saradc_reg.h rename to components/soc/esp32c61/register/soc/apb_saradc_reg.h diff --git a/components/soc/esp32c61/include/soc/apb_saradc_struct.h b/components/soc/esp32c61/register/soc/apb_saradc_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/apb_saradc_struct.h rename to components/soc/esp32c61/register/soc/apb_saradc_struct.h diff --git a/components/soc/esp32c61/include/soc/assist_debug_reg.h b/components/soc/esp32c61/register/soc/assist_debug_reg.h similarity index 99% rename from components/soc/esp32c61/include/soc/assist_debug_reg.h rename to components/soc/esp32c61/register/soc/assist_debug_reg.h index 4b7e6b6ff558..042490974ba6 100644 --- a/components/soc/esp32c61/include/soc/assist_debug_reg.h +++ b/components/soc/esp32c61/register/soc/assist_debug_reg.h @@ -115,7 +115,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_ENA_V 0x00000001U #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_ENA_S 10 /** ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor enbale + * DBUS busy monitor enable */ #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA (BIT(11)) #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_M (ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_V << ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_S) @@ -295,7 +295,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_INTR_ENA_V 0x00000001U #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_INTR_ENA_S 10 /** ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_INTR_ENA : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor interrupt enbale + * DBUS busy monitor interrupt enable */ #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_INTR_ENA (BIT(11)) #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_INTR_ENA_M (ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_INTR_ENA_V << ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_INTR_ENA_S) diff --git a/components/soc/esp32c61/include/soc/assist_debug_struct.h b/components/soc/esp32c61/register/soc/assist_debug_struct.h similarity index 99% rename from components/soc/esp32c61/include/soc/assist_debug_struct.h rename to components/soc/esp32c61/register/soc/assist_debug_struct.h index 243b6959aa01..ca55d0cb8f60 100644 --- a/components/soc/esp32c61/include/soc/assist_debug_struct.h +++ b/components/soc/esp32c61/register/soc/assist_debug_struct.h @@ -83,7 +83,7 @@ typedef union { */ uint32_t core_0_iram0_exception_monitor_ena:1; /** core_0_dram0_exception_monitor_ena : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor enbale + * DBUS busy monitor enable */ uint32_t core_0_dram0_exception_monitor_ena:1; uint32_t reserved_12:20; @@ -372,7 +372,7 @@ typedef union { */ uint32_t core_0_iram0_exception_monitor_intr_ena:1; /** core_0_dram0_exception_monitor_intr_ena : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor interrupt enbale + * DBUS busy monitor interrupt enable */ uint32_t core_0_dram0_exception_monitor_intr_ena:1; uint32_t reserved_12:20; @@ -441,7 +441,7 @@ typedef union { } assist_debug_core_0_intr_clr_reg_t; -/** Group: pc reording configuration register */ +/** Group: pc recording configuration register */ /** Type of core_0_rcd_en register * HP CPU PC logging enable register */ @@ -465,7 +465,7 @@ typedef union { } assist_debug_core_0_rcd_en_reg_t; -/** Group: pc reording status register */ +/** Group: pc recording status register */ /** Type of core_0_rcd_pdebugpc register * PC logging register */ @@ -493,7 +493,7 @@ typedef union { } assist_debug_core_0_rcd_pdebugsp_reg_t; -/** Group: exception monitor regsiter */ +/** Group: exception monitor register */ /** Type of core_0_iram0_exception_monitor_0 register * exception monitor status register0 */ diff --git a/components/soc/esp32c61/include/soc/cache_reg.h b/components/soc/esp32c61/register/soc/cache_reg.h similarity index 99% rename from components/soc/esp32c61/include/soc/cache_reg.h rename to components/soc/esp32c61/register/soc/cache_reg.h index 98390f8e1ae0..d0e294a28cb4 100644 --- a/components/soc/esp32c61/include/soc/cache_reg.h +++ b/components/soc/esp32c61/register/soc/cache_reg.h @@ -4077,7 +4077,7 @@ extern "C" { #define CACHE_L1_UNALLOCATE_BUFFER_CLEAR_REG (DR_REG_CACHE_BASE + 0x254) /** CACHE_L1_ICACHE0_UNALLOC_CLR : HRO; bitpos: [0]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache0 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_ICACHE0_UNALLOC_CLR (BIT(0)) #define CACHE_L1_ICACHE0_UNALLOC_CLR_M (CACHE_L1_ICACHE0_UNALLOC_CLR_V << CACHE_L1_ICACHE0_UNALLOC_CLR_S) @@ -4085,7 +4085,7 @@ extern "C" { #define CACHE_L1_ICACHE0_UNALLOC_CLR_S 0 /** CACHE_L1_ICACHE1_UNALLOC_CLR : HRO; bitpos: [1]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache1 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_ICACHE1_UNALLOC_CLR (BIT(1)) #define CACHE_L1_ICACHE1_UNALLOC_CLR_M (CACHE_L1_ICACHE1_UNALLOC_CLR_V << CACHE_L1_ICACHE1_UNALLOC_CLR_S) @@ -4107,7 +4107,7 @@ extern "C" { #define CACHE_L1_ICACHE3_UNALLOC_CLR_S 3 /** CACHE_L1_CACHE_UNALLOC_CLR : R/W; bitpos: [4]; default: 0; * The bit is used to clear the unallocate request buffer of l1 cache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_CACHE_UNALLOC_CLR (BIT(4)) #define CACHE_L1_CACHE_UNALLOC_CLR_M (CACHE_L1_CACHE_UNALLOC_CLR_V << CACHE_L1_CACHE_UNALLOC_CLR_S) @@ -5937,7 +5937,7 @@ extern "C" { #define CACHE_L2_UNALLOCATE_BUFFER_CLEAR_REG (DR_REG_CACHE_BASE + 0x3b0) /** CACHE_L2_CACHE_UNALLOC_CLR : HRO; bitpos: [5]; default: 0; * The bit is used to clear the unallocate request buffer of l2 icache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L2_CACHE_UNALLOC_CLR (BIT(5)) #define CACHE_L2_CACHE_UNALLOC_CLR_M (CACHE_L2_CACHE_UNALLOC_CLR_V << CACHE_L2_CACHE_UNALLOC_CLR_S) diff --git a/components/soc/esp32c61/include/soc/cache_struct.h b/components/soc/esp32c61/register/soc/cache_struct.h similarity index 99% rename from components/soc/esp32c61/include/soc/cache_struct.h rename to components/soc/esp32c61/register/soc/cache_struct.h index f98620a26b33..408c01c2c784 100644 --- a/components/soc/esp32c61/include/soc/cache_struct.h +++ b/components/soc/esp32c61/register/soc/cache_struct.h @@ -5100,12 +5100,12 @@ typedef union { struct { /** l1_icache0_unalloc_clr : HRO; bitpos: [0]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache0 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_icache0_unalloc_clr:1; /** l1_icache1_unalloc_clr : HRO; bitpos: [1]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache1 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_icache1_unalloc_clr:1; /** l1_icache2_unalloc_clr : HRO; bitpos: [2]; default: 0; @@ -5118,7 +5118,7 @@ typedef union { uint32_t l1_icache3_unalloc_clr:1; /** l1_cache_unalloc_clr : R/W; bitpos: [4]; default: 0; * The bit is used to clear the unallocate request buffer of l1 cache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_cache_unalloc_clr:1; uint32_t reserved_5:27; @@ -5134,7 +5134,7 @@ typedef union { uint32_t reserved_0:5; /** l2_cache_unalloc_clr : HRO; bitpos: [5]; default: 0; * The bit is used to clear the unallocate request buffer of l2 icache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l2_cache_unalloc_clr:1; uint32_t reserved_6:26; diff --git a/components/soc/esp32c61/include/soc/clic_reg.h b/components/soc/esp32c61/register/soc/clic_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/clic_reg.h rename to components/soc/esp32c61/register/soc/clic_reg.h diff --git a/components/soc/esp32c61/include/soc/clint_reg.h b/components/soc/esp32c61/register/soc/clint_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/clint_reg.h rename to components/soc/esp32c61/register/soc/clint_reg.h diff --git a/components/soc/esp32c61/include/soc/ecc_mult_reg.h b/components/soc/esp32c61/register/soc/ecc_mult_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/ecc_mult_reg.h rename to components/soc/esp32c61/register/soc/ecc_mult_reg.h diff --git a/components/soc/esp32c61/include/soc/ecc_mult_struct.h b/components/soc/esp32c61/register/soc/ecc_mult_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/ecc_mult_struct.h rename to components/soc/esp32c61/register/soc/ecc_mult_struct.h diff --git a/components/soc/esp32c61/include/soc/ecdsa_reg.h b/components/soc/esp32c61/register/soc/ecdsa_reg.h similarity index 98% rename from components/soc/esp32c61/include/soc/ecdsa_reg.h rename to components/soc/esp32c61/register/soc/ecdsa_reg.h index aca4b64b199f..4893390ced6e 100644 --- a/components/soc/esp32c61/include/soc/ecdsa_reg.h +++ b/components/soc/esp32c61/register/soc/ecdsa_reg.h @@ -211,7 +211,7 @@ extern "C" { */ #define ECDSA_START_REG (DR_REG_ECDSA_BASE + 0x1c) /** ECDSA_START : WT; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECDSA Accelerator. This bit will be self-cleared + * Write 1 to start calculation of ECDSA Accelerator. This bit will be self-cleared * after configuration. */ #define ECDSA_START (BIT(0)) @@ -299,7 +299,7 @@ extern "C" { */ #define ECDSA_SHA_START_REG (DR_REG_ECDSA_BASE + 0x210) /** ECDSA_SHA_START : WT; bitpos: [0]; default: 0; - * Write 1 to start the first caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the first calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ #define ECDSA_SHA_START (BIT(0)) @@ -312,7 +312,7 @@ extern "C" { */ #define ECDSA_SHA_CONTINUE_REG (DR_REG_ECDSA_BASE + 0x214) /** ECDSA_SHA_CONTINUE : WT; bitpos: [0]; default: 0; - * Write 1 to start the latter caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the latter calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ #define ECDSA_SHA_CONTINUE (BIT(0)) diff --git a/components/soc/esp32c61/include/soc/ecdsa_struct.h b/components/soc/esp32c61/register/soc/ecdsa_struct.h similarity index 97% rename from components/soc/esp32c61/include/soc/ecdsa_struct.h rename to components/soc/esp32c61/register/soc/ecdsa_struct.h index bed383c9da04..858a4ffc5f84 100644 --- a/components/soc/esp32c61/include/soc/ecdsa_struct.h +++ b/components/soc/esp32c61/register/soc/ecdsa_struct.h @@ -57,7 +57,7 @@ typedef union { typedef union { struct { /** start : WT; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECDSA Accelerator. This bit will be self-cleared + * Write 1 to start calculation of ECDSA Accelerator. This bit will be self-cleared * after configuration. */ uint32_t start:1; @@ -260,7 +260,7 @@ typedef union { typedef union { struct { /** sha_start : WT; bitpos: [0]; default: 0; - * Write 1 to start the first caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the first calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ uint32_t sha_start:1; @@ -275,7 +275,7 @@ typedef union { typedef union { struct { /** sha_continue : WT; bitpos: [0]; default: 0; - * Write 1 to start the latter caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the latter calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ uint32_t sha_continue:1; diff --git a/components/soc/esp32c61/include/soc/efuse_reg.h b/components/soc/esp32c61/register/soc/efuse_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/efuse_reg.h rename to components/soc/esp32c61/register/soc/efuse_reg.h diff --git a/components/soc/esp32c61/include/soc/efuse_struct.h b/components/soc/esp32c61/register/soc/efuse_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/efuse_struct.h rename to components/soc/esp32c61/register/soc/efuse_struct.h diff --git a/components/soc/esp32c61/include/soc/gpio_ext_reg.h b/components/soc/esp32c61/register/soc/gpio_ext_reg.h similarity index 99% rename from components/soc/esp32c61/include/soc/gpio_ext_reg.h rename to components/soc/esp32c61/register/soc/gpio_ext_reg.h index 26effdee28ff..2385576c3336 100644 --- a/components/soc/esp32c61/include/soc/gpio_ext_reg.h +++ b/components/soc/esp32c61/register/soc/gpio_ext_reg.h @@ -37,7 +37,7 @@ extern "C" { #define GPIO_EXT_XPD_COMP_0_V 0x00000001U #define GPIO_EXT_XPD_COMP_0_S 0 /** GPIO_EXT_MODE_COMP_0 : R/W; bitpos: [1]; default: 0; - * Configures the reference voltage for analog PAD voltage comparater.. \\ + * Configures the reference voltage for analog PAD voltage comparator.. \\ * 0: Reference voltage is the internal reference voltage, meanwhile GPIO8 PAD can be * used as a regular GPIO\\ * 1: Reference voltage is the voltage on the GPIO8 PAD\\ diff --git a/components/soc/esp32c61/include/soc/gpio_ext_struct.h b/components/soc/esp32c61/register/soc/gpio_ext_struct.h similarity index 97% rename from components/soc/esp32c61/include/soc/gpio_ext_struct.h rename to components/soc/esp32c61/register/soc/gpio_ext_struct.h index f02a5fec8a1d..1f7f58950e20 100644 --- a/components/soc/esp32c61/include/soc/gpio_ext_struct.h +++ b/components/soc/esp32c61/register/soc/gpio_ext_struct.h @@ -39,7 +39,7 @@ typedef union { */ uint32_t xpd_comp_0:1; /** mode_comp_0 : R/W; bitpos: [1]; default: 0; - * Configures the reference voltage for analog PAD voltage comparater.. \\ + * Configures the reference voltage for analog PAD voltage comparator.. \\ * 0: Reference voltage is the internal reference voltage, meanwhile GPIO8 PAD can be * used as a regular GPIO\\ * 1: Reference voltage is the voltage on the GPIO8 PAD\\ @@ -128,6 +128,15 @@ typedef union { uint32_t val; } gpio_ext_etm_event_chn_cfg_reg_t; +/** Type of etm_task_pn_cfg register + * GPIO selection register for ETM. + * This register is an abstraction of the following registers: + * gpio_ext_etm_task_p0_cfg_reg_t ~ gpio_ext_etm_task_p4_cfg_reg_t + */ +typedef union { + uint32_t val; +} gpio_ext_etm_task_pn_cfg_reg_t; + /** Type of etm_task_p0_cfg register * GPIO selection register 0 for ETM */ @@ -659,6 +668,11 @@ typedef union { uint32_t val; } gpio_ext_version_reg_t; +typedef struct gpio_etm_dev_t { + volatile gpio_ext_etm_event_chn_cfg_reg_t etm_event_chn_cfg[8]; + uint32_t reserved_138[8]; + volatile gpio_ext_etm_task_pn_cfg_reg_t etm_task_pn_cfg[5]; +} gpio_etm_dev_t; typedef struct { volatile gpio_ext_clock_gate_reg_t clock_gate; @@ -666,13 +680,7 @@ typedef struct { volatile gpio_ext_pad_comp_config_0_reg_t pad_comp_config_0; volatile gpio_ext_pad_comp_filter_0_reg_t pad_comp_filter_0; uint32_t reserved_060[46]; - volatile gpio_ext_etm_event_chn_cfg_reg_t etm_event_chn_cfg[8]; - uint32_t reserved_138[8]; - volatile gpio_ext_etm_task_p0_cfg_reg_t etm_task_p0_cfg; - volatile gpio_ext_etm_task_p1_cfg_reg_t etm_task_p1_cfg; - volatile gpio_ext_etm_task_p2_cfg_reg_t etm_task_p2_cfg; - volatile gpio_ext_etm_task_p3_cfg_reg_t etm_task_p3_cfg; - volatile gpio_ext_etm_task_p4_cfg_reg_t etm_task_p4_cfg; + volatile gpio_etm_dev_t etm; uint32_t reserved_16c[25]; volatile gpio_ext_int_raw_reg_t int_raw; volatile gpio_ext_int_st_reg_t int_st; @@ -683,6 +691,8 @@ typedef struct { volatile gpio_ext_version_reg_t version; } gpio_ext_dev_t; +extern gpio_etm_dev_t GPIO_ETM; +extern gpio_ext_dev_t GPIO_EXT; #ifndef __cplusplus _Static_assert(sizeof(gpio_ext_dev_t) == 0x200, "Invalid size of gpio_ext_dev_t structure"); diff --git a/components/soc/esp32c61/include/soc/gpio_reg.h b/components/soc/esp32c61/register/soc/gpio_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/gpio_reg.h rename to components/soc/esp32c61/register/soc/gpio_reg.h diff --git a/components/soc/esp32c61/include/soc/gpio_struct.h b/components/soc/esp32c61/register/soc/gpio_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/gpio_struct.h rename to components/soc/esp32c61/register/soc/gpio_struct.h diff --git a/components/soc/esp32c61/include/soc/hp_apm_reg.h b/components/soc/esp32c61/register/soc/hp_apm_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/hp_apm_reg.h rename to components/soc/esp32c61/register/soc/hp_apm_reg.h diff --git a/components/soc/esp32c61/include/soc/hp_apm_struct.h b/components/soc/esp32c61/register/soc/hp_apm_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/hp_apm_struct.h rename to components/soc/esp32c61/register/soc/hp_apm_struct.h diff --git a/components/soc/esp32c61/include/soc/hp_system_reg.h b/components/soc/esp32c61/register/soc/hp_system_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/hp_system_reg.h rename to components/soc/esp32c61/register/soc/hp_system_reg.h diff --git a/components/soc/esp32c61/include/soc/hp_system_struct.h b/components/soc/esp32c61/register/soc/hp_system_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/hp_system_struct.h rename to components/soc/esp32c61/register/soc/hp_system_struct.h diff --git a/components/soc/esp32c61/include/soc/i2c_ana_mst_reg.h b/components/soc/esp32c61/register/soc/i2c_ana_mst_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/i2c_ana_mst_reg.h rename to components/soc/esp32c61/register/soc/i2c_ana_mst_reg.h diff --git a/components/soc/esp32c61/include/soc/i2c_reg.h b/components/soc/esp32c61/register/soc/i2c_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/i2c_reg.h rename to components/soc/esp32c61/register/soc/i2c_reg.h diff --git a/components/soc/esp32c61/include/soc/i2c_struct.h b/components/soc/esp32c61/register/soc/i2c_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/i2c_struct.h rename to components/soc/esp32c61/register/soc/i2c_struct.h diff --git a/components/soc/esp32c61/include/soc/i2s_reg.h b/components/soc/esp32c61/register/soc/i2s_reg.h similarity index 98% rename from components/soc/esp32c61/include/soc/i2s_reg.h rename to components/soc/esp32c61/register/soc/i2s_reg.h index a7f16f4d6123..cea489c0bc21 100644 --- a/components/soc/esp32c61/include/soc/i2s_reg.h +++ b/components/soc/esp32c61/register/soc/i2s_reg.h @@ -320,7 +320,7 @@ extern "C" { #define I2S_TX_SLAVE_MOD_V 0x00000001U #define I2S_TX_SLAVE_MOD_S 3 /** I2S_TX_STOP_EN : R/W; bitpos: [4]; default: 1; - * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty */ #define I2S_TX_STOP_EN (BIT(4)) #define I2S_TX_STOP_EN_M (I2S_TX_STOP_EN_V << I2S_TX_STOP_EN_S) @@ -694,22 +694,6 @@ extern "C" { #define I2S_RX_PDM_HP_BYPASS_M (I2S_RX_PDM_HP_BYPASS_V << I2S_RX_PDM_HP_BYPASS_S) #define I2S_RX_PDM_HP_BYPASS_V 0x00000001U #define I2S_RX_PDM_HP_BYPASS_S 25 -/** I2S_RX_IIR_HP_MULT12_5 : R/W; bitpos: [28:26]; default: 6; - * The fourth parameter of PDM RX IIR_HP filter stage 2 is (504 + - * LP_I2S_RX_IIR_HP_MULT12_5[2:0]) - */ -#define I2S_RX_IIR_HP_MULT12_5 0x00000007U -#define I2S_RX_IIR_HP_MULT12_5_M (I2S_RX_IIR_HP_MULT12_5_V << I2S_RX_IIR_HP_MULT12_5_S) -#define I2S_RX_IIR_HP_MULT12_5_V 0x00000007U -#define I2S_RX_IIR_HP_MULT12_5_S 26 -/** I2S_RX_IIR_HP_MULT12_0 : R/W; bitpos: [31:29]; default: 7; - * The fourth parameter of PDM RX IIR_HP filter stage 1 is (504 + - * LP_I2S_RX_IIR_HP_MULT12_0[2:0]) - */ -#define I2S_RX_IIR_HP_MULT12_0 0x00000007U -#define I2S_RX_IIR_HP_MULT12_0_M (I2S_RX_IIR_HP_MULT12_0_V << I2S_RX_IIR_HP_MULT12_0_S) -#define I2S_RX_IIR_HP_MULT12_0_V 0x00000007U -#define I2S_RX_IIR_HP_MULT12_0_S 29 /** I2S_RX_TDM_CTRL_REG register * I2S TX TDM mode control register diff --git a/components/soc/esp32c61/include/soc/i2s_struct.h b/components/soc/esp32c61/register/soc/i2s_struct.h similarity index 98% rename from components/soc/esp32c61/include/soc/i2s_struct.h rename to components/soc/esp32c61/register/soc/i2s_struct.h index a0ff42939e78..e9afdbf28b7a 100644 --- a/components/soc/esp32c61/include/soc/i2s_struct.h +++ b/components/soc/esp32c61/register/soc/i2s_struct.h @@ -263,16 +263,7 @@ typedef union { * I2S PDM RX bypass hp filter or not. */ uint32_t rx_pdm_hp_bypass:1; - /** rx_iir_hp_mult12_5 : R/W; bitpos: [28:26]; default: 6; - * The fourth parameter of PDM RX IIR_HP filter stage 2 is (504 + - * LP_I2S_RX_IIR_HP_MULT12_5[2:0]) - */ - uint32_t rx_iir_hp_mult12_5:3; - /** rx_iir_hp_mult12_0 : R/W; bitpos: [31:29]; default: 7; - * The fourth parameter of PDM RX IIR_HP filter stage 1 is (504 + - * LP_I2S_RX_IIR_HP_MULT12_0[2:0]) - */ - uint32_t rx_iir_hp_mult12_0:3; + uint32_t reserved_26:6; }; uint32_t val; } i2s_rx_pdm2pcm_conf_reg_t; @@ -410,7 +401,7 @@ typedef union { */ uint32_t tx_slave_mod:1; /** tx_stop_en : R/W; bitpos: [4]; default: 1; - * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty */ uint32_t tx_stop_en:1; /** tx_chan_equal : R/W; bitpos: [5]; default: 0; @@ -859,7 +850,7 @@ typedef union { uint32_t single_data:32; }; uint32_t val; -} i2s_conf_sigle_data_reg_t; +} i2s_conf_single_data_reg_t; /** Group: TX status registers */ @@ -989,8 +980,8 @@ typedef struct { volatile i2s_rx_timing_reg_t rx_timing; volatile i2s_tx_timing_reg_t tx_timing; volatile i2s_lc_hung_conf_reg_t lc_hung_conf; - volatile i2s_rxeof_num_reg_t rxeof_num; - volatile i2s_conf_sigle_data_reg_t conf_sigle_data; + volatile i2s_rxeof_num_reg_t rx_eof_num; + volatile i2s_conf_single_data_reg_t conf_single_data; volatile i2s_state_reg_t state; volatile i2s_etm_conf_reg_t etm_conf; volatile i2s_fifo_cnt_reg_t fifo_cnt; @@ -999,7 +990,7 @@ typedef struct { volatile i2s_date_reg_t date; } i2s_dev_t; -extern i2s_dev_t I2S; +extern i2s_dev_t I2S0; #ifndef __cplusplus _Static_assert(sizeof(i2s_dev_t) == 0x84, "Invalid size of i2s_dev_t structure"); diff --git a/components/soc/esp32c61/include/soc/interrupt_matrix_reg.h b/components/soc/esp32c61/register/soc/interrupt_matrix_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/interrupt_matrix_reg.h rename to components/soc/esp32c61/register/soc/interrupt_matrix_reg.h diff --git a/components/soc/esp32c61/include/soc/interrupt_matrix_struct.h b/components/soc/esp32c61/register/soc/interrupt_matrix_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/interrupt_matrix_struct.h rename to components/soc/esp32c61/register/soc/interrupt_matrix_struct.h diff --git a/components/soc/esp32c61/include/soc/intpri_reg.h b/components/soc/esp32c61/register/soc/intpri_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/intpri_reg.h rename to components/soc/esp32c61/register/soc/intpri_reg.h diff --git a/components/soc/esp32c61/include/soc/intpri_struct.h b/components/soc/esp32c61/register/soc/intpri_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/intpri_struct.h rename to components/soc/esp32c61/register/soc/intpri_struct.h diff --git a/components/soc/esp32c61/include/soc/io_mux_reg.h b/components/soc/esp32c61/register/soc/io_mux_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/io_mux_reg.h rename to components/soc/esp32c61/register/soc/io_mux_reg.h diff --git a/components/soc/esp32c61/include/soc/io_mux_struct.h b/components/soc/esp32c61/register/soc/io_mux_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/io_mux_struct.h rename to components/soc/esp32c61/register/soc/io_mux_struct.h diff --git a/components/soc/esp32c61/include/soc/ledc_reg.h b/components/soc/esp32c61/register/soc/ledc_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/ledc_reg.h rename to components/soc/esp32c61/register/soc/ledc_reg.h diff --git a/components/soc/esp32c61/include/soc/ledc_struct.h b/components/soc/esp32c61/register/soc/ledc_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/ledc_struct.h rename to components/soc/esp32c61/register/soc/ledc_struct.h diff --git a/components/soc/esp32c61/include/soc/lp_analog_peri_reg.h b/components/soc/esp32c61/register/soc/lp_analog_peri_reg.h similarity index 96% rename from components/soc/esp32c61/include/soc/lp_analog_peri_reg.h rename to components/soc/esp32c61/register/soc/lp_analog_peri_reg.h index cea0165480b7..d7398ecbda44 100644 --- a/components/soc/esp32c61/include/soc/lp_analog_peri_reg.h +++ b/components/soc/esp32c61/register/soc/lp_analog_peri_reg.h @@ -108,6 +108,11 @@ extern "C" { #define LP_ANA_ANA_FIB_ENA_V 0xFFFFFFFFU #define LP_ANA_ANA_FIB_ENA_S 0 +#define LP_ANA_ANA_FIB_PWR_GLITCH_ENA 0x0000000FU +#define LP_ANA_ANA_FIB_PWR_GLITCH_ENA_M (LP_ANA_ANA_FIB_PWR_GLITCH_ENA_V << LP_ANA_ANA_FIB_PWR_GLITCH_ENA_S) +#define LP_ANA_ANA_FIB_PWR_GLITCH_ENA_V 0x0000000FU +#define LP_ANA_ANA_FIB_PWR_GLITCH_ENA_S 2 + /** LP_ANA_INT_RAW_REG register * need_des */ diff --git a/components/soc/esp32c61/include/soc/lp_analog_peri_struct.h b/components/soc/esp32c61/register/soc/lp_analog_peri_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_analog_peri_struct.h rename to components/soc/esp32c61/register/soc/lp_analog_peri_struct.h diff --git a/components/soc/esp32c61/include/soc/lp_aon_reg.h b/components/soc/esp32c61/register/soc/lp_aon_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_aon_reg.h rename to components/soc/esp32c61/register/soc/lp_aon_reg.h diff --git a/components/soc/esp32c61/include/soc/lp_aon_struct.h b/components/soc/esp32c61/register/soc/lp_aon_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_aon_struct.h rename to components/soc/esp32c61/register/soc/lp_aon_struct.h diff --git a/components/soc/esp32c61/include/soc/lp_apm_reg.h b/components/soc/esp32c61/register/soc/lp_apm_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_apm_reg.h rename to components/soc/esp32c61/register/soc/lp_apm_reg.h diff --git a/components/soc/esp32c61/include/soc/lp_apm_struct.h b/components/soc/esp32c61/register/soc/lp_apm_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_apm_struct.h rename to components/soc/esp32c61/register/soc/lp_apm_struct.h diff --git a/components/soc/esp32c61/include/soc/lp_clkrst_reg.h b/components/soc/esp32c61/register/soc/lp_clkrst_reg.h similarity index 99% rename from components/soc/esp32c61/include/soc/lp_clkrst_reg.h rename to components/soc/esp32c61/register/soc/lp_clkrst_reg.h index 55d2fb2315f7..755a7c3c6358 100644 --- a/components/soc/esp32c61/include/soc/lp_clkrst_reg.h +++ b/components/soc/esp32c61/register/soc/lp_clkrst_reg.h @@ -211,7 +211,7 @@ extern "C" { #define LP_CLKRST_ANA_PERI_RESET_EN_S 31 /** LP_CLKRST_RESET_CAUSE_REG register - * Represents the reset casue + * Represents the reset cause */ #define LP_CLKRST_RESET_CAUSE_REG (DR_REG_LP_CLKRST_BASE + 0x10) /** LP_CLKRST_RESET_CAUSE : RO; bitpos: [4:0]; default: 0; diff --git a/components/soc/esp32c61/include/soc/lp_clkrst_struct.h b/components/soc/esp32c61/register/soc/lp_clkrst_struct.h similarity index 99% rename from components/soc/esp32c61/include/soc/lp_clkrst_struct.h rename to components/soc/esp32c61/register/soc/lp_clkrst_struct.h index 685b52458723..2c69f169a576 100644 --- a/components/soc/esp32c61/include/soc/lp_clkrst_struct.h +++ b/components/soc/esp32c61/register/soc/lp_clkrst_struct.h @@ -171,7 +171,7 @@ typedef union { } lp_clkrst_lp_rst_en_reg_t; /** Type of reset_cause register - * Represents the reset casue + * Represents the reset cause */ typedef union { struct { diff --git a/components/soc/esp32c61/include/soc/lp_gpio_reg.h b/components/soc/esp32c61/register/soc/lp_gpio_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_gpio_reg.h rename to components/soc/esp32c61/register/soc/lp_gpio_reg.h diff --git a/components/soc/esp32c61/include/soc/lp_gpio_struct.h b/components/soc/esp32c61/register/soc/lp_gpio_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_gpio_struct.h rename to components/soc/esp32c61/register/soc/lp_gpio_struct.h diff --git a/components/soc/esp32c61/include/soc/lp_iomux_reg.h b/components/soc/esp32c61/register/soc/lp_iomux_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_iomux_reg.h rename to components/soc/esp32c61/register/soc/lp_iomux_reg.h diff --git a/components/soc/esp32c61/include/soc/lp_iomux_struct.h b/components/soc/esp32c61/register/soc/lp_iomux_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_iomux_struct.h rename to components/soc/esp32c61/register/soc/lp_iomux_struct.h diff --git a/components/soc/esp32c61/include/soc/lp_tee_reg.h b/components/soc/esp32c61/register/soc/lp_tee_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_tee_reg.h rename to components/soc/esp32c61/register/soc/lp_tee_reg.h diff --git a/components/soc/esp32c61/include/soc/lp_tee_struct.h b/components/soc/esp32c61/register/soc/lp_tee_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_tee_struct.h rename to components/soc/esp32c61/register/soc/lp_tee_struct.h diff --git a/components/soc/esp32c61/include/soc/lp_timer_reg.h b/components/soc/esp32c61/register/soc/lp_timer_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_timer_reg.h rename to components/soc/esp32c61/register/soc/lp_timer_reg.h diff --git a/components/soc/esp32c61/include/soc/lp_timer_struct.h b/components/soc/esp32c61/register/soc/lp_timer_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_timer_struct.h rename to components/soc/esp32c61/register/soc/lp_timer_struct.h diff --git a/components/soc/esp32c61/include/soc/lp_wdt_reg.h b/components/soc/esp32c61/register/soc/lp_wdt_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_wdt_reg.h rename to components/soc/esp32c61/register/soc/lp_wdt_reg.h diff --git a/components/soc/esp32c61/include/soc/lp_wdt_struct.h b/components/soc/esp32c61/register/soc/lp_wdt_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lp_wdt_struct.h rename to components/soc/esp32c61/register/soc/lp_wdt_struct.h diff --git a/components/soc/esp32c61/include/soc/lpperi_reg.h b/components/soc/esp32c61/register/soc/lpperi_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/lpperi_reg.h rename to components/soc/esp32c61/register/soc/lpperi_reg.h diff --git a/components/soc/esp32c61/include/soc/lpperi_struct.h b/components/soc/esp32c61/register/soc/lpperi_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/lpperi_struct.h rename to components/soc/esp32c61/register/soc/lpperi_struct.h diff --git a/components/soc/esp32c61/include/soc/mem_monitor_reg.h b/components/soc/esp32c61/register/soc/mem_monitor_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/mem_monitor_reg.h rename to components/soc/esp32c61/register/soc/mem_monitor_reg.h diff --git a/components/soc/esp32c61/include/soc/mem_monitor_struct.h b/components/soc/esp32c61/register/soc/mem_monitor_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/mem_monitor_struct.h rename to components/soc/esp32c61/register/soc/mem_monitor_struct.h diff --git a/components/soc/esp32c61/include/soc/pau_reg.h b/components/soc/esp32c61/register/soc/pau_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/pau_reg.h rename to components/soc/esp32c61/register/soc/pau_reg.h diff --git a/components/soc/esp32c61/include/soc/pau_struct.h b/components/soc/esp32c61/register/soc/pau_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/pau_struct.h rename to components/soc/esp32c61/register/soc/pau_struct.h diff --git a/components/soc/esp32c61/include/soc/pcr_reg.h b/components/soc/esp32c61/register/soc/pcr_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/pcr_reg.h rename to components/soc/esp32c61/register/soc/pcr_reg.h diff --git a/components/soc/esp32c61/include/soc/pcr_struct.h b/components/soc/esp32c61/register/soc/pcr_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/pcr_struct.h rename to components/soc/esp32c61/register/soc/pcr_struct.h diff --git a/components/soc/esp32c61/include/soc/pmu_reg.h b/components/soc/esp32c61/register/soc/pmu_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/pmu_reg.h rename to components/soc/esp32c61/register/soc/pmu_reg.h diff --git a/components/soc/esp32c61/include/soc/pmu_struct.h b/components/soc/esp32c61/register/soc/pmu_struct.h similarity index 99% rename from components/soc/esp32c61/include/soc/pmu_struct.h rename to components/soc/esp32c61/register/soc/pmu_struct.h index 3e2f9fb16f6f..e59470be4e90 100644 --- a/components/soc/esp32c61/include/soc/pmu_struct.h +++ b/components/soc/esp32c61/register/soc/pmu_struct.h @@ -11,7 +11,7 @@ extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #include "soc/pmu_reg.h" typedef union { diff --git a/components/soc/esp32c61/include/soc/pvt_reg.h b/components/soc/esp32c61/register/soc/pvt_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/pvt_reg.h rename to components/soc/esp32c61/register/soc/pvt_reg.h diff --git a/components/soc/esp32c61/include/soc/pvt_struct.h b/components/soc/esp32c61/register/soc/pvt_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/pvt_struct.h rename to components/soc/esp32c61/register/soc/pvt_struct.h diff --git a/components/soc/esp32c61/include/soc/reg_base.h b/components/soc/esp32c61/register/soc/reg_base.h similarity index 98% rename from components/soc/esp32c61/include/soc/reg_base.h rename to components/soc/esp32c61/register/soc/reg_base.h index e092f8726b69..e52fc35286ca 100644 --- a/components/soc/esp32c61/include/soc/reg_base.h +++ b/components/soc/esp32c61/register/soc/reg_base.h @@ -24,7 +24,7 @@ #define DR_REG_PVT_MONITOR_BASE 0x60019000 #define DR_REG_PSRAM_MEM_MONITOR_BASE 0x6001A000 #define DR_REG_AHB_DMA_BASE 0x60080000 -#define DR_REG_GPSPI_BASE 0x60081000 +#define DR_REG_SPI2_BASE 0x60081000 #define DR_REG_SHA_BASE 0x60089000 #define DR_REG_ECC_MULT_BASE 0x6008B000 #define DR_REG_ECDSA_BASE 0x6008E000 diff --git a/components/soc/esp32c61/include/soc/sha_reg.h b/components/soc/esp32c61/register/soc/sha_reg.h similarity index 98% rename from components/soc/esp32c61/include/soc/sha_reg.h rename to components/soc/esp32c61/register/soc/sha_reg.h index ab9f346e774c..4dd7f4a2d9d5 100644 --- a/components/soc/esp32c61/include/soc/sha_reg.h +++ b/components/soc/esp32c61/register/soc/sha_reg.h @@ -161,7 +161,7 @@ extern "C" { #define SHA_DATE_S 0 /** SHA_H_MEM register - * Sha H memory which contains intermediate hash or finial hash. + * Sha H memory which contains intermediate hash or final hash. */ #define SHA_H_MEM (DR_REG_SHA_BASE + 0x40) #define SHA_H_MEM_SIZE_BYTES 64 diff --git a/components/soc/esp32c61/include/soc/sha_struct.h b/components/soc/esp32c61/register/soc/sha_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/sha_struct.h rename to components/soc/esp32c61/register/soc/sha_struct.h diff --git a/components/soc/esp32c61/include/soc/soc_etm_reg.h b/components/soc/esp32c61/register/soc/soc_etm_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/soc_etm_reg.h rename to components/soc/esp32c61/register/soc/soc_etm_reg.h diff --git a/components/soc/esp32c61/include/soc/soc_etm_struct.h b/components/soc/esp32c61/register/soc/soc_etm_struct.h similarity index 96% rename from components/soc/esp32c61/include/soc/soc_etm_struct.h rename to components/soc/esp32c61/register/soc/soc_etm_struct.h index 464ab7f33e11..2cb80d7c280c 100644 --- a/components/soc/esp32c61/include/soc/soc_etm_struct.h +++ b/components/soc/esp32c61/register/soc/soc_etm_struct.h @@ -3161,113 +3161,17 @@ typedef union { } soc_etm_date_reg_t; -typedef struct { +typedef struct soc_etm_dev_t { volatile soc_etm_ch_ena_ad0_reg_t ch_ena_ad0; volatile soc_etm_ch_ena_ad0_set_reg_t ch_ena_ad0_set; volatile soc_etm_ch_ena_ad0_clr_reg_t ch_ena_ad0_clr; volatile soc_etm_ch_ena_ad1_reg_t ch_ena_ad1; volatile soc_etm_ch_ena_ad1_set_reg_t ch_ena_ad1_set; volatile soc_etm_ch_ena_ad1_clr_reg_t ch_ena_ad1_clr; - volatile soc_etm_chn_evt_id_reg_t ch0_evt_id; - volatile soc_etm_chn_task_id_reg_t ch0_task_id; - volatile soc_etm_chn_evt_id_reg_t ch1_evt_id; - volatile soc_etm_chn_task_id_reg_t ch1_task_id; - volatile soc_etm_chn_evt_id_reg_t ch2_evt_id; - volatile soc_etm_chn_task_id_reg_t ch2_task_id; - volatile soc_etm_chn_evt_id_reg_t ch3_evt_id; - volatile soc_etm_chn_task_id_reg_t ch3_task_id; - volatile soc_etm_chn_evt_id_reg_t ch4_evt_id; - volatile soc_etm_chn_task_id_reg_t ch4_task_id; - volatile soc_etm_chn_evt_id_reg_t ch5_evt_id; - volatile soc_etm_chn_task_id_reg_t ch5_task_id; - volatile soc_etm_chn_evt_id_reg_t ch6_evt_id; - volatile soc_etm_chn_task_id_reg_t ch6_task_id; - volatile soc_etm_chn_evt_id_reg_t ch7_evt_id; - volatile soc_etm_chn_task_id_reg_t ch7_task_id; - volatile soc_etm_chn_evt_id_reg_t ch8_evt_id; - volatile soc_etm_chn_task_id_reg_t ch8_task_id; - volatile soc_etm_chn_evt_id_reg_t ch9_evt_id; - volatile soc_etm_chn_task_id_reg_t ch9_task_id; - volatile soc_etm_chn_evt_id_reg_t ch10_evt_id; - volatile soc_etm_chn_task_id_reg_t ch10_task_id; - volatile soc_etm_chn_evt_id_reg_t ch11_evt_id; - volatile soc_etm_chn_task_id_reg_t ch11_task_id; - volatile soc_etm_chn_evt_id_reg_t ch12_evt_id; - volatile soc_etm_chn_task_id_reg_t ch12_task_id; - volatile soc_etm_chn_evt_id_reg_t ch13_evt_id; - volatile soc_etm_chn_task_id_reg_t ch13_task_id; - volatile soc_etm_chn_evt_id_reg_t ch14_evt_id; - volatile soc_etm_chn_task_id_reg_t ch14_task_id; - volatile soc_etm_chn_evt_id_reg_t ch15_evt_id; - volatile soc_etm_chn_task_id_reg_t ch15_task_id; - volatile soc_etm_chn_evt_id_reg_t ch16_evt_id; - volatile soc_etm_chn_task_id_reg_t ch16_task_id; - volatile soc_etm_chn_evt_id_reg_t ch17_evt_id; - volatile soc_etm_chn_task_id_reg_t ch17_task_id; - volatile soc_etm_chn_evt_id_reg_t ch18_evt_id; - volatile soc_etm_chn_task_id_reg_t ch18_task_id; - volatile soc_etm_chn_evt_id_reg_t ch19_evt_id; - volatile soc_etm_chn_task_id_reg_t ch19_task_id; - volatile soc_etm_chn_evt_id_reg_t ch20_evt_id; - volatile soc_etm_chn_task_id_reg_t ch20_task_id; - volatile soc_etm_chn_evt_id_reg_t ch21_evt_id; - volatile soc_etm_chn_task_id_reg_t ch21_task_id; - volatile soc_etm_chn_evt_id_reg_t ch22_evt_id; - volatile soc_etm_chn_task_id_reg_t ch22_task_id; - volatile soc_etm_chn_evt_id_reg_t ch23_evt_id; - volatile soc_etm_chn_task_id_reg_t ch23_task_id; - volatile soc_etm_chn_evt_id_reg_t ch24_evt_id; - volatile soc_etm_chn_task_id_reg_t ch24_task_id; - volatile soc_etm_chn_evt_id_reg_t ch25_evt_id; - volatile soc_etm_chn_task_id_reg_t ch25_task_id; - volatile soc_etm_chn_evt_id_reg_t ch26_evt_id; - volatile soc_etm_chn_task_id_reg_t ch26_task_id; - volatile soc_etm_chn_evt_id_reg_t ch27_evt_id; - volatile soc_etm_chn_task_id_reg_t ch27_task_id; - volatile soc_etm_chn_evt_id_reg_t ch28_evt_id; - volatile soc_etm_chn_task_id_reg_t ch28_task_id; - volatile soc_etm_chn_evt_id_reg_t ch29_evt_id; - volatile soc_etm_chn_task_id_reg_t ch29_task_id; - volatile soc_etm_chn_evt_id_reg_t ch30_evt_id; - volatile soc_etm_chn_task_id_reg_t ch30_task_id; - volatile soc_etm_chn_evt_id_reg_t ch31_evt_id; - volatile soc_etm_chn_task_id_reg_t ch31_task_id; - volatile soc_etm_chn_evt_id_reg_t ch32_evt_id; - volatile soc_etm_chn_task_id_reg_t ch32_task_id; - volatile soc_etm_chn_evt_id_reg_t ch33_evt_id; - volatile soc_etm_chn_task_id_reg_t ch33_task_id; - volatile soc_etm_chn_evt_id_reg_t ch34_evt_id; - volatile soc_etm_chn_task_id_reg_t ch34_task_id; - volatile soc_etm_chn_evt_id_reg_t ch35_evt_id; - volatile soc_etm_chn_task_id_reg_t ch35_task_id; - volatile soc_etm_chn_evt_id_reg_t ch36_evt_id; - volatile soc_etm_chn_task_id_reg_t ch36_task_id; - volatile soc_etm_chn_evt_id_reg_t ch37_evt_id; - volatile soc_etm_chn_task_id_reg_t ch37_task_id; - volatile soc_etm_chn_evt_id_reg_t ch38_evt_id; - volatile soc_etm_chn_task_id_reg_t ch38_task_id; - volatile soc_etm_chn_evt_id_reg_t ch39_evt_id; - volatile soc_etm_chn_task_id_reg_t ch39_task_id; - volatile soc_etm_chn_evt_id_reg_t ch40_evt_id; - volatile soc_etm_chn_task_id_reg_t ch40_task_id; - volatile soc_etm_chn_evt_id_reg_t ch41_evt_id; - volatile soc_etm_chn_task_id_reg_t ch41_task_id; - volatile soc_etm_chn_evt_id_reg_t ch42_evt_id; - volatile soc_etm_chn_task_id_reg_t ch42_task_id; - volatile soc_etm_chn_evt_id_reg_t ch43_evt_id; - volatile soc_etm_chn_task_id_reg_t ch43_task_id; - volatile soc_etm_chn_evt_id_reg_t ch44_evt_id; - volatile soc_etm_chn_task_id_reg_t ch44_task_id; - volatile soc_etm_chn_evt_id_reg_t ch45_evt_id; - volatile soc_etm_chn_task_id_reg_t ch45_task_id; - volatile soc_etm_chn_evt_id_reg_t ch46_evt_id; - volatile soc_etm_chn_task_id_reg_t ch46_task_id; - volatile soc_etm_chn_evt_id_reg_t ch47_evt_id; - volatile soc_etm_chn_task_id_reg_t ch47_task_id; - volatile soc_etm_chn_evt_id_reg_t ch48_evt_id; - volatile soc_etm_chn_task_id_reg_t ch48_task_id; - volatile soc_etm_chn_evt_id_reg_t ch49_evt_id; - volatile soc_etm_chn_task_id_reg_t ch49_task_id; + volatile struct { + soc_etm_chn_evt_id_reg_t eid; + soc_etm_chn_task_id_reg_t tid; + } channel[50]; volatile soc_etm_evt_st0_reg_t evt_st0; volatile soc_etm_evt_st0_clr_reg_t evt_st0_clr; volatile soc_etm_evt_st1_reg_t evt_st1; diff --git a/components/soc/esp32c61/include/soc/spi1_mem_reg.h b/components/soc/esp32c61/register/soc/spi1_mem_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/spi1_mem_reg.h rename to components/soc/esp32c61/register/soc/spi1_mem_reg.h diff --git a/components/soc/esp32c61/include/soc/spi1_mem_struct.h b/components/soc/esp32c61/register/soc/spi1_mem_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/spi1_mem_struct.h rename to components/soc/esp32c61/register/soc/spi1_mem_struct.h diff --git a/components/soc/esp32c61/include/soc/spi_mem_c_reg.h b/components/soc/esp32c61/register/soc/spi_mem_c_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/spi_mem_c_reg.h rename to components/soc/esp32c61/register/soc/spi_mem_c_reg.h diff --git a/components/soc/esp32c61/include/soc/spi_mem_c_struct.h b/components/soc/esp32c61/register/soc/spi_mem_c_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/spi_mem_c_struct.h rename to components/soc/esp32c61/register/soc/spi_mem_c_struct.h diff --git a/components/soc/esp32c61/include/soc/spi_reg.h b/components/soc/esp32c61/register/soc/spi_reg.h similarity index 98% rename from components/soc/esp32c61/include/soc/spi_reg.h rename to components/soc/esp32c61/register/soc/spi_reg.h index 66a09daf9f39..cce0834349ab 100644 --- a/components/soc/esp32c61/include/soc/spi_reg.h +++ b/components/soc/esp32c61/register/soc/spi_reg.h @@ -14,7 +14,7 @@ extern "C" { /** SPI_CMD_REG register * Command control register */ -#define SPI_CMD_REG (DR_REG_SPI_BASE + 0x0) +#define SPI_CMD_REG(i) (REG_SPI_BASE(i) + 0x0) /** SPI_CONF_BITLEN : R/W; bitpos: [17:0]; default: 0; * Configures the SPI_CLK cycles of SPI CONF state. * Measurement unit: SPI_CLK clock cycle.\\ @@ -50,7 +50,7 @@ extern "C" { /** SPI_ADDR_REG register * Address value register */ -#define SPI_ADDR_REG (DR_REG_SPI_BASE + 0x4) +#define SPI_ADDR_REG(i) (REG_SPI_BASE(i) + 0x4) /** SPI_USR_ADDR_VALUE : R/W; bitpos: [31:0]; default: 0; * Configures the address to slave. * Can be configured in CONF state. @@ -63,7 +63,7 @@ extern "C" { /** SPI_CTRL_REG register * SPI control register */ -#define SPI_CTRL_REG (DR_REG_SPI_BASE + 0x8) +#define SPI_CTRL_REG(i) (REG_SPI_BASE(i) + 0x8) /** SPI_DUMMY_OUT : R/W; bitpos: [3]; default: 0; * Configures whether or not to output the FSPI bus signals in DUMMY state. \\ * 0: Not output \\ @@ -232,7 +232,7 @@ extern "C" { /** SPI_CLOCK_REG register * SPI clock control register */ -#define SPI_CLOCK_REG (DR_REG_SPI_BASE + 0xc) +#define SPI_CLOCK_REG(i) (REG_SPI_BASE(i) + 0xc) /** SPI_CLKCNT_L : R/W; bitpos: [5:0]; default: 3; * In master transfer, this field must be equal to SPI_CLKCNT_N. In slave mode, it * must be 0. Can be configured in CONF state. @@ -273,7 +273,7 @@ extern "C" { /** SPI_CLK_EQU_SYSCLK : R/W; bitpos: [31]; default: 1; * Configures whether or not the SPI_CLK is equal to APB_CLK in master transfer.\\ * 0: SPI_CLK is divided from APB_CLK.\\ - * 1: SPI_CLK is eqaul to APB_CLK.\\ + * 1: SPI_CLK is equal to APB_CLK.\\ * Can be configured in CONF state. */ #define SPI_CLK_EQU_SYSCLK (BIT(31)) @@ -284,7 +284,7 @@ extern "C" { /** SPI_USER_REG register * SPI USER control register */ -#define SPI_USER_REG (DR_REG_SPI_BASE + 0x10) +#define SPI_USER_REG(i) (REG_SPI_BASE(i) + 0x10) /** SPI_DOUTDIN : R/W; bitpos: [0]; default: 0; * Configures whether or not to enable full-duplex communication. \\ * 0: Disable \\ @@ -501,7 +501,7 @@ extern "C" { /** SPI_USER1_REG register * SPI USER control register 1 */ -#define SPI_USER1_REG (DR_REG_SPI_BASE + 0x14) +#define SPI_USER1_REG(i) (REG_SPI_BASE(i) + 0x14) /** SPI_USR_DUMMY_CYCLELEN : R/W; bitpos: [7:0]; default: 7; * Configures the length of DUMMY state. * Measurement unit: SPI_CLK clock cycles.\\ @@ -552,7 +552,7 @@ extern "C" { /** SPI_USER2_REG register * SPI USER control register 2 */ -#define SPI_USER2_REG (DR_REG_SPI_BASE + 0x18) +#define SPI_USER2_REG(i) (REG_SPI_BASE(i) + 0x18) /** SPI_USR_COMMAND_VALUE : R/W; bitpos: [15:0]; default: 0; * Configures the command value. * Can be configured in CONF state. @@ -583,7 +583,7 @@ extern "C" { /** SPI_MS_DLEN_REG register * SPI data bit length control register */ -#define SPI_MS_DLEN_REG (DR_REG_SPI_BASE + 0x1c) +#define SPI_MS_DLEN_REG(i) (REG_SPI_BASE(i) + 0x1c) /** SPI_MS_DATA_BITLEN : R/W; bitpos: [17:0]; default: 0; * Configures the data bit length of SPI transfer in DMA-controlled master transfer or * in CPU-controlled master transfer. Or configures the bit length of SPI RX transfer @@ -598,7 +598,7 @@ extern "C" { /** SPI_MISC_REG register * SPI misc register */ -#define SPI_MISC_REG (DR_REG_SPI_BASE + 0x20) +#define SPI_MISC_REG(i) (REG_SPI_BASE(i) + 0x20) /** SPI_CS0_DIS : R/W; bitpos: [0]; default: 0; * Configures whether or not to disable SPI_CS$n pin.\\ * 0: SPI_CS$n signal is from/to SPI_CS$n pin.\\ @@ -763,7 +763,7 @@ extern "C" { /** SPI_DIN_MODE_REG register * SPI input delay mode configuration */ -#define SPI_DIN_MODE_REG (DR_REG_SPI_BASE + 0x24) +#define SPI_DIN_MODE_REG(i) (REG_SPI_BASE(i) + 0x24) /** SPI_DIN0_MODE : R/W; bitpos: [1:0]; default: 0; * Configures the input mode for FSPID signal.\\ * 0: Input without delay\\ @@ -872,7 +872,7 @@ extern "C" { /** SPI_DIN_NUM_REG register * SPI input delay number configuration */ -#define SPI_DIN_NUM_REG (DR_REG_SPI_BASE + 0x28) +#define SPI_DIN_NUM_REG(i) (REG_SPI_BASE(i) + 0x28) /** SPI_DIN0_NUM : R/W; bitpos: [1:0]; default: 0; * Configures the delays to input signal FSPID based on the setting of SPI_DIN0_MODE.\\ * 0: Delayed by 1 clock cycle\\ @@ -959,7 +959,7 @@ extern "C" { /** SPI_DOUT_MODE_REG register * SPI output delay mode configuration */ -#define SPI_DOUT_MODE_REG (DR_REG_SPI_BASE + 0x2c) +#define SPI_DOUT_MODE_REG(i) (REG_SPI_BASE(i) + 0x2c) /** SPI_DOUT0_MODE : R/W; bitpos: [0]; default: 0; * Configures the output mode for FSPID signal.\\ * 0: Output without delay\\ @@ -1049,7 +1049,7 @@ extern "C" { /** SPI_DMA_CONF_REG register * SPI DMA control register */ -#define SPI_DMA_CONF_REG (DR_REG_SPI_BASE + 0x30) +#define SPI_DMA_CONF_REG(i) (REG_SPI_BASE(i) + 0x30) /** SPI_DMA_OUTFIFO_EMPTY : RO; bitpos: [0]; default: 1; * Represents whether or not the DMA TX FIFO is ready for sending data.\\ * 0: Ready\\ @@ -1177,7 +1177,7 @@ extern "C" { /** SPI_DMA_INT_ENA_REG register * SPI interrupt enable register */ -#define SPI_DMA_INT_ENA_REG (DR_REG_SPI_BASE + 0x34) +#define SPI_DMA_INT_ENA_REG(i) (REG_SPI_BASE(i) + 0x34) /** SPI_DMA_INFIFO_FULL_ERR_INT_ENA : R/W; bitpos: [0]; default: 0; * Write 1 to enable SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1329,7 +1329,7 @@ extern "C" { /** SPI_DMA_INT_CLR_REG register * SPI interrupt clear register */ -#define SPI_DMA_INT_CLR_REG (DR_REG_SPI_BASE + 0x38) +#define SPI_DMA_INT_CLR_REG(i) (REG_SPI_BASE(i) + 0x38) /** SPI_DMA_INFIFO_FULL_ERR_INT_CLR : WT; bitpos: [0]; default: 0; * Write 1 to clear SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1481,7 +1481,7 @@ extern "C" { /** SPI_DMA_INT_RAW_REG register * SPI interrupt raw register */ -#define SPI_DMA_INT_RAW_REG (DR_REG_SPI_BASE + 0x3c) +#define SPI_DMA_INT_RAW_REG(i) (REG_SPI_BASE(i) + 0x3c) /** SPI_DMA_INFIFO_FULL_ERR_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; * The raw interrupt status of SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1637,7 +1637,7 @@ extern "C" { /** SPI_DMA_INT_ST_REG register * SPI interrupt status register */ -#define SPI_DMA_INT_ST_REG (DR_REG_SPI_BASE + 0x40) +#define SPI_DMA_INT_ST_REG(i) (REG_SPI_BASE(i) + 0x40) /** SPI_DMA_INFIFO_FULL_ERR_INT_ST : RO; bitpos: [0]; default: 0; * The interrupt status of SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1789,7 +1789,7 @@ extern "C" { /** SPI_DMA_INT_SET_REG register * SPI interrupt software set register */ -#define SPI_DMA_INT_SET_REG (DR_REG_SPI_BASE + 0x44) +#define SPI_DMA_INT_SET_REG(i) (REG_SPI_BASE(i) + 0x44) /** SPI_DMA_INFIFO_FULL_ERR_INT_SET : WT; bitpos: [0]; default: 0; * Write 1 to set SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1941,7 +1941,7 @@ extern "C" { /** SPI_W0_REG register * SPI CPU-controlled buffer0 */ -#define SPI_W0_REG (DR_REG_SPI_BASE + 0x98) +#define SPI_W0_REG(i) (REG_SPI_BASE(i) + 0x98) /** SPI_BUF0 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -1953,7 +1953,7 @@ extern "C" { /** SPI_W1_REG register * SPI CPU-controlled buffer1 */ -#define SPI_W1_REG (DR_REG_SPI_BASE + 0x9c) +#define SPI_W1_REG(i) (REG_SPI_BASE(i) + 0x9c) /** SPI_BUF1 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -1965,7 +1965,7 @@ extern "C" { /** SPI_W2_REG register * SPI CPU-controlled buffer2 */ -#define SPI_W2_REG (DR_REG_SPI_BASE + 0xa0) +#define SPI_W2_REG(i) (REG_SPI_BASE(i) + 0xa0) /** SPI_BUF2 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -1977,7 +1977,7 @@ extern "C" { /** SPI_W3_REG register * SPI CPU-controlled buffer3 */ -#define SPI_W3_REG (DR_REG_SPI_BASE + 0xa4) +#define SPI_W3_REG(i) (REG_SPI_BASE(i) + 0xa4) /** SPI_BUF3 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -1989,7 +1989,7 @@ extern "C" { /** SPI_W4_REG register * SPI CPU-controlled buffer4 */ -#define SPI_W4_REG (DR_REG_SPI_BASE + 0xa8) +#define SPI_W4_REG(i) (REG_SPI_BASE(i) + 0xa8) /** SPI_BUF4 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2001,7 +2001,7 @@ extern "C" { /** SPI_W5_REG register * SPI CPU-controlled buffer5 */ -#define SPI_W5_REG (DR_REG_SPI_BASE + 0xac) +#define SPI_W5_REG(i) (REG_SPI_BASE(i) + 0xac) /** SPI_BUF5 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2013,7 +2013,7 @@ extern "C" { /** SPI_W6_REG register * SPI CPU-controlled buffer6 */ -#define SPI_W6_REG (DR_REG_SPI_BASE + 0xb0) +#define SPI_W6_REG(i) (REG_SPI_BASE(i) + 0xb0) /** SPI_BUF6 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2025,7 +2025,7 @@ extern "C" { /** SPI_W7_REG register * SPI CPU-controlled buffer7 */ -#define SPI_W7_REG (DR_REG_SPI_BASE + 0xb4) +#define SPI_W7_REG(i) (REG_SPI_BASE(i) + 0xb4) /** SPI_BUF7 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2037,7 +2037,7 @@ extern "C" { /** SPI_W8_REG register * SPI CPU-controlled buffer8 */ -#define SPI_W8_REG (DR_REG_SPI_BASE + 0xb8) +#define SPI_W8_REG(i) (REG_SPI_BASE(i) + 0xb8) /** SPI_BUF8 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2049,7 +2049,7 @@ extern "C" { /** SPI_W9_REG register * SPI CPU-controlled buffer9 */ -#define SPI_W9_REG (DR_REG_SPI_BASE + 0xbc) +#define SPI_W9_REG(i) (REG_SPI_BASE(i) + 0xbc) /** SPI_BUF9 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2061,7 +2061,7 @@ extern "C" { /** SPI_W10_REG register * SPI CPU-controlled buffer10 */ -#define SPI_W10_REG (DR_REG_SPI_BASE + 0xc0) +#define SPI_W10_REG(i) (REG_SPI_BASE(i) + 0xc0) /** SPI_BUF10 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2073,7 +2073,7 @@ extern "C" { /** SPI_W11_REG register * SPI CPU-controlled buffer11 */ -#define SPI_W11_REG (DR_REG_SPI_BASE + 0xc4) +#define SPI_W11_REG(i) (REG_SPI_BASE(i) + 0xc4) /** SPI_BUF11 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2085,7 +2085,7 @@ extern "C" { /** SPI_W12_REG register * SPI CPU-controlled buffer12 */ -#define SPI_W12_REG (DR_REG_SPI_BASE + 0xc8) +#define SPI_W12_REG(i) (REG_SPI_BASE(i) + 0xc8) /** SPI_BUF12 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2097,7 +2097,7 @@ extern "C" { /** SPI_W13_REG register * SPI CPU-controlled buffer13 */ -#define SPI_W13_REG (DR_REG_SPI_BASE + 0xcc) +#define SPI_W13_REG(i) (REG_SPI_BASE(i) + 0xcc) /** SPI_BUF13 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2109,7 +2109,7 @@ extern "C" { /** SPI_W14_REG register * SPI CPU-controlled buffer14 */ -#define SPI_W14_REG (DR_REG_SPI_BASE + 0xd0) +#define SPI_W14_REG(i) (REG_SPI_BASE(i) + 0xd0) /** SPI_BUF14 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2121,7 +2121,7 @@ extern "C" { /** SPI_W15_REG register * SPI CPU-controlled buffer15 */ -#define SPI_W15_REG (DR_REG_SPI_BASE + 0xd4) +#define SPI_W15_REG(i) (REG_SPI_BASE(i) + 0xd4) /** SPI_BUF15 : R/W/SS; bitpos: [31:0]; default: 0; * 32-bit data buffer $n. */ @@ -2133,7 +2133,7 @@ extern "C" { /** SPI_SLAVE_REG register * SPI slave control register */ -#define SPI_SLAVE_REG (DR_REG_SPI_BASE + 0xe0) +#define SPI_SLAVE_REG(i) (REG_SPI_BASE(i) + 0xe0) /** SPI_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * Configures SPI clock mode.\\ * 0: SPI clock is off when CS becomes inactive.\\ @@ -2267,7 +2267,7 @@ extern "C" { /** SPI_SLAVE1_REG register * SPI slave control register 1 */ -#define SPI_SLAVE1_REG (DR_REG_SPI_BASE + 0xe4) +#define SPI_SLAVE1_REG(i) (REG_SPI_BASE(i) + 0xe4) /** SPI_SLV_DATA_BITLEN : R/W/SS; bitpos: [17:0]; default: 0; * Configures the transferred data bit length in SPI slave full-/half-duplex modes. */ @@ -2293,7 +2293,7 @@ extern "C" { /** SPI_CLK_GATE_REG register * SPI module clock and register clock control */ -#define SPI_CLK_GATE_REG (DR_REG_SPI_BASE + 0xe8) +#define SPI_CLK_GATE_REG(i) (REG_SPI_BASE(i) + 0xe8) /** SPI_CLK_EN : R/W; bitpos: [0]; default: 0; * Configures whether or not to enable clock gate.\\ * 0: Disable\\ @@ -2322,7 +2322,7 @@ extern "C" { /** SPI_DATE_REG register * Version control */ -#define SPI_DATE_REG (DR_REG_SPI_BASE + 0xf0) +#define SPI_DATE_REG(i) (REG_SPI_BASE(i) + 0xf0) /** SPI_DATE : R/W; bitpos: [27:0]; default: 36716931; * Version control register. */ diff --git a/components/soc/esp32c61/include/soc/spi_struct.h b/components/soc/esp32c61/register/soc/spi_struct.h similarity index 99% rename from components/soc/esp32c61/include/soc/spi_struct.h rename to components/soc/esp32c61/register/soc/spi_struct.h index 7b84c9d658da..88690647ed5e 100644 --- a/components/soc/esp32c61/include/soc/spi_struct.h +++ b/components/soc/esp32c61/register/soc/spi_struct.h @@ -819,7 +819,7 @@ typedef union { /** clk_equ_sysclk : R/W; bitpos: [31]; default: 1; * Configures whether or not the SPI_CLK is equal to APB_CLK in master transfer.\\ * 0: SPI_CLK is divided from APB_CLK.\\ - * 1: SPI_CLK is eqaul to APB_CLK.\\ + * 1: SPI_CLK is equal to APB_CLK.\\ * Can be configured in CONF state. */ uint32_t clk_equ_sysclk:1; diff --git a/components/soc/esp32c61/include/soc/systimer_reg.h b/components/soc/esp32c61/register/soc/systimer_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/systimer_reg.h rename to components/soc/esp32c61/register/soc/systimer_reg.h diff --git a/components/soc/esp32c61/include/soc/systimer_struct.h b/components/soc/esp32c61/register/soc/systimer_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/systimer_struct.h rename to components/soc/esp32c61/register/soc/systimer_struct.h diff --git a/components/soc/esp32c61/include/soc/tee_reg.h b/components/soc/esp32c61/register/soc/tee_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/tee_reg.h rename to components/soc/esp32c61/register/soc/tee_reg.h diff --git a/components/soc/esp32c61/include/soc/tee_struct.h b/components/soc/esp32c61/register/soc/tee_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/tee_struct.h rename to components/soc/esp32c61/register/soc/tee_struct.h diff --git a/components/soc/esp32c61/include/soc/timer_group_reg.h b/components/soc/esp32c61/register/soc/timer_group_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/timer_group_reg.h rename to components/soc/esp32c61/register/soc/timer_group_reg.h diff --git a/components/soc/esp32c61/include/soc/timer_group_struct.h b/components/soc/esp32c61/register/soc/timer_group_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/timer_group_struct.h rename to components/soc/esp32c61/register/soc/timer_group_struct.h diff --git a/components/soc/esp32c61/include/soc/trace_reg.h b/components/soc/esp32c61/register/soc/trace_reg.h similarity index 98% rename from components/soc/esp32c61/include/soc/trace_reg.h rename to components/soc/esp32c61/register/soc/trace_reg.h index 1abfbbcd0453..785965af2c75 100644 --- a/components/soc/esp32c61/include/soc/trace_reg.h +++ b/components/soc/esp32c61/register/soc/trace_reg.h @@ -76,7 +76,7 @@ extern "C" { #define TRACE_FIFO_EMPTY_S 0 /** TRACE_WORK_STATUS : RO; bitpos: [2:1]; default: 0; * Represent the state of the encoder: \\0: Idle state \\1: Working state\\ 2: Wait - * state becasue hart is halted or in reset \\3: Lost state\\ + * state because hart is halted or in reset \\3: Lost state\\ */ #define TRACE_WORK_STATUS 0x00000003U #define TRACE_WORK_STATUS_M (TRACE_WORK_STATUS_V << TRACE_WORK_STATUS_S) @@ -186,7 +186,7 @@ extern "C" { #define TRACE_DM_TRIGGER_ENA_V 0x00000001U #define TRACE_DM_TRIGGER_ENA_S 0 /** TRACE_RESET_ENA : R/W; bitpos: [1]; default: 0; - * Configure whether to reset, when enabeld, if cpu have reset, the encoder will + * Configure whether to reset, when enabled, if cpu have reset, the encoder will * output a packet to report the address of the last instruction, and upon reset * deassertion, the encoder start again.\\0: Disable\\0: Enable\\ */ @@ -216,7 +216,7 @@ extern "C" { #define TRACE_FULL_ADDRESS_V 0x00000001U #define TRACE_FULL_ADDRESS_S 4 /** TRACE_IMPLICIT_EXCEPT : R/W; bitpos: [5]; default: 0; - * Configure whether or not enabel implicit exception mode. When enabled,, do not sent + * Configure whether or not enable implicit exception mode. When enabled,, do not sent * exception address, only exception cause in exception packets.\\1: enabled\\0: * disabled\\ */ @@ -418,7 +418,7 @@ extern "C" { */ #define TRACE_AHB_CONFIG_REG (DR_REG_TRACE_BASE + 0x40) /** TRACE_HBURST : R/W; bitpos: [2:0]; default: 0; - * Configures the AHB burst mode. \\0: SIGNLE \\1: INCR(length not defined) \\2:INCR4 + * Configures the AHB burst mode. \\0: SINGLE \\1: INCR(length not defined) \\2:INCR4 * \\4:INCR8 \\Others:Invalid */ #define TRACE_HBURST 0x00000007U @@ -440,7 +440,7 @@ extern "C" { /** TRACE_CLK_EN : R/W; bitpos: [0]; default: 1; * Configures register clock gating. \\0: Support clock only when the application * writes registers to save power. \\1:Always force the clock on for registers \\ This - * bit does't affect register access. + * bit doesn't affect register access. */ #define TRACE_CLK_EN (BIT(0)) #define TRACE_CLK_EN_M (TRACE_CLK_EN_V << TRACE_CLK_EN_S) diff --git a/components/soc/esp32c61/include/soc/trace_struct.h b/components/soc/esp32c61/register/soc/trace_struct.h similarity index 98% rename from components/soc/esp32c61/include/soc/trace_struct.h rename to components/soc/esp32c61/register/soc/trace_struct.h index a8337ed0fdb9..1b73fe2666f5 100644 --- a/components/soc/esp32c61/include/soc/trace_struct.h +++ b/components/soc/esp32c61/register/soc/trace_struct.h @@ -81,7 +81,7 @@ typedef union { uint32_t fifo_empty:1; /** work_status : RO; bitpos: [2:1]; default: 0; * Represent the state of the encoder: \\0: Idle state \\1: Working state\\ 2: Wait - * state becasue hart is halted or in reset \\3: Lost state\\ + * state because hart is halted or in reset \\3: Lost state\\ */ uint32_t work_status:2; uint32_t reserved_3:29; @@ -184,7 +184,7 @@ typedef union { */ uint32_t dm_trigger_ena:1; /** reset_ena : R/W; bitpos: [1]; default: 0; - * Configure whether to reset, when enabeld, if cpu have reset, the encoder will + * Configure whether to reset, when enabled, if cpu have reset, the encoder will * output a packet to report the address of the last instruction, and upon reset * deassertion, the encoder start again.\\0: Disable\\0: Enable\\ */ @@ -202,7 +202,7 @@ typedef union { */ uint32_t full_address:1; /** implicit_except : R/W; bitpos: [5]; default: 0; - * Configure whether or not enabel implicit exception mode. When enabled,, do not sent + * Configure whether or not enable implicit exception mode. When enabled,, do not sent * exception address, only exception cause in exception packets.\\1: enabled\\0: * disabled\\ */ @@ -381,7 +381,7 @@ typedef union { typedef union { struct { /** hburst : R/W; bitpos: [2:0]; default: 0; - * Configures the AHB burst mode. \\0: SIGNLE \\1: INCR(length not defined) \\2:INCR4 + * Configures the AHB burst mode. \\0: SINGLE \\1: INCR(length not defined) \\2:INCR4 * \\4:INCR8 \\Others:Invalid */ uint32_t hburst:3; @@ -404,7 +404,7 @@ typedef union { /** clk_en : R/W; bitpos: [0]; default: 1; * Configures register clock gating. \\0: Support clock only when the application * writes registers to save power. \\1:Always force the clock on for registers \\ This - * bit does't affect register access. + * bit doesn't affect register access. */ uint32_t clk_en:1; uint32_t reserved_1:31; diff --git a/components/soc/esp32c61/include/soc/uart_reg.h b/components/soc/esp32c61/register/soc/uart_reg.h similarity index 100% rename from components/soc/esp32c61/include/soc/uart_reg.h rename to components/soc/esp32c61/register/soc/uart_reg.h diff --git a/components/soc/esp32c61/include/soc/uart_struct.h b/components/soc/esp32c61/register/soc/uart_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/uart_struct.h rename to components/soc/esp32c61/register/soc/uart_struct.h diff --git a/components/soc/esp32c61/include/soc/usb_serial_jtag_reg.h b/components/soc/esp32c61/register/soc/usb_serial_jtag_reg.h similarity index 99% rename from components/soc/esp32c61/include/soc/usb_serial_jtag_reg.h rename to components/soc/esp32c61/register/soc/usb_serial_jtag_reg.h index e9e9b8337331..255d08ed4bb9 100644 --- a/components/soc/esp32c61/include/soc/usb_serial_jtag_reg.h +++ b/components/soc/esp32c61/register/soc/usb_serial_jtag_reg.h @@ -1144,7 +1144,7 @@ extern "C" { #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_RESET_RD_V 0x00000001U #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_RESET_RD_S 3 /** USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY : RO; bitpos: [4]; default: 1; - * CDC_ACM OUTOUT async FIFO empty signal in read clock domain. + * CDC_ACM OUTPUT async FIFO empty signal in read clock domain. */ #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY (BIT(4)) #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_M (USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_V << USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_S) diff --git a/components/soc/esp32c61/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32c61/register/soc/usb_serial_jtag_struct.h similarity index 100% rename from components/soc/esp32c61/include/soc/usb_serial_jtag_struct.h rename to components/soc/esp32c61/register/soc/usb_serial_jtag_struct.h diff --git a/components/soc/esp32c61/include/soc/xts_aes_reg.h b/components/soc/esp32c61/register/soc/xts_aes_reg.h similarity index 98% rename from components/soc/esp32c61/include/soc/xts_aes_reg.h rename to components/soc/esp32c61/register/soc/xts_aes_reg.h index 55e0e19beb1c..c3e08778d13a 100644 --- a/components/soc/esp32c61/include/soc/xts_aes_reg.h +++ b/components/soc/esp32c61/register/soc/xts_aes_reg.h @@ -32,7 +32,7 @@ s. Please do not use this field..*/ #define XTS_AES_DESTINATION_REG(i) (REG_SPI_MEM_BASE(i) + 0x344) /* XTS_AES_DESTINATION : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: This bit stores the destination parameter which will be used in manual encryptio +/*description: This bit stores the destination parameter which will be used in manual encryption n calculation. 0: flash(default), 1: psram(reserved). Only default value can be used..*/ #define XTS_AES_DESTINATION (BIT(0)) @@ -54,7 +54,7 @@ size parameter..*/ /* XTS_AES_TRIGGER : WT ;bitpos:[0] ;default: 1'b0 ; */ /*description: Set this bit to trigger the process of manual encryption calculation. This actio n should only be asserted when manual encryption status is 0. After this action, - manual encryption status becomes 1. After calculation is done, manual encryptio + manual encryption status becomes 1. After calculation is done, manual encryption n status becomes 2..*/ #define XTS_AES_TRIGGER (BIT(0)) #define XTS_AES_TRIGGER_M (BIT(0)) @@ -115,7 +115,7 @@ ing key 1..*/ #define XTS_AES_CRYPT_CALC_D_DPA_EN_V 0x1 #define XTS_AES_CRYPT_CALC_D_DPA_EN_S 3 /* XTS_AES_CRYPT_SECURITY_LEVEL : R/W ;bitpos:[2:0] ;default: 3'd7 ; */ -/*description: Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1- +/*description: Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1- 7: The bigger the number is, the more secure the cryption is. (Note that the per formance of cryption will decrease together with this number increasing).*/ #define XTS_AES_CRYPT_SECURITY_LEVEL 0x00000007 diff --git a/components/soc/esp32c61/spi_periph.c b/components/soc/esp32c61/spi_periph.c index dc15ae60eaa1..67fa9fdcb95d 100644 --- a/components/soc/esp32c61/spi_periph.c +++ b/components/soc/esp32c61/spi_periph.c @@ -13,29 +13,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { { // MSPI has dedicated iomux pins - .spiclk_out = -1, - .spiclk_in = -1, - .spid_out = -1, - .spiq_out = -1, - .spiwp_out = -1, - .spihd_out = -1, - .spid_in = -1, - .spiq_in = -1, - .spiwp_in = -1, - .spihd_in = -1, - .spics_out = {-1}, - .spics_in = -1, - .spiclk_iomux_pin = -1, - .spid_iomux_pin = -1, - .spiq_iomux_pin = -1, - .spiwp_iomux_pin = -1, - .spihd_iomux_pin = -1, - .spics0_iomux_pin = -1, - .irq = -1, - .irq_dma = -1, - .module = -1, - .hw = NULL, - .func = -1, }, { .spiclk_out = FSPICLK_OUT_IDX, .spiclk_in = FSPICLK_IN_IDX, @@ -57,8 +34,50 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, .irq = ETS_GPSPI2_INTR_SOURCE, .irq_dma = -1, - .module = -1, .hw = &GPSPI2, .func = SPI2_FUNC_NUM, }, }; + +/** + * Backup registers in Light sleep: (total cnt 12) + * + * cmd + * addr + * ctrl + * clock + * user + * user1 + * user2 + * ms_dlen + * misc + * dma_conf + * dma_int_ena + * slave + */ +#define SPI_RETENTION_REGS_CNT 12 +static const uint32_t spi_regs_map[4] = {0x31ff, 0x1000000, 0x0, 0x0}; +#define SPI_REG_RETENTION_ENTRIES(num) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GPSPI_LINK(0), \ + REG_SPI_BASE(num), REG_SPI_BASE(num), \ + SPI_RETENTION_REGS_CNT, 0, 0, \ + spi_regs_map[0], spi_regs_map[1], \ + spi_regs_map[2], spi_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + /* Additional interrupt setting is required by idf SPI drivers after register recovered */ \ + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_GPSPI_LINK(1), \ + SPI_DMA_INT_SET_REG(num), \ + SPI_TRANS_DONE_INT_SET | SPI_DMA_SEG_TRANS_DONE_INT_SET , \ + UINT32_MAX, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t spi2_regs_retention[] = SPI_REG_RETENTION_ENTRIES(2); // '2' for GPSPI2 + +const spi_reg_retention_info_t spi_reg_retention_info[SOC_SPI_PERIPH_NUM - 1] = { // '-1' to except mspi + { + .module_id = SLEEP_RETENTION_MODULE_GPSPI2, + .entry_array = spi2_regs_retention, + .array_size = ARRAY_SIZE(spi2_regs_retention), + }, +}; diff --git a/components/soc/esp32c61/uart_periph.c b/components/soc/esp32c61/uart_periph.c index be396c4321f5..a4e8c5084117 100644 --- a/components/soc/esp32c61/uart_periph.c +++ b/components/soc/esp32c61/uart_periph.c @@ -150,10 +150,12 @@ static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTI const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { [0] = { + .module = SLEEP_RETENTION_MODULE_UART0, .regdma_entry_array = uart0_regdma_entries, .array_size = ARRAY_SIZE(uart0_regdma_entries), }, [1] = { + .module = SLEEP_RETENTION_MODULE_UART1, .regdma_entry_array = uart1_regdma_entries, .array_size = ARRAY_SIZE(uart1_regdma_entries), }, diff --git a/components/soc/esp32h2/etm_periph.c b/components/soc/esp32h2/etm_periph.c new file mode 100644 index 000000000000..7b268c443a55 --- /dev/null +++ b/components/soc/esp32h2/etm_periph.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/etm_periph.h" +#include "soc/soc_etm_reg.h" + +/** + * ETM Registers to be saved during sleep retention + * - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG +*/ +#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1) + +static const regdma_entries_config_t etm_regdma_entries[] = { + // backup stage: save the status of enabled channels + // restore stage: store the enabled channels + [0] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00), + SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, + [1] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01), + SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [2] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02), + SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0), + .owner = ENTRY(0) | ENTRY(2), + }, +}; + +const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { + [0] = { + .module = SLEEP_RETENTION_MODULE_ETM0, + .regdma_entry_array = etm_regdma_entries, + .array_size = ARRAY_SIZE(etm_regdma_entries) + }, +}; diff --git a/components/soc/esp32h2/i2c_periph.c b/components/soc/esp32h2/i2c_periph.c index f1fd089056a6..5afb3995eb3a 100644 --- a/components/soc/esp32h2/i2c_periph.c +++ b/components/soc/esp32h2/i2c_periph.c @@ -47,7 +47,7 @@ static const regdma_entries_config_t i2c0_regs_retention[] = { [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(0), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \ .owner = ENTRY(0) | ENTRY(2) }, \ [2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(0), 0x0, I2C_FSM_RST_M, 1, 0), \ - .owner = ENTRY(0) | ENTRY(2) }, \ + .owner = ENTRY(0) | ENTRY(2) }, \ [3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(0), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \ .owner = ENTRY(0) | ENTRY(2) }, \ [4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(0), 0x0, I2C_CONF_UPGATE_M, 1, 0), \ @@ -71,6 +71,6 @@ static const regdma_entries_config_t i2c1_regs_retention[] = { }; const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM] = { - {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention)}, - {i2c1_regs_retention, ARRAY_SIZE(i2c1_regs_retention)}, + {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention), SLEEP_RETENTION_MODULE_I2C0}, + {i2c1_regs_retention, ARRAY_SIZE(i2c1_regs_retention), SLEEP_RETENTION_MODULE_I2C1}, }; diff --git a/components/soc/esp32h2/i2s_periph.c b/components/soc/esp32h2/i2s_periph.c index cf70f2cb946c..818b4e1080a2 100644 --- a/components/soc/esp32h2/i2s_periph.c +++ b/components/soc/esp32h2/i2s_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/i2s_periph.h" +#include "soc/i2s_reg.h" #include "soc/gpio_sig_map.h" /* @@ -28,7 +29,44 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_out_sig = I2SO_SD_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, - .irq = ETS_I2S1_INTR_SOURCE, - .module = PERIPH_I2S1_MODULE, + .irq = ETS_I2S0_INTR_SOURCE, } }; + +/** + * I2S Registers to be saved during sleep retention + * - I2S_RX_CONF_REG + * - I2S_TX_CONF_REG + * - I2S_RX_CONF1_REG + * - I2S_TX_CONF1_REG + * - I2S_TX_PCM2PDM_CONF_REG + * - I2S_TX_PCM2PDM_CONF1_REG + * - I2S_RX_TDM_CTRL_REG + * - I2S_TX_TDM_CTRL_REG + * - I2S_RXEOF_NUM_REG + * - I2S_ETM_CONF_REG +*/ +#define I2S_RETENTION_REGS_CNT 10 +#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG +static const uint32_t i2s_regs_map[4] = {0x12330f, 0x0, 0x0, 0x0}; +#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \ + /* Save/restore the register values */ \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \ + REGDMA_I2S_LINK(0x00), \ + I2S_RETENTION_REGS_BASE(i2s_port), \ + I2S_RETENTION_REGS_BASE(i2s_port), \ + I2S_RETENTION_REGS_CNT, 0, 0, \ + i2s_regs_map[0], i2s_regs_map[1], \ + i2s_regs_map[2], i2s_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2)}, \ +}; + +static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(0); + +const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = { + [0] = { + .retention_module = SLEEP_RETENTION_MODULE_I2S0, + .entry_array = i2s0_regs_retention, + .array_size = ARRAY_SIZE(i2s0_regs_retention) + }, +}; diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index f66714fbaea0..f655023a994c 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -467,6 +467,10 @@ config SOC_ETM_CHANNELS_PER_GROUP int default 50 +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_GPIO_PORT int default 1 @@ -675,6 +679,10 @@ config SOC_I2S_TDM_FULL_DATA_WIDTH bool default y +config SOC_I2S_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK bool default y @@ -683,6 +691,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 6 @@ -707,6 +719,10 @@ config SOC_LEDC_FADE_PARAMS_BIT_WIDTH int default 10 +config SOC_LEDC_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED bool default n @@ -747,6 +763,10 @@ config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE bool default y +config SOC_PCNT_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_RMT_GROUPS int default 1 @@ -895,6 +915,10 @@ config SOC_PARLIO_TRANS_BIT_ALIGN bool default y +config SOC_PARLIO_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MPI_MEM_BLOCKS_NUM int default 4 @@ -983,6 +1007,10 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool default y +config SOC_SPI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_SPI_SUPPORT_CLK_XTAL bool default y @@ -1167,6 +1195,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS bool default y +config SOC_TWAI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_EFUSE_DIS_PAD_JTAG bool default y @@ -1415,6 +1447,14 @@ config SOC_TEMPERATURE_SENSOR_SUPPORT_ETM bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + bool + default y + +config SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN + bool + default y + config SOC_RNG_CLOCK_IS_INDEPENDENT bool default y @@ -1450,3 +1490,7 @@ config SOC_BLE_MULTI_CONN_OPTIMIZATION config SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED bool default y + +config SOC_DEBUG_HAVE_OCD_STUB_BINS + bool + default y diff --git a/components/soc/esp32h2/include/soc/dport_access.h b/components/soc/esp32h2/include/soc/dport_access.h index bc42aa9fecce..70f97e86b482 100644 --- a/components/soc/esp32h2/include/soc/dport_access.h +++ b/components/soc/esp32h2/include/soc/dport_access.h @@ -7,8 +7,7 @@ #pragma once #include -#include "soc.h" -#include "uart_reg.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32h2/include/soc/interrupt_reg.h b/components/soc/esp32h2/include/soc/interrupt_reg.h index 1eb4721c8403..4faef7949b9a 100644 --- a/components/soc/esp32h2/include/soc/interrupt_reg.h +++ b/components/soc/esp32h2/include/soc/interrupt_reg.h @@ -5,8 +5,8 @@ */ #pragma once -#include "interrupt_matrix_reg.h" -#include "plic_reg.h" +#include "soc/interrupt_matrix_reg.h" +#include "soc/plic_reg.h" #include "soc/soc_caps.h" #define INTERRUPT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4) diff --git a/components/soc/esp32h2/include/soc/interrupts.h b/components/soc/esp32h2/include/soc/interrupts.h index cac8f027768b..491d0df35127 100644 --- a/components/soc/esp32h2/include/soc/interrupts.h +++ b/components/soc/esp32h2/include/soc/interrupts.h @@ -46,7 +46,7 @@ typedef enum { ETS_HP_APM_M2_INTR_SOURCE, ETS_HP_APM_M3_INTR_SOURCE, ETS_MSPI_INTR_SOURCE, - ETS_I2S1_INTR_SOURCE, /**< interrupt of I2S1, level*/ + ETS_I2S0_INTR_SOURCE, /**< interrupt of I2S0, level*/ ETS_UHCI0_INTR_SOURCE, /**< interrupt of UHCI0, level*/ ETS_UART0_INTR_SOURCE, /**< interrupt of UART0, level*/ ETS_UART1_INTR_SOURCE, /**< interrupt of UART1, level*/ diff --git a/components/soc/esp32h2/include/soc/periph_defs.h b/components/soc/esp32h2/include/soc/periph_defs.h index ea39288868ad..8c8477c51cc2 100644 --- a/components/soc/esp32h2/include/soc/periph_defs.h +++ b/components/soc/esp32h2/include/soc/periph_defs.h @@ -19,7 +19,7 @@ typedef enum { PERIPH_USB_DEVICE_MODULE, PERIPH_I2C0_MODULE, PERIPH_I2C1_MODULE, - PERIPH_I2S1_MODULE, + PERIPH_I2S0_MODULE, PERIPH_TIMG0_MODULE, PERIPH_TIMG1_MODULE, PERIPH_UHCI0_MODULE, diff --git a/components/soc/esp32h2/include/soc/regi2c_brownout.h b/components/soc/esp32h2/include/soc/regi2c_brownout.h index 9daf67f093b3..0d2caf531c15 100644 --- a/components/soc/esp32h2/include/soc/regi2c_brownout.h +++ b/components/soc/esp32h2/include/soc/regi2c_brownout.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,6 +44,10 @@ #define I2C_PMU_OR_DREFH_VDDA_MSB 7 #define I2C_PMU_OR_DREFH_VDDA_LSB 5 -#define I2C_BOD_THRESHOLD I2C_PMU_OR_DREFL_VDDA -#define I2C_BOD_THRESHOLD_MSB I2C_PMU_OR_DREFL_VDDA_MSB -#define I2C_BOD_THRESHOLD_LSB I2C_PMU_OR_DREFL_VDDA_LSB +#define I2C_BOD_THRESHOLD_L I2C_PMU_OR_DREFL_VDDA +#define I2C_BOD_THRESHOLD_L_MSB I2C_PMU_OR_DREFL_VDDA_MSB +#define I2C_BOD_THRESHOLD_L_LSB I2C_PMU_OR_DREFL_VDDA_LSB + +#define I2C_BOD_THRESHOLD_H I2C_PMU_OR_DREFH_VDDA +#define I2C_BOD_THRESHOLD_H_MSB I2C_PMU_OR_DREFH_VDDA_MSB +#define I2C_BOD_THRESHOLD_H_LSB I2C_PMU_OR_DREFH_VDDA_LSB diff --git a/components/soc/esp32h2/include/soc/retention_periph_defs.h b/components/soc/esp32h2/include/soc/retention_periph_defs.h index 9c8ea0ea0570..a6c0bb37ee35 100644 --- a/components/soc/esp32h2/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h2/include/soc/retention_periph_defs.h @@ -15,6 +15,7 @@ extern "C" { typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_MIN = 0, + SLEEP_RETENTION_MODULE_NULL = SLEEP_RETENTION_MODULE_MIN, /* This module is for all peripherals that can't survive from PD_TOP to call init only. Shouldn't have any dependency. */ /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2, @@ -37,6 +38,14 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_RMT0 = 14, SLEEP_RETENTION_MODULE_UART0 = 15, SLEEP_RETENTION_MODULE_UART1 = 16, + SLEEP_RETENTION_MODULE_I2S0 = 17, + SLEEP_RETENTION_MODULE_ETM0 = 18, + SLEEP_RETENTION_MODULE_TEMP_SENSOR = 19, + SLEEP_RETENTION_MODULE_TWAI0 = 20, + SLEEP_RETENTION_MODULE_PARLIO0 = 21, + SLEEP_RETENTION_MODULE_GPSPI2 = 22, + SLEEP_RETENTION_MODULE_LEDC = 23, + SLEEP_RETENTION_MODULE_PCNT0 = 24, /* Modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BLE_MAC = 28, @@ -46,6 +55,8 @@ typedef enum periph_retention_module { } periph_retention_module_t; typedef enum periph_retention_module_bitmap { + SLEEP_RETENTION_MODULE_BM_NULL = BIT(SLEEP_RETENTION_MODULE_NULL), + /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM), @@ -68,6 +79,14 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0), SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0), SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), + SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), + SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), + SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR), + SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0), + SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0), + SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2), + SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC), + SLEEP_RETENTION_MODULE_BM_PCNT0 = BIT(SLEEP_RETENTION_MODULE_PCNT0), /* modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC), SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB), @@ -89,6 +108,15 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_RMT0 \ | SLEEP_RETENTION_MODULE_BM_UART0 \ | SLEEP_RETENTION_MODULE_BM_UART1 \ + | SLEEP_RETENTION_MODULE_BM_I2S0 \ + | SLEEP_RETENTION_MODULE_BM_ETM0 \ + | SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \ + | SLEEP_RETENTION_MODULE_BM_TWAI0 \ + | SLEEP_RETENTION_MODULE_BM_PARLIO0 \ + | SLEEP_RETENTION_MODULE_BM_GPSPI2 \ + | SLEEP_RETENTION_MODULE_BM_LEDC \ + | SLEEP_RETENTION_MODULE_BM_PCNT0 \ + | SLEEP_RETENTION_MODULE_BM_NULL \ ) #ifdef __cplusplus diff --git a/components/soc/esp32h2/include/soc/soc.h b/components/soc/esp32h2/include/soc/soc.h index f3d2b2a90417..b35b9cc15fa0 100644 --- a/components/soc/esp32h2/include/soc/soc.h +++ b/components/soc/esp32h2/include/soc/soc.h @@ -12,7 +12,7 @@ #endif #include "esp_bit_defs.h" -#include "reg_base.h" +#include "soc/reg_base.h" #define PRO_CPU_NUM (0) diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 8831aa1a3cd7..26252ef134d1 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -181,6 +181,7 @@ /*-------------------------- ETM CAPS --------------------------------------*/ #define SOC_ETM_GROUPS 1U // Number of ETM groups #define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-H2 has 1 GPIO peripheral @@ -274,16 +275,19 @@ #define SOC_I2S_PDM_MAX_TX_LINES (2) #define SOC_I2S_SUPPORTS_TDM (1) #define SOC_I2S_TDM_FULL_DATA_WIDTH (1) /*!< No limitation to data bit width when using multiple slots */ +#define SOC_I2S_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up I2S registers before sleep */ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (6) #define SOC_LEDC_TIMER_BIT_WIDTH (20) #define SOC_LEDC_SUPPORT_FADE_STOP (1) #define SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED (1) #define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16) #define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10) +#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- MPU CAPS ----------------------------------------*/ #define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED 0 @@ -298,6 +302,7 @@ #define SOC_PCNT_CHANNELS_PER_UNIT 2 #define SOC_PCNT_THRES_POINT_PER_UNIT 2 #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 +#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ @@ -344,6 +349,7 @@ #define SOC_PARLIO_RX_CLK_SUPPORT_GATING 1 /*!< Support gating RX clock */ #define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */ #define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */ +#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */ /*--------------------------- MPI CAPS ---------------------------------------*/ #define SOC_MPI_MEM_BLOCKS_NUM (4) @@ -390,6 +396,7 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 +#define SOC_SPI_SUPPORT_SLEEP_RETENTION 1 #define SOC_SPI_SUPPORT_CLK_XTAL 1 #define SOC_SPI_SUPPORT_CLK_PLL_F48M 1 #define SOC_SPI_SUPPORT_CLK_RC_FAST 1 @@ -451,11 +458,12 @@ #define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- TWAI CAPS ---------------------------------------*/ -#define SOC_TWAI_CONTROLLER_NUM 1UL -#define SOC_TWAI_CLK_SUPPORT_XTAL 1 -#define SOC_TWAI_BRP_MIN 2 -#define SOC_TWAI_BRP_MAX 32768 -#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_CONTROLLER_NUM 1UL +#define SOC_TWAI_CLK_SUPPORT_XTAL 1 +#define SOC_TWAI_BRP_MIN 2 +#define SOC_TWAI_BRP_MAX 32768 +#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- eFuse CAPS----------------------------*/ #define SOC_EFUSE_DIS_PAD_JTAG 1 @@ -557,6 +565,8 @@ #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) #define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_ETM (1) +#define SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION (1) +#define SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN (1) /*--------------------------------- RNG CAPS --------------------------------------------*/ #define SOC_RNG_CLOCK_IS_INDEPENDENT (1) @@ -570,3 +580,6 @@ #define SOC_BLE_POWER_CONTROL_SUPPORTED (1) /*!< Support Bluetooth Power Control */ #define SOC_BLE_MULTI_CONN_OPTIMIZATION (1) /*!< Support multiple connections optimization */ #define SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED (1) /*!< Support For BLE Periodic Adv Enhancements */ + +/*------------------------------------- DEBUG CAPS -------------------------------------*/ +#define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) diff --git a/components/soc/esp32h2/include/soc/system_reg.h b/components/soc/esp32h2/include/soc/system_reg.h index 6a52d2da700b..b2cb6089eecc 100644 --- a/components/soc/esp32h2/include/soc/system_reg.h +++ b/components/soc/esp32h2/include/soc/system_reg.h @@ -5,7 +5,7 @@ */ #include "soc/hp_system_reg.h" -#include "intpri_reg.h" +#include "soc/intpri_reg.h" // ESP32H2-TODO : TODO: IDF-5720 #define SYSTEM_CPU_INTR_FROM_CPU_0_REG INTPRI_CPU_INTR_FROM_CPU_0_REG diff --git a/components/soc/esp32h2/interrupts.c b/components/soc/esp32h2/interrupts.c index c64a2247adca..68c6cd48bccb 100644 --- a/components/soc/esp32h2/interrupts.c +++ b/components/soc/esp32h2/interrupts.c @@ -38,7 +38,7 @@ const char *const esp_isr_names[] = { [28] = "HP_APM_M2", [29] = "HP_APM_M3", [30] = "MSPI", - [31] = "I2S1", + [31] = "I2S0", [32] = "UHCI0", [33] = "UART0", [34] = "UART1", diff --git a/components/soc/esp32h2/ledc_periph.c b/components/soc/esp32h2/ledc_periph.c index b150f9bc991e..e20f002e5a30 100644 --- a/components/soc/esp32h2/ledc_periph.c +++ b/components/soc/esp32h2/ledc_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,3 +15,141 @@ const ledc_signal_conn_t ledc_periph_signal[1] = { .sig_out0_idx = LEDC_LS_SIG_OUT0_IDX, } }; + +/** + * LEDC registers to be saved for sleep retention + * + * channel: + * LEDC_CHx_CONF0_REG, LEDC_CHx_HPOINT_REG, LEDC_CHx_DUTY_R_REG -> LEDC_CHx_DUTY_REG, + * + * timer: + * LEDC_TIMERn_CONF_REG, LEDC_TIMERn_CMP_REG, + * + * common: + * LEDC_INT_ENA_REG, + * LEDC_EVT_TASK_EN0_REG, LEDC_EVT_TASK_EN1_REG, LEDC_EVT_TASK_EN2_REG, + * LEDC_CONF_REG, + * + * Note 1: Gamma feature is hard to do hardware retention, will consider to use software to do the backup and restore. + * We won't start a fade automatically after wake-up. + * Instead, we will only start a PWM with a fixed duty cycle, the same value as before entering the sleep. + * + * Note 2: For timer/channel registers to get synced, update bits need to be set + * + * Note 3: Retention backup/restore does not rely on LEDC function clock enabled + */ +#define LEDC_COMMON_RETENTION_REGS_CNT 5 +#define LEDC_COMMON_RETENTION_REGS_BASE (DR_REG_LEDC_BASE + 0xc8) +static const uint32_t ledc_common_regs_map[4] = {0x1, 0x1c00000, 0x400, 0x0}; +static const regdma_entries_config_t ledc_common_regdma_entries[] = { + // If a fade is in process, the DUTY_CHNG_END_CHx intr bit is enabled, however, we don't want it to be restored after wake-up (no fade after wake-up). + // Therefore, we can set it to 0 before backup the LEDC_INT_ENA_REG. + [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x00), + LEDC_INT_ENA_REG, 0, + (LEDC_DUTY_CHNG_END_CH0_INT_ENA_M | LEDC_DUTY_CHNG_END_CH1_INT_ENA_M | LEDC_DUTY_CHNG_END_CH2_INT_ENA_M | LEDC_DUTY_CHNG_END_CH3_INT_ENA_M | LEDC_DUTY_CHNG_END_CH4_INT_ENA_M | LEDC_DUTY_CHNG_END_CH5_INT_ENA_M), 0, 1), + .owner = LEDC_RETENTION_ENTRY }, + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x01), + LEDC_COMMON_RETENTION_REGS_BASE, LEDC_COMMON_RETENTION_REGS_BASE, + LEDC_COMMON_RETENTION_REGS_CNT, 0, 0, + ledc_common_regs_map[0], ledc_common_regs_map[1], + ledc_common_regs_map[2], ledc_common_regs_map[3]), + .owner = LEDC_RETENTION_ENTRY }, +}; + +#define LEDC_TIMER_RETENTION_ENTRIES(timer) { \ + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_CONF_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_TIMER##timer##_CMP_REG, LEDC_TIMER##timer##_CMP_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_PARA_UP, \ + LEDC_TIMER##timer##_PARA_UP_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +#define LEDC_CHANNEL_RETENTION_REGS_CNT 2 +static const uint32_t ledc_channel_regs_map[4] = {0x3, 0x0, 0x0, 0x0}; +#define LEDC_CHANNEL_RETENTION_ENTRIES(chan) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_CH##chan##_CONF0_REG, LEDC_CH##chan##_CONF0_REG, \ + LEDC_CHANNEL_RETENTION_REGS_CNT, 0, 0, \ + ledc_channel_regs_map[0], ledc_channel_regs_map[1], \ + ledc_channel_regs_map[2], ledc_channel_regs_map[3]), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_CH##chan##_DUTY_R_REG, LEDC_CH##chan##_DUTY_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_CH##chan##_CONF1_REG, LEDC_DUTY_START_CH##chan, \ + LEDC_DUTY_START_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x03), \ + LEDC_CH##chan##_CONF0_REG, LEDC_PARA_UP_CH##chan, \ + LEDC_PARA_UP_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +static const regdma_entries_config_t ledc_timer0_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_timer1_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_timer2_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_timer3_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(3); + +static const regdma_entries_config_t ledc_channel0_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_channel1_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_channel2_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_channel3_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(3); +static const regdma_entries_config_t ledc_channel4_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(4); +static const regdma_entries_config_t ledc_channel5_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(5); + +const ledc_reg_retention_info_t ledc_reg_retention_info = { + .common = { + .regdma_entry_array = ledc_common_regdma_entries, + .array_size = ARRAY_SIZE(ledc_common_regdma_entries), + }, + .timer[0] = { + .regdma_entry_array = ledc_timer0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer0_regdma_entries), + }, + .timer[1] = { + .regdma_entry_array = ledc_timer1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer1_regdma_entries), + }, + .timer[2] = { + .regdma_entry_array = ledc_timer2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer2_regdma_entries), + }, + .timer[3] = { + .regdma_entry_array = ledc_timer3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer3_regdma_entries), + }, + .channel[0] = { + .regdma_entry_array = ledc_channel0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel0_regdma_entries), + }, + .channel[1] = { + .regdma_entry_array = ledc_channel1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel1_regdma_entries), + }, + .channel[2] = { + .regdma_entry_array = ledc_channel2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel2_regdma_entries), + }, + .channel[3] = { + .regdma_entry_array = ledc_channel3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel3_regdma_entries), + }, + .channel[4] = { + .regdma_entry_array = ledc_channel4_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel4_regdma_entries), + }, + .channel[5] = { + .regdma_entry_array = ledc_channel5_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel5_regdma_entries), + }, + .module_id = SLEEP_RETENTION_MODULE_LEDC, +}; diff --git a/components/soc/esp32h2/parlio_periph.c b/components/soc/esp32h2/parlio_periph.c index 6cc86f13cbf5..bd17bfceb119 100644 --- a/components/soc/esp32h2/parlio_periph.c +++ b/components/soc/esp32h2/parlio_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,3 +48,31 @@ const parlio_signal_conn_t parlio_periph_signals = { }, }, }; + +/** + * PARLIO Registers to be saved during sleep retention + * - Tx Configuration registers, e.g.: PARL_IO_TX_DATA_CFG_REG, PARL_IO_TX_GENRL_CFG_REG + * - Rx Configuration registers, e.g.: PARL_IO_RX_MODE_CFG_REG, PARL_IO_RX_DATA_CFG_REG, PARL_IO_RX_GENRL_CFG_REG + * - CLK Configuration registers, e.g.: PARL_IO_RX_CLK_CFG_REG, PARL_IO_TX_CLK_CFG_REG + * - Interrupt enable registers, e.g.: PARL_IO_INT_ENA_REG +*/ +#define PARLIO_RETENTION_REGS_CNT 8 +#define PARLIO_RETENTION_REGS_BASE (DR_REG_PARL_IO_BASE + 0x0) +static const uint32_t parlio_regs_map[4] = {0x60457, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t parlio_regs_retention[] = { + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PARLIO_LINK(0x00), \ + PARLIO_RETENTION_REGS_BASE, PARLIO_RETENTION_REGS_BASE, \ + PARLIO_RETENTION_REGS_CNT, 0, 0, \ + parlio_regs_map[0], parlio_regs_map[1], \ + parlio_regs_map[2], parlio_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; +const parlio_reg_retention_info_t parlio_reg_retention_info[SOC_PARLIO_GROUPS] = { + [0] = { + .regdma_entry_array = parlio_regs_retention, + .array_size = ARRAY_SIZE(parlio_regs_retention), + .retention_module = SLEEP_RETENTION_MODULE_PARLIO0 + }, +}; diff --git a/components/soc/esp32h2/pcnt_periph.c b/components/soc/esp32h2/pcnt_periph.c index b2b440245b75..14c52fc0d623 100644 --- a/components/soc/esp32h2/pcnt_periph.c +++ b/components/soc/esp32h2/pcnt_periph.c @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/pcnt_periph.h" #include "soc/gpio_sig_map.h" +#include "soc/pcnt_reg.h" const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { @@ -64,3 +65,30 @@ const pcnt_signal_conn_t pcnt_periph_signals = { } } }; + +/** + * PCNT Registers to be saved during sleep retention + * - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG... + * - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG +*/ +#define PCNT_RETENTION_REGS_CNT 14 +#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0) +static const uint32_t pcnt_regs_map[4] = {0x1040fff, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t pcnt_regs_retention[] = { + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \ + PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \ + PCNT_RETENTION_REGS_CNT, 0, 0, \ + pcnt_regs_map[0], pcnt_regs_map[1], \ + pcnt_regs_map[2], pcnt_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = { + [0] = { + .regdma_entry_array = pcnt_regs_retention, + .array_size = ARRAY_SIZE(pcnt_regs_retention), + .retention_module = SLEEP_RETENTION_MODULE_PCNT0 + }, +}; diff --git a/components/soc/esp32h2/register/soc/.gitkeep b/components/soc/esp32h2/register/soc/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/soc/esp32h2/include/soc/aes_reg.h b/components/soc/esp32h2/register/soc/aes_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/aes_reg.h rename to components/soc/esp32h2/register/soc/aes_reg.h diff --git a/components/soc/esp32h2/include/soc/aes_struct.h b/components/soc/esp32h2/register/soc/aes_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/aes_struct.h rename to components/soc/esp32h2/register/soc/aes_struct.h diff --git a/components/soc/esp32h2/include/soc/apb_saradc_reg.h b/components/soc/esp32h2/register/soc/apb_saradc_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/apb_saradc_reg.h rename to components/soc/esp32h2/register/soc/apb_saradc_reg.h diff --git a/components/soc/esp32h2/include/soc/apb_saradc_struct.h b/components/soc/esp32h2/register/soc/apb_saradc_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/apb_saradc_struct.h rename to components/soc/esp32h2/register/soc/apb_saradc_struct.h diff --git a/components/soc/esp32h2/include/soc/assist_debug_reg.h b/components/soc/esp32h2/register/soc/assist_debug_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/assist_debug_reg.h rename to components/soc/esp32h2/register/soc/assist_debug_reg.h index 8e0426dc6f57..d2b947d9466a 100644 --- a/components/soc/esp32h2/include/soc/assist_debug_reg.h +++ b/components/soc/esp32h2/register/soc/assist_debug_reg.h @@ -92,7 +92,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_ENA_V 0x00000001U #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_ENA_S 10 /** ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor enbale + * DBUS busy monitor enable */ #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA (BIT(11)) #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_M (ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_V << ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_ENA_S) @@ -270,7 +270,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_RLS_V 0x00000001U #define ASSIST_DEBUG_CORE_0_IRAM0_EXCEPTION_MONITOR_RLS_S 10 /** ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor interrupt enbale + * DBUS busy monitor interrupt enable */ #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS (BIT(11)) #define ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS_M (ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS_V << ASSIST_DEBUG_CORE_0_DRAM0_EXCEPTION_MONITOR_RLS_S) @@ -491,7 +491,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_SP_MIN_REG (DR_REG_ASSIST_DEBUG_BASE + 0x38) /** ASSIST_DEBUG_CORE_0_SP_MIN : R/W; bitpos: [31:0]; default: 0; - * core0 sp region configuration regsiter + * core0 sp region configuration register */ #define ASSIST_DEBUG_CORE_0_SP_MIN 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_0_SP_MIN_M (ASSIST_DEBUG_CORE_0_SP_MIN_V << ASSIST_DEBUG_CORE_0_SP_MIN_S) @@ -515,7 +515,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_SP_PC_REG (DR_REG_ASSIST_DEBUG_BASE + 0x40) /** ASSIST_DEBUG_CORE_0_SP_PC : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ #define ASSIST_DEBUG_CORE_0_SP_PC 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_0_SP_PC_M (ASSIST_DEBUG_CORE_0_SP_PC_V << ASSIST_DEBUG_CORE_0_SP_PC_S) @@ -542,7 +542,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGEN_S 1 /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG (DR_REG_ASSIST_DEBUG_BASE + 0x48) /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC : RO; bitpos: [31:0]; default: 0; @@ -554,7 +554,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_S 0 /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP_REG (DR_REG_ASSIST_DEBUG_BASE + 0x4c) /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP : RO; bitpos: [31:0]; default: 0; diff --git a/components/soc/esp32h2/include/soc/assist_debug_struct.h b/components/soc/esp32h2/register/soc/assist_debug_struct.h similarity index 98% rename from components/soc/esp32h2/include/soc/assist_debug_struct.h rename to components/soc/esp32h2/register/soc/assist_debug_struct.h index c03f57922921..62323e8dbc1c 100644 --- a/components/soc/esp32h2/include/soc/assist_debug_struct.h +++ b/components/soc/esp32h2/register/soc/assist_debug_struct.h @@ -61,7 +61,7 @@ typedef union { */ uint32_t core_0_iram0_exception_monitor_ena:1; /** core_0_dram0_exception_monitor_ena : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor enbale + * DBUS busy monitor enable */ uint32_t core_0_dram0_exception_monitor_ena:1; uint32_t reserved_12:20; @@ -205,7 +205,7 @@ typedef union { typedef union { struct { /** core_0_sp_min : R/W; bitpos: [31:0]; default: 0; - * core0 sp region configuration regsiter + * core0 sp region configuration register */ uint32_t core_0_sp_min:32; }; @@ -231,7 +231,7 @@ typedef union { typedef union { struct { /** core_0_sp_pc : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ uint32_t core_0_sp_pc:32; }; @@ -348,7 +348,7 @@ typedef union { */ uint32_t core_0_iram0_exception_monitor_rls:1; /** core_0_dram0_exception_monitor_rls : R/W; bitpos: [11]; default: 0; - * DBUS busy monitor interrupt enbale + * DBUS busy monitor interrupt enable */ uint32_t core_0_dram0_exception_monitor_rls:1; uint32_t reserved_12:20; @@ -415,7 +415,7 @@ typedef union { } assist_debug_core_0_intr_clr_reg_t; -/** Group: pc reording configuration register */ +/** Group: pc recording configuration register */ /** Type of core_0_rcd_en register * record enable configuration register */ @@ -435,9 +435,9 @@ typedef union { } assist_debug_core_0_rcd_en_reg_t; -/** Group: pc reording status register */ +/** Group: pc recording status register */ /** Type of core_0_rcd_pdebugpc register - * record status regsiter + * record status register */ typedef union { struct { @@ -450,7 +450,7 @@ typedef union { } assist_debug_core_0_rcd_pdebugpc_reg_t; /** Type of core_0_rcd_pdebugsp register - * record status regsiter + * record status register */ typedef union { struct { @@ -463,7 +463,7 @@ typedef union { } assist_debug_core_0_rcd_pdebugsp_reg_t; -/** Group: exception monitor regsiter */ +/** Group: exception monitor register */ /** Type of core_0_iram0_exception_monitor_0 register * exception monitor status register0 */ diff --git a/components/soc/esp32h2/include/soc/cache_reg.h b/components/soc/esp32h2/register/soc/cache_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/cache_reg.h rename to components/soc/esp32h2/register/soc/cache_reg.h index d811eda10af9..30181edf326d 100644 --- a/components/soc/esp32h2/include/soc/cache_reg.h +++ b/components/soc/esp32h2/register/soc/cache_reg.h @@ -4185,7 +4185,7 @@ extern "C" { #define CACHE_L1_UNALLOCATE_BUFFER_CLEAR_REG (DR_REG_CACHE_BASE + 0x244) /** CACHE_L1_ICACHE0_UNALLOC_CLR : HRO; bitpos: [0]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache0 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_ICACHE0_UNALLOC_CLR (BIT(0)) #define CACHE_L1_ICACHE0_UNALLOC_CLR_M (CACHE_L1_ICACHE0_UNALLOC_CLR_V << CACHE_L1_ICACHE0_UNALLOC_CLR_S) @@ -4193,7 +4193,7 @@ extern "C" { #define CACHE_L1_ICACHE0_UNALLOC_CLR_S 0 /** CACHE_L1_ICACHE1_UNALLOC_CLR : HRO; bitpos: [1]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache1 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_ICACHE1_UNALLOC_CLR (BIT(1)) #define CACHE_L1_ICACHE1_UNALLOC_CLR_M (CACHE_L1_ICACHE1_UNALLOC_CLR_V << CACHE_L1_ICACHE1_UNALLOC_CLR_S) @@ -4215,7 +4215,7 @@ extern "C" { #define CACHE_L1_ICACHE3_UNALLOC_CLR_S 3 /** CACHE_L1_CACHE_UNALLOC_CLR : R/W; bitpos: [4]; default: 0; * The bit is used to clear the unallocate request buffer of l1 cache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_CACHE_UNALLOC_CLR (BIT(4)) #define CACHE_L1_CACHE_UNALLOC_CLR_M (CACHE_L1_CACHE_UNALLOC_CLR_V << CACHE_L1_CACHE_UNALLOC_CLR_S) @@ -6025,7 +6025,7 @@ extern "C" { #define CACHE_L2_UNALLOCATE_BUFFER_CLEAR_REG (DR_REG_CACHE_BASE + 0x390) /** CACHE_L2_CACHE_UNALLOC_CLR : HRO; bitpos: [5]; default: 0; * The bit is used to clear the unallocate request buffer of l2 icache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L2_CACHE_UNALLOC_CLR (BIT(5)) #define CACHE_L2_CACHE_UNALLOC_CLR_M (CACHE_L2_CACHE_UNALLOC_CLR_V << CACHE_L2_CACHE_UNALLOC_CLR_S) diff --git a/components/soc/esp32h2/include/soc/cache_struct.h b/components/soc/esp32h2/register/soc/cache_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/cache_struct.h rename to components/soc/esp32h2/register/soc/cache_struct.h index 7398f887ab67..32ec8a069c75 100644 --- a/components/soc/esp32h2/include/soc/cache_struct.h +++ b/components/soc/esp32h2/register/soc/cache_struct.h @@ -5115,12 +5115,12 @@ typedef union { struct { /** l1_icache0_unalloc_clr : HRO; bitpos: [0]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache0 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_icache0_unalloc_clr:1; /** l1_icache1_unalloc_clr : HRO; bitpos: [1]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache1 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_icache1_unalloc_clr:1; /** l1_icache2_unalloc_clr : HRO; bitpos: [2]; default: 0; @@ -5133,7 +5133,7 @@ typedef union { uint32_t l1_icache3_unalloc_clr:1; /** l1_cache_unalloc_clr : R/W; bitpos: [4]; default: 0; * The bit is used to clear the unallocate request buffer of l1 cache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_cache_unalloc_clr:1; uint32_t reserved_5:27; @@ -5149,7 +5149,7 @@ typedef union { uint32_t reserved_0:5; /** l2_cache_unalloc_clr : HRO; bitpos: [5]; default: 0; * The bit is used to clear the unallocate request buffer of l2 icache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l2_cache_unalloc_clr:1; uint32_t reserved_6:26; diff --git a/components/soc/esp32h2/include/soc/clint_reg.h b/components/soc/esp32h2/register/soc/clint_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/clint_reg.h rename to components/soc/esp32h2/register/soc/clint_reg.h diff --git a/components/soc/esp32h2/include/soc/ds_reg.h b/components/soc/esp32h2/register/soc/ds_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/ds_reg.h rename to components/soc/esp32h2/register/soc/ds_reg.h diff --git a/components/soc/esp32h2/include/soc/ds_struct.h b/components/soc/esp32h2/register/soc/ds_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/ds_struct.h rename to components/soc/esp32h2/register/soc/ds_struct.h diff --git a/components/soc/esp32h2/include/soc/ecc_mult_reg.h b/components/soc/esp32h2/register/soc/ecc_mult_reg.h similarity index 97% rename from components/soc/esp32h2/include/soc/ecc_mult_reg.h rename to components/soc/esp32h2/register/soc/ecc_mult_reg.h index 5d7fa6c1c30b..bd6084940fe0 100644 --- a/components/soc/esp32h2/include/soc/ecc_mult_reg.h +++ b/components/soc/esp32h2/register/soc/ecc_mult_reg.h @@ -64,7 +64,7 @@ extern "C" { */ #define ECC_MULT_CONF_REG (DR_REG_ECC_MULT_BASE + 0x1c) /** ECC_MULT_START : R/W/SC; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECC Accelerator. This bit will be self-cleared after + * Write 1 to start calculation of ECC Accelerator. This bit will be self-cleared after * the caculatrion is done. */ #define ECC_MULT_START (BIT(0)) @@ -97,7 +97,7 @@ extern "C" { * The work mode bits of ECC Accelerator. 0: Point Mult Mode. 1: Reserved. 2: Point * verification mode. 3: Point Verif+mult mode. 4: Jacobian Point Mult Mode. 5: Point * Add Mode. 6: Jacobian Point Verification Mode. 7: Point Verif + Jacobian Mult Mode. - * 8: mod addition. 9. mod substraction. 10: mod multiplication. 11: mod division. + * 8: mod addition. 9. mod subtraction. 10: mod multiplication. 11: mod division. */ #define ECC_MULT_WORK_MODE 0x0000000FU #define ECC_MULT_WORK_MODE_M (ECC_MULT_WORK_MODE_V << ECC_MULT_WORK_MODE_S) diff --git a/components/soc/esp32h2/include/soc/ecc_mult_struct.h b/components/soc/esp32h2/register/soc/ecc_mult_struct.h similarity index 96% rename from components/soc/esp32h2/include/soc/ecc_mult_struct.h rename to components/soc/esp32h2/register/soc/ecc_mult_struct.h index f1596693a8d0..a9f458c5d968 100644 --- a/components/soc/esp32h2/include/soc/ecc_mult_struct.h +++ b/components/soc/esp32h2/register/soc/ecc_mult_struct.h @@ -79,7 +79,7 @@ typedef union { typedef union { struct { /** start : R/W/SC; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECC Accelerator. This bit will be self-cleared after + * Write 1 to start calculation of ECC Accelerator. This bit will be self-cleared after * the caculatrion is done. */ uint32_t start:1; @@ -100,7 +100,7 @@ typedef union { * The work mode bits of ECC Accelerator. 0: Point Mult Mode. 1: Reserved. 2: Point * verification mode. 3: Point Verif+mult mode. 4: Jacobian Point Mult Mode. 5: Point * Add Mode. 6: Jacobian Point Verification Mode. 7: Point Verif + Jacobian Mult Mode. - * 8: mod addition. 9. mod substraction. 10: mod multiplication. 11: mod division. + * 8: mod addition. 9. mod subtraction. 10: mod multiplication. 11: mod division. */ uint32_t work_mode:4; /** security_mode : R/W; bitpos: [8]; default: 0; diff --git a/components/soc/esp32h2/include/soc/ecdsa_reg.h b/components/soc/esp32h2/register/soc/ecdsa_reg.h similarity index 97% rename from components/soc/esp32h2/include/soc/ecdsa_reg.h rename to components/soc/esp32h2/register/soc/ecdsa_reg.h index 62f2e1ad96d1..88f19ad16ce0 100644 --- a/components/soc/esp32h2/include/soc/ecdsa_reg.h +++ b/components/soc/esp32h2/register/soc/ecdsa_reg.h @@ -140,7 +140,7 @@ extern "C" { */ #define ECDSA_START_REG (DR_REG_ECDSA_BASE + 0x1c) /** ECDSA_START : WT; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECDSA Accelerator. This bit will be self-cleared + * Write 1 to start calculation of ECDSA Accelerator. This bit will be self-cleared * after configuration. */ #define ECDSA_START (BIT(0)) @@ -220,7 +220,7 @@ extern "C" { */ #define ECDSA_SHA_START_REG (DR_REG_ECDSA_BASE + 0x210) /** ECDSA_SHA_START : WT; bitpos: [0]; default: 0; - * Write 1 to start the first caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the first calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ #define ECDSA_SHA_START (BIT(0)) @@ -233,7 +233,7 @@ extern "C" { */ #define ECDSA_SHA_CONTINUE_REG (DR_REG_ECDSA_BASE + 0x214) /** ECDSA_SHA_CONTINUE : WT; bitpos: [0]; default: 0; - * Write 1 to start the latter caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the latter calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ #define ECDSA_SHA_CONTINUE (BIT(0)) diff --git a/components/soc/esp32h2/include/soc/ecdsa_struct.h b/components/soc/esp32h2/register/soc/ecdsa_struct.h similarity index 97% rename from components/soc/esp32h2/include/soc/ecdsa_struct.h rename to components/soc/esp32h2/register/soc/ecdsa_struct.h index dcdd806f8ff5..ca9076e5526c 100644 --- a/components/soc/esp32h2/include/soc/ecdsa_struct.h +++ b/components/soc/esp32h2/register/soc/ecdsa_struct.h @@ -48,7 +48,7 @@ typedef union { typedef union { struct { /** start : WT; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECDSA Accelerator. This bit will be self-cleared + * Write 1 to start calculation of ECDSA Accelerator. This bit will be self-cleared * after configuration. */ uint32_t start:1; @@ -214,7 +214,7 @@ typedef union { typedef union { struct { /** sha_start : WT; bitpos: [0]; default: 0; - * Write 1 to start the first caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the first calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ uint32_t sha_start:1; @@ -229,7 +229,7 @@ typedef union { typedef union { struct { /** sha_continue : WT; bitpos: [0]; default: 0; - * Write 1 to start the latter caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the latter calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ uint32_t sha_continue:1; diff --git a/components/soc/esp32h2/include/soc/efuse_reg.h b/components/soc/esp32h2/register/soc/efuse_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/efuse_reg.h rename to components/soc/esp32h2/register/soc/efuse_reg.h index 532514d58761..915c37d84817 100644 --- a/components/soc/esp32h2/include/soc/efuse_reg.h +++ b/components/soc/esp32h2/register/soc/efuse_reg.h @@ -7,7 +7,7 @@ #include #include "soc/soc.h" -#include "efuse_defs.h" +#include "soc/efuse_defs.h" #ifdef __cplusplus extern "C" { #endif @@ -261,14 +261,14 @@ extern "C" { #define EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_V 0x00000001U #define EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_S 20 /** EFUSE_USB_DREFH : RO; bitpos: [22:21]; default: 0; - * Represents the single-end input threhold vrefh, 1.76 V to 2 V with step of 80 mV. + * Represents the single-end input threshold vrefh, 1.76 V to 2 V with step of 80 mV. */ #define EFUSE_USB_DREFH 0x00000003U #define EFUSE_USB_DREFH_M (EFUSE_USB_DREFH_V << EFUSE_USB_DREFH_S) #define EFUSE_USB_DREFH_V 0x00000003U #define EFUSE_USB_DREFH_S 21 /** EFUSE_USB_DREFL : RO; bitpos: [24:23]; default: 0; - * Represents the single-end input threhold vrefl, 1.76 V to 2 V with step of 80 mV. + * Represents the single-end input threshold vrefl, 1.76 V to 2 V with step of 80 mV. */ #define EFUSE_USB_DREFL 0x00000003U #define EFUSE_USB_DREFL_M (EFUSE_USB_DREFL_V << EFUSE_USB_DREFL_S) @@ -2355,7 +2355,7 @@ extern "C" { #define EFUSE_CLK_EN_S 16 /** EFUSE_CONF_REG register - * eFuse operation mode configuraiton register + * eFuse operation mode configuration register */ #define EFUSE_CONF_REG (DR_REG_EFUSE_BASE + 0x1cc) /** EFUSE_OP_CODE : R/W; bitpos: [15:0]; default: 0; diff --git a/components/soc/esp32h2/include/soc/efuse_struct.h b/components/soc/esp32h2/register/soc/efuse_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/efuse_struct.h rename to components/soc/esp32h2/register/soc/efuse_struct.h index c64eaa140c8d..ab4c17e47501 100644 --- a/components/soc/esp32h2/include/soc/efuse_struct.h +++ b/components/soc/esp32h2/register/soc/efuse_struct.h @@ -236,11 +236,11 @@ typedef union { */ uint32_t dis_download_manual_encrypt:1; /** usb_drefh : RO; bitpos: [22:21]; default: 0; - * Represents the single-end input threhold vrefh, 1.76 V to 2 V with step of 80 mV. + * Represents the single-end input threshold vrefh, 1.76 V to 2 V with step of 80 mV. */ uint32_t usb_drefh:2; /** usb_drefl : RO; bitpos: [24:23]; default: 0; - * Represents the single-end input threhold vrefl, 1.76 V to 2 V with step of 80 mV. + * Represents the single-end input threshold vrefl, 1.76 V to 2 V with step of 80 mV. */ uint32_t usb_drefl:2; /** usb_exchg_pins : RO; bitpos: [25]; default: 0; @@ -2007,7 +2007,7 @@ typedef union { } efuse_clk_reg_t; /** Type of conf register - * eFuse operation mode configuraiton register + * eFuse operation mode configuration register */ typedef union { struct { diff --git a/components/soc/esp32h2/include/soc/extmem_reg.h b/components/soc/esp32h2/register/soc/extmem_reg.h similarity index 98% rename from components/soc/esp32h2/include/soc/extmem_reg.h rename to components/soc/esp32h2/register/soc/extmem_reg.h index b53ab4673141..c277ae582c24 100644 --- a/components/soc/esp32h2/include/soc/extmem_reg.h +++ b/components/soc/esp32h2/register/soc/extmem_reg.h @@ -10,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define CACHE_L1_CACHE_CTRL_REG (DR_REG_CACHE_BASE + 0x4) /* CACHE_L1_CACHE_SHUT_BUS1 : R/W ;bitpos:[1] ;default: 1'h0 ; */ @@ -250,8 +250,8 @@ ould be used together with CACHE_LOCK_ADDR_REG.*/ #define CACHE_SYNC_DONE_S 4 /* CACHE_WRITEBACK_INVALIDATE_ENA : R/W/SC ;bitpos:[3] ;default: 1'h0 ; */ /*description: The bit is used to enable writeback-invalidate operation. It will be cleared by -hardware after writeback-invalidate operation done. Note that this bit and the o -ther sync-bits (invalidate_ena, clean_ena, writeback_ena) are mutually exclusive +hardware after writeback-invalidate operation done. Note that this bit and the +other sync-bits (invalidate_ena, clean_ena, writeback_ena) are mutually exclusive , that is, those bits can not be set to 1 at the same time..*/ #define CACHE_WRITEBACK_INVALIDATE_ENA (BIT(3)) #define CACHE_WRITEBACK_INVALIDATE_ENA_M (BIT(3)) @@ -269,16 +269,16 @@ those bits can not be set to 1 at the same time..*/ /* CACHE_CLEAN_ENA : R/W/SC ;bitpos:[1] ;default: 1'h0 ; */ /*description: The bit is used to enable clean operation. It will be cleared by hardware after clean operation done. Note that this bit and the other sync-bits (invalidate_ena -, writeback_ena, writeback_invalidate_ena) are mutually exclusive, that is, thos -e bits can not be set to 1 at the same time..*/ +, writeback_ena, writeback_invalidate_ena) are mutually exclusive, that is, those +bits can not be set to 1 at the same time..*/ #define CACHE_CLEAN_ENA (BIT(1)) #define CACHE_CLEAN_ENA_M (BIT(1)) #define CACHE_CLEAN_ENA_V 0x1 #define CACHE_CLEAN_ENA_S 1 /* CACHE_INVALIDATE_ENA : R/W/SC ;bitpos:[0] ;default: 1'h1 ; */ /*description: The bit is used to enable invalidate operation. It will be cleared by hardware a -fter invalidate operation done. Note that this bit and the other sync-bits (clea -n_ena, writeback_ena, writeback_invalidate_ena) are mutually exclusive, that is, +after invalidate operation done. Note that this bit and the other sync-bits (clean_ena, +writeback_ena, writeback_invalidate_ena) are mutually exclusive, that is, those bits can not be set to 1 at the same time..*/ #define CACHE_INVALIDATE_ENA (BIT(0)) #define CACHE_INVALIDATE_ENA_M (BIT(0)) @@ -499,15 +499,15 @@ SCT3_ADDR and L1_CACHE_AUTOLOAD_SCT3_ENA..*/ #define CACHE_L1_CACHE_ACS_CNT_INT_CLR_REG (DR_REG_CACHE_BASE + 0x15C) /* CACHE_L1_BUS1_OVF_INT_CLR : WT ;bitpos:[5] ;default: 1'b0 ; */ -/*description: The bit is used to clear counters overflow interrupt and counters in L1-DCache d -ue to bus1 accesses L1-DCache..*/ +/*description: The bit is used to clear counters overflow interrupt and counters in L1-DCache +due to bus1 accesses L1-DCache..*/ #define CACHE_L1_BUS1_OVF_INT_CLR (BIT(5)) #define CACHE_L1_BUS1_OVF_INT_CLR_M (BIT(5)) #define CACHE_L1_BUS1_OVF_INT_CLR_V 0x1 #define CACHE_L1_BUS1_OVF_INT_CLR_S 5 /* CACHE_L1_BUS0_OVF_INT_CLR : WT ;bitpos:[4] ;default: 1'b0 ; */ -/*description: The bit is used to clear counters overflow interrupt and counters in L1-DCache d -ue to bus0 accesses L1-DCache..*/ +/*description: The bit is used to clear counters overflow interrupt and counters in L1-DCache +due to bus0 accesses L1-DCache..*/ #define CACHE_L1_BUS0_OVF_INT_CLR (BIT(4)) #define CACHE_L1_BUS0_OVF_INT_CLR_M (BIT(4)) #define CACHE_L1_BUS0_OVF_INT_CLR_V 0x1 @@ -573,8 +573,8 @@ o cpu accesses L1-DCache..*/ #define CACHE_L1_CACHE_ACS_FAIL_INT_ST_REG (DR_REG_CACHE_BASE + 0x174) /* CACHE_L1_CACHE_FAIL_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: The bit indicates the interrupt status of access fail that occurs in L1-DCache d -ue to cpu accesses L1-DCache..*/ +/*description: The bit indicates the interrupt status of access fail that occurs in L1-DCache +due to cpu accesses L1-DCache..*/ #define CACHE_L1_CACHE_FAIL_INT_ST (BIT(4)) #define CACHE_L1_CACHE_FAIL_INT_ST_M (BIT(4)) #define CACHE_L1_CACHE_FAIL_INT_ST_V 0x1 @@ -787,7 +787,7 @@ ror occurs..*/ #define CACHE_SYNC_ERR_INT_ST_V 0x1 #define CACHE_SYNC_ERR_INT_ST_S 13 /* CACHE_L1_CACHE_PLD_ERR_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: The bit indicates the status of the interrupt of L1-Cache preload-operation erro +/*description: The bit indicates the status of the interrupt of L1-Cache preload-operation error r..*/ #define CACHE_L1_CACHE_PLD_ERR_INT_ST (BIT(11)) #define CACHE_L1_CACHE_PLD_ERR_INT_ST_M (BIT(11)) @@ -825,7 +825,7 @@ load-operation is done..*/ #define CACHE_L1_CACHE_SYNC_RST_CTRL_REG (DR_REG_CACHE_BASE + 0x238) /* CACHE_L1_CACHE_SYNC_RST : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: set this bit to reset sync-logic inside L1-Cache. Recommend that this should onl +/*description: set this bit to reset sync-logic inside L1-Cache. Recommend that this should only y be used to initialize sync-logic when some fatal error of sync-logic occurs..*/ #define CACHE_L1_CACHE_SYNC_RST (BIT(4)) #define CACHE_L1_CACHE_SYNC_RST_M (BIT(4)) @@ -855,7 +855,7 @@ rks in L1-Cache..*/ #define CACHE_L1_UNALLOCATE_BUFFER_CLEAR_REG (DR_REG_CACHE_BASE + 0x244) /* CACHE_L1_CACHE_UNALLOC_CLR : R/W ;bitpos:[4] ;default: 1'b0 ; */ /*description: The bit is used to clear the unallocate request buffer of l1 cache where the una -llocate request is responsed but not completed..*/ +llocate request is responded but not completed..*/ #define CACHE_L1_CACHE_UNALLOC_CLR (BIT(4)) #define CACHE_L1_CACHE_UNALLOC_CLR_M (BIT(4)) #define CACHE_L1_CACHE_UNALLOC_CLR_V 0x1 @@ -870,7 +870,7 @@ th the others fields inside this register..*/ #define CACHE_L1_CACHE_MEM_OBJECT_V 0x1 #define CACHE_L1_CACHE_MEM_OBJECT_S 10 /* CACHE_L1_CACHE_TAG_OBJECT : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: Set this bit to set L1-Cache tag memory as object. This bit should be onehot wit +/*description: Set this bit to set L1-Cache tag memory as object. This bit should be onehot with h the others fields inside this register..*/ #define CACHE_L1_CACHE_TAG_OBJECT (BIT(4)) #define CACHE_L1_CACHE_TAG_OBJECT_M (BIT(4)) @@ -888,8 +888,8 @@ h the others fields inside this register..*/ #define CACHE_L1_CACHE_VADDR_REG (DR_REG_CACHE_BASE + 0x250) /* CACHE_L1_CACHE_VADDR : R/W ;bitpos:[31:0] ;default: 32'h40000000 ; */ -/*description: Those bits stores the virtual address which will decide where inside the specifi -ed tag memory object will be accessed..*/ +/*description: Those bits stores the virtual address which will decide where inside the specified +tag memory object will be accessed..*/ #define CACHE_L1_CACHE_VADDR 0xFFFFFFFF #define CACHE_L1_CACHE_VADDR_M ((CACHE_L1_CACHE_VADDR_V)<<(CACHE_L1_CACHE_VADDR_S)) #define CACHE_L1_CACHE_VADDR_V 0xFFFFFFFF diff --git a/components/soc/esp32c6/include/soc/extmem_struct.h b/components/soc/esp32h2/register/soc/extmem_struct.h similarity index 99% rename from components/soc/esp32c6/include/soc/extmem_struct.h rename to components/soc/esp32h2/register/soc/extmem_struct.h index d309e09235e4..d43c5fcee3d7 100644 --- a/components/soc/esp32c6/include/soc/extmem_struct.h +++ b/components/soc/esp32h2/register/soc/extmem_struct.h @@ -5115,12 +5115,12 @@ typedef union { struct { /** l1_icache0_unalloc_clr : HRO; bitpos: [0]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache0 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_icache0_unalloc_clr:1; /** l1_icache1_unalloc_clr : HRO; bitpos: [1]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache1 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_icache1_unalloc_clr:1; /** l1_icache2_unalloc_clr : HRO; bitpos: [2]; default: 0; @@ -5133,7 +5133,7 @@ typedef union { uint32_t l1_icache3_unalloc_clr:1; /** l1_cache_unalloc_clr : R/W; bitpos: [4]; default: 0; * The bit is used to clear the unallocate request buffer of l1 cache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l1_cache_unalloc_clr:1; uint32_t reserved_5:27; @@ -5149,7 +5149,7 @@ typedef union { uint32_t reserved_0:5; /** l2_cache_unalloc_clr : HRO; bitpos: [5]; default: 0; * The bit is used to clear the unallocate request buffer of l2 icache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ uint32_t l2_cache_unalloc_clr:1; uint32_t reserved_6:26; diff --git a/components/soc/esp32h2/include/soc/gdma_reg.h b/components/soc/esp32h2/register/soc/gdma_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/gdma_reg.h rename to components/soc/esp32h2/register/soc/gdma_reg.h diff --git a/components/soc/esp32h2/include/soc/gdma_struct.h b/components/soc/esp32h2/register/soc/gdma_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/gdma_struct.h rename to components/soc/esp32h2/register/soc/gdma_struct.h diff --git a/components/soc/esp32h2/include/soc/gpio_ext_reg.h b/components/soc/esp32h2/register/soc/gpio_ext_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/gpio_ext_reg.h rename to components/soc/esp32h2/register/soc/gpio_ext_reg.h diff --git a/components/soc/esp32h2/include/soc/gpio_ext_struct.h b/components/soc/esp32h2/register/soc/gpio_ext_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/gpio_ext_struct.h rename to components/soc/esp32h2/register/soc/gpio_ext_struct.h diff --git a/components/soc/esp32h2/include/soc/gpio_reg.h b/components/soc/esp32h2/register/soc/gpio_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/gpio_reg.h rename to components/soc/esp32h2/register/soc/gpio_reg.h diff --git a/components/soc/esp32h2/include/soc/gpio_struct.h b/components/soc/esp32h2/register/soc/gpio_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/gpio_struct.h rename to components/soc/esp32h2/register/soc/gpio_struct.h diff --git a/components/soc/esp32h2/include/soc/hmac_reg.h b/components/soc/esp32h2/register/soc/hmac_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/hmac_reg.h rename to components/soc/esp32h2/register/soc/hmac_reg.h diff --git a/components/soc/esp32h2/include/soc/hmac_struct.h b/components/soc/esp32h2/register/soc/hmac_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/hmac_struct.h rename to components/soc/esp32h2/register/soc/hmac_struct.h diff --git a/components/soc/esp32h2/include/soc/hp_apm_reg.h b/components/soc/esp32h2/register/soc/hp_apm_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/hp_apm_reg.h rename to components/soc/esp32h2/register/soc/hp_apm_reg.h diff --git a/components/soc/esp32h2/include/soc/hp_apm_struct.h b/components/soc/esp32h2/register/soc/hp_apm_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/hp_apm_struct.h rename to components/soc/esp32h2/register/soc/hp_apm_struct.h diff --git a/components/soc/esp32h2/include/soc/hp_system_reg.h b/components/soc/esp32h2/register/soc/hp_system_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/hp_system_reg.h rename to components/soc/esp32h2/register/soc/hp_system_reg.h index 1660509115eb..842750731d83 100644 --- a/components/soc/esp32h2/include/soc/hp_system_reg.h +++ b/components/soc/esp32h2/register/soc/hp_system_reg.h @@ -78,7 +78,7 @@ extern "C" { * 0: anti-DPA disable. 1~3: anti-DPA enable with different security level. The larger * the number, the stronger the ability to resist DPA attacks and the higher the * security level, but it will increase the computational overhead of the hardware - * crypto-accelerators. Only avaliable if HP_SYSTEM_SEC_DPA_CFG_SEL is 0. + * crypto-accelerators. Only available if HP_SYSTEM_SEC_DPA_CFG_SEL is 0. */ #define HP_SYSTEM_SEC_DPA_LEVEL 0x00000003U #define HP_SYSTEM_SEC_DPA_LEVEL_M (HP_SYSTEM_SEC_DPA_LEVEL_V << HP_SYSTEM_SEC_DPA_LEVEL_S) diff --git a/components/soc/esp32h2/include/soc/hp_system_struct.h b/components/soc/esp32h2/register/soc/hp_system_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/hp_system_struct.h rename to components/soc/esp32h2/register/soc/hp_system_struct.h index 575349312bc0..4dcaf9550036 100644 --- a/components/soc/esp32h2/include/soc/hp_system_struct.h +++ b/components/soc/esp32h2/register/soc/hp_system_struct.h @@ -70,7 +70,7 @@ typedef union { * 0: anti-DPA disable. 1~3: anti-DPA enable with different security level. The larger * the number, the stronger the ability to resist DPA attacks and the higher the * security level, but it will increase the computational overhead of the hardware - * crypto-accelerators. Only avaliable if HP_SYS_SEC_DPA_CFG_SEL is 0. + * crypto-accelerators. Only available if HP_SYS_SEC_DPA_CFG_SEL is 0. */ uint32_t sec_dpa_level:2; /** sec_dpa_cfg_sel : R/W; bitpos: [2]; default: 0; diff --git a/components/soc/esp32h2/include/soc/i2c_ana_mst_reg.h b/components/soc/esp32h2/register/soc/i2c_ana_mst_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/i2c_ana_mst_reg.h rename to components/soc/esp32h2/register/soc/i2c_ana_mst_reg.h diff --git a/components/soc/esp32h2/include/soc/i2c_reg.h b/components/soc/esp32h2/register/soc/i2c_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/i2c_reg.h rename to components/soc/esp32h2/register/soc/i2c_reg.h diff --git a/components/soc/esp32h2/include/soc/i2c_struct.h b/components/soc/esp32h2/register/soc/i2c_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/i2c_struct.h rename to components/soc/esp32h2/register/soc/i2c_struct.h diff --git a/components/soc/esp32h2/include/soc/i2s_reg.h b/components/soc/esp32h2/register/soc/i2s_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/i2s_reg.h rename to components/soc/esp32h2/register/soc/i2s_reg.h index b79bdd298c3d..95b982407e6d 100644 --- a/components/soc/esp32h2/include/soc/i2s_reg.h +++ b/components/soc/esp32h2/register/soc/i2s_reg.h @@ -320,7 +320,7 @@ extern "C" { #define I2S_TX_SLAVE_MOD_V 0x00000001U #define I2S_TX_SLAVE_MOD_S 3 /** I2S_TX_STOP_EN : R/W; bitpos: [4]; default: 1; - * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty */ #define I2S_TX_STOP_EN (BIT(4)) #define I2S_TX_STOP_EN_M (I2S_TX_STOP_EN_V << I2S_TX_STOP_EN_S) diff --git a/components/soc/esp32h2/include/soc/i2s_struct.h b/components/soc/esp32h2/register/soc/i2s_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/i2s_struct.h rename to components/soc/esp32h2/register/soc/i2s_struct.h index 34f876838f86..0a01bf6f670b 100644 --- a/components/soc/esp32h2/include/soc/i2s_struct.h +++ b/components/soc/esp32h2/register/soc/i2s_struct.h @@ -459,7 +459,7 @@ typedef union { */ uint32_t tx_slave_mod:1; /** tx_stop_en : R/W; bitpos: [4]; default: 1; - * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty */ uint32_t tx_stop_en:1; /** tx_chan_equal : R/W; bitpos: [5]; default: 0; diff --git a/components/soc/esp32h2/include/soc/ieee802154_reg.h b/components/soc/esp32h2/register/soc/ieee802154_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/ieee802154_reg.h rename to components/soc/esp32h2/register/soc/ieee802154_reg.h diff --git a/components/soc/esp32h2/include/soc/ieee802154_struct.h b/components/soc/esp32h2/register/soc/ieee802154_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/ieee802154_struct.h rename to components/soc/esp32h2/register/soc/ieee802154_struct.h diff --git a/components/soc/esp32h2/include/soc/interrupt_matrix_reg.h b/components/soc/esp32h2/register/soc/interrupt_matrix_reg.h similarity index 98% rename from components/soc/esp32h2/include/soc/interrupt_matrix_reg.h rename to components/soc/esp32h2/register/soc/interrupt_matrix_reg.h index 26f76cfb8eb5..c526cacc8bc4 100644 --- a/components/soc/esp32h2/include/soc/interrupt_matrix_reg.h +++ b/components/soc/esp32h2/register/soc/interrupt_matrix_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -383,17 +383,17 @@ extern "C" { #define INTMTX_CORE0_MSPI_INTR_MAP_V 0x0000001FU #define INTMTX_CORE0_MSPI_INTR_MAP_S 0 -/** INTMTX_CORE0_I2S1_INTR_MAP_REG register +/** INTMTX_CORE0_I2S_INTR_MAP_REG register * register description */ -#define INTMTX_CORE0_I2S1_INTR_MAP_REG (DR_REG_INTERRUPT_MATRIX_BASE + 0x7c) -/** INTMTX_CORE0_I2S1_INTR_MAP : R/W; bitpos: [4:0]; default: 0; - * CORE0_I2S1_INTR mapping register +#define INTMTX_CORE0_I2S_INTR_MAP_REG (DR_REG_INTERRUPT_MATRIX_BASE + 0x7c) +/** INTMTX_CORE0_I2S_INTR_MAP : R/W; bitpos: [4:0]; default: 0; + * CORE0_I2S_INTR mapping register */ -#define INTMTX_CORE0_I2S1_INTR_MAP 0x0000001FU -#define INTMTX_CORE0_I2S1_INTR_MAP_M (INTMTX_CORE0_I2S1_INTR_MAP_V << INTMTX_CORE0_I2S1_INTR_MAP_S) -#define INTMTX_CORE0_I2S1_INTR_MAP_V 0x0000001FU -#define INTMTX_CORE0_I2S1_INTR_MAP_S 0 +#define INTMTX_CORE0_I2S_INTR_MAP 0x0000001FU +#define INTMTX_CORE0_I2S_INTR_MAP_M (INTMTX_CORE0_I2S_INTR_MAP_V << INTMTX_CORE0_I2S_INTR_MAP_S) +#define INTMTX_CORE0_I2S_INTR_MAP_V 0x0000001FU +#define INTMTX_CORE0_I2S_INTR_MAP_S 0 /** INTMTX_CORE0_UHCI0_INTR_MAP_REG register * register description diff --git a/components/soc/esp32h2/include/soc/interrupt_matrix_struct.h b/components/soc/esp32h2/register/soc/interrupt_matrix_struct.h similarity index 98% rename from components/soc/esp32h2/include/soc/interrupt_matrix_struct.h rename to components/soc/esp32h2/register/soc/interrupt_matrix_struct.h index 7105872f357f..47e0526b64a6 100644 --- a/components/soc/esp32h2/include/soc/interrupt_matrix_struct.h +++ b/components/soc/esp32h2/register/soc/interrupt_matrix_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -445,19 +445,19 @@ typedef union { uint32_t val; } intmtx_core0_mspi_intr_map_reg_t; -/** Type of i2s1_intr_map register +/** Type of i2s_intr_map register * register description */ typedef union { struct { - /** i2s1_intr_map : R/W; bitpos: [4:0]; default: 0; - * CORE0_I2S1_INTR mapping register + /** i2s_intr_map : R/W; bitpos: [4:0]; default: 0; + * CORE0_i2s_INTR mapping register */ - uint32_t i2s1_intr_map:5; + uint32_t i2s_intr_map:5; uint32_t reserved_5:27; }; uint32_t val; -} intmtx_core0_i2s1_intr_map_reg_t; +} intmtx_core0_i2s_intr_map_reg_t; /** Type of uhci0_intr_map register * register description @@ -1021,7 +1021,7 @@ typedef struct interrupt_matrix_dev_t { volatile intmtx_core0_hp_apm_m2_intr_map_reg_t hp_apm_m2_intr_map; volatile intmtx_core0_hp_apm_m3_intr_map_reg_t hp_apm_m3_intr_map; volatile intmtx_core0_mspi_intr_map_reg_t mspi_intr_map; - volatile intmtx_core0_i2s1_intr_map_reg_t i2s1_intr_map; + volatile intmtx_core0_i2s_intr_map_reg_t i2s_intr_map; volatile intmtx_core0_uhci0_intr_map_reg_t uhci0_intr_map; volatile intmtx_core0_uart0_intr_map_reg_t uart0_intr_map; volatile intmtx_core0_uart1_intr_map_reg_t uart1_intr_map; diff --git a/components/soc/esp32h2/include/soc/intpri_reg.h b/components/soc/esp32h2/register/soc/intpri_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/intpri_reg.h rename to components/soc/esp32h2/register/soc/intpri_reg.h diff --git a/components/soc/esp32h2/include/soc/intpri_struct.h b/components/soc/esp32h2/register/soc/intpri_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/intpri_struct.h rename to components/soc/esp32h2/register/soc/intpri_struct.h diff --git a/components/soc/esp32h2/include/soc/io_mux_reg.h b/components/soc/esp32h2/register/soc/io_mux_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/io_mux_reg.h rename to components/soc/esp32h2/register/soc/io_mux_reg.h index 5db79e1673a6..4bbb466906a6 100644 --- a/components/soc/esp32h2/include/soc/io_mux_reg.h +++ b/components/soc/esp32h2/register/soc/io_mux_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "soc.h" +#include "soc/soc.h" /* The following are the bit fields for PERIPHS_IO_MUX_x_U registers */ /* Output enable in sleep mode */ @@ -79,7 +79,7 @@ #define HYS_EN_S 16 /* HYS_SEL : R/W; bitpos: [17]; default: 0; * Select enabling signals of the pad from software and efuse hardware. - * 1: Select enabling siganl from software. + * 1: Select enabling signal from software. * 0: Select enabling signal from efuse hardware. */ #define HYS_SEL (BIT(17)) diff --git a/components/soc/esp32h2/include/soc/ledc_reg.h b/components/soc/esp32h2/register/soc/ledc_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/ledc_reg.h rename to components/soc/esp32h2/register/soc/ledc_reg.h diff --git a/components/soc/esp32h2/include/soc/ledc_struct.h b/components/soc/esp32h2/register/soc/ledc_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/ledc_struct.h rename to components/soc/esp32h2/register/soc/ledc_struct.h diff --git a/components/soc/esp32h2/include/soc/lp_analog_peri_reg.h b/components/soc/esp32h2/register/soc/lp_analog_peri_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_analog_peri_reg.h rename to components/soc/esp32h2/register/soc/lp_analog_peri_reg.h diff --git a/components/soc/esp32h2/include/soc/lp_analog_peri_struct.h b/components/soc/esp32h2/register/soc/lp_analog_peri_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_analog_peri_struct.h rename to components/soc/esp32h2/register/soc/lp_analog_peri_struct.h diff --git a/components/soc/esp32h2/include/soc/lp_aon_reg.h b/components/soc/esp32h2/register/soc/lp_aon_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_aon_reg.h rename to components/soc/esp32h2/register/soc/lp_aon_reg.h diff --git a/components/soc/esp32h2/include/soc/lp_aon_struct.h b/components/soc/esp32h2/register/soc/lp_aon_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_aon_struct.h rename to components/soc/esp32h2/register/soc/lp_aon_struct.h diff --git a/components/soc/esp32h2/include/soc/lp_apm0_reg.h b/components/soc/esp32h2/register/soc/lp_apm0_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_apm0_reg.h rename to components/soc/esp32h2/register/soc/lp_apm0_reg.h diff --git a/components/soc/esp32h2/include/soc/lp_apm0_struct.h b/components/soc/esp32h2/register/soc/lp_apm0_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_apm0_struct.h rename to components/soc/esp32h2/register/soc/lp_apm0_struct.h diff --git a/components/soc/esp32h2/include/soc/lp_apm_reg.h b/components/soc/esp32h2/register/soc/lp_apm_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_apm_reg.h rename to components/soc/esp32h2/register/soc/lp_apm_reg.h diff --git a/components/soc/esp32h2/include/soc/lp_apm_struct.h b/components/soc/esp32h2/register/soc/lp_apm_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_apm_struct.h rename to components/soc/esp32h2/register/soc/lp_apm_struct.h diff --git a/components/soc/esp32h2/include/soc/lp_clkrst_reg.h b/components/soc/esp32h2/register/soc/lp_clkrst_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_clkrst_reg.h rename to components/soc/esp32h2/register/soc/lp_clkrst_reg.h diff --git a/components/soc/esp32h2/include/soc/lp_clkrst_struct.h b/components/soc/esp32h2/register/soc/lp_clkrst_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_clkrst_struct.h rename to components/soc/esp32h2/register/soc/lp_clkrst_struct.h diff --git a/components/soc/esp32h2/include/soc/lp_timer_reg.h b/components/soc/esp32h2/register/soc/lp_timer_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_timer_reg.h rename to components/soc/esp32h2/register/soc/lp_timer_reg.h diff --git a/components/soc/esp32h2/include/soc/lp_timer_struct.h b/components/soc/esp32h2/register/soc/lp_timer_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_timer_struct.h rename to components/soc/esp32h2/register/soc/lp_timer_struct.h diff --git a/components/soc/esp32h2/include/soc/lp_wdt_reg.h b/components/soc/esp32h2/register/soc/lp_wdt_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_wdt_reg.h rename to components/soc/esp32h2/register/soc/lp_wdt_reg.h diff --git a/components/soc/esp32h2/include/soc/lp_wdt_struct.h b/components/soc/esp32h2/register/soc/lp_wdt_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/lp_wdt_struct.h rename to components/soc/esp32h2/register/soc/lp_wdt_struct.h diff --git a/components/soc/esp32h2/include/soc/lpperi_reg.h b/components/soc/esp32h2/register/soc/lpperi_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/lpperi_reg.h rename to components/soc/esp32h2/register/soc/lpperi_reg.h diff --git a/components/soc/esp32h2/include/soc/lpperi_struct.h b/components/soc/esp32h2/register/soc/lpperi_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/lpperi_struct.h rename to components/soc/esp32h2/register/soc/lpperi_struct.h diff --git a/components/soc/esp32h2/include/soc/mcpwm_reg.h b/components/soc/esp32h2/register/soc/mcpwm_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/mcpwm_reg.h rename to components/soc/esp32h2/register/soc/mcpwm_reg.h index f851de75ceeb..a14ba71be368 100644 --- a/components/soc/esp32h2/include/soc/mcpwm_reg.h +++ b/components/soc/esp32h2/register/soc/mcpwm_reg.h @@ -894,7 +894,7 @@ extern "C" { #define MCPWM_DB0_RED_S 0 /** MCPWM_CARRIER0_CFG_REG register - * Carrier enable and configuratoin + * Carrier enable and configuration */ #define MCPWM_CARRIER0_CFG_REG (DR_REG_MCPWM_BASE + 0x64) /** MCPWM_CHOPPER0_EN : R/W; bitpos: [0]; default: 0; @@ -1575,7 +1575,7 @@ extern "C" { #define MCPWM_DB1_RED_S 0 /** MCPWM_CARRIER1_CFG_REG register - * Carrier enable and configuratoin + * Carrier enable and configuration */ #define MCPWM_CARRIER1_CFG_REG (DR_REG_MCPWM_BASE + 0x9c) /** MCPWM_CHOPPER1_EN : R/W; bitpos: [0]; default: 0; @@ -2256,7 +2256,7 @@ extern "C" { #define MCPWM_DB2_RED_S 0 /** MCPWM_CARRIER2_CFG_REG register - * Carrier enable and configuratoin + * Carrier enable and configuration */ #define MCPWM_CARRIER2_CFG_REG (DR_REG_MCPWM_BASE + 0xd4) /** MCPWM_CHOPPER2_EN : R/W; bitpos: [0]; default: 0; @@ -2621,7 +2621,7 @@ extern "C" { #define MCPWM_CAP0_MODE_V 0x00000003U #define MCPWM_CAP0_MODE_S 1 /** MCPWM_CAP0_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + + * Value of prescaling on positive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + * 1 */ #define MCPWM_CAP0_PRESCALE 0x000000FFU @@ -2664,7 +2664,7 @@ extern "C" { #define MCPWM_CAP1_MODE_V 0x00000003U #define MCPWM_CAP1_MODE_S 1 /** MCPWM_CAP1_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + + * Value of prescaling on positive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + * 1 */ #define MCPWM_CAP1_PRESCALE 0x000000FFU @@ -2707,7 +2707,7 @@ extern "C" { #define MCPWM_CAP2_MODE_V 0x00000003U #define MCPWM_CAP2_MODE_S 1 /** MCPWM_CAP2_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + + * Value of prescaling on positive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + * 1 */ #define MCPWM_CAP2_PRESCALE 0x000000FFU diff --git a/components/soc/esp32h2/include/soc/mcpwm_struct.h b/components/soc/esp32h2/register/soc/mcpwm_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/mcpwm_struct.h rename to components/soc/esp32h2/register/soc/mcpwm_struct.h index 1a91a623f6bc..5fe75f3c99e0 100644 --- a/components/soc/esp32h2/include/soc/mcpwm_struct.h +++ b/components/soc/esp32h2/register/soc/mcpwm_struct.h @@ -462,7 +462,7 @@ typedef union { } mcpwm_dt_red_cfg_reg_t; /** Type of carrier_cfg register - * Carrier enable and configuratoin + * Carrier enable and configuration */ typedef union { struct { @@ -734,7 +734,7 @@ typedef union { */ uint32_t capn_mode:2; /** capn_prescale : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAPn. Prescale value = PWM_CAP0_PRESCALE + + * Value of prescaling on positive edge of CAPn. Prescale value = PWM_CAP0_PRESCALE + * 1 */ uint32_t capn_prescale:8; diff --git a/components/soc/esp32h2/include/soc/mem_monitor_reg.h b/components/soc/esp32h2/register/soc/mem_monitor_reg.h similarity index 98% rename from components/soc/esp32h2/include/soc/mem_monitor_reg.h rename to components/soc/esp32h2/register/soc/mem_monitor_reg.h index bbddf93b89a8..1a90e585be1c 100644 --- a/components/soc/esp32h2/include/soc/mem_monitor_reg.h +++ b/components/soc/esp32h2/register/soc/mem_monitor_reg.h @@ -12,7 +12,7 @@ extern "C" { #endif /** MEM_MONITOR_LOG_SETTING_REG register - * log config regsiter + * log config register */ #define MEM_MONITOR_LOG_SETTING_REG (DR_REG_MEM_MONITOR_BASE + 0x0) /** MEM_MONITOR_LOG_ENA : R/W; bitpos: [2:0]; default: 0; @@ -39,7 +39,7 @@ extern "C" { #define MEM_MONITOR_LOG_MEM_LOOP_ENABLE_S 7 /** MEM_MONITOR_LOG_CHECK_DATA_REG register - * check data regsiter + * check data register */ #define MEM_MONITOR_LOG_CHECK_DATA_REG (DR_REG_MEM_MONITOR_BASE + 0x4) /** MEM_MONITOR_LOG_CHECK_DATA : R/W; bitpos: [31:0]; default: 0; @@ -64,7 +64,7 @@ extern "C" { #define MEM_MONITOR_LOG_DATA_MASK_S 0 /** MEM_MONITOR_LOG_MIN_REG register - * log boundary regsiter + * log boundary register */ #define MEM_MONITOR_LOG_MIN_REG (DR_REG_MEM_MONITOR_BASE + 0xc) /** MEM_MONITOR_LOG_MIN : R/W; bitpos: [31:0]; default: 0; @@ -76,7 +76,7 @@ extern "C" { #define MEM_MONITOR_LOG_MIN_S 0 /** MEM_MONITOR_LOG_MAX_REG register - * log boundary regsiter + * log boundary register */ #define MEM_MONITOR_LOG_MAX_REG (DR_REG_MEM_MONITOR_BASE + 0x10) /** MEM_MONITOR_LOG_MAX : R/W; bitpos: [31:0]; default: 0; diff --git a/components/soc/esp32h2/include/soc/mem_monitor_struct.h b/components/soc/esp32h2/register/soc/mem_monitor_struct.h similarity index 98% rename from components/soc/esp32h2/include/soc/mem_monitor_struct.h rename to components/soc/esp32h2/register/soc/mem_monitor_struct.h index 8d4628467f77..ef63ca9c2648 100644 --- a/components/soc/esp32h2/include/soc/mem_monitor_struct.h +++ b/components/soc/esp32h2/register/soc/mem_monitor_struct.h @@ -12,7 +12,7 @@ extern "C" { /** Group: configuration registers */ /** Type of log_setting register - * log config regsiter + * log config register */ typedef union { struct { @@ -35,7 +35,7 @@ typedef union { } mem_monitor_log_setting_reg_t; /** Type of log_check_data register - * check data regsiter + * check data register */ typedef union { struct { @@ -63,7 +63,7 @@ typedef union { } mem_monitor_log_data_mask_reg_t; /** Type of log_min register - * log boundary regsiter + * log boundary register */ typedef union { struct { @@ -76,7 +76,7 @@ typedef union { } mem_monitor_log_min_reg_t; /** Type of log_max register - * log boundary regsiter + * log boundary register */ typedef union { struct { diff --git a/components/soc/esp32h2/include/soc/parl_io_reg.h b/components/soc/esp32h2/register/soc/parl_io_reg.h similarity index 98% rename from components/soc/esp32h2/include/soc/parl_io_reg.h rename to components/soc/esp32h2/register/soc/parl_io_reg.h index 810530ded7b9..d68f5191cb2b 100644 --- a/components/soc/esp32h2/include/soc/parl_io_reg.h +++ b/components/soc/esp32h2/register/soc/parl_io_reg.h @@ -252,7 +252,7 @@ extern "C" { #define PARL_IO_TX_READY_S 31 /** PARL_IO_INT_ENA_REG register - * Parallel IO interrupt enable singal configuration register. + * Parallel IO interrupt enable signal configuration register. */ #define PARL_IO_INT_ENA_REG (DR_REG_PARL_IO_BASE + 0x28) /** PARL_IO_TX_FIFO_REMPTY_INT_ENA : R/W; bitpos: [0]; default: 0; @@ -278,7 +278,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_ENA_S 2 /** PARL_IO_INT_RAW_REG register - * Parallel IO interrupt raw singal status register. + * Parallel IO interrupt raw signal status register. */ #define PARL_IO_INT_RAW_REG (DR_REG_PARL_IO_BASE + 0x2c) /** PARL_IO_TX_FIFO_REMPTY_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; @@ -304,7 +304,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_RAW_S 2 /** PARL_IO_INT_ST_REG register - * Parallel IO interrupt singal status register. + * Parallel IO interrupt signal status register. */ #define PARL_IO_INT_ST_REG (DR_REG_PARL_IO_BASE + 0x30) /** PARL_IO_TX_FIFO_REMPTY_INT_ST : RO; bitpos: [0]; default: 0; @@ -330,7 +330,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_ST_S 2 /** PARL_IO_INT_CLR_REG register - * Parallel IO interrupt clear singal configuration register. + * Parallel IO interrupt clear signal configuration register. */ #define PARL_IO_INT_CLR_REG (DR_REG_PARL_IO_BASE + 0x34) /** PARL_IO_TX_FIFO_REMPTY_INT_CLR : WT; bitpos: [0]; default: 0; diff --git a/components/soc/esp32h2/include/soc/parl_io_struct.h b/components/soc/esp32h2/register/soc/parl_io_struct.h similarity index 98% rename from components/soc/esp32h2/include/soc/parl_io_struct.h rename to components/soc/esp32h2/register/soc/parl_io_struct.h index 97dc285531d6..6e501e6c5795 100644 --- a/components/soc/esp32h2/include/soc/parl_io_struct.h +++ b/components/soc/esp32h2/register/soc/parl_io_struct.h @@ -251,7 +251,7 @@ typedef union { /** Group: PARL_IO Interrupt Configuration and Status */ /** Type of int_ena register - * Parallel IO interrupt enable singal configuration register. + * Parallel IO interrupt enable signal configuration register. */ typedef union { struct { @@ -273,7 +273,7 @@ typedef union { } parl_io_int_ena_reg_t; /** Type of int_raw register - * Parallel IO interrupt raw singal status register. + * Parallel IO interrupt raw signal status register. */ typedef union { struct { @@ -295,7 +295,7 @@ typedef union { } parl_io_int_raw_reg_t; /** Type of int_st register - * Parallel IO interrupt singal status register. + * Parallel IO interrupt signal status register. */ typedef union { struct { @@ -317,7 +317,7 @@ typedef union { } parl_io_int_st_reg_t; /** Type of int_clr register - * Parallel IO interrupt clear singal configuration register. + * Parallel IO interrupt clear signal configuration register. */ typedef union { struct { diff --git a/components/soc/esp32h2/include/soc/pau_reg.h b/components/soc/esp32h2/register/soc/pau_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/pau_reg.h rename to components/soc/esp32h2/register/soc/pau_reg.h diff --git a/components/soc/esp32h2/include/soc/pau_struct.h b/components/soc/esp32h2/register/soc/pau_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/pau_struct.h rename to components/soc/esp32h2/register/soc/pau_struct.h diff --git a/components/soc/esp32h2/include/soc/pcnt_reg.h b/components/soc/esp32h2/register/soc/pcnt_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/pcnt_reg.h rename to components/soc/esp32h2/register/soc/pcnt_reg.h diff --git a/components/soc/esp32h2/include/soc/pcnt_struct.h b/components/soc/esp32h2/register/soc/pcnt_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/pcnt_struct.h rename to components/soc/esp32h2/register/soc/pcnt_struct.h diff --git a/components/soc/esp32h2/include/soc/pcr_reg.h b/components/soc/esp32h2/register/soc/pcr_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/pcr_reg.h rename to components/soc/esp32h2/register/soc/pcr_reg.h index f44d7a31ea5d..02d26df2db3e 100644 --- a/components/soc/esp32h2/include/soc/pcr_reg.h +++ b/components/soc/esp32h2/register/soc/pcr_reg.h @@ -229,7 +229,7 @@ extern "C" { #define PCR_MSPI_CLK_CONF_REG (DR_REG_PCR_BASE + 0x1c) /** PCR_MSPI_FAST_DIV_NUM : R/W; bitpos: [7:0]; default: 0; * Set as one within (0,1,2) to generate div1(default)/div2/div4 of low-speed - * clock-source to drive clk_mspi_fast. Only avaiable whe the clck-source is a + * clock-source to drive clk_mspi_fast. Only available when the clck-source is a * low-speed clock-source such as XTAL/FOSC. */ #define PCR_MSPI_FAST_DIV_NUM 0x000000FFU @@ -1331,7 +1331,7 @@ extern "C" { #define PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM_V 0x0000000FU #define PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM_S 0 /** PCR_PVT_MONITOR_FUNC_CLK_SEL : R/W; bitpos: [20]; default: 0; - * set this field to select clock-source. 0: XTAL, 1(default): 160MHz drived by SPLL + * set this field to select clock-source. 0: XTAL, 1(default): 160MHz driven by SPLL * divided by 3. */ #define PCR_PVT_MONITOR_FUNC_CLK_SEL (BIT(20)) @@ -1904,8 +1904,8 @@ extern "C" { */ #define PCR_CPU_FREQ_CONF_REG (DR_REG_PCR_BASE + 0x114) /** PCR_CPU_DIV_NUM : R/W; bitpos: [7:0]; default: 0; - * Set this field to generate clk_cpu drived by clk_hproot. The clk_cpu is - * div1(default)/div2/div4 of clk_hproot. This field is only avaliable for low-speed + * Set this field to generate clk_cpu driven by clk_hproot. The clk_cpu is + * div1(default)/div2/div4 of clk_hproot. This field is only available for low-speed * clock-source such as XTAL/FOSC, and should be used together with PCR_AHB_DIV_NUM. */ #define PCR_CPU_DIV_NUM 0x000000FFU @@ -1918,8 +1918,8 @@ extern "C" { */ #define PCR_AHB_FREQ_CONF_REG (DR_REG_PCR_BASE + 0x118) /** PCR_AHB_DIV_NUM : R/W; bitpos: [7:0]; default: 0; - * Set this field to generate clk_ahb drived by clk_hproot. The clk_ahb is - * div1(default)/div2/div4/div8 of clk_hproot. This field is only avaliable for + * Set this field to generate clk_ahb driven by clk_hproot. The clk_ahb is + * div1(default)/div2/div4/div8 of clk_hproot. This field is only available for * low-speed clock-source such as XTAL/FOSC, and should be used together with * PCR_CPU_DIV_NUM. */ @@ -1946,7 +1946,7 @@ extern "C" { #define PCR_APB_DECREASE_DIV_NUM_V 0x000000FFU #define PCR_APB_DECREASE_DIV_NUM_S 0 /** PCR_APB_DIV_NUM : R/W; bitpos: [15:8]; default: 0; - * Set as one within (0,1,3) to generate clk_apb drived by clk_ahb. The clk_apb is + * Set as one within (0,1,3) to generate clk_apb driven by clk_ahb. The clk_apb is * div1(default)/div2/div4 of clk_ahb. */ #define PCR_APB_DIV_NUM 0x000000FFU @@ -1978,48 +1978,48 @@ extern "C" { */ #define PCR_PLL_DIV_CLK_EN_REG (DR_REG_PCR_BASE + 0x124) /** PCR_PLL_240M_CLK_EN : R/W; bitpos: [0]; default: 1; - * This field is used to open 96 MHz clock (SPLL) drived from SPLL. 0: close, 1: - * open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 96 MHz clock (SPLL) driven from SPLL. 0: close, 1: + * open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_240M_CLK_EN (BIT(0)) #define PCR_PLL_240M_CLK_EN_M (PCR_PLL_240M_CLK_EN_V << PCR_PLL_240M_CLK_EN_S) #define PCR_PLL_240M_CLK_EN_V 0x00000001U #define PCR_PLL_240M_CLK_EN_S 0 /** PCR_PLL_160M_CLK_EN : R/W; bitpos: [1]; default: 1; - * This field is used to open 64 MHz clock (div3 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 64 MHz clock (div3 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_160M_CLK_EN (BIT(1)) #define PCR_PLL_160M_CLK_EN_M (PCR_PLL_160M_CLK_EN_V << PCR_PLL_160M_CLK_EN_S) #define PCR_PLL_160M_CLK_EN_V 0x00000001U #define PCR_PLL_160M_CLK_EN_S 1 /** PCR_PLL_120M_CLK_EN : R/W; bitpos: [2]; default: 1; - * This field is used to open 48 MHz clock (div4 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 48 MHz clock (div4 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_120M_CLK_EN (BIT(2)) #define PCR_PLL_120M_CLK_EN_M (PCR_PLL_120M_CLK_EN_V << PCR_PLL_120M_CLK_EN_S) #define PCR_PLL_120M_CLK_EN_V 0x00000001U #define PCR_PLL_120M_CLK_EN_S 2 /** PCR_PLL_80M_CLK_EN : R/W; bitpos: [3]; default: 1; - * This field is used to open 32 MHz clock (div6 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 32 MHz clock (div6 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_80M_CLK_EN (BIT(3)) #define PCR_PLL_80M_CLK_EN_M (PCR_PLL_80M_CLK_EN_V << PCR_PLL_80M_CLK_EN_S) #define PCR_PLL_80M_CLK_EN_V 0x00000001U #define PCR_PLL_80M_CLK_EN_S 3 /** PCR_PLL_48M_CLK_EN : R/W; bitpos: [4]; default: 1; - * This field is used to open 16 MHz clock (div10 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 16 MHz clock (div10 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_48M_CLK_EN (BIT(4)) #define PCR_PLL_48M_CLK_EN_M (PCR_PLL_48M_CLK_EN_V << PCR_PLL_48M_CLK_EN_S) #define PCR_PLL_48M_CLK_EN_V 0x00000001U #define PCR_PLL_48M_CLK_EN_S 4 /** PCR_PLL_40M_CLK_EN : R/W; bitpos: [5]; default: 1; - * This field is used to open 8 MHz clock (div12 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 8 MHz clock (div12 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ #define PCR_PLL_40M_CLK_EN (BIT(5)) #define PCR_PLL_40M_CLK_EN_M (PCR_PLL_40M_CLK_EN_V << PCR_PLL_40M_CLK_EN_S) diff --git a/components/soc/esp32h2/include/soc/pcr_struct.h b/components/soc/esp32h2/register/soc/pcr_struct.h similarity index 98% rename from components/soc/esp32h2/include/soc/pcr_struct.h rename to components/soc/esp32h2/register/soc/pcr_struct.h index 31e49c232cc8..cf1a690ac30f 100644 --- a/components/soc/esp32h2/include/soc/pcr_struct.h +++ b/components/soc/esp32h2/register/soc/pcr_struct.h @@ -192,7 +192,7 @@ typedef union { struct { /** mspi_fast_div_num : R/W; bitpos: [7:0]; default: 0; * Set as one within (0,1,2) to generate div1(default)/div2/div4 of low-speed - * clock-source to drive clk_mspi_fast. Only avaiable whe the clck-source is a + * clock-source to drive clk_mspi_fast. Only available when the clck-source is a * low-speed clock-source such as XTAL/FOSC. */ uint32_t mspi_fast_div_num:8; @@ -1067,7 +1067,7 @@ typedef union { uint32_t pvt_monitor_func_clk_div_num:4; uint32_t reserved_4:16; /** pvt_monitor_func_clk_sel : R/W; bitpos: [20]; default: 0; - * set this field to select clock-source. 0: XTAL, 1(default): 160MHz drived by SPLL + * set this field to select clock-source. 0: XTAL, 1(default): 160MHz driven by SPLL * divided by 3. */ uint32_t pvt_monitor_func_clk_sel:1; @@ -1573,8 +1573,8 @@ typedef union { typedef union { struct { /** cpu_div_num : R/W; bitpos: [7:0]; default: 0; - * Set this field to generate clk_cpu drived by clk_hproot. The clk_cpu is - * div1(default)/div2/div4 of clk_hproot. This field is only avaliable for low-speed + * Set this field to generate clk_cpu driven by clk_hproot. The clk_cpu is + * div1(default)/div2/div4 of clk_hproot. This field is only available for low-speed * clock-source such as XTAL/FOSC, and should be used together with PCR_AHB_DIV_NUM. */ uint32_t cpu_div_num:8; @@ -1589,8 +1589,8 @@ typedef union { typedef union { struct { /** ahb_div_num : R/W; bitpos: [7:0]; default: 0; - * Set this field to generate clk_ahb drived by clk_hproot. The clk_ahb is - * div1(default)/div2/div4/div8 of clk_hproot. This field is only avaliable for + * Set this field to generate clk_ahb driven by clk_hproot. The clk_ahb is + * div1(default)/div2/div4/div8 of clk_hproot. This field is only available for * low-speed clock-source such as XTAL/FOSC, and should be used together with * PCR_CPU_DIV_NUM. */ @@ -1616,7 +1616,7 @@ typedef union { */ uint32_t apb_decrease_div_num:8; /** apb_div_num : R/W; bitpos: [15:8]; default: 0; - * Set as one within (0,1,3) to generate clk_apb drived by clk_ahb. The clk_apb is + * Set as one within (0,1,3) to generate clk_apb driven by clk_ahb. The clk_apb is * div1(default)/div2/div4 of clk_ahb. */ uint32_t apb_div_num:8; @@ -1631,33 +1631,33 @@ typedef union { typedef union { struct { /** pll_240m_clk_en : R/W; bitpos: [0]; default: 1; - * This field is used to open 96 MHz clock (SPLL) drived from SPLL. 0: close, 1: - * open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 96 MHz clock (SPLL) driven from SPLL. 0: close, 1: + * open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_240m_clk_en:1; /** pll_160m_clk_en : R/W; bitpos: [1]; default: 1; - * This field is used to open 64 MHz clock (div3 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 64 MHz clock (div3 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_160m_clk_en:1; /** pll_120m_clk_en : R/W; bitpos: [2]; default: 1; - * This field is used to open 48 MHz clock (div4 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 48 MHz clock (div4 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_120m_clk_en:1; /** pll_80m_clk_en : R/W; bitpos: [3]; default: 1; - * This field is used to open 32 MHz clock (div6 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 32 MHz clock (div6 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_80m_clk_en:1; /** pll_48m_clk_en : R/W; bitpos: [4]; default: 1; - * This field is used to open 16 MHz clock (div10 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 16 MHz clock (div10 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_48m_clk_en:1; /** pll_40m_clk_en : R/W; bitpos: [5]; default: 1; - * This field is used to open 8 MHz clock (div12 of SPLL) drived from SPLL. 0: close, - * 1: open(default). Only avaliable when high-speed clock-source SPLL is active. + * This field is used to open 8 MHz clock (div12 of SPLL) driven from SPLL. 0: close, + * 1: open(default). Only available when high-speed clock-source SPLL is active. */ uint32_t pll_40m_clk_en:1; uint32_t reserved_6:26; diff --git a/components/soc/esp32h2/include/soc/plic_reg.h b/components/soc/esp32h2/register/soc/plic_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/plic_reg.h rename to components/soc/esp32h2/register/soc/plic_reg.h diff --git a/components/soc/esp32h2/include/soc/pmu_reg.h b/components/soc/esp32h2/register/soc/pmu_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/pmu_reg.h rename to components/soc/esp32h2/register/soc/pmu_reg.h diff --git a/components/soc/esp32h2/include/soc/pmu_struct.h b/components/soc/esp32h2/register/soc/pmu_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/pmu_struct.h rename to components/soc/esp32h2/register/soc/pmu_struct.h diff --git a/components/soc/esp32h2/include/soc/reg_base.h b/components/soc/esp32h2/register/soc/reg_base.h similarity index 98% rename from components/soc/esp32h2/include/soc/reg_base.h rename to components/soc/esp32h2/register/soc/reg_base.h index e3801b9c9a6f..1a5a0e4f0a64 100644 --- a/components/soc/esp32h2/include/soc/reg_base.h +++ b/components/soc/esp32h2/register/soc/reg_base.h @@ -24,7 +24,7 @@ #define DR_REG_PCNT_BASE 0x60012000 #define DR_REG_SOC_ETM_BASE 0x60013000 #define DR_REG_MCPWM_BASE 0x60014000 -#define DR_REG_PARl_IO_BASE 0x60015000 +#define DR_REG_PARL_IO_BASE 0x60015000 #define DR_REG_PVT_MONITOR_BASE 0x60019000 #define DR_REG_GDMA_BASE 0x60080000 #define DR_REG_SPI2_BASE 0x60081000 diff --git a/components/soc/esp32h2/include/soc/rmt_reg.h b/components/soc/esp32h2/register/soc/rmt_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/rmt_reg.h rename to components/soc/esp32h2/register/soc/rmt_reg.h diff --git a/components/soc/esp32h2/include/soc/rmt_struct.h b/components/soc/esp32h2/register/soc/rmt_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/rmt_struct.h rename to components/soc/esp32h2/register/soc/rmt_struct.h diff --git a/components/soc/esp32h2/include/soc/rsa_reg.h b/components/soc/esp32h2/register/soc/rsa_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/rsa_reg.h rename to components/soc/esp32h2/register/soc/rsa_reg.h diff --git a/components/soc/esp32h2/include/soc/rsa_struct.h b/components/soc/esp32h2/register/soc/rsa_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/rsa_struct.h rename to components/soc/esp32h2/register/soc/rsa_struct.h diff --git a/components/soc/esp32h2/include/soc/sha_reg.h b/components/soc/esp32h2/register/soc/sha_reg.h similarity index 98% rename from components/soc/esp32h2/include/soc/sha_reg.h rename to components/soc/esp32h2/register/soc/sha_reg.h index b5a4529f4e13..633d53446c7a 100644 --- a/components/soc/esp32h2/include/soc/sha_reg.h +++ b/components/soc/esp32h2/register/soc/sha_reg.h @@ -156,7 +156,7 @@ extern "C" { #define SHA_DATE_S 0 /** SHA_H_MEM register - * Sha H memory which contains intermediate hash or finial hash. + * Sha H memory which contains intermediate hash or final hash. */ #define SHA_H_MEM_REG (DR_REG_SHA_BASE + 0x40) #define SHA_H_MEM_SIZE_BYTES 64 diff --git a/components/soc/esp32h2/include/soc/sha_struct.h b/components/soc/esp32h2/register/soc/sha_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/sha_struct.h rename to components/soc/esp32h2/register/soc/sha_struct.h diff --git a/components/soc/esp32h2/include/soc/soc_etm_reg.h b/components/soc/esp32h2/register/soc/soc_etm_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/soc_etm_reg.h rename to components/soc/esp32h2/register/soc/soc_etm_reg.h diff --git a/components/soc/esp32h2/include/soc/soc_etm_struct.h b/components/soc/esp32h2/register/soc/soc_etm_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/soc_etm_struct.h rename to components/soc/esp32h2/register/soc/soc_etm_struct.h diff --git a/components/soc/esp32h2/include/soc/spi_mem_reg.h b/components/soc/esp32h2/register/soc/spi_mem_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/spi_mem_reg.h rename to components/soc/esp32h2/register/soc/spi_mem_reg.h index adb74b0e0b54..1f084a0acc12 100644 --- a/components/soc/esp32h2/include/soc/spi_mem_reg.h +++ b/components/soc/esp32h2/register/soc/spi_mem_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { @@ -93,23 +93,23 @@ he bit will be cleared once the operation done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_DP_S 21 /* SPI_MEM_FLASH_RES : R/W/SC ;bitpos:[20] ;default: 1'b0 ; */ /*description: This bit combined with reg_resandres bit releases Flash from the power-down stat -e or high performance mode and obtains the devices ID. The bit will be cleared o -nce the operation done.1: enable 0: disable..*/ +e or high performance mode and obtains the devices ID. The bit will be cleared once +the operation done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_RES (BIT(20)) #define SPI_MEM_FLASH_RES_M (BIT(20)) #define SPI_MEM_FLASH_RES_V 0x1 #define SPI_MEM_FLASH_RES_S 20 /* SPI_MEM_FLASH_HPM : R/W/SC ;bitpos:[19] ;default: 1'b0 ; */ -/*description: Drive Flash into high performance mode. The bit will be cleared once the operat -ion done.1: enable 0: disable..*/ +/*description: Drive Flash into high performance mode. The bit will be cleared once the operation +done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_HPM (BIT(19)) #define SPI_MEM_FLASH_HPM_M (BIT(19)) #define SPI_MEM_FLASH_HPM_V 0x1 #define SPI_MEM_FLASH_HPM_S 19 /* SPI_MEM_USR : HRO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: SPI0 USR_CMD start bit, only used when SPI_MEM_AXI_REQ_EN is cleared. An operat -ion will be triggered when the bit is set. The bit will be cleared once the oper -ation done.1: enable 0: disable..*/ +/*description: SPI0 USR_CMD start bit, only used when SPI_MEM_AXI_REQ_EN is cleared. An operation +will be triggered when the bit is set. The bit will be cleared once the operation +done.1: enable 0: disable..*/ #define SPI_MEM_USR (BIT(18)) #define SPI_MEM_USR_M (BIT(18)) #define SPI_MEM_USR_V 0x1 @@ -123,9 +123,9 @@ peration done.1: enable 0: disable..*/ #define SPI_MEM_FLASH_PE_V 0x1 #define SPI_MEM_FLASH_PE_S 17 /* SPI_MEM_SLV_ST : RO ;bitpos:[7:4] ;default: 4'b0 ; */ -/*description: The current status of SPI0 slave FSM: mspi_st. 0: idle state, 1: preparation sta -te, 2: send command state, 3: send address state, 4: wait state, 5: read data st -ate, 6:write data state, 7: done state, 8: read data end state..*/ +/*description: The current status of SPI0 slave FSM: mspi_st. 0: idle state, 1: preparation +state, 2: send command state, 3: send address state, 4: wait state, 5: read data state +, 6:write data state, 7: done state, 8: read data end state..*/ #define SPI_MEM_SLV_ST 0x0000000F #define SPI_MEM_SLV_ST_M ((SPI_MEM_SLV_ST_V)<<(SPI_MEM_SLV_ST_S)) #define SPI_MEM_SLV_ST_V 0xF @@ -157,7 +157,7 @@ lways 1. 0: Others..*/ #define SPI_MEM_DATA_IE_ALWAYS_ON_V 0x1 #define SPI_MEM_DATA_IE_ALWAYS_ON_S 31 /* SPI_MEM_DQS_IE_ALWAYS_ON : HRO ;bitpos:[30] ;default: 1'b0 ; */ -/*description: When accesses to flash, 1: the IE signals of pads connected to SPI_DQS are alway +/*description: When accesses to flash, 1: the IE signals of pads connected to SPI_DQS are always s 1. 0: Others..*/ #define SPI_MEM_DQS_IE_ALWAYS_ON (BIT(30)) #define SPI_MEM_DQS_IE_ALWAYS_ON_M (BIT(30)) @@ -229,14 +229,14 @@ UT and SPI_MEM_FREAD_DOUT. 1: enable 0: disable..*/ #define SPI_MEM_FASTRD_MODE_V 0x1 #define SPI_MEM_FASTRD_MODE_S 13 /* SPI_MEM_TX_CRC_EN : HRO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disabl +/*description: For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disable e.*/ #define SPI_MEM_TX_CRC_EN (BIT(11)) #define SPI_MEM_TX_CRC_EN_M (BIT(11)) #define SPI_MEM_TX_CRC_EN_V 0x1 #define SPI_MEM_TX_CRC_EN_S 11 /* SPI_MEM_FCS_CRC_EN : HRO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: For SPI1, initialize crc32 module before writing encrypted data to flash. Activ +/*description: For SPI1, initialize crc32 module before writing encrypted data to flash. Active e low..*/ #define SPI_MEM_FCS_CRC_EN (BIT(10)) #define SPI_MEM_FCS_CRC_EN_M (BIT(10)) @@ -392,7 +392,7 @@ y the real AXI read data back. 0: When ARSIZE 0~1, MSPI reply SLV_ERR..*/ /* SPI_MEM_CLK_MODE : R/W ;bitpos:[1:0] ;default: 2'h0 ; */ /*description: SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delaye d one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inacti -ve 3: SPI clock is alwasy on..*/ +ve 3: SPI clock is always on..*/ #define SPI_MEM_CLK_MODE 0x00000003 #define SPI_MEM_CLK_MODE_M ((SPI_MEM_CLK_MODE_V)<<(SPI_MEM_CLK_MODE_S)) #define SPI_MEM_CLK_MODE_V 0x3 @@ -422,8 +422,8 @@ whether there is an ECC region or not..*/ #define SPI_MEM_SPLIT_TRANS_EN_V 0x1 #define SPI_MEM_SPLIT_TRANS_EN_S 24 /* SPI_MEM_ECC_16TO18_BYTE_EN : HRO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: Set this bit to enable SPI0 and SPI1 ECC 16 bytes data with 2 ECC bytes mode whe -n accesses flash..*/ +/*description: Set this bit to enable SPI0 and SPI1 ECC 16 bytes data with 2 ECC bytes mode when +accesses flash..*/ #define SPI_MEM_ECC_16TO18_BYTE_EN (BIT(14)) #define SPI_MEM_ECC_16TO18_BYTE_EN_M (BIT(14)) #define SPI_MEM_ECC_16TO18_BYTE_EN_V 0x1 @@ -803,8 +803,8 @@ he register value shall be (bit_num-1)..*/ #define SPI_MEM_SRAM_RDUMMY_CYCLELEN_V 0x3F #define SPI_MEM_SRAM_RDUMMY_CYCLELEN_S 6 /* SPI_MEM_CACHE_SRAM_USR_RCMD : HRO ;bitpos:[5] ;default: 1'b1 ; */ -/*description: For SPI0, In the external RAM mode cache read external RAM for user define comma -nd..*/ +/*description: For SPI0, In the external RAM mode cache read external RAM for user define command +..*/ #define SPI_MEM_CACHE_SRAM_USR_RCMD (BIT(5)) #define SPI_MEM_CACHE_SRAM_USR_RCMD_M (BIT(5)) #define SPI_MEM_CACHE_SRAM_USR_RCMD_V 0x1 @@ -1011,7 +1011,7 @@ e for sram..*/ #define SPI_MEM_SRAM_CLK_REG(i) (REG_SPI_MEM_BASE(i) + 0x50) /* SPI_MEM_SCLK_EQU_SYSCLK : HRO ;bitpos:[31] ;default: 1'b0 ; */ -/*description: For SPI0 external RAM interface, 1: spi_mem_clk is eqaul to system 0: spi_mem_c +/*description: For SPI0 external RAM interface, 1: spi_mem_clk is equal to system 0: spi_mem_c lk is divided from system clock..*/ #define SPI_MEM_SCLK_EQU_SYSCLK (BIT(31)) #define SPI_MEM_SCLK_EQU_SYSCLK_M (BIT(31)) @@ -1269,7 +1269,7 @@ out, status_in[15:0] is valid when two bytes of data are read out), SUS/SUS1/SUS #define SPI_MEM_FLASH_PES_EN_S 5 /* SPI_MEM_PES_PER_EN : R/W ;bitpos:[4] ;default: 1'b0 ; */ /*description: Set this bit to enable PES end triggers PER transfer option. If this bit is 0, a -pplication should send PER after PES is done..*/ +application should send PER after PES is done..*/ #define SPI_MEM_PES_PER_EN (BIT(4)) #define SPI_MEM_PES_PER_EN_M (BIT(4)) #define SPI_MEM_PES_PER_EN_V 0x1 @@ -1291,8 +1291,8 @@ resume command is sent..*/ #define SPI_MEM_FLASH_PER_WAIT_EN_V 0x1 #define SPI_MEM_FLASH_PER_WAIT_EN_S 2 /* SPI_MEM_FLASH_PES : R/W/SC ;bitpos:[1] ;default: 1'b0 ; */ -/*description: program erase suspend bit, program erase suspend operation will be triggered whe -n the bit is set. The bit will be cleared once the operation done.1: enable 0: d +/*description: program erase suspend bit, program erase suspend operation will be triggered when +the bit is set. The bit will be cleared once the operation done.1: enable 0: d isable..*/ #define SPI_MEM_FLASH_PES (BIT(1)) #define SPI_MEM_FLASH_PES_M (BIT(1)) @@ -1536,7 +1536,7 @@ mmand is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles #define SPI_MEM_INT_RAW_REG(i) (REG_SPI_MEM_BASE(i) + 0xC8) /* SPI_MEM_BROWN_OUT_INT_RAW : R/WTC/SS ;bitpos:[10] ;default: 1'b0 ; */ /*description: The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that -chip is loosing power and RTC module sends out brown out close flash request to +chip is losing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others..*/ #define SPI_MEM_BROWN_OUT_INT_RAW (BIT(10)) @@ -1580,8 +1580,8 @@ his bit is triggered when the error times of SPI0/1 ECC read external RAM are eq ual or bigger than SPI_MEM_ECC_ERR_INT_NUM. When SPI_FMEM_ECC_ERR_INT_EN and SP I_SMEM_ECC_ERR_INT_EN are set, this bit is triggered when the total error times of SPI0/1 ECC read external RAM and flash are equal or bigger than SPI_MEM_ECC_E -RR_INT_NUM. When SPI_FMEM_ECC_ERR_INT_EN and SPI_SMEM_ECC_ERR_INT_EN are cleare -d, this bit will not be triggered..*/ +RR_INT_NUM. When SPI_FMEM_ECC_ERR_INT_EN and SPI_SMEM_ECC_ERR_INT_EN are clearer, +this bit will not be triggered..*/ #define SPI_MEM_ECC_ERR_INT_RAW (BIT(5)) #define SPI_MEM_ECC_ERR_INT_RAW_M (BIT(5)) #define SPI_MEM_ECC_ERR_INT_RAW_V 0x1 @@ -2371,9 +2371,9 @@ and RDATA_AFIFO are empty and spi0_mst_st is IDLE..*/ #define SPI_MEM_ALL_FIFO_EMPTY_V 0x1 #define SPI_MEM_ALL_FIFO_EMPTY_S 26 /* SPI_MEM_AXI_ERR_ADDR : R/SS/WTC ;bitpos:[25:0] ;default: 26'h0 ; */ -/*description: This bits show the first AXI write/read invalid error or AXI write flash error a -ddress. It is cleared by when SPI_MEM_AXI_WADDR_ERR_INT_CLR, SPI_MEM_AXI_WR_FLAS -H_ERR_IN_CLR or SPI_MEM_AXI_RADDR_ERR_IN_CLR bit is set..*/ +/*description: This bits show the first AXI write/read invalid error or AXI write flash error +address. It is cleared by when SPI_MEM_AXI_WADDR_ERR_INT_CLR, SPI_MEM_AXI_WR_FLASH_ERR_IN_CLR +or SPI_MEM_AXI_RADDR_ERR_IN_CLR bit is set..*/ #define SPI_MEM_AXI_ERR_ADDR 0x03FFFFFF #define SPI_MEM_AXI_ERR_ADDR_M ((SPI_MEM_AXI_ERR_ADDR_V)<<(SPI_MEM_AXI_ERR_ADDR_S)) #define SPI_MEM_AXI_ERR_ADDR_V 0x3FFFFFF @@ -2679,7 +2679,7 @@ ations..*/ #define SPI_MEM_SMEM_TIMING_CALI_V 0x1 #define SPI_MEM_SMEM_TIMING_CALI_S 1 /* SPI_MEM_SMEM_TIMING_CLK_ENA : HRO ;bitpos:[0] ;default: 1'b1 ; */ -/*description: For sram, the bit is used to enable timing adjust clock for all reading operatio +/*description: For sram, the bit is used to enable timing adjust clock for all reading operation ns..*/ #define SPI_MEM_SMEM_TIMING_CLK_ENA (BIT(0)) #define SPI_MEM_SMEM_TIMING_CLK_ENA_M (BIT(0)) @@ -2937,8 +2937,8 @@ SPI core clock cycles..*/ #define SPI_MEM_SMEM_CS_HOLD_DELAY_V 0x3F #define SPI_MEM_SMEM_CS_HOLD_DELAY_S 25 /* SPI_MEM_SMEM_ECC_16TO18_BYTE_EN : HRO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: Set this bit to enable SPI0 and SPI1 ECC 16 bytes data with 2 ECC bytes mode whe -n accesses external RAM..*/ +/*description: Set this bit to enable SPI0 and SPI1 ECC 16 bytes data with 2 ECC bytes mode when +accesses external RAM..*/ #define SPI_MEM_SMEM_ECC_16TO18_BYTE_EN (BIT(16)) #define SPI_MEM_SMEM_ECC_16TO18_BYTE_EN_M (BIT(16)) #define SPI_MEM_SMEM_ECC_16TO18_BYTE_EN_V 0x1 diff --git a/components/soc/esp32h2/include/soc/spi_mem_struct.h b/components/soc/esp32h2/register/soc/spi_mem_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/spi_mem_struct.h rename to components/soc/esp32h2/register/soc/spi_mem_struct.h index 95578484588d..45810eb9afab 100644 --- a/components/soc/esp32h2/include/soc/spi_mem_struct.h +++ b/components/soc/esp32h2/register/soc/spi_mem_struct.h @@ -9,7 +9,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" typedef volatile struct spi_mem_dev_s { union { @@ -70,7 +70,7 @@ typedef volatile struct spi_mem_dev_s { } ctrl; union { struct { - uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on.*/ + uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is always on.*/ uint32_t cs_hold_dly_res : 10; /*After RES/DP/HPM command is sent, SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 512) SPI_CLK cycles.*/ uint32_t reserved2 : 9; /*reserved*/ uint32_t reg_ar_size0_1_support_en : 1; /*1: MSPI supports ARSIZE 0~3. When ARSIZE =0~2, MSPI read address is 4*n and reply the real AXI read data back. 0: When ARSIZE 0~1, MSPI reply SLV_ERR.*/ @@ -272,7 +272,7 @@ typedef volatile struct spi_mem_dev_s { uint32_t sclkcnt_h : 8; /*For SPI0 external RAM interface, it must be floor((spi_mem_clkcnt_N+1)/2-1).*/ uint32_t sclkcnt_n : 8; /*For SPI0 external RAM interface, it is the divider of spi_mem_clk. So spi_mem_clk frequency is system/(spi_mem_clkcnt_N+1)*/ uint32_t reserved24 : 7; /*reserved*/ - uint32_t sclk_equ_sysclk : 1; /*For SPI0 external RAM interface, 1: spi_mem_clk is eqaul to system 0: spi_mem_clk is divided from system clock.*/ + uint32_t sclk_equ_sysclk : 1; /*For SPI0 external RAM interface, 1: spi_mem_clk is equal to system 0: spi_mem_clk is divided from system clock.*/ }; uint32_t val; } sram_clk; @@ -389,7 +389,7 @@ typedef volatile struct spi_mem_dev_s { uint32_t axi_raddr_err : 1; /*The raw bit for SPI_MEM_AXI_RADDR_ERR_INT interrupt. 1: Triggered when AXI read address is invalid by compared to MMU configuration. 0: Others.*/ uint32_t axi_wr_flash_err : 1; /*The raw bit for SPI_MEM_AXI_WR_FALSH_ERR_INT interrupt. 1: Triggered when AXI write flash request is received. 0: Others.*/ uint32_t axi_waddr_err : 1; /*The raw bit for SPI_MEM_AXI_WADDR_ERR_INT interrupt. 1: Triggered when AXI write address is invalid by compared to MMU configuration. 0: Others.*/ - uint32_t brown_out : 1; /*The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is loosing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others.*/ + uint32_t brown_out : 1; /*The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is losing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others.*/ uint32_t reserved11 : 21; /*reserved*/ }; uint32_t val; @@ -1026,7 +1026,7 @@ typedef volatile struct spi_mem_dev_s { } mmu_power_ctrl; union { struct { - uint32_t reg_crypt_security_level : 3; /*Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1-7: The bigger the number is, the more secure the cryption is. (Note that the performance of cryption will decrease together with this number increasing)*/ + uint32_t reg_crypt_security_level : 3; /*Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1-7: The bigger the number is, the more secure the cryption is. (Note that the performance of cryption will decrease together with this number increasing)*/ uint32_t reg_crypt_calc_d_dpa_en : 1; /*Only available when SPI_CRYPT_SECURITY_LEVEL is not 0. 1: Enable DPA in the calculation that using key 1 or key 2. 0: Enable DPA only in the calculation that using key 1.*/ uint32_t reg_crypt_dpa_selectister : 1; /*1: MSPI XTS DPA clock gate is controlled by SPI_CRYPT_CALC_D_DPA_EN and SPI_CRYPT_SECURITY_LEVEL. 0: Controlled by efuse bits.*/ uint32_t reserved5 : 27; /*reserved*/ diff --git a/components/soc/esp32h2/include/soc/spi_reg.h b/components/soc/esp32h2/register/soc/spi_reg.h similarity index 97% rename from components/soc/esp32h2/include/soc/spi_reg.h rename to components/soc/esp32h2/register/soc/spi_reg.h index 126b6b53243c..d1326cea82a0 100644 --- a/components/soc/esp32h2/include/soc/spi_reg.h +++ b/components/soc/esp32h2/register/soc/spi_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +14,7 @@ extern "C" { /** SPI_CMD_REG register * Command control register */ -#define SPI_CMD_REG (DR_REG_SPI_BASE + 0x0) +#define SPI_CMD_REG(i) (REG_SPI_BASE(i) + 0x0) /** SPI_CONF_BITLEN : R/W; bitpos: [17:0]; default: 0; * Define the APB cycles of SPI_CONF state. Can be configured in CONF state. */ @@ -43,7 +43,7 @@ extern "C" { /** SPI_ADDR_REG register * Address value register */ -#define SPI_ADDR_REG (DR_REG_SPI_BASE + 0x4) +#define SPI_ADDR_REG(i) (REG_SPI_BASE(i) + 0x4) /** SPI_USR_ADDR_VALUE : R/W; bitpos: [31:0]; default: 0; * Address to slave. Can be configured in CONF state. */ @@ -55,7 +55,7 @@ extern "C" { /** SPI_CTRL_REG register * SPI control register */ -#define SPI_CTRL_REG (DR_REG_SPI_BASE + 0x8) +#define SPI_CTRL_REG(i) (REG_SPI_BASE(i) + 0x8) /** SPI_DUMMY_OUT : R/W; bitpos: [3]; default: 0; * 0: In the dummy phase, the FSPI bus signals are not output. 1: In the dummy phase, * the FSPI bus signals are output. Can be configured in CONF state. @@ -188,7 +188,7 @@ extern "C" { /** SPI_CLOCK_REG register * SPI clock control register */ -#define SPI_CLOCK_REG (DR_REG_SPI_BASE + 0xc) +#define SPI_CLOCK_REG(i) (REG_SPI_BASE(i) + 0xc) /** SPI_CLKCNT_L : R/W; bitpos: [5:0]; default: 3; * In the master mode it must be equal to spi_clkcnt_N. In the slave mode it must be * 0. Can be configured in CONF state. @@ -221,7 +221,7 @@ extern "C" { #define SPI_CLKDIV_PRE_V 0x0000000FU #define SPI_CLKDIV_PRE_S 18 /** SPI_CLK_EQU_SYSCLK : R/W; bitpos: [31]; default: 1; - * In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system + * In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system * clock. Can be configured in CONF state. */ #define SPI_CLK_EQU_SYSCLK (BIT(31)) @@ -232,7 +232,7 @@ extern "C" { /** SPI_USER_REG register * SPI USER control register */ -#define SPI_USER_REG (DR_REG_SPI_BASE + 0x10) +#define SPI_USER_REG(i) (REG_SPI_BASE(i) + 0x10) /** SPI_DOUTDIN : R/W; bitpos: [0]; default: 0; * Set the bit to enable full duplex communication. 1: enable 0: disable. Can be * configured in CONF state. @@ -403,7 +403,7 @@ extern "C" { /** SPI_USER1_REG register * SPI USER control register 1 */ -#define SPI_USER1_REG (DR_REG_SPI_BASE + 0x14) +#define SPI_USER1_REG(i) (REG_SPI_BASE(i) + 0x14) /** SPI_USR_DUMMY_CYCLELEN : R/W; bitpos: [7:0]; default: 7; * The length in spi_clk cycles of dummy phase. The register value shall be * (cycle_num-1). Can be configured in CONF state. @@ -449,7 +449,7 @@ extern "C" { /** SPI_USER2_REG register * SPI USER control register 2 */ -#define SPI_USER2_REG (DR_REG_SPI_BASE + 0x18) +#define SPI_USER2_REG(i) (REG_SPI_BASE(i) + 0x18) /** SPI_USR_COMMAND_VALUE : R/W; bitpos: [15:0]; default: 0; * The value of command. Can be configured in CONF state. */ @@ -478,7 +478,7 @@ extern "C" { /** SPI_MS_DLEN_REG register * SPI data bit length control register */ -#define SPI_MS_DLEN_REG (DR_REG_SPI_BASE + 0x1c) +#define SPI_MS_DLEN_REG(i) (REG_SPI_BASE(i) + 0x1c) /** SPI_MS_DATA_BITLEN : R/W; bitpos: [17:0]; default: 0; * The value of these bits is the configured SPI transmission data bit length in * master mode DMA controlled transfer or CPU controlled transfer. The value is also @@ -493,7 +493,7 @@ extern "C" { /** SPI_MISC_REG register * SPI misc register */ -#define SPI_MISC_REG (DR_REG_SPI_BASE + 0x20) +#define SPI_MISC_REG(i) (REG_SPI_BASE(i) + 0x20) /** SPI_CS0_DIS : R/W; bitpos: [0]; default: 0; * SPI CS$n pin enable, 1: disable CS$n, 0: spi_cs$n signal is from/to CS$n pin. Can * be configured in CONF state. @@ -634,7 +634,7 @@ extern "C" { /** SPI_DIN_MODE_REG register * SPI input delay mode configuration */ -#define SPI_DIN_MODE_REG (DR_REG_SPI_BASE + 0x24) +#define SPI_DIN_MODE_REG(i) (REG_SPI_BASE(i) + 0x24) /** SPI_DIN0_MODE : R/W; bitpos: [1:0]; default: 0; * the input signals are delayed by SPI module clock cycles, 0: input without delayed, * 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input @@ -725,7 +725,7 @@ extern "C" { /** SPI_DIN_NUM_REG register * SPI input delay number configuration */ -#define SPI_DIN_NUM_REG (DR_REG_SPI_BASE + 0x28) +#define SPI_DIN_NUM_REG(i) (REG_SPI_BASE(i) + 0x28) /** SPI_DIN0_NUM : R/W; bitpos: [1:0]; default: 0; * the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: * delayed by 2 cycles,... Can be configured in CONF state. @@ -794,7 +794,7 @@ extern "C" { /** SPI_DOUT_MODE_REG register * SPI output delay mode configuration */ -#define SPI_DOUT_MODE_REG (DR_REG_SPI_BASE + 0x2c) +#define SPI_DOUT_MODE_REG(i) (REG_SPI_BASE(i) + 0x2c) /** SPI_DOUT0_MODE : R/W; bitpos: [0]; default: 0; * The output signal $n is delayed by the SPI module clock, 0: output without delayed, * 1: output delay for a SPI module clock cycle at its negative edge. Can be @@ -880,7 +880,7 @@ extern "C" { /** SPI_DMA_CONF_REG register * SPI DMA control register */ -#define SPI_DMA_CONF_REG (DR_REG_SPI_BASE + 0x30) +#define SPI_DMA_CONF_REG(i) (REG_SPI_BASE(i) + 0x30) /** SPI_DMA_OUTFIFO_EMPTY : RO; bitpos: [0]; default: 1; * Records the status of DMA TX FIFO. 1: DMA TX FIFO is not ready for sending data. 0: * DMA TX FIFO is ready for sending data. @@ -972,7 +972,7 @@ extern "C" { /** SPI_DMA_INT_ENA_REG register * SPI interrupt enable register */ -#define SPI_DMA_INT_ENA_REG (DR_REG_SPI_BASE + 0x34) +#define SPI_DMA_INT_ENA_REG(i) (REG_SPI_BASE(i) + 0x34) /** SPI_DMA_INFIFO_FULL_ERR_INT_ENA : R/W; bitpos: [0]; default: 0; * The enable bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1124,7 +1124,7 @@ extern "C" { /** SPI_DMA_INT_CLR_REG register * SPI interrupt clear register */ -#define SPI_DMA_INT_CLR_REG (DR_REG_SPI_BASE + 0x38) +#define SPI_DMA_INT_CLR_REG(i) (REG_SPI_BASE(i) + 0x38) /** SPI_DMA_INFIFO_FULL_ERR_INT_CLR : WT; bitpos: [0]; default: 0; * The clear bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1276,7 +1276,7 @@ extern "C" { /** SPI_DMA_INT_RAW_REG register * SPI interrupt raw register */ -#define SPI_DMA_INT_RAW_REG (DR_REG_SPI_BASE + 0x3c) +#define SPI_DMA_INT_RAW_REG(i) (REG_SPI_BASE(i) + 0x3c) /** SPI_DMA_INFIFO_FULL_ERR_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; * 1: The current data rate of DMA Rx is smaller than that of SPI, which will lose the * receive data. 0: Others. @@ -1450,7 +1450,7 @@ extern "C" { /** SPI_DMA_INT_ST_REG register * SPI interrupt status register */ -#define SPI_DMA_INT_ST_REG (DR_REG_SPI_BASE + 0x40) +#define SPI_DMA_INT_ST_REG(i) (REG_SPI_BASE(i) + 0x40) /** SPI_DMA_INFIFO_FULL_ERR_INT_ST : RO; bitpos: [0]; default: 0; * The status bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1602,7 +1602,7 @@ extern "C" { /** SPI_DMA_INT_SET_REG register * SPI interrupt software set register */ -#define SPI_DMA_INT_SET_REG (DR_REG_SPI_BASE + 0x44) +#define SPI_DMA_INT_SET_REG(i) (REG_SPI_BASE(i) + 0x44) /** SPI_DMA_INFIFO_FULL_ERR_INT_SET : WT; bitpos: [0]; default: 0; * The software set bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt. */ @@ -1754,7 +1754,7 @@ extern "C" { /** SPI_W0_REG register * SPI CPU-controlled buffer0 */ -#define SPI_W0_REG (DR_REG_SPI_BASE + 0x98) +#define SPI_W0_REG(i) (REG_SPI_BASE(i) + 0x98) /** SPI_BUF0 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1766,7 +1766,7 @@ extern "C" { /** SPI_W1_REG register * SPI CPU-controlled buffer1 */ -#define SPI_W1_REG (DR_REG_SPI_BASE + 0x9c) +#define SPI_W1_REG(i) (REG_SPI_BASE(i) + 0x9c) /** SPI_BUF1 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1778,7 +1778,7 @@ extern "C" { /** SPI_W2_REG register * SPI CPU-controlled buffer2 */ -#define SPI_W2_REG (DR_REG_SPI_BASE + 0xa0) +#define SPI_W2_REG(i) (REG_SPI_BASE(i) + 0xa0) /** SPI_BUF2 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1790,7 +1790,7 @@ extern "C" { /** SPI_W3_REG register * SPI CPU-controlled buffer3 */ -#define SPI_W3_REG (DR_REG_SPI_BASE + 0xa4) +#define SPI_W3_REG(i) (REG_SPI_BASE(i) + 0xa4) /** SPI_BUF3 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1802,7 +1802,7 @@ extern "C" { /** SPI_W4_REG register * SPI CPU-controlled buffer4 */ -#define SPI_W4_REG (DR_REG_SPI_BASE + 0xa8) +#define SPI_W4_REG(i) (REG_SPI_BASE(i) + 0xa8) /** SPI_BUF4 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1814,7 +1814,7 @@ extern "C" { /** SPI_W5_REG register * SPI CPU-controlled buffer5 */ -#define SPI_W5_REG (DR_REG_SPI_BASE + 0xac) +#define SPI_W5_REG(i) (REG_SPI_BASE(i) + 0xac) /** SPI_BUF5 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1826,7 +1826,7 @@ extern "C" { /** SPI_W6_REG register * SPI CPU-controlled buffer6 */ -#define SPI_W6_REG (DR_REG_SPI_BASE + 0xb0) +#define SPI_W6_REG(i) (REG_SPI_BASE(i) + 0xb0) /** SPI_BUF6 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1838,7 +1838,7 @@ extern "C" { /** SPI_W7_REG register * SPI CPU-controlled buffer7 */ -#define SPI_W7_REG (DR_REG_SPI_BASE + 0xb4) +#define SPI_W7_REG(i) (REG_SPI_BASE(i) + 0xb4) /** SPI_BUF7 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1850,7 +1850,7 @@ extern "C" { /** SPI_W8_REG register * SPI CPU-controlled buffer8 */ -#define SPI_W8_REG (DR_REG_SPI_BASE + 0xb8) +#define SPI_W8_REG(i) (REG_SPI_BASE(i) + 0xb8) /** SPI_BUF8 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1862,7 +1862,7 @@ extern "C" { /** SPI_W9_REG register * SPI CPU-controlled buffer9 */ -#define SPI_W9_REG (DR_REG_SPI_BASE + 0xbc) +#define SPI_W9_REG(i) (REG_SPI_BASE(i) + 0xbc) /** SPI_BUF9 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1874,7 +1874,7 @@ extern "C" { /** SPI_W10_REG register * SPI CPU-controlled buffer10 */ -#define SPI_W10_REG (DR_REG_SPI_BASE + 0xc0) +#define SPI_W10_REG(i) (REG_SPI_BASE(i) + 0xc0) /** SPI_BUF10 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1886,7 +1886,7 @@ extern "C" { /** SPI_W11_REG register * SPI CPU-controlled buffer11 */ -#define SPI_W11_REG (DR_REG_SPI_BASE + 0xc4) +#define SPI_W11_REG(i) (REG_SPI_BASE(i) + 0xc4) /** SPI_BUF11 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1898,7 +1898,7 @@ extern "C" { /** SPI_W12_REG register * SPI CPU-controlled buffer12 */ -#define SPI_W12_REG (DR_REG_SPI_BASE + 0xc8) +#define SPI_W12_REG(i) (REG_SPI_BASE(i) + 0xc8) /** SPI_BUF12 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1910,7 +1910,7 @@ extern "C" { /** SPI_W13_REG register * SPI CPU-controlled buffer13 */ -#define SPI_W13_REG (DR_REG_SPI_BASE + 0xcc) +#define SPI_W13_REG(i) (REG_SPI_BASE(i) + 0xcc) /** SPI_BUF13 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1922,7 +1922,7 @@ extern "C" { /** SPI_W14_REG register * SPI CPU-controlled buffer14 */ -#define SPI_W14_REG (DR_REG_SPI_BASE + 0xd0) +#define SPI_W14_REG(i) (REG_SPI_BASE(i) + 0xd0) /** SPI_BUF14 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1934,7 +1934,7 @@ extern "C" { /** SPI_W15_REG register * SPI CPU-controlled buffer15 */ -#define SPI_W15_REG (DR_REG_SPI_BASE + 0xd4) +#define SPI_W15_REG(i) (REG_SPI_BASE(i) + 0xd4) /** SPI_BUF15 : R/W/SS; bitpos: [31:0]; default: 0; * data buffer */ @@ -1946,11 +1946,11 @@ extern "C" { /** SPI_SLAVE_REG register * SPI slave control register */ -#define SPI_SLAVE_REG (DR_REG_SPI_BASE + 0xe0) +#define SPI_SLAVE_REG(i) (REG_SPI_BASE(i) + 0xe0) /** SPI_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. Can be configured in CONF state. + * SPI clock is always on. Can be configured in CONF state. */ #define SPI_CLK_MODE 0x00000003U #define SPI_CLK_MODE_M (SPI_CLK_MODE_V << SPI_CLK_MODE_S) @@ -2047,7 +2047,7 @@ extern "C" { /** SPI_SLAVE1_REG register * SPI slave control register 1 */ -#define SPI_SLAVE1_REG (DR_REG_SPI_BASE + 0xe4) +#define SPI_SLAVE1_REG(i) (REG_SPI_BASE(i) + 0xe4) /** SPI_SLV_DATA_BITLEN : R/W/SS; bitpos: [17:0]; default: 0; * The transferred data bit length in SPI slave FD and HD mode. */ @@ -2073,7 +2073,7 @@ extern "C" { /** SPI_CLK_GATE_REG register * SPI module clock and register clock control */ -#define SPI_CLK_GATE_REG (DR_REG_SPI_BASE + 0xe8) +#define SPI_CLK_GATE_REG(i) (REG_SPI_BASE(i) + 0xe8) /** SPI_CLK_EN : R/W; bitpos: [0]; default: 0; * Set this bit to enable clk gate */ @@ -2100,7 +2100,7 @@ extern "C" { /** SPI_DATE_REG register * Version control */ -#define SPI_DATE_REG (DR_REG_SPI_BASE + 0xf0) +#define SPI_DATE_REG(i) (REG_SPI_BASE(i) + 0xf0) /** SPI_DATE : R/W; bitpos: [27:0]; default: 35656448; * SPI register version. */ diff --git a/components/soc/esp32h2/include/soc/spi_struct.h b/components/soc/esp32h2/register/soc/spi_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/spi_struct.h rename to components/soc/esp32h2/register/soc/spi_struct.h index de7705f92c91..76644890a568 100644 --- a/components/soc/esp32h2/include/soc/spi_struct.h +++ b/components/soc/esp32h2/register/soc/spi_struct.h @@ -511,7 +511,7 @@ typedef union { /** clk_mode : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. Can be configured in CONF state. + * SPI clock is always on. Can be configured in CONF state. */ uint32_t clk_mode:2; /** clk_mode_13 : R/W; bitpos: [2]; default: 0; @@ -624,7 +624,7 @@ typedef union { uint32_t clkdiv_pre:4; uint32_t reserved_22:9; /** clk_equ_sysclk : R/W; bitpos: [31]; default: 1; - * In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system + * In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system * clock. Can be configured in CONF state. */ uint32_t clk_equ_sysclk:1; diff --git a/components/soc/esp32h2/include/soc/systimer_reg.h b/components/soc/esp32h2/register/soc/systimer_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/systimer_reg.h rename to components/soc/esp32h2/register/soc/systimer_reg.h diff --git a/components/soc/esp32h2/include/soc/systimer_struct.h b/components/soc/esp32h2/register/soc/systimer_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/systimer_struct.h rename to components/soc/esp32h2/register/soc/systimer_struct.h diff --git a/components/soc/esp32h2/include/soc/tee_reg.h b/components/soc/esp32h2/register/soc/tee_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/tee_reg.h rename to components/soc/esp32h2/register/soc/tee_reg.h diff --git a/components/soc/esp32h2/include/soc/tee_struct.h b/components/soc/esp32h2/register/soc/tee_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/tee_struct.h rename to components/soc/esp32h2/register/soc/tee_struct.h diff --git a/components/soc/esp32h2/include/soc/timer_group_reg.h b/components/soc/esp32h2/register/soc/timer_group_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/timer_group_reg.h rename to components/soc/esp32h2/register/soc/timer_group_reg.h diff --git a/components/soc/esp32h2/include/soc/timer_group_struct.h b/components/soc/esp32h2/register/soc/timer_group_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/timer_group_struct.h rename to components/soc/esp32h2/register/soc/timer_group_struct.h diff --git a/components/soc/esp32c6/include/soc/trace_reg.h b/components/soc/esp32h2/register/soc/trace_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/trace_reg.h rename to components/soc/esp32h2/register/soc/trace_reg.h index a5c3eda9dc77..b363fbd1f8eb 100644 --- a/components/soc/esp32c6/include/soc/trace_reg.h +++ b/components/soc/esp32h2/register/soc/trace_reg.h @@ -154,7 +154,7 @@ extern "C" { #define TRACE_TRIGGER_OFF_V 0x00000001U #define TRACE_TRIGGER_OFF_S 1 /** TRACE_MEM_LOOP : R/W; bitpos: [2]; default: 1; - * if this reg is 1, trace will loop wrtie trace_mem. If is 0, when mem_current_addr + * if this reg is 1, trace will loop write trace_mem. If is 0, when mem_current_addr * at mem_end_addr, it will stop at the mem_end_addr */ #define TRACE_MEM_LOOP (BIT(2)) diff --git a/components/soc/esp32h2/include/soc/trace_struct.h b/components/soc/esp32h2/register/soc/trace_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/trace_struct.h rename to components/soc/esp32h2/register/soc/trace_struct.h index 41677de42885..365ac45dd06a 100644 --- a/components/soc/esp32h2/include/soc/trace_struct.h +++ b/components/soc/esp32h2/register/soc/trace_struct.h @@ -156,7 +156,7 @@ typedef union { */ uint32_t trigger_off:1; /** mem_loop : R/W; bitpos: [2]; default: 1; - * if this reg is 1, trace will loop wrtie trace_mem. If is 0, when mem_current_addr + * if this reg is 1, trace will loop write trace_mem. If is 0, when mem_current_addr * at mem_end_addr, it will stop at the mem_end_addr */ uint32_t mem_loop:1; diff --git a/components/soc/esp32h2/include/soc/twai_reg.h b/components/soc/esp32h2/register/soc/twai_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/twai_reg.h rename to components/soc/esp32h2/register/soc/twai_reg.h diff --git a/components/soc/esp32h2/include/soc/twai_struct.h b/components/soc/esp32h2/register/soc/twai_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/twai_struct.h rename to components/soc/esp32h2/register/soc/twai_struct.h diff --git a/components/soc/esp32h2/include/soc/uart_reg.h b/components/soc/esp32h2/register/soc/uart_reg.h similarity index 99% rename from components/soc/esp32h2/include/soc/uart_reg.h rename to components/soc/esp32h2/register/soc/uart_reg.h index 5c8d8c01f9f9..a8c550dfbb1a 100644 --- a/components/soc/esp32h2/include/soc/uart_reg.h +++ b/components/soc/esp32h2/register/soc/uart_reg.h @@ -100,7 +100,7 @@ extern "C" { #define UART_RXFIFO_TOUT_INT_RAW_V 0x00000001U #define UART_RXFIFO_TOUT_INT_RAW_S 8 /** UART_SW_XON_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ #define UART_SW_XON_INT_RAW (BIT(9)) @@ -285,7 +285,7 @@ extern "C" { #define UART_TX_BRK_DONE_INT_ST_V 0x00000001U #define UART_TX_BRK_DONE_INT_ST_S 12 /** UART_TX_BRK_IDLE_DONE_INT_ST : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ #define UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) @@ -760,7 +760,7 @@ extern "C" { #define UART_STOP_BIT_NUM_V 0x00000003U #define UART_STOP_BIT_NUM_S 4 /** UART_TXD_BRK : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ #define UART_TXD_BRK (BIT(6)) @@ -1326,7 +1326,7 @@ extern "C" { */ #define UART_TOUT_CONF_SYNC_REG(i) (REG_UART_BASE(i) + 0x64) /** UART_RX_TOUT_EN : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ #define UART_RX_TOUT_EN (BIT(0)) #define UART_RX_TOUT_EN_M (UART_RX_TOUT_EN_V << UART_RX_TOUT_EN_S) @@ -1450,7 +1450,7 @@ extern "C" { */ #define UART_HIGHPULSE_REG(i) (REG_UART_BASE(i) + 0x80) /** UART_HIGHPULSE_MIN_CNT : RO; bitpos: [11:0]; default: 4095; - * This register stores the value of the maxinum duration time for the high level + * This register stores the value of the maximum duration time for the high level * pulse. It is used in baud rate-detect process. */ #define UART_HIGHPULSE_MIN_CNT 0x00000FFFU diff --git a/components/soc/esp32h2/include/soc/uart_struct.h b/components/soc/esp32h2/register/soc/uart_struct.h similarity index 99% rename from components/soc/esp32h2/include/soc/uart_struct.h rename to components/soc/esp32h2/register/soc/uart_struct.h index 467f86ff5a44..b1ae4a2b419d 100644 --- a/components/soc/esp32h2/include/soc/uart_struct.h +++ b/components/soc/esp32h2/register/soc/uart_struct.h @@ -49,7 +49,7 @@ typedef union { typedef union { struct { /** rx_tout_en : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ uint32_t rx_tout_en:1; /** rx_tout_flow_dis : R/W; bitpos: [1]; default: 0; @@ -120,7 +120,7 @@ typedef union { */ uint32_t rxfifo_tout:1; /** sw_xon : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ uint32_t sw_xon:1; @@ -238,7 +238,7 @@ typedef union { */ uint32_t tx_brk_done:1; /** tx_brk_idle_done : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ uint32_t tx_brk_idle_done:1; @@ -515,7 +515,7 @@ typedef union { */ uint32_t stop_bit_num:2; /** txd_brk : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ uint32_t txd_brk:1; @@ -1120,7 +1120,7 @@ typedef union { typedef union { struct { /** highpulse_min_cnt : RO; bitpos: [11:0]; default: 4095; - * This register stores the value of the maxinum duration time for the high level + * This register stores the value of the maximum duration time for the high level * pulse. It is used in baud rate-detect process. */ uint32_t highpulse_min_cnt:12; diff --git a/components/soc/esp32h2/include/soc/uhci_reg.h b/components/soc/esp32h2/register/soc/uhci_reg.h similarity index 100% rename from components/soc/esp32h2/include/soc/uhci_reg.h rename to components/soc/esp32h2/register/soc/uhci_reg.h diff --git a/components/soc/esp32h2/include/soc/uhci_struct.h b/components/soc/esp32h2/register/soc/uhci_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/uhci_struct.h rename to components/soc/esp32h2/register/soc/uhci_struct.h diff --git a/components/soc/esp32c6/include/soc/usb_serial_jtag_reg.h b/components/soc/esp32h2/register/soc/usb_serial_jtag_reg.h similarity index 99% rename from components/soc/esp32c6/include/soc/usb_serial_jtag_reg.h rename to components/soc/esp32h2/register/soc/usb_serial_jtag_reg.h index eb4b8a1e039a..e188eea91118 100644 --- a/components/soc/esp32c6/include/soc/usb_serial_jtag_reg.h +++ b/components/soc/esp32h2/register/soc/usb_serial_jtag_reg.h @@ -1144,7 +1144,7 @@ extern "C" { #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_RESET_RD_V 0x00000001U #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_RESET_RD_S 3 /** USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY : RO; bitpos: [4]; default: 1; - * CDC_ACM OUTOUT async FIFO empty signal in read clock domain. + * CDC_ACM OUTPUT async FIFO empty signal in read clock domain. */ #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY (BIT(4)) #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_M (USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_V << USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_S) diff --git a/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32h2/register/soc/usb_serial_jtag_struct.h similarity index 100% rename from components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h rename to components/soc/esp32h2/register/soc/usb_serial_jtag_struct.h diff --git a/components/soc/esp32h2/include/soc/xts_aes_reg.h b/components/soc/esp32h2/register/soc/xts_aes_reg.h similarity index 98% rename from components/soc/esp32h2/include/soc/xts_aes_reg.h rename to components/soc/esp32h2/register/soc/xts_aes_reg.h index ab5f66583ed9..921701bc7421 100644 --- a/components/soc/esp32h2/include/soc/xts_aes_reg.h +++ b/components/soc/esp32h2/register/soc/xts_aes_reg.h @@ -32,7 +32,7 @@ s. Please do not use this field..*/ #define XTS_AES_DESTINATION_REG(i) (REG_SPI_MEM_BASE(i) + 0x344) /* XTS_AES_DESTINATION : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: This bit stores the destination parameter which will be used in manual encryptio +/*description: This bit stores the destination parameter which will be used in manual encryption n calculation. 0: flash(default), 1: psram(reserved). Only default value can be used..*/ #define XTS_AES_DESTINATION (BIT(0)) @@ -54,7 +54,7 @@ size parameter..*/ /* XTS_AES_TRIGGER : WT ;bitpos:[0] ;default: 1'b0 ; */ /*description: Set this bit to trigger the process of manual encryption calculation. This actio n should only be asserted when manual encryption status is 0. After this action, - manual encryption status becomes 1. After calculation is done, manual encryptio + manual encryption status becomes 1. After calculation is done, manual encryption n status becomes 2..*/ #define XTS_AES_TRIGGER (BIT(0)) #define XTS_AES_TRIGGER_M (BIT(0)) @@ -116,7 +116,7 @@ ing key 1..*/ #define XTS_AES_CRYPT_CALC_D_DPA_EN_V 0x1 #define XTS_AES_CRYPT_CALC_D_DPA_EN_S 3 /* XTS_AES_CRYPT_SECURITY_LEVEL : R/W ;bitpos:[2:0] ;default: 3'd7 ; */ -/*description: Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1- +/*description: Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1- 7: The bigger the number is, the more secure the cryption is. (Note that the per formance of cryption will decrease together with this number increasing).*/ #define XTS_AES_CRYPT_SECURITY_LEVEL 0x00000007 diff --git a/components/soc/esp32h2/rmt_periph.c b/components/soc/esp32h2/rmt_periph.c index 7ca8a5ddcbd6..c08da463f299 100644 --- a/components/soc/esp32h2/rmt_periph.c +++ b/components/soc/esp32h2/rmt_periph.c @@ -60,6 +60,7 @@ static const regdma_entries_config_t rmt_regdma_entries[] = { const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = { [0] = { + .module = SLEEP_RETENTION_MODULE_RMT0, .regdma_entry_array = rmt_regdma_entries, .array_size = ARRAY_SIZE(rmt_regdma_entries) }, diff --git a/components/soc/esp32h2/spi_periph.c b/components/soc/esp32h2/spi_periph.c index 213bed6def4c..1ac5f7e40cb4 100644 --- a/components/soc/esp32h2/spi_periph.c +++ b/components/soc/esp32h2/spi_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,29 +13,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { { // MSPI has dedicated iomux pins - .spiclk_out = -1, - .spiclk_in = -1, - .spid_out = -1, - .spiq_out = -1, - .spiwp_out = -1, - .spihd_out = -1, - .spid_in = -1, - .spiq_in = -1, - .spiwp_in = -1, - .spihd_in = -1, - .spics_out = {-1}, - .spics_in = -1, - .spiclk_iomux_pin = -1, - .spid_iomux_pin = -1, - .spiq_iomux_pin = -1, - .spiwp_iomux_pin = -1, - .spihd_iomux_pin = -1, - .spics0_iomux_pin = -1, - .irq = -1, - .irq_dma = -1, - .module = -1, - .hw = NULL, - .func = -1, }, { .spiclk_out = FSPICLK_OUT_IDX, .spiclk_in = FSPICLK_IN_IDX, @@ -57,8 +34,50 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, .irq = ETS_GSPI2_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_SPI2_MODULE, .hw = &GPSPI2, .func = SPI2_FUNC_NUM, } }; + +/** + * Backup registers in Light sleep: (total cnt 12) + * + * cmd + * addr + * ctrl + * clock + * user + * user1 + * user2 + * ms_dlen + * misc + * dma_conf + * dma_int_ena + * slave + */ +#define SPI_RETENTION_REGS_CNT 12 +static const uint32_t spi_regs_map[4] = {0x31ff, 0x1000000, 0x0, 0x0}; +#define SPI_REG_RETENTION_ENTRIES(num) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GPSPI_LINK(0), \ + REG_SPI_BASE(num), REG_SPI_BASE(num), \ + SPI_RETENTION_REGS_CNT, 0, 0, \ + spi_regs_map[0], spi_regs_map[1], \ + spi_regs_map[2], spi_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + /* Additional interrupt setting is required by idf SPI drivers after register recovered */ \ + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_GPSPI_LINK(1), \ + SPI_DMA_INT_SET_REG(num), \ + SPI_TRANS_DONE_INT_SET | SPI_DMA_SEG_TRANS_DONE_INT_SET , \ + UINT32_MAX, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t spi2_regs_retention[] = SPI_REG_RETENTION_ENTRIES(2); // '2' for GPSPI2 + +const spi_reg_retention_info_t spi_reg_retention_info[SOC_SPI_PERIPH_NUM - 1] = { // '-1' to except mspi + { + .module_id = SLEEP_RETENTION_MODULE_GPSPI2, + .entry_array = spi2_regs_retention, + .array_size = ARRAY_SIZE(spi2_regs_retention), + }, +}; diff --git a/components/soc/esp32h2/temperature_sensor_periph.c b/components/soc/esp32h2/temperature_sensor_periph.c index e75c60b31783..348567d3f2f1 100644 --- a/components/soc/esp32h2/temperature_sensor_periph.c +++ b/components/soc/esp32h2/temperature_sensor_periph.c @@ -1,10 +1,14 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" +#include "soc/apb_saradc_reg.h" + const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ @@ -14,3 +18,24 @@ const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_S { 1, 11, -30, 50, 2}, { 2, 10, -40, 20, 3}, }; + +// Temperature sensor sleep retention entries +// Temperature sensor registers require set the reg_update bit to make the configuration take effect + +/* Temperature sensor Registers Context + Include: APB_SARADC_INT_ENA_REG / + APB_SARADC_APB_TSENS_CTRL_REG / APB_SARADC_TSENS_CTRL2_REG / APB_TSENS_WAKE_REG / APB_TSENS_SAMPLE_REG +*/ +#define TEMPERATURE_SENSOR_RETENTION_REGS_CNT 5 +#define TEMPERATURE_SENSOR_RETENTION_MAP_BASE APB_SARADC_INT_ENA_REG +static const uint32_t temperature_sensor_regs_map[4] = {0x6c1, 0, 0, 0}; +static const regdma_entries_config_t temperature_sensor_regs_entries[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TSENS_LINK(0x00), TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_REGS_CNT, 0, 0, temperature_sensor_regs_map[0], temperature_sensor_regs_map[1], temperature_sensor_regs_map[2], temperature_sensor_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const temperature_sensor_reg_ctx_link_t temperature_sensor_regs_retention = { + .link_list = temperature_sensor_regs_entries, + .link_num = ARRAY_SIZE(temperature_sensor_regs_entries), + .module_id = SLEEP_RETENTION_MODULE_TEMP_SENSOR, +}; diff --git a/components/soc/esp32h2/twai_periph.c b/components/soc/esp32h2/twai_periph.c index 5104c78ed85b..b81202a74111 100644 --- a/components/soc/esp32h2/twai_periph.c +++ b/components/soc/esp32h2/twai_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/twai_periph.h" +#include "soc/twai_reg.h" #include "soc/gpio_sig_map.h" const twai_controller_signal_conn_t twai_controller_periph_signals = { @@ -20,3 +21,42 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = { } } }; + +/** + * TWAI Registers to be saved during sleep retention + * - TWAI_MODE_REG + * - TWAI_INTERRUPT_ENABLE_REG + * - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG + * - TWAI_ERR_WARNING_LIMIT_REG + * - TWAI_RX_ERR_CNT_REG + * - TWAI_TX_ERR_CNT_REG + * - TWAI_DATA_x_REG + * - TWAI_CLOCK_DIVIDER_REG + * - TWAI_SW_STANDBY_CFG_REG + * - TWAI_HW_CFG_REG + * - TWAI_HW_STANDBY_CNT_REG + * - TWAI_IDLE_INTR_CNT_REG + * - TWAI_ECO_CFG_REG + * - TWAI_TIMESTAMP_PRESCALER_REG + * - TWAI_TIMESTAMP_CFG_REG +*/ +#define TWAI_RETENTION_REGS_CNT 28 +#define TWAI_RETENTION_REGS_BASE(i) DR_REG_TWAI_BASE +static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0}; +#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \ + TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \ + TWAI_RETENTION_REGS_CNT, 0, 0, \ + twai_regs_map[0], twai_regs_map[1], \ + twai_regs_map[2], twai_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0); +const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = { + [0] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI0, + .entry_array = twai0_regs_retention, + .array_size = ARRAY_SIZE(twai0_regs_retention) + }, +}; diff --git a/components/soc/esp32h2/uart_periph.c b/components/soc/esp32h2/uart_periph.c index 7e44499e1e63..857eeb65e5d4 100644 --- a/components/soc/esp32h2/uart_periph.c +++ b/components/soc/esp32h2/uart_periph.c @@ -118,10 +118,12 @@ static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTI const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { [0] = { + .module = SLEEP_RETENTION_MODULE_UART0, .regdma_entry_array = uart0_regdma_entries, .array_size = ARRAY_SIZE(uart0_regdma_entries), }, [1] = { + .module = SLEEP_RETENTION_MODULE_UART1, .regdma_entry_array = uart1_regdma_entries, .array_size = ARRAY_SIZE(uart1_regdma_entries), }, diff --git a/components/soc/esp32p4/etm_periph.c b/components/soc/esp32p4/etm_periph.c new file mode 100644 index 000000000000..f7b28b02bf7d --- /dev/null +++ b/components/soc/esp32p4/etm_periph.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/etm_periph.h" +#include "soc/soc_etm_reg.h" + +/** + * ETM Registers to be saved during sleep retention + * - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG +*/ +#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1) + +static const regdma_entries_config_t etm_regdma_entries[] = { + // backup stage: save the status of enabled channels + // restore stage: store the enabled channels + [0] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00), + SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0), + .owner = ENTRY(0), + }, + [1] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01), + SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0), + .owner = ENTRY(0), + }, + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [2] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02), + SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0), + .owner = ENTRY(0), + }, +}; + +const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = { + [0] = { + .module = SLEEP_RETENTION_MODULE_ETM0, + .regdma_entry_array = etm_regdma_entries, + .array_size = ARRAY_SIZE(etm_regdma_entries) + }, +}; diff --git a/components/soc/esp32p4/i2c_periph.c b/components/soc/esp32p4/i2c_periph.c index 41c208dda0f0..699e5890decd 100644 --- a/components/soc/esp32p4/i2c_periph.c +++ b/components/soc/esp32p4/i2c_periph.c @@ -34,3 +34,49 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = { .irq = ETS_LP_I2C_INTR_SOURCE, }, }; + +// I2C sleep retention entries +// I2C registers require set the reg_update bit to make the configuration take effect + +/* I2C Registers Context + Include: I2C_SCL_LOW_PERIOD_REG / + I2C_CTR_REG / I2C_TO_REG / I2C_SLAVE_ADDR_REG / I2C_FIFO_CONF_REG + I2C_INT_ENA_REG / I2C_SDA_HOLD_REG / I2C_SDA_SAMPLE_REG / I2C_SCL_START_HOLD_REG + I2C_SCL_RSTART_SETUP_REG / I2C_SCL_STOP_HOLD_REG / I2C_SCL_STOP_SETUP_REG /I2C_FILTER_CFG_REG / I2C_CLK_CONF_REG / I2C_SCL_ST_TIME_OUT_REG / I2C_SCL_MAIN_ST_TIME_OUT_REG / I2C_SCL_SP_CONF_REG / I2C_SCL_STRETCH_CONF_REG +*/ +#define I2C0_RETENTION_REGS_CNT 18 +#define I2C0_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(0) +static const uint32_t i2c0_regs_map[4] = {0xc03f345b, 0x3, 0, 0}; +static const regdma_entries_config_t i2c0_regs_retention[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_REGS_CNT, 0, 0, i2c0_regs_map[0], i2c0_regs_map[1], i2c0_regs_map[2], i2c0_regs_map[3]), \ + .owner = ENTRY(0) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(0), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) }, \ + [2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(0), 0x0, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) }, \ + [3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(0), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) }, \ + [4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(0), 0x0, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) }, \ +}; + +#define I2C1_RETENTION_REGS_CNT 18 +#define I2C1_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(1) +static const uint32_t i2c1_regs_map[4] = {0xc03f345b, 0x3, 0, 0}; +static const regdma_entries_config_t i2c1_regs_retention[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C1_RETENTION_MAP_BASE, I2C1_RETENTION_MAP_BASE, I2C1_RETENTION_REGS_CNT, 0, 0, i2c1_regs_map[0], i2c1_regs_map[1], i2c1_regs_map[2], i2c1_regs_map[3]), \ + .owner = ENTRY(0) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(1), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) }, \ + [2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(1), 0x0, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) }, \ + [3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(1), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) }, \ + [4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(1), 0x0, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) }, \ +}; + +const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM] = { + {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention), SLEEP_RETENTION_MODULE_I2C0}, + {i2c1_regs_retention, ARRAY_SIZE(i2c1_regs_retention), SLEEP_RETENTION_MODULE_I2C1}, +}; diff --git a/components/soc/esp32p4/i2s_periph.c b/components/soc/esp32p4/i2s_periph.c index a0208659f1f1..76d39c743561 100644 --- a/components/soc/esp32p4/i2s_periph.c +++ b/components/soc/esp32p4/i2s_periph.c @@ -5,6 +5,7 @@ */ #include "soc/i2s_periph.h" +#include "soc/i2s_reg.h" #include "soc/gpio_sig_map.h" #include "soc/lp_gpio_sig_map.h" @@ -34,7 +35,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[3] = I2S0_I_SD3_PAD_IN_IDX, .irq = ETS_I2S0_INTR_SOURCE, - .module = PERIPH_I2S0_MODULE, }, [1] = { .mck_out_sig = I2S1_MCLK_PAD_OUT_IDX, @@ -58,7 +58,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[3] = -1, .irq = ETS_I2S1_INTR_SOURCE, - .module = PERIPH_I2S1_MODULE, }, [2] = { .mck_out_sig = I2S2_MCLK_PAD_OUT_IDX, @@ -82,7 +81,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[3] = -1, .irq = ETS_I2S2_INTR_SOURCE, - .module = PERIPH_I2S2_MODULE, }, }; @@ -111,3 +109,54 @@ const i2s_signal_conn_t lp_i2s_periph_signal[SOC_LP_I2S_NUM] = { .irq = ETS_LP_I2S_INTR_SOURCE, }, }; + +/** + * I2S Registers to be saved during sleep retention + * - I2S_RX_CONF_REG + * - I2S_TX_CONF_REG + * - I2S_RX_CONF1_REG + * - I2S_TX_CONF1_REG + * - I2S_TX_PCM2PDM_CONF_REG + * - I2S_TX_PCM2PDM_CONF1_REG + * - I2S_RX_PDM2PCM_CONF_REG + * - I2S_RX_TDM_CTRL_REG + * - I2S_TX_TDM_CTRL_REG + * - I2S_RXEOF_NUM_REG + * - I2S_ETM_CONF_REG +*/ +#define I2S_RETENTION_REGS_CNT 11 +#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG(i) +static const uint32_t i2s_regs_map[4] = {0x12370f, 0x0, 0x0, 0x0}; +#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \ + /* Save/restore the register values */ \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \ + REGDMA_I2S_LINK(0x00), \ + I2S_RETENTION_REGS_BASE(i2s_port), \ + I2S_RETENTION_REGS_BASE(i2s_port), \ + I2S_RETENTION_REGS_CNT, 0, 0, \ + i2s_regs_map[0], i2s_regs_map[1], \ + i2s_regs_map[2], i2s_regs_map[3]), \ + .owner = ENTRY(0)}, \ +}; + +static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t i2s1_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(1); +static const regdma_entries_config_t i2s2_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(2); + +const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = { + [0] = { + .retention_module = SLEEP_RETENTION_MODULE_I2S0, + .entry_array = i2s0_regs_retention, + .array_size = ARRAY_SIZE(i2s0_regs_retention) + }, + [1] = { + .retention_module = SLEEP_RETENTION_MODULE_I2S1, + .entry_array = i2s1_regs_retention, + .array_size = ARRAY_SIZE(i2s1_regs_retention) + }, + [2] = { + .retention_module = SLEEP_RETENTION_MODULE_I2S2, + .entry_array = i2s2_regs_retention, + .array_size = ARRAY_SIZE(i2s2_regs_retention) + }, +}; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 32f555421ef1..81ee7c7c5c3a 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -59,6 +59,10 @@ config SOC_LCDCAM_I80_LCD_SUPPORTED bool default y +config SOC_LCDCAM_RGB_LCD_SUPPORTED + bool + default y + config SOC_MIPI_CSI_SUPPORTED bool default y @@ -263,6 +267,10 @@ config SOC_LP_ADC_SUPPORTED bool default y +config SOC_LP_VAD_SUPPORTED + bool + default y + config SOC_SPIRAM_SUPPORTED bool default y @@ -595,6 +603,10 @@ config SOC_ETM_CHANNELS_PER_GROUP int default 50 +config SOC_ETM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_GPIO_PORT int default 1 @@ -775,6 +787,10 @@ config SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH bool default y +config SOC_I2C_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_LP_I2C_NUM int default 1 @@ -843,6 +859,10 @@ config SOC_I2S_TDM_FULL_DATA_WIDTH bool default y +config SOC_I2S_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_LP_I2S_NUM int default 1 @@ -871,6 +891,10 @@ config SOC_ISP_COLOR_SUPPORTED bool default y +config SOC_ISP_LSC_SUPPORTED + bool + default y + config SOC_ISP_SHARE_CSI_BRG bool default y @@ -983,6 +1007,18 @@ config SOC_ISP_HIST_INTERVAL_NUMS int default 15 +config SOC_ISP_LSC_GRAD_RATIO_INT_BITS + int + default 2 + +config SOC_ISP_LSC_GRAD_RATIO_DEC_BITS + int + default 8 + +config SOC_ISP_LSC_GRAD_RATIO_RES_BITS + int + default 22 + config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK bool default y @@ -991,6 +1027,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 8 @@ -1015,6 +1055,10 @@ config SOC_LEDC_FADE_PARAMS_BIT_WIDTH int default 10 +config SOC_LEDC_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MMU_PERIPH_NUM int default 2 @@ -1143,6 +1187,10 @@ config SOC_LCD_I80_SUPPORTED bool default y +config SOC_LCD_RGB_SUPPORTED + bool + default y + config SOC_LCDCAM_I80_NUM_BUSES int default 1 @@ -1155,6 +1203,14 @@ config SOC_LCDCAM_RGB_NUM_PANELS int default 1 +config SOC_LCDCAM_RGB_DATA_WIDTH + int + default 24 + +config SOC_LCD_SUPPORT_RGB_YUV_CONV + bool + default y + config SOC_MCPWM_GROUPS int default 2 @@ -1215,6 +1271,14 @@ config SOC_MCPWM_CAPTURE_CLK_FROM_GROUP bool default y +config SOC_USB_OTG_PERIPH_NUM + int + default 2 + +config SOC_USB_UTMI_PHY_NUM + int + default 1 + config SOC_PARLIO_GROUPS int default 1 @@ -1255,6 +1319,10 @@ config SOC_PARLIO_TX_SIZE_BY_DMA bool default y +config SOC_PARLIO_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MPI_MEM_BLOCKS_NUM int default 4 @@ -1379,6 +1447,10 @@ config SOC_SPI_MAXIMUM_BUFFER_SIZE int default 64 +config SOC_SPI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool default y @@ -1627,6 +1699,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS bool default y +config SOC_TWAI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_EFUSE_DIS_PAD_JTAG bool default y @@ -1751,6 +1827,10 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y +config SOC_LP_I2S_SUPPORT_VAD + bool + default y + config SOC_COEX_HW_PTI bool default y @@ -1839,6 +1919,14 @@ config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE bool default y +config SOC_SLEEP_SYSTIMER_STALL_WORKAROUND + bool + default y + +config SOC_SLEEP_TGWDT_STOP_WORKAROUND + bool + default y + config SOC_PSRAM_VDD_POWER_MPLL bool default y @@ -1895,6 +1983,10 @@ config SOC_TEMPERATURE_SENSOR_SUPPORT_ETM bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MEM_TCM_SUPPORTED bool default y @@ -1950,3 +2042,7 @@ config SOC_LP_CORE_SUPPORT_ETM config SOC_LP_CORE_SUPPORT_LP_ADC bool default y + +config SOC_LP_CORE_SUPPORT_LP_VAD + bool + default y diff --git a/components/soc/esp32p4/include/soc/dport_access.h b/components/soc/esp32p4/include/soc/dport_access.h index 3747073d224c..189fc786b837 100644 --- a/components/soc/esp32p4/include/soc/dport_access.h +++ b/components/soc/esp32p4/include/soc/dport_access.h @@ -9,7 +9,6 @@ #include #include "soc.h" -#include "uart_reg.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32p4/include/soc/pmu_icg_mapping.h b/components/soc/esp32p4/include/soc/pmu_icg_mapping.h index 9021eaaba7d8..f81d1da6f464 100644 --- a/components/soc/esp32p4/include/soc/pmu_icg_mapping.h +++ b/components/soc/esp32p4/include/soc/pmu_icg_mapping.h @@ -6,8 +6,6 @@ #pragma once -// TODO: IDF-5731 - #define PMU_ICG_APB_ENA_CORE0_CPU 0 #define PMU_ICG_APB_ENA_CORE1_CPU 1 #define PMU_ICG_APB_ENA_CORE0_CLIC 2 diff --git a/components/soc/esp32p4/include/soc/regi2c_brownout.h b/components/soc/esp32p4/include/soc/regi2c_brownout.h index 0504a137056f..b7297808f491 100644 --- a/components/soc/esp32p4/include/soc/regi2c_brownout.h +++ b/components/soc/esp32p4/include/soc/regi2c_brownout.h @@ -14,9 +14,12 @@ * bus. These definitions are used via macros defined in regi2c_ctrl.h. */ -#define I2C_BOD 0x61 +#define I2C_BOD 0x6a #define I2C_BOD_HOSTID 0 -#define I2C_BOD_THRESHOLD 0x5 -#define I2C_BOD_THRESHOLD_MSB 2 -#define I2C_BOD_THRESHOLD_LSB 0 +#define I2C_BOD_THRESHOLD_L 0x9 +#define I2C_BOD_THRESHOLD_L_MSB 4 +#define I2C_BOD_THRESHOLD_L_LSB 2 +#define I2C_BOD_THRESHOLD_H 0x9 +#define I2C_BOD_THRESHOLD_H_MSB 7 +#define I2C_BOD_THRESHOLD_H_LSB 5 diff --git a/components/soc/esp32p4/include/soc/reset_reasons.h b/components/soc/esp32p4/include/soc/reset_reasons.h index 39b792e549e9..4e6952d555be 100644 --- a/components/soc/esp32p4/include/soc/reset_reasons.h +++ b/components/soc/esp32p4/include/soc/reset_reasons.h @@ -45,7 +45,7 @@ typedef enum { RESET_REASON_CORE_USB_JTAG = 0x16, // USB Serial/JTAG controller's JTAG resets the digital core RESET_REASON_CORE_USB_UART = 0x17, // USB Serial/JTAG controller's UART resets the digital core RESET_REASON_CPU_JTAG = 0x18, // Triggered when a reset command from JTAG is received - RESET_REASON_CPU_LOCKUP = 0x1A, // Triggered when the CPU enters lockup (exception inside the execption handler would cause this) + RESET_REASON_CPU_LOCKUP = 0x1A, // Triggered when the CPU enters lockup (exception inside the exception handler would cause this) } soc_reset_reason_t; diff --git a/components/soc/esp32p4/include/soc/retention_periph_defs.h b/components/soc/esp32p4/include/soc/retention_periph_defs.h index f70293e0f781..1f3c144aaf6e 100644 --- a/components/soc/esp32p4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32p4/include/soc/retention_periph_defs.h @@ -15,6 +15,7 @@ extern "C" { typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_MIN = 0, + SLEEP_RETENTION_MODULE_NULL = SLEEP_RETENTION_MODULE_MIN, /* This module is for all peripherals that can't survive from PD_TOP to call init only. Shouldn't have any dependency. */ /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, @@ -25,26 +26,41 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_TG1_WDT = 4, SLEEP_RETENTION_MODULE_TG0_TIMER = 5, SLEEP_RETENTION_MODULE_TG1_TIMER = 6, - /* MISC Peripherals */ - SLEEP_RETENTION_MODULE_UART0 = 7, - SLEEP_RETENTION_MODULE_UART1 = 8, - SLEEP_RETENTION_MODULE_UART2 = 9, - SLEEP_RETENTION_MODULE_UART3 = 10, - SLEEP_RETENTION_MODULE_UART4 = 11, - SLEEP_RETENTION_MODULE_RMT0 = 12, /* AHB_DMA by channel */ - SLEEP_RETENTION_MODULE_AHB_DMA_CH0 = 13, - SLEEP_RETENTION_MODULE_AHB_DMA_CH1 = 14, - SLEEP_RETENTION_MODULE_AHB_DMA_CH2 = 15, + SLEEP_RETENTION_MODULE_AHB_DMA_CH0 = 7, + SLEEP_RETENTION_MODULE_AHB_DMA_CH1 = 8, + SLEEP_RETENTION_MODULE_AHB_DMA_CH2 = 9, /* AXI_DMA by channel */ - SLEEP_RETENTION_MODULE_AXI_DMA_CH0 = 16, - SLEEP_RETENTION_MODULE_AXI_DMA_CH1 = 17, - SLEEP_RETENTION_MODULE_AXI_DMA_CH2 = 18, + SLEEP_RETENTION_MODULE_AXI_DMA_CH0 = 10, + SLEEP_RETENTION_MODULE_AXI_DMA_CH1 = 11, + SLEEP_RETENTION_MODULE_AXI_DMA_CH2 = 12, + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_UART0 = 13, + SLEEP_RETENTION_MODULE_UART1 = 14, + SLEEP_RETENTION_MODULE_UART2 = 15, + SLEEP_RETENTION_MODULE_UART3 = 16, + SLEEP_RETENTION_MODULE_UART4 = 17, + SLEEP_RETENTION_MODULE_RMT0 = 18, + SLEEP_RETENTION_MODULE_I2S0 = 19, + SLEEP_RETENTION_MODULE_I2S1 = 20, + SLEEP_RETENTION_MODULE_I2S2 = 21, + SLEEP_RETENTION_MODULE_I2C0 = 22, + SLEEP_RETENTION_MODULE_I2C1 = 23, + SLEEP_RETENTION_MODULE_ETM0 = 24, + SLEEP_RETENTION_MODULE_TWAI0 = 25, + SLEEP_RETENTION_MODULE_TWAI1 = 26, + SLEEP_RETENTION_MODULE_TWAI2 = 27, + SLEEP_RETENTION_MODULE_PARLIO0 = 28, + SLEEP_RETENTION_MODULE_GPSPI2 = 29, + SLEEP_RETENTION_MODULE_GPSPI3 = 30, + SLEEP_RETENTION_MODULE_LEDC = 31, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; typedef enum periph_retention_module_bitmap { + SLEEP_RETENTION_MODULE_BM_NULL = BIT(SLEEP_RETENTION_MODULE_NULL), + /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, @@ -70,6 +86,19 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_UART3 = BIT(SLEEP_RETENTION_MODULE_UART3), SLEEP_RETENTION_MODULE_BM_UART4 = BIT(SLEEP_RETENTION_MODULE_UART4), SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0), + SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), + SLEEP_RETENTION_MODULE_BM_I2S1 = BIT(SLEEP_RETENTION_MODULE_I2S1), + SLEEP_RETENTION_MODULE_BM_I2S2 = BIT(SLEEP_RETENTION_MODULE_I2S2), + SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), + SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), + SLEEP_RETENTION_MODULE_BM_I2C1 = BIT(SLEEP_RETENTION_MODULE_I2C1), + SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0), + SLEEP_RETENTION_MODULE_BM_TWAI1 = BIT(SLEEP_RETENTION_MODULE_TWAI1), + SLEEP_RETENTION_MODULE_BM_TWAI2 = BIT(SLEEP_RETENTION_MODULE_TWAI2), + SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0), + SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2), + SLEEP_RETENTION_MODULE_BM_GPSPI3 = BIT(SLEEP_RETENTION_MODULE_GPSPI3), + SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC), SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; @@ -91,6 +120,20 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_UART3 \ | SLEEP_RETENTION_MODULE_BM_UART4 \ | SLEEP_RETENTION_MODULE_BM_RMT0 \ + | SLEEP_RETENTION_MODULE_BM_I2S0 \ + | SLEEP_RETENTION_MODULE_BM_I2S1 \ + | SLEEP_RETENTION_MODULE_BM_I2S2 \ + | SLEEP_RETENTION_MODULE_BM_ETM0 \ + | SLEEP_RETENTION_MODULE_BM_I2C0 \ + | SLEEP_RETENTION_MODULE_BM_I2C1 \ + | SLEEP_RETENTION_MODULE_BM_TWAI0 \ + | SLEEP_RETENTION_MODULE_BM_TWAI1 \ + | SLEEP_RETENTION_MODULE_BM_TWAI2 \ + | SLEEP_RETENTION_MODULE_BM_PARLIO0 \ + | SLEEP_RETENTION_MODULE_BM_GPSPI2 \ + | SLEEP_RETENTION_MODULE_BM_GPSPI3 \ + | SLEEP_RETENTION_MODULE_BM_LEDC \ + | SLEEP_RETENTION_MODULE_BM_NULL \ ) #ifdef __cplusplus diff --git a/components/soc/esp32p4/include/soc/soc.h b/components/soc/esp32p4/include/soc/soc.h index baf879c9e5e4..e8e79a9d07db 100644 --- a/components/soc/esp32p4/include/soc/soc.h +++ b/components/soc/esp32p4/include/soc/soc.h @@ -12,7 +12,7 @@ #endif #include "esp_bit_defs.h" -#include "reg_base.h" +#include "soc/reg_base.h" #define PRO_CPU_NUM (0) diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 33cf1c070a8f..ee00d3083d79 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -29,9 +29,9 @@ #define SOC_GPTIMER_SUPPORTED 1 #define SOC_PCNT_SUPPORTED 1 #define SOC_LCDCAM_SUPPORTED 1 -#define SOC_LCDCAM_CAM_SUPPORTED 1 +#define SOC_LCDCAM_CAM_SUPPORTED 1 // support the camera driver based on the LCD_CAM peripheral #define SOC_LCDCAM_I80_LCD_SUPPORTED 1 // support the Intel 8080 bus driver based on the LCD_CAM peripheral -// #define SOC_LCDCAM_RGB_LCD_SUPPORTED 1 // TODO: IDF-7465 +#define SOC_LCDCAM_RGB_LCD_SUPPORTED 1 // support the RGB LCD driver based on the LCD_CAM peripheral #define SOC_MIPI_CSI_SUPPORTED 1 #define SOC_MIPI_DSI_SUPPORTED 1 #define SOC_MCPWM_SUPPORTED 1 @@ -83,6 +83,7 @@ #define SOC_LP_I2S_SUPPORTED 1 #define SOC_LP_SPI_SUPPORTED 1 #define SOC_LP_ADC_SUPPORTED 1 +#define SOC_LP_VAD_SUPPORTED 1 #define SOC_SPIRAM_SUPPORTED 1 #define SOC_PSRAM_DMA_CAPABLE 1 #define SOC_SDMMC_HOST_SUPPORTED 1 @@ -221,6 +222,7 @@ /*-------------------------- ETM CAPS --------------------------------------*/ #define SOC_ETM_GROUPS 1U // Number of ETM groups #define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group +#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-P4 has 1 GPIO peripheral @@ -304,7 +306,7 @@ #define SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS (1) #define SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH (1) -// #define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) // TODO: IDF-9353 +#define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- LP_I2C CAPS -------------------------------------*/ // ESP32-P4 has 1 LP_I2C @@ -328,6 +330,7 @@ #define SOC_I2S_PDM_MAX_TX_LINES (2) // On I2S0 #define SOC_I2S_PDM_MAX_RX_LINES (4) // On I2S0 #define SOC_I2S_TDM_FULL_DATA_WIDTH (1) /*!< No limitation to data bit width when using multiple slots */ +#define SOC_I2S_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up I2S registers before sleep */ /*-------------------------- LP_I2S CAPS -------------------------------------*/ #define SOC_LP_I2S_NUM (1U) @@ -339,6 +342,7 @@ #define SOC_ISP_DVP_SUPPORTED 1 #define SOC_ISP_SHARPEN_SUPPORTED 1 #define SOC_ISP_COLOR_SUPPORTED 1 +#define SOC_ISP_LSC_SUPPORTED 1 #define SOC_ISP_SHARE_CSI_BRG 1 #define SOC_ISP_NUMS 1U @@ -368,16 +372,21 @@ #define SOC_ISP_HIST_BLOCK_Y_NUMS 5 #define SOC_ISP_HIST_SEGMENT_NUMS 16 #define SOC_ISP_HIST_INTERVAL_NUMS 15 +#define SOC_ISP_LSC_GRAD_RATIO_INT_BITS 2 +#define SOC_ISP_LSC_GRAD_RATIO_DEC_BITS 8 +#define SOC_ISP_LSC_GRAD_RATIO_RES_BITS 22 /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (8) #define SOC_LEDC_TIMER_BIT_WIDTH (20) #define SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED (1) #define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16) #define SOC_LEDC_SUPPORT_FADE_STOP (1) #define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10) +#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- MMU CAPS ----------------------------------------*/ #define SOC_MMU_PERIPH_NUM (2U) @@ -399,6 +408,7 @@ #define SOC_PCNT_THRES_POINT_PER_UNIT 2 #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 #define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1 /*!< Support clear signal input */ +// #define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 // TODO: IDF-9907 Waiting for expansion of module ID /*!< The sleep retention feature can help back up PCNT registers before sleep */ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ @@ -421,11 +431,12 @@ /*-------------------------- LCD CAPS ----------------------------------------*/ /* I80 bus and RGB timing generator can't work at the same time in the LCD_CAM peripheral */ #define SOC_LCD_I80_SUPPORTED 1 /*!< support intel 8080 driver */ +#define SOC_LCD_RGB_SUPPORTED 1 /*!< RGB LCD is supported */ #define SOC_LCDCAM_I80_NUM_BUSES 1U /*!< LCD_CAM peripheral provides one LCD Intel 8080 bus */ #define SOC_LCDCAM_I80_BUS_WIDTH 24 /*!< Intel 8080 bus max data width */ #define SOC_LCDCAM_RGB_NUM_PANELS 1U /*!< Support one RGB LCD panel */ -// #define SOC_LCD_RGB_DATA_WIDTH 24 /*!< Number of LCD data lines */ -// #define SOC_LCD_SUPPORT_RGB_YUV_CONV 1 /*!< Support color format conversion between RGB and YUV */ +#define SOC_LCDCAM_RGB_DATA_WIDTH 24 /*!< Number of LCD data lines */ +#define SOC_LCD_SUPPORT_RGB_YUV_CONV 1 /*!< Support color format conversion between RGB and YUV */ /*-------------------------- MCPWM CAPS --------------------------------------*/ #define SOC_MCPWM_GROUPS (2U) ///< 2 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals) @@ -444,9 +455,16 @@ #define SOC_MCPWM_SUPPORT_EVENT_COMPARATOR (1) ///< Support event comparator (based on ETM) #define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP (1) ///< Capture timer shares clock with other PWM timers -/*------------------------ USB SERIAL JTAG CAPS ------------------------------*/ +/*-------------------------- USB CAPS ----------------------------------------*/ +// USB Serial JTAG Caps // #define SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP (1) /*!< Support to maintain minimum usb communication during light sleep */ // TODO: IDF-6395 +// USB OTG Caps +#define SOC_USB_OTG_PERIPH_NUM (2U) + +// USB PHY Caps +#define SOC_USB_UTMI_PHY_NUM (1U) + /*-------------------------- PARLIO CAPS --------------------------------------*/ #define SOC_PARLIO_GROUPS 1U /*!< Number of parallel IO peripherals */ #define SOC_PARLIO_TX_UNITS_PER_GROUP 1U /*!< number of TX units in each group */ @@ -458,6 +476,7 @@ #define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */ #define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */ #define SOC_PARLIO_TX_SIZE_BY_DMA 1 /*!< Transaction length is controlled by DMA instead of indicated by register */ +#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */ /*--------------------------- MPI CAPS ---------------------------------------*/ #define SOC_MPI_MEM_BLOCKS_NUM (4) @@ -524,6 +543,7 @@ #define SOC_SPI_MAX_CS_NUM 6 #define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 +#define SOC_SPI_SUPPORT_SLEEP_RETENTION 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 #define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1 #define SOC_SPI_SUPPORT_DDRCLK 1 @@ -609,11 +629,12 @@ #define SOC_TOUCH_SAMPLE_CFG_NUM (3) /*!< The sample configurations number in total, each sampler can be used to sample on one frequency */ /*-------------------------- TWAI CAPS ---------------------------------------*/ -#define SOC_TWAI_CONTROLLER_NUM 3 -#define SOC_TWAI_CLK_SUPPORT_XTAL 1 -#define SOC_TWAI_BRP_MIN 2 -#define SOC_TWAI_BRP_MAX 32768 -#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_CONTROLLER_NUM 3 +#define SOC_TWAI_CLK_SUPPORT_XTAL 1 +#define SOC_TWAI_BRP_MIN 2 +#define SOC_TWAI_BRP_MAX 32768 +#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- eFuse CAPS----------------------------*/ #define SOC_EFUSE_DIS_PAD_JTAG 1 @@ -660,6 +681,9 @@ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) +/*-------------------------- LP_VAD CAPS -------------------------------------*/ +#define SOC_LP_I2S_SUPPORT_VAD (1) + // TODO: IDF-5679 (Copy from esp32c3, need check) /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) @@ -696,6 +720,8 @@ #define SOC_CPU_IN_TOP_DOMAIN (1) #define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1) +#define SOC_SLEEP_SYSTIMER_STALL_WORKAROUND 1 //TODO IDF-11381: replace with all xtal field clk gate control +#define SOC_SLEEP_TGWDT_STOP_WORKAROUND 1 //TODO IDF-11381: replace with all xtal field clk gate control /*-------------------------- PSRAM CAPS ----------------------------*/ #define SOC_PSRAM_VDD_POWER_MPLL (1) @@ -720,6 +746,8 @@ #define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1) #define SOC_TSENS_IS_INDEPENDENT_FROM_ADC (1) /*!< Temperature sensor is a separate module, not share regs with ADC */ #define SOC_TEMPERATURE_SENSOR_SUPPORT_ETM (1) +// temperature sensor on esp32p4 in under low power domain. +#define SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- Memory CAPS --------------------------*/ #define SOC_MEM_TCM_SUPPORTED (1) @@ -743,3 +771,4 @@ /*------------------------------------- ULP CAPS -------------------------------------*/ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ #define SOC_LP_CORE_SUPPORT_LP_ADC (1) /*!< LP ADC can be accessed from the LP-Core */ +#define SOC_LP_CORE_SUPPORT_LP_VAD (1) /*!< LP VAD can be accessed from the LP-Core */ diff --git a/components/soc/esp32p4/include/soc/usb_dwc_struct.h b/components/soc/esp32p4/include/soc/usb_dwc_struct.h index 728be16b0f66..206d566277e7 100644 --- a/components/soc/esp32p4/include/soc/usb_dwc_struct.h +++ b/components/soc/esp32p4/include/soc/usb_dwc_struct.h @@ -33,7 +33,7 @@ typedef union { uint32_t hnpreq: 1; uint32_t hstsethnpen: 1; uint32_t devhnpen: 1; - uint32_t ehen: 1; + uint32_t ehen: 1; // codespell:ignore ehen uint32_t reserved_13: 2; uint32_t dbncefltrbypass: 1; uint32_t conidsts: 1; diff --git a/components/soc/esp32p4/ledc_periph.c b/components/soc/esp32p4/ledc_periph.c index 6258f357a50b..11a073f72b31 100644 --- a/components/soc/esp32p4/ledc_periph.c +++ b/components/soc/esp32p4/ledc_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,3 +15,162 @@ const ledc_signal_conn_t ledc_periph_signal[1] = { .sig_out0_idx = LEDC_LS_SIG_OUT_PAD_OUT0_IDX, } }; + +/** + * LEDC registers to be saved for sleep retention + * + * channel: + * LEDC_CHx_CONF0_REG, LEDC_CHx_HPOINT_REG, LEDC_CHx_DUTY_R_REG -> LEDC_CHx_DUTY_REG, + * LEDC_CHx_GAMMA_CONF_REG, LEDC_CHx_GAMMA_RANGEi_REG + * + * timer: + * LEDC_TIMERn_CONF_REG, LEDC_TIMERn_CMP_REG, + * + * common: + * LEDC_INT_ENA_REG, + * LEDC_EVT_TASK_EN0_REG, LEDC_EVT_TASK_EN1_REG, LEDC_EVT_TASK_EN2_REG, + * LEDC_CONF_REG, + * + * Note 1: Gamma parameter registers are backuped and restored. But we won't start a fade automatically after wake-up. + * Instead, we will only start a PWM with a fixed duty cycle, the same value as before entering the sleep. + * + * Note 2: For timer/channel registers to get synced, update bits need to be set + * + * Note 3: Gamma RAM registers R/W relies both APB and function clock, therefore, retention requires the existence of function clock + */ +#define LEDC_COMMON_RETENTION_REGS_CNT 5 +#define LEDC_COMMON_RETENTION_REGS_BASE (DR_REG_LEDC_BASE + 0xc8) +static const uint32_t ledc_common_regs_map[4] = {0x1c00001, 0x400, 0x0, 0x0}; +static const regdma_entries_config_t ledc_common_regdma_entries[] = { + // If a fade is in process, the DUTY_CHNG_END_CHx intr bit is enabled, however, we don't want it to be restored after wake-up (no fade after wake-up). + // Therefore, we can set it to 0 before backup the LEDC_INT_ENA_REG. + [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x00), + LEDC_INT_ENA_REG, 0, + (LEDC_DUTY_CHNG_END_CH0_INT_ENA_M | LEDC_DUTY_CHNG_END_CH1_INT_ENA_M | LEDC_DUTY_CHNG_END_CH2_INT_ENA_M | LEDC_DUTY_CHNG_END_CH3_INT_ENA_M | LEDC_DUTY_CHNG_END_CH4_INT_ENA_M | LEDC_DUTY_CHNG_END_CH5_INT_ENA_M | LEDC_DUTY_CHNG_END_CH6_INT_ENA_M | LEDC_DUTY_CHNG_END_CH7_INT_ENA_M), 0, 1), + .owner = LEDC_RETENTION_ENTRY }, + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x01), + LEDC_COMMON_RETENTION_REGS_BASE, LEDC_COMMON_RETENTION_REGS_BASE, + LEDC_COMMON_RETENTION_REGS_CNT, 0, 0, + ledc_common_regs_map[0], ledc_common_regs_map[1], + ledc_common_regs_map[2], ledc_common_regs_map[3]), + .owner = LEDC_RETENTION_ENTRY }, +}; + +#define LEDC_TIMER_RETENTION_ENTRIES(timer) { \ + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_CONF_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_TIMER##timer##_CMP_REG, LEDC_TIMER##timer##_CMP_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_PARA_UP, \ + LEDC_TIMER##timer##_PARA_UP_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +#define LEDC_CHANNEL_RETENTION_REGS_CNT 2 +static const uint32_t ledc_channel_regs_map[4] = {0x3, 0x0, 0x0, 0x0}; +static const uint32_t ledc_channel_gamma_regs_map[4] = {0xffff, 0x0, 0x0, 0x0}; +#define LEDC_CHANNEL_RETENTION_ENTRIES(chan) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x00), \ + LEDC_CH##chan##_CONF0_REG, LEDC_CH##chan##_CONF0_REG, \ + LEDC_CHANNEL_RETENTION_REGS_CNT, 0, 0, \ + ledc_channel_regs_map[0], ledc_channel_regs_map[1], \ + ledc_channel_regs_map[2], ledc_channel_regs_map[3]), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \ + LEDC_CH##chan##_DUTY_R_REG, LEDC_CH##chan##_DUTY_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \ + LEDC_CH##chan##_CONF1_REG, LEDC_DUTY_START_CH##chan, \ + LEDC_DUTY_START_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x03), \ + LEDC_CH##chan##_CONF0_REG, LEDC_PARA_UP_CH##chan, \ + LEDC_PARA_UP_CH##chan##_M, 1, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x04), \ + LEDC_CH##chan##_GAMMA_CONF_REG, LEDC_CH##chan##_GAMMA_CONF_REG, \ + 1, 0, 0), \ + .owner = LEDC_RETENTION_ENTRY }, \ + [5] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x05), \ + LEDC_CH##chan##_GAMMA_RANGE0_REG, LEDC_CH##chan##_GAMMA_RANGE0_REG, \ + SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX, 0, 0, \ + ledc_channel_gamma_regs_map[0], ledc_channel_gamma_regs_map[1], \ + ledc_channel_gamma_regs_map[2], ledc_channel_gamma_regs_map[3]), \ + .owner = LEDC_RETENTION_ENTRY }, \ +} + +static const regdma_entries_config_t ledc_timer0_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_timer1_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_timer2_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_timer3_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(3); + +static const regdma_entries_config_t ledc_channel0_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(0); +static const regdma_entries_config_t ledc_channel1_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(1); +static const regdma_entries_config_t ledc_channel2_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(2); +static const regdma_entries_config_t ledc_channel3_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(3); +static const regdma_entries_config_t ledc_channel4_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(4); +static const regdma_entries_config_t ledc_channel5_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(5); +static const regdma_entries_config_t ledc_channel6_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(6); +static const regdma_entries_config_t ledc_channel7_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(7); + +const ledc_reg_retention_info_t ledc_reg_retention_info = { + .common = { + .regdma_entry_array = ledc_common_regdma_entries, + .array_size = ARRAY_SIZE(ledc_common_regdma_entries), + }, + .timer[0] = { + .regdma_entry_array = ledc_timer0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer0_regdma_entries), + }, + .timer[1] = { + .regdma_entry_array = ledc_timer1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer1_regdma_entries), + }, + .timer[2] = { + .regdma_entry_array = ledc_timer2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer2_regdma_entries), + }, + .timer[3] = { + .regdma_entry_array = ledc_timer3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_timer3_regdma_entries), + }, + .channel[0] = { + .regdma_entry_array = ledc_channel0_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel0_regdma_entries), + }, + .channel[1] = { + .regdma_entry_array = ledc_channel1_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel1_regdma_entries), + }, + .channel[2] = { + .regdma_entry_array = ledc_channel2_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel2_regdma_entries), + }, + .channel[3] = { + .regdma_entry_array = ledc_channel3_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel3_regdma_entries), + }, + .channel[4] = { + .regdma_entry_array = ledc_channel4_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel4_regdma_entries), + }, + .channel[5] = { + .regdma_entry_array = ledc_channel5_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel5_regdma_entries), + }, + .channel[6] = { + .regdma_entry_array = ledc_channel6_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel6_regdma_entries), + }, + .channel[7] = { + .regdma_entry_array = ledc_channel7_regdma_entries, + .array_size = ARRAY_SIZE(ledc_channel7_regdma_entries), + }, + .module_id = SLEEP_RETENTION_MODULE_LEDC, +}; diff --git a/components/soc/esp32p4/parlio_periph.c b/components/soc/esp32p4/parlio_periph.c index 5dcafc7206e2..62ab0ed29577 100644 --- a/components/soc/esp32p4/parlio_periph.c +++ b/components/soc/esp32p4/parlio_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,3 +64,31 @@ const parlio_signal_conn_t parlio_periph_signals = { }, }, }; + +/** + * PARLIO Registers to be saved during sleep retention + * - Tx Configuration registers, e.g.: PARL_IO_TX_DATA_CFG_REG, PARL_IO_TX_GENRL_CFG_REG + * - Rx Configuration registers, e.g.: PARL_IO_RX_MODE_CFG_REG, PARL_IO_RX_DATA_CFG_REG, PARL_IO_RX_GENRL_CFG_REG + * - CLK Configuration registers, e.g.: PARL_IO_RX_CLK_CFG_REG, PARL_IO_TX_CLK_CFG_REG + * - Interrupt enable registers, e.g.: PARL_IO_INT_ENA_REG +*/ +#define PARLIO_RETENTION_REGS_CNT 8 +#define PARLIO_RETENTION_REGS_BASE (DR_REG_PARL_IO_BASE + 0x0) +static const uint32_t parlio_regs_map[4] = {0x60457, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t parlio_regs_retention[] = { + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PARLIO_LINK(0x00), + PARLIO_RETENTION_REGS_BASE, PARLIO_RETENTION_REGS_BASE, + PARLIO_RETENTION_REGS_CNT, 0, 0, + parlio_regs_map[0], parlio_regs_map[1], + parlio_regs_map[2], parlio_regs_map[3]), + .owner = ENTRY(0)}, +}; +const parlio_reg_retention_info_t parlio_reg_retention_info[SOC_PARLIO_GROUPS] = { + [0] = { + .regdma_entry_array = parlio_regs_retention, + .array_size = ARRAY_SIZE(parlio_regs_retention), + .retention_module = SLEEP_RETENTION_MODULE_PARLIO0 + }, +}; diff --git a/components/soc/esp32p4/pcnt_periph.c b/components/soc/esp32p4/pcnt_periph.c index ae7d32b2fe89..4b1cbcac5c69 100644 --- a/components/soc/esp32p4/pcnt_periph.c +++ b/components/soc/esp32p4/pcnt_periph.c @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/pcnt_periph.h" #include "soc/gpio_sig_map.h" +#include "soc/pcnt_reg.h" const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { @@ -68,3 +69,33 @@ const pcnt_signal_conn_t pcnt_periph_signals = { } } }; + +#if SOC_PCNT_SUPPORT_SLEEP_RETENTION +/** + * PCNT Registers to be saved during sleep retention + * - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG... + * - Step Configuration registers, e.g.: PCNT_U0_CHANGE_CONF_REG, PCNT_U1_CHANGE_CONF_REG, PCNT_U2_CHANGE_CONF_REG, PCNT_U3_CHANGE_CONF_REG + * - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG +*/ +#define PCNT_RETENTION_REGS_CNT 18 +#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0) +static const uint32_t pcnt_regs_map[4] = {0x1f040fff, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t pcnt_regs_retention[] = { + // backup stage: save configuration registers + // restore stage: restore the configuration registers + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \ + PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \ + PCNT_RETENTION_REGS_CNT, 0, 0, \ + pcnt_regs_map[0], pcnt_regs_map[1], \ + pcnt_regs_map[2], pcnt_regs_map[3]), \ + .owner = ENTRY(0)}, \ +}; + +const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = { + [0] = { + .regdma_entry_array = pcnt_regs_retention, + .array_size = ARRAY_SIZE(pcnt_regs_retention), + .retention_module = SLEEP_RETENTION_MODULE_PCNT0 + }, +}; +#endif // SOC_PCNT_SUPPORT_SLEEP_RETENTION diff --git a/components/soc/esp32p4/register/soc/.gitkeep b/components/soc/esp32p4/register/soc/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/soc/esp32p4/include/soc/adc_reg.h b/components/soc/esp32p4/register/soc/adc_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/adc_reg.h rename to components/soc/esp32p4/register/soc/adc_reg.h diff --git a/components/soc/esp32p4/include/soc/adc_struct.h b/components/soc/esp32p4/register/soc/adc_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/adc_struct.h rename to components/soc/esp32p4/register/soc/adc_struct.h diff --git a/components/soc/esp32p4/include/soc/aes_reg.h b/components/soc/esp32p4/register/soc/aes_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/aes_reg.h rename to components/soc/esp32p4/register/soc/aes_reg.h diff --git a/components/soc/esp32p4/include/soc/aes_struct.h b/components/soc/esp32p4/register/soc/aes_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/aes_struct.h rename to components/soc/esp32p4/register/soc/aes_struct.h diff --git a/components/soc/esp32p4/include/soc/ahb_dma_reg.h b/components/soc/esp32p4/register/soc/ahb_dma_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/ahb_dma_reg.h rename to components/soc/esp32p4/register/soc/ahb_dma_reg.h diff --git a/components/soc/esp32p4/include/soc/ahb_dma_struct.h b/components/soc/esp32p4/register/soc/ahb_dma_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/ahb_dma_struct.h rename to components/soc/esp32p4/register/soc/ahb_dma_struct.h diff --git a/components/soc/esp32p4/include/soc/assist_debug_reg.h b/components/soc/esp32p4/register/soc/assist_debug_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/assist_debug_reg.h rename to components/soc/esp32p4/register/soc/assist_debug_reg.h index 89c49a9cc6fc..f8f13c353191 100644 --- a/components/soc/esp32p4/include/soc/assist_debug_reg.h +++ b/components/soc/esp32p4/register/soc/assist_debug_reg.h @@ -435,7 +435,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_SP_MIN_REG (DR_REG_ASSIST_DEBUG_BASE + 0x38) /** ASSIST_DEBUG_CORE_0_SP_MIN : R/W; bitpos: [31:0]; default: 0; - * core0 sp region configuration regsiter + * core0 sp region configuration register */ #define ASSIST_DEBUG_CORE_0_SP_MIN 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_0_SP_MIN_M (ASSIST_DEBUG_CORE_0_SP_MIN_V << ASSIST_DEBUG_CORE_0_SP_MIN_S) @@ -459,7 +459,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_0_SP_PC_REG (DR_REG_ASSIST_DEBUG_BASE + 0x40) /** ASSIST_DEBUG_CORE_0_SP_PC : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ #define ASSIST_DEBUG_CORE_0_SP_PC 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_0_SP_PC_M (ASSIST_DEBUG_CORE_0_SP_PC_V << ASSIST_DEBUG_CORE_0_SP_PC_S) @@ -486,7 +486,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGEN_S 1 /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG (DR_REG_ASSIST_DEBUG_BASE + 0x48) /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC : RO; bitpos: [31:0]; default: 0; @@ -498,7 +498,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_S 0 /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP_REG (DR_REG_ASSIST_DEBUG_BASE + 0x4c) /** ASSIST_DEBUG_CORE_0_RCD_PDEBUGSP : RO; bitpos: [31:0]; default: 0; @@ -1103,7 +1103,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_1_SP_MIN_REG (DR_REG_ASSIST_DEBUG_BASE + 0xb8) /** ASSIST_DEBUG_CORE_1_SP_MIN : R/W; bitpos: [31:0]; default: 0; - * core1 sp region configuration regsiter + * core1 sp region configuration register */ #define ASSIST_DEBUG_CORE_1_SP_MIN 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_1_SP_MIN_M (ASSIST_DEBUG_CORE_1_SP_MIN_V << ASSIST_DEBUG_CORE_1_SP_MIN_S) @@ -1127,7 +1127,7 @@ extern "C" { */ #define ASSIST_DEBUG_CORE_1_SP_PC_REG (DR_REG_ASSIST_DEBUG_BASE + 0xc0) /** ASSIST_DEBUG_CORE_1_SP_PC : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ #define ASSIST_DEBUG_CORE_1_SP_PC 0xFFFFFFFFU #define ASSIST_DEBUG_CORE_1_SP_PC_M (ASSIST_DEBUG_CORE_1_SP_PC_V << ASSIST_DEBUG_CORE_1_SP_PC_S) @@ -1154,7 +1154,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_1_RCD_PDEBUGEN_S 1 /** ASSIST_DEBUG_CORE_1_RCD_PDEBUGPC_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_1_RCD_PDEBUGPC_REG (DR_REG_ASSIST_DEBUG_BASE + 0xc8) /** ASSIST_DEBUG_CORE_1_RCD_PDEBUGPC : RO; bitpos: [31:0]; default: 0; @@ -1166,7 +1166,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_1_RCD_PDEBUGPC_S 0 /** ASSIST_DEBUG_CORE_1_RCD_PDEBUGSP_REG register - * record status regsiter + * record status register */ #define ASSIST_DEBUG_CORE_1_RCD_PDEBUGSP_REG (DR_REG_ASSIST_DEBUG_BASE + 0xcc) /** ASSIST_DEBUG_CORE_1_RCD_PDEBUGSP : RO; bitpos: [31:0]; default: 0; diff --git a/components/soc/esp32p4/include/soc/assist_debug_struct.h b/components/soc/esp32p4/register/soc/assist_debug_struct.h similarity index 98% rename from components/soc/esp32p4/include/soc/assist_debug_struct.h rename to components/soc/esp32p4/register/soc/assist_debug_struct.h index 88dd72df88e6..645e5a1cf081 100644 --- a/components/soc/esp32p4/include/soc/assist_debug_struct.h +++ b/components/soc/esp32p4/register/soc/assist_debug_struct.h @@ -197,7 +197,7 @@ typedef union { typedef union { struct { /** core_0_sp_min : R/W; bitpos: [31:0]; default: 0; - * core0 sp region configuration regsiter + * core0 sp region configuration register */ uint32_t core_0_sp_min:32; }; @@ -223,7 +223,7 @@ typedef union { typedef union { struct { /** core_0_sp_pc : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ uint32_t core_0_sp_pc:32; }; @@ -416,7 +416,7 @@ typedef union { typedef union { struct { /** core_1_sp_min : R/W; bitpos: [31:0]; default: 0; - * core1 sp region configuration regsiter + * core1 sp region configuration register */ uint32_t core_1_sp_min:32; }; @@ -442,7 +442,7 @@ typedef union { typedef union { struct { /** core_1_sp_pc : RO; bitpos: [31:0]; default: 0; - * This regsiter stores the PC when trigger stack monitor. + * This register stores the PC when trigger stack monitor. */ uint32_t core_1_sp_pc:32; }; @@ -752,7 +752,7 @@ typedef union { } assist_debug_core_1_intr_clr_reg_t; -/** Group: pc reording configuration register */ +/** Group: pc recording configuration register */ /** Type of core_0_rcd_en register * record enable configuration register */ @@ -790,9 +790,9 @@ typedef union { } assist_debug_core_1_rcd_en_reg_t; -/** Group: pc reording status register */ +/** Group: pc recording status register */ /** Type of core_0_rcd_pdebugpc register - * record status regsiter + * record status register */ typedef union { struct { @@ -805,7 +805,7 @@ typedef union { } assist_debug_core_0_rcd_pdebugpc_reg_t; /** Type of core_0_rcd_pdebugsp register - * record status regsiter + * record status register */ typedef union { struct { @@ -818,7 +818,7 @@ typedef union { } assist_debug_core_0_rcd_pdebugsp_reg_t; /** Type of core_1_rcd_pdebugpc register - * record status regsiter + * record status register */ typedef union { struct { @@ -831,7 +831,7 @@ typedef union { } assist_debug_core_1_rcd_pdebugpc_reg_t; /** Type of core_1_rcd_pdebugsp register - * record status regsiter + * record status register */ typedef union { struct { @@ -844,7 +844,7 @@ typedef union { } assist_debug_core_1_rcd_pdebugsp_reg_t; -/** Group: exception monitor regsiter */ +/** Group: exception monitor register */ /** Type of core_0_iram0_exception_monitor_0 register * exception monitor status register0 */ diff --git a/components/soc/esp32p4/include/soc/axi_dma_reg.h b/components/soc/esp32p4/register/soc/axi_dma_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/axi_dma_reg.h rename to components/soc/esp32p4/register/soc/axi_dma_reg.h index e3dfc907dbd3..8f2775e79592 100644 --- a/components/soc/esp32p4/include/soc/axi_dma_reg.h +++ b/components/soc/esp32p4/register/soc/axi_dma_reg.h @@ -770,7 +770,7 @@ extern "C" { #define AXI_DMA_RX_CH_ARB_WEIGH_CH0_V 0x0000000FU #define AXI_DMA_RX_CH_ARB_WEIGH_CH0_S 4 /** AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH0 : R/W; bitpos: [8]; default: 0; - * 0: mean not optimazation weight function ,1: mean optimazation + * 0: mean not optimization weight function ,1: mean optimization */ #define AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH0 (BIT(8)) #define AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH0_M (AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH0_V << AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH0_S) @@ -1654,7 +1654,7 @@ extern "C" { #define AXI_DMA_RX_CH_ARB_WEIGH_CH1_V 0x0000000FU #define AXI_DMA_RX_CH_ARB_WEIGH_CH1_S 4 /** AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH1 : R/W; bitpos: [8]; default: 0; - * 0: mean not optimazation weight function ,1: mean optimazation + * 0: mean not optimization weight function ,1: mean optimization */ #define AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH1 (BIT(8)) #define AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH1_M (AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH1_V << AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH1_S) @@ -2538,7 +2538,7 @@ extern "C" { #define AXI_DMA_RX_CH_ARB_WEIGH_CH2_V 0x0000000FU #define AXI_DMA_RX_CH_ARB_WEIGH_CH2_S 4 /** AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH2 : R/W; bitpos: [8]; default: 0; - * 0: mean not optimazation weight function ,1: mean optimazation + * 0: mean not optimization weight function ,1: mean optimization */ #define AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH2 (BIT(8)) #define AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH2_M (AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH2_V << AXI_DMA_RX_ARB_WEIGH_OPT_DIR_CH2_S) @@ -3384,7 +3384,7 @@ extern "C" { #define AXI_DMA_TX_CH_ARB_WEIGH_CH0_V 0x0000000FU #define AXI_DMA_TX_CH_ARB_WEIGH_CH0_S 4 /** AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH0 : R/W; bitpos: [8]; default: 0; - * 0: mean not optimazation weight function ,1: mean optimazation + * 0: mean not optimization weight function ,1: mean optimization */ #define AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH0 (BIT(8)) #define AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH0_M (AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH0_V << AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH0_S) @@ -4230,7 +4230,7 @@ extern "C" { #define AXI_DMA_TX_CH_ARB_WEIGH_CH1_V 0x0000000FU #define AXI_DMA_TX_CH_ARB_WEIGH_CH1_S 4 /** AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH1 : R/W; bitpos: [8]; default: 0; - * 0: mean not optimazation weight function ,1: mean optimazation + * 0: mean not optimization weight function ,1: mean optimization */ #define AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH1 (BIT(8)) #define AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH1_M (AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH1_V << AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH1_S) @@ -5076,7 +5076,7 @@ extern "C" { #define AXI_DMA_TX_CH_ARB_WEIGH_CH2_V 0x0000000FU #define AXI_DMA_TX_CH_ARB_WEIGH_CH2_S 4 /** AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH2 : R/W; bitpos: [8]; default: 0; - * 0: mean not optimazation weight function ,1: mean optimazation + * 0: mean not optimization weight function ,1: mean optimization */ #define AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH2 (BIT(8)) #define AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH2_M (AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH2_V << AXI_DMA_TX_ARB_WEIGH_OPT_DIR_CH2_S) @@ -5490,11 +5490,11 @@ extern "C" { #define AXI_DMA_RDN_ECO_LOW_S 0 /** AXI_DMA_WRESP_CNT_REG register - * AXI wr responce cnt register. + * AXI wr response cnt register. */ #define AXI_DMA_WRESP_CNT_REG (DR_REG_AXI_DMA_BASE + 0x2b8) /** AXI_DMA_WRESP_CNT : RO; bitpos: [3:0]; default: 0; - * axi wr responce cnt reg. + * axi wr response cnt reg. */ #define AXI_DMA_WRESP_CNT 0x0000000FU #define AXI_DMA_WRESP_CNT_M (AXI_DMA_WRESP_CNT_V << AXI_DMA_WRESP_CNT_S) @@ -5502,11 +5502,11 @@ extern "C" { #define AXI_DMA_WRESP_CNT_S 0 /** AXI_DMA_RRESP_CNT_REG register - * AXI wr responce cnt register. + * AXI wr response cnt register. */ #define AXI_DMA_RRESP_CNT_REG (DR_REG_AXI_DMA_BASE + 0x2bc) /** AXI_DMA_RRESP_CNT : RO; bitpos: [3:0]; default: 0; - * axi rd responce cnt reg. + * axi rd response cnt reg. */ #define AXI_DMA_RRESP_CNT 0x0000000FU #define AXI_DMA_RRESP_CNT_M (AXI_DMA_RRESP_CNT_V << AXI_DMA_RRESP_CNT_S) diff --git a/components/soc/esp32p4/include/soc/axi_dma_struct.h b/components/soc/esp32p4/register/soc/axi_dma_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/axi_dma_struct.h rename to components/soc/esp32p4/register/soc/axi_dma_struct.h diff --git a/components/soc/esp32p4/include/soc/bitscrambler_reg.h b/components/soc/esp32p4/register/soc/bitscrambler_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/bitscrambler_reg.h rename to components/soc/esp32p4/register/soc/bitscrambler_reg.h index 44bfc3c87457..4b8fbe5df572 100644 --- a/components/soc/esp32p4/include/soc/bitscrambler_reg.h +++ b/components/soc/esp32p4/register/soc/bitscrambler_reg.h @@ -216,7 +216,7 @@ extern "C" { #define BITSCRAMBLER_TX_COND_MODE_S 4 /** BITSCRAMBLER_TX_FETCH_MODE : R/W; bitpos: [5]; default: 0; * write this bit to set the bitscrambler tx core fetch instruction mode, 0: prefetch - * by reset, 1: fetch by instrutions + * by reset, 1: fetch by instructions */ #define BITSCRAMBLER_TX_FETCH_MODE (BIT(5)) #define BITSCRAMBLER_TX_FETCH_MODE_M (BITSCRAMBLER_TX_FETCH_MODE_V << BITSCRAMBLER_TX_FETCH_MODE_S) @@ -291,7 +291,7 @@ extern "C" { #define BITSCRAMBLER_RX_COND_MODE_S 4 /** BITSCRAMBLER_RX_FETCH_MODE : R/W; bitpos: [5]; default: 0; * write this bit to set the bitscrambler rx core fetch instruction mode, 0: prefetch - * by reset, 1: fetch by instrutions + * by reset, 1: fetch by instructions */ #define BITSCRAMBLER_RX_FETCH_MODE (BIT(5)) #define BITSCRAMBLER_RX_FETCH_MODE_M (BITSCRAMBLER_RX_FETCH_MODE_V << BITSCRAMBLER_RX_FETCH_MODE_S) diff --git a/components/soc/esp32p4/include/soc/bitscrambler_struct.h b/components/soc/esp32p4/register/soc/bitscrambler_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/bitscrambler_struct.h rename to components/soc/esp32p4/register/soc/bitscrambler_struct.h index 007c244d5050..6a451171ba11 100644 --- a/components/soc/esp32p4/include/soc/bitscrambler_struct.h +++ b/components/soc/esp32p4/register/soc/bitscrambler_struct.h @@ -208,7 +208,7 @@ typedef union { uint32_t tx_cond_mode:1; /** tx_fetch_mode : R/W; bitpos: [5]; default: 0; * write this bit to set the bitscrambler tx core fetch instruction mode, 0: prefetch - * by reset, 1: fetch by instrutions + * by reset, 1: fetch by instructions */ uint32_t tx_fetch_mode:1; /** tx_halt_mode : R/W; bitpos: [6]; default: 0; @@ -261,7 +261,7 @@ typedef union { uint32_t rx_cond_mode:1; /** rx_fetch_mode : R/W; bitpos: [5]; default: 0; * write this bit to set the bitscrambler rx core fetch instruction mode, 0: prefetch - * by reset, 1: fetch by instrutions + * by reset, 1: fetch by instructions */ uint32_t rx_fetch_mode:1; /** rx_halt_mode : R/W; bitpos: [6]; default: 0; diff --git a/components/soc/esp32p4/include/soc/cache_reg.h b/components/soc/esp32p4/register/soc/cache_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/cache_reg.h rename to components/soc/esp32p4/register/soc/cache_reg.h index b3cc3cd039c7..e80afcd41bd2 100644 --- a/components/soc/esp32p4/include/soc/cache_reg.h +++ b/components/soc/esp32p4/register/soc/cache_reg.h @@ -4270,7 +4270,7 @@ extern "C" { #define CACHE_L1_UNALLOCATE_BUFFER_CLEAR_REG (DR_REG_CACHE_BASE + 0x258) /** CACHE_L1_ICACHE0_UNALLOC_CLR : R/W; bitpos: [0]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache0 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_ICACHE0_UNALLOC_CLR (BIT(0)) #define CACHE_L1_ICACHE0_UNALLOC_CLR_M (CACHE_L1_ICACHE0_UNALLOC_CLR_V << CACHE_L1_ICACHE0_UNALLOC_CLR_S) @@ -4278,7 +4278,7 @@ extern "C" { #define CACHE_L1_ICACHE0_UNALLOC_CLR_S 0 /** CACHE_L1_ICACHE1_UNALLOC_CLR : R/W; bitpos: [1]; default: 0; * The bit is used to clear the unallocate request buffer of l1 icache1 where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_ICACHE1_UNALLOC_CLR (BIT(1)) #define CACHE_L1_ICACHE1_UNALLOC_CLR_M (CACHE_L1_ICACHE1_UNALLOC_CLR_V << CACHE_L1_ICACHE1_UNALLOC_CLR_S) @@ -4300,7 +4300,7 @@ extern "C" { #define CACHE_L1_ICACHE3_UNALLOC_CLR_S 3 /** CACHE_L1_DCACHE_UNALLOC_CLR : R/W; bitpos: [4]; default: 0; * The bit is used to clear the unallocate request buffer of l1 dcache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L1_DCACHE_UNALLOC_CLR (BIT(4)) #define CACHE_L1_DCACHE_UNALLOC_CLR_M (CACHE_L1_DCACHE_UNALLOC_CLR_V << CACHE_L1_DCACHE_UNALLOC_CLR_S) @@ -6156,7 +6156,7 @@ extern "C" { #define CACHE_L2_UNALLOCATE_BUFFER_CLEAR_REG (DR_REG_CACHE_BASE + 0x3b8) /** CACHE_L2_CACHE_UNALLOC_CLR : R/W; bitpos: [5]; default: 0; * The bit is used to clear the unallocate request buffer of l2 icache where the - * unallocate request is responsed but not completed. + * unallocate request is responded but not completed. */ #define CACHE_L2_CACHE_UNALLOC_CLR (BIT(5)) #define CACHE_L2_CACHE_UNALLOC_CLR_M (CACHE_L2_CACHE_UNALLOC_CLR_V << CACHE_L2_CACHE_UNALLOC_CLR_S) diff --git a/components/soc/esp32p4/include/soc/cache_struct.h b/components/soc/esp32p4/register/soc/cache_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/cache_struct.h rename to components/soc/esp32p4/register/soc/cache_struct.h diff --git a/components/soc/esp32p4/include/soc/dma2d_reg.h b/components/soc/esp32p4/register/soc/dma2d_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/dma2d_reg.h rename to components/soc/esp32p4/register/soc/dma2d_reg.h diff --git a/components/soc/esp32p4/include/soc/dma2d_struct.h b/components/soc/esp32p4/register/soc/dma2d_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/dma2d_struct.h rename to components/soc/esp32p4/register/soc/dma2d_struct.h diff --git a/components/soc/esp32p4/include/soc/dma_pms_reg.h b/components/soc/esp32p4/register/soc/dma_pms_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/dma_pms_reg.h rename to components/soc/esp32p4/register/soc/dma_pms_reg.h diff --git a/components/soc/esp32p4/include/soc/dma_pms_struct.h b/components/soc/esp32p4/register/soc/dma_pms_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/dma_pms_struct.h rename to components/soc/esp32p4/register/soc/dma_pms_struct.h diff --git a/components/soc/esp32p4/include/soc/ds_reg.h b/components/soc/esp32p4/register/soc/ds_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/ds_reg.h rename to components/soc/esp32p4/register/soc/ds_reg.h diff --git a/components/soc/esp32p4/include/soc/ds_struct.h b/components/soc/esp32p4/register/soc/ds_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/ds_struct.h rename to components/soc/esp32p4/register/soc/ds_struct.h diff --git a/components/soc/esp32p4/include/soc/dw_gdma_reg.h b/components/soc/esp32p4/register/soc/dw_gdma_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/dw_gdma_reg.h rename to components/soc/esp32p4/register/soc/dw_gdma_reg.h diff --git a/components/soc/esp32p4/include/soc/dw_gdma_struct.h b/components/soc/esp32p4/register/soc/dw_gdma_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/dw_gdma_struct.h rename to components/soc/esp32p4/register/soc/dw_gdma_struct.h diff --git a/components/soc/esp32p4/include/soc/ecc_mult_reg.h b/components/soc/esp32p4/register/soc/ecc_mult_reg.h similarity index 97% rename from components/soc/esp32p4/include/soc/ecc_mult_reg.h rename to components/soc/esp32p4/register/soc/ecc_mult_reg.h index 2bec4bb8c79a..54033489df3d 100644 --- a/components/soc/esp32p4/include/soc/ecc_mult_reg.h +++ b/components/soc/esp32p4/register/soc/ecc_mult_reg.h @@ -64,7 +64,7 @@ extern "C" { */ #define ECC_MULT_CONF_REG (DR_REG_ECC_MULT_BASE + 0x1c) /** ECC_MULT_START : R/W/SC; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECC Accelerator. This bit will be self-cleared after + * Write 1 to start calculation of ECC Accelerator. This bit will be self-cleared after * the caculatrion is done. */ #define ECC_MULT_START (BIT(0)) @@ -97,7 +97,7 @@ extern "C" { * The work mode bits of ECC Accelerator. 0: Point Mult Mode. 1: Reserved. 2: Point * verification mode. 3: Point Verif+mult mode. 4: Jacobian Point Mult Mode. 5: Point * Add Mode. 6: Jacobian Point Verification Mode. 7: Point Verif + Jacobian Mult Mode. - * 8: mod addition. 9. mod substraction. 10: mod multiplication. 11: mod division. + * 8: mod addition. 9. mod subtraction. 10: mod multiplication. 11: mod division. */ #define ECC_MULT_WORK_MODE 0x0000000FU #define ECC_MULT_WORK_MODE_M (ECC_MULT_WORK_MODE_V << ECC_MULT_WORK_MODE_S) diff --git a/components/soc/esp32p4/include/soc/ecc_mult_struct.h b/components/soc/esp32p4/register/soc/ecc_mult_struct.h similarity index 96% rename from components/soc/esp32p4/include/soc/ecc_mult_struct.h rename to components/soc/esp32p4/register/soc/ecc_mult_struct.h index 5754a9e3cdd4..d868fcc8f1fa 100644 --- a/components/soc/esp32p4/include/soc/ecc_mult_struct.h +++ b/components/soc/esp32p4/register/soc/ecc_mult_struct.h @@ -77,7 +77,7 @@ typedef union { typedef union { struct { /** start : R/W/SC; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECC Accelerator. This bit will be self-cleared after + * Write 1 to start calculation of ECC Accelerator. This bit will be self-cleared after * the caculatrion is done. */ uint32_t start:1; @@ -98,7 +98,7 @@ typedef union { * The work mode bits of ECC Accelerator. 0: Point Mult Mode. 1: Reserved. 2: Point * verification mode. 3: Point Verif+mult mode. 4: Jacobian Point Mult Mode. 5: Point * Add Mode. 6: Jacobian Point Verification Mode. 7: Point Verif + Jacobian Mult Mode. - * 8: mod addition. 9. mod substraction. 10: mod multiplication. 11: mod division. + * 8: mod addition. 9. mod subtraction. 10: mod multiplication. 11: mod division. */ uint32_t work_mode:4; /** security_mode : R/W; bitpos: [8]; default: 0; diff --git a/components/soc/esp32p4/include/soc/ecdsa_reg.h b/components/soc/esp32p4/register/soc/ecdsa_reg.h similarity index 98% rename from components/soc/esp32p4/include/soc/ecdsa_reg.h rename to components/soc/esp32p4/register/soc/ecdsa_reg.h index 6e09925e0907..b5cc4f696af7 100644 --- a/components/soc/esp32p4/include/soc/ecdsa_reg.h +++ b/components/soc/esp32p4/register/soc/ecdsa_reg.h @@ -155,7 +155,7 @@ extern "C" { */ #define ECDSA_START_REG (DR_REG_ECDSA_BASE + 0x1c) /** ECDSA_START : WT; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECDSA Accelerator. This bit will be self-cleared + * Write 1 to start calculation of ECDSA Accelerator. This bit will be self-cleared * after configuration. */ #define ECDSA_START (BIT(0)) @@ -243,7 +243,7 @@ extern "C" { */ #define ECDSA_SHA_START_REG (DR_REG_ECDSA_BASE + 0x210) /** ECDSA_SHA_START : WT; bitpos: [0]; default: 0; - * Write 1 to start the first caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the first calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ #define ECDSA_SHA_START (BIT(0)) @@ -256,7 +256,7 @@ extern "C" { */ #define ECDSA_SHA_CONTINUE_REG (DR_REG_ECDSA_BASE + 0x214) /** ECDSA_SHA_CONTINUE : WT; bitpos: [0]; default: 0; - * Write 1 to start the latter caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the latter calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ #define ECDSA_SHA_CONTINUE (BIT(0)) diff --git a/components/soc/esp32p4/include/soc/ecdsa_struct.h b/components/soc/esp32p4/register/soc/ecdsa_struct.h similarity index 97% rename from components/soc/esp32p4/include/soc/ecdsa_struct.h rename to components/soc/esp32p4/register/soc/ecdsa_struct.h index 1d39f1ad04d9..67e226f86d59 100644 --- a/components/soc/esp32p4/include/soc/ecdsa_struct.h +++ b/components/soc/esp32p4/register/soc/ecdsa_struct.h @@ -57,7 +57,7 @@ typedef union { typedef union { struct { /** start : WT; bitpos: [0]; default: 0; - * Write 1 to start caculation of ECDSA Accelerator. This bit will be self-cleared + * Write 1 to start calculation of ECDSA Accelerator. This bit will be self-cleared * after configuration. */ uint32_t start:1; @@ -228,7 +228,7 @@ typedef union { typedef union { struct { /** sha_start : WT; bitpos: [0]; default: 0; - * Write 1 to start the first caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the first calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ uint32_t sha_start:1; @@ -243,7 +243,7 @@ typedef union { typedef union { struct { /** sha_continue : WT; bitpos: [0]; default: 0; - * Write 1 to start the latter caculation of SHA Calculator in ECDSA Accelerator. This + * Write 1 to start the latter calculation of SHA Calculator in ECDSA Accelerator. This * bit will be self-cleared after configuration. */ uint32_t sha_continue:1; diff --git a/components/soc/esp32p4/include/soc/efuse_reg.h b/components/soc/esp32p4/register/soc/efuse_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/efuse_reg.h rename to components/soc/esp32p4/register/soc/efuse_reg.h index 310bdaa73f6e..f26a3c342e8c 100644 --- a/components/soc/esp32p4/include/soc/efuse_reg.h +++ b/components/soc/esp32p4/register/soc/efuse_reg.h @@ -7,7 +7,7 @@ #include #include "soc/soc.h" -#include "efuse_defs.h" +#include "soc/efuse_defs.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32p4/include/soc/efuse_struct.h b/components/soc/esp32p4/register/soc/efuse_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/efuse_struct.h rename to components/soc/esp32p4/register/soc/efuse_struct.h diff --git a/components/soc/esp32p4/include/soc/emac_dma_struct.h b/components/soc/esp32p4/register/soc/emac_dma_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/emac_dma_struct.h rename to components/soc/esp32p4/register/soc/emac_dma_struct.h diff --git a/components/soc/esp32p4/include/soc/emac_mac_struct.h b/components/soc/esp32p4/register/soc/emac_mac_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/emac_mac_struct.h rename to components/soc/esp32p4/register/soc/emac_mac_struct.h diff --git a/components/soc/esp32p4/include/soc/gpio_ext_reg.h b/components/soc/esp32p4/register/soc/gpio_ext_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/gpio_ext_reg.h rename to components/soc/esp32p4/register/soc/gpio_ext_reg.h diff --git a/components/soc/esp32p4/include/soc/gpio_ext_struct.h b/components/soc/esp32p4/register/soc/gpio_ext_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/gpio_ext_struct.h rename to components/soc/esp32p4/register/soc/gpio_ext_struct.h diff --git a/components/soc/esp32p4/include/soc/gpio_reg.h b/components/soc/esp32p4/register/soc/gpio_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/gpio_reg.h rename to components/soc/esp32p4/register/soc/gpio_reg.h index 014c37539402..06b161299296 100644 --- a/components/soc/esp32p4/include/soc/gpio_reg.h +++ b/components/soc/esp32p4/register/soc/gpio_reg.h @@ -12151,11 +12151,11 @@ extern "C" { #define GPIO_SEND_SEQ_S 0 /** GPIO_RECIVE_SEQ_REG register - * High speed sdio pad bist recive sequence + * High speed sdio pad bist receive sequence */ #define GPIO_RECIVE_SEQ_REG (DR_REG_GPIO_BASE + 0x71c) /** GPIO_RECIVE_SEQ : RO; bitpos: [31:0]; default: 0; - * High speed sdio pad bist recive sequence + * High speed sdio pad bist receive sequence */ #define GPIO_RECIVE_SEQ 0xFFFFFFFFU #define GPIO_RECIVE_SEQ_M (GPIO_RECIVE_SEQ_V << GPIO_RECIVE_SEQ_S) diff --git a/components/soc/esp32p4/include/soc/gpio_struct.h b/components/soc/esp32p4/register/soc/gpio_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/gpio_struct.h rename to components/soc/esp32p4/register/soc/gpio_struct.h index 052c0b9a6db6..5a9cab91712f 100644 --- a/components/soc/esp32p4/include/soc/gpio_struct.h +++ b/components/soc/esp32p4/register/soc/gpio_struct.h @@ -580,12 +580,12 @@ typedef union { } gpio_send_seq_reg_t; /** Type of recive_seq register - * High speed sdio pad bist recive sequence + * High speed sdio pad bist receive sequence */ typedef union { struct { /** recive_seq : RO; bitpos: [31:0]; default: 0; - * High speed sdio pad bist recive sequence + * High speed sdio pad bist receive sequence */ uint32_t recive_seq:32; }; diff --git a/components/soc/esp32p4/include/soc/h264_dma_reg.h b/components/soc/esp32p4/register/soc/h264_dma_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/h264_dma_reg.h rename to components/soc/esp32p4/register/soc/h264_dma_reg.h diff --git a/components/soc/esp32p4/include/soc/h264_dma_struct.h b/components/soc/esp32p4/register/soc/h264_dma_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/h264_dma_struct.h rename to components/soc/esp32p4/register/soc/h264_dma_struct.h diff --git a/components/soc/esp32p4/include/soc/h264_reg.h b/components/soc/esp32p4/register/soc/h264_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/h264_reg.h rename to components/soc/esp32p4/register/soc/h264_reg.h diff --git a/components/soc/esp32p4/include/soc/h264_struct.h b/components/soc/esp32p4/register/soc/h264_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/h264_struct.h rename to components/soc/esp32p4/register/soc/h264_struct.h diff --git a/components/soc/esp32p4/include/soc/hmac_reg.h b/components/soc/esp32p4/register/soc/hmac_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/hmac_reg.h rename to components/soc/esp32p4/register/soc/hmac_reg.h diff --git a/components/soc/esp32p4/include/soc/hmac_struct.h b/components/soc/esp32p4/register/soc/hmac_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/hmac_struct.h rename to components/soc/esp32p4/register/soc/hmac_struct.h diff --git a/components/soc/esp32p4/include/soc/hp2lp_peri_pms_reg.h b/components/soc/esp32p4/register/soc/hp2lp_peri_pms_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/hp2lp_peri_pms_reg.h rename to components/soc/esp32p4/register/soc/hp2lp_peri_pms_reg.h diff --git a/components/soc/esp32p4/include/soc/hp2lp_peri_pms_struct.h b/components/soc/esp32p4/register/soc/hp2lp_peri_pms_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/hp2lp_peri_pms_struct.h rename to components/soc/esp32p4/register/soc/hp2lp_peri_pms_struct.h diff --git a/components/soc/esp32p4/include/soc/hp_peri_pms_reg.h b/components/soc/esp32p4/register/soc/hp_peri_pms_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/hp_peri_pms_reg.h rename to components/soc/esp32p4/register/soc/hp_peri_pms_reg.h diff --git a/components/soc/esp32p4/include/soc/hp_peri_pms_struct.h b/components/soc/esp32p4/register/soc/hp_peri_pms_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/hp_peri_pms_struct.h rename to components/soc/esp32p4/register/soc/hp_peri_pms_struct.h diff --git a/components/soc/esp32p4/include/soc/hp_sys_clkrst_reg.h b/components/soc/esp32p4/register/soc/hp_sys_clkrst_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/hp_sys_clkrst_reg.h rename to components/soc/esp32p4/register/soc/hp_sys_clkrst_reg.h diff --git a/components/soc/esp32p4/include/soc/hp_sys_clkrst_struct.h b/components/soc/esp32p4/register/soc/hp_sys_clkrst_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/hp_sys_clkrst_struct.h rename to components/soc/esp32p4/register/soc/hp_sys_clkrst_struct.h diff --git a/components/soc/esp32p4/include/soc/hp_system_reg.h b/components/soc/esp32p4/register/soc/hp_system_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/hp_system_reg.h rename to components/soc/esp32p4/register/soc/hp_system_reg.h index ec9b55a793a2..e5d5a228e621 100644 --- a/components/soc/esp32p4/include/soc/hp_system_reg.h +++ b/components/soc/esp32p4/register/soc/hp_system_reg.h @@ -39,7 +39,7 @@ extern "C" { */ #define HP_SYSTEM_CPU_INT_FROM_CPU_0_REG (DR_REG_HP_SYS_BASE + 0x10) /** HP_SYSTEM_CPU_INT_FROM_CPU_0 : R/W; bitpos: [0]; default: 0; - * set 1 will triger a interrupt + * set 1 will trigger a interrupt */ #define HP_SYSTEM_CPU_INT_FROM_CPU_0 (BIT(0)) #define HP_SYSTEM_CPU_INT_FROM_CPU_0_M (HP_SYSTEM_CPU_INT_FROM_CPU_0_V << HP_SYSTEM_CPU_INT_FROM_CPU_0_S) @@ -51,7 +51,7 @@ extern "C" { */ #define HP_SYSTEM_CPU_INT_FROM_CPU_1_REG (DR_REG_HP_SYS_BASE + 0x14) /** HP_SYSTEM_CPU_INT_FROM_CPU_1 : R/W; bitpos: [0]; default: 0; - * set 1 will triger a interrupt + * set 1 will trigger a interrupt */ #define HP_SYSTEM_CPU_INT_FROM_CPU_1 (BIT(0)) #define HP_SYSTEM_CPU_INT_FROM_CPU_1_M (HP_SYSTEM_CPU_INT_FROM_CPU_1_V << HP_SYSTEM_CPU_INT_FROM_CPU_1_S) @@ -63,7 +63,7 @@ extern "C" { */ #define HP_SYSTEM_CPU_INT_FROM_CPU_2_REG (DR_REG_HP_SYS_BASE + 0x18) /** HP_SYSTEM_CPU_INT_FROM_CPU_2 : R/W; bitpos: [0]; default: 0; - * set 1 will triger a interrupt + * set 1 will trigger a interrupt */ #define HP_SYSTEM_CPU_INT_FROM_CPU_2 (BIT(0)) #define HP_SYSTEM_CPU_INT_FROM_CPU_2_M (HP_SYSTEM_CPU_INT_FROM_CPU_2_V << HP_SYSTEM_CPU_INT_FROM_CPU_2_S) @@ -75,7 +75,7 @@ extern "C" { */ #define HP_SYSTEM_CPU_INT_FROM_CPU_3_REG (DR_REG_HP_SYS_BASE + 0x1c) /** HP_SYSTEM_CPU_INT_FROM_CPU_3 : R/W; bitpos: [0]; default: 0; - * set 1 will triger a interrupt + * set 1 will trigger a interrupt */ #define HP_SYSTEM_CPU_INT_FROM_CPU_3 (BIT(0)) #define HP_SYSTEM_CPU_INT_FROM_CPU_3_M (HP_SYSTEM_CPU_INT_FROM_CPU_3_V << HP_SYSTEM_CPU_INT_FROM_CPU_3_S) @@ -87,7 +87,7 @@ extern "C" { */ #define HP_SYSTEM_CACHE_CLK_CONFIG_REG (DR_REG_HP_SYS_BASE + 0x20) /** HP_SYSTEM_REG_L2_CACHE_CLK_ON : R/W; bitpos: [0]; default: 1; - * l2 cahce clk enable + * l2 cache clk enable */ #define HP_SYSTEM_REG_L2_CACHE_CLK_ON (BIT(0)) #define HP_SYSTEM_REG_L2_CACHE_CLK_ON_M (HP_SYSTEM_REG_L2_CACHE_CLK_ON_V << HP_SYSTEM_REG_L2_CACHE_CLK_ON_S) @@ -269,7 +269,7 @@ extern "C" { */ #define HP_SYSTEM_PROBEA_CTRL_REG (DR_REG_HP_SYS_BASE + 0x50) /** HP_SYSTEM_REG_PROBE_A_MOD_SEL : R/W; bitpos: [15:0]; default: 0; - * Tihs field is used to selec probe_group from probe_group0 to probe_group15 for + * This field is used to selec probe_group from probe_group0 to probe_group15 for * module's probe_out[31:0] in a mode */ #define HP_SYSTEM_REG_PROBE_A_MOD_SEL 0x0000FFFFU @@ -277,21 +277,21 @@ extern "C" { #define HP_SYSTEM_REG_PROBE_A_MOD_SEL_V 0x0000FFFFU #define HP_SYSTEM_REG_PROBE_A_MOD_SEL_S 0 /** HP_SYSTEM_REG_PROBE_A_TOP_SEL : R/W; bitpos: [23:16]; default: 0; - * Tihs field is used to selec module's probe_out[31:0] as probe out in a mode + * This field is used to selec module's probe_out[31:0] as probe out in a mode */ #define HP_SYSTEM_REG_PROBE_A_TOP_SEL 0x000000FFU #define HP_SYSTEM_REG_PROBE_A_TOP_SEL_M (HP_SYSTEM_REG_PROBE_A_TOP_SEL_V << HP_SYSTEM_REG_PROBE_A_TOP_SEL_S) #define HP_SYSTEM_REG_PROBE_A_TOP_SEL_V 0x000000FFU #define HP_SYSTEM_REG_PROBE_A_TOP_SEL_S 16 /** HP_SYSTEM_REG_PROBE_L_SEL : R/W; bitpos: [25:24]; default: 0; - * Tihs field is used to selec probe_out[31:16] + * This field is used to selec probe_out[31:16] */ #define HP_SYSTEM_REG_PROBE_L_SEL 0x00000003U #define HP_SYSTEM_REG_PROBE_L_SEL_M (HP_SYSTEM_REG_PROBE_L_SEL_V << HP_SYSTEM_REG_PROBE_L_SEL_S) #define HP_SYSTEM_REG_PROBE_L_SEL_V 0x00000003U #define HP_SYSTEM_REG_PROBE_L_SEL_S 24 /** HP_SYSTEM_REG_PROBE_H_SEL : R/W; bitpos: [27:26]; default: 0; - * Tihs field is used to selec probe_out[31:16] + * This field is used to selec probe_out[31:16] */ #define HP_SYSTEM_REG_PROBE_H_SEL 0x00000003U #define HP_SYSTEM_REG_PROBE_H_SEL_M (HP_SYSTEM_REG_PROBE_H_SEL_V << HP_SYSTEM_REG_PROBE_H_SEL_S) @@ -310,7 +310,7 @@ extern "C" { */ #define HP_SYSTEM_PROBEB_CTRL_REG (DR_REG_HP_SYS_BASE + 0x54) /** HP_SYSTEM_REG_PROBE_B_MOD_SEL : R/W; bitpos: [15:0]; default: 0; - * Tihs field is used to selec probe_group from probe_group0 to probe_group15 for + * This field is used to selec probe_group from probe_group0 to probe_group15 for * module's probe_out[31:0] in b mode. */ #define HP_SYSTEM_REG_PROBE_B_MOD_SEL 0x0000FFFFU @@ -318,7 +318,7 @@ extern "C" { #define HP_SYSTEM_REG_PROBE_B_MOD_SEL_V 0x0000FFFFU #define HP_SYSTEM_REG_PROBE_B_MOD_SEL_S 0 /** HP_SYSTEM_REG_PROBE_B_TOP_SEL : R/W; bitpos: [23:16]; default: 0; - * Tihs field is used to select module's probe_out[31:0] as probe_out in b mode + * This field is used to select module's probe_out[31:0] as probe_out in b mode */ #define HP_SYSTEM_REG_PROBE_B_TOP_SEL 0x000000FFU #define HP_SYSTEM_REG_PROBE_B_TOP_SEL_M (HP_SYSTEM_REG_PROBE_B_TOP_SEL_V << HP_SYSTEM_REG_PROBE_B_TOP_SEL_S) @@ -1069,7 +1069,7 @@ extern "C" { */ #define HP_SYSTEM_BITSCRAMBLER_PERI_SEL_REG (DR_REG_HP_SYS_BASE + 0x140) /** HP_SYSTEM_BITSCRAMBLER_PERI_RX_SEL : R/W; bitpos: [3:0]; default: 15; - * Set this field to sel peri with DMA RX interface to connec with bitscrambler: 4'h0 + * Set this field to sel peri with DMA RX interface to connect with bitscrambler: 4'h0 * : lcd_cam, 4'h1: gpspi2, 4'h2: gpspi3, 4'h3: parl_io, 4'h4: aes, 4'h5: sha, 4'h6: * adc, 4'h7: i2s0, 4'h8: i2s1, 4'h9: i2s2, 4'ha: i3c_mst, 4'hb: uhci0, 4'hc: RMT, * else : none @@ -1079,7 +1079,7 @@ extern "C" { #define HP_SYSTEM_BITSCRAMBLER_PERI_RX_SEL_V 0x0000000FU #define HP_SYSTEM_BITSCRAMBLER_PERI_RX_SEL_S 0 /** HP_SYSTEM_BITSCRAMBLER_PERI_TX_SEL : R/W; bitpos: [7:4]; default: 15; - * Set this field to sel peri with DMA TX interface to connec with bitscrambler: 4'h0 + * Set this field to sel peri with DMA TX interface to connect with bitscrambler: 4'h0 * : lcd_cam, 4'h1: gpspi2, 4'h2: gpspi3, 4'h3: parl_io, 4'h4: aes, 4'h5: sha, 4'h6: * adc, 4'h7: i2s0, 4'h8: i2s1, 4'h9: i2s2, 4'ha: i3c_mst, 4'hb: uhci0, 4'hc: RMT, * else : none diff --git a/components/soc/esp32p4/include/soc/hp_system_struct.h b/components/soc/esp32p4/register/soc/hp_system_struct.h similarity index 98% rename from components/soc/esp32p4/include/soc/hp_system_struct.h rename to components/soc/esp32p4/register/soc/hp_system_struct.h index 628ef31ef4f8..4e3d23f78abb 100644 --- a/components/soc/esp32p4/include/soc/hp_system_struct.h +++ b/components/soc/esp32p4/register/soc/hp_system_struct.h @@ -48,7 +48,7 @@ typedef union { typedef union { struct { /** cpu_int_from_cpu_0 : R/W; bitpos: [0]; default: 0; - * set 1 will triger a interrupt + * set 1 will trigger a interrupt */ uint32_t cpu_int_from_cpu_0:1; uint32_t reserved_1:31; @@ -64,7 +64,7 @@ typedef union { typedef union { struct { /** cpu_int_from_cpu_1 : R/W; bitpos: [0]; default: 0; - * set 1 will triger a interrupt + * set 1 will trigger a interrupt */ uint32_t cpu_int_from_cpu_1:1; uint32_t reserved_1:31; @@ -80,7 +80,7 @@ typedef union { typedef union { struct { /** cpu_int_from_cpu_2 : R/W; bitpos: [0]; default: 0; - * set 1 will triger a interrupt + * set 1 will trigger a interrupt */ uint32_t cpu_int_from_cpu_2:1; uint32_t reserved_1:31; @@ -96,7 +96,7 @@ typedef union { typedef union { struct { /** cpu_int_from_cpu_3 : R/W; bitpos: [0]; default: 0; - * set 1 will triger a interrupt + * set 1 will trigger a interrupt */ uint32_t cpu_int_from_cpu_3:1; uint32_t reserved_1:31; @@ -112,7 +112,7 @@ typedef union { typedef union { struct { /** reg_l2_cache_clk_on : R/W; bitpos: [0]; default: 1; - * l2 cahce clk enable + * l2 cache clk enable */ uint32_t reg_l2_cache_clk_on:1; /** reg_l1_d_cache_clk_on : R/W; bitpos: [1]; default: 1; @@ -283,20 +283,20 @@ typedef union { typedef union { struct { /** reg_probe_a_mod_sel : R/W; bitpos: [15:0]; default: 0; - * Tihs field is used to selec probe_group from probe_group0 to probe_group15 for + * This field is used to selec probe_group from probe_group0 to probe_group15 for * module's probe_out[31:0] in a mode */ uint32_t reg_probe_a_mod_sel:16; /** reg_probe_a_top_sel : R/W; bitpos: [23:16]; default: 0; - * Tihs field is used to selec module's probe_out[31:0] as probe out in a mode + * This field is used to selec module's probe_out[31:0] as probe out in a mode */ uint32_t reg_probe_a_top_sel:8; /** reg_probe_l_sel : R/W; bitpos: [25:24]; default: 0; - * Tihs field is used to selec probe_out[31:16] + * This field is used to selec probe_out[31:16] */ uint32_t reg_probe_l_sel:2; /** reg_probe_h_sel : R/W; bitpos: [27:26]; default: 0; - * Tihs field is used to selec probe_out[31:16] + * This field is used to selec probe_out[31:16] */ uint32_t reg_probe_h_sel:2; /** reg_probe_global_en : R/W; bitpos: [28]; default: 0; @@ -316,12 +316,12 @@ typedef union { typedef union { struct { /** reg_probe_b_mod_sel : R/W; bitpos: [15:0]; default: 0; - * Tihs field is used to selec probe_group from probe_group0 to probe_group15 for + * This field is used to selec probe_group from probe_group0 to probe_group15 for * module's probe_out[31:0] in b mode. */ uint32_t reg_probe_b_mod_sel:16; /** reg_probe_b_top_sel : R/W; bitpos: [23:16]; default: 0; - * Tihs field is used to select module's probe_out[31:0] as probe_out in b mode + * This field is used to select module's probe_out[31:0] as probe_out in b mode */ uint32_t reg_probe_b_top_sel:8; /** reg_probe_b_en : R/W; bitpos: [24]; default: 0; @@ -834,7 +834,7 @@ typedef union { } hp_system_tcm_rdn_eco_high_reg_t; -/** Group: HP GPIO DED HOLD CTRL REG */ +/** Group: HP GPIO DEAD HOLD CTRL REG */ /** Type of gpio_ded_hold_ctrl register * NA */ @@ -1021,14 +1021,14 @@ typedef union { typedef union { struct { /** bitscrambler_peri_rx_sel : R/W; bitpos: [3:0]; default: 15; - * Set this field to sel peri with DMA RX interface to connec with bitscrambler: 4'h0 + * Set this field to sel peri with DMA RX interface to connect with bitscrambler: 4'h0 * : lcd_cam, 4'h1: gpspi2, 4'h2: gpspi3, 4'h3: parl_io, 4'h4: aes, 4'h5: sha, 4'h6: * adc, 4'h7: i2s0, 4'h8: i2s1, 4'h9: i2s2, 4'ha: i3c_mst, 4'hb: uhci0, 4'hc: RMT, * else : none */ uint32_t bitscrambler_peri_rx_sel:4; /** bitscrambler_peri_tx_sel : R/W; bitpos: [7:4]; default: 15; - * Set this field to sel peri with DMA TX interface to connec with bitscrambler: 4'h0 + * Set this field to sel peri with DMA TX interface to connect with bitscrambler: 4'h0 * : lcd_cam, 4'h1: gpspi2, 4'h2: gpspi3, 4'h3: parl_io, 4'h4: aes, 4'h5: sha, 4'h6: * adc, 4'h7: i2s0, 4'h8: i2s1, 4'h9: i2s2, 4'ha: i3c_mst, 4'hb: uhci0, 4'hc: RMT, * else : none diff --git a/components/soc/esp32p4/include/soc/huk_reg.h b/components/soc/esp32p4/register/soc/huk_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/huk_reg.h rename to components/soc/esp32p4/register/soc/huk_reg.h diff --git a/components/soc/esp32p4/include/soc/huk_struct.h b/components/soc/esp32p4/register/soc/huk_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/huk_struct.h rename to components/soc/esp32p4/register/soc/huk_struct.h diff --git a/components/soc/esp32p4/include/soc/i2c_ana_mst_reg.h b/components/soc/esp32p4/register/soc/i2c_ana_mst_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/i2c_ana_mst_reg.h rename to components/soc/esp32p4/register/soc/i2c_ana_mst_reg.h diff --git a/components/soc/esp32p4/include/soc/i2c_ana_mst_struct.h b/components/soc/esp32p4/register/soc/i2c_ana_mst_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/i2c_ana_mst_struct.h rename to components/soc/esp32p4/register/soc/i2c_ana_mst_struct.h diff --git a/components/soc/esp32p4/include/soc/i2c_reg.h b/components/soc/esp32p4/register/soc/i2c_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/i2c_reg.h rename to components/soc/esp32p4/register/soc/i2c_reg.h diff --git a/components/soc/esp32p4/include/soc/i2c_struct.h b/components/soc/esp32p4/register/soc/i2c_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/i2c_struct.h rename to components/soc/esp32p4/register/soc/i2c_struct.h diff --git a/components/soc/esp32p4/include/soc/i2s_reg.h b/components/soc/esp32p4/register/soc/i2s_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/i2s_reg.h rename to components/soc/esp32p4/register/soc/i2s_reg.h index cf9267487d13..88ada789e789 100644 --- a/components/soc/esp32p4/include/soc/i2s_reg.h +++ b/components/soc/esp32p4/register/soc/i2s_reg.h @@ -320,7 +320,7 @@ extern "C" { #define I2S_TX_SLAVE_MOD_V 0x00000001U #define I2S_TX_SLAVE_MOD_S 3 /** I2S_TX_STOP_EN : R/W; bitpos: [4]; default: 1; - * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty */ #define I2S_TX_STOP_EN (BIT(4)) #define I2S_TX_STOP_EN_M (I2S_TX_STOP_EN_V << I2S_TX_STOP_EN_S) diff --git a/components/soc/esp32p4/include/soc/i2s_struct.h b/components/soc/esp32p4/register/soc/i2s_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/i2s_struct.h rename to components/soc/esp32p4/register/soc/i2s_struct.h index 6e05f6a2eb86..191b9dc6a1bb 100644 --- a/components/soc/esp32p4/include/soc/i2s_struct.h +++ b/components/soc/esp32p4/register/soc/i2s_struct.h @@ -496,7 +496,7 @@ typedef union { */ uint32_t tx_slave_mod:1; /** tx_stop_en : R/W; bitpos: [4]; default: 1; - * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty */ uint32_t tx_stop_en:1; /** tx_chan_equal : R/W; bitpos: [5]; default: 0; diff --git a/components/soc/esp32p4/include/soc/i3c_mst_mem_reg.h b/components/soc/esp32p4/register/soc/i3c_mst_mem_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/i3c_mst_mem_reg.h rename to components/soc/esp32p4/register/soc/i3c_mst_mem_reg.h diff --git a/components/soc/esp32p4/include/soc/i3c_mst_mem_struct.h b/components/soc/esp32p4/register/soc/i3c_mst_mem_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/i3c_mst_mem_struct.h rename to components/soc/esp32p4/register/soc/i3c_mst_mem_struct.h diff --git a/components/soc/esp32p4/include/soc/i3c_mst_reg.h b/components/soc/esp32p4/register/soc/i3c_mst_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/i3c_mst_reg.h rename to components/soc/esp32p4/register/soc/i3c_mst_reg.h diff --git a/components/soc/esp32p4/include/soc/i3c_mst_struct.h b/components/soc/esp32p4/register/soc/i3c_mst_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/i3c_mst_struct.h rename to components/soc/esp32p4/register/soc/i3c_mst_struct.h diff --git a/components/soc/esp32p4/include/soc/i3c_slv_reg.h b/components/soc/esp32p4/register/soc/i3c_slv_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/i3c_slv_reg.h rename to components/soc/esp32p4/register/soc/i3c_slv_reg.h index a5684d88e0e5..335ec44fc206 100644 --- a/components/soc/esp32p4/include/soc/i3c_slv_reg.h +++ b/components/soc/esp32p4/register/soc/i3c_slv_reg.h @@ -103,7 +103,7 @@ extern "C" { #define I3C_SLV_STNOTSTOP_V 0x00000001U #define I3C_SLV_STNOTSTOP_S 0 /** I3C_SLV_STMSG : RO; bitpos: [1]; default: 0; - * Is 1 if this bus Slave is listening to the bus traffic or repsonding, If + * Is 1 if this bus Slave is listening to the bus traffic or responding, If * STNOSTOP=1, then this will be 0 when a non-matching address seen until next * respeated START it STOP. */ diff --git a/components/soc/esp32p4/include/soc/i3c_slv_struct.h b/components/soc/esp32p4/register/soc/i3c_slv_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/i3c_slv_struct.h rename to components/soc/esp32p4/register/soc/i3c_slv_struct.h index 125ca7d62779..7df80af89422 100644 --- a/components/soc/esp32p4/include/soc/i3c_slv_struct.h +++ b/components/soc/esp32p4/register/soc/i3c_slv_struct.h @@ -83,7 +83,7 @@ typedef union { */ uint32_t stnotstop:1; /** stmsg : RO; bitpos: [1]; default: 0; - * Is 1 if this bus Slave is listening to the bus traffic or repsonding, If + * Is 1 if this bus Slave is listening to the bus traffic or responding, If * STNOSTOP=1, then this will be 0 when a non-matching address seen until next * respeated START it STOP. */ @@ -459,10 +459,10 @@ typedef union { */ typedef union { struct { - /** capablities : RO; bitpos: [31:0]; default: 2081684508; + /** capabilities : RO; bitpos: [31:0]; default: 2081684508; * NA */ - uint32_t capablities:32; + uint32_t capabilities:32; }; uint32_t val; } i3c_slv_capabilities_reg_t; diff --git a/components/soc/esp32p4/include/soc/icm_sys_qos_reg.h b/components/soc/esp32p4/register/soc/icm_sys_qos_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/icm_sys_qos_reg.h rename to components/soc/esp32p4/register/soc/icm_sys_qos_reg.h diff --git a/components/soc/esp32p4/include/soc/icm_sys_qos_struct.h b/components/soc/esp32p4/register/soc/icm_sys_qos_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/icm_sys_qos_struct.h rename to components/soc/esp32p4/register/soc/icm_sys_qos_struct.h diff --git a/components/soc/esp32p4/include/soc/icm_sys_reg.h b/components/soc/esp32p4/register/soc/icm_sys_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/icm_sys_reg.h rename to components/soc/esp32p4/register/soc/icm_sys_reg.h diff --git a/components/soc/esp32p4/include/soc/icm_sys_struct.h b/components/soc/esp32p4/register/soc/icm_sys_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/icm_sys_struct.h rename to components/soc/esp32p4/register/soc/icm_sys_struct.h diff --git a/components/soc/esp32p4/include/soc/interrupt_core0_reg.h b/components/soc/esp32p4/register/soc/interrupt_core0_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/interrupt_core0_reg.h rename to components/soc/esp32p4/register/soc/interrupt_core0_reg.h diff --git a/components/soc/esp32p4/include/soc/interrupt_core0_struct.h b/components/soc/esp32p4/register/soc/interrupt_core0_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/interrupt_core0_struct.h rename to components/soc/esp32p4/register/soc/interrupt_core0_struct.h diff --git a/components/soc/esp32p4/include/soc/interrupt_core1_reg.h b/components/soc/esp32p4/register/soc/interrupt_core1_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/interrupt_core1_reg.h rename to components/soc/esp32p4/register/soc/interrupt_core1_reg.h diff --git a/components/soc/esp32p4/include/soc/interrupt_core1_struct.h b/components/soc/esp32p4/register/soc/interrupt_core1_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/interrupt_core1_struct.h rename to components/soc/esp32p4/register/soc/interrupt_core1_struct.h diff --git a/components/soc/esp32p4/include/soc/io_mux_reg.h b/components/soc/esp32p4/register/soc/io_mux_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/io_mux_reg.h rename to components/soc/esp32p4/register/soc/io_mux_reg.h index 02440af90307..d7eba33c2cfc 100644 --- a/components/soc/esp32p4/include/soc/io_mux_reg.h +++ b/components/soc/esp32p4/register/soc/io_mux_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "soc.h" +#include "soc/soc.h" /* The following are the bit fields for PERIPHS_IO_MUX_x_U registers */ /* Output enable in sleep mode */ diff --git a/components/soc/esp32p4/include/soc/io_mux_struct.h b/components/soc/esp32p4/register/soc/io_mux_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/io_mux_struct.h rename to components/soc/esp32p4/register/soc/io_mux_struct.h diff --git a/components/soc/esp32p4/include/soc/iomux_mspi_pin_reg.h b/components/soc/esp32p4/register/soc/iomux_mspi_pin_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/iomux_mspi_pin_reg.h rename to components/soc/esp32p4/register/soc/iomux_mspi_pin_reg.h diff --git a/components/soc/esp32p4/include/soc/iomux_mspi_pin_struct.h b/components/soc/esp32p4/register/soc/iomux_mspi_pin_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/iomux_mspi_pin_struct.h rename to components/soc/esp32p4/register/soc/iomux_mspi_pin_struct.h diff --git a/components/soc/esp32p4/include/soc/isp_reg.h b/components/soc/esp32p4/register/soc/isp_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/isp_reg.h rename to components/soc/esp32p4/register/soc/isp_reg.h index 13749f014c8f..c1c42d64aafe 100644 --- a/components/soc/esp32p4/include/soc/isp_reg.h +++ b/components/soc/esp32p4/register/soc/isp_reg.h @@ -521,56 +521,56 @@ extern "C" { */ #define ISP_BF_GAU0_REG (DR_REG_ISP_BASE + 0x30) /** ISP_GAU_TEMPLATE21 : R/W; bitpos: [3:0]; default: 15; - * this field configures index 21 of gausian template + * this field configures index 21 of gaussian template */ #define ISP_GAU_TEMPLATE21 0x0000000FU #define ISP_GAU_TEMPLATE21_M (ISP_GAU_TEMPLATE21_V << ISP_GAU_TEMPLATE21_S) #define ISP_GAU_TEMPLATE21_V 0x0000000FU #define ISP_GAU_TEMPLATE21_S 0 /** ISP_GAU_TEMPLATE20 : R/W; bitpos: [7:4]; default: 15; - * this field configures index 20 of gausian template + * this field configures index 20 of gaussian template */ #define ISP_GAU_TEMPLATE20 0x0000000FU #define ISP_GAU_TEMPLATE20_M (ISP_GAU_TEMPLATE20_V << ISP_GAU_TEMPLATE20_S) #define ISP_GAU_TEMPLATE20_V 0x0000000FU #define ISP_GAU_TEMPLATE20_S 4 /** ISP_GAU_TEMPLATE12 : R/W; bitpos: [11:8]; default: 15; - * this field configures index 12 of gausian template + * this field configures index 12 of gaussian template */ #define ISP_GAU_TEMPLATE12 0x0000000FU #define ISP_GAU_TEMPLATE12_M (ISP_GAU_TEMPLATE12_V << ISP_GAU_TEMPLATE12_S) #define ISP_GAU_TEMPLATE12_V 0x0000000FU #define ISP_GAU_TEMPLATE12_S 8 /** ISP_GAU_TEMPLATE11 : R/W; bitpos: [15:12]; default: 15; - * this field configures index 11 of gausian template + * this field configures index 11 of gaussian template */ #define ISP_GAU_TEMPLATE11 0x0000000FU #define ISP_GAU_TEMPLATE11_M (ISP_GAU_TEMPLATE11_V << ISP_GAU_TEMPLATE11_S) #define ISP_GAU_TEMPLATE11_V 0x0000000FU #define ISP_GAU_TEMPLATE11_S 12 /** ISP_GAU_TEMPLATE10 : R/W; bitpos: [19:16]; default: 15; - * this field configures index 10 of gausian template + * this field configures index 10 of gaussian template */ #define ISP_GAU_TEMPLATE10 0x0000000FU #define ISP_GAU_TEMPLATE10_M (ISP_GAU_TEMPLATE10_V << ISP_GAU_TEMPLATE10_S) #define ISP_GAU_TEMPLATE10_V 0x0000000FU #define ISP_GAU_TEMPLATE10_S 16 /** ISP_GAU_TEMPLATE02 : R/W; bitpos: [23:20]; default: 15; - * this field configures index 02 of gausian template + * this field configures index 02 of gaussian template */ #define ISP_GAU_TEMPLATE02 0x0000000FU #define ISP_GAU_TEMPLATE02_M (ISP_GAU_TEMPLATE02_V << ISP_GAU_TEMPLATE02_S) #define ISP_GAU_TEMPLATE02_V 0x0000000FU #define ISP_GAU_TEMPLATE02_S 20 /** ISP_GAU_TEMPLATE01 : R/W; bitpos: [27:24]; default: 15; - * this field configures index 01 of gausian template + * this field configures index 01 of gaussian template */ #define ISP_GAU_TEMPLATE01 0x0000000FU #define ISP_GAU_TEMPLATE01_M (ISP_GAU_TEMPLATE01_V << ISP_GAU_TEMPLATE01_S) #define ISP_GAU_TEMPLATE01_V 0x0000000FU #define ISP_GAU_TEMPLATE01_S 24 /** ISP_GAU_TEMPLATE00 : R/W; bitpos: [31:28]; default: 15; - * this field configures index 00 of gausian template + * this field configures index 00 of gaussian template */ #define ISP_GAU_TEMPLATE00 0x0000000FU #define ISP_GAU_TEMPLATE00_M (ISP_GAU_TEMPLATE00_V << ISP_GAU_TEMPLATE00_S) @@ -582,7 +582,7 @@ extern "C" { */ #define ISP_BF_GAU1_REG (DR_REG_ISP_BASE + 0x34) /** ISP_GAU_TEMPLATE22 : R/W; bitpos: [3:0]; default: 15; - * this field configures index 22 of gausian template + * this field configures index 22 of gaussian template */ #define ISP_GAU_TEMPLATE22 0x0000000FU #define ISP_GAU_TEMPLATE22_M (ISP_GAU_TEMPLATE22_V << ISP_GAU_TEMPLATE22_S) @@ -2584,7 +2584,7 @@ extern "C" { #define ISP_AE_MONITOR_TH_V 0x000000FFU #define ISP_AE_MONITOR_TH_S 8 /** ISP_AE_MONITOR_PERIOD : R/W; bitpos: [21:16]; default: 0; - * this field cnfigures ae monitor frame period + * this field configures ae monitor frame period */ #define ISP_AE_MONITOR_PERIOD 0x0000003FU #define ISP_AE_MONITOR_PERIOD_M (ISP_AE_MONITOR_PERIOD_V << ISP_AE_MONITOR_PERIOD_S) @@ -3030,7 +3030,7 @@ extern "C" { */ #define ISP_DMA_CNTL_REG (DR_REG_ISP_BASE + 0x10c) /** ISP_DMA_EN : WT; bitpos: [0]; default: 0; - * write 1 to triger dma to get 1 frame + * write 1 to trigger dma to get 1 frame */ #define ISP_DMA_EN (BIT(0)) #define ISP_DMA_EN_M (ISP_DMA_EN_V << ISP_DMA_EN_S) @@ -3090,7 +3090,7 @@ extern "C" { */ #define ISP_CAM_CNTL_REG (DR_REG_ISP_BASE + 0x114) /** ISP_CAM_EN : R/W; bitpos: [0]; default: 0; - * write 1 to start recive camera data, write 0 to disable + * write 1 to start receive camera data, write 0 to disable */ #define ISP_CAM_EN (BIT(0)) #define ISP_CAM_EN_M (ISP_CAM_EN_V << ISP_CAM_EN_S) @@ -3111,7 +3111,7 @@ extern "C" { #define ISP_CAM_RESET_V 0x00000001U #define ISP_CAM_RESET_S 2 /** ISP_CAM_CLK_INV : R/W; bitpos: [3]; default: 0; - * this bit configures the invertion of cam clk from pad. 0: not invert cam clk, 1: + * this bit configures the inversion of cam clk from pad. 0: not invert cam clk, 1: * invert cam clk */ #define ISP_CAM_CLK_INV (BIT(3)) @@ -3487,7 +3487,7 @@ extern "C" { */ #define ISP_AWB_MODE_REG (DR_REG_ISP_BASE + 0x164) /** ISP_AWB_MODE : R/W; bitpos: [1:0]; default: 3; - * this field configures awb algo sel. 00: none sellected. 01: sel algo0. 10: sel + * this field configures awb algo sel. 00: none selected. 01: sel algo0. 10: sel * algo1. 11: sel both algo0 and algo1 */ #define ISP_AWB_MODE 0x00000003U diff --git a/components/soc/esp32p4/include/soc/isp_struct.h b/components/soc/esp32p4/register/soc/isp_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/isp_struct.h rename to components/soc/esp32p4/register/soc/isp_struct.h diff --git a/components/soc/esp32p4/include/soc/jpeg_reg.h b/components/soc/esp32p4/register/soc/jpeg_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/jpeg_reg.h rename to components/soc/esp32p4/register/soc/jpeg_reg.h diff --git a/components/soc/esp32p4/include/soc/jpeg_struct.h b/components/soc/esp32p4/register/soc/jpeg_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/jpeg_struct.h rename to components/soc/esp32p4/register/soc/jpeg_struct.h diff --git a/components/soc/esp32p4/include/soc/keymng_reg.h b/components/soc/esp32p4/register/soc/keymng_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/keymng_reg.h rename to components/soc/esp32p4/register/soc/keymng_reg.h diff --git a/components/soc/esp32p4/include/soc/keymng_struct.h b/components/soc/esp32p4/register/soc/keymng_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/keymng_struct.h rename to components/soc/esp32p4/register/soc/keymng_struct.h diff --git a/components/soc/esp32p4/include/soc/l2mem_monitor_reg.h b/components/soc/esp32p4/register/soc/l2mem_monitor_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/l2mem_monitor_reg.h rename to components/soc/esp32p4/register/soc/l2mem_monitor_reg.h diff --git a/components/soc/esp32p4/include/soc/l2mem_monitor_struct.h b/components/soc/esp32p4/register/soc/l2mem_monitor_struct.h similarity index 98% rename from components/soc/esp32p4/include/soc/l2mem_monitor_struct.h rename to components/soc/esp32p4/register/soc/l2mem_monitor_struct.h index c88691215af4..e3e1abf3761d 100644 --- a/components/soc/esp32p4/include/soc/l2mem_monitor_struct.h +++ b/components/soc/esp32p4/register/soc/l2mem_monitor_struct.h @@ -12,7 +12,7 @@ extern "C" { /** Group: configuration registers */ /** Type of log_setting register - * log config regsiter + * log config register */ typedef union { struct { @@ -43,7 +43,7 @@ typedef union { } mem_monitor_log_setting_reg_t; /** Type of log_setting1 register - * log config regsiter + * log config register */ typedef union { struct { @@ -61,7 +61,7 @@ typedef union { } mem_monitor_log_setting1_reg_t; /** Type of log_check_data register - * check data regsiter + * check data register */ typedef union { struct { @@ -89,7 +89,7 @@ typedef union { } mem_monitor_log_data_mask_reg_t; /** Type of log_min register - * log boundary regsiter + * log boundary register */ typedef union { struct { @@ -102,7 +102,7 @@ typedef union { } mem_monitor_log_min_reg_t; /** Type of log_max register - * log boundary regsiter + * log boundary register */ typedef union { struct { diff --git a/components/soc/esp32p4/include/soc/lcd_cam_reg.h b/components/soc/esp32p4/register/soc/lcd_cam_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lcd_cam_reg.h rename to components/soc/esp32p4/register/soc/lcd_cam_reg.h diff --git a/components/soc/esp32p4/include/soc/lcd_cam_struct.h b/components/soc/esp32p4/register/soc/lcd_cam_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lcd_cam_struct.h rename to components/soc/esp32p4/register/soc/lcd_cam_struct.h diff --git a/components/soc/esp32p4/include/soc/ledc_reg.h b/components/soc/esp32p4/register/soc/ledc_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/ledc_reg.h rename to components/soc/esp32p4/register/soc/ledc_reg.h diff --git a/components/soc/esp32p4/include/soc/ledc_struct.h b/components/soc/esp32p4/register/soc/ledc_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/ledc_struct.h rename to components/soc/esp32p4/register/soc/ledc_struct.h diff --git a/components/soc/esp32p4/include/soc/lp2hp_peri_pms_reg.h b/components/soc/esp32p4/register/soc/lp2hp_peri_pms_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp2hp_peri_pms_reg.h rename to components/soc/esp32p4/register/soc/lp2hp_peri_pms_reg.h diff --git a/components/soc/esp32p4/include/soc/lp2hp_peri_pms_struct.h b/components/soc/esp32p4/register/soc/lp2hp_peri_pms_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp2hp_peri_pms_struct.h rename to components/soc/esp32p4/register/soc/lp2hp_peri_pms_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_adc_reg.h b/components/soc/esp32p4/register/soc/lp_adc_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_adc_reg.h rename to components/soc/esp32p4/register/soc/lp_adc_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_adc_struct.h b/components/soc/esp32p4/register/soc/lp_adc_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_adc_struct.h rename to components/soc/esp32p4/register/soc/lp_adc_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_analog_peri_reg.h b/components/soc/esp32p4/register/soc/lp_analog_peri_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_analog_peri_reg.h rename to components/soc/esp32p4/register/soc/lp_analog_peri_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_analog_peri_struct.h b/components/soc/esp32p4/register/soc/lp_analog_peri_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_analog_peri_struct.h rename to components/soc/esp32p4/register/soc/lp_analog_peri_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_clkrst_reg.h b/components/soc/esp32p4/register/soc/lp_clkrst_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/lp_clkrst_reg.h rename to components/soc/esp32p4/register/soc/lp_clkrst_reg.h index de3f17820c11..a771250be620 100644 --- a/components/soc/esp32p4/include/soc/lp_clkrst_reg.h +++ b/components/soc/esp32p4/register/soc/lp_clkrst_reg.h @@ -829,7 +829,7 @@ extern "C" { #define LP_CLKRST_HP_FOSC_20M_CLK_EN_V 0x00000001U #define LP_CLKRST_HP_FOSC_20M_CLK_EN_S 24 /** LP_CLKRST_HP_XTAL_40M_CLK_EN : R/W; bitpos: [25]; default: 1; - * XTAL 40M Clock Enalbe. + * XTAL 40M Clock Enable. */ #define LP_CLKRST_HP_XTAL_40M_CLK_EN (BIT(25)) #define LP_CLKRST_HP_XTAL_40M_CLK_EN_M (LP_CLKRST_HP_XTAL_40M_CLK_EN_V << LP_CLKRST_HP_XTAL_40M_CLK_EN_S) diff --git a/components/soc/esp32p4/include/soc/lp_clkrst_struct.h b/components/soc/esp32p4/register/soc/lp_clkrst_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/lp_clkrst_struct.h rename to components/soc/esp32p4/register/soc/lp_clkrst_struct.h index 2e2246001f4b..b21775966a18 100644 --- a/components/soc/esp32p4/include/soc/lp_clkrst_struct.h +++ b/components/soc/esp32p4/register/soc/lp_clkrst_struct.h @@ -611,7 +611,7 @@ typedef union { */ uint32_t hp_fosc_20m_clk_en:1; /** hp_xtal_40m_clk_en : R/W; bitpos: [25]; default: 1; - * XTAL 40M Clock Enalbe. + * XTAL 40M Clock Enable. */ uint32_t hp_xtal_40m_clk_en:1; /** hp_cpll_400m_clk_en : R/W; bitpos: [26]; default: 1; diff --git a/components/soc/esp32p4/include/soc/lp_gpio_reg.h b/components/soc/esp32p4/register/soc/lp_gpio_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_gpio_reg.h rename to components/soc/esp32p4/register/soc/lp_gpio_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_gpio_struct.h b/components/soc/esp32p4/register/soc/lp_gpio_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_gpio_struct.h rename to components/soc/esp32p4/register/soc/lp_gpio_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_i2c_reg.h b/components/soc/esp32p4/register/soc/lp_i2c_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_i2c_reg.h rename to components/soc/esp32p4/register/soc/lp_i2c_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_i2c_struct.h b/components/soc/esp32p4/register/soc/lp_i2c_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_i2c_struct.h rename to components/soc/esp32p4/register/soc/lp_i2c_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_i2s_reg.h b/components/soc/esp32p4/register/soc/lp_i2s_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_i2s_reg.h rename to components/soc/esp32p4/register/soc/lp_i2s_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_i2s_struct.h b/components/soc/esp32p4/register/soc/lp_i2s_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_i2s_struct.h rename to components/soc/esp32p4/register/soc/lp_i2s_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_intr_reg.h b/components/soc/esp32p4/register/soc/lp_intr_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_intr_reg.h rename to components/soc/esp32p4/register/soc/lp_intr_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_intr_struct.h b/components/soc/esp32p4/register/soc/lp_intr_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_intr_struct.h rename to components/soc/esp32p4/register/soc/lp_intr_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_iomux_reg.h b/components/soc/esp32p4/register/soc/lp_iomux_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_iomux_reg.h rename to components/soc/esp32p4/register/soc/lp_iomux_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_iomux_struct.h b/components/soc/esp32p4/register/soc/lp_iomux_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_iomux_struct.h rename to components/soc/esp32p4/register/soc/lp_iomux_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_mailbox_reg.h b/components/soc/esp32p4/register/soc/lp_mailbox_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_mailbox_reg.h rename to components/soc/esp32p4/register/soc/lp_mailbox_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_mailbox_struct.h b/components/soc/esp32p4/register/soc/lp_mailbox_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_mailbox_struct.h rename to components/soc/esp32p4/register/soc/lp_mailbox_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_peri_pms_reg.h b/components/soc/esp32p4/register/soc/lp_peri_pms_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_peri_pms_reg.h rename to components/soc/esp32p4/register/soc/lp_peri_pms_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_peri_pms_struct.h b/components/soc/esp32p4/register/soc/lp_peri_pms_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_peri_pms_struct.h rename to components/soc/esp32p4/register/soc/lp_peri_pms_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_spi_reg.h b/components/soc/esp32p4/register/soc/lp_spi_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/lp_spi_reg.h rename to components/soc/esp32p4/register/soc/lp_spi_reg.h index c00998b2b82f..5892adfe42cf 100644 --- a/components/soc/esp32p4/include/soc/lp_spi_reg.h +++ b/components/soc/esp32p4/register/soc/lp_spi_reg.h @@ -126,7 +126,7 @@ extern "C" { #define LP_REG_CLKDIV_PRE_V 0x0000000FU #define LP_REG_CLKDIV_PRE_S 18 /** LP_REG_CLK_EQU_SYSCLK : R/W; bitpos: [31]; default: 1; - * In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system + * In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system * clock. Can be configured in CONF state. */ #define LP_REG_CLK_EQU_SYSCLK (BIT(31)) @@ -1208,7 +1208,7 @@ extern "C" { /** LP_REG_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. Can be configured in CONF state. + * SPI clock is always on. Can be configured in CONF state. */ #define LP_REG_CLK_MODE 0x00000003U #define LP_REG_CLK_MODE_M (LP_REG_CLK_MODE_V << LP_REG_CLK_MODE_S) diff --git a/components/soc/esp32p4/include/soc/lp_spi_struct.h b/components/soc/esp32p4/register/soc/lp_spi_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_spi_struct.h rename to components/soc/esp32p4/register/soc/lp_spi_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_system_reg.h b/components/soc/esp32p4/register/soc/lp_system_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_system_reg.h rename to components/soc/esp32p4/register/soc/lp_system_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_system_struct.h b/components/soc/esp32p4/register/soc/lp_system_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_system_struct.h rename to components/soc/esp32p4/register/soc/lp_system_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_timer_reg.h b/components/soc/esp32p4/register/soc/lp_timer_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_timer_reg.h rename to components/soc/esp32p4/register/soc/lp_timer_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_timer_struct.h b/components/soc/esp32p4/register/soc/lp_timer_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_timer_struct.h rename to components/soc/esp32p4/register/soc/lp_timer_struct.h diff --git a/components/soc/esp32p4/include/soc/lp_uart_reg.h b/components/soc/esp32p4/register/soc/lp_uart_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/lp_uart_reg.h rename to components/soc/esp32p4/register/soc/lp_uart_reg.h index 0a5ba491f401..d488866f781e 100644 --- a/components/soc/esp32p4/include/soc/lp_uart_reg.h +++ b/components/soc/esp32p4/register/soc/lp_uart_reg.h @@ -100,7 +100,7 @@ extern "C" { #define LP_UART_RXFIFO_TOUT_INT_RAW_V 0x00000001U #define LP_UART_RXFIFO_TOUT_INT_RAW_S 8 /** LP_UART_SW_XON_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ #define LP_UART_SW_XON_INT_RAW (BIT(9)) @@ -261,7 +261,7 @@ extern "C" { #define LP_UART_TX_BRK_DONE_INT_ST_V 0x00000001U #define LP_UART_TX_BRK_DONE_INT_ST_S 12 /** LP_UART_TX_BRK_IDLE_DONE_INT_ST : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ #define LP_UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) @@ -671,7 +671,7 @@ extern "C" { #define LP_UART_STOP_BIT_NUM_V 0x00000003U #define LP_UART_STOP_BIT_NUM_S 4 /** LP_UART_TXD_BRK : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ #define LP_UART_TXD_BRK (BIT(6)) @@ -1151,7 +1151,7 @@ extern "C" { */ #define LP_UART_TOUT_CONF_SYNC_REG (DR_REG_LP_UART_BASE + 0x64) /** LP_UART_RX_TOUT_EN : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ #define LP_UART_RX_TOUT_EN (BIT(0)) #define LP_UART_RX_TOUT_EN_M (LP_UART_RX_TOUT_EN_V << LP_UART_RX_TOUT_EN_S) diff --git a/components/soc/esp32p4/include/soc/lp_uart_struct.h b/components/soc/esp32p4/register/soc/lp_uart_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/lp_uart_struct.h rename to components/soc/esp32p4/register/soc/lp_uart_struct.h index 5bd4d605c0bc..d86d6a0d91d0 100644 --- a/components/soc/esp32p4/include/soc/lp_uart_struct.h +++ b/components/soc/esp32p4/register/soc/lp_uart_struct.h @@ -50,7 +50,7 @@ typedef union { typedef union { struct { /** rx_tout_en : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ uint32_t rx_tout_en:1; /** rx_tout_flow_dis : R/W; bitpos: [1]; default: 0; @@ -121,7 +121,7 @@ typedef union { */ uint32_t rxfifo_tout_int_raw:1; /** sw_xon_int_raw : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ uint32_t sw_xon_int_raw:1; @@ -225,7 +225,7 @@ typedef union { */ uint32_t tx_brk_done_int_st:1; /** tx_brk_idle_done_int_st : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ uint32_t tx_brk_idle_done_int_st:1; @@ -467,7 +467,7 @@ typedef union { */ uint32_t stop_bit_num:2; /** txd_brk : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ uint32_t txd_brk:1; diff --git a/components/soc/esp32p4/include/soc/lp_wdt_reg.h b/components/soc/esp32p4/register/soc/lp_wdt_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_wdt_reg.h rename to components/soc/esp32p4/register/soc/lp_wdt_reg.h diff --git a/components/soc/esp32p4/include/soc/lp_wdt_struct.h b/components/soc/esp32p4/register/soc/lp_wdt_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lp_wdt_struct.h rename to components/soc/esp32p4/register/soc/lp_wdt_struct.h diff --git a/components/soc/esp32p4/include/soc/lpperi_reg.h b/components/soc/esp32p4/register/soc/lpperi_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/lpperi_reg.h rename to components/soc/esp32p4/register/soc/lpperi_reg.h diff --git a/components/soc/esp32p4/include/soc/lpperi_struct.h b/components/soc/esp32p4/register/soc/lpperi_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/lpperi_struct.h rename to components/soc/esp32p4/register/soc/lpperi_struct.h diff --git a/components/soc/esp32p4/include/soc/mcpwm_reg.h b/components/soc/esp32p4/register/soc/mcpwm_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/mcpwm_reg.h rename to components/soc/esp32p4/register/soc/mcpwm_reg.h index e526c38e6052..8534b7f33457 100644 --- a/components/soc/esp32p4/include/soc/mcpwm_reg.h +++ b/components/soc/esp32p4/register/soc/mcpwm_reg.h @@ -2764,7 +2764,7 @@ extern "C" { #define MCPWM_CAP0_MODE_V 0x00000003U #define MCPWM_CAP0_MODE_S 1 /** MCPWM_CAP0_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Configures prescale value on possitive edge of CAP0. Prescale value = + * Configures prescale value on positive edge of CAP0. Prescale value = * PWM_CAP0_PRESCALE + 1 */ #define MCPWM_CAP0_PRESCALE 0x000000FFU @@ -2809,7 +2809,7 @@ extern "C" { #define MCPWM_CAP0_MODE_V 0x00000003U #define MCPWM_CAP0_MODE_S 1 /** MCPWM_CAP0_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Configures prescale value on possitive edge of CAP1. Prescale value = + * Configures prescale value on positive edge of CAP1. Prescale value = * PWM_CAP1_PRESCALE + 1 */ #define MCPWM_CAP0_PRESCALE 0x000000FFU @@ -2854,7 +2854,7 @@ extern "C" { #define MCPWM_CAP0_MODE_V 0x00000003U #define MCPWM_CAP0_MODE_S 1 /** MCPWM_CAP0_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Configures prescale value on possitive edge of CAP2. Prescale value = + * Configures prescale value on positive edge of CAP2. Prescale value = * PWM_CAP2_PRESCALE + 1 */ #define MCPWM_CAP0_PRESCALE 0x000000FFU diff --git a/components/soc/esp32p4/include/soc/mcpwm_struct.h b/components/soc/esp32p4/register/soc/mcpwm_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/mcpwm_struct.h rename to components/soc/esp32p4/register/soc/mcpwm_struct.h index 2b72d044e1a5..71a4864a9c38 100644 --- a/components/soc/esp32p4/include/soc/mcpwm_struct.h +++ b/components/soc/esp32p4/register/soc/mcpwm_struct.h @@ -780,7 +780,7 @@ typedef union { */ uint32_t capn_mode:2; /** capn_prescale : R/W; bitpos: [10:3]; default: 0; - * Configures prescale value on possitive edge of CAPn. Prescale value = + * Configures prescale value on positive edge of CAPn. Prescale value = * PWM_CAPn_PRESCALE + 1 */ uint32_t capn_prescale:8; diff --git a/components/soc/esp32p4/include/soc/mipi_csi_bridge_reg.h b/components/soc/esp32p4/register/soc/mipi_csi_bridge_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/mipi_csi_bridge_reg.h rename to components/soc/esp32p4/register/soc/mipi_csi_bridge_reg.h diff --git a/components/soc/esp32p4/include/soc/mipi_csi_bridge_struct.h b/components/soc/esp32p4/register/soc/mipi_csi_bridge_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/mipi_csi_bridge_struct.h rename to components/soc/esp32p4/register/soc/mipi_csi_bridge_struct.h diff --git a/components/soc/esp32p4/include/soc/mipi_csi_host_reg.h b/components/soc/esp32p4/register/soc/mipi_csi_host_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/mipi_csi_host_reg.h rename to components/soc/esp32p4/register/soc/mipi_csi_host_reg.h diff --git a/components/soc/esp32p4/include/soc/mipi_csi_host_struct.h b/components/soc/esp32p4/register/soc/mipi_csi_host_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/mipi_csi_host_struct.h rename to components/soc/esp32p4/register/soc/mipi_csi_host_struct.h diff --git a/components/soc/esp32p4/include/soc/mipi_dsi_bridge_reg.h b/components/soc/esp32p4/register/soc/mipi_dsi_bridge_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/mipi_dsi_bridge_reg.h rename to components/soc/esp32p4/register/soc/mipi_dsi_bridge_reg.h diff --git a/components/soc/esp32p4/include/soc/mipi_dsi_bridge_struct.h b/components/soc/esp32p4/register/soc/mipi_dsi_bridge_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/mipi_dsi_bridge_struct.h rename to components/soc/esp32p4/register/soc/mipi_dsi_bridge_struct.h diff --git a/components/soc/esp32p4/include/soc/mipi_dsi_host_reg.h b/components/soc/esp32p4/register/soc/mipi_dsi_host_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/mipi_dsi_host_reg.h rename to components/soc/esp32p4/register/soc/mipi_dsi_host_reg.h diff --git a/components/soc/esp32p4/include/soc/mipi_dsi_host_struct.h b/components/soc/esp32p4/register/soc/mipi_dsi_host_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/mipi_dsi_host_struct.h rename to components/soc/esp32p4/register/soc/mipi_dsi_host_struct.h diff --git a/components/soc/esp32p4/include/soc/parl_io_reg.h b/components/soc/esp32p4/register/soc/parl_io_reg.h similarity index 98% rename from components/soc/esp32p4/include/soc/parl_io_reg.h rename to components/soc/esp32p4/register/soc/parl_io_reg.h index 74a528017d98..812470334d86 100644 --- a/components/soc/esp32p4/include/soc/parl_io_reg.h +++ b/components/soc/esp32p4/register/soc/parl_io_reg.h @@ -260,7 +260,7 @@ extern "C" { #define PARL_IO_TX_READY_S 31 /** PARL_IO_INT_ENA_REG register - * Parallel IO interrupt enable singal configuration register. + * Parallel IO interrupt enable signal configuration register. */ #define PARL_IO_INT_ENA_REG (DR_REG_PARL_IO_BASE + 0x28) /** PARL_IO_TX_FIFO_REMPTY_INT_ENA : R/W; bitpos: [0]; default: 0; @@ -286,7 +286,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_ENA_S 2 /** PARL_IO_INT_RAW_REG register - * Parallel IO interrupt raw singal status register. + * Parallel IO interrupt raw signal status register. */ #define PARL_IO_INT_RAW_REG (DR_REG_PARL_IO_BASE + 0x2c) /** PARL_IO_TX_FIFO_REMPTY_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; @@ -312,7 +312,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_RAW_S 2 /** PARL_IO_INT_ST_REG register - * Parallel IO interrupt singal status register. + * Parallel IO interrupt signal status register. */ #define PARL_IO_INT_ST_REG (DR_REG_PARL_IO_BASE + 0x30) /** PARL_IO_TX_FIFO_REMPTY_INT_ST : RO; bitpos: [0]; default: 0; @@ -338,7 +338,7 @@ extern "C" { #define PARL_IO_TX_EOF_INT_ST_S 2 /** PARL_IO_INT_CLR_REG register - * Parallel IO interrupt clear singal configuration register. + * Parallel IO interrupt clear signal configuration register. */ #define PARL_IO_INT_CLR_REG (DR_REG_PARL_IO_BASE + 0x34) /** PARL_IO_TX_FIFO_REMPTY_INT_CLR : WT; bitpos: [0]; default: 0; diff --git a/components/soc/esp32p4/include/soc/parl_io_struct.h b/components/soc/esp32p4/register/soc/parl_io_struct.h similarity index 98% rename from components/soc/esp32p4/include/soc/parl_io_struct.h rename to components/soc/esp32p4/register/soc/parl_io_struct.h index aea2cb383b8c..7304e7be2c58 100644 --- a/components/soc/esp32p4/include/soc/parl_io_struct.h +++ b/components/soc/esp32p4/register/soc/parl_io_struct.h @@ -256,7 +256,7 @@ typedef union { /** Group: PARL_IO Interrupt Configuration and Status */ /** Type of int_ena register - * Parallel IO interrupt enable singal configuration register. + * Parallel IO interrupt enable signal configuration register. */ typedef union { struct { @@ -278,7 +278,7 @@ typedef union { } parl_io_int_ena_reg_t; /** Type of int_raw register - * Parallel IO interrupt raw singal status register. + * Parallel IO interrupt raw signal status register. */ typedef union { struct { @@ -300,7 +300,7 @@ typedef union { } parl_io_int_raw_reg_t; /** Type of int_st register - * Parallel IO interrupt singal status register. + * Parallel IO interrupt signal status register. */ typedef union { struct { @@ -322,7 +322,7 @@ typedef union { } parl_io_int_st_reg_t; /** Type of int_clr register - * Parallel IO interrupt clear singal configuration register. + * Parallel IO interrupt clear signal configuration register. */ typedef union { struct { diff --git a/components/soc/esp32p4/include/soc/pau_reg.h b/components/soc/esp32p4/register/soc/pau_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/pau_reg.h rename to components/soc/esp32p4/register/soc/pau_reg.h diff --git a/components/soc/esp32p4/include/soc/pau_struct.h b/components/soc/esp32p4/register/soc/pau_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/pau_struct.h rename to components/soc/esp32p4/register/soc/pau_struct.h diff --git a/components/soc/esp32p4/include/soc/pcnt_reg.h b/components/soc/esp32p4/register/soc/pcnt_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/pcnt_reg.h rename to components/soc/esp32p4/register/soc/pcnt_reg.h diff --git a/components/soc/esp32p4/include/soc/pcnt_struct.h b/components/soc/esp32p4/register/soc/pcnt_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/pcnt_struct.h rename to components/soc/esp32p4/register/soc/pcnt_struct.h diff --git a/components/soc/esp32p4/include/soc/pmu_reg.h b/components/soc/esp32p4/register/soc/pmu_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/pmu_reg.h rename to components/soc/esp32p4/register/soc/pmu_reg.h diff --git a/components/soc/esp32p4/include/soc/pmu_struct.h b/components/soc/esp32p4/register/soc/pmu_struct.h similarity index 98% rename from components/soc/esp32p4/include/soc/pmu_struct.h rename to components/soc/esp32p4/register/soc/pmu_struct.h index f8727c5c88e3..d8936af001e0 100644 --- a/components/soc/esp32p4/include/soc/pmu_struct.h +++ b/components/soc/esp32p4/register/soc/pmu_struct.h @@ -121,6 +121,7 @@ typedef union { } pmu_hp_sysclk_reg_t; typedef union { + // For chip_revsion < 1.0 struct { uint32_t reserved0 : 4; /* Only HP_ACTIVE modem under hp system is valid */ uint32_t lp_dbias_vol : 5; /* Only HP_ACTIVE modem under hp system is valid */ @@ -130,10 +131,16 @@ typedef union { uint32_t slp_mem_xpd : 1; uint32_t slp_logic_xpd : 1; uint32_t xpd : 1; - uint32_t slp_mem_dbias : 4; + uint32_t slp_mem_dbias : 4; /* slp_mem_dbias is not used on chip_revision < 100 */ uint32_t slp_logic_dbias: 4; uint32_t dbias : 5; }; + // For chip revision >= 100 + struct { + uint32_t reserved1 : 19; + uint32_t xpd_0p1a : 4; /* slp_mem_dbias[3] is used to control the volt output of VO1 on chip_revision >= 1.0 */ + uint32_t reserved2 : 9; + }; uint32_t val; } pmu_hp_regulator0_reg_t; diff --git a/components/soc/esp32p4/include/soc/ppa_reg.h b/components/soc/esp32p4/register/soc/ppa_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/ppa_reg.h rename to components/soc/esp32p4/register/soc/ppa_reg.h index 2b17794d771c..a7a64aa44fba 100644 --- a/components/soc/esp32p4/include/soc/ppa_reg.h +++ b/components/soc/esp32p4/register/soc/ppa_reg.h @@ -645,21 +645,21 @@ extern "C" { */ #define PPA_CK_DEFAULT_REG (DR_REG_PPA_BASE + 0x60) /** PPA_COLORKEY_DEFAULT_B : R/W; bitpos: [7:0]; default: 0; - * default B channle value of color key + * default B channel value of color key */ #define PPA_COLORKEY_DEFAULT_B 0x000000FFU #define PPA_COLORKEY_DEFAULT_B_M (PPA_COLORKEY_DEFAULT_B_V << PPA_COLORKEY_DEFAULT_B_S) #define PPA_COLORKEY_DEFAULT_B_V 0x000000FFU #define PPA_COLORKEY_DEFAULT_B_S 0 /** PPA_COLORKEY_DEFAULT_G : R/W; bitpos: [15:8]; default: 0; - * default G channle value of color key + * default G channel value of color key */ #define PPA_COLORKEY_DEFAULT_G 0x000000FFU #define PPA_COLORKEY_DEFAULT_G_M (PPA_COLORKEY_DEFAULT_G_V << PPA_COLORKEY_DEFAULT_G_S) #define PPA_COLORKEY_DEFAULT_G_V 0x000000FFU #define PPA_COLORKEY_DEFAULT_G_S 8 /** PPA_COLORKEY_DEFAULT_R : R/W; bitpos: [23:16]; default: 0; - * default R channle value of color key + * default R channel value of color key */ #define PPA_COLORKEY_DEFAULT_R 0x000000FFU #define PPA_COLORKEY_DEFAULT_R_M (PPA_COLORKEY_DEFAULT_R_V << PPA_COLORKEY_DEFAULT_R_S) diff --git a/components/soc/esp32p4/include/soc/ppa_struct.h b/components/soc/esp32p4/register/soc/ppa_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/ppa_struct.h rename to components/soc/esp32p4/register/soc/ppa_struct.h index 5aa064b90144..abcc3dc0a7dd 100644 --- a/components/soc/esp32p4/include/soc/ppa_struct.h +++ b/components/soc/esp32p4/register/soc/ppa_struct.h @@ -446,15 +446,15 @@ typedef union { typedef union { struct { /** colorkey_default_b : R/W; bitpos: [7:0]; default: 0; - * default B channle value of color key + * default B channel value of color key */ uint32_t colorkey_default_b:8; /** colorkey_default_g : R/W; bitpos: [15:8]; default: 0; - * default G channle value of color key + * default G channel value of color key */ uint32_t colorkey_default_g:8; /** colorkey_default_r : R/W; bitpos: [23:16]; default: 0; - * default R channle value of color key + * default R channel value of color key */ uint32_t colorkey_default_r:8; /** colorkey_fg_bg_reverse : R/W; bitpos: [24]; default: 0; diff --git a/components/soc/esp32p4/include/soc/pvt_reg.h b/components/soc/esp32p4/register/soc/pvt_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/pvt_reg.h rename to components/soc/esp32p4/register/soc/pvt_reg.h diff --git a/components/soc/esp32p4/include/soc/pvt_struct.h b/components/soc/esp32p4/register/soc/pvt_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/pvt_struct.h rename to components/soc/esp32p4/register/soc/pvt_struct.h diff --git a/components/soc/esp32p4/include/soc/reg_base.h b/components/soc/esp32p4/register/soc/reg_base.h similarity index 100% rename from components/soc/esp32p4/include/soc/reg_base.h rename to components/soc/esp32p4/register/soc/reg_base.h diff --git a/components/soc/esp32p4/include/soc/rmt_reg.h b/components/soc/esp32p4/register/soc/rmt_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/rmt_reg.h rename to components/soc/esp32p4/register/soc/rmt_reg.h diff --git a/components/soc/esp32p4/include/soc/rmt_struct.h b/components/soc/esp32p4/register/soc/rmt_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/rmt_struct.h rename to components/soc/esp32p4/register/soc/rmt_struct.h diff --git a/components/soc/esp32p4/include/soc/rsa_reg.h b/components/soc/esp32p4/register/soc/rsa_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/rsa_reg.h rename to components/soc/esp32p4/register/soc/rsa_reg.h diff --git a/components/soc/esp32p4/include/soc/rsa_struct.h b/components/soc/esp32p4/register/soc/rsa_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/rsa_struct.h rename to components/soc/esp32p4/register/soc/rsa_struct.h diff --git a/components/soc/esp32p4/include/soc/rtclockcali_reg.h b/components/soc/esp32p4/register/soc/rtclockcali_reg.h similarity index 98% rename from components/soc/esp32p4/include/soc/rtclockcali_reg.h rename to components/soc/esp32p4/register/soc/rtclockcali_reg.h index 329ef154c4d2..d9794fe943b6 100644 --- a/components/soc/esp32p4/include/soc/rtclockcali_reg.h +++ b/components/soc/esp32p4/register/soc/rtclockcali_reg.h @@ -267,21 +267,21 @@ extern "C" { #define RTCLOCKCALI_DREQ_UPDATE_V 0x00000001U #define RTCLOCKCALI_DREQ_UPDATE_S 0 /** RTCLOCKCALI_DREQ_INIT_32K : WT; bitpos: [2]; default: 0; - * Initialize the vaule of 32K OSC dfreq setting. + * Initialize the value of 32K OSC dfreq setting. */ #define RTCLOCKCALI_DREQ_INIT_32K (BIT(2)) #define RTCLOCKCALI_DREQ_INIT_32K_M (RTCLOCKCALI_DREQ_INIT_32K_V << RTCLOCKCALI_DREQ_INIT_32K_S) #define RTCLOCKCALI_DREQ_INIT_32K_V 0x00000001U #define RTCLOCKCALI_DREQ_INIT_32K_S 2 /** RTCLOCKCALI_DREQ_INIT_FOSC : WT; bitpos: [3]; default: 0; - * Initialize the vaule of FOSC dfreq setting. + * Initialize the value of FOSC dfreq setting. */ #define RTCLOCKCALI_DREQ_INIT_FOSC (BIT(3)) #define RTCLOCKCALI_DREQ_INIT_FOSC_M (RTCLOCKCALI_DREQ_INIT_FOSC_V << RTCLOCKCALI_DREQ_INIT_FOSC_S) #define RTCLOCKCALI_DREQ_INIT_FOSC_V 0x00000001U #define RTCLOCKCALI_DREQ_INIT_FOSC_S 3 /** RTCLOCKCALI_DREQ_INIT_SOSC : WT; bitpos: [4]; default: 0; - * Initialize the vaule of SOSC dfreq setting. + * Initialize the value of SOSC dfreq setting. */ #define RTCLOCKCALI_DREQ_INIT_SOSC (BIT(4)) #define RTCLOCKCALI_DREQ_INIT_SOSC_M (RTCLOCKCALI_DREQ_INIT_SOSC_V << RTCLOCKCALI_DREQ_INIT_SOSC_S) @@ -312,21 +312,21 @@ extern "C" { #define RTCLOCKCALI_SOSC_DFREQ_SEL_V 0x00000001U #define RTCLOCKCALI_SOSC_DFREQ_SEL_S 7 /** RTCLOCKCALI_FINE_STEP : R/W; bitpos: [15:8]; default: 1; - * Frequncy fine step. + * Frequency fine step. */ #define RTCLOCKCALI_FINE_STEP 0x000000FFU #define RTCLOCKCALI_FINE_STEP_M (RTCLOCKCALI_FINE_STEP_V << RTCLOCKCALI_FINE_STEP_S) #define RTCLOCKCALI_FINE_STEP_V 0x000000FFU #define RTCLOCKCALI_FINE_STEP_S 8 /** RTCLOCKCALI_COARSE_STEP_FAST : R/W; bitpos: [23:16]; default: 8; - * Frequncy coarse step,use to decrease calibration time. + * Frequency coarse step,use to decrease calibration time. */ #define RTCLOCKCALI_COARSE_STEP_FAST 0x000000FFU #define RTCLOCKCALI_COARSE_STEP_FAST_M (RTCLOCKCALI_COARSE_STEP_FAST_V << RTCLOCKCALI_COARSE_STEP_FAST_S) #define RTCLOCKCALI_COARSE_STEP_FAST_V 0x000000FFU #define RTCLOCKCALI_COARSE_STEP_FAST_S 16 /** RTCLOCKCALI_COARSE_STEP_SLOW : R/W; bitpos: [31:24]; default: 8; - * Frequncy coarse step,use to decrease calibration time. + * Frequency coarse step,use to decrease calibration time. */ #define RTCLOCKCALI_COARSE_STEP_SLOW 0x000000FFU #define RTCLOCKCALI_COARSE_STEP_SLOW_M (RTCLOCKCALI_COARSE_STEP_SLOW_V << RTCLOCKCALI_COARSE_STEP_SLOW_S) @@ -409,14 +409,14 @@ extern "C" { */ #define RTCLOCKCALI_INT_RAW_REG (DR_REG_RTCLOCKCALI_BASE + 0x38) /** RTCLOCKCALI_XTAL_TIMEOUT_INT_RAW : R/WTC/SS; bitpos: [29]; default: 0; - * Indicate the xtal timeout once happend . + * Indicate the xtal timeout once happened . */ #define RTCLOCKCALI_XTAL_TIMEOUT_INT_RAW (BIT(29)) #define RTCLOCKCALI_XTAL_TIMEOUT_INT_RAW_M (RTCLOCKCALI_XTAL_TIMEOUT_INT_RAW_V << RTCLOCKCALI_XTAL_TIMEOUT_INT_RAW_S) #define RTCLOCKCALI_XTAL_TIMEOUT_INT_RAW_V 0x00000001U #define RTCLOCKCALI_XTAL_TIMEOUT_INT_RAW_S 29 /** RTCLOCKCALI_CALI_TIMEOUT_INT_RAW : R/WTC/SS; bitpos: [30]; default: 0; - * Indicate the calibration timeout once happend . + * Indicate the calibration timeout once happened . */ #define RTCLOCKCALI_CALI_TIMEOUT_INT_RAW (BIT(30)) #define RTCLOCKCALI_CALI_TIMEOUT_INT_RAW_M (RTCLOCKCALI_CALI_TIMEOUT_INT_RAW_V << RTCLOCKCALI_CALI_TIMEOUT_INT_RAW_S) diff --git a/components/soc/esp32p4/include/soc/rtclockcali_struct.h b/components/soc/esp32p4/register/soc/rtclockcali_struct.h similarity index 97% rename from components/soc/esp32p4/include/soc/rtclockcali_struct.h rename to components/soc/esp32p4/register/soc/rtclockcali_struct.h index 358ab21fc80a..3898c7629381 100644 --- a/components/soc/esp32p4/include/soc/rtclockcali_struct.h +++ b/components/soc/esp32p4/register/soc/rtclockcali_struct.h @@ -107,15 +107,15 @@ typedef union { uint32_t dreq_update:1; uint32_t reserved_1:1; /** dreq_init_32k : WT; bitpos: [2]; default: 0; - * Initialize the vaule of 32K OSC dfreq setting. + * Initialize the value of 32K OSC dfreq setting. */ uint32_t dreq_init_32k:1; /** dreq_init_fosc : WT; bitpos: [3]; default: 0; - * Initialize the vaule of FOSC dfreq setting. + * Initialize the value of FOSC dfreq setting. */ uint32_t dreq_init_fosc:1; /** dreq_init_sosc : WT; bitpos: [4]; default: 0; - * Initialize the vaule of SOSC dfreq setting. + * Initialize the value of SOSC dfreq setting. */ uint32_t dreq_init_sosc:1; /** rc32k_dfreq_sel : R/W; bitpos: [5]; default: 0; @@ -134,15 +134,15 @@ typedef union { */ uint32_t sosc_dfreq_sel:1; /** fine_step : R/W; bitpos: [15:8]; default: 1; - * Frequncy fine step. + * Frequency fine step. */ uint32_t fine_step:8; /** coarse_step_fast : R/W; bitpos: [23:16]; default: 8; - * Frequncy coarse step,use to decrease calibration time. + * Frequency coarse step,use to decrease calibration time. */ uint32_t coarse_step_fast:8; /** coarse_step_slow : R/W; bitpos: [31:24]; default: 8; - * Frequncy coarse step,use to decrease calibration time. + * Frequency coarse step,use to decrease calibration time. */ uint32_t coarse_step_slow:8; }; @@ -218,11 +218,11 @@ typedef union { struct { uint32_t reserved_0:29; /** xtal_timeout_int_raw : R/WTC/SS; bitpos: [29]; default: 0; - * Indicate the xtal timeout once happend . + * Indicate the xtal timeout once happened . */ uint32_t xtal_timeout_int_raw:1; /** cali_timeout_int_raw : R/WTC/SS; bitpos: [30]; default: 0; - * Indicate the calibration timeout once happend . + * Indicate the calibration timeout once happened . */ uint32_t cali_timeout_int_raw:1; /** cali_done_int_raw : R/WTC/SS; bitpos: [31]; default: 0; diff --git a/components/soc/esp32p4/include/soc/sdmmc_reg.h b/components/soc/esp32p4/register/soc/sdmmc_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/sdmmc_reg.h rename to components/soc/esp32p4/register/soc/sdmmc_reg.h index f8ba68d49fef..536a95e4ef9a 100644 --- a/components/soc/esp32p4/include/soc/sdmmc_reg.h +++ b/components/soc/esp32p4/register/soc/sdmmc_reg.h @@ -893,7 +893,7 @@ extern "C" { #define SDHOST_BUS_TYPE_REG_V 0x00000001U #define SDHOST_BUS_TYPE_REG_S 6 /** SDHOST_DATA_WIDTH_REG : RO; bitpos: [9:7]; default: 1; - * Regisger data widht is 32. + * Regisger data width is 32. */ #define SDHOST_DATA_WIDTH_REG 0x00000007U #define SDHOST_DATA_WIDTH_REG_M (SDHOST_DATA_WIDTH_REG_V << SDHOST_DATA_WIDTH_REG_S) @@ -907,7 +907,7 @@ extern "C" { #define SDHOST_ADDR_WIDTH_REG_V 0x0000003FU #define SDHOST_ADDR_WIDTH_REG_S 10 /** SDHOST_DMA_WIDTH_REG : RO; bitpos: [20:18]; default: 1; - * DMA data witdth is 32. + * DMA data width is 32. */ #define SDHOST_DMA_WIDTH_REG 0x00000007U #define SDHOST_DMA_WIDTH_REG_M (SDHOST_DMA_WIDTH_REG_V << SDHOST_DMA_WIDTH_REG_S) @@ -921,7 +921,7 @@ extern "C" { #define SDHOST_RAM_INDISE_REG_V 0x00000001U #define SDHOST_RAM_INDISE_REG_S 21 /** SDHOST_HOLD_REG : RO; bitpos: [22]; default: 1; - * Have a hold regiser in data path . + * Have a hold register in data path . */ #define SDHOST_HOLD_REG (BIT(22)) #define SDHOST_HOLD_REG_M (SDHOST_HOLD_REG_V << SDHOST_HOLD_REG_S) @@ -940,9 +940,9 @@ extern "C" { */ #define SDHOST_UHS_REG (DR_REG_SDHOST_BASE + 0x74) /** SDHOST_DDR_REG : R/W; bitpos: [17:16]; default: 0; - * DDR mode selecton,1 bit for each card. - * 0-Non-DDR mdoe. - * 1-DDR mdoe. + * DDR mode selection,1 bit for each card. + * 0-Non-DDR mode. + * 1-DDR mode. */ #define SDHOST_DDR_REG 0x00000003U #define SDHOST_DDR_REG_M (SDHOST_DDR_REG_V << SDHOST_DDR_REG_S) diff --git a/components/soc/esp32p4/include/soc/sdmmc_struct.h b/components/soc/esp32p4/register/soc/sdmmc_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/sdmmc_struct.h rename to components/soc/esp32p4/register/soc/sdmmc_struct.h index f9b5a5ed77b1..10318d6c9c72 100644 --- a/components/soc/esp32p4/include/soc/sdmmc_struct.h +++ b/components/soc/esp32p4/register/soc/sdmmc_struct.h @@ -870,7 +870,7 @@ typedef union { */ uint32_t bus_type_reg:1; /** data_width_reg : RO; bitpos: [9:7]; default: 1; - * Regisger data widht is 32. + * Regisger data width is 32. */ uint32_t data_width_reg:3; /** addr_width_reg : RO; bitpos: [15:10]; default: 19; @@ -879,7 +879,7 @@ typedef union { uint32_t addr_width_reg:6; uint32_t reserved_16:2; /** dma_width_reg : RO; bitpos: [20:18]; default: 1; - * DMA data witdth is 32. + * DMA data width is 32. */ uint32_t dma_width_reg:3; /** ram_indise_reg : RO; bitpos: [21]; default: 0; @@ -887,7 +887,7 @@ typedef union { */ uint32_t ram_indise_reg:1; /** hold_reg : RO; bitpos: [22]; default: 1; - * Have a hold regiser in data path . + * Have a hold register in data path . */ uint32_t hold_reg:1; uint32_t reserved_23:1; @@ -909,9 +909,9 @@ typedef union { struct { uint32_t reserved_0:16; /** ddr : R/W; bitpos: [17:16]; default: 0; - * DDR mode selecton,1 bit for each card. - * 0-Non-DDR mdoe. - * 1-DDR mdoe. + * DDR mode selection,1 bit for each card. + * 0-Non-DDR mode. + * 1-DDR mode. */ uint32_t ddr:2; uint32_t reserved_18:14; diff --git a/components/soc/esp32p4/include/soc/sha_reg.h b/components/soc/esp32p4/register/soc/sha_reg.h similarity index 98% rename from components/soc/esp32p4/include/soc/sha_reg.h rename to components/soc/esp32p4/register/soc/sha_reg.h index 888da914b300..40f4d53dfb07 100644 --- a/components/soc/esp32p4/include/soc/sha_reg.h +++ b/components/soc/esp32p4/register/soc/sha_reg.h @@ -156,7 +156,7 @@ extern "C" { #define SHA_DATE_S 0 /** SHA_H_MEM register - * Sha H memory which contains intermediate hash or finial hash. + * Sha H memory which contains intermediate hash or final hash. */ #define SHA_H_MEM (DR_REG_SHA_BASE + 0x40) #define SHA_H_MEM_SIZE_BYTES 64 diff --git a/components/soc/esp32p4/include/soc/sha_struct.h b/components/soc/esp32p4/register/soc/sha_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/sha_struct.h rename to components/soc/esp32p4/register/soc/sha_struct.h diff --git a/components/soc/esp32p4/include/soc/soc_etm_reg.h b/components/soc/esp32p4/register/soc/soc_etm_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/soc_etm_reg.h rename to components/soc/esp32p4/register/soc/soc_etm_reg.h diff --git a/components/soc/esp32p4/include/soc/soc_etm_struct.h b/components/soc/esp32p4/register/soc/soc_etm_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/soc_etm_struct.h rename to components/soc/esp32p4/register/soc/soc_etm_struct.h diff --git a/components/soc/esp32p4/include/soc/spi1_mem_c_reg.h b/components/soc/esp32p4/register/soc/spi1_mem_c_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi1_mem_c_reg.h rename to components/soc/esp32p4/register/soc/spi1_mem_c_reg.h index e3bfc692140c..eab9fa8a7e31 100644 --- a/components/soc/esp32p4/include/soc/spi1_mem_c_reg.h +++ b/components/soc/esp32p4/register/soc/spi1_mem_c_reg.h @@ -321,7 +321,7 @@ extern "C" { /** SPI1_MEM_C_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. + * SPI clock is always on. */ #define SPI1_MEM_C_CLK_MODE 0x00000003U #define SPI1_MEM_C_CLK_MODE_M (SPI1_MEM_C_CLK_MODE_V << SPI1_MEM_C_CLK_MODE_S) @@ -1268,7 +1268,7 @@ extern "C" { #define SPI1_MEM_C_MST_ST_END_INT_RAW_S 4 /** SPI1_MEM_C_BROWN_OUT_INT_RAW : R/WTC/SS; bitpos: [10]; default: 0; * The raw bit for SPI1_MEM_C_BROWN_OUT_INT interrupt. 1: Triggered condition is that - * chip is loosing power and RTC module sends out brown out close flash request to + * chip is losing power and RTC module sends out brown out close flash request to * SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered * and MSPI returns to idle state. 0: Others. */ diff --git a/components/soc/esp32p4/include/soc/spi1_mem_c_struct.h b/components/soc/esp32p4/register/soc/spi1_mem_c_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi1_mem_c_struct.h rename to components/soc/esp32p4/register/soc/spi1_mem_c_struct.h index b78578c0825a..6b08445b576d 100644 --- a/components/soc/esp32p4/include/soc/spi1_mem_c_struct.h +++ b/components/soc/esp32p4/register/soc/spi1_mem_c_struct.h @@ -334,7 +334,7 @@ typedef union { /** clk_mode : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. + * SPI clock is always on. */ uint32_t clk_mode:2; /** cs_hold_dly_res : R/W; bitpos: [11:2]; default: 1023; @@ -912,7 +912,7 @@ typedef union { uint32_t reserved_5:5; /** brown_out_int_raw : R/WTC/SS; bitpos: [10]; default: 0; * The raw bit for SPI1_MEM_C_BROWN_OUT_INT interrupt. 1: Triggered condition is that - * chip is loosing power and RTC module sends out brown out close flash request to + * chip is losing power and RTC module sends out brown out close flash request to * SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered * and MSPI returns to idle state. 0: Others. */ diff --git a/components/soc/esp32p4/include/soc/spi1_mem_s_reg.h b/components/soc/esp32p4/register/soc/spi1_mem_s_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi1_mem_s_reg.h rename to components/soc/esp32p4/register/soc/spi1_mem_s_reg.h index 8aa91923ec71..9bc4517be9ab 100644 --- a/components/soc/esp32p4/include/soc/spi1_mem_s_reg.h +++ b/components/soc/esp32p4/register/soc/spi1_mem_s_reg.h @@ -321,7 +321,7 @@ extern "C" { /** SPI1_MEM_S_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. + * SPI clock is always on. */ #define SPI1_MEM_S_CLK_MODE 0x00000003U #define SPI1_MEM_S_CLK_MODE_M (SPI1_MEM_S_CLK_MODE_V << SPI1_MEM_S_CLK_MODE_S) @@ -1268,7 +1268,7 @@ extern "C" { #define SPI1_MEM_S_MST_ST_END_INT_RAW_S 4 /** SPI1_MEM_S_BROWN_OUT_INT_RAW : R/WTC/SS; bitpos: [10]; default: 0; * The raw bit for SPI1_MEM_S_BROWN_OUT_INT interrupt. 1: Triggered condition is that - * chip is loosing power and RTC module sends out brown out close flash request to + * chip is losing power and RTC module sends out brown out close flash request to * SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered * and MSPI returns to idle state. 0: Others. */ diff --git a/components/soc/esp32p4/include/soc/spi1_mem_s_struct.h b/components/soc/esp32p4/register/soc/spi1_mem_s_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi1_mem_s_struct.h rename to components/soc/esp32p4/register/soc/spi1_mem_s_struct.h index c2bb46eb9d2d..5cbe96076bab 100644 --- a/components/soc/esp32p4/include/soc/spi1_mem_s_struct.h +++ b/components/soc/esp32p4/register/soc/spi1_mem_s_struct.h @@ -334,7 +334,7 @@ typedef union { /** clk_mode : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. + * SPI clock is always on. */ uint32_t clk_mode:2; /** cs_hold_dly_res : R/W; bitpos: [11:2]; default: 1023; @@ -1123,7 +1123,7 @@ typedef union { uint32_t reserved_5:5; /** brown_out_int_raw : R/WTC/SS; bitpos: [10]; default: 0; * The raw bit for SPI1_MEM_S_BROWN_OUT_INT interrupt. 1: Triggered condition is that - * chip is loosing power and RTC module sends out brown out close flash request to + * chip is losing power and RTC module sends out brown out close flash request to * SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered * and MSPI returns to idle state. 0: Others. */ diff --git a/components/soc/esp32p4/include/soc/spi_mem_c_reg.h b/components/soc/esp32p4/register/soc/spi_mem_c_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi_mem_c_reg.h rename to components/soc/esp32p4/register/soc/spi_mem_c_reg.h index 89ff7ae94899..4b5c8c54e52f 100644 --- a/components/soc/esp32p4/include/soc/spi_mem_c_reg.h +++ b/components/soc/esp32p4/register/soc/spi_mem_c_reg.h @@ -199,7 +199,7 @@ extern "C" { /** SPI_MEM_C_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. + * SPI clock is always on. */ #define SPI_MEM_C_CLK_MODE 0x00000003U #define SPI_MEM_C_CLK_MODE_M (SPI_MEM_C_CLK_MODE_V << SPI_MEM_C_CLK_MODE_S) @@ -2694,7 +2694,7 @@ extern "C" { */ #define SPI_MEM_C_DPA_CTRL_REG (DR_REG_FLASH_SPI0_BASE + 0x388) /** SPI_MEM_C_CRYPT_SECURITY_LEVEL : R/W; bitpos: [2:0]; default: 7; - * Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1-7: + * Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1-7: * The bigger the number is, the more secure the cryption is. (Note that the * performance of cryption will decrease together with this number increasing) */ diff --git a/components/soc/esp32p4/include/soc/spi_mem_c_struct.h b/components/soc/esp32p4/register/soc/spi_mem_c_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi_mem_c_struct.h rename to components/soc/esp32p4/register/soc/spi_mem_c_struct.h index c694be7e0a31..61abcf05911f 100644 --- a/components/soc/esp32p4/include/soc/spi_mem_c_struct.h +++ b/components/soc/esp32p4/register/soc/spi_mem_c_struct.h @@ -167,7 +167,7 @@ typedef union { /** clk_mode : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. + * SPI clock is always on. */ uint32_t clk_mode:2; uint32_t reserved_2:19; @@ -1908,7 +1908,7 @@ typedef union { typedef union { struct { /** crypt_security_level : R/W; bitpos: [2:0]; default: 7; - * Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1-7: + * Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1-7: * The bigger the number is, the more secure the cryption is. (Note that the * performance of cryption will decrease together with this number increasing) */ diff --git a/components/soc/esp32p4/include/soc/spi_mem_s_reg.h b/components/soc/esp32p4/register/soc/spi_mem_s_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi_mem_s_reg.h rename to components/soc/esp32p4/register/soc/spi_mem_s_reg.h index 4e81aa49b4f7..ec83145c7719 100644 --- a/components/soc/esp32p4/include/soc/spi_mem_s_reg.h +++ b/components/soc/esp32p4/register/soc/spi_mem_s_reg.h @@ -199,7 +199,7 @@ extern "C" { /** SPI_MEM_S_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. + * SPI clock is always on. */ #define SPI_MEM_S_CLK_MODE 0x00000003U #define SPI_MEM_S_CLK_MODE_M (SPI_MEM_S_CLK_MODE_V << SPI_MEM_S_CLK_MODE_S) @@ -945,7 +945,7 @@ extern "C" { #define SPI_MEM_S_SCLKCNT_N_V 0x000000FFU #define SPI_MEM_S_SCLKCNT_N_S 16 /** SPI_MEM_S_SCLK_EQU_SYSCLK : R/W; bitpos: [31]; default: 0; - * For SPI0 external RAM interface, 1: spi_mem_clk is eqaul to system 0: spi_mem_clk + * For SPI0 external RAM interface, 1: spi_mem_clk is equal to system 0: spi_mem_clk * is divided from system clock. */ #define SPI_MEM_S_SCLK_EQU_SYSCLK (BIT(31)) @@ -3461,7 +3461,7 @@ extern "C" { */ #define SPI_MEM_S_DPA_CTRL_REG (DR_REG_PSRAM_MSPI0_BASE + 0x388) /** SPI_MEM_S_CRYPT_SECURITY_LEVEL : R/W; bitpos: [2:0]; default: 7; - * Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1-7: + * Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1-7: * The bigger the number is, the more secure the cryption is. (Note that the * performance of cryption will decrease together with this number increasing) */ diff --git a/components/soc/esp32p4/include/soc/spi_mem_s_struct.h b/components/soc/esp32p4/register/soc/spi_mem_s_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi_mem_s_struct.h rename to components/soc/esp32p4/register/soc/spi_mem_s_struct.h index 691b30c6d7d0..4948325c47ce 100644 --- a/components/soc/esp32p4/include/soc/spi_mem_s_struct.h +++ b/components/soc/esp32p4/register/soc/spi_mem_s_struct.h @@ -167,7 +167,7 @@ typedef union { /** mem_clk_mode : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. + * SPI clock is always on. */ uint32_t mem_clk_mode:2; uint32_t reserved_2:19; @@ -504,7 +504,7 @@ typedef union { uint32_t mem_sclkcnt_n:8; uint32_t reserved_24:7; /** mem_sclk_equ_sysclk : R/W; bitpos: [31]; default: 0; - * For SPI0 external RAM interface, 1: spi_mem_s_clk is eqaul to system 0: spi_mem_s_clk + * For SPI0 external RAM interface, 1: spi_mem_s_clk is equal to system 0: spi_mem_s_clk * is divided from system clock. */ uint32_t mem_sclk_equ_sysclk:1; @@ -2446,7 +2446,7 @@ typedef union { typedef union { struct { /** crypt_security_level : R/W; bitpos: [2:0]; default: 7; - * Set the security level of spi mem cryption. 0: Shut off cryption DPA funtion. 1-7: + * Set the security level of spi mem cryption. 0: Shut off cryption DPA function. 1-7: * The bigger the number is, the more secure the cryption is. (Note that the * performance of cryption will decrease together with this number increasing) */ diff --git a/components/soc/esp32p4/include/soc/spi_reg.h b/components/soc/esp32p4/register/soc/spi_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi_reg.h rename to components/soc/esp32p4/register/soc/spi_reg.h index 61a1858b0965..ffce14740eee 100644 --- a/components/soc/esp32p4/include/soc/spi_reg.h +++ b/components/soc/esp32p4/register/soc/spi_reg.h @@ -225,7 +225,7 @@ extern "C" { #define SPI_CLKDIV_PRE_V 0x0000000FU #define SPI_CLKDIV_PRE_S 18 /** SPI_CLK_EQU_SYSCLK : R/W; bitpos: [31]; default: 1; - * In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system + * In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system * clock. Can be configured in CONF state. */ #define SPI_CLK_EQU_SYSCLK (BIT(31)) @@ -1978,7 +1978,7 @@ extern "C" { /** SPI_CLK_MODE : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. Can be configured in CONF state. + * SPI clock is always on. Can be configured in CONF state. */ #define SPI_CLK_MODE 0x00000003U #define SPI_CLK_MODE_M (SPI_CLK_MODE_V << SPI_CLK_MODE_S) diff --git a/components/soc/esp32p4/include/soc/spi_struct.h b/components/soc/esp32p4/register/soc/spi_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/spi_struct.h rename to components/soc/esp32p4/register/soc/spi_struct.h index 66929cd3a071..8d004e60e1db 100644 --- a/components/soc/esp32p4/include/soc/spi_struct.h +++ b/components/soc/esp32p4/register/soc/spi_struct.h @@ -511,7 +511,7 @@ typedef union { /** clk_mode : R/W; bitpos: [1:0]; default: 0; * SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed * one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: - * SPI clock is alwasy on. Can be configured in CONF state. + * SPI clock is always on. Can be configured in CONF state. */ uint32_t clk_mode:2; /** clk_mode_13 : R/W; bitpos: [2]; default: 0; @@ -629,7 +629,7 @@ typedef union { uint32_t clkdiv_pre:4; uint32_t reserved_22:9; /** clk_equ_sysclk : R/W; bitpos: [31]; default: 1; - * In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system + * In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system * clock. Can be configured in CONF state. */ uint32_t clk_equ_sysclk:1; diff --git a/components/soc/esp32p4/include/soc/systimer_reg.h b/components/soc/esp32p4/register/soc/systimer_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/systimer_reg.h rename to components/soc/esp32p4/register/soc/systimer_reg.h diff --git a/components/soc/esp32p4/include/soc/systimer_struct.h b/components/soc/esp32p4/register/soc/systimer_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/systimer_struct.h rename to components/soc/esp32p4/register/soc/systimer_struct.h diff --git a/components/soc/esp32p4/include/soc/tcm_monitor_reg.h b/components/soc/esp32p4/register/soc/tcm_monitor_reg.h similarity index 98% rename from components/soc/esp32p4/include/soc/tcm_monitor_reg.h rename to components/soc/esp32p4/register/soc/tcm_monitor_reg.h index d89fc3009cce..f04f761def9c 100644 --- a/components/soc/esp32p4/include/soc/tcm_monitor_reg.h +++ b/components/soc/esp32p4/register/soc/tcm_monitor_reg.h @@ -12,7 +12,7 @@ extern "C" { #endif /** MEM_MONITOR_LOG_SETTING_REG register - * log config regsiter + * log config register */ #define MEM_MONITOR_LOG_SETTING_REG (DR_REG_MEM_MONITOR_BASE + 0x0) /** MEM_MONITOR_LOG_MODE : R/W; bitpos: [3:0]; default: 0; @@ -53,7 +53,7 @@ extern "C" { #define MEM_MONITOR_LOG_DMA_1_ENA_S 24 /** MEM_MONITOR_LOG_SETTING1_REG register - * log config regsiter + * log config register */ #define MEM_MONITOR_LOG_SETTING1_REG (DR_REG_MEM_MONITOR_BASE + 0x4) /** MEM_MONITOR_LOG_DMA_2_ENA : R/W; bitpos: [7:0]; default: 0; @@ -72,7 +72,7 @@ extern "C" { #define MEM_MONITOR_LOG_DMA_3_ENA_S 8 /** MEM_MONITOR_LOG_CHECK_DATA_REG register - * check data regsiter + * check data register */ #define MEM_MONITOR_LOG_CHECK_DATA_REG (DR_REG_MEM_MONITOR_BASE + 0x8) /** MEM_MONITOR_LOG_CHECK_DATA : R/W; bitpos: [31:0]; default: 0; @@ -97,7 +97,7 @@ extern "C" { #define MEM_MONITOR_LOG_DATA_MASK_S 0 /** MEM_MONITOR_LOG_MIN_REG register - * log boundary regsiter + * log boundary register */ #define MEM_MONITOR_LOG_MIN_REG (DR_REG_MEM_MONITOR_BASE + 0x10) /** MEM_MONITOR_LOG_MIN : R/W; bitpos: [31:0]; default: 0; @@ -109,7 +109,7 @@ extern "C" { #define MEM_MONITOR_LOG_MIN_S 0 /** MEM_MONITOR_LOG_MAX_REG register - * log boundary regsiter + * log boundary register */ #define MEM_MONITOR_LOG_MAX_REG (DR_REG_MEM_MONITOR_BASE + 0x14) /** MEM_MONITOR_LOG_MAX : R/W; bitpos: [31:0]; default: 0; diff --git a/components/soc/esp32p4/include/soc/tcm_monitor_struct.h b/components/soc/esp32p4/register/soc/tcm_monitor_struct.h similarity index 98% rename from components/soc/esp32p4/include/soc/tcm_monitor_struct.h rename to components/soc/esp32p4/register/soc/tcm_monitor_struct.h index c88691215af4..e3e1abf3761d 100644 --- a/components/soc/esp32p4/include/soc/tcm_monitor_struct.h +++ b/components/soc/esp32p4/register/soc/tcm_monitor_struct.h @@ -12,7 +12,7 @@ extern "C" { /** Group: configuration registers */ /** Type of log_setting register - * log config regsiter + * log config register */ typedef union { struct { @@ -43,7 +43,7 @@ typedef union { } mem_monitor_log_setting_reg_t; /** Type of log_setting1 register - * log config regsiter + * log config register */ typedef union { struct { @@ -61,7 +61,7 @@ typedef union { } mem_monitor_log_setting1_reg_t; /** Type of log_check_data register - * check data regsiter + * check data register */ typedef union { struct { @@ -89,7 +89,7 @@ typedef union { } mem_monitor_log_data_mask_reg_t; /** Type of log_min register - * log boundary regsiter + * log boundary register */ typedef union { struct { @@ -102,7 +102,7 @@ typedef union { } mem_monitor_log_min_reg_t; /** Type of log_max register - * log boundary regsiter + * log boundary register */ typedef union { struct { diff --git a/components/soc/esp32p4/include/soc/timer_group_reg.h b/components/soc/esp32p4/register/soc/timer_group_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/timer_group_reg.h rename to components/soc/esp32p4/register/soc/timer_group_reg.h diff --git a/components/soc/esp32p4/include/soc/timer_group_struct.h b/components/soc/esp32p4/register/soc/timer_group_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/timer_group_struct.h rename to components/soc/esp32p4/register/soc/timer_group_struct.h diff --git a/components/soc/esp32p4/include/soc/touch_reg.h b/components/soc/esp32p4/register/soc/touch_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/touch_reg.h rename to components/soc/esp32p4/register/soc/touch_reg.h diff --git a/components/soc/esp32p4/include/soc/touch_struct.h b/components/soc/esp32p4/register/soc/touch_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/touch_struct.h rename to components/soc/esp32p4/register/soc/touch_struct.h diff --git a/components/soc/esp32p4/include/soc/trace_reg.h b/components/soc/esp32p4/register/soc/trace_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/trace_reg.h rename to components/soc/esp32p4/register/soc/trace_reg.h diff --git a/components/soc/esp32p4/include/soc/trace_struct.h b/components/soc/esp32p4/register/soc/trace_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/trace_struct.h rename to components/soc/esp32p4/register/soc/trace_struct.h diff --git a/components/soc/esp32p4/include/soc/tsens_reg.h b/components/soc/esp32p4/register/soc/tsens_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/tsens_reg.h rename to components/soc/esp32p4/register/soc/tsens_reg.h diff --git a/components/soc/esp32p4/include/soc/tsens_struct.h b/components/soc/esp32p4/register/soc/tsens_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/tsens_struct.h rename to components/soc/esp32p4/register/soc/tsens_struct.h diff --git a/components/soc/esp32p4/include/soc/twai_reg.h b/components/soc/esp32p4/register/soc/twai_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/twai_reg.h rename to components/soc/esp32p4/register/soc/twai_reg.h diff --git a/components/soc/esp32p4/include/soc/twai_struct.h b/components/soc/esp32p4/register/soc/twai_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/twai_struct.h rename to components/soc/esp32p4/register/soc/twai_struct.h diff --git a/components/soc/esp32p4/include/soc/uart_reg.h b/components/soc/esp32p4/register/soc/uart_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/uart_reg.h rename to components/soc/esp32p4/register/soc/uart_reg.h index fc3c662721eb..014f8eaed299 100644 --- a/components/soc/esp32p4/include/soc/uart_reg.h +++ b/components/soc/esp32p4/register/soc/uart_reg.h @@ -100,7 +100,7 @@ extern "C" { #define UART_RXFIFO_TOUT_INT_RAW_V 0x00000001U #define UART_RXFIFO_TOUT_INT_RAW_S 8 /** UART_SW_XON_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ #define UART_SW_XON_INT_RAW (BIT(9)) @@ -285,7 +285,7 @@ extern "C" { #define UART_TX_BRK_DONE_INT_ST_V 0x00000001U #define UART_TX_BRK_DONE_INT_ST_S 12 /** UART_TX_BRK_IDLE_DONE_INT_ST : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ #define UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) @@ -760,7 +760,7 @@ extern "C" { #define UART_STOP_BIT_NUM_V 0x00000003U #define UART_STOP_BIT_NUM_S 4 /** UART_TXD_BRK : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ #define UART_TXD_BRK (BIT(6)) @@ -1326,7 +1326,7 @@ extern "C" { */ #define UART_TOUT_CONF_SYNC_REG(i) (REG_UART_BASE(i) + 0x64) /** UART_RX_TOUT_EN : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ #define UART_RX_TOUT_EN (BIT(0)) #define UART_RX_TOUT_EN_M (UART_RX_TOUT_EN_V << UART_RX_TOUT_EN_S) @@ -1450,7 +1450,7 @@ extern "C" { */ #define UART_HIGHPULSE_REG(i) (REG_UART_BASE(i) + 0x80) /** UART_HIGHPULSE_MIN_CNT : RO; bitpos: [11:0]; default: 4095; - * This register stores the value of the maxinum duration time for the high level + * This register stores the value of the maximum duration time for the high level * pulse. It is used in baud rate-detect process. */ #define UART_HIGHPULSE_MIN_CNT 0x00000FFFU diff --git a/components/soc/esp32p4/include/soc/uart_struct.h b/components/soc/esp32p4/register/soc/uart_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/uart_struct.h rename to components/soc/esp32p4/register/soc/uart_struct.h index b23e6db9305b..b750ef943afc 100644 --- a/components/soc/esp32p4/include/soc/uart_struct.h +++ b/components/soc/esp32p4/register/soc/uart_struct.h @@ -49,7 +49,7 @@ typedef union { typedef union { struct { /** rx_tout_en : R/W; bitpos: [0]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ uint32_t rx_tout_en:1; /** rx_tout_flow_dis : R/W; bitpos: [1]; default: 0; @@ -120,7 +120,7 @@ typedef union { */ uint32_t rxfifo_tout_int_raw:1; /** sw_xon_int_raw : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ uint32_t sw_xon_int_raw:1; @@ -238,7 +238,7 @@ typedef union { */ uint32_t tx_brk_done_int_st:1; /** tx_brk_idle_done_int_st : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ uint32_t tx_brk_idle_done_int_st:1; @@ -515,7 +515,7 @@ typedef union { */ uint32_t stop_bit_num:2; /** txd_brk : R/W; bitpos: [6]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ uint32_t txd_brk:1; @@ -1160,7 +1160,7 @@ typedef union { typedef union { struct { /** highpulse_min_cnt : RO; bitpos: [11:0]; default: 4095; - * This register stores the value of the maxinum duration time for the high level + * This register stores the value of the maximum duration time for the high level * pulse. It is used in baud rate-detect process. */ uint32_t highpulse_min_cnt:12; diff --git a/components/soc/esp32p4/include/soc/uhci_reg.h b/components/soc/esp32p4/register/soc/uhci_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/uhci_reg.h rename to components/soc/esp32p4/register/soc/uhci_reg.h diff --git a/components/soc/esp32p4/include/soc/uhci_struct.h b/components/soc/esp32p4/register/soc/uhci_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/uhci_struct.h rename to components/soc/esp32p4/register/soc/uhci_struct.h diff --git a/components/soc/esp32p4/include/soc/usb_serial_jtag_reg.h b/components/soc/esp32p4/register/soc/usb_serial_jtag_reg.h similarity index 99% rename from components/soc/esp32p4/include/soc/usb_serial_jtag_reg.h rename to components/soc/esp32p4/register/soc/usb_serial_jtag_reg.h index 478c734ea806..6de18f3a76f7 100644 --- a/components/soc/esp32p4/include/soc/usb_serial_jtag_reg.h +++ b/components/soc/esp32p4/register/soc/usb_serial_jtag_reg.h @@ -1140,7 +1140,7 @@ extern "C" { #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_RESET_RD_V 0x00000001U #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_RESET_RD_S 3 /** USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY : RO; bitpos: [4]; default: 1; - * CDC_ACM OUTOUT async FIFO empty signal in read clock domain. + * CDC_ACM OUTPUT async FIFO empty signal in read clock domain. */ #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY (BIT(4)) #define USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_M (USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_V << USB_SERIAL_JTAG_SERIAL_OUT_AFIFO_REMPTY_S) diff --git a/components/soc/esp32p4/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32p4/register/soc/usb_serial_jtag_struct.h similarity index 100% rename from components/soc/esp32p4/include/soc/usb_serial_jtag_struct.h rename to components/soc/esp32p4/register/soc/usb_serial_jtag_struct.h diff --git a/components/soc/esp32p4/include/soc/usb_wrap_reg.h b/components/soc/esp32p4/register/soc/usb_wrap_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/usb_wrap_reg.h rename to components/soc/esp32p4/register/soc/usb_wrap_reg.h diff --git a/components/soc/esp32p4/include/soc/usb_wrap_struct.h b/components/soc/esp32p4/register/soc/usb_wrap_struct.h similarity index 99% rename from components/soc/esp32p4/include/soc/usb_wrap_struct.h rename to components/soc/esp32p4/register/soc/usb_wrap_struct.h index b5f36b526dba..dd1b234e3426 100644 --- a/components/soc/esp32p4/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32p4/register/soc/usb_wrap_struct.h @@ -121,7 +121,7 @@ typedef union { */ uint32_t test_enable:1; /** test_usb_wrap_oe : R/W; bitpos: [1]; default: 0; - * USB pad one in test. + * USB pad oen in test. */ uint32_t test_usb_wrap_oe:1; /** test_tx_dp : R/W; bitpos: [2]; default: 0; diff --git a/components/soc/esp32p4/rmt_periph.c b/components/soc/esp32p4/rmt_periph.c index ec8625bc9450..e838ccb182a1 100644 --- a/components/soc/esp32p4/rmt_periph.c +++ b/components/soc/esp32p4/rmt_periph.c @@ -76,6 +76,7 @@ static const regdma_entries_config_t rmt_regdma_entries[] = { const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = { [0] = { + .module = SLEEP_RETENTION_MODULE_RMT0, .regdma_entry_array = rmt_regdma_entries, .array_size = ARRAY_SIZE(rmt_regdma_entries) }, diff --git a/components/soc/esp32p4/spi_periph.c b/components/soc/esp32p4/spi_periph.c index 5a629b6604c1..db30a6bf6893 100644 --- a/components/soc/esp32p4/spi_periph.c +++ b/components/soc/esp32p4/spi_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,29 +13,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { { // MSPI on P4 has dedicated iomux pins - .spiclk_out = -1, - .spiclk_in = -1, - .spid_out = -1, - .spiq_out = -1, - .spiwp_out = -1, - .spihd_out = -1, - .spid_in = -1, - .spiq_in = -1, - .spiwp_in = -1, - .spihd_in = -1, - .spics_out = {-1}, - .spics_in = -1, - .spiclk_iomux_pin = -1, - .spid_iomux_pin = -1, - .spiq_iomux_pin = -1, - .spiwp_iomux_pin = -1, - .spihd_iomux_pin = -1, - .spics0_iomux_pin = -1, - .irq = -1, - .irq_dma = -1, - .module = -1, - .hw = NULL, - .func = -1, }, { .spiclk_out = SPI2_CK_PAD_OUT_IDX, .spiclk_in = SPI2_CK_PAD_IN_IDX, @@ -65,7 +42,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, .irq = ETS_SPI2_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_GPSPI2_MODULE, .hw = &GPSPI2, .func = SPI2_FUNC_NUM, }, { @@ -73,7 +49,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spiclk_in = SPI3_CK_PAD_IN_IDX, .spid_out = SPI3_D_PAD_OUT_IDX, .spiq_out = SPI3_QO_PAD_OUT_IDX, - //SPI3 doesn't have wp and hd signals .spiwp_out = SPI3_WP_PAD_OUT_IDX, .spihd_out = SPI3_HOLD_PAD_OUT_IDX, .spid_in = SPI3_D_PAD_IN_IDX, @@ -91,8 +66,56 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = -1, .irq = ETS_SPI3_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_GPSPI3_MODULE, .hw = &GPSPI3, .func = -1, } }; + +/** + * Backup registers in Light sleep: (total cnt 12) + * + * cmd + * addr + * ctrl + * clock + * user + * user1 + * user2 + * ms_dlen + * misc + * dma_conf + * dma_int_ena + * slave + */ +#define SPI_RETENTION_REGS_CNT 12 +static const uint32_t spi_regs_map[4] = {0x31ff, 0x1000000, 0x0, 0x0}; +#define SPI_REG_RETENTION_ENTRIES(num) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GPSPI_LINK(0), \ + REG_SPI_BASE(num), REG_SPI_BASE(num), \ + SPI_RETENTION_REGS_CNT, 0, 0, \ + spi_regs_map[0], spi_regs_map[1], \ + spi_regs_map[2], spi_regs_map[3]), \ + .owner = ENTRY(0) }, \ + /* Additional interrupt setting is required by idf SPI drivers after register recovered */ \ + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_GPSPI_LINK(1), \ + SPI_DMA_INT_SET_REG(num), \ + SPI_TRANS_DONE_INT_SET | SPI_DMA_SEG_TRANS_DONE_INT_SET , \ + UINT32_MAX, 1, 0), \ + .owner = ENTRY(0) }, \ +} + +static const regdma_entries_config_t spi2_regs_retention[] = SPI_REG_RETENTION_ENTRIES(2); // '2' for GPSPI2 +static const regdma_entries_config_t spi3_regs_retention[] = SPI_REG_RETENTION_ENTRIES(3); + +const spi_reg_retention_info_t spi_reg_retention_info[SOC_SPI_PERIPH_NUM - 1] = { // '-1' to except mspi + { + .module_id = SLEEP_RETENTION_MODULE_GPSPI2, + .entry_array = spi2_regs_retention, + .array_size = ARRAY_SIZE(spi2_regs_retention), + }, + { + .module_id = SLEEP_RETENTION_MODULE_GPSPI3, + .entry_array = spi3_regs_retention, + .array_size = ARRAY_SIZE(spi3_regs_retention), + }, +}; diff --git a/components/soc/esp32p4/twai_periph.c b/components/soc/esp32p4/twai_periph.c index 67b016fa0d66..b9fde3d047ea 100644 --- a/components/soc/esp32p4/twai_periph.c +++ b/components/soc/esp32p4/twai_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/twai_periph.h" +#include "soc/twai_reg.h" #include "soc/gpio_sig_map.h" const twai_controller_signal_conn_t twai_controller_periph_signals = { @@ -38,3 +39,55 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = { } } }; + +/** + * TWAI Registers to be saved during sleep retention + * - TWAI_MODE_REG + * - TWAI_INTERRUPT_ENABLE_REG + * - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG + * - TWAI_ERR_WARNING_LIMIT_REG + * - TWAI_RX_ERR_CNT_REG + * - TWAI_TX_ERR_CNT_REG + * - TWAI_DATA_x_REG + * - TWAI_CLOCK_DIVIDER_REG + * - TWAI_SW_STANDBY_CFG_REG + * - TWAI_HW_CFG_REG + * - TWAI_HW_STANDBY_CNT_REG + * - TWAI_IDLE_INTR_CNT_REG + * - TWAI_ECO_CFG_REG + * - TWAI_TIMESTAMP_PRESCALER_REG + * - TWAI_TIMESTAMP_CFG_REG +*/ +#define TWAI_RETENTION_REGS_CNT 28 +#define TWAI_RETENTION_REGS_BASE(i) REG_TWAI_BASE(i) +static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0}; +#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \ + TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \ + TWAI_RETENTION_REGS_CNT, 0, 0, \ + twai_regs_map[0], twai_regs_map[1], \ + twai_regs_map[2], twai_regs_map[3]), \ + .owner = ENTRY(0) }, \ +} + +static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t twai1_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(1); +static const regdma_entries_config_t twai2_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(2); + +const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = { + [0] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI0, + .entry_array = twai0_regs_retention, + .array_size = ARRAY_SIZE(twai0_regs_retention) + }, + [1] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI1, + .entry_array = twai1_regs_retention, + .array_size = ARRAY_SIZE(twai1_regs_retention) + }, + [2] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI2, + .entry_array = twai2_regs_retention, + .array_size = ARRAY_SIZE(twai2_regs_retention) + }, +}; diff --git a/components/soc/esp32p4/uart_periph.c b/components/soc/esp32p4/uart_periph.c index 98d00fd4a224..c28c0be81460 100644 --- a/components/soc/esp32p4/uart_periph.c +++ b/components/soc/esp32p4/uart_periph.c @@ -253,22 +253,27 @@ static const regdma_entries_config_t uart4_regdma_entries[] = UART_SLEEP_RETENTI const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { [0] = { + .module = SLEEP_RETENTION_MODULE_UART0, .regdma_entry_array = uart0_regdma_entries, .array_size = ARRAY_SIZE(uart0_regdma_entries), }, [1] = { + .module = SLEEP_RETENTION_MODULE_UART1, .regdma_entry_array = uart1_regdma_entries, .array_size = ARRAY_SIZE(uart1_regdma_entries), }, [2] = { + .module = SLEEP_RETENTION_MODULE_UART2, .regdma_entry_array = uart2_regdma_entries, .array_size = ARRAY_SIZE(uart2_regdma_entries), }, [3] = { + .module = SLEEP_RETENTION_MODULE_UART3, .regdma_entry_array = uart3_regdma_entries, .array_size = ARRAY_SIZE(uart3_regdma_entries), }, [4] = { + .module = SLEEP_RETENTION_MODULE_UART4, .regdma_entry_array = uart4_regdma_entries, .array_size = ARRAY_SIZE(uart4_regdma_entries), }, diff --git a/components/soc/esp32p4/usb_dwc_periph.c b/components/soc/esp32p4/usb_dwc_periph.c new file mode 100644 index 000000000000..23fecc8afebb --- /dev/null +++ b/components/soc/esp32p4/usb_dwc_periph.c @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "soc/interrupts.h" +#include "soc/gpio_sig_map.h" +#include "soc/usb_dwc_periph.h" +#include "soc/usb_dwc_struct.h" + +/* -------------------------------- Private --------------------------------- */ + +static const usb_utmi_otg_signal_conn_t dwc_fs_otg_signals = { + // Inputs + .iddig = USB_OTG11_IDDIG_PAD_IN_IDX, + .avalid = USB_OTG11_AVALID_PAD_IN_IDX, + .bvalid = USB_SRP_BVALID_PAD_IN_IDX, + .vbusvalid = USB_OTG11_VBUSVALID_PAD_IN_IDX, + .sessend = USB_SRP_SESSEND_PAD_IN_IDX, + // Outputs + .idpullup = USB_OTG11_IDPULLUP_PAD_OUT_IDX, + .dppulldown = USB_OTG11_DPPULLDOWN_PAD_OUT_IDX, + .dmpulldown = USB_OTG11_DMPULLDOWN_PAD_OUT_IDX, + .drvvbus = USB_OTG11_DRVVBUS_PAD_OUT_IDX, + .chrgvbus = USB_SRP_CHRGVBUS_PAD_OUT_IDX, + .dischrgvbus = USB_SRP_DISCHRGVBUS_PAD_OUT_IDX, +}; + +/* --------------------------------- Public --------------------------------- */ + +const usb_dwc_info_t usb_dwc_info = { + .controllers = { + // High-Speed USB-DWC + [0] = { + .fsls_signals = NULL, + .otg_signals = NULL, + .irq = ETS_USB_OTG_INTR_SOURCE, + .irq_2nd_cpu = ETS_USB_OTG_ENDP_MULTI_PROC_INTR_SOURCE, + }, + // Full-Speed USB-DWC + [1] = { + .fsls_signals = NULL, + .otg_signals = &dwc_fs_otg_signals, + .irq = ETS_USB_OTG11_CH0_INTR_SOURCE, + .irq_2nd_cpu = -1, + }, + }, +}; diff --git a/components/soc/esp32s2/i2s_periph.c b/components/soc/esp32s2/i2s_periph.c index 25b4804cb2d2..c13b47926dfb 100644 --- a/components/soc/esp32s2/i2s_periph.c +++ b/components/soc/esp32s2/i2s_periph.c @@ -29,6 +29,5 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sig = I2S0I_DATA_IN15_IDX, .irq = ETS_I2S0_INTR_SOURCE, - .module = PERIPH_I2S0_MODULE, } }; diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index ebb997e5406c..686747c9f8da 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -535,6 +535,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 8 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 966adf439c82..3e50662f7346 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -233,6 +233,7 @@ #define SOC_LEDC_SUPPORT_APB_CLOCK (1) #define SOC_LEDC_SUPPORT_REF_TICK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (8) #define SOC_LEDC_TIMER_BIT_WIDTH (14) #define SOC_LEDC_SUPPORT_FADE_STOP (1) diff --git a/components/soc/esp32s2/interrupts.c b/components/soc/esp32s2/interrupts.c index 460c907ef0c9..9e566ceb49ee 100644 --- a/components/soc/esp32s2/interrupts.c +++ b/components/soc/esp32s2/interrupts.c @@ -43,7 +43,7 @@ const char * const esp_isr_names[ETS_MAX_INTR_SOURCE] = { [33] = "SPI2", [34] = "SPI3", [35] = "I2S0", - [36] = "I2S1", + [36] = "RESERVED", [37] = "UART0", [38] = "UART1", [39] = "UART2", diff --git a/components/soc/esp32s2/register/soc/interrupt_reg.h b/components/soc/esp32s2/register/soc/interrupt_reg.h index a0b7bc1a3fee..dace8948cf40 100644 --- a/components/soc/esp32s2/register/soc/interrupt_reg.h +++ b/components/soc/esp32s2/register/soc/interrupt_reg.h @@ -299,14 +299,6 @@ extern "C" { #define DPORT_PRO_I2S0_INT_MAP_V 0x1F #define DPORT_PRO_I2S0_INT_MAP_S 0 -#define DPORT_PRO_I2S1_INT_MAP_REG (DR_REG_INTERRUPT_BASE + 0x090) -/* DPORT_PRO_I2S1_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */ -/*description: */ -#define DPORT_PRO_I2S1_INT_MAP 0x0000001F -#define DPORT_PRO_I2S1_INT_MAP_M ((DPORT_PRO_I2S1_INT_MAP_V)<<(DPORT_PRO_I2S1_INT_MAP_S)) -#define DPORT_PRO_I2S1_INT_MAP_V 0x1F -#define DPORT_PRO_I2S1_INT_MAP_S 0 - #define DPORT_PRO_UART_INTR_MAP_REG (DR_REG_INTERRUPT_BASE + 0x094) /* DPORT_PRO_UART_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */ /*description: */ diff --git a/components/soc/esp32s2/register/soc/system_reg.h b/components/soc/esp32s2/register/soc/system_reg.h index 87f02a07a619..9058fd0f4628 100644 --- a/components/soc/esp32s2/register/soc/system_reg.h +++ b/components/soc/esp32s2/register/soc/system_reg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -236,12 +236,6 @@ extern "C" { #define DPORT_SPI2_DMA_CLK_EN_M (BIT(22)) #define DPORT_SPI2_DMA_CLK_EN_V 0x1 #define DPORT_SPI2_DMA_CLK_EN_S 22 -/* DPORT_I2S1_CLK_EN : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: */ -#define DPORT_I2S1_CLK_EN (BIT(21)) -#define DPORT_I2S1_CLK_EN_M (BIT(21)) -#define DPORT_I2S1_CLK_EN_V 0x1 -#define DPORT_I2S1_CLK_EN_S 21 /* DPORT_PWM1_CLK_EN : R/W ;bitpos:[20] ;default: 1'b0 ; */ /*description: */ #define DPORT_PWM1_CLK_EN (BIT(20)) @@ -464,12 +458,6 @@ extern "C" { #define DPORT_SPI2_DMA_RST_M (BIT(22)) #define DPORT_SPI2_DMA_RST_V 0x1 #define DPORT_SPI2_DMA_RST_S 22 -/* DPORT_I2S1_RST : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: */ -#define DPORT_I2S1_RST (BIT(21)) -#define DPORT_I2S1_RST_M (BIT(21)) -#define DPORT_I2S1_RST_V 0x1 -#define DPORT_I2S1_RST_S 21 /* DPORT_PWM1_RST : R/W ;bitpos:[20] ;default: 1'b0 ; */ /*description: */ #define DPORT_PWM1_RST (BIT(20)) diff --git a/components/soc/esp32s2/spi_periph.c b/components/soc/esp32s2/spi_periph.c index 2dfcdfb20bc1..c1ed623608ce 100644 --- a/components/soc/esp32s2/spi_periph.c +++ b/components/soc/esp32s2/spi_periph.c @@ -32,7 +32,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = MSPI_IOMUX_PIN_NUM_CS0, .irq = ETS_SPI1_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_SPI_MODULE, .hw = (spi_dev_t *) &SPIMEM1, .func = MSPI_FUNC_NUM, @@ -65,7 +64,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = FSPI_IOMUX_PIN_NUM_CS, .irq = ETS_SPI2_INTR_SOURCE, .irq_dma = ETS_SPI2_DMA_INTR_SOURCE, - .module = PERIPH_FSPI_MODULE, .hw = &GPSPI2, .func = FSPI_FUNC_NUM, }, { @@ -91,7 +89,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = -1, .irq = ETS_SPI3_INTR_SOURCE, .irq_dma = ETS_SPI3_DMA_INTR_SOURCE, - .module = PERIPH_HSPI_MODULE, .hw = &GPSPI3, .func = -1, } diff --git a/components/soc/esp32s2/usb_dwc_periph.c b/components/soc/esp32s2/usb_dwc_periph.c index eba3eaaf60bb..2cb76077e76b 100644 --- a/components/soc/esp32s2/usb_dwc_periph.c +++ b/components/soc/esp32s2/usb_dwc_periph.c @@ -4,8 +4,78 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "soc/usb_dwc_periph.h" #include "soc/gpio_sig_map.h" +#include "soc/usb_periph.h" +#include "soc/interrupts.h" +#include "soc/usb_dwc_periph.h" + +/* -------------------------------- Private --------------------------------- */ + +static const usb_fsls_serial_signal_conn_t fsls_signals = { + // Inputs + .rx_dp = USB_EXTPHY_VP_IDX, + .rx_dm = USB_EXTPHY_VM_IDX, + .rx_rcv = USB_EXTPHY_RCV_IDX, + // Outputs + .suspend_n = USB_EXTPHY_SUSPND_IDX, + .tx_enable_n = USB_EXTPHY_OEN_IDX, + .tx_dp = USB_EXTPHY_VPO_IDX, + .tx_dm = USB_EXTPHY_VMO_IDX, + .fs_edge_sel = USB_EXTPHY_SPEED_IDX, +}; + +static const usb_utmi_otg_signal_conn_t otg_signals = { + // Inputs + .iddig = USB_OTG_IDDIG_IN_IDX, + .avalid = USB_OTG_AVALID_IN_IDX, + .bvalid = USB_SRP_BVALID_IN_IDX, + .vbusvalid = USB_OTG_VBUSVALID_IN_IDX, + .sessend = USB_SRP_SESSEND_IN_IDX, + // Outputs + .idpullup = USB_OTG_IDPULLUP_IDX, + .dppulldown = USB_OTG_DPPULLDOWN_IDX, + .dmpulldown = USB_OTG_DMPULLDOWN_IDX, + .drvvbus = USB_OTG_DRVVBUS_IDX, + .chrgvbus = USB_SRP_CHRGVBUS_IDX, + .dischrgvbus = USB_SRP_DISCHRGVBUS_IDX, +}; + +/* --------------------------------- Public --------------------------------- */ + +const usb_dwc_info_t usb_dwc_info = { + .controllers = { + [0] = { + .fsls_signals = &fsls_signals, + .otg_signals = &otg_signals, + .irq = ETS_USB_INTR_SOURCE, + .irq_2nd_cpu = -1, + }, + }, +}; + +/* ------------------------------- Deprecated ------------------------------- */ + +/* +Note: These IO pins are deprecated. When connecting USB OTG to an external FSLS +PHY, the FSLS Serial Interface signals can be routed to any GPIO via the GPIO +matrix. Thus, this mapping of signals to IO pins is meaningless. + +Todo: Remove in IDF v6.0 (IDF-9029) +*/ +const usb_iopin_dsc_t usb_periph_iopins[] = { + {USBPHY_VP_NUM, USB_EXTPHY_VP_IDX, 0, 1}, + {USBPHY_VM_NUM, USB_EXTPHY_VM_IDX, 0, 1}, + {USBPHY_RCV_NUM, USB_EXTPHY_RCV_IDX, 0, 1}, + {USBPHY_OEN_NUM, USB_EXTPHY_OEN_IDX, 1, 1}, + {USBPHY_VPO_NUM, USB_EXTPHY_VPO_IDX, 1, 1}, + {USBPHY_VMO_NUM, USB_EXTPHY_VMO_IDX, 1, 1}, + {GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, 0, 0}, //connected connector is mini-B + //connected connector is mini-B + {GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, 0, 0}, //HIGH to force USB device mode + {GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, 0, 0}, //receiving a valid Vbus from host + {GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_AVALID_IN_IDX, 0, 0}, + {-1, -1, 0, 0} +}; /* Bunch of constants for USB peripheral: GPIO signals diff --git a/components/soc/esp32s2/usb_periph.c b/components/soc/esp32s2/usb_periph.c deleted file mode 100644 index a3fda7193e38..000000000000 --- a/components/soc/esp32s2/usb_periph.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "soc/soc_caps.h" -#include "soc/usb_periph.h" - -/* -Note: These IO pins are deprecated. When connecting USB OTG to an external FSLS -PHY, the FSLS Serial Interface signals can be routed to any GPIO via the GPIO -matrix. Thus, this mapping of signals to IO pins is meaningless. - -Todo: Remove in IDF v6.0 (IDF-9029) -*/ -const usb_iopin_dsc_t usb_periph_iopins[] = { - {USBPHY_VP_NUM, USB_EXTPHY_VP_IDX, 0, 1}, - {USBPHY_VM_NUM, USB_EXTPHY_VM_IDX, 0, 1}, - {USBPHY_RCV_NUM, USB_EXTPHY_RCV_IDX, 0, 1}, - {USBPHY_OEN_NUM, USB_EXTPHY_OEN_IDX, 1, 1}, - {USBPHY_VPO_NUM, USB_EXTPHY_VPO_IDX, 1, 1}, - {USBPHY_VMO_NUM, USB_EXTPHY_VMO_IDX, 1, 1}, - {GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, 0, 0}, //connected connector is mini-B - //connected connector is mini-B - {GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, 0, 0}, //HIGH to force USB device mode - {GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, 0, 0}, //receiving a valid Vbus from host - {GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_AVALID_IN_IDX, 0, 0}, - {-1, -1, 0, 0} -}; diff --git a/components/soc/esp32s3/i2s_periph.c b/components/soc/esp32s3/i2s_periph.c index 853541bd9eb2..9d040cfc5451 100644 --- a/components/soc/esp32s3/i2s_periph.c +++ b/components/soc/esp32s3/i2s_periph.c @@ -33,7 +33,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[3] = I2S0I_SD3_IN_IDX, .irq = ETS_I2S0_INTR_SOURCE, - .module = PERIPH_I2S0_MODULE, }, { .mck_out_sig = I2S1_MCLK_OUT_IDX, @@ -57,6 +56,5 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[3] = -1, .irq = ETS_I2S1_INTR_SOURCE, - .module = PERIPH_I2S1_MODULE, } }; diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 649a3da6ca84..0c228dc8416b 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -603,6 +603,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK bool default y +config SOC_LEDC_TIMER_NUM + int + default 4 + config SOC_LEDC_CHANNEL_NUM int default 8 diff --git a/components/soc/esp32s3/include/soc/dport_reg.h b/components/soc/esp32s3/include/soc/dport_reg.h index e17afb79b5c2..e9f3de4c442d 100644 --- a/components/soc/esp32s3/include/soc/dport_reg.h +++ b/components/soc/esp32s3/include/soc/dport_reg.h @@ -5,20 +5,19 @@ */ #pragma once -#include "soc.h" +#include "soc/interrupt_reg.h" +#include "soc/system_reg.h" +#include "soc/sensitive_reg.h" +#include "soc/soc.h" + #ifdef __cplusplus extern "C" { #endif -#include "interrupt_reg.h" -#include "system_reg.h" -#include "sensitive_reg.h" -#include "soc.h" - #define DPORT_DATE_REG SYSTEM_DATE_REG #ifndef __ASSEMBLER__ -#include "dport_access.h" +#include "soc/dport_access.h" #endif #ifdef __cplusplus diff --git a/components/soc/esp32s3/include/soc/soc.h b/components/soc/esp32s3/include/soc/soc.h index 056c6d9f4e5d..78a29ee2c309 100644 --- a/components/soc/esp32s3/include/soc/soc.h +++ b/components/soc/esp32s3/include/soc/soc.h @@ -12,7 +12,7 @@ #endif #include "esp_bit_defs.h" -#include "reg_base.h" +#include "soc/reg_base.h" #define PRO_CPU_NUM (0) #define APP_CPU_NUM (1) diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index aef115bfe30e..6e8194fbf97d 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -236,6 +236,7 @@ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_APB_CLOCK (1) #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_TIMER_NUM (4) #define SOC_LEDC_CHANNEL_NUM (8) #define SOC_LEDC_TIMER_BIT_WIDTH (14) #define SOC_LEDC_SUPPORT_FADE_STOP (1) diff --git a/components/soc/esp32s3/include/soc/usb_dwc_struct.h b/components/soc/esp32s3/include/soc/usb_dwc_struct.h index 5fd5800715e8..70f73e37b7a8 100644 --- a/components/soc/esp32s3/include/soc/usb_dwc_struct.h +++ b/components/soc/esp32s3/include/soc/usb_dwc_struct.h @@ -33,7 +33,7 @@ typedef union { uint32_t hnpreq: 1; uint32_t hstsethnpen: 1; uint32_t devhnpen: 1; - uint32_t ehen: 1; + uint32_t ehen: 1; // codespell:ignore ehen uint32_t reserved_13: 2; uint32_t dbncefltrbypass: 1; uint32_t conidsts: 1; diff --git a/components/soc/esp32s3/register/soc/.gitkeep b/components/soc/esp32s3/register/soc/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/soc/esp32s3/include/soc/apb_ctrl_reg.h b/components/soc/esp32s3/register/soc/apb_ctrl_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/apb_ctrl_reg.h rename to components/soc/esp32s3/register/soc/apb_ctrl_reg.h index 845394f702ea..809463766aea 100644 --- a/components/soc/esp32s3/include/soc/apb_ctrl_reg.h +++ b/components/soc/esp32s3/register/soc/apb_ctrl_reg.h @@ -8,7 +8,7 @@ #warning "apb_ctrl_reg is deprecated due to duplicated with syscon_reg, please use syscon_reg instead, they are same" -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/apb_ctrl_struct.h b/components/soc/esp32s3/register/soc/apb_ctrl_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/apb_ctrl_struct.h rename to components/soc/esp32s3/register/soc/apb_ctrl_struct.h diff --git a/components/soc/esp32s3/include/soc/apb_saradc_reg.h b/components/soc/esp32s3/register/soc/apb_saradc_reg.h similarity index 97% rename from components/soc/esp32s3/include/soc/apb_saradc_reg.h rename to components/soc/esp32s3/register/soc/apb_saradc_reg.h index b9c88f225470..61d99974db4d 100644 --- a/components/soc/esp32s3/include/soc/apb_saradc_reg.h +++ b/components/soc/esp32s3/register/soc/apb_saradc_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_APB_SARADC_REG_H_ #define _SOC_APB_SARADC_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/apb_saradc_struct.h b/components/soc/esp32s3/register/soc/apb_saradc_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/apb_saradc_struct.h rename to components/soc/esp32s3/register/soc/apb_saradc_struct.h diff --git a/components/soc/esp32s3/include/soc/assist_debug_reg.h b/components/soc/esp32s3/register/soc/assist_debug_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/assist_debug_reg.h rename to components/soc/esp32s3/register/soc/assist_debug_reg.h index 0bf71c44d33e..35a89cadabb5 100644 --- a/components/soc/esp32s3/include/soc/assist_debug_reg.h +++ b/components/soc/esp32s3/register/soc/assist_debug_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_ASSIST_DEBUG_REG_H_ #define _SOC_ASSIST_DEBUG_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/assist_debug_struct.h b/components/soc/esp32s3/register/soc/assist_debug_struct.h similarity index 96% rename from components/soc/esp32s3/include/soc/assist_debug_struct.h rename to components/soc/esp32s3/register/soc/assist_debug_struct.h index a6152af468c6..a66c4ecb772b 100644 --- a/components/soc/esp32s3/include/soc/assist_debug_struct.h +++ b/components/soc/esp32s3/register/soc/assist_debug_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_ASSIST_DEBUG_STRUCT_H_ #define _SOC_ASSIST_DEBUG_STRUCT_H_ diff --git a/components/soc/esp32s3/include/soc/efuse_reg.h b/components/soc/esp32s3/register/soc/efuse_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/efuse_reg.h rename to components/soc/esp32s3/register/soc/efuse_reg.h index c4b8a5ed47a5..0c89dd3808ea 100644 --- a/components/soc/esp32s3/include/soc/efuse_reg.h +++ b/components/soc/esp32s3/register/soc/efuse_reg.h @@ -7,7 +7,7 @@ #include #include "soc/soc.h" -#include "efuse_defs.h" +#include "soc/efuse_defs.h" #ifdef __cplusplus extern "C" { #endif @@ -553,7 +553,7 @@ extern "C" { #define EFUSE_DIS_DIRECT_BOOT_V 0x00000001U #define EFUSE_DIS_DIRECT_BOOT_S 1 /** EFUSE_DIS_USB_SERIAL_JTAG_ROM_PRINT : RO; bitpos: [2]; default: 0; - * Selectes the default UART print channel. 0: UART0. 1: UART1. + * Selects the default UART print channel. 0: UART0. 1: UART1. */ #define EFUSE_DIS_USB_SERIAL_JTAG_ROM_PRINT (BIT(2)) #define EFUSE_DIS_USB_SERIAL_JTAG_ROM_PRINT_M (EFUSE_DIS_USB_SERIAL_JTAG_ROM_PRINT_V << EFUSE_DIS_USB_SERIAL_JTAG_ROM_PRINT_S) @@ -2638,7 +2638,7 @@ extern "C" { #define EFUSE_CLK_EN_S 16 /** EFUSE_CONF_REG register - * eFuse operation mode configuraiton register + * eFuse operation mode configuration register */ #define EFUSE_CONF_REG (DR_REG_EFUSE_BASE + 0x1cc) /** EFUSE_OP_CODE : R/W; bitpos: [15:0]; default: 0; diff --git a/components/soc/esp32s3/include/soc/efuse_struct.h b/components/soc/esp32s3/register/soc/efuse_struct.h similarity index 99% rename from components/soc/esp32s3/include/soc/efuse_struct.h rename to components/soc/esp32s3/register/soc/efuse_struct.h index a3c589f543c9..2b2639c7522d 100644 --- a/components/soc/esp32s3/include/soc/efuse_struct.h +++ b/components/soc/esp32s3/register/soc/efuse_struct.h @@ -423,7 +423,7 @@ typedef union { */ uint32_t dis_direct_boot:1; /** dis_usb_serial_jtag_rom_print : RO; bitpos: [2]; default: 0; - * Selectes the default UART print channel. 0: UART0. 1: UART1. + * Selects the default UART print channel. 0: UART0. 1: UART1. */ uint32_t dis_usb_serial_jtag_rom_print:1; /** flash_ecc_mode : RO; bitpos: [3]; default: 0; @@ -2163,7 +2163,7 @@ typedef union { } efuse_clk_reg_t; /** Type of conf register - * eFuse operation mode configuraiton register + * eFuse operation mode configuration register */ typedef union { struct { diff --git a/components/soc/esp32s3/include/soc/extmem_reg.h b/components/soc/esp32s3/register/soc/extmem_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/extmem_reg.h rename to components/soc/esp32s3/register/soc/extmem_reg.h index 5763ec6df774..4929c47f86c2 100644 --- a/components/soc/esp32s3/include/soc/extmem_reg.h +++ b/components/soc/esp32s3/register/soc/extmem_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_EXTMEM_REG_H_ #define _SOC_EXTMEM_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif @@ -112,15 +104,15 @@ which is combined with DCACHE_PRELOCK_SCT0_SIZE_REG.*/ #define EXTMEM_DCACHE_PRELOCK_SCT_SIZE_REG (DR_REG_EXTMEM_BASE + 0x18) /* EXTMEM_DCACHE_PRELOCK_SCT0_SIZE : R/W ;bitpos:[31:16] ;default: 16'h0 ; */ -/*description: The bits are used to configure the first length of data locking, which is combin -ed with DCACHE_PRELOCK_SCT0_ADDR_REG.*/ +/*description: The bits are used to configure the first length of data locking, which is +combined with DCACHE_PRELOCK_SCT0_ADDR_REG.*/ #define EXTMEM_DCACHE_PRELOCK_SCT0_SIZE 0x0000FFFF #define EXTMEM_DCACHE_PRELOCK_SCT0_SIZE_M ((EXTMEM_DCACHE_PRELOCK_SCT0_SIZE_V)<<(EXTMEM_DCACHE_PRELOCK_SCT0_SIZE_S)) #define EXTMEM_DCACHE_PRELOCK_SCT0_SIZE_V 0xFFFF #define EXTMEM_DCACHE_PRELOCK_SCT0_SIZE_S 16 /* EXTMEM_DCACHE_PRELOCK_SCT1_SIZE : R/W ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: The bits are used to configure the second length of data locking, which is combi -ned with DCACHE_PRELOCK_SCT1_ADDR_REG.*/ +/*description: The bits are used to configure the second length of data locking, which is +combined with DCACHE_PRELOCK_SCT1_ADDR_REG.*/ #define EXTMEM_DCACHE_PRELOCK_SCT1_SIZE 0x0000FFFF #define EXTMEM_DCACHE_PRELOCK_SCT1_SIZE_M ((EXTMEM_DCACHE_PRELOCK_SCT1_SIZE_V)<<(EXTMEM_DCACHE_PRELOCK_SCT1_SIZE_S)) #define EXTMEM_DCACHE_PRELOCK_SCT1_SIZE_V 0xFFFF @@ -189,7 +181,7 @@ ter writeback operation done..*/ #define EXTMEM_DCACHE_WRITEBACK_ENA_S 1 /* EXTMEM_DCACHE_INVALIDATE_ENA : R/W ;bitpos:[0] ;default: 1'b1 ; */ /*description: The bit is used to enable invalidate operation. It will be cleared by hardware a -fter invalidate operation done..*/ +after invalidate operation done..*/ #define EXTMEM_DCACHE_INVALIDATE_ENA (BIT(0)) #define EXTMEM_DCACHE_INVALIDATE_ENA_M (BIT(0)) #define EXTMEM_DCACHE_INVALIDATE_ENA_V 0x1 @@ -342,8 +334,8 @@ ache_autoload_done. 1: enable, 0: disable. .*/ #define EXTMEM_DCACHE_AUTOLOAD_SCT0_ADDR_REG (DR_REG_EXTMEM_BASE + 0x50) /* EXTMEM_DCACHE_AUTOLOAD_SCT0_ADDR : R/W ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: The bits are used to configure the start virtual address of the first section fo -r autoload operation. It should be combined with dcache_autoload_sct0_ena..*/ +/*description: The bits are used to configure the start virtual address of the first section +for autoload operation. It should be combined with dcache_autoload_sct0_ena..*/ #define EXTMEM_DCACHE_AUTOLOAD_SCT0_ADDR 0xFFFFFFFF #define EXTMEM_DCACHE_AUTOLOAD_SCT0_ADDR_M ((EXTMEM_DCACHE_AUTOLOAD_SCT0_ADDR_V)<<(EXTMEM_DCACHE_AUTOLOAD_SCT0_ADDR_S)) #define EXTMEM_DCACHE_AUTOLOAD_SCT0_ADDR_V 0xFFFFFFFF @@ -472,15 +464,15 @@ which is combined with ICACHE_PRELOCK_SCT0_SIZE_REG.*/ #define EXTMEM_ICACHE_PRELOCK_SCT_SIZE_REG (DR_REG_EXTMEM_BASE + 0x78) /* EXTMEM_ICACHE_PRELOCK_SCT0_SIZE : R/W ;bitpos:[31:16] ;default: 16'h0 ; */ -/*description: The bits are used to configure the first length of data locking, which is combin -ed with ICACHE_PRELOCK_SCT0_ADDR_REG.*/ +/*description: The bits are used to configure the first length of data locking, which is +combined with ICACHE_PRELOCK_SCT0_ADDR_REG.*/ #define EXTMEM_ICACHE_PRELOCK_SCT0_SIZE 0x0000FFFF #define EXTMEM_ICACHE_PRELOCK_SCT0_SIZE_M ((EXTMEM_ICACHE_PRELOCK_SCT0_SIZE_V)<<(EXTMEM_ICACHE_PRELOCK_SCT0_SIZE_S)) #define EXTMEM_ICACHE_PRELOCK_SCT0_SIZE_V 0xFFFF #define EXTMEM_ICACHE_PRELOCK_SCT0_SIZE_S 16 /* EXTMEM_ICACHE_PRELOCK_SCT1_SIZE : R/W ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: The bits are used to configure the second length of data locking, which is combi -ned with ICACHE_PRELOCK_SCT1_ADDR_REG.*/ +/*description: The bits are used to configure the second length of data locking, which is +combined with ICACHE_PRELOCK_SCT1_ADDR_REG.*/ #define EXTMEM_ICACHE_PRELOCK_SCT1_SIZE 0x0000FFFF #define EXTMEM_ICACHE_PRELOCK_SCT1_SIZE_M ((EXTMEM_ICACHE_PRELOCK_SCT1_SIZE_V)<<(EXTMEM_ICACHE_PRELOCK_SCT1_SIZE_S)) #define EXTMEM_ICACHE_PRELOCK_SCT1_SIZE_V 0xFFFF @@ -535,7 +527,7 @@ counts of cache block. It should be combined with ICACHE_LOCK_ADDR_REG..*/ #define EXTMEM_ICACHE_SYNC_DONE_S 1 /* EXTMEM_ICACHE_INVALIDATE_ENA : R/W ;bitpos:[0] ;default: 1'b1 ; */ /*description: The bit is used to enable invalidate operation. It will be cleared by hardware a -fter invalidate operation done..*/ +after invalidate operation done..*/ #define EXTMEM_ICACHE_INVALIDATE_ENA (BIT(0)) #define EXTMEM_ICACHE_INVALIDATE_ENA_M (BIT(0)) #define EXTMEM_ICACHE_INVALIDATE_ENA_V 0x1 @@ -655,8 +647,8 @@ ache_autoload_done. 1: enable, 0: disable. .*/ #define EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR_REG (DR_REG_EXTMEM_BASE + 0xA4) /* EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR : R/W ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: The bits are used to configure the start virtual address of the first section fo -r autoload operation. It should be combined with icache_autoload_sct0_ena..*/ +/*description: The bits are used to configure the start virtual address of the first section +for autoload operation. It should be combined with icache_autoload_sct0_ena..*/ #define EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR 0xFFFFFFFF #define EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR_M ((EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR_V)<<(EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR_S)) #define EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR_V 0xFFFFFFFF @@ -855,7 +847,7 @@ cks all have been occupied by occupy-mode..*/ #define EXTMEM_IBUS_CNT_OVF_INT_CLR_V 0x1 #define EXTMEM_IBUS_CNT_OVF_INT_CLR_S 7 /* EXTMEM_DCACHE_OCCUPY_EXC_INT_CLR : WOD ;bitpos:[6] ;default: 1'b0 ; */ -/*description: The bit is used to clear interrupt by dcache trying to replace a line whose bloc +/*description: The bit is used to clear interrupt by dcache trying to replace a line whose block ks all have been occupied by occupy-mode..*/ #define EXTMEM_DCACHE_OCCUPY_EXC_INT_CLR (BIT(6)) #define EXTMEM_DCACHE_OCCUPY_EXC_INT_CLR_M (BIT(6)) @@ -914,7 +906,7 @@ w..*/ #define EXTMEM_DBUS_ACS_FLASH_MISS_CNT_OVF_ST_V 0x1 #define EXTMEM_DBUS_ACS_FLASH_MISS_CNT_OVF_ST_S 10 /* EXTMEM_DBUS_ACS_CNT_OVF_ST : RO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: The bit is used to indicate interrupt by dbus access flash/spiram counter overfl +/*description: The bit is used to indicate interrupt by dbus access flash/spiram counter overflow ow..*/ #define EXTMEM_DBUS_ACS_CNT_OVF_ST (BIT(9)) #define EXTMEM_DBUS_ACS_CNT_OVF_ST_M (BIT(9)) @@ -928,7 +920,7 @@ verflow..*/ #define EXTMEM_IBUS_ACS_MISS_CNT_OVF_ST_V 0x1 #define EXTMEM_IBUS_ACS_MISS_CNT_OVF_ST_S 8 /* EXTMEM_IBUS_ACS_CNT_OVF_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: The bit is used to indicate interrupt by ibus access flash/spiram counter overfl +/*description: The bit is used to indicate interrupt by ibus access flash/spiram counter overflow ow..*/ #define EXTMEM_IBUS_ACS_CNT_OVF_ST (BIT(7)) #define EXTMEM_IBUS_ACS_CNT_OVF_ST_M (BIT(7)) @@ -1642,8 +1634,8 @@ the others fields inside this register..*/ #define EXTMEM_CACHE_VADDR_REG (DR_REG_EXTMEM_BASE + 0x188) /* EXTMEM_CACHE_VADDR : R/W ;bitpos:[31:0] ;default: 32'h00000000 ; */ -/*description: Those bits stores the virtual address which will decide where inside the specifi -ed tag memory object will be accessed..*/ +/*description: Those bits stores the virtual address which will decide where inside the +specified tag memory object will be accessed..*/ #define EXTMEM_CACHE_VADDR 0xFFFFFFFF #define EXTMEM_CACHE_VADDR_M ((EXTMEM_CACHE_VADDR_V)<<(EXTMEM_CACHE_VADDR_S)) #define EXTMEM_CACHE_VADDR_V 0xFFFFFFFF diff --git a/components/soc/esp32s3/include/soc/extmem_struct.h b/components/soc/esp32s3/register/soc/extmem_struct.h similarity index 98% rename from components/soc/esp32s3/include/soc/extmem_struct.h rename to components/soc/esp32s3/register/soc/extmem_struct.h index 58ca64629426..8e2a9aad3c25 100644 --- a/components/soc/esp32s3/include/soc/extmem_struct.h +++ b/components/soc/esp32s3/register/soc/extmem_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_EXTMEM_STRUCT_H_ #define _SOC_EXTMEM_STRUCT_H_ diff --git a/components/soc/esp32s3/include/soc/gdma_reg.h b/components/soc/esp32s3/register/soc/gdma_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/gdma_reg.h rename to components/soc/esp32s3/register/soc/gdma_reg.h index 53e76bdc6ff0..7c37c513ef9e 100644 --- a/components/soc/esp32s3/include/soc/gdma_reg.h +++ b/components/soc/esp32s3/register/soc/gdma_reg.h @@ -7,7 +7,7 @@ #define _SOC_GDMA_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/gdma_struct.h b/components/soc/esp32s3/register/soc/gdma_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/gdma_struct.h rename to components/soc/esp32s3/register/soc/gdma_struct.h diff --git a/components/soc/esp32s3/include/soc/gpio_reg.h b/components/soc/esp32s3/register/soc/gpio_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/gpio_reg.h rename to components/soc/esp32s3/register/soc/gpio_reg.h index 39656ffce35c..8a109f6dd200 100644 --- a/components/soc/esp32s3/include/soc/gpio_reg.h +++ b/components/soc/esp32s3/register/soc/gpio_reg.h @@ -1,26 +1,18 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_GPIO_REG_H_ #define _SOC_GPIO_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define GPIO_PIN_CONFIG_MSB 12 #define GPIO_PIN_CONFIG_LSB 11 diff --git a/components/soc/esp32s3/include/soc/gpio_sd_reg.h b/components/soc/esp32s3/register/soc/gpio_sd_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/gpio_sd_reg.h rename to components/soc/esp32s3/register/soc/gpio_sd_reg.h index 4aa1fe8f86f6..f171b12dae5b 100644 --- a/components/soc/esp32s3/include/soc/gpio_sd_reg.h +++ b/components/soc/esp32s3/register/soc/gpio_sd_reg.h @@ -6,7 +6,7 @@ #pragma once -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32s3/include/soc/gpio_sd_struct.h b/components/soc/esp32s3/register/soc/gpio_sd_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/gpio_sd_struct.h rename to components/soc/esp32s3/register/soc/gpio_sd_struct.h diff --git a/components/soc/esp32s3/include/soc/gpio_struct.h b/components/soc/esp32s3/register/soc/gpio_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/gpio_struct.h rename to components/soc/esp32s3/register/soc/gpio_struct.h diff --git a/components/soc/esp32s3/include/soc/hinf_reg.h b/components/soc/esp32s3/register/soc/hinf_reg.h similarity index 93% rename from components/soc/esp32s3/include/soc/hinf_reg.h rename to components/soc/esp32s3/register/soc/hinf_reg.h index 212fe817ca2e..d419cf129e01 100644 --- a/components/soc/esp32s3/include/soc/hinf_reg.h +++ b/components/soc/esp32s3/register/soc/hinf_reg.h @@ -1,19 +1,11 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once -#include "soc.h" +#include "soc/soc.h" #define HINF_CFG_DATA0_REG (DR_REG_HINF_BASE + 0x0) /* HINF_DEVICE_ID_FN1 : R/W ;bitpos:[31:16] ;default: 16'h2222 ; */ diff --git a/components/soc/esp32s3/include/soc/hinf_struct.h b/components/soc/esp32s3/register/soc/hinf_struct.h similarity index 84% rename from components/soc/esp32s3/include/soc/hinf_struct.h rename to components/soc/esp32s3/register/soc/hinf_struct.h index 965f8bd43c1e..cf0713461bff 100644 --- a/components/soc/esp32s3/include/soc/hinf_struct.h +++ b/components/soc/esp32s3/register/soc/hinf_struct.h @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include diff --git a/components/soc/esp32s3/include/soc/host_reg.h b/components/soc/esp32s3/register/soc/host_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/host_reg.h rename to components/soc/esp32s3/register/soc/host_reg.h index afcd67d85f28..4dc04161fcae 100644 --- a/components/soc/esp32s3/include/soc/host_reg.h +++ b/components/soc/esp32s3/register/soc/host_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_HOST_REG_H_ #define _SOC_HOST_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/host_struct.h b/components/soc/esp32s3/register/soc/host_struct.h similarity index 97% rename from components/soc/esp32s3/include/soc/host_struct.h rename to components/soc/esp32s3/register/soc/host_struct.h index 1a6b89e28175..79a830ef1454 100644 --- a/components/soc/esp32s3/include/soc/host_struct.h +++ b/components/soc/esp32s3/register/soc/host_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_HOST_STRUCT_H_ #define _SOC_HOST_STRUCT_H_ @@ -459,7 +451,7 @@ typedef volatile struct host_dev_s { uint32_t reserved_f0; union { struct { - uint32_t infor : 20; + uint32_t infor : 20; // codespell:ignore infor uint32_t reserved20 : 12; }; uint32_t val; diff --git a/components/soc/esp32s3/include/soc/i2c_reg.h b/components/soc/esp32s3/register/soc/i2c_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/i2c_reg.h rename to components/soc/esp32s3/register/soc/i2c_reg.h index 5d19afa1c32a..0585f139b325 100644 --- a/components/soc/esp32s3/include/soc/i2c_reg.h +++ b/components/soc/esp32s3/register/soc/i2c_reg.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32s3/include/soc/i2c_struct.h b/components/soc/esp32s3/register/soc/i2c_struct.h similarity index 98% rename from components/soc/esp32s3/include/soc/i2c_struct.h rename to components/soc/esp32s3/register/soc/i2c_struct.h index 807ffa508d14..fe3695f44fd5 100644 --- a/components/soc/esp32s3/include/soc/i2c_struct.h +++ b/components/soc/esp32s3/register/soc/i2c_struct.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) CO LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32s3/include/soc/i2s_reg.h b/components/soc/esp32s3/register/soc/i2s_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/i2s_reg.h rename to components/soc/esp32s3/register/soc/i2s_reg.h index 3200bd25bc8a..162938443437 100644 --- a/components/soc/esp32s3/include/soc/i2s_reg.h +++ b/components/soc/esp32s3/register/soc/i2s_reg.h @@ -7,7 +7,7 @@ #define _SOC_I2S_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif @@ -151,7 +151,7 @@ MSB is received first..*/ #define I2S_RX_BIT_ORDER_S 18 /* I2S_RX_WS_IDLE_POL : R/W ;bitpos:[17] ;default: 1'h0 ; */ /*description: 0: WS should be 0 when receiving left channel data, and WS is 1in right channel. - 1: WS should be 1 when receiving left channel data, and WS is 0in right channe + 1: WS should be 1 when receiving left channel data, and WS is 0in right channel l. .*/ #define I2S_RX_WS_IDLE_POL (BIT(17)) #define I2S_RX_WS_IDLE_POL_M (BIT(17)) @@ -330,7 +330,7 @@ his bit will be cleared by hardware after update register done..*/ #define I2S_TX_UPDATE_S 8 /* I2S_TX_BIG_ENDIAN : R/W ;bitpos:[7] ;default: 1'b0 ; */ /*description: I2S Tx byte endian, 1: low addr value to high addr. 0: low addr with low addr v -alue..*/ +value..*/ #define I2S_TX_BIG_ENDIAN (BIT(7)) #define I2S_TX_BIG_ENDIAN_M (BIT(7)) #define I2S_TX_BIG_ENDIAN_V 0x1 @@ -530,7 +530,7 @@ I2S_RX_CLKM_DIV_YN1 is 1. .*/ #define I2S_RX_CLKM_DIV_YN1_V 0x1 #define I2S_RX_CLKM_DIV_YN1_S 27 /* I2S_RX_CLKM_DIV_X : R/W ;bitpos:[26:18] ;default: 9'h0 ; */ -/*description: For b <= a/2, the value of I2S_RX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the valu +/*description: For b <= a/2, the value of I2S_RX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value e of I2S_RX_CLKM_DIV_X is (a/(a-b)) - 1. .*/ #define I2S_RX_CLKM_DIV_X 0x000001FF #define I2S_RX_CLKM_DIV_X_M ((I2S_RX_CLKM_DIV_X_V)<<(I2S_RX_CLKM_DIV_X_S)) @@ -560,7 +560,7 @@ I2S_TX_CLKM_DIV_YN1 is 1. .*/ #define I2S_TX_CLKM_DIV_YN1_V 0x1 #define I2S_TX_CLKM_DIV_YN1_S 27 /* I2S_TX_CLKM_DIV_X : R/W ;bitpos:[26:18] ;default: 9'h0 ; */ -/*description: For b <= a/2, the value of I2S_TX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the valu +/*description: For b <= a/2, the value of I2S_TX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value e of I2S_TX_CLKM_DIV_X is (a/(a-b)) - 1. .*/ #define I2S_TX_CLKM_DIV_X 0x000001FF #define I2S_TX_CLKM_DIV_X_M ((I2S_TX_CLKM_DIV_X_V)<<(I2S_TX_CLKM_DIV_X_S)) @@ -747,56 +747,56 @@ T12_5[2:0]).*/ #define I2S_RX_TDM_CHAN8_EN_V 0x1 #define I2S_RX_TDM_CHAN8_EN_S 8 /* I2S_RX_TDM_PDM_CHAN7_EN : R/W ;bitpos:[7] ;default: 1'h1 ; */ -/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, jus +/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, just t input 0 in this channel..*/ #define I2S_RX_TDM_PDM_CHAN7_EN (BIT(7)) #define I2S_RX_TDM_PDM_CHAN7_EN_M (BIT(7)) #define I2S_RX_TDM_PDM_CHAN7_EN_V 0x1 #define I2S_RX_TDM_PDM_CHAN7_EN_S 7 /* I2S_RX_TDM_PDM_CHAN6_EN : R/W ;bitpos:[6] ;default: 1'h1 ; */ -/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, jus +/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, just t input 0 in this channel..*/ #define I2S_RX_TDM_PDM_CHAN6_EN (BIT(6)) #define I2S_RX_TDM_PDM_CHAN6_EN_M (BIT(6)) #define I2S_RX_TDM_PDM_CHAN6_EN_V 0x1 #define I2S_RX_TDM_PDM_CHAN6_EN_S 6 /* I2S_RX_TDM_PDM_CHAN5_EN : R/W ;bitpos:[5] ;default: 1'h1 ; */ -/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, jus +/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, just t input 0 in this channel..*/ #define I2S_RX_TDM_PDM_CHAN5_EN (BIT(5)) #define I2S_RX_TDM_PDM_CHAN5_EN_M (BIT(5)) #define I2S_RX_TDM_PDM_CHAN5_EN_V 0x1 #define I2S_RX_TDM_PDM_CHAN5_EN_S 5 /* I2S_RX_TDM_PDM_CHAN4_EN : R/W ;bitpos:[4] ;default: 1'h1 ; */ -/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, jus +/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, just t input 0 in this channel..*/ #define I2S_RX_TDM_PDM_CHAN4_EN (BIT(4)) #define I2S_RX_TDM_PDM_CHAN4_EN_M (BIT(4)) #define I2S_RX_TDM_PDM_CHAN4_EN_V 0x1 #define I2S_RX_TDM_PDM_CHAN4_EN_S 4 /* I2S_RX_TDM_PDM_CHAN3_EN : R/W ;bitpos:[3] ;default: 1'h1 ; */ -/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, jus +/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, just t input 0 in this channel..*/ #define I2S_RX_TDM_PDM_CHAN3_EN (BIT(3)) #define I2S_RX_TDM_PDM_CHAN3_EN_M (BIT(3)) #define I2S_RX_TDM_PDM_CHAN3_EN_V 0x1 #define I2S_RX_TDM_PDM_CHAN3_EN_S 3 /* I2S_RX_TDM_PDM_CHAN2_EN : R/W ;bitpos:[2] ;default: 1'h1 ; */ -/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, jus +/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, just t input 0 in this channel..*/ #define I2S_RX_TDM_PDM_CHAN2_EN (BIT(2)) #define I2S_RX_TDM_PDM_CHAN2_EN_M (BIT(2)) #define I2S_RX_TDM_PDM_CHAN2_EN_V 0x1 #define I2S_RX_TDM_PDM_CHAN2_EN_S 2 /* I2S_RX_TDM_PDM_CHAN1_EN : R/W ;bitpos:[1] ;default: 1'h1 ; */ -/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, jus +/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, just t input 0 in this channel..*/ #define I2S_RX_TDM_PDM_CHAN1_EN (BIT(1)) #define I2S_RX_TDM_PDM_CHAN1_EN_M (BIT(1)) #define I2S_RX_TDM_PDM_CHAN1_EN_V 0x1 #define I2S_RX_TDM_PDM_CHAN1_EN_S 1 /* I2S_RX_TDM_PDM_CHAN0_EN : R/W ;bitpos:[0] ;default: 1'h1 ; */ -/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, jus +/*description: 1: Enable the valid data input of I2S RX TDM or PDM channel $n. 0: Disable, just t input 0 in this channel..*/ #define I2S_RX_TDM_PDM_CHAN0_EN (BIT(0)) #define I2S_RX_TDM_PDM_CHAN0_EN_M (BIT(0)) @@ -805,8 +805,8 @@ t input 0 in this channel..*/ #define I2S_TX_TDM_CTRL_REG(i) (REG_I2S_BASE(i) + 0x54) /* I2S_TX_TDM_SKIP_MSK_EN : R/W ;bitpos:[20] ;default: 1'b0 ; */ -/*description: When DMA TX buffer stores the data of (REG_TX_TDM_TOT_CHAN_NUM + 1) channels, a -nd only the data of the enabled channels is sent, then this bit should be set. C +/*description: When DMA TX buffer stores the data of (REG_TX_TDM_TOT_CHAN_NUM + 1) channels, +and only the data of the enabled channels is sent, then this bit should be set. C lear it when all the data stored in DMA TX buffer is for enabled channels..*/ #define I2S_TX_TDM_SKIP_MSK_EN (BIT(20)) #define I2S_TX_TDM_SKIP_MSK_EN_M (BIT(20)) @@ -1041,8 +1041,8 @@ delay by neg edge. 3: not used..*/ #define I2S_LC_FIFO_TIMEOUT_ENA_V 0x1 #define I2S_LC_FIFO_TIMEOUT_ENA_S 11 /* I2S_LC_FIFO_TIMEOUT_SHIFT : R/W ;bitpos:[10:8] ;default: 3'b0 ; */ -/*description: The bits are used to scale tick counter threshold. The tick counter is reset whe -n counter value >= 88000/2^i2s_lc_fifo_timeout_shift.*/ +/*description: The bits are used to scale tick counter threshold. The tick counter is reset +when counter value >= 88000/2^i2s_lc_fifo_timeout_shift.*/ #define I2S_LC_FIFO_TIMEOUT_SHIFT 0x00000007 #define I2S_LC_FIFO_TIMEOUT_SHIFT_M ((I2S_LC_FIFO_TIMEOUT_SHIFT_V)<<(I2S_LC_FIFO_TIMEOUT_SHIFT_S)) #define I2S_LC_FIFO_TIMEOUT_SHIFT_V 0x7 diff --git a/components/soc/esp32s3/include/soc/i2s_struct.h b/components/soc/esp32s3/register/soc/i2s_struct.h similarity index 99% rename from components/soc/esp32s3/include/soc/i2s_struct.h rename to components/soc/esp32s3/register/soc/i2s_struct.h index 2ad9b84d5128..c7500479b10b 100644 --- a/components/soc/esp32s3/include/soc/i2s_struct.h +++ b/components/soc/esp32s3/register/soc/i2s_struct.h @@ -97,7 +97,7 @@ typedef volatile struct i2s_dev_s { uint32_t tx_mono_fst_vld : 1; /*1: The first channel data value is valid in I2S TX mono mode. 0: The second channel data value is valid in I2S TX mono mode.*/ uint32_t tx_pcm_conf : 2; /*I2S TX compress/decompress configuration bit. & 0 (atol): A-Law decompress, 1 (ltoa) : A-Law compress, 2 (utol) : u-Law decompress, 3 (ltou) : u-Law compress. &*/ uint32_t tx_pcm_bypass : 1; /*Set this bit to bypass Compress/Decompress module for transmitted data.*/ - uint32_t tx_stop_en : 1; /*Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy*/ + uint32_t tx_stop_en : 1; /*Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty*/ uint32_t reserved14 : 1; /* Reserved*/ uint32_t tx_left_align : 1; /*1: I2S TX left alignment mode. 0: I2S TX right alignment mode.*/ uint32_t tx_24_fill_en : 1; /*1: Sent 32 bits in 24 channel bits mode. 0: Sent 24 bits in 24 channel bits mode*/ diff --git a/components/soc/esp32s3/include/soc/interrupt_core0_reg.h b/components/soc/esp32s3/register/soc/interrupt_core0_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/interrupt_core0_reg.h rename to components/soc/esp32s3/register/soc/interrupt_core0_reg.h index f686720be442..132bb9f98ed0 100644 --- a/components/soc/esp32s3/include/soc/interrupt_core0_reg.h +++ b/components/soc/esp32s3/register/soc/interrupt_core0_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_INTERRUPT_CORE0_REG_H_ #define _SOC_INTERRUPT_CORE0_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/interrupt_core0_struct.h b/components/soc/esp32s3/register/soc/interrupt_core0_struct.h similarity index 98% rename from components/soc/esp32s3/include/soc/interrupt_core0_struct.h rename to components/soc/esp32s3/register/soc/interrupt_core0_struct.h index aa27462fb00c..4a9094950683 100644 --- a/components/soc/esp32s3/include/soc/interrupt_core0_struct.h +++ b/components/soc/esp32s3/register/soc/interrupt_core0_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_INTERRUPT_CORE0_STRUCT_H_ #define _SOC_INTERRUPT_CORE0_STRUCT_H_ #include diff --git a/components/soc/esp32s3/include/soc/interrupt_core1_reg.h b/components/soc/esp32s3/register/soc/interrupt_core1_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/interrupt_core1_reg.h rename to components/soc/esp32s3/register/soc/interrupt_core1_reg.h index 82d77e2f0d1b..854106dbf528 100644 --- a/components/soc/esp32s3/include/soc/interrupt_core1_reg.h +++ b/components/soc/esp32s3/register/soc/interrupt_core1_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_INTERRUPT_CORE1_REG_H_ #define _SOC_INTERRUPT_CORE1_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/interrupt_core1_struct.h b/components/soc/esp32s3/register/soc/interrupt_core1_struct.h similarity index 98% rename from components/soc/esp32s3/include/soc/interrupt_core1_struct.h rename to components/soc/esp32s3/register/soc/interrupt_core1_struct.h index d4dee29ae508..850cc4dc7772 100644 --- a/components/soc/esp32s3/include/soc/interrupt_core1_struct.h +++ b/components/soc/esp32s3/register/soc/interrupt_core1_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_INTERRUPT_CORE1_STRUCT_H_ #define _SOC_INTERRUPT_CORE1_STRUCT_H_ #include diff --git a/components/soc/esp32s3/include/soc/io_mux_reg.h b/components/soc/esp32s3/register/soc/io_mux_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/io_mux_reg.h rename to components/soc/esp32s3/register/soc/io_mux_reg.h index 3ca2cd04989e..fa72d3630649 100644 --- a/components/soc/esp32s3/include/soc/io_mux_reg.h +++ b/components/soc/esp32s3/register/soc/io_mux_reg.h @@ -5,7 +5,7 @@ */ #pragma once -#include "soc.h" +#include "soc/soc.h" /* The following are the bit fields for PERIPHS_IO_MUX_x_U registers */ /* Output enable in sleep mode */ diff --git a/components/soc/esp32s3/include/soc/lcd_cam_reg.h b/components/soc/esp32s3/register/soc/lcd_cam_reg.h similarity index 100% rename from components/soc/esp32s3/include/soc/lcd_cam_reg.h rename to components/soc/esp32s3/register/soc/lcd_cam_reg.h diff --git a/components/soc/esp32s3/include/soc/lcd_cam_struct.h b/components/soc/esp32s3/register/soc/lcd_cam_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/lcd_cam_struct.h rename to components/soc/esp32s3/register/soc/lcd_cam_struct.h diff --git a/components/soc/esp32s3/include/soc/ledc_reg.h b/components/soc/esp32s3/register/soc/ledc_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/ledc_reg.h rename to components/soc/esp32s3/register/soc/ledc_reg.h index 23f5a5f88999..1a4d70e26357 100644 --- a/components/soc/esp32s3/include/soc/ledc_reg.h +++ b/components/soc/esp32s3/register/soc/ledc_reg.h @@ -1,24 +1,16 @@ -// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define LEDC_LSCH0_CONF0_REG (DR_REG_LEDC_BASE + 0x0000) /* LEDC_OVF_CNT_RESET_ST_LSCH0 : RO ;bitpos:[17] ;default: 1'b0 ; */ diff --git a/components/soc/esp32s3/include/soc/ledc_struct.h b/components/soc/esp32s3/register/soc/ledc_struct.h similarity index 92% rename from components/soc/esp32s3/include/soc/ledc_struct.h rename to components/soc/esp32s3/register/soc/ledc_struct.h index 85cea78e5826..c3e0765a4008 100644 --- a/components/soc/esp32s3/include/soc/ledc_struct.h +++ b/components/soc/esp32s3/register/soc/ledc_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include diff --git a/components/soc/esp32s3/include/soc/mcpwm_reg.h b/components/soc/esp32s3/register/soc/mcpwm_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/mcpwm_reg.h rename to components/soc/esp32s3/register/soc/mcpwm_reg.h index 6a370aa6910e..c8e749dac0cb 100644 --- a/components/soc/esp32s3/include/soc/mcpwm_reg.h +++ b/components/soc/esp32s3/register/soc/mcpwm_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -921,7 +921,7 @@ extern "C" { #define MCPWM_DT0_RED_S 0 /** MCPWM_CARRIER0_CFG_REG register - * PWM generator 0 carrier enable and configuratoin + * PWM generator 0 carrier enable and configuration */ #define MCPWM_CARRIER0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x64) /** MCPWM_CARRIER0_EN : R/W; bitpos: [0]; default: 0; @@ -1625,7 +1625,7 @@ extern "C" { #define MCPWM_DT1_RED_S 0 /** MCPWM_CARRIER1_CFG_REG register - * PWM generator 1 carrier enable and configuratoin + * PWM generator 1 carrier enable and configuration */ #define MCPWM_CARRIER1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x9c) /** MCPWM_CARRIER1_EN : R/W; bitpos: [0]; default: 0; @@ -2328,7 +2328,7 @@ extern "C" { #define MCPWM_DT2_RED_S 0 /** MCPWM_CARRIER2_CFG_REG register - * PWM generator 2 carrier enable and configuratoin + * PWM generator 2 carrier enable and configuration */ #define MCPWM_CARRIER2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd4) /** MCPWM_CARRIER2_EN : R/W; bitpos: [0]; default: 0; @@ -2693,7 +2693,7 @@ extern "C" { #define MCPWM_CAP0_MODE_V 0x00000003U #define MCPWM_CAP0_MODE_S 1 /** MCPWM_CAP0_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + + * Value of prescaling on positive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + * 1 */ #define MCPWM_CAP0_PRESCALE 0x000000FFU @@ -2736,7 +2736,7 @@ extern "C" { #define MCPWM_CAP1_MODE_V 0x00000003U #define MCPWM_CAP1_MODE_S 1 /** MCPWM_CAP1_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + + * Value of prescaling on positive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + * 1 */ #define MCPWM_CAP1_PRESCALE 0x000000FFU @@ -2779,7 +2779,7 @@ extern "C" { #define MCPWM_CAP2_MODE_V 0x00000003U #define MCPWM_CAP2_MODE_S 1 /** MCPWM_CAP2_PRESCALE : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + + * Value of prescaling on positive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + * 1 */ #define MCPWM_CAP2_PRESCALE 0x000000FFU diff --git a/components/soc/esp32s3/include/soc/mcpwm_struct.h b/components/soc/esp32s3/register/soc/mcpwm_struct.h similarity index 99% rename from components/soc/esp32s3/include/soc/mcpwm_struct.h rename to components/soc/esp32s3/register/soc/mcpwm_struct.h index e2f4d32eba9f..9040142e67ee 100644 --- a/components/soc/esp32s3/include/soc/mcpwm_struct.h +++ b/components/soc/esp32s3/register/soc/mcpwm_struct.h @@ -474,7 +474,7 @@ typedef union { } mcpwm_dt_red_cfg_reg_t; /** Type of carrier_cfg register - * PWM generator carrier enable and configuratoin + * PWM generator carrier enable and configuration */ typedef union { struct { @@ -746,7 +746,7 @@ typedef union { */ uint32_t capn_mode: 2; /** capn_prescale : R/W; bitpos: [10:3]; default: 0; - * Value of prescaling on possitive edge of CAPn. Prescale value = PWM_CAPn_PRESCALE + + * Value of prescaling on positive edge of CAPn. Prescale value = PWM_CAPn_PRESCALE + * 1 */ uint32_t capn_prescale: 8; diff --git a/components/soc/esp32s3/include/soc/pcnt_reg.h b/components/soc/esp32s3/register/soc/pcnt_reg.h similarity index 100% rename from components/soc/esp32s3/include/soc/pcnt_reg.h rename to components/soc/esp32s3/register/soc/pcnt_reg.h diff --git a/components/soc/esp32s3/include/soc/pcnt_struct.h b/components/soc/esp32s3/register/soc/pcnt_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/pcnt_struct.h rename to components/soc/esp32s3/register/soc/pcnt_struct.h diff --git a/components/soc/esp32s3/include/soc/peri_backup_reg.h b/components/soc/esp32s3/register/soc/peri_backup_reg.h similarity index 92% rename from components/soc/esp32s3/include/soc/peri_backup_reg.h rename to components/soc/esp32s3/register/soc/peri_backup_reg.h index 71907355b0cc..b627104fc3b2 100644 --- a/components/soc/esp32s3/include/soc/peri_backup_reg.h +++ b/components/soc/esp32s3/register/soc/peri_backup_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_PERI_BACKUP_REG_H_ #define _SOC_PERI_BACKUP_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/peri_backup_struct.h b/components/soc/esp32s3/register/soc/peri_backup_struct.h similarity index 85% rename from components/soc/esp32s3/include/soc/peri_backup_struct.h rename to components/soc/esp32s3/register/soc/peri_backup_struct.h index 20d6673f2ec2..bc0563f71569 100644 --- a/components/soc/esp32s3/include/soc/peri_backup_struct.h +++ b/components/soc/esp32s3/register/soc/peri_backup_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_PERI_BACKUP_STRUCT_H_ #define _SOC_PERI_BACKUP_STRUCT_H_ diff --git a/components/soc/esp32s3/include/soc/reg_base.h b/components/soc/esp32s3/register/soc/reg_base.h similarity index 100% rename from components/soc/esp32s3/include/soc/reg_base.h rename to components/soc/esp32s3/register/soc/reg_base.h diff --git a/components/soc/esp32s3/include/soc/rmt_reg.h b/components/soc/esp32s3/register/soc/rmt_reg.h similarity index 100% rename from components/soc/esp32s3/include/soc/rmt_reg.h rename to components/soc/esp32s3/register/soc/rmt_reg.h diff --git a/components/soc/esp32s3/include/soc/rmt_struct.h b/components/soc/esp32s3/register/soc/rmt_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/rmt_struct.h rename to components/soc/esp32s3/register/soc/rmt_struct.h diff --git a/components/soc/esp32s3/include/soc/rtc_cntl_reg.h b/components/soc/esp32s3/register/soc/rtc_cntl_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/rtc_cntl_reg.h rename to components/soc/esp32s3/register/soc/rtc_cntl_reg.h index 33e0fd40629d..00958eb0dba1 100644 --- a/components/soc/esp32s3/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32s3/register/soc/rtc_cntl_reg.h @@ -8,7 +8,7 @@ #define _SOC_RTC_CNTL_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/rtc_cntl_struct.h b/components/soc/esp32s3/register/soc/rtc_cntl_struct.h similarity index 99% rename from components/soc/esp32s3/include/soc/rtc_cntl_struct.h rename to components/soc/esp32s3/register/soc/rtc_cntl_struct.h index 56e5f2d47e8c..7ef1825ebdf4 100644 --- a/components/soc/esp32s3/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32s3/register/soc/rtc_cntl_struct.h @@ -207,7 +207,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t rtc_xtal32k_dead : 1; /*enable xtal32k_dead interrupt*/ uint32_t rtc_cocpu_trap : 1; /*enable cocpu trap interrupt*/ uint32_t rtc_touch_timeout : 1; /*enable touch timeout interrupt*/ - uint32_t rtc_glitch_det : 1; /*enbale gitch det interrupt*/ + uint32_t rtc_glitch_det : 1; /*enable gitch det interrupt*/ uint32_t rtc_touch_approach_loop_done : 1; uint32_t reserved21 : 11; }; @@ -565,7 +565,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t swd_signal_width : 10; /*adjust signal width send to swd*/ uint32_t swd_rst_flag_clr : 1; /*reset swd reset flag*/ uint32_t swd_feed : 1; /*Sw feed swd*/ - uint32_t swd_disable : 1; /*disabel SWD*/ + uint32_t swd_disable : 1; /*disable SWD*/ uint32_t swd_auto_feed_en : 1; /*automatically feed swd when int comes*/ }; uint32_t val; @@ -689,7 +689,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t xtal32k_clk_factor; union { struct { - uint32_t xtal32k_return_wait : 4; /*cycles to wait to return noral xtal 32k*/ + uint32_t xtal32k_return_wait : 4; /*cycles to wait to return normal xtal 32k*/ uint32_t xtal32k_restart_wait : 16; /*cycles to wait to repower on xtal 32k*/ uint32_t xtal32k_wdt_timeout : 8; /*If no clock detected for this amount of time*/ uint32_t xtal32k_stable_thres : 4; /*if restarted xtal32k period is smaller than this*/ @@ -894,7 +894,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t rtc_xtal32k_dead_w1ts : 1; /*enable xtal32k_dead interrupt*/ uint32_t rtc_cocpu_trap_w1ts : 1; /*enable cocpu trap interrupt*/ uint32_t rtc_touch_timeout_w1ts : 1; /*enable touch timeout interrupt*/ - uint32_t rtc_glitch_det_w1ts : 1; /*enbale gitch det interrupt*/ + uint32_t rtc_glitch_det_w1ts : 1; /*enable gitch det interrupt*/ uint32_t rtc_touch_approach_loop_done_w1ts: 1; uint32_t reserved21 : 11; }; @@ -921,7 +921,7 @@ typedef volatile struct rtc_cntl_dev_s { uint32_t rtc_xtal32k_dead_w1tc : 1; /*enable xtal32k_dead interrupt*/ uint32_t rtc_cocpu_trap_w1tc : 1; /*enable cocpu trap interrupt*/ uint32_t rtc_touch_timeout_w1tc : 1; /*enable touch timeout interrupt*/ - uint32_t rtc_glitch_det_w1tc : 1; /*enbale gitch det interrupt*/ + uint32_t rtc_glitch_det_w1tc : 1; /*enable gitch det interrupt*/ uint32_t rtc_touch_approach_loop_done_w1tc: 1; uint32_t reserved21 : 11; }; diff --git a/components/soc/esp32s3/include/soc/rtc_i2c_reg.h b/components/soc/esp32s3/register/soc/rtc_i2c_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/rtc_i2c_reg.h rename to components/soc/esp32s3/register/soc/rtc_i2c_reg.h index 322f28192e22..ba10ed023300 100644 --- a/components/soc/esp32s3/include/soc/rtc_i2c_reg.h +++ b/components/soc/esp32s3/register/soc/rtc_i2c_reg.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32s3/include/soc/rtc_i2c_struct.h b/components/soc/esp32s3/register/soc/rtc_i2c_struct.h similarity index 96% rename from components/soc/esp32s3/include/soc/rtc_i2c_struct.h rename to components/soc/esp32s3/register/soc/rtc_i2c_struct.h index 2bac2fa5804a..0d42c68906d9 100644 --- a/components/soc/esp32s3/include/soc/rtc_i2c_struct.h +++ b/components/soc/esp32s3/register/soc/rtc_i2c_struct.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32s3/include/soc/rtc_io_reg.h b/components/soc/esp32s3/register/soc/rtc_io_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/rtc_io_reg.h rename to components/soc/esp32s3/register/soc/rtc_io_reg.h index a324329117a9..0ce66dde6136 100644 --- a/components/soc/esp32s3/include/soc/rtc_io_reg.h +++ b/components/soc/esp32s3/register/soc/rtc_io_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_RTC_IO_REG_H_ #define _SOC_RTC_IO_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif @@ -109,8 +101,8 @@ extern "C" { #define RTC_GPIO_PIN0_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN0_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN0_INT_TYPE 0x00000007 #define RTC_GPIO_PIN0_INT_TYPE_M ((RTC_GPIO_PIN0_INT_TYPE_V)<<(RTC_GPIO_PIN0_INT_TYPE_S)) #define RTC_GPIO_PIN0_INT_TYPE_V 0x7 @@ -131,8 +123,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN1_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN1_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN1_INT_TYPE 0x00000007 #define RTC_GPIO_PIN1_INT_TYPE_M ((RTC_GPIO_PIN1_INT_TYPE_V)<<(RTC_GPIO_PIN1_INT_TYPE_S)) #define RTC_GPIO_PIN1_INT_TYPE_V 0x7 @@ -153,8 +145,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN2_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN2_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN2_INT_TYPE 0x00000007 #define RTC_GPIO_PIN2_INT_TYPE_M ((RTC_GPIO_PIN2_INT_TYPE_V)<<(RTC_GPIO_PIN2_INT_TYPE_S)) #define RTC_GPIO_PIN2_INT_TYPE_V 0x7 @@ -175,8 +167,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN3_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN3_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN3_INT_TYPE 0x00000007 #define RTC_GPIO_PIN3_INT_TYPE_M ((RTC_GPIO_PIN3_INT_TYPE_V)<<(RTC_GPIO_PIN3_INT_TYPE_S)) #define RTC_GPIO_PIN3_INT_TYPE_V 0x7 @@ -197,8 +189,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN4_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN4_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN4_INT_TYPE 0x00000007 #define RTC_GPIO_PIN4_INT_TYPE_M ((RTC_GPIO_PIN4_INT_TYPE_V)<<(RTC_GPIO_PIN4_INT_TYPE_S)) #define RTC_GPIO_PIN4_INT_TYPE_V 0x7 @@ -219,8 +211,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN5_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN5_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN5_INT_TYPE 0x00000007 #define RTC_GPIO_PIN5_INT_TYPE_M ((RTC_GPIO_PIN5_INT_TYPE_V)<<(RTC_GPIO_PIN5_INT_TYPE_S)) #define RTC_GPIO_PIN5_INT_TYPE_V 0x7 @@ -241,8 +233,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN6_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN6_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN6_INT_TYPE 0x00000007 #define RTC_GPIO_PIN6_INT_TYPE_M ((RTC_GPIO_PIN6_INT_TYPE_V)<<(RTC_GPIO_PIN6_INT_TYPE_S)) #define RTC_GPIO_PIN6_INT_TYPE_V 0x7 @@ -263,8 +255,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN7_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN7_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN7_INT_TYPE 0x00000007 #define RTC_GPIO_PIN7_INT_TYPE_M ((RTC_GPIO_PIN7_INT_TYPE_V)<<(RTC_GPIO_PIN7_INT_TYPE_S)) #define RTC_GPIO_PIN7_INT_TYPE_V 0x7 @@ -285,8 +277,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN8_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN8_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN8_INT_TYPE 0x00000007 #define RTC_GPIO_PIN8_INT_TYPE_M ((RTC_GPIO_PIN8_INT_TYPE_V)<<(RTC_GPIO_PIN8_INT_TYPE_S)) #define RTC_GPIO_PIN8_INT_TYPE_V 0x7 @@ -307,8 +299,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN9_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN9_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN9_INT_TYPE 0x00000007 #define RTC_GPIO_PIN9_INT_TYPE_M ((RTC_GPIO_PIN9_INT_TYPE_V)<<(RTC_GPIO_PIN9_INT_TYPE_S)) #define RTC_GPIO_PIN9_INT_TYPE_V 0x7 @@ -329,8 +321,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN10_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN10_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN10_INT_TYPE 0x00000007 #define RTC_GPIO_PIN10_INT_TYPE_M ((RTC_GPIO_PIN10_INT_TYPE_V)<<(RTC_GPIO_PIN10_INT_TYPE_S)) #define RTC_GPIO_PIN10_INT_TYPE_V 0x7 @@ -351,8 +343,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN11_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN11_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN11_INT_TYPE 0x00000007 #define RTC_GPIO_PIN11_INT_TYPE_M ((RTC_GPIO_PIN11_INT_TYPE_V)<<(RTC_GPIO_PIN11_INT_TYPE_S)) #define RTC_GPIO_PIN11_INT_TYPE_V 0x7 @@ -373,8 +365,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN12_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN12_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN12_INT_TYPE 0x00000007 #define RTC_GPIO_PIN12_INT_TYPE_M ((RTC_GPIO_PIN12_INT_TYPE_V)<<(RTC_GPIO_PIN12_INT_TYPE_S)) #define RTC_GPIO_PIN12_INT_TYPE_V 0x7 @@ -395,8 +387,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN13_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN13_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN13_INT_TYPE 0x00000007 #define RTC_GPIO_PIN13_INT_TYPE_M ((RTC_GPIO_PIN13_INT_TYPE_V)<<(RTC_GPIO_PIN13_INT_TYPE_S)) #define RTC_GPIO_PIN13_INT_TYPE_V 0x7 @@ -417,8 +409,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN14_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN14_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN14_INT_TYPE 0x00000007 #define RTC_GPIO_PIN14_INT_TYPE_M ((RTC_GPIO_PIN14_INT_TYPE_V)<<(RTC_GPIO_PIN14_INT_TYPE_S)) #define RTC_GPIO_PIN14_INT_TYPE_V 0x7 @@ -439,8 +431,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN15_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN15_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN15_INT_TYPE 0x00000007 #define RTC_GPIO_PIN15_INT_TYPE_M ((RTC_GPIO_PIN15_INT_TYPE_V)<<(RTC_GPIO_PIN15_INT_TYPE_S)) #define RTC_GPIO_PIN15_INT_TYPE_V 0x7 @@ -461,8 +453,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN16_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN16_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN16_INT_TYPE 0x00000007 #define RTC_GPIO_PIN16_INT_TYPE_M ((RTC_GPIO_PIN16_INT_TYPE_V)<<(RTC_GPIO_PIN16_INT_TYPE_S)) #define RTC_GPIO_PIN16_INT_TYPE_V 0x7 @@ -483,8 +475,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN17_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN17_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN17_INT_TYPE 0x00000007 #define RTC_GPIO_PIN17_INT_TYPE_M ((RTC_GPIO_PIN17_INT_TYPE_V)<<(RTC_GPIO_PIN17_INT_TYPE_S)) #define RTC_GPIO_PIN17_INT_TYPE_V 0x7 @@ -505,8 +497,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN18_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN18_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN18_INT_TYPE 0x00000007 #define RTC_GPIO_PIN18_INT_TYPE_M ((RTC_GPIO_PIN18_INT_TYPE_V)<<(RTC_GPIO_PIN18_INT_TYPE_S)) #define RTC_GPIO_PIN18_INT_TYPE_V 0x7 @@ -527,8 +519,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN19_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN19_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN19_INT_TYPE 0x00000007 #define RTC_GPIO_PIN19_INT_TYPE_M ((RTC_GPIO_PIN19_INT_TYPE_V)<<(RTC_GPIO_PIN19_INT_TYPE_S)) #define RTC_GPIO_PIN19_INT_TYPE_V 0x7 @@ -549,8 +541,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN20_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN20_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN20_INT_TYPE 0x00000007 #define RTC_GPIO_PIN20_INT_TYPE_M ((RTC_GPIO_PIN20_INT_TYPE_V)<<(RTC_GPIO_PIN20_INT_TYPE_S)) #define RTC_GPIO_PIN20_INT_TYPE_V 0x7 @@ -571,8 +563,8 @@ l trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN21_WAKEUP_ENABLE_S 10 /* RTC_GPIO_PIN21_INT_TYPE : R/W ;bitpos:[9:7] ;default: 0 ; */ /*description: if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set -to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low leve -l trigger, if set to 5: high level trigger.*/ +to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low +level trigger, if set to 5: high level trigger.*/ #define RTC_GPIO_PIN21_INT_TYPE 0x00000007 #define RTC_GPIO_PIN21_INT_TYPE_M ((RTC_GPIO_PIN21_INT_TYPE_V)<<(RTC_GPIO_PIN21_INT_TYPE_S)) #define RTC_GPIO_PIN21_INT_TYPE_V 0x7 diff --git a/components/soc/esp32s3/include/soc/rtc_io_struct.h b/components/soc/esp32s3/register/soc/rtc_io_struct.h similarity index 95% rename from components/soc/esp32s3/include/soc/rtc_io_struct.h rename to components/soc/esp32s3/register/soc/rtc_io_struct.h index 1154be038b3a..d91204e18da2 100644 --- a/components/soc/esp32s3/include/soc/rtc_io_struct.h +++ b/components/soc/esp32s3/register/soc/rtc_io_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_RTC_IO_STRUCT_H_ #define _SOC_RTC_IO_STRUCT_H_ diff --git a/components/soc/esp32s3/include/soc/sdmmc_reg.h b/components/soc/esp32s3/register/soc/sdmmc_reg.h similarity index 85% rename from components/soc/esp32s3/include/soc/sdmmc_reg.h rename to components/soc/esp32s3/register/soc/sdmmc_reg.h index 41c191eb68ff..4d0a141781d0 100644 --- a/components/soc/esp32s3/include/soc/sdmmc_reg.h +++ b/components/soc/esp32s3/register/soc/sdmmc_reg.h @@ -1,19 +1,11 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once -#include "soc.h" +#include "soc/soc.h" #define SDMMC_CTRL_REG (DR_REG_SDMMC_BASE + 0x00) #define SDMMC_PWREN_REG (DR_REG_SDMMC_BASE + 0x04) diff --git a/components/soc/esp32s3/include/soc/sdmmc_struct.h b/components/soc/esp32s3/register/soc/sdmmc_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/sdmmc_struct.h rename to components/soc/esp32s3/register/soc/sdmmc_struct.h diff --git a/components/soc/esp32s3/include/soc/sens_reg.h b/components/soc/esp32s3/register/soc/sens_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/sens_reg.h rename to components/soc/esp32s3/register/soc/sens_reg.h index ca14d862dc92..350804cf20ef 100644 --- a/components/soc/esp32s3/include/soc/sens_reg.h +++ b/components/soc/esp32s3/register/soc/sens_reg.h @@ -7,7 +7,7 @@ #define _SOC_SENS_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/sens_struct.h b/components/soc/esp32s3/register/soc/sens_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/sens_struct.h rename to components/soc/esp32s3/register/soc/sens_struct.h diff --git a/components/soc/esp32s3/include/soc/sensitive_reg.h b/components/soc/esp32s3/register/soc/sensitive_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/sensitive_reg.h rename to components/soc/esp32s3/register/soc/sensitive_reg.h index a3393c5c0561..3c17e73cce0c 100644 --- a/components/soc/esp32s3/include/soc/sensitive_reg.h +++ b/components/soc/esp32s3/register/soc/sensitive_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SENSITIVE_REG_H_ #define _SOC_SENSITIVE_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/sensitive_struct.h b/components/soc/esp32s3/register/soc/sensitive_struct.h similarity index 99% rename from components/soc/esp32s3/include/soc/sensitive_struct.h rename to components/soc/esp32s3/register/soc/sensitive_struct.h index e9919cb0a69b..c6102c055b56 100644 --- a/components/soc/esp32s3/include/soc/sensitive_struct.h +++ b/components/soc/esp32s3/register/soc/sensitive_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SENSITIVE_STRUCT_H_ #define _SOC_SENSITIVE_STRUCT_H_ diff --git a/components/soc/esp32s3/include/soc/spi_mem_reg.h b/components/soc/esp32s3/register/soc/spi_mem_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/spi_mem_reg.h rename to components/soc/esp32s3/register/soc/spi_mem_reg.h index aa4639ed8d80..16a8ec5f9c5d 100644 --- a/components/soc/esp32s3/include/soc/spi_mem_reg.h +++ b/components/soc/esp32s3/register/soc/spi_mem_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SPI_MEM_REG_H_ #define _SOC_SPI_MEM_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif @@ -209,14 +201,14 @@ QUAD or SPI_MEM_FREAD_DUAL is set..*/ #define SPI_MEM_FASTRD_MODE_V 0x1 #define SPI_MEM_FASTRD_MODE_S 13 /* SPI_MEM_TX_CRC_EN : R/W ;bitpos:[11] ;default: 1'b0 ; */ -/*description: For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disabl +/*description: For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disable e.*/ #define SPI_MEM_TX_CRC_EN (BIT(11)) #define SPI_MEM_TX_CRC_EN_M (BIT(11)) #define SPI_MEM_TX_CRC_EN_V 0x1 #define SPI_MEM_TX_CRC_EN_S 11 /* SPI_MEM_FCS_CRC_EN : R/W ;bitpos:[10] ;default: 1'b0 ; */ -/*description: For SPI1, initialize crc32 module before writing encrypted data to flash. Activ +/*description: For SPI1, initialize crc32 module before writing encrypted data to flash. Active e low..*/ #define SPI_MEM_FCS_CRC_EN (BIT(10)) #define SPI_MEM_FCS_CRC_EN_M (BIT(10)) @@ -826,8 +818,8 @@ tive 1: SPI_CLK is delayed one cycle after CS inactive 2: SPI_CLK is delayed two #define SPI_MEM_SRAM_DRD_CMD_REG(i) (REG_SPI_MEM_BASE(i) + 0x48) /* SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN : R/W ;bitpos:[31:28] ;default: 4'h0 ; */ -/*description: When SPI0 reads Ext_RAM, it is the length in bits of CMD phase. The register val -ue shall be (bit_num-1)..*/ +/*description: When SPI0 reads Ext_RAM, it is the length in bits of CMD phase. The register +value shall be (bit_num-1)..*/ #define SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN 0x0000000F #define SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_M ((SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_V)<<(SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_S)) #define SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_V 0xF @@ -1072,8 +1064,8 @@ ES command is sent..*/ #define SPI_MEM_FLASH_PER_WAIT_EN_V 0x1 #define SPI_MEM_FLASH_PER_WAIT_EN_S 2 /* SPI_MEM_FLASH_PES : R/W/SS/SC ;bitpos:[1] ;default: 1'b0 ; */ -/*description: program erase suspend bit, program erase suspend operation will be triggered whe -n the bit is set. The bit will be cleared once the operation done.1: enable 0: d +/*description: program erase suspend bit, program erase suspend operation will be triggered +when the bit is set. The bit will be cleared once the operation done.1: enable 0: d isable. .*/ #define SPI_MEM_FLASH_PES (BIT(1)) #define SPI_MEM_FLASH_PES_M (BIT(1)) @@ -1166,7 +1158,7 @@ PI_MEM_TIMING_CALI bit is set..*/ #define SPI_MEM_EXTRA_DUMMY_CYCLELEN_V 0x7 #define SPI_MEM_EXTRA_DUMMY_CYCLELEN_S 2 /* SPI_MEM_TIMING_CALI : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: Set this bit to add extra SPI_CLK cycles in DUMMY phase for all reading operatio +/*description: Set this bit to add extra SPI_CLK cycles in DUMMY phase for all reading operation ns..*/ #define SPI_MEM_TIMING_CALI (BIT(1)) #define SPI_MEM_TIMING_CALI_M (BIT(1)) @@ -1174,7 +1166,7 @@ ns..*/ #define SPI_MEM_TIMING_CALI_S 1 /* SPI_MEM_TIMING_CLK_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ /*description: Set this bit to power on HCLK. When PLL is powered on, the frequency of HCLK equ -als to that of PLL. Otherwise, the frequency equals to that of XTAL..*/ +also to that of PLL. Otherwise, the frequency equals to that of XTAL..*/ #define SPI_MEM_TIMING_CLK_ENA (BIT(0)) #define SPI_MEM_TIMING_CLK_ENA_M (BIT(0)) #define SPI_MEM_TIMING_CLK_ENA_V 0x1 @@ -1245,8 +1237,8 @@ cles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge..*/ /*description: SPI_HD input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN$n_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN$n_NUM+1) cycles at HCL K positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_ -MEM_DIN$n_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK neg -ative edge. 4: Delay for (SPI_MEM_DIN$n_NUM+1) cycles at HCLK negative edge and +MEM_DIN$n_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK +nagetive edge. 4: Delay for (SPI_MEM_DIN$n_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN$n_NUM+1) cyc les at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge..*/ #define SPI_MEM_DIN3_MODE 0x00000007 @@ -1257,8 +1249,8 @@ les at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge..*/ /*description: SPI_WP input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN$n_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN$n_NUM+1) cycles at HCL K positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_ -MEM_DIN$n_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK neg -ative edge. 4: Delay for (SPI_MEM_DIN$n_NUM+1) cycles at HCLK negative edge and +MEM_DIN$n_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK +nagetive edge. 4: Delay for (SPI_MEM_DIN$n_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN$n_NUM+1) cyc les at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge..*/ #define SPI_MEM_DIN2_MODE 0x00000007 @@ -1420,7 +1412,7 @@ esses to Ext_RAM. Active when SPI_SMEM_TIMING_CALI bit is set..*/ #define SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V 0x7 #define SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S 2 /* SPI_MEM_SPI_SMEM_TIMING_CALI : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: Set this bit to add extra SPI_CLK cycles in DUMMY phase for all reading operatio +/*description: Set this bit to add extra SPI_CLK cycles in DUMMY phase for all reading operation ns..*/ #define SPI_MEM_SPI_SMEM_TIMING_CALI (BIT(1)) #define SPI_MEM_SPI_SMEM_TIMING_CALI_M (BIT(1)) @@ -1428,7 +1420,7 @@ ns..*/ #define SPI_MEM_SPI_SMEM_TIMING_CALI_S 1 /* SPI_MEM_SPI_SMEM_TIMING_CLK_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ /*description: Set this bit to power on HCLK. When PLL is powered on, the frequency of HCLK equ -als to that of PLL. Otherwise, the frequency equals to that of XTAL..*/ +also to that of PLL. Otherwise, the frequency equals to that of XTAL..*/ #define SPI_MEM_SPI_SMEM_TIMING_CLK_ENA (BIT(0)) #define SPI_MEM_SPI_SMEM_TIMING_CLK_ENA_M (BIT(0)) #define SPI_MEM_SPI_SMEM_TIMING_CLK_ENA_V 0x1 @@ -1524,8 +1516,8 @@ and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN$n_NUM+1 at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN$n_NUM+1) cycles at HC LK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI _SMEM_DIN$n_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK n -egative edge. 4: Delay for (SPI_SMEM_DIN$n_NUM+1) cycles at HCLK negative edge a -nd one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN$n_NUM+1) +egative edge. 4: Delay for (SPI_SMEM_DIN$n_NUM+1) cycles at HCLK negative edge +and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN$n_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge..*/ #define SPI_MEM_SPI_SMEM_DIN1_MODE 0x00000007 #define SPI_MEM_SPI_SMEM_DIN1_MODE_M ((SPI_MEM_SPI_SMEM_DIN1_MODE_V)<<(SPI_MEM_SPI_SMEM_DIN1_MODE_S)) @@ -1536,8 +1528,8 @@ nd one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN$n_NUM+1) at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN$n_NUM+1) cycles at HC LK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI _SMEM_DIN$n_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK n -egative edge. 4: Delay for (SPI_SMEM_DIN$n_NUM+1) cycles at HCLK negative edge a -nd one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN$n_NUM+1) +egative edge. 4: Delay for (SPI_SMEM_DIN$n_NUM+1) cycles at HCLK negative edge +and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN$n_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge..*/ #define SPI_MEM_SPI_SMEM_DIN0_MODE 0x00000007 #define SPI_MEM_SPI_SMEM_DIN0_MODE_M ((SPI_MEM_SPI_SMEM_DIN0_MODE_V)<<(SPI_MEM_SPI_SMEM_DIN0_MODE_S)) @@ -1708,8 +1700,8 @@ INT_CLR bit..*/ #define SPI_MEM_ECC_BYTE_ERR_V 0x1 #define SPI_MEM_ECC_BYTE_ERR_S 16 /* SPI_MEM_ECC_CHK_ERR_BIT : R/SS/WTC ;bitpos:[15:13] ;default: 3'd0 ; */ -/*description: When SPI_MEM_ECC_BYTE_ERR is set, these bits show the error bit number of ECC by -te..*/ +/*description: When SPI_MEM_ECC_BYTE_ERR is set, these bits show the error bit number of ECC +byte..*/ #define SPI_MEM_ECC_CHK_ERR_BIT 0x00000007 #define SPI_MEM_ECC_CHK_ERR_BIT_M ((SPI_MEM_ECC_CHK_ERR_BIT_V)<<(SPI_MEM_ECC_CHK_ERR_BIT_S)) #define SPI_MEM_ECC_CHK_ERR_BIT_V 0x7 @@ -2126,7 +2118,7 @@ or times of SPI0/1 ECC read flash are equal or bigger than APB_CTRL_ECC_ERR_INT_ NUM. When APB_CTRL_FECC_ERR_INT_EN is cleared and APB_CTRL_SECC_ERR_INT_EN is s et, this bit is triggered when the error times of SPI0/1 ECC read external RAM a re equal or bigger than APB_CTRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN -and APB_CTRL_SECC_ERR_INT_EN are set, this bit is triggered when the total erro +and APB_CTRL_SECC_ERR_INT_EN are set, this bit is triggered when the total error r times of SPI0/1 ECC read external RAM and flash are equal or bigger than APB_C TRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN and APB_CTRL_SECC_ERR_INT_EN are cleared, this bit will not be triggered..*/ @@ -2136,7 +2128,7 @@ TRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN and APB_CTRL_SECC_ERR_INT_EN #define SPI_MEM_ECC_ERR_INT_RAW_S 4 /* SPI_MEM_BROWN_OUT_INT_RAW : R/WTC/SS ;bitpos:[3] ;default: 1'b0 ; */ /*description: The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that -chip is loosing power and RTC module sends out brown out close flash request to +chip is losing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others..*/ #define SPI_MEM_BROWN_OUT_INT_RAW (BIT(3)) diff --git a/components/soc/esp32s3/include/soc/spi_mem_struct.h b/components/soc/esp32s3/register/soc/spi_mem_struct.h similarity index 98% rename from components/soc/esp32s3/include/soc/spi_mem_struct.h rename to components/soc/esp32s3/register/soc/spi_mem_struct.h index aa6f388653c4..07d352bb184c 100644 --- a/components/soc/esp32s3/include/soc/spi_mem_struct.h +++ b/components/soc/esp32s3/register/soc/spi_mem_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SPI_MEM_STRUCT_H_ #define _SOC_SPI_MEM_STRUCT_H_ @@ -551,7 +543,7 @@ typedef volatile struct spi_mem_dev_s { uint32_t per_end_int_raw : 1; /*The raw bit for SPI_MEM_PER_END_INT interrupt. 1: Triggered when Auto Resume command (0x7A) is sent and flash is resumed successfully. 0: Others.*/ uint32_t pes_end_int_raw : 1; /*The raw bit for SPI_MEM_PES_END_INT interrupt.1: Triggered when Auto Suspend command (0x75) is sent and flash is suspended successfully. 0: Others.*/ uint32_t total_trans_end_int_raw : 1; /*The raw bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. 1: Triggered when SPI1 transfer is done and flash is already idle. When WRSR/PP/SE/BE/CE is sent and PES/PER command is sent, this bit is set when WRSR/PP/SE/BE/CE is success. 0: Others.*/ - uint32_t brown_out_int_raw : 1; /*The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is loosing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others.*/ + uint32_t brown_out_int_raw : 1; /*The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is losing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others.*/ uint32_t ecc_err_int_raw : 1; /*The raw bit for SPI_MEM_ECC_ERR_INT interrupt. When APB_CTRL_FECC_ERR_INT_EN is set and APB_CTRL_SECC_ERR_INT_EN is cleared, this bit is triggered when the error times of SPI0/1 ECC read flash are equal or bigger than APB_CTRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN is cleared and APB_CTRL_SECC_ERR_INT_EN is set, this bit is triggered when the error times of SPI0/1 ECC read external RAM are equal or bigger than APB_CTRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN and APB_CTRL_SECC_ERR_INT_EN are set, this bit is triggered when the total error times of SPI0/1 ECC read external RAM and flash are equal or bigger than APB_CTRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN and APB_CTRL_SECC_ERR_INT_EN are cleared, this bit will not be triggered.*/ uint32_t reserved5 : 27; /*reserved*/ }; diff --git a/components/soc/esp32s3/include/soc/spi_reg.h b/components/soc/esp32s3/register/soc/spi_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/spi_reg.h rename to components/soc/esp32s3/register/soc/spi_reg.h index 533158870aef..a58705471249 100644 --- a/components/soc/esp32s3/include/soc/spi_reg.h +++ b/components/soc/esp32s3/register/soc/spi_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SPI_REG_H_ #define _SOC_SPI_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif @@ -167,7 +159,7 @@ e, the FSPI bus signals are output. Can be configured in CONF state..*/ #define SPI_CLOCK_REG(i) (REG_SPI_BASE(i) + 0xC) /* SPI_CLK_EQU_SYSCLK : R/W ;bitpos:[31] ;default: 1'b1 ; */ -/*description: In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from syst +/*description: In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from syst em clock. Can be configured in CONF state..*/ #define SPI_CLK_EQU_SYSCLK (BIT(31)) #define SPI_CLK_EQU_SYSCLK_M (BIT(31)) @@ -204,15 +196,15 @@ e 0. Can be configured in CONF state..*/ #define SPI_USER_REG(i) (REG_SPI_BASE(i) + 0x10) /* SPI_USR_COMMAND : R/W ;bitpos:[31] ;default: 1'b1 ; */ -/*description: This bit enable the command phase of an operation. Can be configured in CONF sta -te..*/ +/*description: This bit enable the command phase of an operation. Can be configured in CONF +state..*/ #define SPI_USR_COMMAND (BIT(31)) #define SPI_USR_COMMAND_M (BIT(31)) #define SPI_USR_COMMAND_V 0x1 #define SPI_USR_COMMAND_S 31 /* SPI_USR_ADDR : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: This bit enable the address phase of an operation. Can be configured in CONF sta -te..*/ +/*description: This bit enable the address phase of an operation. Can be configured in CONF +state..*/ #define SPI_USR_ADDR (BIT(30)) #define SPI_USR_ADDR_M (BIT(30)) #define SPI_USR_ADDR_V 0x1 @@ -400,7 +392,7 @@ n be configured in CONF state..*/ #define SPI_USR_COMMAND_BITLEN_S 28 /* SPI_MST_REMPTY_ERR_END_EN : R/W ;bitpos:[27] ;default: 1'b1 ; */ /*description: 1: SPI transfer is ended when SPI TX AFIFO read empty error is valid in GP-SPI m -aster FD/HD-mode. 0: SPI transfer is not ended when SPI TX AFIFO read empty erro +aster FD/HD-mode. 0: SPI transfer is not ended when SPI TX AFIFO read empty error r is valid in GP-SPI master FD/HD-mode..*/ #define SPI_MST_REMPTY_ERR_END_EN (BIT(27)) #define SPI_MST_REMPTY_ERR_END_EN_M (BIT(27)) @@ -1121,7 +1113,7 @@ AFIFO read-empty error when SPI outputs data in master mode. 0: Others..*/ #define SPI_SLV_CMD_ERR_INT_RAW_V 0x1 #define SPI_SLV_CMD_ERR_INT_RAW_S 16 /* SPI_SLV_BUF_ADDR_ERR_INT_RAW : R/WTC/SS ;bitpos:[15] ;default: 1'b0 ; */ -/*description: The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data addres +/*description: The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data address s of the current SPI slave mode CPU controlled FD, Wr_BUF or Rd_BUF transmission is bigger than 63. 0: Others..*/ #define SPI_SLV_BUF_ADDR_ERR_INT_RAW (BIT(15)) @@ -1692,7 +1684,7 @@ dge 0: output data at tsck posedge .*/ /* SPI_CLK_MODE : R/W ;bitpos:[1:0] ;default: 2'b0 ; */ /*description: SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delaye d one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inacti -ve 3: SPI clock is alwasy on. Can be configured in CONF state..*/ +ve 3: SPI clock is always on. Can be configured in CONF state..*/ #define SPI_CLK_MODE 0x00000003 #define SPI_CLK_MODE_M ((SPI_CLK_MODE_V)<<(SPI_CLK_MODE_S)) #define SPI_CLK_MODE_V 0x3 diff --git a/components/soc/esp32s3/include/soc/spi_struct.h b/components/soc/esp32s3/register/soc/spi_struct.h similarity index 98% rename from components/soc/esp32s3/include/soc/spi_struct.h rename to components/soc/esp32s3/register/soc/spi_struct.h index 2a3abd257c17..e9d62932e2b5 100644 --- a/components/soc/esp32s3/include/soc/spi_struct.h +++ b/components/soc/esp32s3/register/soc/spi_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SPI_STRUCT_H_ #define _SOC_SPI_STRUCT_H_ @@ -66,7 +58,7 @@ typedef volatile struct spi_dev_s { uint32_t clkcnt_n : 6; /*In the master mode it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1). Can be configured in CONF state.*/ uint32_t clkdiv_pre : 4; /*In the master mode it is pre-divider of spi_clk. Can be configured in CONF state.*/ uint32_t reserved22 : 9; /*reserved*/ - uint32_t clk_equ_sysclk : 1; /*In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system clock. Can be configured in CONF state.*/ + uint32_t clk_equ_sysclk : 1; /*In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system clock. Can be configured in CONF state.*/ }; uint32_t val; } clock; @@ -374,7 +366,7 @@ typedef volatile struct spi_dev_s { uint32_t reserved_dc; union { struct { - uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on. Can be configured in CONF state.*/ + uint32_t clk_mode : 2; /*SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is always on. Can be configured in CONF state.*/ uint32_t clk_mode_13 : 1; /*{CPOL, CPHA},1: support spi clk mode 1 and 3, first edge output data B[0]/B[7]. 0: support spi clk mode 0 and 2, first edge output data B[1]/B[6].*/ uint32_t rsck_data_out : 1; /*It saves half a cycle when tsck is the same as rsck. 1: output data at rsck posedge 0: output data at tsck posedge */ uint32_t reserved4 : 4; /*reserved*/ diff --git a/components/soc/esp32s3/include/soc/syscon_reg.h b/components/soc/esp32s3/register/soc/syscon_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/syscon_reg.h rename to components/soc/esp32s3/register/soc/syscon_reg.h index e22f18c92ee5..75a58fcdb521 100644 --- a/components/soc/esp32s3/include/soc/syscon_reg.h +++ b/components/soc/esp32s3/register/soc/syscon_reg.h @@ -7,7 +7,7 @@ #define _SOC_SYSCON_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif @@ -210,7 +210,7 @@ extern "C" { #define SYSTEM_MACPWR_RST BIT(8) #define SYSTEM_RW_BTMAC_RST BIT(9) /* Bluetooth MAC */ #define SYSTEM_RW_BTLP_RST BIT(10) /* Bluetooth Low Power Module */ -#define SYSTEM_RW_BTMAC_REG_RST BIT(11) /* Bluetooth MAC Regsiters */ +#define SYSTEM_RW_BTMAC_REG_RST BIT(11) /* Bluetooth MAC Registers */ #define SYSTEM_RW_BTLP_REG_RST BIT(12) /* Bluetooth Low Power Registers */ #define SYSTEM_BTBB_REG_RST BIT(13) /* Bluetooth Baseband Registers */ diff --git a/components/soc/esp32s3/include/soc/syscon_struct.h b/components/soc/esp32s3/register/soc/syscon_struct.h similarity index 96% rename from components/soc/esp32s3/include/soc/syscon_struct.h rename to components/soc/esp32s3/register/soc/syscon_struct.h index a392939e4226..e01c71534973 100644 --- a/components/soc/esp32s3/include/soc/syscon_struct.h +++ b/components/soc/esp32s3/register/soc/syscon_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SYSCON_STRUCT_H_ #define _SOC_SYSCON_STRUCT_H_ diff --git a/components/soc/esp32s3/include/soc/system_reg.h b/components/soc/esp32s3/register/soc/system_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/system_reg.h rename to components/soc/esp32s3/register/soc/system_reg.h index 49a02b007eb0..736e90a84a45 100644 --- a/components/soc/esp32s3/include/soc/system_reg.h +++ b/components/soc/esp32s3/register/soc/system_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SYSTEM_REG_H_ #define _SOC_SYSTEM_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/system_struct.h b/components/soc/esp32s3/register/soc/system_struct.h similarity index 98% rename from components/soc/esp32s3/include/soc/system_struct.h rename to components/soc/esp32s3/register/soc/system_struct.h index 6c4ce1f11824..b0e5f2a712e3 100644 --- a/components/soc/esp32s3/include/soc/system_struct.h +++ b/components/soc/esp32s3/register/soc/system_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SYSTEM_STRUCT_H_ #define _SOC_SYSTEM_STRUCT_H_ diff --git a/components/soc/esp32s3/include/soc/systimer_reg.h b/components/soc/esp32s3/register/soc/systimer_reg.h similarity index 97% rename from components/soc/esp32s3/include/soc/systimer_reg.h rename to components/soc/esp32s3/register/soc/systimer_reg.h index 869012065b04..45873735b429 100644 --- a/components/soc/esp32s3/include/soc/systimer_reg.h +++ b/components/soc/esp32s3/register/soc/systimer_reg.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32s3/include/soc/systimer_struct.h b/components/soc/esp32s3/register/soc/systimer_struct.h similarity index 94% rename from components/soc/esp32s3/include/soc/systimer_struct.h rename to components/soc/esp32s3/register/soc/systimer_struct.h index a28ef359f167..4216561c3c28 100644 --- a/components/soc/esp32s3/include/soc/systimer_struct.h +++ b/components/soc/esp32s3/register/soc/systimer_struct.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32s3/include/soc/timer_group_reg.h b/components/soc/esp32s3/register/soc/timer_group_reg.h similarity index 97% rename from components/soc/esp32s3/include/soc/timer_group_reg.h rename to components/soc/esp32s3/register/soc/timer_group_reg.h index 7252d2506735..e712afc168f0 100644 --- a/components/soc/esp32s3/include/soc/timer_group_reg.h +++ b/components/soc/esp32s3/register/soc/timer_group_reg.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32s3/include/soc/timer_group_struct.h b/components/soc/esp32s3/register/soc/timer_group_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/timer_group_struct.h rename to components/soc/esp32s3/register/soc/timer_group_struct.h diff --git a/components/soc/esp32s3/include/soc/twai_struct.h b/components/soc/esp32s3/register/soc/twai_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/twai_struct.h rename to components/soc/esp32s3/register/soc/twai_struct.h diff --git a/components/soc/esp32s3/include/soc/uart_reg.h b/components/soc/esp32s3/register/soc/uart_reg.h similarity index 98% rename from components/soc/esp32s3/include/soc/uart_reg.h rename to components/soc/esp32s3/register/soc/uart_reg.h index 73c2d80b9d8b..ecae7cb64629 100644 --- a/components/soc/esp32s3/include/soc/uart_reg.h +++ b/components/soc/esp32s3/register/soc/uart_reg.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once @@ -109,7 +100,7 @@ extern "C" { #define UART_RXFIFO_TOUT_INT_RAW_V 0x00000001U #define UART_RXFIFO_TOUT_INT_RAW_S 8 /** UART_SW_XON_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ #define UART_SW_XON_INT_RAW (BIT(9)) @@ -294,7 +285,7 @@ extern "C" { #define UART_TX_BRK_DONE_INT_ST_V 0x00000001U #define UART_TX_BRK_DONE_INT_ST_S 12 /** UART_TX_BRK_IDLE_DONE_INT_ST : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ #define UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) @@ -785,7 +776,7 @@ extern "C" { #define UART_SW_DTR_V 0x00000001U #define UART_SW_DTR_S 7 /** UART_TXD_BRK : R/W; bitpos: [8]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ #define UART_TXD_BRK (BIT(8)) @@ -978,7 +969,7 @@ extern "C" { #define UART_RX_FLOW_EN_V 0x00000001U #define UART_RX_FLOW_EN_S 22 /** UART_RX_TOUT_EN : R/W; bitpos: [23]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ #define UART_RX_TOUT_EN (BIT(23)) #define UART_RX_TOUT_EN_M (UART_RX_TOUT_EN_V << UART_RX_TOUT_EN_S) @@ -1003,7 +994,7 @@ extern "C" { */ #define UART_HIGHPULSE_REG(i) (REG_UART_BASE(i) + 0x2c) /** UART_HIGHPULSE_MIN_CNT : RO; bitpos: [11:0]; default: 4095; - * This register stores the value of the maxinum duration time for the high level + * This register stores the value of the maximum duration time for the high level * pulse. It is used in baud rate-detect process. */ #define UART_HIGHPULSE_MIN_CNT 0x00000FFFU diff --git a/components/soc/esp32s3/include/soc/uart_struct.h b/components/soc/esp32s3/register/soc/uart_struct.h similarity index 97% rename from components/soc/esp32s3/include/soc/uart_struct.h rename to components/soc/esp32s3/register/soc/uart_struct.h index 23d6d15450e1..a5e7dc12e00b 100644 --- a/components/soc/esp32s3/include/soc/uart_struct.h +++ b/components/soc/esp32s3/register/soc/uart_struct.h @@ -1,16 +1,7 @@ -/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once @@ -129,7 +120,7 @@ typedef union { */ uint32_t rxfifo_tout_int_raw:1; /** sw_xon_int_raw : R/WTC/SS; bitpos: [9]; default: 0; - * This interrupt raw bit turns to high level when receiver recevies Xon char when + * This interrupt raw bit turns to high level when receiver receives Xon char when * uart_sw_flow_con_en is set to 1. */ uint32_t sw_xon_int_raw:1; @@ -247,7 +238,7 @@ typedef union { */ uint32_t tx_brk_done_int_st:1; /** tx_brk_idle_done_int_st : RO; bitpos: [13]; default: 0; - * This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena + * This is the status bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena * is set to 1. */ uint32_t tx_brk_idle_done_int_st:1; @@ -534,7 +525,7 @@ typedef union { */ uint32_t sw_dtr:1; /** txd_brk : R/W; bitpos: [8]; default: 0; - * Set this bit to enbale transmitter to send NULL when the process of sending data + * Set this bit to enable transmitter to send NULL when the process of sending data * is done. */ uint32_t txd_brk:1; @@ -654,7 +645,7 @@ typedef union { */ uint32_t rx_flow_en:1; /** rx_tout_en : R/W; bitpos: [23]; default: 0; - * This is the enble bit for uart receiver's timeout function. + * This is the enable bit for uart receiver's timeout function. */ uint32_t rx_tout_en:1; uint32_t reserved_24:8; @@ -1001,7 +992,7 @@ typedef union { typedef union { struct { /** highpulse_min_cnt : RO; bitpos: [11:0]; default: 4095; - * This register stores the value of the maxinum duration time for the high level + * This register stores the value of the maximum duration time for the high level * pulse. It is used in baud rate-detect process. */ uint32_t highpulse_min_cnt:12; diff --git a/components/soc/esp32s3/include/soc/uhci_reg.h b/components/soc/esp32s3/register/soc/uhci_reg.h similarity index 97% rename from components/soc/esp32s3/include/soc/uhci_reg.h rename to components/soc/esp32s3/register/soc/uhci_reg.h index 280bafd55c71..19fefc9f35ea 100644 --- a/components/soc/esp32s3/include/soc/uhci_reg.h +++ b/components/soc/esp32s3/register/soc/uhci_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_UHCI_REG_H_ #define _SOC_UHCI_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/uhci_struct.h b/components/soc/esp32s3/register/soc/uhci_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/uhci_struct.h rename to components/soc/esp32s3/register/soc/uhci_struct.h diff --git a/components/soc/esp32s3/include/soc/usb_reg.h b/components/soc/esp32s3/register/soc/usb_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/usb_reg.h rename to components/soc/esp32s3/register/soc/usb_reg.h index 90bc61d71ac6..d98ebf419b65 100644 --- a/components/soc/esp32s3/include/soc/usb_reg.h +++ b/components/soc/esp32s3/register/soc/usb_reg.h @@ -8,7 +8,7 @@ #include #include "soc/soc.h" -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif @@ -608,7 +608,7 @@ extern "C" { #define USB_H_LSPDDEV0_V 0x00000001 #define USB_H_LSPDDEV0_S 17 /** USB_H_EPTYPE0 : R/W; bitpos: [20:18]; default: 0; - * 0x0 (CTRL): Contro + * 0x0 (CTRL): Control * 0x1 (ISOC): Isochronous * 0x2 (BULK): Bulk * 0x3 (INTERR): Interrupt @@ -647,7 +647,7 @@ extern "C" { #define USB_H_ODDFRM0_S 29 /** USB_H_CHDIS0 : R/W; bitpos: [30]; default: 0; * Channel Disable - * 0x0 : Transmit/Recieve norma + * 0x0 : Transmit/Receive norma * 0x1 : Stop transmitting/receiving data on channel */ #define USB_H_CHDIS0 (BIT(30)) @@ -720,7 +720,7 @@ extern "C" { #define USB_H_LSPDDEV1_V 0x00000001 #define USB_H_LSPDDEV1_S 17 /** USB_H_EPTYPE1 : R/W; bitpos: [20:18]; default: 0; - * 0x0 (CTRL): Contro + * 0x0 (CTRL): Control * 0x1 (ISOC): Isochronous * 0x2 (BULK): Bulk * 0x3 (INTERR): Interrupt @@ -759,7 +759,7 @@ extern "C" { #define USB_H_ODDFRM1_S 29 /** USB_H_CHDIS1 : R/W; bitpos: [30]; default: 0; * Channel Disable - * 0x0 : Transmit/Recieve norma + * 0x0 : Transmit/Receive norma * 0x1 : Stop transmitting/receiving data on channel */ #define USB_H_CHDIS1 (BIT(30)) @@ -832,7 +832,7 @@ extern "C" { #define USB_H_LSPDDEV2_V 0x00000001 #define USB_H_LSPDDEV2_S 17 /** USB_H_EPTYPE2 : R/W; bitpos: [20:18]; default: 0; - * 0x0 (CTRL): Contro + * 0x0 (CTRL): Control * 0x1 (ISOC): Isochronous * 0x2 (BULK): Bulk * 0x3 (INTERR): Interrupt @@ -871,7 +871,7 @@ extern "C" { #define USB_H_ODDFRM2_S 29 /** USB_H_CHDIS2 : R/W; bitpos: [30]; default: 0; * Channel Disable - * 0x0 : Transmit/Recieve norma + * 0x0 : Transmit/Receive norma * 0x1 : Stop transmitting/receiving data on channel */ #define USB_H_CHDIS2 (BIT(30)) @@ -944,7 +944,7 @@ extern "C" { #define USB_H_LSPDDEV3_V 0x00000001 #define USB_H_LSPDDEV3_S 17 /** USB_H_EPTYPE3 : R/W; bitpos: [20:18]; default: 0; - * 0x0 (CTRL): Contro + * 0x0 (CTRL): Control * 0x1 (ISOC): Isochronous * 0x2 (BULK): Bulk * 0x3 (INTERR): Interrupt @@ -983,7 +983,7 @@ extern "C" { #define USB_H_ODDFRM3_S 29 /** USB_H_CHDIS3 : R/W; bitpos: [30]; default: 0; * Channel Disable - * 0x0 : Transmit/Recieve norma + * 0x0 : Transmit/Receive norma * 0x1 : Stop transmitting/receiving data on channel */ #define USB_H_CHDIS3 (BIT(30)) @@ -1056,7 +1056,7 @@ extern "C" { #define USB_H_LSPDDEV4_V 0x00000001 #define USB_H_LSPDDEV4_S 17 /** USB_H_EPTYPE4 : R/W; bitpos: [20:18]; default: 0; - * 0x0 (CTRL): Contro + * 0x0 (CTRL): Control * 0x1 (ISOC): Isochronous * 0x2 (BULK): Bulk * 0x3 (INTERR): Interrupt @@ -1095,7 +1095,7 @@ extern "C" { #define USB_H_ODDFRM4_S 29 /** USB_H_CHDIS4 : R/W; bitpos: [30]; default: 0; * Channel Disable - * 0x0 : Transmit/Recieve norma + * 0x0 : Transmit/Receive norma * 0x1 : Stop transmitting/receiving data on channel */ #define USB_H_CHDIS4 (BIT(30)) @@ -1168,7 +1168,7 @@ extern "C" { #define USB_H_LSPDDEV5_V 0x00000001 #define USB_H_LSPDDEV5_S 17 /** USB_H_EPTYPE5 : R/W; bitpos: [20:18]; default: 0; - * 0x0 (CTRL): Contro + * 0x0 (CTRL): Control * 0x1 (ISOC): Isochronous * 0x2 (BULK): Bulk * 0x3 (INTERR): Interrupt @@ -1207,7 +1207,7 @@ extern "C" { #define USB_H_ODDFRM5_S 29 /** USB_H_CHDIS5 : R/W; bitpos: [30]; default: 0; * Channel Disable - * 0x0 : Transmit/Recieve norma + * 0x0 : Transmit/Receive norma * 0x1 : Stop transmitting/receiving data on channel */ #define USB_H_CHDIS5 (BIT(30)) @@ -1280,7 +1280,7 @@ extern "C" { #define USB_H_LSPDDEV6_V 0x00000001 #define USB_H_LSPDDEV6_S 17 /** USB_H_EPTYPE6 : R/W; bitpos: [20:18]; default: 0; - * 0x0 (CTRL): Contro + * 0x0 (CTRL): Control * 0x1 (ISOC): Isochronous * 0x2 (BULK): Bulk * 0x3 (INTERR): Interrupt @@ -1319,7 +1319,7 @@ extern "C" { #define USB_H_ODDFRM6_S 29 /** USB_H_CHDIS6 : R/W; bitpos: [30]; default: 0; * Channel Disable - * 0x0 : Transmit/Recieve norma + * 0x0 : Transmit/Receive norma * 0x1 : Stop transmitting/receiving data on channel */ #define USB_H_CHDIS6 (BIT(30)) @@ -1392,7 +1392,7 @@ extern "C" { #define USB_H_LSPDDEV7_V 0x00000001 #define USB_H_LSPDDEV7_S 17 /** USB_H_EPTYPE7 : R/W; bitpos: [20:18]; default: 0; - * 0x0 (CTRL): Contro + * 0x0 (CTRL): Control * 0x1 (ISOC): Isochronous * 0x2 (BULK): Bulk * 0x3 (INTERR): Interrupt @@ -1431,7 +1431,7 @@ extern "C" { #define USB_H_ODDFRM7_S 29 /** USB_H_CHDIS7 : R/W; bitpos: [30]; default: 0; * Channel Disable - * 0x0 : Transmit/Recieve norma + * 0x0 : Transmit/Receive norma * 0x1 : Stop transmitting/receiving data on channel */ #define USB_H_CHDIS7 (BIT(30)) @@ -1476,7 +1476,7 @@ extern "C" { /** USB_NZSTSOUTHSHK : R/W; bitpos: [2]; default: 0; * 1'b0: Send the received OUT packet to the application (zero-length or non-zero * length) and send a handshake based on NAK and STALL bits for the endpoint in the - * Devce Endpoint Control Register + * Device Endpoint Control Register * 1'b1: Send a STALL handshake on a nonzero-length status OUT transaction and do not * send the received OUT packet to the application */ @@ -1488,7 +1488,7 @@ extern "C" { * This bit can be set only if FS PHY interface is selected. * Otherwise, this bit needs to be set to zero. * 1'b0: USB 1.1 Full-Speed Serial transiver not selected - * 1'b1: If FS PHY interface is choosen and this bit is set, the PHY clock during Suspend + * 1'b1: If FS PHY interface is chosen and this bit is set, the PHY clock during Suspend * must be switched from 48 MHz to 32 KHz */ #define USB_ENA32KHZSUSP (BIT(3)) @@ -1580,7 +1580,7 @@ extern "C" { #define USB_DCTL_REG (SOC_DPORT_USB_BASE + 0x804) /** USB_RMTWKUPSIG : R/W; bitpos: [0]; default: 0; * 0x0 : Core does not send Remote Wakeup Signaling - * 0x1 : Core sends Remote Wakeup Signalin + * 0x1 : Core sends Remote Wakeup Signaling */ #define USB_RMTWKUPSIG (BIT(0)) #define USB_RMTWKUPSIG_M (USB_RMTWKUPSIG_V << USB_RMTWKUPSIG_S) @@ -4729,7 +4729,7 @@ extern "C" { #define USB_H_NACK0_S 4 /** USB_H_ACK0 : R/W1C; bitpos: [5]; default: 0; * 1'b0: No ACK Response Received or Transmitted Interrupt - * 1'b1: ACK Response Received or Transmitted Interrup + * 1'b1: ACK Response Received or Transmitted Interrupt */ #define USB_H_ACK0 (BIT(5)) #define USB_H_ACK0_M (USB_H_ACK0_V << USB_H_ACK0_S) @@ -4965,7 +4965,7 @@ extern "C" { #define USB_H_NACK1_S 4 /** USB_H_ACK1 : R/W1C; bitpos: [5]; default: 0; * 1'b0: No ACK Response Received or Transmitted Interrupt - * 1'b1: ACK Response Received or Transmitted Interrup + * 1'b1: ACK Response Received or Transmitted Interrupt */ #define USB_H_ACK1 (BIT(5)) #define USB_H_ACK1_M (USB_H_ACK1_V << USB_H_ACK1_S) @@ -5201,7 +5201,7 @@ extern "C" { #define USB_H_NACK2_S 4 /** USB_H_ACK2 : R/W1C; bitpos: [5]; default: 0; * 1'b0: No ACK Response Received or Transmitted Interrupt - * 1'b1: ACK Response Received or Transmitted Interrup + * 1'b1: ACK Response Received or Transmitted Interrupt */ #define USB_H_ACK2 (BIT(5)) #define USB_H_ACK2_M (USB_H_ACK2_V << USB_H_ACK2_S) @@ -5437,7 +5437,7 @@ extern "C" { #define USB_H_NACK3_S 4 /** USB_H_ACK3 : R/W1C; bitpos: [5]; default: 0; * 1'b0: No ACK Response Received or Transmitted Interrupt - * 1'b1: ACK Response Received or Transmitted Interrup + * 1'b1: ACK Response Received or Transmitted Interrupt */ #define USB_H_ACK3 (BIT(5)) #define USB_H_ACK3_M (USB_H_ACK3_V << USB_H_ACK3_S) @@ -5673,7 +5673,7 @@ extern "C" { #define USB_H_NACK4_S 4 /** USB_H_ACK4 : R/W1C; bitpos: [5]; default: 0; * 1'b0: No ACK Response Received or Transmitted Interrupt - * 1'b1: ACK Response Received or Transmitted Interrup + * 1'b1: ACK Response Received or Transmitted Interrupt */ #define USB_H_ACK4 (BIT(5)) #define USB_H_ACK4_M (USB_H_ACK4_V << USB_H_ACK4_S) @@ -5909,7 +5909,7 @@ extern "C" { #define USB_H_NACK5_S 4 /** USB_H_ACK5 : R/W1C; bitpos: [5]; default: 0; * 1'b0: No ACK Response Received or Transmitted Interrupt - * 1'b1: ACK Response Received or Transmitted Interrup + * 1'b1: ACK Response Received or Transmitted Interrupt */ #define USB_H_ACK5 (BIT(5)) #define USB_H_ACK5_M (USB_H_ACK5_V << USB_H_ACK5_S) @@ -6145,7 +6145,7 @@ extern "C" { #define USB_H_NACK6_S 4 /** USB_H_ACK6 : R/W1C; bitpos: [5]; default: 0; * 1'b0: No ACK Response Received or Transmitted Interrupt - * 1'b1: ACK Response Received or Transmitted Interrup + * 1'b1: ACK Response Received or Transmitted Interrupt */ #define USB_H_ACK6 (BIT(5)) #define USB_H_ACK6_M (USB_H_ACK6_V << USB_H_ACK6_S) @@ -6381,7 +6381,7 @@ extern "C" { #define USB_H_NACK7_S 4 /** USB_H_ACK7 : R/W1C; bitpos: [5]; default: 0; * 1'b0: No ACK Response Received or Transmitted Interrupt - * 1'b1: ACK Response Received or Transmitted Interrup + * 1'b1: ACK Response Received or Transmitted Interrupt */ #define USB_H_ACK7 (BIT(5)) #define USB_H_ACK7_M (USB_H_ACK7_V << USB_H_ACK7_S) @@ -8915,9 +8915,9 @@ extern "C" { #define USB_AHBSINGLE_V 0x00000001 #define USB_AHBSINGLE_S 23 /** USB_INVDESCENDIANESS : R/W; bitpos: [24]; default: 0; - * Invert Descriptor Endianess + * Invert Descriptor Endianness * 1'b0: Descriptor Endianness is same as AHB Master Endianness - * 1'b1:Invert Descriptor Endianess according to AHB Master endianness + * 1'b1:Invert Descriptor Endianness according to AHB Master endianness */ #define USB_INVDESCENDIANESS (BIT(24)) #define USB_INVDESCENDIANESS_M (USB_INVDESCENDIANESS_V << USB_INVDESCENDIANESS_S) @@ -9678,7 +9678,7 @@ extern "C" { /** USB_GSNPSID_REG register - * Synopsys ID Register + * ID Register */ #define USB_GSNPSID_REG (SOC_DPORT_USB_BASE + 0x40) /** USB_SYNOPSYSID : RO; bitpos: [32:0]; default: 1330921482; diff --git a/components/soc/esp32s3/include/soc/usb_serial_jtag_reg.h b/components/soc/esp32s3/register/soc/usb_serial_jtag_reg.h similarity index 99% rename from components/soc/esp32s3/include/soc/usb_serial_jtag_reg.h rename to components/soc/esp32s3/register/soc/usb_serial_jtag_reg.h index 5774f2d711ae..2338bc6a4de4 100644 --- a/components/soc/esp32s3/include/soc/usb_serial_jtag_reg.h +++ b/components/soc/esp32s3/register/soc/usb_serial_jtag_reg.h @@ -9,7 +9,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" #define USB_SERIAL_JTAG_EP1_REG (DR_REG_USB_SERIAL_JTAG_BASE + 0x0) /* USB_SERIAL_JTAG_RDWR_BYTE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ @@ -31,8 +31,8 @@ ived, then read data from UART Rx FIFO..*/ #define USB_SERIAL_JTAG_SERIAL_OUT_EP_DATA_AVAIL_V 0x1 #define USB_SERIAL_JTAG_SERIAL_OUT_EP_DATA_AVAIL_S 2 /* USB_SERIAL_JTAG_SERIAL_IN_EP_DATA_FREE : RO ;bitpos:[1] ;default: 1'b1 ; */ -/*description: 1'b1: Indicate UART Tx FIFO is not full and can write data into in. After writin -g USB_SERIAL_JTAG_WR_DONE, this bit would be 0 until data in UART Tx FIFO is read by +/*description: 1'b1: Indicate UART Tx FIFO is not full and can write data into in. After +writing USB_SERIAL_JTAG_WR_DONE, this bit would be 0 until data in UART Tx FIFO is read by USB Host..*/ #define USB_SERIAL_JTAG_SERIAL_IN_EP_DATA_FREE (BIT(1)) #define USB_SERIAL_JTAG_SERIAL_IN_EP_DATA_FREE_M (BIT(1)) @@ -117,8 +117,8 @@ eived..*/ #define USB_SERIAL_JTAG_SOF_INT_RAW_V 0x1 #define USB_SERIAL_JTAG_SOF_INT_RAW_S 1 /* USB_SERIAL_JTAG_JTAG_IN_FLUSH_INT_RAW : R/WTC/SS ;bitpos:[0] ;default: 1'b0 ; */ -/*description: The raw interrupt bit turns to high level when flush cmd is received for IN endp -oint 2 of JTAG..*/ +/*description: The raw interrupt bit turns to high level when flush cmd is received for IN +endpoint 2 of JTAG..*/ #define USB_SERIAL_JTAG_JTAG_IN_FLUSH_INT_RAW (BIT(0)) #define USB_SERIAL_JTAG_JTAG_IN_FLUSH_INT_RAW_M (BIT(0)) #define USB_SERIAL_JTAG_JTAG_IN_FLUSH_INT_RAW_V 0x1 @@ -146,7 +146,7 @@ pt..*/ #define USB_SERIAL_JTAG_USB_BUS_RESET_INT_ST_V 0x1 #define USB_SERIAL_JTAG_USB_BUS_RESET_INT_ST_S 9 /* USB_SERIAL_JTAG_IN_TOKEN_REC_IN_EP1_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: The raw interrupt status bit for the USB_SERIAL_JTAG_IN_TOKEN_REC_IN_EP1_INT interrup +/*description: The raw interrupt status bit for the USB_SERIAL_JTAG_IN_TOKEN_REC_IN_EP1_INT interrupt t..*/ #define USB_SERIAL_JTAG_IN_TOKEN_REC_IN_EP1_INT_ST (BIT(8)) #define USB_SERIAL_JTAG_IN_TOKEN_REC_IN_EP1_INT_ST_M (BIT(8)) @@ -183,7 +183,7 @@ t..*/ #define USB_SERIAL_JTAG_SERIAL_IN_EMPTY_INT_ST_V 0x1 #define USB_SERIAL_JTAG_SERIAL_IN_EMPTY_INT_ST_S 3 /* USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: The raw interrupt status bit for the USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT interrup +/*description: The raw interrupt status bit for the USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT interrupt t..*/ #define USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT_ST (BIT(2)) #define USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT_ST_M (BIT(2)) diff --git a/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32s3/register/soc/usb_serial_jtag_struct.h similarity index 96% rename from components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h rename to components/soc/esp32s3/register/soc/usb_serial_jtag_struct.h index 539717f267b6..aeb3bb47caa2 100644 --- a/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32s3/register/soc/usb_serial_jtag_struct.h @@ -1,16 +1,8 @@ -// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_USB_SERIAL_JTAG_STRUCT_H_ #define _SOC_USB_SERIAL_JTAG_STRUCT_H_ @@ -18,7 +10,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "soc.h" +#include "soc/soc.h" typedef volatile struct usb_serial_jtag_dev_s { union { diff --git a/components/soc/esp32s3/include/soc/usb_struct.h b/components/soc/esp32s3/register/soc/usb_struct.h similarity index 98% rename from components/soc/esp32s3/include/soc/usb_struct.h rename to components/soc/esp32s3/register/soc/usb_struct.h index 697c79e416fc..a07aa34f533c 100644 --- a/components/soc/esp32s3/include/soc/usb_struct.h +++ b/components/soc/esp32s3/register/soc/usb_struct.h @@ -50,7 +50,7 @@ typedef struct usb_reg { volatile uint32_t gnptxfsiz; // 0x0028 Non-periodic Transmit FIFO Size Register volatile uint32_t gnptxsts; // 0x002c Non-periodic Transmit FIFO/Queue Status Register uint32_t reserved_0x0030_0x0040[4]; // 0x0030 to 0x0040 - volatile uint32_t gsnpsid; // 0x0040 Synopsys ID Register + volatile uint32_t gsnpsid; // 0x0040 ID Register volatile uint32_t ghwcfg1; // 0x0044 User Hardware Configuration 1 Register volatile uint32_t ghwcfg2; // 0x0048 User Hardware Configuration 2 Register volatile uint32_t ghwcfg3; // 0x004c User Hardware Configuration 3 Register diff --git a/components/soc/esp32s3/include/soc/usb_wrap_reg.h b/components/soc/esp32s3/register/soc/usb_wrap_reg.h similarity index 93% rename from components/soc/esp32s3/include/soc/usb_wrap_reg.h rename to components/soc/esp32s3/register/soc/usb_wrap_reg.h index 45502289cdfa..9b8ea950a240 100644 --- a/components/soc/esp32s3/include/soc/usb_wrap_reg.h +++ b/components/soc/esp32s3/register/soc/usb_wrap_reg.h @@ -1,21 +1,13 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_USB_WRAP_REG_H_ #define _SOC_USB_WRAP_REG_H_ -#include "soc.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/include/soc/usb_wrap_struct.h b/components/soc/esp32s3/register/soc/usb_wrap_struct.h similarity index 95% rename from components/soc/esp32s3/include/soc/usb_wrap_struct.h rename to components/soc/esp32s3/register/soc/usb_wrap_struct.h index 71013fe25f7b..9f440d17e9aa 100644 --- a/components/soc/esp32s3/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32s3/register/soc/usb_wrap_struct.h @@ -1,16 +1,7 @@ -/** Copyright 2020 Espressif Systems (Shanghai) PTE LTD +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #pragma once diff --git a/components/soc/esp32s3/include/soc/world_controller_reg.h b/components/soc/esp32s3/register/soc/world_controller_reg.h similarity index 100% rename from components/soc/esp32s3/include/soc/world_controller_reg.h rename to components/soc/esp32s3/register/soc/world_controller_reg.h diff --git a/components/soc/esp32s3/include/soc/world_controller_struct.h b/components/soc/esp32s3/register/soc/world_controller_struct.h similarity index 100% rename from components/soc/esp32s3/include/soc/world_controller_struct.h rename to components/soc/esp32s3/register/soc/world_controller_struct.h diff --git a/components/soc/esp32s3/spi_periph.c b/components/soc/esp32s3/spi_periph.c index 91fdc8735517..3675131a9b93 100644 --- a/components/soc/esp32s3/spi_periph.c +++ b/components/soc/esp32s3/spi_periph.c @@ -33,7 +33,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = -1, .irq = -1, .irq_dma = -1, - .module = -1, .hw = NULL, .func = -1, }, { @@ -65,7 +64,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, .irq = ETS_SPI2_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_SPI2_MODULE, .hw = &GPSPI2, .func = SPI2_FUNC_NUM, }, { @@ -91,7 +89,6 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spics0_iomux_pin = -1, .irq = ETS_SPI3_INTR_SOURCE, .irq_dma = -1, - .module = PERIPH_SPI3_MODULE, .hw = &GPSPI3, .func = -1, } diff --git a/components/soc/esp32s3/usb_dwc_periph.c b/components/soc/esp32s3/usb_dwc_periph.c index eba3eaaf60bb..51386dde8b88 100644 --- a/components/soc/esp32s3/usb_dwc_periph.c +++ b/components/soc/esp32s3/usb_dwc_periph.c @@ -4,8 +4,79 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "soc/usb_dwc_periph.h" +#include #include "soc/gpio_sig_map.h" +#include "soc/usb_periph.h" +#include "soc/interrupts.h" +#include "soc/usb_dwc_periph.h" + +/* -------------------------------- Private --------------------------------- */ + +static const usb_fsls_serial_signal_conn_t fsls_signals = { + // Inputs + .rx_dp = USB_EXTPHY_VP_IDX, + .rx_dm = USB_EXTPHY_VM_IDX, + .rx_rcv = USB_EXTPHY_RCV_IDX, + // Outputs + .suspend_n = USB_EXTPHY_SUSPND_IDX, + .tx_enable_n = USB_EXTPHY_OEN_IDX, + .tx_dp = USB_EXTPHY_VPO_IDX, + .tx_dm = USB_EXTPHY_VMO_IDX, + .fs_edge_sel = USB_EXTPHY_SPEED_IDX, +}; + +static const usb_utmi_otg_signal_conn_t otg_signals = { + // Inputs + .iddig = USB_OTG_IDDIG_IN_IDX, + .avalid = USB_OTG_AVALID_IN_IDX, + .bvalid = USB_SRP_BVALID_IN_IDX, + .vbusvalid = USB_OTG_VBUSVALID_IN_IDX, + .sessend = USB_SRP_SESSEND_IN_IDX, + // Outputs + .idpullup = USB_OTG_IDPULLUP_IDX, + .dppulldown = USB_OTG_DPPULLDOWN_IDX, + .dmpulldown = USB_OTG_DMPULLDOWN_IDX, + .drvvbus = USB_OTG_DRVVBUS_IDX, + .chrgvbus = USB_SRP_CHRGVBUS_IDX, + .dischrgvbus = USB_SRP_DISCHRGVBUS_IDX, +}; + +/* --------------------------------- Public --------------------------------- */ + +const usb_dwc_info_t usb_dwc_info = { + .controllers = { + [0] = { + .fsls_signals = &fsls_signals, + .otg_signals = &otg_signals, + .irq = ETS_USB_INTR_SOURCE, + .irq_2nd_cpu = -1, + }, + }, +}; + +/* ------------------------------- Deprecated ------------------------------- */ + +/* +Note: These IO pins are deprecated. When connecting USB OTG to an external FSLS +PHY, the FSLS Serial Interface signals can be routed to any GPIO via the GPIO +matrix. Thus, this mapping of signals to IO pins is meaningless. + +Todo: Remove in IDF v6.0 (IDF-9029) +*/ +const usb_iopin_dsc_t usb_periph_iopins[] = { + {USBPHY_VP_NUM, USB_EXTPHY_VP_IDX, 0, 1}, + {USBPHY_VM_NUM, USB_EXTPHY_VM_IDX, 0, 1}, + {USBPHY_RCV_NUM, USB_EXTPHY_RCV_IDX, 0, 1}, + {USBPHY_OEN_NUM, USB_EXTPHY_OEN_IDX, 1, 1}, + {USBPHY_VPO_NUM, USB_EXTPHY_VPO_IDX, 1, 1}, + {USBPHY_VMO_NUM, USB_EXTPHY_VMO_IDX, 1, 1}, + {GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, 0, 0}, //connected connector is mini-B + //connected connector is mini-B + {GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, 0, 0}, //HIGH to force USB device mode + {GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, 0, 0}, //receiving a valid Vbus from host + {GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_AVALID_IN_IDX, 0, 0}, + {-1, -1, 0, 0} +}; /* Bunch of constants for USB peripheral: GPIO signals diff --git a/components/soc/esp32s3/usb_periph.c b/components/soc/esp32s3/usb_periph.c deleted file mode 100644 index a3fda7193e38..000000000000 --- a/components/soc/esp32s3/usb_periph.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "soc/soc_caps.h" -#include "soc/usb_periph.h" - -/* -Note: These IO pins are deprecated. When connecting USB OTG to an external FSLS -PHY, the FSLS Serial Interface signals can be routed to any GPIO via the GPIO -matrix. Thus, this mapping of signals to IO pins is meaningless. - -Todo: Remove in IDF v6.0 (IDF-9029) -*/ -const usb_iopin_dsc_t usb_periph_iopins[] = { - {USBPHY_VP_NUM, USB_EXTPHY_VP_IDX, 0, 1}, - {USBPHY_VM_NUM, USB_EXTPHY_VM_IDX, 0, 1}, - {USBPHY_RCV_NUM, USB_EXTPHY_RCV_IDX, 0, 1}, - {USBPHY_OEN_NUM, USB_EXTPHY_OEN_IDX, 1, 1}, - {USBPHY_VPO_NUM, USB_EXTPHY_VPO_IDX, 1, 1}, - {USBPHY_VMO_NUM, USB_EXTPHY_VMO_IDX, 1, 1}, - {GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, 0, 0}, //connected connector is mini-B - //connected connector is mini-B - {GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, 0, 0}, //HIGH to force USB device mode - {GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, 0, 0}, //receiving a valid Vbus from host - {GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_AVALID_IN_IDX, 0, 0}, - {-1, -1, 0, 0} -}; diff --git a/components/soc/include/soc/etm_periph.h b/components/soc/include/soc/etm_periph.h new file mode 100644 index 000000000000..f7168ff71731 --- /dev/null +++ b/components/soc/include/soc/etm_periph.h @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc_caps.h" +#include "soc/regdma.h" + +#if SOC_ETM_SUPPORT_SLEEP_RETENTION +#include "soc/retention_periph_defs.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_ETM_SUPPORT_SLEEP_RETENTION +typedef struct { + periph_retention_module_t module; + const regdma_entries_config_t *regdma_entry_array; + uint32_t array_size; +} etm_reg_retention_info_t; + +extern const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS]; +#endif // SOC_ETM_SUPPORT_SLEEP_RETENTION + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/include/soc/gdma_periph.h b/components/soc/include/soc/gdma_periph.h index 4da8b042b2ec..478aab39a90e 100644 --- a/components/soc/include/soc/gdma_periph.h +++ b/components/soc/include/soc/gdma_periph.h @@ -44,7 +44,7 @@ extern const gdma_signal_conn_t gdma_periph_signals; typedef struct { const regdma_entries_config_t *link_list; uint32_t link_num; - periph_retention_module_t module_id; + const periph_retention_module_t module_id; } gdma_chx_reg_ctx_link_t; extern const gdma_chx_reg_ctx_link_t gdma_chx_regs_retention[SOC_GDMA_NUM_GROUPS_MAX][SOC_GDMA_PAIRS_PER_GROUP_MAX]; diff --git a/components/soc/include/soc/i2c_periph.h b/components/soc/include/soc/i2c_periph.h index 408da3afc49e..c1fbb0fbc8dc 100644 --- a/components/soc/include/soc/i2c_periph.h +++ b/components/soc/include/soc/i2c_periph.h @@ -11,6 +11,9 @@ #if SOC_I2C_SUPPORTED #include "soc/regdma.h" #include "soc/interrupts.h" +#if SOC_I2C_SUPPORT_SLEEP_RETENTION +#include "soc/retention_periph_defs.h" +#endif #ifdef __cplusplus extern "C" { @@ -31,6 +34,7 @@ extern const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM]; typedef struct { const regdma_entries_config_t *link_list; uint32_t link_num; + periph_retention_module_t module_id; } i2c_reg_ctx_link_t; extern const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM]; diff --git a/components/soc/include/soc/i2s_periph.h b/components/soc/include/soc/i2s_periph.h index cf2d483f48f6..0dfc4a1196ca 100644 --- a/components/soc/include/soc/i2s_periph.h +++ b/components/soc/include/soc/i2s_periph.h @@ -1,13 +1,17 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include "soc/soc.h" -#include "soc/periph_defs.h" +#include "soc/interrupts.h" #include "soc/soc_caps.h" +#include "soc/regdma.h" +#if SOC_I2S_SUPPORT_SLEEP_RETENTION +#include "soc/retention_periph_defs.h" +#endif #if SOC_I2S_SUPPORTED #include "soc/i2s_struct.h" @@ -51,7 +55,6 @@ typedef struct { }; const uint8_t irq; - const periph_module_t module; } i2s_signal_conn_t; extern const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM]; @@ -62,6 +65,16 @@ extern const i2s_signal_conn_t lp_i2s_periph_signal[SOC_LP_I2S_NUM]; #endif // SOC_I2S_SUPPORTED +#if SOC_I2S_SUPPORT_SLEEP_RETENTION +typedef struct { + const periph_retention_module_t retention_module; + const regdma_entries_config_t *entry_array; + uint32_t array_size; +} i2s_reg_retention_info_t; + +extern const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM]; +#endif // SOC_I2S_SUPPORT_SLEEP_RETENTION + #ifdef __cplusplus } #endif diff --git a/components/soc/include/soc/ledc_periph.h b/components/soc/include/soc/ledc_periph.h index d90f22e79310..8ed332010baf 100644 --- a/components/soc/include/soc/ledc_periph.h +++ b/components/soc/include/soc/ledc_periph.h @@ -1,21 +1,18 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once + #include "soc/soc_caps.h" #include "soc/ledc_reg.h" #include "soc/ledc_struct.h" +#if SOC_PAU_SUPPORTED +#include "soc/regdma.h" +#include "soc/retention_periph_defs.h" +#endif #ifdef __cplusplus extern "C" { @@ -34,6 +31,33 @@ extern const ledc_signal_conn_t ledc_periph_signal[2]; extern const ledc_signal_conn_t ledc_periph_signal[1]; #endif +#if SOC_PAU_SUPPORTED + +#if SOC_LIGHT_SLEEP_SUPPORTED +#if SOC_PHY_SUPPORTED +#define LEDC_RETENTION_ENTRY (ENTRY(0) | ENTRY(2)) +#else +#define LEDC_RETENTION_ENTRY (ENTRY(0)) +#endif +#else // !SOC_LIGHT_SLEEP_SUPPORTED +#define LEDC_RETENTION_ENTRY REGDMA_SW_TRIGGER_ENTRY +#endif + +typedef struct { + const regdma_entries_config_t *regdma_entry_array; + uint32_t array_size; +} ledc_sub_reg_retention_info_t; + +typedef struct { + ledc_sub_reg_retention_info_t common; + ledc_sub_reg_retention_info_t timer[SOC_LEDC_TIMER_NUM]; + ledc_sub_reg_retention_info_t channel[SOC_LEDC_CHANNEL_NUM]; + const periph_retention_module_t module_id; +} ledc_reg_retention_info_t; + +extern const ledc_reg_retention_info_t ledc_reg_retention_info; +#endif + #ifdef __cplusplus } #endif diff --git a/components/soc/include/soc/parlio_periph.h b/components/soc/include/soc/parlio_periph.h index c9781a048f55..3bb4de72b022 100644 --- a/components/soc/include/soc/parlio_periph.h +++ b/components/soc/include/soc/parlio_periph.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,10 @@ #include "soc/parl_io_reg.h" #include "soc/parl_io_struct.h" #endif +#include "soc/regdma.h" +#if SOC_PARLIO_SUPPORT_SLEEP_RETENTION +#include "soc/retention_periph_defs.h" +#endif #ifdef __cplusplus extern "C" { @@ -39,6 +43,16 @@ typedef struct { extern const parlio_signal_conn_t parlio_periph_signals; +#if SOC_PARLIO_SUPPORT_SLEEP_RETENTION +typedef struct { + const periph_retention_module_t retention_module; + const regdma_entries_config_t *regdma_entry_array; + uint32_t array_size; +} parlio_reg_retention_info_t; + +extern const parlio_reg_retention_info_t parlio_reg_retention_info[SOC_PARLIO_GROUPS]; +#endif // SOC_PARLIO_SUPPORT_SLEEP_RETENTION + #endif #ifdef __cplusplus diff --git a/components/soc/include/soc/pcnt_periph.h b/components/soc/include/soc/pcnt_periph.h index e7d8818b090b..a060af597fe4 100644 --- a/components/soc/include/soc/pcnt_periph.h +++ b/components/soc/include/soc/pcnt_periph.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,10 @@ #include #include "soc/soc_caps.h" #include "soc/periph_defs.h" +#include "soc/regdma.h" +#if SOC_PCNT_SUPPORT_SLEEP_RETENTION +#include "soc/retention_periph_defs.h" +#endif #ifdef __cplusplus extern "C" { @@ -31,6 +35,16 @@ typedef struct { extern const pcnt_signal_conn_t pcnt_periph_signals; +#if SOC_PCNT_SUPPORT_SLEEP_RETENTION +typedef struct { + const periph_retention_module_t retention_module; + const regdma_entries_config_t *regdma_entry_array; + uint32_t array_size; +} pcnt_reg_retention_info_t; + +extern const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS]; +#endif // SOC_PCNT_SUPPORT_SLEEP_RETENTION + #endif // SOC_PCNT_SUPPORTED #ifdef __cplusplus diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index c48c66d0ebff..7ee06f0095bd 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -53,6 +53,14 @@ extern "C" { #define REGDMA_TG1_WDT_LINK(_pri) ((0x1B << 8) | _pri) #define REGDMA_TG0_TIMER_LINK(_pri) ((0x1C << 8) | _pri) #define REGDMA_TG1_TIMER_LINK(_pri) ((0x1D << 8) | _pri) +#define REGDMA_I2S_LINK(_pri) ((0x1E << 8) | _pri) +#define REGDMA_ETM_LINK(_pri) ((0x1F << 8) | _pri) +#define REGDMA_TSENS_LINK(_pri) ((0x20 << 8) | _pri) +#define REGDMA_TWAI_LINK(_pri) ((0x21 << 8) | _pri) +#define REGDMA_PARLIO_LINK(_pri) ((0x22 << 8) | _pri) +#define REGDMA_GPSPI_LINK(_pri) ((0x23 << 8) | _pri) +#define REGDMA_LEDC_LINK(_pri) ((0x24 << 8) | _pri) +#define REGDMA_PCNT_LINK(_pri) ((0x25 << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) #define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0 @@ -67,9 +75,17 @@ extern "C" { #define REGDMA_LINK_PRI_IEEE802154 REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_GDMA REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_RMT REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_ETM REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_GPTIMER REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_I2C REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_I2S REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_PARLIO REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_PCNT REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_TEMPERATURE_SENSOR REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_TWAI REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_GPSPI REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_LEDC REGDMA_LINK_PRI_GENERAL_PERIPH typedef enum { REGDMA_LINK_PRI_0 = 0, diff --git a/components/soc/include/soc/rmt_periph.h b/components/soc/include/soc/rmt_periph.h index a85b5930a220..bb35a67b8635 100644 --- a/components/soc/include/soc/rmt_periph.h +++ b/components/soc/include/soc/rmt_periph.h @@ -10,6 +10,10 @@ #include "soc/periph_defs.h" #include "soc/regdma.h" +#if SOC_RMT_SUPPORT_SLEEP_RETENTION +#include "soc/retention_periph_defs.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -32,6 +36,7 @@ extern const rmt_signal_conn_t rmt_periph_signals; #if SOC_RMT_SUPPORT_SLEEP_RETENTION typedef struct { + periph_retention_module_t module; const regdma_entries_config_t *regdma_entry_array; uint32_t array_size; } rmt_reg_retention_info_t; diff --git a/components/soc/include/soc/spi_periph.h b/components/soc/include/soc/spi_periph.h index 7a85aafa6502..8e653edf0c36 100644 --- a/components/soc/include/soc/spi_periph.h +++ b/components/soc/include/soc/spi_periph.h @@ -9,13 +9,17 @@ #include #include "sdkconfig.h" #include "soc/soc.h" -#include "soc/periph_defs.h" +#include "soc/soc_caps.h" +#include "soc/spi_pins.h" +#if SOC_PAU_SUPPORTED +#include "soc/regdma.h" +#include "soc/retention_periph_defs.h" +#endif //include soc related (generated) definitions -#include "soc/soc_caps.h" +#include "soc/interrupts.h" #include "soc/spi_reg.h" #include "soc/spi_struct.h" -#include "soc/spi_pins.h" #include "soc/gpio_sig_map.h" #if SOC_MEMSPI_IS_INDEPENDENT #include "soc/spi_mem_struct.h" @@ -71,13 +75,22 @@ typedef struct { const uint8_t spics0_iomux_pin; const uint8_t irq; //irq source for interrupt mux const uint8_t irq_dma; //dma irq source for interrupt mux - const periph_module_t module; //peripheral module, for enabling clock etc - const int func; //function number for IOMUX - spi_dev_t *hw; //Pointer to the hardware registers + const int func; //function number for IOMUX + spi_dev_t *hw; //Pointer to the hardware registers } spi_signal_conn_t; extern const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM]; +#if SOC_PAU_SUPPORTED +typedef struct { + const periph_retention_module_t module_id; + const regdma_entries_config_t *entry_array; + uint32_t array_size; +} spi_reg_retention_info_t; + +extern const spi_reg_retention_info_t spi_reg_retention_info[SOC_SPI_PERIPH_NUM - 1]; // -1 to except mspi +#endif // SOC_PAU_SUPPORTED + #ifdef __cplusplus } #endif diff --git a/components/soc/include/soc/temperature_sensor_periph.h b/components/soc/include/soc/temperature_sensor_periph.h index 737428193506..d52739255415 100644 --- a/components/soc/include/soc/temperature_sensor_periph.h +++ b/components/soc/include/soc/temperature_sensor_periph.h @@ -1,11 +1,16 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include "soc/regdma.h" +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION +#include "soc/retention_periph_defs.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -22,6 +27,16 @@ typedef struct { extern const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM]; +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION +typedef struct { + const regdma_entries_config_t *link_list; + uint32_t link_num; + periph_retention_module_t module_id; +} temperature_sensor_reg_ctx_link_t; + +extern const temperature_sensor_reg_ctx_link_t temperature_sensor_regs_retention; +#endif // SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + #ifdef __cplusplus } #endif diff --git a/components/soc/include/soc/twai_periph.h b/components/soc/include/soc/twai_periph.h index 72a37210a2bb..89ca029f02cc 100644 --- a/components/soc/include/soc/twai_periph.h +++ b/components/soc/include/soc/twai_periph.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,10 @@ #include #include "soc/soc_caps.h" #include "soc/periph_defs.h" +#if SOC_PAU_SUPPORTED +#include "soc/regdma.h" +#include "soc/retention_periph_defs.h" +#endif #ifdef __cplusplus extern "C" { @@ -30,6 +34,16 @@ typedef struct { extern const twai_controller_signal_conn_t twai_controller_periph_signals; +#if SOC_PAU_SUPPORTED +typedef struct { + const periph_retention_module_t module_id; + const regdma_entries_config_t *entry_array; + uint32_t array_size; +} twai_reg_retention_info_t; + +extern const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM]; +#endif // SOC_PAU_SUPPORTED + #endif // SOC_TWAI_SUPPORTED #ifdef __cplusplus diff --git a/components/soc/include/soc/uart_periph.h b/components/soc/include/soc/uart_periph.h index 2c0681e8dad6..ba73db130954 100644 --- a/components/soc/include/soc/uart_periph.h +++ b/components/soc/include/soc/uart_periph.h @@ -12,7 +12,10 @@ #include "soc/uart_pins.h" #include "soc/uart_struct.h" #include "soc/uart_reg.h" +#if SOC_PAU_SUPPORTED #include "soc/regdma.h" +#include "soc/retention_periph_defs.h" +#endif #ifdef __cplusplus extern "C" { @@ -50,8 +53,9 @@ typedef struct { extern const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM]; -#if SOC_UART_SUPPORT_SLEEP_RETENTION +#if SOC_UART_SUPPORT_SLEEP_RETENTION && SOC_PAU_SUPPORTED typedef struct { + const periph_retention_module_t module; const regdma_entries_config_t *regdma_entry_array; uint32_t array_size; } uart_reg_retention_info_t; diff --git a/components/soc/include/soc/usb_dwc_periph.h b/components/soc/include/soc/usb_dwc_periph.h index d13286aa1dcc..8e1832c2ced9 100644 --- a/components/soc/include/soc/usb_dwc_periph.h +++ b/components/soc/include/soc/usb_dwc_periph.h @@ -1,18 +1,93 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once + #include +#include +#include "soc/soc_pins.h" #include "soc/soc_caps.h" #include "soc/periph_defs.h" +#include "soc/gpio_sig_map.h" #ifdef __cplusplus extern "C" { #endif +#if SOC_USB_OTG_SUPPORTED + +/* ---------------------------------- Types --------------------------------- */ + +/** + * @brief USB PHY FSLS Serial Interface Signals + * + * Structure to store the GPIO matrix signal indexes for a USB PHY FSLS Serial + * interface's signals. + * + * @note Refer to section "2.2.1.13 FsLsSerialMode" of the UTMI+ for more + * details regarding the FSLS Serial Interface. + */ +typedef struct { + // Inputs + int rx_dp; + int rx_dm; + int rx_rcv; + // Outputs + int suspend_n; + int tx_enable_n; + int tx_dp; + int tx_dm; + int fs_edge_sel; +} usb_fsls_serial_signal_conn_t; + +/** + * @brief USB PHY UTMI OTG Interface Signal Index Type + * + * Structure to store the GPIO matrix signal indexes for a UTMI PHY interface's + * OTG signals. + */ +typedef struct { + // Inputs + int iddig; + int avalid; + int bvalid; + int vbusvalid; + int sessend; + // Outputs + int idpullup; + int dppulldown; + int dmpulldown; + int drvvbus; + int chrgvbus; + int dischrgvbus; +} usb_utmi_otg_signal_conn_t; + +/** + * @brief USB Controller Information + * + * Structure to store information for all USB-DWC instances + */ +typedef struct { + struct { + const usb_fsls_serial_signal_conn_t * const fsls_signals; // Must be set if external PHY is supported by controller + const usb_utmi_otg_signal_conn_t * const otg_signals; + const int irq; + const int irq_2nd_cpu; // The USB-DWC can provide 2nd interrupt so each CPU can have its own interrupt line. Set to -1 if not supported + } controllers [SOC_USB_OTG_PERIPH_NUM]; +} usb_dwc_info_t; + +extern const usb_dwc_info_t usb_dwc_info; + +#endif // SOC_USB_OTG_SUPPORTED + +/* ------------------------------- Deprecated ------------------------------- */ +/* Todo: Remove in ESP-IDF v6.0 (IDF-9052) */ + +#if SOC_USB_OTG_SUPPORTED + /* Stores a bunch of USB-peripheral data. */ @@ -41,6 +116,8 @@ typedef struct { extern const usb_phy_signal_conn_t usb_otg_periph_signal; +#endif // SOC_USB_OTG_SUPPORTED + #ifdef __cplusplus } #endif diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt index 147f01294fd3..5e85a5c94f2b 100644 --- a/components/spi_flash/CMakeLists.txt +++ b/components/spi_flash/CMakeLists.txt @@ -1,13 +1,16 @@ idf_build_get_property(target IDF_TARGET) +idf_build_get_property(non_os_build NON_OS_BUILD) + if(${target} STREQUAL "linux") idf_component_register(SRCS "linux/spi_flash_linux.c" "linux/cache_utils.c" + "linux/flash_mmap.c" INCLUDE_DIRS include PRIV_INCLUDE_DIRS include/spi_flash) return() endif() -if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) +if(non_os_build OR CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) set(srcs "spi_flash_wrap.c") set(priv_requires bootloader_support soc) else() @@ -69,7 +72,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU") " -fno-inline-small-functions -fno-inline-functions-called-once") endif() -if(NOT BOOTLOADER_BUILD AND NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) +if(NOT non_os_build AND NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) if(CONFIG_SPIRAM) # [refactor-todo]: requires "esp_psram" for few MMU usages in `flash_mmap.c` # will be replaced with MMU requirements diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index 367b1376571c..80a48a1b7e48 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -109,6 +109,17 @@ menu "Main Flash configuration" This config is used for setting Tsus parameter. Tsus means CS# high to next command after suspend. You can refer to the chapter of AC CHARACTERISTICS of flash datasheet. + config SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND + bool "Enable XMC-C series flash chip suspend feature anyway" + default n + help + XMC-C series is regarded as not qualified for the Suspend feature, since its specification + has a tRS >= 1ms restriction. We strongly do not suggest using it for the Suspend feature. + However, if your product in field has enabled this feature, you may still enable this + config option to keep the legacy behavior. + + For new users, DO NOT enable this config. + endmenu endmenu diff --git a/components/spi_flash/flash_brownout_hook.c b/components/spi_flash/flash_brownout_hook.c index 762b54028df1..7d070c0b19b4 100644 --- a/components/spi_flash/flash_brownout_hook.c +++ b/components/spi_flash/flash_brownout_hook.c @@ -20,7 +20,7 @@ void spi_flash_needs_reset_check(void) { // Currently only XMC is suggested to reset when brownout #if CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC - if ((g_rom_flashchip.device_id >> 16) == 0x20 || (g_rom_flashchip.device_id >> 16) == 0x46) { + if ((g_rom_flashchip.device_id >> 16) == 0x20) { flash_brownout_needs_reset = true; } #endif diff --git a/components/spi_flash/include/esp_flash_internal.h b/components/spi_flash/include/esp_flash_internal.h index e7d35b0dfb2d..d07b3e229007 100644 --- a/components/spi_flash/include/esp_flash_internal.h +++ b/components/spi_flash/include/esp_flash_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -95,7 +95,27 @@ esp_err_t esp_flash_app_enable_os_functions(esp_flash_t* chip); */ esp_err_t esp_flash_app_disable_os_functions(esp_flash_t* chip); - +/** + * @brief Set or clear dangerous write protection check on the flash chip. + * + * This function sets the runtime option to allow or disallow writing to + * dangerous areas such as the bootloader and partition table. If + * CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set, this function allows + * the caller to toggle the protection for specific areas. + * + * If CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is set, there is no protection + * check in the system, and this function does nothing. + * + * @param chip The flash chip on which to set the write protection. Only + * "esp_flash_default_chip" is supported. + * @param protect Set to true to enable protection against writing in dangerous + * areas (bootloader, partition table). Set to false to disable + * the protection. + * @return + * - ESP_OK: Successful operation. + * - ESP_ERR_INVALID_ARG: The chip argument is null. + */ +esp_err_t esp_flash_set_dangerous_write_protection(esp_flash_t *chip, const bool protect); #ifdef __cplusplus } diff --git a/components/spi_flash/include/spi_flash/spi_flash_defs.h b/components/spi_flash/include/spi_flash/spi_flash_defs.h index 08247c619bea..7a8bf432f78f 100644 --- a/components/spi_flash/include/spi_flash/spi_flash_defs.h +++ b/components/spi_flash/include/spi_flash/spi_flash_defs.h @@ -53,6 +53,8 @@ #define CMD_RST_EN 0x66 #define CMD_RST_DEV 0x99 +#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */ + #define SPI_FLASH_DIO_ADDR_BITLEN 24 #define SPI_FLASH_DIO_DUMMY_BITLEN 4 #define SPI_FLASH_QIO_ADDR_BITLEN 24 diff --git a/components/spi_flash/linux/flash_mmap.c b/components/spi_flash/linux/flash_mmap.c new file mode 100644 index 000000000000..4a48b69108db --- /dev/null +++ b/components/spi_flash/linux/flash_mmap.c @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "spi_flash_mmap.h" + +uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory) +{ + (void) memory; + return 10; +} diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index 33bd1c302918..8233eaf174bf 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -599,11 +599,37 @@ spi_flash_caps_t spi_flash_chip_generic_get_caps(esp_flash_t *chip) // 32M-bits address support // flash suspend support - // XMC support suspend - if (chip->chip_id >> 16 == 0x20 || chip->chip_id >> 16 == 0x46) { + // XMC-D support suspend + if (chip->chip_id >> 16 == 0x46) { caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND; } + // XMC-D support suspend (some D series flash chip begin with 0x20, difference checked by SFDP) + if (chip->chip_id >> 16 == 0x20) { + uint8_t data = 0; + spi_flash_trans_t t = { + .command = CMD_RDSFDP, + .address_bitlen = 24, + .address = 0x32, + .mosi_len = 0, + .mosi_data = 0, + .miso_len = 1, + .miso_data = &data, + .dummy_bitlen = 8, + }; + chip->host->driver->common_command(chip->host, &t); + if((data & 0x8) == 0x8) { + caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND; + } + } + +#if CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND + // XMC-C suspend has big risk. But can enable this anyway. + if (chip->chip_id >> 16 == 0x20) { + caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND; + } +#endif + // FM support suspend if (chip->chip_id >> 16 == 0xa1) { caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND; diff --git a/components/spi_flash/spi_flash_os_func_app.c b/components/spi_flash/spi_flash_os_func_app.c index 1cae38728132..51f0671f0992 100644 --- a/components/spi_flash/spi_flash_os_func_app.c +++ b/components/spi_flash/spi_flash_os_func_app.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -350,6 +350,22 @@ esp_err_t esp_flash_app_enable_os_functions(esp_flash_t* chip) return ESP_OK; } +esp_err_t esp_flash_set_dangerous_write_protection(esp_flash_t *chip, const bool protect) +{ +#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED + if (chip == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (chip->os_func_data != NULL) { + ((app_func_arg_t*)chip->os_func_data)->no_protect = !protect; + } +#else + (void)chip; + (void)protect; +#endif + return ESP_OK; +} + // The goal of this part is to manually insert one valid task execution interval, if the time since // last valid interval exceed the limitation (CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS). // diff --git a/components/spi_flash/test_apps/flash_encryption/main/test_flash_encryption.c b/components/spi_flash/test_apps/flash_encryption/main/test_flash_encryption.c index 6ebfa46b523d..0277dd5ebcd3 100644 --- a/components/spi_flash/test_apps/flash_encryption/main/test_flash_encryption.c +++ b/components/spi_flash/test_apps/flash_encryption/main/test_flash_encryption.c @@ -273,6 +273,33 @@ TEST_CASE("test read & write encrypted data(32 bytes alianed address)", "[flash_ free(cmp_normal_buf); free(cmp_encrypt_buf); + + uint32_t size; + esp_flash_get_physical_size(NULL, &size); + + if (size > 0x1000000) { + start = 0x1030000; + TEST_ESP_OK(esp_flash_erase_region(NULL, start, SPI_FLASH_SEC_SIZE)); + start = (start + 31) & (~31); // round up to 32 byte boundary + printf("Test data partition @ 0x%" PRIx32 "\n", (uint32_t) start); + ESP_LOG_BUFFER_HEXDUMP(TAG, plainttext_data, sizeof(plainttext_data), ESP_LOG_INFO); + printf("Encrypted writing......\n"); + TEST_ESP_OK(esp_flash_write_encrypted(NULL, start, plainttext_data, sizeof(plainttext_data))); + + cmp_encrypt_buf = heap_caps_malloc(SPI_FLASH_SEC_SIZE, MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + printf("Encrypted reading......\n"); + TEST_ESP_OK(esp_flash_read_encrypted(NULL, start, cmp_encrypt_buf, SPI_FLASH_SEC_SIZE)); + ESP_LOG_BUFFER_HEXDUMP(TAG, cmp_encrypt_buf, sizeof(plainttext_data), ESP_LOG_INFO); + TEST_ASSERT_EQUAL_HEX8_ARRAY(plainttext_data, cmp_encrypt_buf, sizeof(plainttext_data)); + + cmp_normal_buf = heap_caps_malloc(SPI_FLASH_SEC_SIZE, MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ESP_OK(esp_flash_read(NULL, cmp_normal_buf, start, SPI_FLASH_SEC_SIZE)); + printf("Normal read(esp_flash_read)......\n"); + ESP_LOG_BUFFER_HEXDUMP(TAG, cmp_normal_buf, sizeof(plainttext_data), ESP_LOG_INFO); + + free(cmp_normal_buf); + free(cmp_encrypt_buf); + } } TEST_CASE("test read & write encrypted data(16 bytes alianed but 32 bytes unaligned)", "[flash_encryption]") @@ -305,6 +332,38 @@ TEST_CASE("test read & write encrypted data(16 bytes alianed but 32 bytes unalig free(cmp_normal_buf); free(cmp_encrypt_buf); + + uint32_t size; + esp_flash_get_physical_size(NULL, &size); + if (size > 0x1000000) { + start = 0x1030000; + TEST_ESP_OK(esp_flash_erase_region(NULL, start, SPI_FLASH_SEC_SIZE)); + do { + start++; + } while ((start % 16) != 0); + + if (start % 32 == 0) { + start += 16; + } + printf("Test data partition @ 0x%" PRIx32 "\n", (uint32_t) start); + ESP_LOG_BUFFER_HEXDUMP(TAG, plainttext_data, sizeof(plainttext_data), ESP_LOG_INFO); + printf("Encrypted writing......\n"); + TEST_ESP_OK(esp_flash_write_encrypted(NULL, start, plainttext_data, sizeof(plainttext_data))); + + cmp_encrypt_buf = heap_caps_malloc(SPI_FLASH_SEC_SIZE, MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + printf("Encrypted reading......\n"); + TEST_ESP_OK(esp_flash_read_encrypted(NULL, start, cmp_encrypt_buf, SPI_FLASH_SEC_SIZE)); + ESP_LOG_BUFFER_HEXDUMP(TAG, cmp_encrypt_buf, sizeof(plainttext_data), ESP_LOG_INFO); + TEST_ASSERT_EQUAL_HEX8_ARRAY(plainttext_data, cmp_encrypt_buf, sizeof(plainttext_data)); + + cmp_normal_buf = heap_caps_malloc(SPI_FLASH_SEC_SIZE, MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ESP_OK(esp_flash_read(NULL, cmp_normal_buf, start, SPI_FLASH_SEC_SIZE)); + printf("Normal read(esp_flash_read)......\n"); + ESP_LOG_BUFFER_HEXDUMP(TAG, cmp_normal_buf, sizeof(plainttext_data), ESP_LOG_INFO); + + free(cmp_normal_buf); + free(cmp_encrypt_buf); + } } static const uint8_t large_const_buffer[16432] = { @@ -338,6 +397,27 @@ TEST_CASE("test read & write encrypted data with large buffer(n*64+32+16)", "[fl TEST_ESP_OK(esp_flash_read_encrypted(NULL, start, buf, sizeof(large_const_buffer))); TEST_ASSERT_EQUAL_HEX8_ARRAY(buf, large_const_buffer, sizeof(large_const_buffer)); free(buf); + + uint32_t size; + esp_flash_get_physical_size(NULL, &size); + + if (size > 0x1000000) { + start = 0x1030000; + printf("Test data partition @ 0x%" PRIx32 "\n", (uint32_t) start); + TEST_ESP_OK(esp_flash_erase_region(NULL, start, 5 * 4096)); + printf("Encrypted writing......\n"); + + TEST_ESP_OK(ccomp_timer_start()); + TEST_ESP_OK(esp_flash_write_encrypted(NULL, start, large_const_buffer, sizeof(large_const_buffer))); + write_time = ccomp_timer_stop(); + IDF_LOG_PERFORMANCE(TAG, "Writing speed: %.2f us/KB", (double)(write_time/sizeof(large_const_buffer))*1024); + + buf = (uint8_t*)heap_caps_malloc(sizeof(large_const_buffer), MALLOC_CAP_8BIT); + + TEST_ESP_OK(esp_flash_read_encrypted(NULL, start, buf, sizeof(large_const_buffer))); + TEST_ASSERT_EQUAL_HEX8_ARRAY(buf, large_const_buffer, sizeof(large_const_buffer)); + free(buf); + } } static DRAM_ATTR const uint8_t large_const_buffer_dram[16432] = { diff --git a/components/spi_flash/test_apps/flash_encryption/sdkconfig.ci.release_f8r8 b/components/spi_flash/test_apps/flash_encryption/sdkconfig.ci.release_f8r8 index b31f5907ca34..6fab53cf3ad6 100644 --- a/components/spi_flash/test_apps/flash_encryption/sdkconfig.ci.release_f8r8 +++ b/components/spi_flash/test_apps/flash_encryption/sdkconfig.ci.release_f8r8 @@ -18,3 +18,4 @@ CONFIG_SPIRAM_MODE_OCT=y CONFIG_SPIRAM_TYPE_AUTO=y CONFIG_ESPTOOLPY_OCT_FLASH=y CONFIG_ESPTOOLPY_FLASHMODE_OPI=y +CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y diff --git a/components/spiffs/host_test/main/host_test_spiffs.c b/components/spiffs/host_test/main/host_test_spiffs.c index 4fcfce13c1f9..8a63c1316acf 100644 --- a/components/spiffs/host_test/main/host_test_spiffs.c +++ b/components/spiffs/host_test/main/host_test_spiffs.c @@ -281,29 +281,27 @@ TEST(spiffs, erase_check) init_spiffs(&fs, 5); - for (int boot_iter = 0; boot_iter <= 10000; ++boot_iter) { - for (int write_iter = 0; write_iter < 1000; ++write_iter) { - spiffs_file f = SPIFFS_open(&fs, "/test", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); - if (f < 0) { - fprintf(stderr, "Failed to open file\n"); + for (int write_iter = 0; write_iter < 100; ++write_iter) { + spiffs_file f = SPIFFS_open(&fs, "/test", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); + if (f < 0) { + fprintf(stderr, "Failed to open file\n"); #if !CONFIG_ESP_PARTITION_ERASE_CHECK - TEST_FAIL(); + TEST_FAIL(); #endif - return; - } - const int data_sz = 7 * 1024; - char data[data_sz]; - memset(data, 0x55, data_sz); - int cb = SPIFFS_write(&fs, f, data, data_sz); - if (cb != data_sz) { - fprintf(stderr, "Failed to write file\n"); - TEST_FAIL(); - } - int rc = SPIFFS_close(&fs, f); - if (rc < 0) { - fprintf(stderr, "Failed to close file\n"); - TEST_FAIL(); - } + return; + } + const int data_sz = 7 * 1024; + char data[data_sz]; + memset(data, 0x55, data_sz); + int cb = SPIFFS_write(&fs, f, data, data_sz); + if (cb != data_sz) { + fprintf(stderr, "Failed to write file\n"); + TEST_FAIL(); + } + int rc = SPIFFS_close(&fs, f); + if (rc < 0) { + fprintf(stderr, "Failed to close file\n"); + TEST_FAIL(); } } diff --git a/components/ulp/CMakeLists.txt b/components/ulp/CMakeLists.txt index 058d05922b3a..dbe990e652e0 100644 --- a/components/ulp/CMakeLists.txt +++ b/components/ulp/CMakeLists.txt @@ -78,6 +78,10 @@ if(CONFIG_ULP_COPROC_TYPE_LP_CORE) if(CONFIG_SOC_LP_ADC_SUPPORTED) list(APPEND srcs "lp_core/shared/ulp_lp_core_lp_adc_shared.c") endif() + + if(CONFIG_SOC_LP_VAD_SUPPORTED) + list(APPEND srcs "lp_core/shared/ulp_lp_core_lp_vad_shared.c") + endif() endif() idf_component_register(SRCS ${srcs} diff --git a/components/ulp/cmake/IDFULPProject.cmake b/components/ulp/cmake/IDFULPProject.cmake index 04da71b00c28..fd90cfd87ffb 100644 --- a/components/ulp/cmake/IDFULPProject.cmake +++ b/components/ulp/cmake/IDFULPProject.cmake @@ -126,6 +126,7 @@ function(ulp_apply_default_sources ulp_app_name) "${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_spi.c" "${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_ubsan.c" "${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_adc_shared.c" + "${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c" "${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_critical_section_shared.c") set(target_folder ${IDF_TARGET}) diff --git a/components/ulp/lp_core/include/ulp_lp_core.h b/components/ulp/lp_core/include/ulp_lp_core.h index d737d638aca8..6a0373aefa21 100644 --- a/components/ulp/lp_core/include/ulp_lp_core.h +++ b/components/ulp/lp_core/include/ulp_lp_core.h @@ -22,6 +22,7 @@ extern "C" { #define ULP_LP_CORE_WAKEUP_SOURCE_LP_IO BIT(2) // Enable wake-up by LP IO interrupt #define ULP_LP_CORE_WAKEUP_SOURCE_ETM BIT(3) // Enable wake-up by ETM event #define ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER BIT(4) // Enable wake-up by LP timer +#define ULP_LP_CORE_WAKEUP_SOURCE_LP_VAD BIT(5) // Enable wake-up by LP VAD /** * @brief ULP LP core init parameters diff --git a/components/ulp/lp_core/lp_core.c b/components/ulp/lp_core/lp_core.c index aedcf0e78e25..0efa300ac0f5 100644 --- a/components/ulp/lp_core/lp_core.c +++ b/components/ulp/lp_core/lp_core.c @@ -35,7 +35,7 @@ extern uint32_t _rtc_ulp_memory_start; const static char* TAG = "ulp-lp-core"; -#define WAKEUP_SOURCE_MAX_NUMBER 5 +#define WAKEUP_SOURCE_MAX_NUMBER 6 #define RESET_HANDLER_ADDR (intptr_t)(&_rtc_ulp_memory_start + 0x80 / 4) // Placed after the 0x80 byte long vector table @@ -46,6 +46,9 @@ static uint32_t wakeup_src_sw_to_hw_flag_lookup[WAKEUP_SOURCE_MAX_NUMBER] = { LP_CORE_LL_WAKEUP_SOURCE_LP_IO, LP_CORE_LL_WAKEUP_SOURCE_ETM, LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER, +#if SOC_LP_VAD_SUPPORTED + LP_CORE_LL_WAKEUP_SOURCE_LP_VAD, +#endif }; /* Convert the wake-up sources defined in ulp_lp_core.h to the actual HW wake-up source values */ @@ -130,7 +133,7 @@ esp_err_t ulp_lp_core_run(ulp_lp_core_cfg_t* cfg) } #endif - if (cfg->wakeup_source & (ULP_LP_CORE_WAKEUP_SOURCE_LP_UART | ULP_LP_CORE_WAKEUP_SOURCE_LP_IO)) { + if (cfg->wakeup_source & (ULP_LP_CORE_WAKEUP_SOURCE_LP_UART)) { ESP_LOGE(TAG, "Wake-up source not yet supported"); return ESP_ERR_INVALID_ARG; } diff --git a/components/ulp/lp_core/lp_core/lp_core_utils.c b/components/ulp/lp_core/lp_core/lp_core_utils.c index 8b358741fbb1..d3e8664907b0 100644 --- a/components/ulp/lp_core/lp_core/lp_core_utils.c +++ b/components/ulp/lp_core/lp_core/lp_core_utils.c @@ -14,6 +14,10 @@ #include "hal/pmu_ll.h" #include "hal/uart_ll.h" #include "hal/rtc_io_ll.h" +#if SOC_LP_I2S_SUPPORT_VAD +//For VAD +#include "hal/lp_i2s_ll.h" +#endif #if SOC_LP_TIMER_SUPPORTED #include "hal/lp_timer_ll.h" @@ -56,6 +60,13 @@ void ulp_lp_core_update_wakeup_cause(void) rtcio_ll_clear_interrupt_status(); } +#if SOC_LP_VAD_SUPPORTED + if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_LP_VAD)) { + lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_LP_VAD; + lp_i2s_ll_rx_clear_interrupt_status(&LP_I2S, LP_I2S_LL_EVENT_VAD_DONE_INT); + } +#endif + #if SOC_ETM_SUPPORTED if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_ETM) \ && lp_core_ll_get_etm_wakeup_flag()) { diff --git a/components/ulp/lp_core/shared/include/ulp_lp_core_lp_vad_shared.h b/components/ulp/lp_core/shared/include/ulp_lp_core_lp_vad_shared.h new file mode 100644 index 000000000000..8a37dee54dbd --- /dev/null +++ b/components/ulp/lp_core/shared/include/ulp_lp_core_lp_vad_shared.h @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/lp_i2s_vad.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LP VAD configurations + */ +typedef lp_vad_init_config_t lp_core_lp_vad_cfg_t; + +/** + * @brief State Machine + ┌──────────────────────────────────┐ + │ │ + ┌─────────────┤ speak-activity-listening-state │ ◄───────────────┐ + │ │ │ │ + │ └──────────────────────────────────┘ │ + │ ▲ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ +detected speak activity │ │ detected speak activity │ detected speak activity + >= │ │ >= │ >= +'speak_activity_thresh' │ │ 'min_speak_activity_thresh' │ 'max_speak_activity_thresh' + │ │ │ + │ │ && │ + │ │ │ + │ │ detected non-speak activity │ + │ │ < │ + │ │ 'non_speak_activity_thresh' │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ ┌───────────┴─────────────────────┐ │ + │ │ │ │ + └───────────► │ speak-activity-detected-state ├─────────────────┘ + │ │ + └─┬───────────────────────────────┘ + │ + │ ▲ + │ │ + │ │ + │ │ detected speak activity + │ │ >= + │ │ 'min_speak_activity_thresh' + │ │ + │ │ && + │ │ + │ │ detected non-speak activity + │ │ < + └─────────────────────┘ 'non_speak_activity_thresh' +*/ + +/** + * @brief LP VAD init + * + * @param[in] vad_id VAD ID + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_core_lp_vad_init(lp_vad_t vad_id, const lp_core_lp_vad_cfg_t *init_config); + +/** + * @brief Enable LP VAD + * + * @param[in] vad_id VAD ID + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_core_lp_vad_enable(lp_vad_t vad_id); + +/** + * @brief Disable LP VAD + * + * @param[in] vad_id VAD ID + * @param[in] init_config Initial configurations + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_core_lp_vad_disable(lp_vad_t vad_id); + +/** + * @brief Deinit LP VAD + * + * @param[in] vad_id VAD ID + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment + */ +esp_err_t lp_core_lp_vad_deinit(lp_vad_t vad_id); + +#ifdef __cplusplus +} +#endif diff --git a/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c b/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c new file mode 100644 index 000000000000..db78e7463357 --- /dev/null +++ b/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" +#if SOC_LP_VAD_SUPPORTED +#include "esp_check.h" +#include "esp_err.h" +#include "ulp_lp_core_lp_vad_shared.h" +#if SOC_LP_I2S_SUPPORT_VAD +//For VAD +#include "hal/lp_i2s_ll.h" +#include "hal/lp_i2s_hal.h" +#include "esp_private/lp_i2s_private.h" +#endif //SOC_LP_I2S_SUPPORT_VAD + +//make this available for multi vad id in future +vad_unit_handle_t s_vad_handle; + +esp_err_t lp_core_lp_vad_init(lp_vad_t vad_id, const lp_core_lp_vad_cfg_t *init_config) +{ +#if IS_ULP_COCPU + // Not supported + return ESP_ERR_NOT_SUPPORTED; +#else + esp_err_t ret = lp_i2s_vad_new_unit(vad_id, init_config, &s_vad_handle); + return ret; +#endif +} + +esp_err_t lp_core_lp_vad_enable(lp_vad_t vad_id) +{ +#if IS_ULP_COCPU + // Not supported + return ESP_ERR_NOT_SUPPORTED; +#else + esp_err_t ret = lp_i2s_vad_enable(s_vad_handle); + return ret; +#endif +} + +esp_err_t lp_core_lp_vad_disable(lp_vad_t vad_id) +{ +#if IS_ULP_COCPU + // Not supported + return ESP_ERR_NOT_SUPPORTED; +#else + esp_err_t ret = lp_i2s_vad_disable(s_vad_handle); + return ret; +#endif +} + +esp_err_t lp_core_lp_vad_deinit(lp_vad_t vad_id) +{ +#if IS_ULP_COCPU + // Not supported + return ESP_ERR_NOT_SUPPORTED; +#else + esp_err_t ret = lp_i2s_vad_del_unit(s_vad_handle); + return ret; +#endif +} +#endif /* SOC_LP_VAD_SUPPORTED */ diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt index 63d8f905d7c4..239b78cf330d 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt @@ -20,6 +20,10 @@ if(CONFIG_SOC_LP_ADC_SUPPORTED) list(APPEND app_sources "test_lp_core_adc.c") endif() +if(CONFIG_SOC_LP_VAD_SUPPORTED) + list(APPEND app_sources "test_lp_core_vad.c") +endif() + set(lp_core_sources "lp_core/test_main.c") set(lp_core_sources_counter "lp_core/test_main_counter.c") @@ -46,10 +50,15 @@ if(CONFIG_SOC_LP_ADC_SUPPORTED) set(lp_core_sources_adc "lp_core/test_main_adc.c") endif() +if(CONFIG_SOC_LP_VAD_SUPPORTED) + set(lp_core_sources_vad "lp_core/test_main_vad.c") +endif() + idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "lp_core" REQUIRES ulp unity esp_timer test_utils - WHOLE_ARCHIVE) + WHOLE_ARCHIVE + EMBED_FILES "test_vad_8k.pcm") set(lp_core_exp_dep_srcs ${app_sources}) @@ -79,3 +88,7 @@ endif() if(CONFIG_SOC_LP_ADC_SUPPORTED) ulp_embed_binary(lp_core_test_app_adc "${lp_core_sources_adc}" "${lp_core_exp_dep_srcs}") endif() + +if(CONFIG_SOC_LP_VAD_SUPPORTED) + ulp_embed_binary(lp_core_test_app_vad "${lp_core_sources_vad}" "${lp_core_exp_dep_srcs}") +endif() diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/Kconfig.projbuild b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/Kconfig.projbuild new file mode 100644 index 000000000000..5783fc5daf08 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "Test Configurations" + + config TEST_LP_CORE_VAD_ENABLE + bool "Enable LP VAD test" + default n + help + Enable this to trigger LP VAD test + +endmenu diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_vad.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_vad.c new file mode 100644 index 000000000000..5f6198fe3704 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_vad.c @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +volatile bool vad_wakup; + +int main(void) +{ + vad_wakup = true; + + return 0; +} diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_vad.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_vad.c new file mode 100644 index 000000000000..16a3c059dd8e --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_vad.c @@ -0,0 +1,154 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "unity.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "driver/lp_i2s.h" +#include "driver/lp_i2s_std.h" +#include "driver/i2s_std.h" +#include "ulp_lp_core.h" +#include "ulp_lp_core_lp_vad_shared.h" +#include "lp_core_test_app_vad.h" + +#if CONFIG_TEST_LP_CORE_VAD_ENABLE + +#define TEST_I2S_FRAME_SIZE (128) // Frame numbers in every writing / reading +#define TEST_I2S_TRANS_SIZE (4096) // Trans size + +extern const uint8_t test_vad_pcm_start[] asm("_binary_test_vad_8k_pcm_start"); +extern const uint8_t test_vad_pcm_end[] asm("_binary_test_vad_8k_pcm_end"); +extern const uint8_t lp_core_main_vad_bin_start[] asm("_binary_lp_core_test_app_vad_bin_start"); +extern const uint8_t lp_core_main_vad_bin_end[] asm("_binary_lp_core_test_app_vad_bin_end"); +static const char *TAG = "TEST_VAD"; + +static void load_and_start_lp_core_firmware(ulp_lp_core_cfg_t* cfg, const uint8_t* firmware_start, const uint8_t* firmware_end) +{ + TEST_ASSERT(ulp_lp_core_load_binary(firmware_start, + (firmware_end - firmware_start)) == ESP_OK); + + TEST_ASSERT(ulp_lp_core_run(cfg) == ESP_OK); +} + +void test_lp_vad(lp_vad_t vad_id) +{ + esp_err_t ret = ESP_FAIL; + int pcm_size = test_vad_pcm_end - test_vad_pcm_start; + printf("pcm_size: %d\n", pcm_size); + + lp_i2s_chan_handle_t rx_handle = NULL; + lp_i2s_chan_config_t config = { + .id = 0, + .role = I2S_ROLE_SLAVE, + .threshold = 512, + }; + TEST_ESP_OK(lp_i2s_new_channel(&config, NULL, &rx_handle)); + + i2s_chan_handle_t tx_handle = NULL; + i2s_chan_config_t i2s_channel_config = { + .id = I2S_NUM_0, + .role = I2S_ROLE_MASTER, + .dma_desc_num = 4, + .dma_frame_num = TEST_I2S_FRAME_SIZE, + .auto_clear = false, + }; + TEST_ESP_OK(i2s_new_channel(&i2s_channel_config, &tx_handle, NULL)); + + lp_i2s_std_config_t lp_std_cfg = { + .pin_cfg = { + .bck = 4, + .ws = 5, + .din = 6, + }, + }; + lp_std_cfg.slot_cfg = (lp_i2s_std_slot_config_t)LP_I2S_STD_PCM_SHORT_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + TEST_ESP_OK(lp_i2s_channel_init_std_mode(rx_handle, &lp_std_cfg)); + + i2s_std_config_t i2s_std_config = { + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = GPIO_NUM_7, + .ws = GPIO_NUM_8, + .dout = GPIO_NUM_21, + .din = -1, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + i2s_std_config.clk_cfg = (i2s_std_clk_config_t)I2S_STD_CLK_DEFAULT_CONFIG(16000); + i2s_std_config.slot_cfg = (i2s_std_slot_config_t)I2S_STD_PCM_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &i2s_std_config)); + + // LP VAD Init + lp_vad_init_config_t init_config = { + .lp_i2s_chan = rx_handle, + .vad_config = { + .init_frame_num = 100, + .min_energy_thresh = 100, + .speak_activity_thresh = 10, + .non_speak_activity_thresh = 30, + .min_speak_activity_thresh = 3, + .max_speak_activity_thresh = 100, + }, + }; + TEST_ESP_OK(lp_core_lp_vad_init(0, &init_config)); + + /* Load ULP firmware and start the coprocessor */ + ulp_lp_core_cfg_t cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_VAD, + }; + load_and_start_lp_core_firmware(&cfg, lp_core_main_vad_bin_start, lp_core_main_vad_bin_end); + + uint8_t *txbuf = (uint8_t *)heap_caps_calloc(1, TEST_I2S_TRANS_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(txbuf); + + uint8_t *prebuf = (uint8_t *)heap_caps_calloc(1, TEST_I2S_TRANS_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(prebuf); + + memcpy(prebuf, test_vad_pcm_start, TEST_I2S_TRANS_SIZE); + memcpy(txbuf, test_vad_pcm_start, TEST_I2S_TRANS_SIZE); + + for (int i = 0; i < TEST_I2S_TRANS_SIZE; i++) { + ESP_LOGD(TAG, "prebuf[%d]: %d", i, prebuf[i]); + ESP_LOGD(TAG, "txbuf[%d]: %d", i, txbuf[i]); + } + + size_t bytes_written = 0; + TEST_ESP_OK(i2s_channel_preload_data(tx_handle, prebuf, TEST_I2S_TRANS_SIZE, &bytes_written)); + TEST_ESP_OK(lp_i2s_channel_enable(rx_handle)); + TEST_ESP_OK(lp_core_lp_vad_enable(0)); + TEST_ESP_OK(i2s_channel_enable(tx_handle)); + + ret = i2s_channel_write(tx_handle, txbuf, TEST_I2S_TRANS_SIZE, &bytes_written, 0); + if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) { + TEST_ESP_OK(ret); + } + ESP_LOGD(TAG, "bytes_written: %d", bytes_written); + + while (!ulp_vad_wakup) { + ; + } + + ESP_LOGI(TAG, "wakeup"); + + TEST_ESP_OK(lp_i2s_channel_disable(rx_handle)); + TEST_ESP_OK(lp_i2s_del_channel(rx_handle)); + TEST_ESP_OK(i2s_channel_disable(tx_handle)); + TEST_ESP_OK(i2s_del_channel(tx_handle)); + free(txbuf); + free(prebuf); +} + +TEST_CASE("LP VAD wakeup test", "[lp_core][lp_vad]") +{ + test_lp_vad(0); +} +#endif //CONFIG_TEST_LP_CORE_VAD_ENABLE diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_vad_8k.pcm b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_vad_8k.pcm new file mode 100644 index 000000000000..5b6c32a03731 Binary files /dev/null and b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_vad_8k.pcm differ diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py index 53178dca4e84..33e7b3c9507e 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py @@ -33,6 +33,19 @@ def test_lp_core_xtal(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.esp32p4 +@pytest.mark.lp_i2s +@pytest.mark.parametrize( + 'config', + [ + 'lp_vad', + ], + indirect=True, +) +def test_lp_vad(dut: Dut) -> None: + dut.run_all_single_board_cases(group='lp_vad') + + @pytest.mark.esp32c6 # TODO: Enable LP I2C test for esp32p4 (IDF-9407) @pytest.mark.generic_multi_device diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.default b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.default deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad new file mode 100644 index 000000000000..766d6c83cde5 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.lp_vad @@ -0,0 +1 @@ +CONFIG_TEST_LP_CORE_VAD_ENABLE=y diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/CMakeLists.txt b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/CMakeLists.txt index 9e6a9d16bbbe..a1ca21afaf94 100644 --- a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/CMakeLists.txt +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/CMakeLists.txt @@ -1,7 +1,8 @@ set(app_sources "test_app_main.c" "test_lp_core.c") set(lp_core_sources "lp_core/test_hello_main.c") set(lp_core_sources_panic "lp_core/test_panic_main.c") -set(lp_core_sources_shared_mem "lp_core/test_shared_mem_main.c") +set(lp_core_sources_shared_mem "lp_core/test_shared_mem_main.c") +set(lp_core_sources_lp_rom "lp_core/test_lp_rom_main.c") idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "lp_core" @@ -13,3 +14,7 @@ set(lp_core_exp_dep_srcs ${app_sources}) ulp_embed_binary(lp_core_test_app "${lp_core_sources}" "${lp_core_exp_dep_srcs}") ulp_embed_binary(lp_core_test_app_panic "${lp_core_sources_panic}" "${lp_core_exp_dep_srcs}") ulp_embed_binary(lp_core_test_app_shared_mem "${lp_core_sources_shared_mem}" "${lp_core_exp_dep_srcs}") + +if(CONFIG_ESP_ROM_HAS_LP_ROM) + ulp_embed_binary(lp_core_test_app_lp_rom "${lp_core_sources_lp_rom}" "${lp_core_exp_dep_srcs}") +endif() diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_lp_rom_main.c b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_lp_rom_main.c new file mode 100644 index 000000000000..6a99e116f74e --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_lp_rom_main.c @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "soc/soc.h" +#include "ulp_lp_core_print.h" +#include + +void assert_function_in_rom(void *func) +{ + if ((intptr_t)func < SOC_LP_ROM_LOW || (intptr_t)func > SOC_LP_ROM_HIGH) { + abort(); + } +} + +static void test_memset(void) +{ +#define TEST_MEMSET_VAL 0xAB + assert_function_in_rom(memset); + + lp_core_printf("Testing memset\n"); + uint8_t test_buf[100]; + + memset(test_buf, TEST_MEMSET_VAL, sizeof(test_buf)); + + for (int i = 0; i < sizeof(test_buf); i++) { + if (test_buf[i] != TEST_MEMSET_VAL) { + lp_core_printf("test_buf[%d]: 0x%X != 0x%X\n", i, test_buf[i], TEST_MEMSET_VAL); + abort(); + } + } +} + +static void test_memcpy(void) +{ +#define TEST_MEMCPY_VAL 0xAC +#define TEST_SIZE 100 + + assert_function_in_rom(memcpy); + lp_core_printf("Testing memcpy\n"); + uint8_t test_buf_a[TEST_SIZE]; + memset(test_buf_a, TEST_MEMCPY_VAL, TEST_SIZE); + + uint8_t test_buf_b[TEST_SIZE]; + + memcpy(test_buf_b, test_buf_a, TEST_SIZE); + + for (int i = 0; i < TEST_SIZE; i++) { + if (test_buf_b[i] != TEST_MEMCPY_VAL) { + lp_core_printf("test_buf_b[%d]: 0x%X != 0x%X\n", i, test_buf_b[i], TEST_MEMCPY_VAL); + abort(); + } + } +} + +static void test_abs(void) +{ + assert_function_in_rom(abs); + lp_core_printf("Testing abs\n"); + if (abs(-123) != 123) { + lp_core_printf("Failed abs() test\n"); + abort(); + } +} + +volatile bool lp_rom_test_finished; + +int main(void) +{ + // Test a misc of ROM functions to catch any regression with LD file updates + test_memset(); + test_memcpy(); + test_abs(); + + lp_core_printf("ULP: all tests passed\n"); + lp_rom_test_finished = true; + + return 0; +} diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/test_lp_core.c b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/test_lp_core.c index e21d52afbda9..3567f4a65f71 100644 --- a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/test_lp_core.c +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/test_lp_core.c @@ -19,6 +19,10 @@ #include "ulp_lp_core_memory_shared.h" #include "test_shared.h" +#if ESP_ROM_HAS_LP_ROM +#include "lp_core_test_app_lp_rom.h" +#endif + extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_test_app_bin_start"); extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_test_app_bin_end"); @@ -28,6 +32,11 @@ extern const uint8_t lp_core_panic_bin_end[] asm("_binary_lp_core_test_app_pan extern const uint8_t lp_core_shared_mem_bin_start[] asm("_binary_lp_core_test_app_shared_mem_bin_start"); extern const uint8_t lp_core_shared_mem_bin_end[] asm("_binary_lp_core_test_app_shared_mem_bin_end"); +#if ESP_ROM_HAS_LP_ROM +extern const uint8_t lp_core_lp_rom_bin_start[] asm("_binary_lp_core_test_app_lp_rom_bin_start"); +extern const uint8_t lp_core_lp_rom_bin_end[] asm("_binary_lp_core_test_app_lp_rom_bin_end"); +#endif + static void load_and_start_lp_core_firmware(ulp_lp_core_cfg_t* cfg, const uint8_t* firmware_start, const uint8_t* firmware_end) { TEST_ASSERT(ulp_lp_core_load_binary(firmware_start, @@ -93,3 +102,24 @@ TEST_CASE("LP-Core Shared-mem", "[lp_core]") printf("HP shared memory test passed\n"); } + +#if ESP_ROM_HAS_LP_ROM +TEST_CASE("LP-Core LP-ROM", "[lp_core]") +{ + /* Load ULP firmware and start the coprocessor */ + ulp_lp_core_cfg_t cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, + }; + + TEST_ASSERT(ulp_lp_core_load_binary(lp_core_lp_rom_bin_start, (lp_core_lp_rom_bin_end - lp_core_lp_rom_bin_start)) == ESP_OK); + + TEST_ASSERT(ulp_lp_core_run(&cfg) == ESP_OK); + // Actual test output on UART is checked by pytest, not unity test-case + // We simply wait to allow the lp-core to run once + while (!ulp_lp_rom_test_finished) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + printf("LP ROM test passed\n"); +} +#endif diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py b/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py index b21e6e3e3589..1da728516544 100644 --- a/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py @@ -47,3 +47,12 @@ def test_lp_core_shared_mem(dut: Dut) -> None: dut.expect_exact('ULP shared memory test passed') dut.expect_exact('HP shared memory test passed') + + +@pytest.mark.esp32p4 +@pytest.mark.generic +def test_lp_core_lp_rom(dut: Dut) -> None: + dut.expect_exact('Press ENTER to see the list of tests') + dut.write('"LP-Core LP-ROM"') + dut.expect_exact('ULP: all tests passed') + dut.expect_exact('LP ROM test passed') diff --git a/components/usb/CMakeLists.txt b/components/usb/CMakeLists.txt index 8f2ab8dc12ba..f81514661950 100644 --- a/components/usb/CMakeLists.txt +++ b/components/usb/CMakeLists.txt @@ -30,7 +30,8 @@ if(CONFIG_SOC_USB_OTG_SUPPORTED) endif() if(CONFIG_USB_HOST_HUBS_SUPPORTED) - list(APPEND srcs "ext_hub.c") + list(APPEND srcs "ext_hub.c" + "ext_port.c") endif() idf_component_register(SRCS ${srcs} diff --git a/components/usb/Kconfig b/components/usb/Kconfig index 1c333f870b82..376b7fc58c15 100644 --- a/components/usb/Kconfig +++ b/components/usb/Kconfig @@ -112,6 +112,63 @@ menu "USB-OTG" help Enables support for connecting multiple Hubs simultaneously. + menu "Downstream Port configuration" + depends on USB_HOST_HUBS_SUPPORTED + + config USB_HOST_EXT_PORT_SUPPORT_LS + depends on IDF_EXPERIMENTAL_FEATURES + bool "Support LS" + default n + help + Enables support of Low-speed devices, connected through the external Hub. + + config USB_HOST_EXT_PORT_RESET_ATTEMPTS + depends on IDF_EXPERIMENTAL_FEATURES + # Invisible config option + # Todo: IDF-11283 + int + default 1 + help + Amount of attempts to reset the device. + + The default value is 1. + + config USB_HOST_EXT_PORT_RESET_RECOVERY_DELAY_MS + int "Reset recovery delay in ms" + default 30 + help + After a port stops driving the reset signal, the USB 2.0 specification requires that + the "USB System Software guarantees a minimum of 10 ms for reset recovery" before the + attached device is expected to respond to data transfers (see USB 2.0 chapter 7.1.7.3 for + more details). + The device may ignore any data transfers during the recovery interval. + + The default value is set to 30 ms to be safe. + + config USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_ENABLE + bool "Custom bPwrOn2PwrGood value" + default n + help + Enables the possibility to configure custom time for the power-on sequence on a port + until power is good on that port. + + When enabled, applies the custom PwrOn2PwrGood delay. + When disabled, applies the PwrOn2PwrGood value from the Hub Descriptor. + + config USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_MS + depends on USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_ENABLE + int "PwrOn2PwrGood delay in ms" + default 100 + range 0 5000 + help + Custom value of delay from the time the power-on sequence begins on a port + until power is good on that port. + Value 0 is used for a hub with no power switches. + + The default value is 100 ms. + + endmenu #Downstream Port configuration + endmenu #Hub Driver Configuration config USB_HOST_ENABLE_ENUM_FILTER_CALLBACK diff --git a/components/usb/enum.c b/components/usb/enum.c index ec18294c514e..2024c09ee518 100644 --- a/components/usb/enum.c +++ b/components/usb/enum.c @@ -765,9 +765,15 @@ static esp_err_t control_response_handling(enum_stage_t stage) usb_transfer_t *ctrl_xfer = &p_enum_driver->constant.urb->transfer; if (ctrl_xfer->status != USB_TRANSFER_STATUS_COMPLETED) { - ESP_LOGE(ENUM_TAG, "Bad transfer status %d: %s", - ctrl_xfer->status, - enum_stage_strings[stage]); + if (ctrl_xfer->status == USB_TRANSFER_STATUS_STALL && + stage >= ENUM_STAGE_CHECK_SHORT_LANGID_TABLE && + stage <= ENUM_STAGE_CHECK_FULL_SER_STR_DESC) { + // String Descriptor request could be STALLed, if the device doesn't have them + } else { + ESP_LOGE(ENUM_TAG, "Bad transfer status %d: %s", + ctrl_xfer->status, + enum_stage_strings[stage]); + } return ret; } @@ -1015,10 +1021,6 @@ static bool set_next_stage(bool last_stage_pass) next_stage = last_stage + 1; } } else { - ESP_LOGE(ENUM_TAG, "[%d:%d] %s FAILED", - p_enum_driver->single_thread.parent_dev_addr, - p_enum_driver->single_thread.parent_port_num, - enum_stage_strings[last_stage]); // These stages cannot fail assert(last_stage != ENUM_STAGE_SET_ADDR_RECOVERY && last_stage != ENUM_STAGE_SELECT_CONFIG && @@ -1055,6 +1057,10 @@ static bool set_next_stage(bool last_stage_pass) break; default: // Stage is not allowed to failed. Cancel enumeration. + ESP_LOGE(ENUM_TAG, "[%d:%d] %s FAILED", + p_enum_driver->single_thread.parent_dev_addr, + p_enum_driver->single_thread.parent_port_num, + enum_stage_strings[last_stage]); next_stage = ENUM_STAGE_CANCEL; break; } diff --git a/components/usb/ext_hub.c b/components/usb/ext_hub.c index fb20242f7071..8b02f4191f14 100644 --- a/components/usb/ext_hub.c +++ b/components/usb/ext_hub.c @@ -5,18 +5,16 @@ */ #include #include +#include "sdkconfig.h" #include "esp_err.h" #include "esp_log.h" #include "esp_heap_caps.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" +#include "esp_private/critical_section.h" #include "usb_private.h" #include "ext_hub.h" +#include "ext_port.h" #include "usb/usb_helpers.h" -typedef struct ext_port_s *ext_port_hdl_t; /* This will be implemented during ext_port driver implementation */ - #define EXT_HUB_MAX_STATUS_BYTES_SIZE (sizeof(uint32_t)) #define EXT_HUB_STATUS_CHANGE_FLAG (1 << 0) #define EXT_HUB_STATUS_PORT1_CHANGE_FLAG (1 << 1) @@ -153,7 +151,6 @@ typedef struct { } ext_hub_driver_t; static ext_hub_driver_t *p_ext_hub_driver = NULL; -static portMUX_TYPE ext_hub_driver_lock = portMUX_INITIALIZER_UNLOCKED; const char *EXT_HUB_TAG = "EXT_HUB"; @@ -161,10 +158,11 @@ const char *EXT_HUB_TAG = "EXT_HUB"; // ------------------------------- Helpers ------------------------------------- // ----------------------------------------------------------------------------- -#define EXT_HUB_ENTER_CRITICAL() portENTER_CRITICAL(&ext_hub_driver_lock) -#define EXT_HUB_EXIT_CRITICAL() portEXIT_CRITICAL(&ext_hub_driver_lock) -#define EXT_HUB_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&ext_hub_driver_lock) -#define EXT_HUB_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&ext_hub_driver_lock) +DEFINE_CRIT_SECTION_LOCK_STATIC(ext_hub_driver_lock); +#define EXT_HUB_ENTER_CRITICAL() esp_os_enter_critical(&ext_hub_driver_lock) +#define EXT_HUB_EXIT_CRITICAL() esp_os_exit_critical(&ext_hub_driver_lock) +#define EXT_HUB_ENTER_CRITICAL_SAFE() esp_os_enter_critical_safe(&ext_hub_driver_lock) +#define EXT_HUB_EXIT_CRITICAL_SAFE() esp_os_exit_critical_safe(&ext_hub_driver_lock) #define EXT_HUB_CHECK(cond, ret_val) ({ \ if (!(cond)) { \ @@ -396,8 +394,15 @@ static void device_error(ext_hub_dev_t *ext_hub_dev) static esp_err_t device_port_new(ext_hub_dev_t *ext_hub_dev, uint8_t port_idx) { + ext_port_config_t port_config = { + .ext_hub_hdl = (ext_hub_handle_t) ext_hub_dev, + .parent_dev_hdl = ext_hub_dev->constant.dev_hdl, + .parent_port_num = port_idx + 1, + .port_power_delay_ms = ext_hub_dev->constant.hub_desc->bPwrOn2PwrGood * 2, + }; + assert(p_ext_hub_driver->constant.port_driver); - esp_err_t ret = p_ext_hub_driver->constant.port_driver->new (NULL, (void**) &ext_hub_dev->constant.ports[port_idx]); + esp_err_t ret = p_ext_hub_driver->constant.port_driver->new (&port_config, (void**) &ext_hub_dev->constant.ports[port_idx]); if (ret != ESP_OK) { ESP_LOGE(EXT_HUB_TAG, "[%d:%d] Port allocation error: %s", ext_hub_dev->constant.dev_addr, port_idx + 1, esp_err_to_name(ret)); goto fail; @@ -418,7 +423,7 @@ static esp_err_t device_port_free(ext_hub_dev_t *ext_hub_dev, uint8_t port_idx) assert(ext_hub_dev->single_thread.maxchild != 0); assert(p_ext_hub_driver->constant.port_driver); - esp_err_t ret = p_ext_hub_driver->constant.port_driver->free(ext_hub_dev->constant.ports[port_idx]); + esp_err_t ret = p_ext_hub_driver->constant.port_driver->del(ext_hub_dev->constant.ports[port_idx]); if (ret != ESP_OK) { ESP_LOGE(EXT_HUB_TAG, "[%d:%d] Unable to free port: %s", ext_hub_dev->constant.dev_addr, port_idx + 1, esp_err_to_name(ret)); @@ -523,7 +528,7 @@ static esp_err_t device_alloc(device_config_t *config, ext_hub_dev_t **ext_hub_d usb_device_info_t dev_info; ESP_ERROR_CHECK(usbh_dev_get_info(config->dev_hdl, &dev_info)); if (dev_info.parent.dev_hdl) { - ESP_LOGW(EXT_HUB_TAG, "Multiple Hubs not supported, use menuconfig to enable feature"); + ESP_LOGW(EXT_HUB_TAG, "Multiple Hubs support disabled, Hub device was not initialized"); ret = ESP_ERR_NOT_SUPPORTED; goto fail; } @@ -1038,6 +1043,7 @@ static void handle_device(ext_hub_dev_t *ext_hub_dev) // FSM for external Hub switch (ext_hub_dev->single_thread.stage) { case EXT_HUB_STAGE_IDLE: + stage_pass = true; break; case EXT_HUB_STAGE_GET_DEVICE_STATUS: case EXT_HUB_STAGE_GET_HUB_DESCRIPTOR: @@ -1118,8 +1124,7 @@ esp_err_t ext_hub_install(const ext_hub_config_t *config) { esp_err_t ret; ext_hub_driver_t *ext_hub_drv = heap_caps_calloc(1, sizeof(ext_hub_driver_t), MALLOC_CAP_DEFAULT); - SemaphoreHandle_t mux_lock = xSemaphoreCreateMutex(); - if (ext_hub_drv == NULL || mux_lock == NULL) { + if (ext_hub_drv == NULL) { ret = ESP_ERR_NO_MEM; goto err; } @@ -1151,9 +1156,6 @@ esp_err_t ext_hub_install(const ext_hub_config_t *config) return ESP_OK; err: - if (mux_lock != NULL) { - vSemaphoreDelete(mux_lock); - } heap_caps_free(ext_hub_drv); return ret; } @@ -1672,7 +1674,7 @@ esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, esp_err_t ext_hub_set_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature) { EXT_HUB_ENTER_CRITICAL(); - EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_INVALID_STATE); + EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_NOT_ALLOWED); EXT_HUB_EXIT_CRITICAL(); esp_err_t ret; @@ -1701,7 +1703,7 @@ esp_err_t ext_hub_set_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_nu esp_err_t ext_hub_clear_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature) { EXT_HUB_ENTER_CRITICAL(); - EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_INVALID_STATE); + EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_NOT_ALLOWED); EXT_HUB_EXIT_CRITICAL(); esp_err_t ret; @@ -1730,7 +1732,7 @@ esp_err_t ext_hub_clear_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_ esp_err_t ext_hub_get_port_status(ext_hub_handle_t ext_hub_hdl, uint8_t port_num) { EXT_HUB_ENTER_CRITICAL(); - EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_INVALID_STATE); + EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_NOT_ALLOWED); EXT_HUB_EXIT_CRITICAL(); esp_err_t ret; diff --git a/components/usb/ext_port.c b/components/usb/ext_port.c new file mode 100644 index 000000000000..efce9ed7de33 --- /dev/null +++ b/components/usb/ext_port.c @@ -0,0 +1,1404 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "usb_private.h" +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_ch11.h" +#include "usbh.h" +#include "ext_port.h" +#include "usb/usb_helpers.h" + +// Amount of attempts to reset the port with a device in case of a failure +#if (CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS) +#define EXT_PORT_RESET_ATTEMPTS CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS +#else +#define EXT_PORT_RESET_ATTEMPTS 1 +#endif +// Delay in ms after sending the SetFeature() class specific request +#define EXT_PORT_RESET_RECOVERY_DELAY_MS CONFIG_USB_HOST_EXT_PORT_RESET_RECOVERY_DELAY_MS +#define EXT_PORT_POWER_ON_CUSTOM_DELAY CONFIG_USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_ENABLE +#define EXT_PORT_POWER_ON_CUSTOM_DELAY_MS CONFIG_USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_MS + +/** + * @brief External Port driver action flags + */ +typedef enum { + PORT_ACTION_HANDLE = (1 << 0), /**< Port requires handling */ + PORT_ACTION_DISABLE = (1 << 1), /**< Disable port */ + PORT_ACTION_RECYCLE = (1 << 2), /**< Recycle port */ + PORT_ACTION_RESET = (1 << 3), /**< Reset port */ + PORT_ACTION_GET_STATUS = (1 << 4), /**< Get status request */ +} port_action_t; + +/** + * @brief State of the device, attached to the port + */ +typedef enum { + PORT_DEV_NOT_PRESENT = 0, + PORT_DEV_PRESENT +} port_dev_state_t; + +/** + * @brief Object representing a single External Port + */ +struct ext_port_s { + /**< Single thread members don't require a critical section so long as they are never accessed from multiple threads */ + TAILQ_ENTRY(ext_port_s) tailq_entry; + union { + struct { + uint32_t in_pending_list: 1; /**< Port in pending list */ + uint32_t status_lock: 1; /**< Ports' status lock. Parent Hub processes receiving new status */ + uint32_t status_outdated: 1; /**< Ports' has changed and status is not valid. Get port status is required */ + uint32_t is_gone: 1; /**< Ports' parent Hub is gone */ + uint32_t has_enum_device: 1; /**< Port has an enumerated device */ + uint32_t waiting_recycle: 1; /**< Port is waiting to be recycled */ + uint32_t waiting_free: 1; /**< Port is waiting to be freed */ + uint32_t reserved25: 25; /**< Reserved */ + }; + uint32_t val; /**< Ports' flags value */ + } flags; /**< Ports' flags */ + uint32_t action_flags; /**< Ports' action flags */ + usb_hub_port_state_t state; /**< Ports' state */ + usb_port_status_t status; /**< Ports' status data */ + port_dev_state_t dev_state; /**< Ports' device state */ + uint8_t dev_reset_attempts; /**< Ports' device reset failure */ + + struct { + // Ports' parent info for optimisation and better debug output + usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ + uint8_t parent_dev_addr; /**< Ports' parent device bus address */ + // Port related constant members + ext_hub_handle_t ext_hub_hdl; /**< Ports' parent External Hub handle */ + uint8_t port_num; /**< Ports' parent External Hub Port number */ + int power_on_delay_ms; /**< Ports' Power on time to Power Good, ms */ + } constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ +}; + +/** + * @brief Definition of the type for the struct, representing a single External Port + */ +typedef struct ext_port_s ext_port_t; + +/** + * @brief Object representing the External Port Driver + */ +typedef struct { + struct { + TAILQ_HEAD(ext_ports, ext_port_s) pending_tailq; /**< External Ports require handling */ + } single_thread; /**< Single thread members don't require a critical section so long as they are never accessed from multiple threads */ + + struct { + ext_port_cb_t proc_req_cb; /**< External Port process callback */ + void *proc_req_cb_arg; /**< External Port process callback argument */ + ext_port_event_cb_t event_cb; /**< External Port event callback */ + void *event_cb_arg; /**< External Port event callback argument */ + } constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ +} ext_port_driver_t; + +static ext_port_driver_t *p_ext_port_driver = NULL; + +const char *EXT_PORT_TAG = "EXT_PORT"; + +// ----------------------------------------------------------------------------- +// --------------------------- Helpers & Macros -------------------------------- +// ----------------------------------------------------------------------------- + +#define EXT_PORT_CHECK(cond, ret_val) ({ \ + if (!(cond)) { \ + return (ret_val); \ + } \ +}) + +/** + * @brief Port connection status + * + * @param[in] ext_port Port object + * @return + * - true Port has a connection + * - false Port doesn't have a connection + */ +static inline bool port_has_connection(ext_port_t *ext_port) +{ + return ext_port->status.wPortStatus.PORT_CONNECTION ? true : false; +} + +/** + * @brief Port power status + * + * @param[in] ext_port Port object + * @return + * - true Port is powered + * - false Port in not powered + */ +static inline bool port_is_powered(ext_port_t *ext_port) +{ + return ext_port->status.wPortStatus.PORT_POWER ? true : false; +} + +/** + * @brief Port reset status + * + * @param[in] ext_port Port object + * @return + * - true Port is in reset + * - false Port is not in reset + */ +static inline bool port_is_in_reset(ext_port_t *ext_port) +{ + return ext_port->status.wPortStatus.PORT_RESET ? true : false; +} + +/** + * @brief Port enable status + * + * @param[in] ext_port Port object + * @return + * - true Port is enabled + * - false Port is disabled + */ +static inline bool port_is_enabled(ext_port_t *ext_port) +{ + return ext_port->status.wPortStatus.PORT_ENABLE ? true : false; +} + +/** + * @brief Port connection status changed + * + * @param[in] ext_port Port object + * @return + * - true Port connection changed + * - false Port connection not changed + */ +static inline bool port_has_changed_connection(ext_port_t * ext_port) +{ + return ext_port->status.wPortChange.C_PORT_CONNECTION ? true : false; +} + +/** + * @brief Port enabled status changed + * + * @param[in] ext_port Port object + * @return + * - true Port has error state and was disabled + * - false Port operates normally + */ +static inline bool port_has_changed_from_enable(ext_port_t *ext_port) +{ + return ext_port->status.wPortChange.C_PORT_ENABLE ? true : false; +} + +/** + * @brief Port reset status changed + * + * @param[in] ext_port Port object + * @return + * - true Port has finished the reset + * - false Port hasn't finished the reset + */ +static inline bool port_has_finished_reset(ext_port_t *ext_port) +{ + return ext_port->status.wPortChange.C_PORT_RESET ? true : false; +} + +// ----------------------------------------------------------------------------- +// ------------------------ Parent Hub related logic --------------------------- +// ----------------------------------------------------------------------------- + +/** + * @brief Request the port status for the port object + * + * @note This call uses the External Hub Driver API + * + * @param[in] ext_port Port object + * @return + * - ESP_ERR_NOT_ALLOWED: The External Hub Driver has not been installed + * - ESP_ERR_INVALID_ARG: The parent hub handle couldn't be NULL + * - ESP_ERR_INVALID_SIZE: The port number should be in a range: [1, .. , bNbrPort] + * - ESP_ERR_INVALID_STATE: The parent hub device wasn't configured + * - ESP_OK: Status has been requested + */ +static esp_err_t port_request_status(ext_port_t* ext_port) +{ + esp_err_t ret = ext_hub_get_port_status(ext_port->constant.ext_hub_hdl, ext_port->constant.port_num); + if (ret != ESP_OK) { + return ret; + } + // Port is requesting status, lock the status + ext_port->flags.status_lock = 1; + return ret; +} + +/** + * @brief Sets the feature to the port + * + * @note This call uses the External Hub Driver API + * + * @param[in] ext_port Port object + * @param[in] feature Port feature to set + * @return + * - ESP_ERR_NOT_ALLOWED: The External Hub Driver has not been installed + * - ESP_ERR_INVALID_ARG: The parent hub handle couldn't be NULL + * - ESP_ERR_INVALID_SIZE: The port number should be in a range: [1, .. , bNbrPort] + * - ESP_ERR_INVALID_STATE: The parent hub device wasn't configured + * - ESP_OK: SetPortFeature() has been requested + */ +static esp_err_t port_set_feature(ext_port_t *ext_port, const usb_hub_port_feature_t feature) +{ + esp_err_t ret = ext_hub_set_port_feature(ext_port->constant.ext_hub_hdl, + ext_port->constant.port_num, + feature); + if (ret != ESP_OK) { + return ret; + } + // Every set feature requires status update + ext_port->flags.status_outdated = 1; + switch (feature) { + case USB_FEATURE_PORT_POWER: + // PowerOn to PowerGood delay for port + vTaskDelay(pdMS_TO_TICKS(ext_port->constant.power_on_delay_ms)); + break; + case USB_FEATURE_PORT_RESET: + // Port has reset, give the port some time to recover + vTaskDelay(pdMS_TO_TICKS(EXT_PORT_RESET_RECOVERY_DELAY_MS)); + break; + default: + break; + } + return ret; +} + +/** + * @brief Clears the feature to the port + * + * @note This call uses the External Hub Driver API + * + * @param[in] ext_port Port object + * @param[in] feature Port feature to set + * @return + * - ESP_ERR_NOT_ALLOWED: The External Hub Driver has not been installed + * - ESP_ERR_INVALID_ARG: The parent hub handle couldn't be NULL + * - ESP_ERR_INVALID_SIZE: The port number should be in a range: [1, .. , bNbrPort] + * - ESP_ERR_INVALID_STATE: The parent hub device wasn't configured + * - ESP_OK: ClearPortFeature() has been requested + */ +static esp_err_t port_clear_feature(ext_port_t *ext_port, const usb_hub_port_feature_t feature) +{ + esp_err_t ret = ext_hub_clear_port_feature(ext_port->constant.ext_hub_hdl, + ext_port->constant.port_num, + feature); + if (ret != ESP_OK) { + return ret; + } + // Every clearing feature requires status update + ext_port->flags.status_outdated = 1; + return ret; +} + +// ----------------------------------------------------------------------------- +// ---------------------------- Internal logic --------------------------------- +// ----------------------------------------------------------------------------- +/** + * @brief Port set actions + * + * @note + * - The External Port Driver is a single threaded driver + * - All calls are made from USB Host related task + * - Does not need critical section + * - Always requires processing + * + * @param[in] ext_port Port object + * @param[in] action_flags Action flags (could not be 0) + */ +static void port_set_actions(ext_port_t *ext_port, uint32_t action_flags) +{ + assert(action_flags != 0); // Sanity check + + // Check if port is not in the pending list + if (!ext_port->flags.in_pending_list) { + // Add port to pending list + ext_port->flags.in_pending_list = 1; + TAILQ_INSERT_TAIL(&p_ext_port_driver->single_thread.pending_tailq, ext_port, tailq_entry); + } + + ext_port->action_flags |= action_flags; + p_ext_port_driver->constant.proc_req_cb(p_ext_port_driver->constant.proc_req_cb_arg); +} + +/** + * @brief Stops the handling and remove the port from the pending list + * + * When the ports parent hub device has been removed, the port could be freed immediately + * if it doesn't have an inserted device. + * For this purpose port object should be removed from the pending + * list and the action flags should be dropped. + * + * @note + * - The External Port Driver is a single threaded driver + * - All calls are made from USB Host related task + * - Does not need critical section + * - Does not require processing + * + * @param[in] ext_port Port object + */ +static void port_stop_handling(ext_port_t *ext_port) +{ + // Check if port is in the pending list + if (ext_port->flags.in_pending_list) { + // Add port to pending list + ext_port->flags.in_pending_list = 0; + TAILQ_REMOVE(&p_ext_port_driver->single_thread.pending_tailq, ext_port, tailq_entry); + } + if (ext_port->action_flags) { + // Port should be freed but has actions + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Port stop handling. Dropped actions 0x%"PRIx32"", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->action_flags); + } + ext_port->action_flags = 0; +} + +/** + * @brief Port event propagation + * + * Propagating the following events to the Hub Driver: + * - EXT_PORT_CONNECTED + * - EXT_PORT_RESET_COMPLETED + * - EXT_PORT_DISCONNECTED + * + * Filling all the event data parameters, according to the event. + * + * @param[in] ext_port Port object + * @param[in] event Port event + */ +static void port_event(ext_port_t *ext_port, ext_port_event_t event) +{ + ext_port_event_data_t event_data = { + .event = event, + }; + switch (event) { + case EXT_PORT_CONNECTED: + event_data.connected.ext_hub_hdl = ext_port->constant.ext_hub_hdl; + event_data.connected.parent_dev_hdl = ext_port->constant.parent_dev_hdl; + event_data.connected.parent_port_num = ext_port->constant.port_num; + break; + case EXT_PORT_RESET_COMPLETED: + event_data.reset_completed.parent_dev_hdl = ext_port->constant.parent_dev_hdl; + event_data.reset_completed.parent_port_num = ext_port->constant.port_num; + break; + case EXT_PORT_DISCONNECTED: + event_data.disconnected.parent_dev_hdl = ext_port->constant.parent_dev_hdl; + event_data.disconnected.parent_port_num = ext_port->constant.port_num; + break; + default: + // Should never occur + abort(); + break; + } + + p_ext_port_driver->constant.event_cb(&event_data, p_ext_port_driver->constant.event_cb_arg); +} + +/** + * @brief Returns first port from the pending list + * + * @return + * - Port object pointer. NULL if no ports in pending list. + */ +static ext_port_t *get_port_from_pending_list(void) +{ + ext_port_t *ext_port = NULL; + if (!TAILQ_EMPTY(&p_ext_port_driver->single_thread.pending_tailq)) { + ext_port = TAILQ_FIRST(&p_ext_port_driver->single_thread.pending_tailq); + } + return ext_port; +} + +/** + * @brief Allocates port object + * + * Allocates new por object with following parameters: + * - Port state: USB_PORT_STATE_NOT_CONFIGURED + * - Port device status: PORT_DEV_NOT_PRESENT + * + * @param[in] ext_hub_hdl Ports' parent hub handle + * @param[in] parent_dev_hdl Ports' parent device handle + * @param[in] parent_port_num Ports' parent port number + * @param[in] port_delay_ms Ports' Power on time to Power Good, ms + * @param[out] port_obj Port objects' pointer + * @return + * - ESP_ERR_INVALID_ARG: Unable to allocate the port object: parent hub handle and parent device handle must be not NULL + * - ESP_ERR_NO_MEM: Unable to allocate the port object: no memory + * - ESP_ERR_NOT_FINISHED: Unable to allocate the port object: parent device is not available + * - ESP_OK: Port object created successfully + */ +static esp_err_t port_alloc(ext_hub_handle_t ext_hub_hdl, usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num, uint16_t port_delay_ms, ext_port_t **port_obj) +{ + uint8_t parent_dev_addr = 0; + EXT_PORT_CHECK(ext_hub_hdl != NULL && parent_dev_hdl != NULL, ESP_ERR_INVALID_ARG); + // This is the one exception from the requirement to use only the Ext Hub Driver API. + // TODO: IDF-10023 Move responsibility of parent-child tree building to Hub Driver instead of USBH + EXT_PORT_CHECK(usbh_dev_get_addr(parent_dev_hdl, &parent_dev_addr) == ESP_OK, ESP_ERR_NOT_FINISHED); + + ext_port_t *ext_port = heap_caps_calloc(1, sizeof(ext_port_t), MALLOC_CAP_DEFAULT); + if (ext_port == NULL) { + return ESP_ERR_NO_MEM; + } + + ext_port->constant.parent_dev_hdl = parent_dev_hdl; + ext_port->constant.parent_dev_addr = parent_dev_addr; + ext_port->constant.ext_hub_hdl = ext_hub_hdl; + ext_port->constant.port_num = parent_port_num; +#if (EXT_PORT_POWER_ON_CUSTOM_DELAY) + ext_port->constant.power_on_delay_ms = EXT_PORT_POWER_ON_CUSTOM_DELAY_MS; +#else + // We don't need any additional delay in case port_delay_ms == 0, because this usually means + // that parent Hub device has no power switches + ext_port->constant.power_on_delay_ms = port_delay_ms; +#endif // EXT_PORT_POWER_ON_CUSTOM_DELAY + + ext_port->state = USB_PORT_STATE_NOT_CONFIGURED; + ext_port->dev_state = PORT_DEV_NOT_PRESENT; + + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Port has been added (PwrOn2PwrGood=%d ms)", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->constant.power_on_delay_ms); + + *port_obj = ext_port; + return ESP_OK; +} + +/** + * @brief Port object handling complete + * + * @note This is the final stage of port object handling. + * After port being handled, the port object: + * - is removed from the pending list + * - is freed, is the port gone or port object waiting to be freed + * + * The final stage is parent notification about port object handling completion to enable the EP IN + * + * @param[in] ext_port Port object + * @return + * - ESP_OK: Port object handle completed + */ +static esp_err_t handle_complete(ext_port_t *ext_port) +{ + bool all_ports_were_handled = true; + bool has_pending_ports = false; + + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Port is %s", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->flags.is_gone ? "gone" : + (ext_port->dev_state == PORT_DEV_PRESENT) ? "active" : "idle"); + + assert(ext_port->flags.is_gone == 0); // Handle complete could be called only on port that is still available + assert(ext_port->flags.waiting_free == 0); // Handle completion could be called only on port that should be freed + assert(ext_port->action_flags == 0); // Port should not have any further actions + assert(ext_port->flags.waiting_recycle == 0); // Port should not await to be recycled + assert(ext_port->flags.in_pending_list == 1); // Port should be in pending list + + // Remove port from it + port_stop_handling(ext_port); + + // Verify, that list has more ports in pending list + if (!TAILQ_EMPTY(&p_ext_port_driver->single_thread.pending_tailq)) { + has_pending_ports = true; + } + + // Port handling complete +#if ENABLE_MULTIPLE_HUBS + // When multiply Hubs are attached, we can have ports in pending list, but for another parent + ext_port_t *port = NULL; + TAILQ_FOREACH(port, &p_ext_port_driver->single_thread.pending_tailq, tailq_entry) { + if (port->constant.ext_hub_hdl == ext_port->constant.ext_hub_hdl) { + // Port with same parent has been found + all_ports_were_handled = false; + break; + } + } +#else + // When only one hub is supported - all ports have the same parent + // all_port_were_handled should be triggered if no more ports in pending list + all_ports_were_handled = !has_pending_ports; +#endif // + + if (all_ports_were_handled) { + // Notify parent to enable Interrupt EP + ext_hub_status_handle_complete(ext_port->constant.ext_hub_hdl); + } + + if (has_pending_ports) { + // Re-trigger the processing if there are more ports in pending list + p_ext_port_driver->constant.proc_req_cb(p_ext_port_driver->constant.proc_req_cb_arg); + } + + return ESP_OK; +} + +/** + * @brief Handles port status + * + * @param[in] ext_port Port object + * @return + * - true: Port has a status, that requires processing + * - false: Port has a status, that doesn't require processing + */ +static bool handle_port_status(ext_port_t *ext_port) +{ + bool need_processing = false; + if (port_is_in_reset(ext_port)) { + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Port still in reset, wait and repeat get status...", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + port_request_status(ext_port); + need_processing = true; + } + + return need_processing; +} + +/** + * @brief Handles port connection + * + * @param[in] ext_port Port object + */ +static void handle_port_connection(ext_port_t *ext_port) +{ + bool has_device = false; + + switch (ext_port->state) { + case USB_PORT_STATE_POWERED_OFF: + if (!port_is_powered(ext_port)) { + ext_port->state = USB_PORT_STATE_DISCONNECTED; + port_set_feature(ext_port, USB_FEATURE_PORT_POWER); + } + break; + case USB_PORT_STATE_DISCONNECTED: + case USB_PORT_STATE_DISABLED: + if (port_has_connection(ext_port)) { + if (ext_port->dev_state == PORT_DEV_PRESENT) { + ESP_LOGE(EXT_PORT_TAG, "[%d:%d] Mismatch port state and device status", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + has_device = true; + } else { + // New device connected, flush reset attempts + ext_port->dev_reset_attempts = 0; + ext_port->state = USB_PORT_STATE_RESETTING; + // New device has not been enumerated yet, reset the flag + ext_port->flags.has_enum_device = 0; + } + } + break; + case USB_PORT_STATE_RESETTING: + if (!port_has_connection(ext_port)) { + if (ext_port->dev_state == PORT_DEV_PRESENT) { + ESP_LOGE(EXT_PORT_TAG, "[%d:%d] Failed to issue downstream port reset", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + has_device = true; + } else { + ext_port->state = USB_PORT_STATE_DISCONNECTED; + } + } + break; + case USB_PORT_STATE_ENABLED: + // TODO: IDF-10071 Port debounce mechanism + if (ext_port->dev_state == PORT_DEV_PRESENT) { + ext_port->flags.waiting_recycle = 1; + } + break; + + default: + // Should never occur + abort(); + break; + } + + if (has_device) { + ext_port->flags.waiting_recycle = 1; + ext_port->dev_state = PORT_DEV_NOT_PRESENT; + port_event(ext_port, EXT_PORT_DISCONNECTED); + } +} + +/** + * @brief Handles port changes + * + * @param[in] ext_port Port object + * @return + * - true: Port has a change, that requires processing + * - false: Port has no changes and doesn't require processing + */ +static bool handle_port_changes(ext_port_t *ext_port) +{ + bool need_processing = false; + if (port_has_changed_connection(ext_port)) { + handle_port_connection(ext_port); + port_clear_feature(ext_port, USB_FEATURE_C_PORT_CONNECTION); + need_processing = true; + } else if (port_has_changed_from_enable(ext_port)) { + // For more information, refer to section 11.8.1 Port Error of usb_2.0 specification + ESP_LOGE(EXT_PORT_TAG, "[%d:%d] Error on port (state=%d, dev=%d)", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->state, + ext_port->dev_state == PORT_DEV_PRESENT); + port_clear_feature(ext_port, USB_FEATURE_C_PORT_ENABLE); + need_processing = true; + } else if (port_has_finished_reset(ext_port)) { + if (port_has_connection(ext_port)) { + ext_port->state = USB_PORT_STATE_ENABLED; + } + port_clear_feature(ext_port, USB_FEATURE_C_PORT_RESET); + need_processing = true; + } + + return need_processing; +} + +/** + * @brief Handles port state + * + * @param[in] ext_port Port object + */ +static void handle_port_state(ext_port_t *ext_port) +{ + bool need_handling = false; + usb_hub_port_state_t curr_state = ext_port->state; + usb_hub_port_state_t new_state = ext_port->state; + + switch (curr_state) { + case USB_PORT_STATE_NOT_CONFIGURED: + new_state = USB_PORT_STATE_POWERED_OFF; + port_request_status(ext_port); + need_handling = true; + break; + case USB_PORT_STATE_POWERED_OFF: + // Port power state depends on the wHubCharacteristics.power_switching + new_state = USB_PORT_STATE_DISCONNECTED; + port_set_feature(ext_port, USB_FEATURE_PORT_POWER); + need_handling = true; + break; + case USB_PORT_STATE_DISCONNECTED: + if (port_has_connection(ext_port)) { + if (ext_port->dev_reset_attempts < EXT_PORT_RESET_ATTEMPTS) { + // Available, it EXT_PORT_RESET_ATTEMPTS > 1 + ext_port->dev_reset_attempts++; + port_set_feature(ext_port, USB_FEATURE_PORT_RESET); + need_handling = true; + } else { + ESP_LOGE(EXT_PORT_TAG, "[%d:%d] Unable to reset the device", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + } + } + break; + case USB_PORT_STATE_DISABLED: + if (port_has_connection(ext_port)) { + // This logic does depend on the moment, when we propagate the EXT_PORT_DISCONNECTED event + // during the port disable. + if (!ext_port->flags.has_enum_device && ext_port->flags.waiting_recycle) { + // Port was disabled before enumeration, so the USBH device object was not created. + // Clean the recycle flag and complete port handling with device attached. + ext_port->flags.waiting_recycle = 0; + } + } + break; + case USB_PORT_STATE_RESETTING: + if (port_has_connection(ext_port)) { + // Port in resetting state and has connection + if (ext_port->dev_state == PORT_DEV_NOT_PRESENT) { + assert(ext_port->dev_reset_attempts == 0); // First reset, attempts always should be 0 + ext_port->dev_reset_attempts++; + port_set_feature(ext_port, USB_FEATURE_PORT_RESET); + } else { + assert(port_is_enabled(ext_port)); // Port should be enabled + port_event(ext_port, EXT_PORT_RESET_COMPLETED); + new_state = USB_PORT_STATE_ENABLED; + } + need_handling = true; + } else { + // Port in resetting state and doesn't have connection + // Error case, could be, when device was removed during port reset + ESP_LOGE(EXT_PORT_TAG, "[%d:%d] Device gone during port reset, recover port", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + new_state = USB_PORT_STATE_DISCONNECTED; + } + break; + case USB_PORT_STATE_ENABLED: + if (port_is_enabled(ext_port)) { + if (port_has_connection(ext_port)) { + if (ext_port->dev_state == PORT_DEV_NOT_PRESENT) { + usb_speed_t dev_speed = USB_SPEED_LOW; + if (ext_port->status.wPortStatus.PORT_LOW_SPEED == 0) { + dev_speed = ext_port->status.wPortStatus.PORT_HIGH_SPEED + ? USB_SPEED_HIGH + : USB_SPEED_FULL; + } + ESP_LOGD(EXT_PORT_TAG, "Device speed %s", (char *[]) { + "Low", "Full", "High" + }[dev_speed]); + ext_port->dev_state = PORT_DEV_PRESENT; + port_event(ext_port, EXT_PORT_CONNECTED); + } else { + // Port enabled, device present, reset completed + ext_port->dev_reset_attempts = 0; + port_event(ext_port, EXT_PORT_RESET_COMPLETED); + } + need_handling = true; + } else { + // TODO: IDF-10071 Port debounce mechanism + ESP_LOGE(EXT_PORT_TAG, "[%d:%d] Enabled, but doesn't have connection", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + } + } else { + // If port was enabled, there should be an active device + if (ext_port->dev_state == PORT_DEV_PRESENT) { + ext_port->dev_state = PORT_DEV_NOT_PRESENT; + port_event(ext_port, EXT_PORT_DISCONNECTED); + ext_port->flags.waiting_recycle = 1; + } else { + // Error state + ESP_LOGE(EXT_PORT_TAG, "[%d:%d] Enabled, but doesn't have a device", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + new_state = USB_PORT_STATE_DISCONNECTED; + } + } + break; + default: + // Should never occur + abort(); + break; + } + + if (curr_state != new_state) { + ESP_LOGD(EXT_PORT_TAG, "New state: %d", new_state); + ext_port->state = new_state; + } + + if (!ext_port->flags.waiting_recycle && !need_handling) { + handle_complete(ext_port); + } +} + +/** + * @brief Port object handling action + * + * @note Handles the port in the following order: + * - Port changes (C_CONNECTION, C_ENABLE, C_RESET) + * - Port status (Port still in RESET state) + * - Port state + * + * When ports' handling has been completed, removes the port object from the pending list. + * + * @param[in] ext_port Port object + */ +static void handle_port(ext_port_t *ext_port) +{ + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] change=0x%04x, status=0x%04x, state=%d", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->status.wPortChange.val, + ext_port->status.wPortStatus.val, + ext_port->state); + + if (handle_port_changes(ext_port)) { + return; + } else if (handle_port_status(ext_port)) { + return; + } + handle_port_state(ext_port); +} + +/** + * @brief Port object handling recycle action + * + * @note Port should undergo a recycle procedure when: + * - Device has been detached and freed by all clients (port is present) + * - Parent device been detached (port is gone) + * - Port has run an error during the handling + * + * @param[in] ext_port Port object + */ +static void handle_recycle(ext_port_t *ext_port) +{ + assert(ext_port->flags.waiting_recycle == 1); + + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Port recycle (state=%d, dev=%d)", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->state, + ext_port->dev_state); + + ext_port->flags.waiting_recycle = 0; + + if (ext_port->flags.status_lock) { + // Port is awaiting the status + return; + } + + // Port should not have any changes + assert(ext_port->status.wPortChange.val == 0); + switch (ext_port->state) { + case USB_PORT_STATE_DISABLED: + // We don't need to do anything, as port will be handled after completing USB_FEATURE_PORT_ENABLE + if (ext_port->flags.is_gone) { + handle_complete(ext_port); + } + break; + default: + ext_port->state = USB_PORT_STATE_DISCONNECTED; + if (ext_port->flags.is_gone) { + handle_complete(ext_port); + } else { + handle_port(ext_port); + } + break; + } +} + +/** + * @brief Port object handling disable action + * + * @param[in] ext_port Port object + */ +static void handle_disable(ext_port_t *ext_port) +{ + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Disable (state=%d, dev=%d)", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->state, + ext_port->dev_state); + + assert(ext_port->state != USB_PORT_STATE_POWERED_OFF); + assert(ext_port->state != USB_PORT_STATE_DISCONNECTED); + assert(ext_port->state != USB_PORT_STATE_NOT_CONFIGURED); + + if (ext_port->state == USB_PORT_STATE_ENABLED) { + if (port_has_connection(ext_port)) { + ESP_LOGE(EXT_PORT_TAG, "[%d:%d] Port disabled, reset attempts=%d", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->dev_reset_attempts); + + // Do not try to reset port anymore + ext_port->dev_reset_attempts = EXT_PORT_RESET_ATTEMPTS; + + if (ext_port->dev_state == PORT_DEV_PRESENT) { + ext_port->dev_state = PORT_DEV_NOT_PRESENT; + // Propagate device disconnection if device present + port_event(ext_port, EXT_PORT_DISCONNECTED); + ext_port->flags.waiting_recycle = 1; + } + } + } + + ext_port->state = USB_PORT_STATE_DISABLED; + + if (!ext_port->flags.is_gone) { + // Port not gone, disable port + port_clear_feature(ext_port, USB_FEATURE_PORT_ENABLE); + } +} + +// ----------------------------------------------------------------------------- +// ------------------------ External Port API ---------------------------------- +// ----------------------------------------------------------------------------- + +/** + * @brief Creates new port object + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_cfg Port configuration + * @param[out] port_hdl Port object handle + * @return + * - ESP_ERR_INVALID_STATE: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: Unable to create the port, arguments couldn't be NULL + * - ESP_ERR_NO_MEM: Unable to allocate the port object: no memory + * - ESP_ERR_NOT_FINISHED: Unable to allocate the port object: parent device is not available + * - ESP_OK: Port has been created and added to the pending list + */ +static esp_err_t port_new(void *port_cfg, void **port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_INVALID_STATE); + EXT_PORT_CHECK(port_cfg != NULL && port_hdl != NULL, ESP_ERR_INVALID_ARG); + + ext_port_t *port = NULL; + ext_port_config_t *config = (ext_port_config_t *)port_cfg; + esp_err_t ret = port_alloc(config->ext_hub_hdl, + config->parent_dev_hdl, + config->parent_port_num, + config->port_power_delay_ms, + &port); + + if (ret != ESP_OK) { + *port_hdl = NULL; + goto exit; + } + + port_set_actions(port, PORT_ACTION_HANDLE); + *port_hdl = (ext_port_hdl_t) port; +exit: + return ret; +} + +/** + * @brief Indicates to the External Port driver that a device's port can be recycled + * + * The device connected to the port has been freed. The External Port driver can now + * recycle the port. + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: Unable to recycle the port, port handle couldn't be NULL + * - ESP_OK: + */ +static esp_err_t port_recycle(void *port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *) port_hdl; + + ESP_LOGD(EXT_PORT_TAG, "Port %d request recycle, state=%d", ext_port->constant.port_num, ext_port->state); + + port_set_actions(ext_port, PORT_ACTION_RECYCLE); + return ESP_OK; +} + +/** + * @brief Indicate to the External Port driver that reset of a device's port is required + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: Port handle couldn't be NULL + * - ESP_ERR_INVALID_STATE: Port doesn't have a connection or not enabled + * - ESP_OK: Port reset requested + */ +static esp_err_t port_reset(void *port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *) port_hdl; + + EXT_PORT_CHECK(port_has_connection(ext_port), ESP_ERR_INVALID_STATE); + + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Port reset request", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + + // Reset can be triggered only when port is enabled + EXT_PORT_CHECK(ext_port->state == USB_PORT_STATE_ENABLED, ESP_ERR_INVALID_STATE); + + port_set_actions(ext_port, PORT_ACTION_RESET); + return ESP_OK; +} + +/** + * @brief Get the speed of the External Port + * + * The speed of the port is determined by the speed of the device connected to it. + * + * @note This function is only when a device connected to the port and has been reset + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @param[out] speed Speed of the port + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: The port handle can't be NULL, speed pointer can't be NULL + * - ESP_ERR_INVALID_STATE: No valid device connected to the port + * - ESP_OK: Device speed obtained + */ +esp_err_t port_get_speed(void *port_hdl, usb_speed_t *speed) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL && speed != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *) port_hdl; + + usb_speed_t dev_speed = USB_SPEED_LOW; + EXT_PORT_CHECK(port_has_connection(ext_port), ESP_ERR_INVALID_STATE); + // Full-speed or High-speed device attached to this port (determined by bit PORT_HIGH_SPEED). + if (ext_port->status.wPortStatus.PORT_LOW_SPEED == 0) { + dev_speed = ext_port->status.wPortStatus.PORT_HIGH_SPEED + ? USB_SPEED_HIGH + : USB_SPEED_FULL; + } + // Otherwise, Low-speed + *speed = dev_speed; + return ESP_OK; +} + +/** + * @brief Indicate to the External Port Driver that port has an active device + * + * The device: + * - has been enumerated + * - still present + * - is in configured state + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: The port handle can't be NULL + * - ESP_OK: Port has a device and the device completed enumeration process + */ +static esp_err_t port_active(void *port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *) port_hdl; + + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Port has an enumerated device", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + + ext_port->flags.has_enum_device = 1; + + return handle_complete(ext_port); +} + +/** + * @brief Indicate to the External Port Driver that port should be disabled + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: The port handle can't be NULL + * - ESP_ERR_INVALID_STATE: The port is not enabled + * - ESP_OK: Port disable requested + */ +static esp_err_t port_disable(void *port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *) port_hdl; + + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Disable", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + + EXT_PORT_CHECK(ext_port->state == USB_PORT_STATE_ENABLED, ESP_ERR_INVALID_STATE); + + port_set_actions(ext_port, PORT_ACTION_DISABLE); + return ESP_OK; +} + +/** + * @brief Deletes the port object + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: The port handle can't be NULL + * - ESP_OK: Port object has been freed and deleted + */ +static esp_err_t port_delete(void *port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *) port_hdl; + // Sanity checks + assert(ext_port->dev_state == PORT_DEV_NOT_PRESENT); // Port should not have a device + assert(ext_port->flags.in_pending_list == 0); // Port should not be in pending list + + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Freeing", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num); + + heap_caps_free(ext_port); + + return ESP_OK; +} + +/** + * @brief Marks the Port as gone and initialize process of freeing the Port + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: The port handle can't be NULL + * - ESP_ERR_NOT_FINISHED: The port has a device and should be recycled + * - ESP_OK: Port object has been marked as gone and could be freed + */ +static esp_err_t port_gone(void *port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *)port_hdl; + + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Port is gone (state=%d, dev=%d)", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + ext_port->state, + ext_port->dev_state); + + bool has_device = false; + + ext_port->flags.is_gone = 1; + ext_port->flags.waiting_free = 1; + + switch (ext_port->state) { + case USB_PORT_STATE_ENABLED: + case USB_PORT_STATE_DISABLED: + case USB_PORT_STATE_RESETTING: + // Port could have a device + if (ext_port->dev_state == PORT_DEV_PRESENT) { + ext_port->dev_state = PORT_DEV_NOT_PRESENT; + ext_port->flags.waiting_recycle = 1; + port_event(ext_port, EXT_PORT_DISCONNECTED); + has_device = true; + } + break; + case USB_PORT_STATE_NOT_CONFIGURED: + // Port has been added, but the Driver has not started the handling yet + case USB_PORT_STATE_POWERED_OFF: + case USB_PORT_STATE_DISCONNECTED: + // Port has been added, but doesn't have a device + // We can remove the port from pending list and could be freed by the External Hub Driver + break; + default: + // Should never occur + abort(); + break; + } + + // If the port is in handling list, stop it + if (ext_port->flags.in_pending_list) { + port_stop_handling(ext_port); + } + + return (has_device) ? ESP_ERR_NOT_FINISHED : ESP_OK; +} + +/** + * @brief Indicate to the External Port Driver that Port request has been finished and the Port requires handling + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: The port handle can't be NULL + * - ESP_OK: Port action was requested + */ +static esp_err_t port_get_status(void* port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *)port_hdl; + + port_set_actions(ext_port, PORT_ACTION_GET_STATUS); + return ESP_OK; +} + +/** + * @brief Indicate to the External Port Driver that the Port has new status + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @param[in] port_status New status data + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: The port handle can't be NULL, the status data can't be NULL + * - ESP_OK: Port action was requested + */ +static esp_err_t port_set_status(void* port_hdl, const usb_port_status_t *port_status) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL && port_status != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *)port_hdl; + + // Update status + ext_port->status.wPortChange.val = port_status->wPortChange.val; + ext_port->status.wPortStatus.val = port_status->wPortStatus.val; + // Status valid + ext_port->flags.status_outdated = 0; + // Remove status lock + ext_port->flags.status_lock = 0; + // Request port handling + port_set_actions(ext_port, PORT_ACTION_HANDLE); + return ESP_OK; +} + +/** + * @brief Indicate to the External Port Driver that the Port requires processing + * + * @note This function should only be called from the External Hub Driver + * + * @param[in] port_hdl Port object handle + * @return + * - ESP_ERR_NOT_ALLOWED: The External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG: The port handle can't be NULL + * - ESP_OK: Port action was requested + */ +static esp_err_t port_req_process(void* port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *)port_hdl; + + if (ext_port->flags.status_outdated) { + port_set_actions(ext_port, PORT_ACTION_GET_STATUS); + } else { + port_set_actions(ext_port, PORT_ACTION_HANDLE); + } + return ESP_OK; +} + +// ----------------------------------------------------------------------------- +// ------------------ External Port Processing Functions ----------------------- +// ----------------------------------------------------------------------------- + +/** + * @brief External Port Driver API + */ +const ext_hub_port_driver_t ext_port_driver = { + .new = port_new, + .reset = port_reset, + .recycle = port_recycle, + .active = port_active, + .disable = port_disable, + .gone = port_gone, + .del = port_delete, + .get_speed = port_get_speed, + .get_status = port_get_status, + .set_status = port_set_status, + .req_process = port_req_process, +}; + +esp_err_t ext_port_install(const ext_port_driver_config_t *config) +{ + EXT_PORT_CHECK(p_ext_port_driver == NULL, ESP_ERR_NOT_ALLOWED); + + ext_port_driver_t *ext_port_drv = heap_caps_calloc(1, sizeof(ext_port_driver_t), MALLOC_CAP_DEFAULT); + EXT_PORT_CHECK(ext_port_drv != NULL, ESP_ERR_NO_MEM); + + // Save callbacks + ext_port_drv->constant.proc_req_cb = config->proc_req_cb; + ext_port_drv->constant.proc_req_cb_arg = config->proc_req_cb_arg; + ext_port_drv->constant.event_cb = config->event_cb; + ext_port_drv->constant.event_cb_arg = config->event_cb_arg; + TAILQ_INIT(&ext_port_drv->single_thread.pending_tailq); + + p_ext_port_driver = ext_port_drv; + + ESP_LOGD(EXT_PORT_TAG, "Driver installed"); + return ESP_OK; +} + +esp_err_t ext_port_uninstall(void) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(TAILQ_EMPTY(&p_ext_port_driver->single_thread.pending_tailq), ESP_ERR_INVALID_STATE); + ext_port_driver_t *ext_port_drv = p_ext_port_driver; + p_ext_port_driver = NULL; + + heap_caps_free(ext_port_drv); + ESP_LOGD(EXT_PORT_TAG, "Driver uninstalled"); + return ESP_OK; +} + +esp_err_t ext_port_process(void) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + + ext_port_t *ext_port = get_port_from_pending_list(); + if (ext_port == NULL) { + // No more ports in list to handle + // NOTE: + // This is possible, when an external Hub detached sooner than being + // configured and handled by the Driver. This is not an error case, + // because the processing requests by the HUB_DRIVER_ACTION_EXT_PORT + // flag in the Hub Driver and there is no way to clean it. + ESP_LOGD(EXT_PORT_TAG, "No more ports to handle"); + return ESP_OK; + } + + uint32_t action_flags = ext_port->action_flags; + ext_port->action_flags = 0; + + while (action_flags) { + // Keep processing until all port's action have been handled + ESP_LOGD(EXT_PORT_TAG, "[%d:%d] Processing actions 0x%"PRIx32"", + ext_port->constant.parent_dev_addr, + ext_port->constant.port_num, + action_flags); + + if (action_flags & PORT_ACTION_HANDLE) { + handle_port(ext_port); + } + if (action_flags & PORT_ACTION_DISABLE) { + handle_disable(ext_port); + } + if (action_flags & PORT_ACTION_RECYCLE) { + handle_recycle(ext_port); + } + + /* + * Feature related actions are mutual exclusive and require: + * - transfer completion callback + * - further request of new port status via get_status(), except PORT_ACTION_GET_STATUS itself + */ + if (action_flags & PORT_ACTION_GET_STATUS) { + port_request_status(ext_port); + } else if (action_flags & PORT_ACTION_RESET) { + if (ext_port->state != USB_PORT_STATE_RESETTING) { + /* + * IMPORTANT NOTE + * This is possible, when the reset is requested via port_reset() + * Port reset is possible only in two states: + * - USB_PORT_STATE_DISCONNECTED (mainly, first reset) + * - USB_PORT_STATE_ENABLED (mainly, second reset) + */ + assert(ext_port->state == USB_PORT_STATE_DISCONNECTED || + ext_port->state == USB_PORT_STATE_ENABLED); + ext_port->state = USB_PORT_STATE_RESETTING; + } + port_set_feature(ext_port, USB_FEATURE_PORT_RESET); + } + + action_flags = ext_port->action_flags; + ext_port->action_flags = 0; + } + + return ESP_OK; +} + +const ext_hub_port_driver_t *ext_port_get_driver(void) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, NULL); + return &ext_port_driver; +} diff --git a/components/usb/hcd_dwc.c b/components/usb/hcd_dwc.c index a5ea7d736ff4..7254ba3f0c2a 100644 --- a/components/usb/hcd_dwc.c +++ b/components/usb/hcd_dwc.c @@ -10,13 +10,14 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" +#include "esp_private/critical_section.h" #include "esp_heap_caps.h" #include "esp_intr_alloc.h" -#include "soc/interrupts.h" // For interrupt index #include "esp_err.h" #include "esp_log.h" + +#include "soc/usb_dwc_periph.h" #include "hal/usb_dwc_hal.h" -#include "hal/usb_dwc_types.h" #include "hcd.h" #include "usb_private.h" #include "usb/usb_types_ch9.h" @@ -28,15 +29,6 @@ // ----------------------------------------------------- Macros -------------------------------------------------------- -// ------------------ Target specific ---------------------- -// TODO: Remove target specific section after support for multiple USB peripherals is implemented -#include "sdkconfig.h" -#if (CONFIG_IDF_TARGET_ESP32P4) -#define USB_INTR ETS_USB_OTG_INTR_SOURCE -#else -#define USB_INTR ETS_USB_INTR_SOURCE -#endif - // --------------------- Constants ------------------------- #define INIT_DELAY_MS 30 // A delay of at least 25ms to enter Host mode. Make it 30ms to be safe @@ -64,30 +56,28 @@ #define XFER_LIST_LEN_ISOC 64 // Implement longer ISOC transfer list to give us enough space for additional timing margin #define XFER_LIST_ISOC_MARGIN 3 // The 1st ISOC transfer is scheduled 3 (micro)frames later so we have enough timing margin -// ------------------------ Flags -------------------------- +// ------------------------ Internal -------------------------- /** - * @brief Bit masks for the HCD to use in the URBs reserved_flags field + * @brief Values for the HCD to use in the URBs hcd_var field * - * The URB object has a reserved_flags member for host stack's internal use. The following flags will be set in - * reserved_flags in order to keep track of state of an URB within the HCD. + * The URB object has a hcd_var member for host stack's internal use. The following values will be set in + * hcd_var in order to keep track of state of an URB within the HCD. */ #define URB_HCD_STATE_IDLE 0 // The URB is not enqueued in an HCD pipe #define URB_HCD_STATE_PENDING 1 // The URB is enqueued and pending execution #define URB_HCD_STATE_INFLIGHT 2 // The URB is currently in flight #define URB_HCD_STATE_DONE 3 // The URB has completed execution or is retired, and is waiting to be dequeued -#define URB_HCD_STATE_SET(reserved_flags, state) (reserved_flags = (reserved_flags & ~URB_HCD_STATE_MASK) | state) -#define URB_HCD_STATE_GET(reserved_flags) (reserved_flags & URB_HCD_STATE_MASK) - // -------------------- Convenience ------------------------ const char *HCD_DWC_TAG = "HCD DWC"; -#define HCD_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&hcd_lock) -#define HCD_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&hcd_lock) -#define HCD_ENTER_CRITICAL() portENTER_CRITICAL(&hcd_lock) -#define HCD_EXIT_CRITICAL() portEXIT_CRITICAL(&hcd_lock) +DEFINE_CRIT_SECTION_LOCK_STATIC(hcd_lock); +#define HCD_ENTER_CRITICAL_ISR() esp_os_enter_critical_isr(&hcd_lock) +#define HCD_EXIT_CRITICAL_ISR() esp_os_exit_critical_isr(&hcd_lock) +#define HCD_ENTER_CRITICAL() esp_os_enter_critical(&hcd_lock) +#define HCD_EXIT_CRITICAL() esp_os_exit_critical(&hcd_lock) #define HCD_CHECK(cond, ret_val) ({ \ if (!(cond)) { \ @@ -270,7 +260,6 @@ typedef struct { intr_handle_t isr_hdl; } hcd_obj_t; -static portMUX_TYPE hcd_lock = portMUX_INITIALIZER_UNLOCKED; static hcd_obj_t *s_hcd_obj = NULL; // Note: "s_" is for the static pointer // ------------------------------------------------- Forward Declare --------------------------------------------------- @@ -1005,7 +994,7 @@ esp_err_t hcd_install(const hcd_config_t *config) goto port_alloc_err; } // Allocate interrupt - err_ret = esp_intr_alloc(USB_INTR, + err_ret = esp_intr_alloc(usb_dwc_info.controllers[0].irq, config->intr_flags | ESP_INTR_FLAG_INTRDISABLED, // The interrupt must be disabled until the port is initialized intr_hdlr_main, (void *)p_hcd_obj_dmy->port_obj, @@ -1825,6 +1814,8 @@ esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pi bool chan_allocated = usb_dwc_hal_chan_alloc(port->hal, pipe->chan_obj, (void *) pipe); if (!chan_allocated) { HCD_EXIT_CRITICAL(); + // The only reason why alloc channel could return false is no more free channels + ESP_LOGE(HCD_DWC_TAG, "No more HCD channels available"); ret = ESP_ERR_NOT_SUPPORTED; goto err; } diff --git a/components/usb/hub.c b/components/usb/hub.c index 6fa14fa303f6..e39e741d6949 100644 --- a/components/usb/hub.c +++ b/components/usb/hub.c @@ -9,10 +9,9 @@ #include #include #include -#include "freertos/FreeRTOS.h" -#include "freertos/portmacro.h" #include "esp_err.h" #include "esp_heap_caps.h" +#include "esp_private/critical_section.h" #include "esp_log.h" #include "usb_private.h" #include "hcd.h" @@ -20,7 +19,7 @@ #include "usb/usb_helpers.h" #if ENABLE_USB_HUBS -#include "ext_hub.h" +#include "ext_port.h" #endif // ENABLE_USB_HUBS /* @@ -107,16 +106,16 @@ typedef struct { } hub_driver_t; static hub_driver_t *p_hub_driver_obj = NULL; -static portMUX_TYPE hub_driver_lock = portMUX_INITIALIZER_UNLOCKED; const char *HUB_DRIVER_TAG = "HUB"; -#define HUB_DRIVER_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&hub_driver_lock) -#define HUB_DRIVER_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&hub_driver_lock) -#define HUB_DRIVER_ENTER_CRITICAL() portENTER_CRITICAL(&hub_driver_lock) -#define HUB_DRIVER_EXIT_CRITICAL() portEXIT_CRITICAL(&hub_driver_lock) -#define HUB_DRIVER_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&hub_driver_lock) -#define HUB_DRIVER_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&hub_driver_lock) +DEFINE_CRIT_SECTION_LOCK_STATIC(hub_driver_lock); +#define HUB_DRIVER_ENTER_CRITICAL_ISR() esp_os_enter_critical_isr(&hub_driver_lock) +#define HUB_DRIVER_EXIT_CRITICAL_ISR() esp_os_exit_critical_isr(&hub_driver_lock) +#define HUB_DRIVER_ENTER_CRITICAL() esp_os_enter_critical(&hub_driver_lock) +#define HUB_DRIVER_EXIT_CRITICAL() esp_os_exit_critical(&hub_driver_lock) +#define HUB_DRIVER_ENTER_CRITICAL_SAFE() esp_os_enter_critical_safe(&hub_driver_lock) +#define HUB_DRIVER_EXIT_CRITICAL_SAFE() esp_os_exit_critical_safe(&hub_driver_lock) #define HUB_DRIVER_CHECK(cond, ret_val) ({ \ if (!(cond)) { \ @@ -320,6 +319,72 @@ static bool ext_hub_callback(bool in_isr, void *user_arg) HUB_DRIVER_EXIT_CRITICAL_SAFE(); return p_hub_driver_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.proc_req_cb_arg); } + +static void ext_port_callback(void *user_arg) +{ + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_ACTION_EXT_PORT; + HUB_DRIVER_EXIT_CRITICAL(); + p_hub_driver_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_HUB, false, p_hub_driver_obj->constant.proc_req_cb_arg); +} + +static void ext_port_event_callback(ext_port_event_data_t *event_data, void *arg) +{ + switch (event_data->event) { + case EXT_PORT_CONNECTED: + // First reset is done by ext_port logic + usb_speed_t port_speed; + + if (ext_hub_port_get_speed(event_data->connected.ext_hub_hdl, + event_data->connected.parent_port_num, + &port_speed) != ESP_OK) { + goto new_ds_dev_err; + } + + // TODO: IDF-10023 Move responsibility of parent-child tree building to Hub Driver instead of USBH + usb_device_info_t parent_dev_info; + ESP_ERROR_CHECK(usbh_dev_get_info(event_data->connected.parent_dev_hdl, &parent_dev_info)); + if (parent_dev_info.speed == USB_SPEED_HIGH) { + if (port_speed != parent_dev_info.speed) { + ESP_LOGE(HUB_DRIVER_TAG, "Connected device is %s, transaction translator (TT) is not supported", + (char *[]) { + "LS", "FS", "HS" + }[port_speed]); + goto new_ds_dev_err; + } + } + +#if (!CONFIG_USB_HOST_EXT_PORT_SUPPORT_LS) + if (port_speed == USB_SPEED_LOW) { + ESP_LOGE(HUB_DRIVER_TAG, "Connected %s-speed device, not supported", + (char *[]) { + "Low", "Full", "High" + }[port_speed]); + goto new_ds_dev_err; + } +#endif // CONFIG_USB_HOST_EXT_PORT_SUPPORT_LS + + if (new_dev_tree_node(event_data->connected.parent_dev_hdl, event_data->connected.parent_port_num, port_speed) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to add new downstream device"); + goto new_ds_dev_err; + } + break; +new_ds_dev_err: + ext_hub_port_disable(event_data->connected.ext_hub_hdl, event_data->connected.parent_port_num); + break; + case EXT_PORT_RESET_COMPLETED: + ESP_ERROR_CHECK(dev_tree_node_reset_completed(event_data->reset_completed.parent_dev_hdl, event_data->reset_completed.parent_port_num)); + break; + case EXT_PORT_DISCONNECTED: + // The node could be freed by now, no need to verify the result here + dev_tree_node_dev_gone(event_data->disconnected.parent_dev_hdl, event_data->disconnected.parent_port_num); + break; + default: + // Should never occur + abort(); + break; + } +} #endif // ENABLE_USB_HUBS // ---------------------- Handlers ------------------------- @@ -479,10 +544,20 @@ esp_err_t hub_install(hub_config_t *hub_config, void **client_ret) } #if ENABLE_USB_HUBS + // Install External Port driver + ext_port_driver_config_t ext_port_config = { + .proc_req_cb = ext_port_callback, + .event_cb = ext_port_event_callback, + }; + ret = ext_port_install(&ext_port_config); + if (ret != ESP_OK) { + goto err_ext_port; + } + // Install External HUB driver ext_hub_config_t ext_hub_config = { .proc_req_cb = ext_hub_callback, - .port_driver = NULL, + .port_driver = ext_port_get_driver(), }; ret = ext_hub_install(&ext_hub_config); if (ret != ESP_OK) { @@ -536,6 +611,8 @@ esp_err_t hub_install(hub_config_t *hub_config, void **client_ret) #if ENABLE_USB_HUBS ext_hub_uninstall(); err_ext_hub: + ext_port_uninstall(); +err_ext_port: #endif // ENABLE_USB_HUBS heap_caps_free(hub_driver_obj); return ret; @@ -552,6 +629,7 @@ esp_err_t hub_uninstall(void) #if ENABLE_USB_HUBS ESP_ERROR_CHECK(ext_hub_uninstall()); + ESP_ERROR_CHECK(ext_port_uninstall()); #endif // ENABLE_USB_HUBS ESP_ERROR_CHECK(hcd_port_deinit(hub_driver_obj->constant.root_port_hdl)); @@ -700,14 +778,35 @@ esp_err_t hub_port_disable(usb_device_handle_t parent_dev_hdl, uint8_t parent_po return ret; } -#if ENABLE_USB_HUBS esp_err_t hub_notify_new_dev(uint8_t dev_addr) { HUB_DRIVER_ENTER_CRITICAL(); HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); HUB_DRIVER_EXIT_CRITICAL(); - return ext_hub_new_dev(dev_addr); + esp_err_t ret; +#if ENABLE_USB_HUBS + ret = ext_hub_new_dev(dev_addr); +#else + // Verify the device descriptor and if the bDeviceClass is a Hub class, + // show the warning message, that Hub support feature is not enabled + usb_device_handle_t dev_hdl = NULL; + const usb_device_desc_t *device_desc = NULL; + // Open device + if (usbh_devs_open(dev_addr, &dev_hdl) == ESP_OK) { + // Get Device Descriptor + if (usbh_dev_get_desc(dev_hdl, &device_desc) == ESP_OK) { + if (device_desc->bDeviceClass == USB_CLASS_HUB) { + ESP_LOGW(HUB_DRIVER_TAG, "External Hubs support disabled, Hub device was not initialized"); + } + } + // Close device + usbh_dev_close(dev_hdl); + } + // Logic should not stop the flow, so no error to return + ret = ESP_OK; +#endif // ENABLE_USB_HUBS + return ret; } esp_err_t hub_notify_dev_gone(uint8_t dev_addr) @@ -716,9 +815,17 @@ esp_err_t hub_notify_dev_gone(uint8_t dev_addr) HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); HUB_DRIVER_EXIT_CRITICAL(); - return ext_hub_dev_gone(dev_addr); + esp_err_t ret; +#if ENABLE_USB_HUBS + ret = ext_hub_dev_gone(dev_addr); +#else + // Nothing to do, while Hubs support is not enabled + ret = ESP_OK; +#endif // ENABLE_USB_HUBS + return ret; } +#if (ENABLE_USB_HUBS) esp_err_t hub_notify_all_free(void) { HUB_DRIVER_ENTER_CRITICAL(); @@ -739,10 +846,7 @@ esp_err_t hub_process(void) while (action_flags) { #if ENABLE_USB_HUBS if (action_flags & HUB_DRIVER_ACTION_EXT_PORT) { - ESP_LOGW(HUB_DRIVER_TAG, "ext_port_process() has not been implemented yet"); - /* ESP_ERROR_CHECK(ext_port_process()); - */ } if (action_flags & HUB_DRIVER_ACTION_EXT_HUB) { ESP_ERROR_CHECK(ext_hub_process()); diff --git a/components/usb/include/usb/usb_types_ch11.h b/components/usb/include/usb/usb_types_ch11.h index a30e9d3919be..f3c9a3d77a46 100644 --- a/components/usb/include/usb/usb_types_ch11.h +++ b/components/usb/include/usb/usb_types_ch11.h @@ -43,6 +43,28 @@ typedef enum { USB_B_REQUEST_HUB_STOP_TT = 0x0B, /**< Stop TT. */ } usb_hub_class_request_t ; +/** + * @brief USB Hub Port state + * + * See USB 2.0 spec, 11.5.1 Downstream Facing Port State Descriptions + */ +typedef enum { + USB_PORT_STATE_NOT_CONFIGURED = 0x00, /**< The hub is not configured. A port transitions to and remains in this state whenever the value of the hub configuration is zero. */ + USB_PORT_STATE_POWERED_OFF, /**< Powered_off: Port requires explicit request to transition. */ + USB_PORT_STATE_DISCONNECTED, /**< In the Disconnected state, the port’s differential transmitter and receiver are disabled and only connection detection is possible.*/ + USB_PORT_STATE_DISABLED, /**< A port in the Disabled state will not propagate signaling in either the upstream or the downstream direction */ + USB_PORT_STATE_RESETTING, /**< The duration of the Resetting state is nominally 10 ms to 20 ms (10 ms is preferred). */ + USB_PORT_STATE_ENABLED, /**< While in this state, the output of the port’s differential receiver is available to the Hub Repeater so that appropriate signaling transitions can establish upstream connectivity*/ + USB_PORT_STATE_TRANSMIT, /**< This state is entered from the Enabled state on the transition of the Hub Repeater to the WFEOPFU state */ + USB_PORT_STATE_TRANSMIT_R, /**< When in this state, the port repeats the resume ‘K’ at the upstream facing port to the downstream facing port. */ + USB_PORT_STATE_SUSPENDED, /**< While a port is in the Suspended state, the port's differential transmitter is disabled. */ + USB_PORT_STATE_RESUMING, /**< While in this state, the hub drives a 'K' on the port. */ + USB_PORT_STATE_SEND_EOR, /**< This state is entered from the Resuming state if the 20 ms timer expires. */ + USB_PORT_STATE_RESTART_S, /**< A port enters the Restart_S state from the Suspended state when an SE0 or ‘K’ is seen at the port and the Receiver is in the Suspended state */ + USB_PORT_STATE_RESTART_E, /**< A port enters the Restart_E state from the Enabled state when an ‘SE0’ or ‘K’ is seen at the port and the Receiver is in the Suspended state. */ + USB_PORT_STATE_TESTING, /**< A port transitions to this state from any state when the port sees SetTest. */ +} usb_hub_port_state_t; + /** * @brief USB Hub Port feature selector codes * diff --git a/components/usb/private_include/ext_hub.h b/components/usb/private_include/ext_hub.h index 396d838be1cd..93432542a7ab 100644 --- a/components/usb/private_include/ext_hub.h +++ b/components/usb/private_include/ext_hub.h @@ -46,7 +46,7 @@ typedef struct { esp_err_t (*active)(void *port_hdl); esp_err_t (*disable)(void *port_hdl); esp_err_t (*gone)(void *port_hdl); - esp_err_t (*free)(void *port_hdl); + esp_err_t (*del)(void *port_hdl); esp_err_t (*get_speed)(void *por_hdl, usb_speed_t *speed); esp_err_t (*get_status)(void *port_hdl); esp_err_t (*set_status)(void *port_hdl, const usb_port_status_t *status); @@ -278,7 +278,7 @@ esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, * * @return * - ESP_OK: Port's feature set successfully - * - ESP_ERR_INVALID_STATE: External Hub driver is not installed; + * - ESP_ERR_NOT_ALLOWED: External Hub driver is not installed * - ESP_ERR_INVALID_ARG: Invalid argument * - ESP_ERR_INVALID_SIZE: External Hub port number out of the hub's range */ @@ -293,7 +293,7 @@ esp_err_t ext_hub_set_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_nu * * @return * - ESP_OK: Port's feature cleared successfully - * - ESP_ERR_INVALID_STATE: External Hub driver is not installed; + * - ESP_ERR_NOT_ALLOWED: External Hub driver is not installed * - ESP_ERR_INVALID_ARG: Invalid argument * - ESP_ERR_INVALID_SIZE: External Hub port number out of the hub's range */ @@ -310,7 +310,7 @@ esp_err_t ext_hub_clear_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_ * * @return * - ESP_OK: Port's status obtained successfully - * - ESP_ERR_INVALID_STATE: External Hub driver is not installed; + * - ESP_ERR_NOT_ALLOWED: External Hub driver is not installed * - ESP_ERR_INVALID_ARG: Invalid argument * - ESP_ERR_INVALID_SIZE: External Hub port number out of the hub's range */ diff --git a/components/usb/private_include/ext_port.h b/components/usb/private_include/ext_port.h new file mode 100644 index 000000000000..5795e41575cc --- /dev/null +++ b/components/usb/private_include/ext_port.h @@ -0,0 +1,143 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "esp_err.h" +#include "ext_hub.h" +#include "usb/usb_types_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ext_port_s *ext_port_hdl_t; + +// ------------------------------ Events --------------------------------------- +typedef enum { + EXT_PORT_CONNECTED = 0x01, /**< Port has a device connection event */ + EXT_PORT_RESET_COMPLETED, /**< Port has completed the reset routine */ + EXT_PORT_DISCONNECTED, /**< Port has a device disconnection event */ +} ext_port_event_t; + +/** + * @brief Event data object for External Port driver events + */ +typedef struct { + ext_port_event_t event; + union { + struct { + ext_hub_handle_t ext_hub_hdl; /**< Ports' parent external Hub handle */ + usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ + uint8_t parent_port_num; /**< Ports' parent port number */ + } connected; /**< EXT_PORT_CONNECTED event specific data */ + + struct { + usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ + uint8_t parent_port_num; /**< Ports' parent port number */ + } reset_completed; /**< EXT_PORT_RESET_COMPLETED event specific data */ + + struct { + usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ + uint8_t parent_port_num; /**< Ports' parent port number */ + } disconnected; /**< EXT_PORT_DISCONNECTED event specific data */ + }; +} ext_port_event_data_t; + +// ------------------------------ Callbacks ------------------------------------ +/** + * @brief Callback used to indicate that the External Port Driver requires process callback + * + * @note For the Hub Driver only + */ +typedef void (*ext_port_cb_t)(void *user_arg); + +/** + * @brief Callback used to indicate that the External Port driver has an event + * + * @note For the Hub Driver only + */ +typedef void (*ext_port_event_cb_t)(ext_port_event_data_t *event_data, void *arg); + +// ----------------- External Port Driver configuration ------------------------ + +/** + * @brief External Port driver configuration + */ +typedef struct { + ext_port_cb_t proc_req_cb; /**< External Port process callback */ + void *proc_req_cb_arg; /**< External Port process callback argument */ + ext_port_event_cb_t event_cb; /**< External Port event callback */ + void *event_cb_arg; /**< External Port event callback argument */ +} ext_port_driver_config_t; + +/** + * @brief External Port configuration + * + * Structure is used to create new port + */ +typedef struct { + ext_hub_handle_t ext_hub_hdl; /**< Ports' parent external Hub handle */ + usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ + uint8_t parent_port_num; /**< Ports' parent port number */ + uint16_t port_power_delay_ms; /**< Ports' Power on time to Power Good, ms */ +} ext_port_config_t; + +// -------------------- External Port Processing Functions --------------------- + +/** + * @brief Install the External Port Driver + * + * @note This function should only be called from the Hub Driver + * + * @param[in] config External Port Driver configuration + * @return + * - ESP_ERR_NOT_ALLOWED: The Driver was already installed + * - ESP_ERR_NO_MEM: Unable to install the Driver, no memory + * - ESP_OK: The Driver has been installed successfully + */ +esp_err_t ext_port_install(const ext_port_driver_config_t *config); + +/** + * @brief Uninstall the External Port Driver + * + * @note This function should only be called from the Hub Driver + * + * @return + * - ESP_ERR_NOT_ALLOWED: The Driver was not installed + * - ESP_ERR_INVALID_STATE: The Driver has ports in the pending list and can't be uninstalled + * - ESP_OK: The Driver has been uninstall successfully + */ +esp_err_t ext_port_uninstall(void); + +/** + * @brief External Port Driver's process function + * + * @note This function should only be called from the Hub Driver + * + * External Port Driver process function that must be called repeatedly to process the driver's actions and events. + * If blocking, the caller can block on the notification callback of source USB_PROC_REQ_SOURCE_HUB + * to run this function. + * + * @return + * - ESP_ERR_NOT_ALLOWED: The Driver was not installed + * - ESP_OK: The Driver processed completed + */ +esp_err_t ext_port_process(void); + +/** + * @brief Returns External Port Driver's API + * + * @note This is a specific API for the External Hub Driver to handle the ports. + * @return + * - NULL: The Driver has not been installed + * - not NULL: Pointer to the External Port Driver API + */ +const ext_hub_port_driver_t *ext_port_get_driver(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/private_include/hub.h b/components/usb/private_include/hub.h index a580c458559e..f563a56f2834 100644 --- a/components/usb/private_include/hub.h +++ b/components/usb/private_include/hub.h @@ -134,8 +134,8 @@ esp_err_t hub_root_stop(void); * * @note This function should only be called from the Host Library task * - * @param[in] parent_dev_hdl - * @param[in] parent_port_num + * @param[in] parent_dev_hdl Parent device handle (is used to get the External Hub handle) + * @param[in] parent_port_num Parent number (is used to specify the External Port) * @param[in] dev_uid Device's unique ID * * @return @@ -151,9 +151,8 @@ esp_err_t hub_port_recycle(usb_device_handle_t parent_dev_hdl, uint8_t parent_po * * @note This function should only be called from the Host Library task * - * @param[in] parent_dev_hdl - * @param[in] parent_port_num - * + * @param[in] parent_dev_hdl Parent device handle (is used to get the External Hub handle) + * @param[in] parent_port_num Parent number (is used to specify the External Port) * @return * - ESP_OK: Port reset successful * - ESP_ERR_INVALID_STATE: Hub driver is not installed @@ -192,12 +191,14 @@ esp_err_t hub_port_active(usb_device_handle_t parent_dev_hdl, uint8_t parent_por */ esp_err_t hub_port_disable(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num); -#if ENABLE_USB_HUBS /** * @brief Notify Hub driver that new device has been attached * * If device is has a HUB class, then it will be added as External Hub to Hub Driver. * + * @note This function should only be called from the Host Library task + * @note If the Hub support feature is disabled and device has a Hub class, only the warning message will be shown. + * * @param[in] dev_addr Device bus address * * @return @@ -211,6 +212,9 @@ esp_err_t hub_notify_new_dev(uint8_t dev_addr); * * If the device was an External Hub, then it will be removed from the Hub Driver. * + * @note This function should only be called from the Host Library task + * @note If the Hub support feature is disabled, no additional logic requires here. + * * @param[in] dev_addr Device bus address * * @return @@ -219,9 +223,12 @@ esp_err_t hub_notify_new_dev(uint8_t dev_addr); */ esp_err_t hub_notify_dev_gone(uint8_t dev_addr); +#if ENABLE_USB_HUBS /** * @brief Notify Hub driver that all devices should be freed * + * @note This function should only be called from the Host Library task + * * @return * - ESP_OK: All the devices can be freed * - ESP_ERR_INVALID_STATE: Hub driver is not in a correct state diff --git a/components/usb/test_apps/hcd/sdkconfig.defaults b/components/usb/test_apps/hcd/sdkconfig.defaults index 0632edf7579e..d433503fbfd7 100644 --- a/components/usb/test_apps/hcd/sdkconfig.defaults +++ b/components/usb/test_apps/hcd/sdkconfig.defaults @@ -6,3 +6,4 @@ CONFIG_HEAP_POISONING_COMPREHENSIVE=y # CONFIG_UNITY_ENABLE_FLOAT is not set # CONFIG_UNITY_ENABLE_DOUBLE is not set CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y +CONFIG_USB_HOST_HUBS_SUPPORTED=y diff --git a/components/usb/test_apps/usb_host/sdkconfig.defaults b/components/usb/test_apps/usb_host/sdkconfig.defaults index 0632edf7579e..d433503fbfd7 100644 --- a/components/usb/test_apps/usb_host/sdkconfig.defaults +++ b/components/usb/test_apps/usb_host/sdkconfig.defaults @@ -6,3 +6,4 @@ CONFIG_HEAP_POISONING_COMPREHENSIVE=y # CONFIG_UNITY_ENABLE_FLOAT is not set # CONFIG_UNITY_ENABLE_DOUBLE is not set CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y +CONFIG_USB_HOST_HUBS_SUPPORTED=y diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c index 644a5e777e5c..9e5f3feea368 100644 --- a/components/usb/usb_host.c +++ b/components/usb/usb_host.c @@ -16,6 +16,7 @@ Warning: The USB Host Library API is still a beta version and may be subject to #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" +#include "esp_private/critical_section.h" #include "esp_err.h" #include "esp_log.h" #include "esp_heap_caps.h" @@ -26,14 +27,13 @@ Warning: The USB Host Library API is still a beta version and may be subject to #include "esp_private/usb_phy.h" #include "usb/usb_host.h" -static portMUX_TYPE host_lock = portMUX_INITIALIZER_UNLOCKED; - -#define HOST_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&host_lock) -#define HOST_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&host_lock) -#define HOST_ENTER_CRITICAL() portENTER_CRITICAL(&host_lock) -#define HOST_EXIT_CRITICAL() portEXIT_CRITICAL(&host_lock) -#define HOST_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&host_lock) -#define HOST_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&host_lock) +DEFINE_CRIT_SECTION_LOCK_STATIC(host_lock); +#define HOST_ENTER_CRITICAL_ISR() esp_os_enter_critical_isr(&host_lock) +#define HOST_EXIT_CRITICAL_ISR() esp_os_exit_critical_isr(&host_lock) +#define HOST_ENTER_CRITICAL() esp_os_enter_critical(&host_lock) +#define HOST_EXIT_CRITICAL() esp_os_exit_critical(&host_lock) +#define HOST_ENTER_CRITICAL_SAFE() esp_os_enter_critical_safe(&host_lock) +#define HOST_EXIT_CRITICAL_SAFE() esp_os_exit_critical_safe(&host_lock) #define HOST_CHECK(cond, ret_val) ({ \ if (!(cond)) { \ @@ -309,21 +309,21 @@ static void usbh_event_callback(usbh_event_data_t *event_data, void *arg) break; } case USBH_EVENT_NEW_DEV: { + // Internal client + hub_notify_new_dev(event_data->new_dev_data.dev_addr); + // External clients // Prepare a NEW_DEV client event message, the send it to all clients usb_host_client_event_msg_t event_msg = { .event = USB_HOST_CLIENT_EVENT_NEW_DEV, .new_dev.address = event_data->new_dev_data.dev_addr, }; send_event_msg_to_clients(&event_msg, true, 0); -#if ENABLE_USB_HUBS - hub_notify_new_dev(event_data->new_dev_data.dev_addr); -#endif // ENABLE_USB_HUBS break; } case USBH_EVENT_DEV_GONE: { -#if ENABLE_USB_HUBS + // Internal client hub_notify_dev_gone(event_data->new_dev_data.dev_addr); -#endif // ENABLE_USB_HUBS + // External clients // Prepare event msg, send only to clients that have opened the device usb_host_client_event_msg_t event_msg = { .event = USB_HOST_CLIENT_EVENT_DEV_GONE, diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index 7ae5e5f3826b..220e63173214 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -6,11 +6,11 @@ #include #include -#include "freertos/FreeRTOS.h" #include "esp_log.h" #include "esp_check.h" #include "esp_private/periph_ctrl.h" #include "esp_private/usb_phy.h" +#include "esp_private/critical_section.h" #include "soc/usb_dwc_periph.h" #include "hal/usb_wrap_hal.h" #include "hal/usb_serial_jtag_hal.h" @@ -61,7 +61,10 @@ typedef struct { } usb_iopin_dsc_t; static phy_ctrl_obj_t *p_phy_ctrl_obj = NULL; -static portMUX_TYPE phy_spinlock = portMUX_INITIALIZER_UNLOCKED; + +DEFINE_CRIT_SECTION_LOCK_STATIC(phy_spinlock); +#define PHY_ENTER_CRITICAL() esp_os_enter_critical(&phy_spinlock) +#define PHY_EXIT_CRITICAL() esp_os_exit_critical(&phy_spinlock) static esp_err_t phy_iopins_configure(const usb_iopin_dsc_t *usb_periph_iopins, int iopins_num) { @@ -235,29 +238,29 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) static esp_err_t usb_phy_install(void) { - portENTER_CRITICAL(&phy_spinlock); + PHY_ENTER_CRITICAL(); if (p_phy_ctrl_obj) { // p_phy_ctrl_obj already installed, return immediately - portEXIT_CRITICAL(&phy_spinlock); + PHY_EXIT_CRITICAL(); return ESP_OK; } - portEXIT_CRITICAL(&phy_spinlock); + PHY_EXIT_CRITICAL(); esp_err_t ret = ESP_OK; phy_ctrl_obj_t *phy_ctrl_obj = (phy_ctrl_obj_t *) calloc(1, sizeof(phy_ctrl_obj_t)); ESP_GOTO_ON_FALSE(phy_ctrl_obj, ESP_ERR_NO_MEM, cleanup, USBPHY_TAG, "no mem for USB_PHY driver"); - portENTER_CRITICAL(&phy_spinlock); + PHY_ENTER_CRITICAL(); if (!p_phy_ctrl_obj) { p_phy_ctrl_obj = phy_ctrl_obj; p_phy_ctrl_obj->ref_count = 0; } else { // p_phy_ctrl_obj already installed, need to free resource - portEXIT_CRITICAL(&phy_spinlock); + PHY_EXIT_CRITICAL(); goto cleanup; } // Enable USB peripheral and reset the register - portEXIT_CRITICAL(&phy_spinlock); + PHY_EXIT_CRITICAL(); USB_WRAP_RCC_ATOMIC() { usb_wrap_ll_enable_bus_clock(true); usb_wrap_ll_reset_register(); @@ -281,7 +284,7 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r phy_context_t *phy_context = (phy_context_t *) calloc(1, sizeof(phy_context_t)); ESP_GOTO_ON_FALSE(phy_context, ESP_ERR_NO_MEM, cleanup, USBPHY_TAG, "no mem for phy context"); - portENTER_CRITICAL(&phy_spinlock); + PHY_ENTER_CRITICAL(); usb_phy_get_phy_status(config->target, &phy_context->status); if (phy_context->status == USB_PHY_STATUS_FREE) { new_phy = true; @@ -292,7 +295,7 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r p_phy_ctrl_obj->internal_phy = phy_context; } } - portEXIT_CRITICAL(&phy_spinlock); + PHY_EXIT_CRITICAL(); ESP_GOTO_ON_FALSE(new_phy, ESP_ERR_INVALID_STATE, cleanup, USBPHY_TAG, "selected PHY is in use"); phy_context->target = config->target; @@ -354,7 +357,7 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r static void phy_uninstall(void) { phy_ctrl_obj_t *p_phy_ctrl_obj_free = NULL; - portENTER_CRITICAL(&phy_spinlock); + PHY_ENTER_CRITICAL(); if (p_phy_ctrl_obj->ref_count == 0) { p_phy_ctrl_obj_free = p_phy_ctrl_obj; p_phy_ctrl_obj = NULL; @@ -363,7 +366,7 @@ static void phy_uninstall(void) usb_wrap_ll_enable_bus_clock(false); } } - portEXIT_CRITICAL(&phy_spinlock); + PHY_EXIT_CRITICAL(); free(p_phy_ctrl_obj_free); } @@ -371,7 +374,7 @@ esp_err_t usb_del_phy(usb_phy_handle_t handle) { ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, USBPHY_TAG, "handle argument is invalid"); - portENTER_CRITICAL(&phy_spinlock); + PHY_ENTER_CRITICAL(); p_phy_ctrl_obj->ref_count--; if (handle->target == USB_PHY_TARGET_EXT) { p_phy_ctrl_obj->external_phy = NULL; @@ -380,7 +383,7 @@ esp_err_t usb_del_phy(usb_phy_handle_t handle) usb_wrap_hal_phy_disable_pull_override(&handle->wrap_hal); p_phy_ctrl_obj->internal_phy = NULL; } - portEXIT_CRITICAL(&phy_spinlock); + PHY_EXIT_CRITICAL(); free(handle->iopins); free(handle); phy_uninstall(); diff --git a/components/usb/usb_phy_p4.c b/components/usb/usb_phy_p4.c index b81e9be54836..43611c393c4b 100644 --- a/components/usb/usb_phy_p4.c +++ b/components/usb/usb_phy_p4.c @@ -4,47 +4,33 @@ * SPDX-License-Identifier: Apache-2.0 */ -// TODO: Refactor during the IDF-9198 -#include "sdkconfig.h" -#include "soc/soc_caps.h" -#include "soc/usb_dwc_cfg.h" -#include "hal/usb_utmi_ll.h" // We don't have usb_utmi_hal yet -#include "esp_private/periph_ctrl.h" -// TODO: Remove this file when proper support of P4 PHYs is implemented IDF-7323 +// TODO: Remove this file when proper support of P4 PHYs is implemented IDF-11144 +#include "hal/usb_utmi_hal.h" #include "esp_private/usb_phy.h" -#include "esp_private/periph_ctrl.h" +#include "soc/soc_caps.h" #if SOC_RCC_IS_INDEPENDENT #define USB_UTMI_BUS_CLK_ATOMIC() #else +#include "esp_private/periph_ctrl.h" #define USB_UTMI_BUS_CLK_ATOMIC() PERIPH_RCC_ATOMIC() #endif +static usb_utmi_hal_context_t s_utmi_hal_context; + esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_ret) { -#if (OTG_HSPHY_INTERFACE != 0) -#if CONFIG_IDF_TARGET_ESP32P4 USB_UTMI_BUS_CLK_ATOMIC() { - usb_utmi_ll_enable_bus_clock(true); - usb_utmi_ll_reset_register(); + usb_utmi_hal_init(&s_utmi_hal_context); } - /* - Additional setting to solve missing DCONN event on ESP32P4 (IDF-9953). - - Note: On ESP32P4, the HP_SYSTEM_OTG_SUSPENDM is not connected to 1 by hardware. - For correct detection of the device detaching, internal signal should be set to 1 by the software. - */ - usb_utmi_ll_enable_precise_detection(true); - usb_utmi_ll_configure_ls(&USB_UTMI, true); -#endif // CONFIG_IDF_TARGET_ESP32P4 -#endif // (OTG_HSPHY_INTERFACE != 0) return ESP_OK; } esp_err_t usb_del_phy(usb_phy_handle_t handle) { + // Note: handle argument is not checked, because we don't have phy_handle for P4 yet USB_UTMI_BUS_CLK_ATOMIC() { - usb_utmi_ll_enable_bus_clock(false); + usb_utmi_hal_disable(); } return ESP_OK; } diff --git a/components/usb/usbh.c b/components/usb/usbh.c index 75188f02d9c7..54355ace682b 100644 --- a/components/usb/usbh.c +++ b/components/usb/usbh.c @@ -10,9 +10,8 @@ #include #include #include "freertos/FreeRTOS.h" -#include "freertos/portmacro.h" -#include "freertos/task.h" #include "freertos/semphr.h" +#include "esp_private/critical_section.h" #include "esp_err.h" #include "esp_log.h" #include "esp_heap_caps.h" @@ -117,16 +116,15 @@ typedef struct { static usbh_t *p_usbh_obj = NULL; -static portMUX_TYPE usbh_lock = portMUX_INITIALIZER_UNLOCKED; - const char *USBH_TAG = "USBH"; -#define USBH_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&usbh_lock) -#define USBH_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&usbh_lock) -#define USBH_ENTER_CRITICAL() portENTER_CRITICAL(&usbh_lock) -#define USBH_EXIT_CRITICAL() portEXIT_CRITICAL(&usbh_lock) -#define USBH_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&usbh_lock) -#define USBH_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&usbh_lock) +DEFINE_CRIT_SECTION_LOCK_STATIC(usbh_lock); +#define USBH_ENTER_CRITICAL_ISR() esp_os_enter_critical_isr(&usbh_lock) +#define USBH_EXIT_CRITICAL_ISR() esp_os_exit_critical_isr(&usbh_lock) +#define USBH_ENTER_CRITICAL() esp_os_enter_critical(&usbh_lock) +#define USBH_EXIT_CRITICAL() esp_os_exit_critical(&usbh_lock) +#define USBH_ENTER_CRITICAL_SAFE() esp_os_enter_critical_safe(&usbh_lock) +#define USBH_EXIT_CRITICAL_SAFE() esp_os_exit_critical_safe(&usbh_lock) #define USBH_CHECK(cond, ret_val) ({ \ if (!(cond)) { \ @@ -1050,7 +1048,6 @@ esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl) if (dev_obj->dynamic.open_count == 0) { // Sanity check. assert(dev_obj->dynamic.num_ctrl_xfers_inflight == 0); // There cannot be any control transfer in-flight - assert(!dev_obj->dynamic.flags.waiting_free); // This can only be set when open_count reaches 0 if (dev_obj->dynamic.flags.is_gone || dev_obj->dynamic.flags.waiting_free) { // Device is already gone or is awaiting to be freed. Trigger the USBH process to free the device call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_FREE); diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index 655bbf5790f9..8e71115a435e 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -29,6 +29,8 @@ #include #include "sdkconfig.h" +#include "esp_vfs_ops.h" + #ifdef __cplusplus extern "C" { #endif @@ -62,20 +64,11 @@ extern "C" { */ #define ESP_VFS_FLAG_READONLY_FS (1 << 2) -/* - * @brief VFS identificator used for esp_vfs_register_with_id() - */ -typedef int esp_vfs_id_t; - /** - * @brief VFS semaphore type for select() - * + * Flag which indicates that VFS structure should be freed upon unregistering. + * @note Free if false, do not free if true */ -typedef struct -{ - bool is_sem_local; /*!< type of "sem" is SemaphoreHandle_t when true, defined by socket driver otherwise */ - void *sem; /*!< semaphore instance */ -} esp_vfs_select_sem_t; +#define ESP_VFS_FLAG_STATIC (1 << 3) /** * @brief VFS definition structure @@ -259,6 +252,8 @@ typedef struct #endif // CONFIG_VFS_SUPPORT_SELECT || defined __DOXYGEN__ } esp_vfs_t; + + /** * Register a virtual filesystem for given path prefix. * @@ -284,7 +279,6 @@ typedef struct */ esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ctx); - /** * Special case function for registering a VFS that uses a method other than * open() to open new file descriptors from the interval : -> + + where: + index : internal index in the table of registered FSs (the same as returned when registering fd with id) + VFS Path Prefix : file prefix used in the esp_vfs_register call or "NULL" + VFS entry ptr : pointer to the esp_vfs_fs_ops_t struct used internally when resolving the calls + @endverbatim + * + * @param fp File descriptor where data will be dumped + */ +void esp_vfs_dump_registered_paths(FILE *fp); + #ifdef __cplusplus } // extern "C" #endif diff --git a/components/vfs/include/esp_vfs_ops.h b/components/vfs/include/esp_vfs_ops.h new file mode 100644 index 000000000000..bd5d635235ce --- /dev/null +++ b/components/vfs/include/esp_vfs_ops.h @@ -0,0 +1,308 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include +#include +#include +#include +#include +#include +#ifdef __clang__ // TODO LLVM-330 +#include +#else +#include +#endif +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _SYS_TYPES_FD_SET +#error "VFS should be used with FD_SETSIZE and FD_SET from sys/types.h" +#endif + +/* + * @brief VFS identificator used for esp_vfs_register_with_id() + */ +typedef int esp_vfs_id_t; + +/** + * @brief VFS semaphore type for select() + * + */ +typedef struct +{ + bool is_sem_local; /*!< type of "sem" is SemaphoreHandle_t when true, defined by socket driver otherwise */ + void *sem; /*!< semaphore instance */ +} esp_vfs_select_sem_t; + +#ifdef CONFIG_VFS_SUPPORT_DIR + +/** + * @brief Struct containing function pointers to directory related functionality. + * + */ +typedef struct { + union { + int (*stat_p)(void* ctx, const char * path, struct stat * st); /*!< stat with context pointer */ + int (*stat)(const char * path, struct stat * st); /*!< stat without context pointer */ + }; + union { + int (*link_p)(void* ctx, const char* n1, const char* n2); /*!< link with context pointer */ + int (*link)(const char* n1, const char* n2); /*!< link without context pointer */ + }; + union { + int (*unlink_p)(void* ctx, const char *path); /*!< unlink with context pointer */ + int (*unlink)(const char *path); /*!< unlink without context pointer */ + }; + union { + int (*rename_p)(void* ctx, const char *src, const char *dst); /*!< rename with context pointer */ + int (*rename)(const char *src, const char *dst); /*!< rename without context pointer */ + }; + union { + DIR* (*opendir_p)(void* ctx, const char* name); /*!< opendir with context pointer */ + DIR* (*opendir)(const char* name); /*!< opendir without context pointer */ + }; + union { + struct dirent* (*readdir_p)(void* ctx, DIR* pdir); /*!< readdir with context pointer */ + struct dirent* (*readdir)(DIR* pdir); /*!< readdir without context pointer */ + }; + union { + int (*readdir_r_p)(void* ctx, DIR* pdir, struct dirent* entry, struct dirent** out_dirent); /*!< readdir_r with context pointer */ + int (*readdir_r)(DIR* pdir, struct dirent* entry, struct dirent** out_dirent); /*!< readdir_r without context pointer */ + }; + union { + long (*telldir_p)(void* ctx, DIR* pdir); /*!< telldir with context pointer */ + long (*telldir)(DIR* pdir); /*!< telldir without context pointer */ + }; + union { + void (*seekdir_p)(void* ctx, DIR* pdir, long offset); /*!< seekdir with context pointer */ + void (*seekdir)(DIR* pdir, long offset); /*!< seekdir without context pointer */ + }; + union { + int (*closedir_p)(void* ctx, DIR* pdir); /*!< closedir with context pointer */ + int (*closedir)(DIR* pdir); /*!< closedir without context pointer */ + }; + union { + int (*mkdir_p)(void* ctx, const char* name, mode_t mode); /*!< mkdir with context pointer */ + int (*mkdir)(const char* name, mode_t mode); /*!< mkdir without context pointer */ + }; + union { + int (*rmdir_p)(void* ctx, const char* name); /*!< rmdir with context pointer */ + int (*rmdir)(const char* name); /*!< rmdir without context pointer */ + }; + union { + int (*access_p)(void* ctx, const char *path, int amode); /*!< access with context pointer */ + int (*access)(const char *path, int amode); /*!< access without context pointer */ + }; + union { + int (*truncate_p)(void* ctx, const char *path, off_t length); /*!< truncate with context pointer */ + int (*truncate)(const char *path, off_t length); /*!< truncate without context pointer */ + }; + union { + int (*ftruncate_p)(void* ctx, int fd, off_t length); /*!< ftruncate with context pointer */ + int (*ftruncate)(int fd, off_t length); /*!< ftruncate without context pointer */ + }; + union { + int (*utime_p)(void* ctx, const char *path, const struct utimbuf *times); /*!< utime with context pointer */ + int (*utime)(const char *path, const struct utimbuf *times); /*!< utime without context pointer */ + }; +} esp_vfs_dir_ops_t; + +#endif // CONFIG_VFS_SUPPORT_DIR + +#ifdef CONFIG_VFS_SUPPORT_TERMIOS + +/** + * @brief Struct containing function pointers to termios related functionality. + * + */ +typedef struct { + union { + int (*tcsetattr_p)(void *ctx, int fd, int optional_actions, const struct termios *p); /*!< tcsetattr with context pointer */ + int (*tcsetattr)(int fd, int optional_actions, const struct termios *p); /*!< tcsetattr without context pointer */ + }; + union { + int (*tcgetattr_p)(void *ctx, int fd, struct termios *p); /*!< tcgetattr with context pointer */ + int (*tcgetattr)(int fd, struct termios *p); /*!< tcgetattr without context pointer */ + }; + union { + int (*tcdrain_p)(void *ctx, int fd); /*!< tcdrain with context pointer */ + int (*tcdrain)(int fd); /*!< tcdrain without context pointer */ + }; + union { + int (*tcflush_p)(void *ctx, int fd, int select); /*!< tcflush with context pointer */ + int (*tcflush)(int fd, int select); /*!< tcflush without context pointer */ + }; + union { + int (*tcflow_p)(void *ctx, int fd, int action); /*!< tcflow with context pointer */ + int (*tcflow)(int fd, int action); /*!< tcflow without context pointer */ + }; + union { + pid_t (*tcgetsid_p)(void *ctx, int fd); /*!< tcgetsid with context pointer */ + pid_t (*tcgetsid)(int fd); /*!< tcgetsid without context pointer */ + }; + union { + int (*tcsendbreak_p)(void *ctx, int fd, int duration); /*!< tcsendbreak with context pointer */ + int (*tcsendbreak)(int fd, int duration); /*!< tcsendbreak without context pointer */ + }; +} esp_vfs_termios_ops_t; + +#endif // CONFIG_VFS_SUPPORT_TERMIOS + +#ifdef CONFIG_VFS_SUPPORT_SELECT + +/** + * @brief Struct containing function pointers to select related functionality. + * + */ +typedef struct { + /** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */ + esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, esp_vfs_select_sem_t sem, void **end_select_args); + + /** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */ + int (*socket_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); + + /** called by VFS to interrupt the socket_select call when select is activated from a non-socket VFS driver; set only for the socket driver */ + void (*stop_socket_select)(void *sem); + + /** stop_socket_select which can be called from ISR; set only for the socket driver */ + void (*stop_socket_select_isr)(void *sem, BaseType_t *woken); + + /** end_select is called to stop the I/O multiplexing and deinitialize the environment created by start_select for the given VFS */ + void* (*get_socket_select_semaphore)(void); + + /** get_socket_select_semaphore returns semaphore allocated in the socket driver; set only for the socket driver */ + esp_err_t (*end_select)(void *end_select_args); +} esp_vfs_select_ops_t; + +#endif // CONFIG_VFS_SUPPORT_SELECT + +/** + * @brief Main struct of the minified vfs API, containing basic function pointers as well as pointers to the other subcomponents. + * + */ +typedef struct { + union { + ssize_t (*write_p)(void* p, int fd, const void * data, size_t size); /*!< Write with context pointer */ + ssize_t (*write)(int fd, const void * data, size_t size); /*!< Write without context pointer */ + }; + union { + off_t (*lseek_p)(void* p, int fd, off_t size, int mode); /*!< Seek with context pointer */ + off_t (*lseek)(int fd, off_t size, int mode); /*!< Seek without context pointer */ + }; + union { + ssize_t (*read_p)(void* ctx, int fd, void * dst, size_t size); /*!< Read with context pointer */ + ssize_t (*read)(int fd, void * dst, size_t size); /*!< Read without context pointer */ + }; + union { + ssize_t (*pread_p)(void *ctx, int fd, void * dst, size_t size, off_t offset); /*!< pread with context pointer */ + ssize_t (*pread)(int fd, void * dst, size_t size, off_t offset); /*!< pread without context pointer */ + }; + union { + ssize_t (*pwrite_p)(void *ctx, int fd, const void *src, size_t size, off_t offset); /*!< pwrite with context pointer */ + ssize_t (*pwrite)(int fd, const void *src, size_t size, off_t offset); /*!< pwrite without context pointer */ + }; + union { + int (*open_p)(void* ctx, const char * path, int flags, int mode); /*!< open with context pointer */ + int (*open)(const char * path, int flags, int mode); /*!< open without context pointer */ + }; + union { + int (*close_p)(void* ctx, int fd); /*!< close with context pointer */ + int (*close)(int fd); /*!< close without context pointer */ + }; + union { + int (*fstat_p)(void* ctx, int fd, struct stat * st); /*!< fstat with context pointer */ + int (*fstat)(int fd, struct stat * st); /*!< fstat without context pointer */ + }; + union { + int (*fcntl_p)(void* ctx, int fd, int cmd, int arg); /*!< fcntl with context pointer */ + int (*fcntl)(int fd, int cmd, int arg); /*!< fcntl without context pointer */ + }; + union { + int (*ioctl_p)(void* ctx, int fd, int cmd, va_list args); /*!< ioctl with context pointer */ + int (*ioctl)(int fd, int cmd, va_list args); /*!< ioctl without context pointer */ + }; + union { + int (*fsync_p)(void* ctx, int fd); /*!< fsync with context pointer */ + int (*fsync)(int fd); /*!< fsync without context pointer */ + }; + +#ifdef CONFIG_VFS_SUPPORT_DIR + esp_vfs_dir_ops_t *dir; /*!< pointer to the dir subcomponent */ +#endif + +#ifdef CONFIG_VFS_SUPPORT_TERMIOS + esp_vfs_termios_ops_t *termios; /*!< pointer to the termios subcomponent */ +#endif + +#if CONFIG_VFS_SUPPORT_SELECT || defined __DOXYGEN__ + esp_vfs_select_ops_t *select; /*!< pointer to the select subcomponent */ +#endif + +} esp_vfs_fs_ops_t; + +/** + * Register a virtual filesystem for given path prefix. + * + * @param base_path file path prefix associated with the filesystem. + * Must be a zero-terminated C string, may be empty. + * If not empty, must be up to ESP_VFS_PATH_MAX + * characters long, and at least 2 characters long. + * Name must start with a "/" and must not end with "/". + * For example, "/data" or "/dev/spi" are valid. + * These VFSes would then be called to handle file paths such as + * "/data/myfile.txt" or "/dev/spi/0". + * In the special case of an empty base_path, a "fallback" + * VFS is registered. Such VFS will handle paths which are not + * matched by any other registered VFS. + * @param vfs Pointer to esp_vfs_fs_ops_t, a structure which maps syscalls to + * the filesystem driver functions. VFS component does not assume ownership of this struct, but see flags for more info + * + * @param flags Set of binary flags controlling how the registered FS should be treated + * - ESP_VFS_FLAG_STATIC - if this flag is specified VFS assumes the provided esp_vfs_fs_ops_t and all its subcomponents are statically allocated, + * if it is not enabled a deep copy of the provided struct will be created, which will be managed by the VFS component + * - ESP_VFS_FLAG_CONTEXT_PTR - If set, the VFS will use the context-aware versions of the filesystem operation functions (suffixed with `_p`) in `esp_vfs_fs_ops_t` and its subcomponents. + * The `ctx` parameter will be passed as the context argument when these functions are invoked. + * + * @param ctx Context pointer for fs operation functions, see the ESP_VFS_FLAG_CONTEXT_PTR. + * Should be `NULL` if not used. + * + * @return ESP_OK if successful, ESP_ERR_NO_MEM if too many FSes are + * registered. + */ +esp_err_t esp_vfs_register_fs(const char* base_path, const esp_vfs_fs_ops_t* vfs, int flags, void* ctx); + +/** + * Analog of esp_vfs_register_with_id which accepts esp_vfs_fs_ops_t instead. + * + */ +esp_err_t esp_vfs_register_fs_with_id(const esp_vfs_fs_ops_t* vfs, int flags, void* ctx, esp_vfs_id_t* id); + +/** + * Alias for esp_vfs_unregister for naming consistency + */ +esp_err_t esp_vfs_unregister_fs(const char* base_path); + +/** + * Alias for esp_vfs_unregister_with_id for naming consistency + */ +esp_err_t esp_vfs_unregister_fs_with_id(esp_vfs_id_t id); + +#ifdef __cplusplus +} +#endif diff --git a/components/vfs/private_include/esp_vfs_private.h b/components/vfs/private_include/esp_vfs_private.h index fda3e9712ba7..5dcca69b55fe 100644 --- a/components/vfs/private_include/esp_vfs_private.h +++ b/components/vfs/private_include/esp_vfs_private.h @@ -19,7 +19,8 @@ extern "C" { #endif typedef struct vfs_entry_ { - esp_vfs_t vfs; // contains pointers to VFS functions + int flags; /*!< ESP_VFS_FLAG_CONTEXT_PTR and/or ESP_VFS_FLAG_READONLY_FS or ESP_VFS_FLAG_DEFAULT */ + const esp_vfs_fs_ops_t *vfs; // contains pointers to VFS functions char path_prefix[ESP_VFS_PATH_MAX]; // path prefix mapped to this VFS size_t path_prefix_len; // micro-optimization to avoid doing extra strlen void* ctx; // optional pointer which can be passed to VFS diff --git a/components/vfs/test_apps/.build-test-rules.yml b/components/vfs/test_apps/.build-test-rules.yml index 5a050d00c463..6f8e89a2a642 100644 --- a/components/vfs/test_apps/.build-test-rules.yml +++ b/components/vfs/test_apps/.build-test-rules.yml @@ -1,8 +1,4 @@ components/vfs/test_apps: - disable: - - if: IDF_TARGET in ["esp32c5", "esp32c61"] - temporary: true - reason: not support yet # TODO: [ESP32C5] IDF-8704, [esp32c61] IDF-9305 disable_test: - if: IDF_TARGET not in ["esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s3"] temporary: true diff --git a/components/vfs/test_apps/README.md b/components/vfs/test_apps/README.md index bf47d80ec649..7b96141437ec 100644 --- a/components/vfs/test_apps/README.md +++ b/components/vfs/test_apps/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/components/vfs/test_apps/main/CMakeLists.txt b/components/vfs/test_apps/main/CMakeLists.txt index 7ab4968a9e0e..e7cfc100f531 100644 --- a/components/vfs/test_apps/main/CMakeLists.txt +++ b/components/vfs/test_apps/main/CMakeLists.txt @@ -3,6 +3,7 @@ set(src "test_app_main.c" "test_vfs_access.c" "test_vfs_fd.c" "test_vfs_lwip.c" "test_vfs_open.c" "test_vfs_paths.c" "test_vfs_select.c" "test_vfs_nullfs.c" + "test_vfs_minified.c" ) idf_component_register(SRCS ${src} diff --git a/components/vfs/test_apps/main/test_vfs_lwip.c b/components/vfs/test_apps/main/test_vfs_lwip.c index 3bed7d5ec8b9..e9cf3870ab50 100644 --- a/components/vfs/test_apps/main/test_vfs_lwip.c +++ b/components/vfs/test_apps/main/test_vfs_lwip.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,8 +15,9 @@ TEST_CASE("fstat() sets st_mode to socket type", "[vfs][lwip]") { test_case_uses_tcpip(); int socket_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + TEST_ASSERT(socket_fd >= 0); struct stat stat = { 0 }; - fstat(socket_fd, &stat); + TEST_ASSERT_EQUAL(0, fstat(socket_fd, &stat)); TEST_ASSERT_TRUE(S_ISSOCK(stat.st_mode)); TEST_ASSERT_FALSE(S_ISBLK(stat.st_mode)); @@ -25,5 +26,5 @@ TEST_CASE("fstat() sets st_mode to socket type", "[vfs][lwip]") TEST_ASSERT_FALSE(S_ISREG(stat.st_mode)); TEST_ASSERT_FALSE(S_ISLNK(stat.st_mode)); - close(socket_fd); + TEST_ASSERT_EQUAL(0, close(socket_fd)); } diff --git a/components/vfs/test_apps/main/test_vfs_minified.c b/components/vfs/test_apps/main/test_vfs_minified.c new file mode 100644 index 000000000000..bef2e507fbac --- /dev/null +++ b/components/vfs/test_apps/main/test_vfs_minified.c @@ -0,0 +1,166 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include + +#include "esp_err.h" +#include "esp_vfs_ops.h" +#include "unity.h" +#include "esp_vfs.h" + +#include "unity_test_runner.h" + +#define BUF_CAP 1024 + +typedef struct { + uint8_t data[BUF_CAP]; + size_t head; + size_t tail; +} cb_t; + +void cb_reset(cb_t* buf) { + buf->head = 0; + buf->tail = 0; +} + +size_t cb_count(const cb_t *buf) { + return buf->head - buf->tail; +} + +int cb_write(cb_t *buf, const uint8_t *data, size_t size) { + size_t count = cb_count(buf); + size_t space = BUF_CAP - count; + + size_t to_write = (size > space) ? space : size; + + size_t idx = buf->head % BUF_CAP; + size_t first_chunk = BUF_CAP - idx; + if (first_chunk > to_write) + first_chunk = to_write; + + memcpy(&buf->data[idx], data, first_chunk); + buf->head += first_chunk; + + if (first_chunk < to_write) { + size_t second_chunk = to_write - first_chunk; + memcpy(&buf->data[0], data + first_chunk, second_chunk); + buf->head += second_chunk; + } + + return (int)to_write; +} + +int cb_read(cb_t *buf, uint8_t *dest, size_t count) { + size_t available = cb_count(buf); + size_t to_read = (count > available) ? available : count; + + size_t idx = buf->tail % BUF_CAP; + size_t first_chunk = BUF_CAP - idx; + if (first_chunk > to_read) + first_chunk = to_read; + + memcpy(dest, &buf->data[idx], first_chunk); + buf->tail += first_chunk; + + if (first_chunk < to_read) { + size_t second_chunk = to_read - first_chunk; + memcpy(dest + first_chunk, &buf->data[0], second_chunk); + buf->tail += second_chunk; + } + + return (int)to_read; +} + + +int buffer_open(void *ctx, const char *path, int flags, int mode) { + return 0; +} + +int buffer_write(void *ctx, int fd, const void *data, size_t size) { + cb_t* buf = (cb_t*) ctx; + return cb_write(buf, data, size); +} + +int buffer_read(void *ctx, int fd, void *data, size_t size) { + cb_t* buf = (cb_t*) ctx; + return cb_read(buf, data, size); +} + +int buffer_close(void *ctx, int fd) { + cb_reset((cb_t*) ctx); + return 0; +} + +static esp_vfs_fs_ops_t s_buffer_fs = { + .write_p = buffer_write, + .read_p = buffer_read, + .open_p = buffer_open, + .close_p = buffer_close, +}; + +TEST_CASE("VFS won't create a copy when ESP_FLAG_VFS_STATIC is specified", "[esp_vfs_fs_ops_t]") +{ + TEST_MESSAGE("test"); + static esp_vfs_dir_ops_t dir = {}; + static esp_vfs_fs_ops_t vfs = { + .dir = &dir, + }; + + cb_t *buffer = calloc(1, sizeof(cb_t)); + + esp_err_t err = ESP_OK; + err = esp_vfs_register_fs("/buffer", &s_buffer_fs, ESP_VFS_FLAG_CONTEXT_PTR | ESP_VFS_FLAG_STATIC, buffer); + TEST_ASSERT_EQUAL(ESP_OK, err); + + err = esp_vfs_register_fs("/static", &vfs, ESP_VFS_FLAG_STATIC, NULL); + TEST_ASSERT_EQUAL(ESP_OK, err); + + err = esp_vfs_register_fs("/dynamic", &vfs, ESP_VFS_FLAG_DEFAULT, NULL); + TEST_ASSERT_EQUAL(ESP_OK, err); + + FILE *buf_f = fopen("/buffer/a", "r+"); + + esp_vfs_dump_registered_paths(buf_f); + + char read_buffer[512]; + size_t bytes_read = fread(read_buffer, 1, sizeof(read_buffer) - 1, buf_f); + read_buffer[bytes_read] = '\0'; // Null-terminate the string + + // Parse the buffer to extract VFS pointers + char *line = strtok(read_buffer, "\n"); + void *static_vfs_ptr = NULL; + void *dynamic_vfs_ptr = NULL; + + while (line != NULL) { + int index; + char path_prefix[64]; + char ptr_str[32]; + TEST_MESSAGE(line); + if (sscanf(line, "%d:%63s -> %31s", &index, path_prefix, ptr_str) == 3) { + void *vfs_ptr = (void *)strtoul(ptr_str, NULL, 0); + if (strcmp(path_prefix, "/static") == 0) { + static_vfs_ptr = vfs_ptr; + } else if (strcmp(path_prefix, "/dynamic") == 0) { + dynamic_vfs_ptr = vfs_ptr; + } + } + line = strtok(NULL, "\n"); + } + + // Check that the pointer for "/static" is the same as 'vfs' and "/dynamic" is different + TEST_ASSERT_EQUAL_PTR(&vfs, static_vfs_ptr); + TEST_ASSERT_NOT_EQUAL(&vfs, dynamic_vfs_ptr); + + free(buffer); + fclose(buf_f); + + esp_vfs_unregister("/buffer"); + esp_vfs_unregister("/static"); + esp_vfs_unregister("/dynamic"); +} diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index 906e8684d9d9..1f02e0f55096 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -19,6 +19,7 @@ #include "freertos/semphr.h" #include "esp_vfs.h" #include "esp_vfs_private.h" +#include "include/esp_vfs.h" #include "sdkconfig.h" // Warn about using deprecated option @@ -75,8 +76,283 @@ static size_t s_vfs_count = 0; static fd_table_t s_fd_table[MAX_FDS] = { [0 ... MAX_FDS-1] = FD_TABLE_ENTRY_UNUSED }; static _lock_t s_fd_table_lock; -esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index) +static ssize_t esp_get_free_index(void) { + for (ssize_t i = 0; i < VFS_MAX_COUNT; i++) { + if (s_vfs[i] == NULL) { + return i; + } + } + return -1; +} + +static void esp_vfs_free_fs_ops(esp_vfs_fs_ops_t *vfs) { +#ifdef CONFIG_VFS_SUPPORT_TERMIOS + free(vfs->termios); +#endif + +#ifdef CONFIG_VFS_SUPPORT_DIR + free(vfs->dir); +#endif + +#ifdef CONFIG_VFS_SUPPORT_SELECT + free(vfs->select); +#endif + + free(vfs); +} + +static void esp_vfs_free_entry(vfs_entry_t *entry) { + if (entry == NULL) { // Necessary because of the following flags check + return; + } + + if (!(entry->flags & ESP_VFS_FLAG_STATIC)) { + esp_vfs_free_fs_ops((esp_vfs_fs_ops_t*)entry->vfs); // const cast, but we know it's not static from the flag + } + + free(entry); +} + +static void esp_minify_vfs(const esp_vfs_t * const vfs, esp_vfs_fs_ops_t *min) { + assert(vfs != NULL); + assert(min != NULL); + *min = (esp_vfs_fs_ops_t) { + .write = vfs->write, + .lseek = vfs->lseek, + .read = vfs->read, + .pread = vfs->pread, + .pwrite = vfs->pwrite, + .open = vfs->open, + .close = vfs->close, + .fstat = vfs->fstat, + .fcntl = vfs->fcntl, + .ioctl = vfs->ioctl, + .fsync = vfs->fsync, +#ifdef CONFIG_VFS_SUPPORT_DIR + .dir = min->dir, +#endif +#ifdef CONFIG_VFS_SUPPORT_TERMIOS + .termios = min->termios, +#endif +#ifdef CONFIG_VFS_SUPPORT_SELECT + .select = min->select, +#endif + }; + +#ifdef CONFIG_VFS_SUPPORT_DIR + // If the dir functions are not implemented, we don't need to convert them + if (min->dir != NULL) { + *(min->dir) = (esp_vfs_dir_ops_t) { + .stat = vfs->stat, + .link = vfs->link, + .unlink = vfs->unlink, + .rename = vfs->rename, + .opendir = vfs->opendir, + .readdir = vfs->readdir, + .readdir_r = vfs->readdir_r, + .telldir = vfs->telldir, + .seekdir = vfs->seekdir, + .closedir = vfs->closedir, + .mkdir = vfs->mkdir, + .rmdir = vfs->rmdir, + .access = vfs->access, + .truncate = vfs->truncate, + .ftruncate = vfs->ftruncate, + .utime = vfs->utime, + }; + } +#endif // CONFIG_VFS_SUPPORT_DIR + +#ifdef CONFIG_VFS_SUPPORT_TERMIOS + // If the termios functions are not implemented, we don't need to convert them + if (min->termios != NULL) { + *(min->termios) = (esp_vfs_termios_ops_t) { + .tcsetattr = vfs->tcsetattr, + .tcgetattr = vfs->tcgetattr, + .tcdrain = vfs->tcdrain, + .tcflush = vfs->tcflush, + .tcflow = vfs->tcflow, + .tcgetsid = vfs->tcgetsid, + .tcsendbreak = vfs->tcsendbreak, + }; + } +#endif // CONFIG_VFS_SUPPORT_TERMIOS + +#ifdef CONFIG_VFS_SUPPORT_SELECT + // If the select functions are not implemented, we don't need to convert them + if (min->select != NULL) { + *(min->select) = (esp_vfs_select_ops_t) { + .start_select = vfs->start_select, + .socket_select = vfs->socket_select, + .stop_socket_select = vfs->stop_socket_select, + .stop_socket_select_isr = vfs->stop_socket_select_isr, + .get_socket_select_semaphore = vfs->get_socket_select_semaphore, + .end_select = vfs->end_select, + }; + } +#endif // CONFIG_VFS_SUPPORT_SELECT + +} + +static esp_vfs_fs_ops_t* esp_vfs_duplicate_fs_ops(const esp_vfs_fs_ops_t *vfs) { + esp_vfs_fs_ops_t *min = (esp_vfs_fs_ops_t*) heap_caps_malloc(sizeof(esp_vfs_fs_ops_t), VFS_MALLOC_FLAGS); + if (min == NULL) { + return NULL; + } + + memcpy(min, vfs, sizeof(esp_vfs_fs_ops_t)); + + // remove references to the original components +#ifdef CONFIG_VFS_SUPPORT_DIR + min->dir = NULL; +#endif +#ifdef CONFIG_VFS_SUPPORT_TERMIOS + min->termios = NULL; +#endif +#ifdef CONFIG_VFS_SUPPORT_SELECT + min->select = NULL; +#endif + +#ifdef CONFIG_VFS_SUPPORT_DIR + if (vfs->dir != NULL) { + min->dir = (esp_vfs_dir_ops_t*) heap_caps_malloc(sizeof(esp_vfs_dir_ops_t), VFS_MALLOC_FLAGS); + if (min->dir == NULL) { + goto fail; + } + memcpy(min->dir, vfs->dir, sizeof(esp_vfs_dir_ops_t)); + } +#endif + +#ifdef CONFIG_VFS_SUPPORT_TERMIOS + if (vfs->termios != NULL) { + min->termios = (esp_vfs_termios_ops_t*) heap_caps_malloc(sizeof(esp_vfs_termios_ops_t), VFS_MALLOC_FLAGS); + if (min->termios == NULL) { + goto fail; + } + memcpy(min->termios, vfs->termios, sizeof(esp_vfs_termios_ops_t)); + } +#endif + +#ifdef CONFIG_VFS_SUPPORT_SELECT + if (vfs->select != NULL) { + min->select = (esp_vfs_select_ops_t*) heap_caps_malloc(sizeof(esp_vfs_select_ops_t), VFS_MALLOC_FLAGS); + if (min->select == NULL) { + goto fail; + } + memcpy(min->select, vfs->select, sizeof(esp_vfs_select_ops_t)); + } +#endif + + return min; + +#if defined(CONFIG_VFS_SUPPORT_SELECT) || defined(CONFIG_VFS_SUPPORT_TERMIOS) || defined(CONFIG_VFS_SUPPORT_DIR) +fail: +#endif + esp_vfs_free_fs_ops(min); + return NULL; +} + +static esp_err_t esp_vfs_make_fs_ops(const esp_vfs_t *vfs, esp_vfs_fs_ops_t **min) { + if (vfs == NULL) { + ESP_LOGE(TAG, "Cannot minify NULL VFS"); + return ESP_ERR_INVALID_ARG; + } + + if (min == NULL) { + ESP_LOGE(TAG, "Cannot minify VFS to NULL"); + return ESP_ERR_INVALID_ARG; + } + + esp_vfs_fs_ops_t *main = (esp_vfs_fs_ops_t*) heap_caps_malloc(sizeof(esp_vfs_fs_ops_t), VFS_MALLOC_FLAGS); + if (main == NULL) { + return ESP_ERR_NO_MEM; + } + + // Initialize all fields to NULL + memset(main, 0, sizeof(esp_vfs_fs_ops_t)); + +#ifdef CONFIG_VFS_SUPPORT_DIR + bool skip_dir = + vfs->stat == NULL && + vfs->link == NULL && + vfs->unlink == NULL && + vfs->rename == NULL && + vfs->opendir == NULL && + vfs->readdir == NULL && + vfs->readdir_r == NULL && + vfs->telldir == NULL && + vfs->seekdir == NULL && + vfs->closedir == NULL && + vfs->mkdir == NULL && + vfs->rmdir == NULL && + vfs->access == NULL && + vfs->truncate == NULL && + vfs->ftruncate == NULL && + vfs->utime == NULL; + + if (!skip_dir) { + main->dir = (esp_vfs_dir_ops_t*) heap_caps_malloc(sizeof(esp_vfs_dir_ops_t), VFS_MALLOC_FLAGS); + if (main->dir == NULL) { + goto fail; + } + } +#endif + +#ifdef CONFIG_VFS_SUPPORT_TERMIOS + bool skip_termios = + vfs->tcsetattr == NULL && + vfs->tcgetattr == NULL && + vfs->tcdrain == NULL && + vfs->tcflush == NULL && + vfs->tcflow == NULL && + vfs->tcgetsid == NULL && + vfs->tcsendbreak == NULL; + + if (!skip_termios) { + main->termios = (esp_vfs_termios_ops_t*) heap_caps_malloc(sizeof(esp_vfs_termios_ops_t), VFS_MALLOC_FLAGS); + if (main->termios == NULL) { + goto fail; + } + } +#endif + +#ifdef CONFIG_VFS_SUPPORT_SELECT + bool skip_select = + vfs->start_select == NULL && + vfs->socket_select == NULL && + vfs->stop_socket_select == NULL && + vfs->stop_socket_select_isr == NULL && + vfs->get_socket_select_semaphore == NULL && + vfs->end_select == NULL; + + if (!skip_select) { + main->select = (esp_vfs_select_ops_t*) heap_caps_malloc(sizeof(esp_vfs_select_ops_t), VFS_MALLOC_FLAGS); + if (main->select == NULL) { + goto fail; + } + } +#endif + + esp_minify_vfs(vfs, main); + + *min = main; + return ESP_OK; + +#if defined(CONFIG_VFS_SUPPORT_SELECT) || defined(CONFIG_VFS_SUPPORT_TERMIOS) || defined(CONFIG_VFS_SUPPORT_DIR) +fail: + + esp_vfs_free_fs_ops(main); + return ESP_ERR_NO_MEM; +#endif +} + +static esp_err_t esp_vfs_register_fs_common(const char* base_path, size_t len, const esp_vfs_fs_ops_t* vfs, int flags, void* ctx, int *vfs_index) { + if (vfs == NULL) { + ESP_LOGE(TAG, "VFS is NULL"); + return ESP_ERR_INVALID_ARG; + } + if (len != LEN_PATH_PREFIX_IGNORED) { /* empty prefix is allowed, "/" is not allowed */ if ((len == 1) || (len > ESP_VFS_PATH_MAX)) { @@ -87,33 +363,36 @@ esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_v return ESP_ERR_INVALID_ARG; } } - vfs_entry_t *entry = (vfs_entry_t*) heap_caps_malloc(sizeof(vfs_entry_t), VFS_MALLOC_FLAGS); - if (entry == NULL) { + + ssize_t index = esp_get_free_index(); + if (index < 0) { return ESP_ERR_NO_MEM; } - size_t index; - for (index = 0; index < s_vfs_count; ++index) { - if (s_vfs[index] == NULL) { - break; - } + + if (s_vfs[index] != NULL) { + return ESP_ERR_INVALID_STATE; } + if (index == s_vfs_count) { - if (s_vfs_count >= VFS_MAX_COUNT) { - free(entry); - return ESP_ERR_NO_MEM; - } - ++s_vfs_count; + s_vfs_count++; } + + vfs_entry_t *entry = (vfs_entry_t*) heap_caps_malloc(sizeof(vfs_entry_t), VFS_MALLOC_FLAGS); + if (entry == NULL) { + return ESP_ERR_NO_MEM; + } + s_vfs[index] = entry; if (len != LEN_PATH_PREFIX_IGNORED) { strcpy(entry->path_prefix, base_path); // we have already verified argument length } else { bzero(entry->path_prefix, sizeof(entry->path_prefix)); } - memcpy(&entry->vfs, vfs, sizeof(esp_vfs_t)); entry->path_prefix_len = len; + entry->vfs = vfs; entry->ctx = ctx; entry->offset = index; + entry->flags = flags; if (vfs_index) { *vfs_index = index; @@ -122,6 +401,58 @@ esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_v return ESP_OK; } +esp_err_t esp_vfs_register_fs(const char* base_path, const esp_vfs_fs_ops_t* vfs, int flags, void* ctx) +{ + if (vfs == NULL) { + ESP_LOGE(TAG, "VFS is NULL"); + return ESP_ERR_INVALID_ARG; + } + + if ((flags & ESP_VFS_FLAG_STATIC)) { + return esp_vfs_register_fs_common(base_path, strlen(base_path), vfs, flags, ctx, NULL); + } + + esp_vfs_fs_ops_t *_vfs = esp_vfs_duplicate_fs_ops(vfs); + if (_vfs == NULL) { + return ESP_ERR_NO_MEM; + } + + esp_err_t ret = esp_vfs_register_fs_common(base_path, strlen(base_path), _vfs, flags, ctx, NULL); + if (ret != ESP_OK) { + esp_vfs_free_fs_ops(_vfs); + return ret; + } + + return ESP_OK; +} + +esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index) +{ + if (vfs == NULL) { + ESP_LOGE(TAG, "VFS is NULL"); + return ESP_ERR_INVALID_ARG; + } + + if (vfs->flags & ESP_VFS_FLAG_STATIC) { + ESP_LOGE(TAG, "ESP_VFS_FLAG_STATIC is not supported for esp_vfs_t, use esp_vfs_register_fs instead"); + return ESP_ERR_INVALID_ARG; + } + + esp_vfs_fs_ops_t *_vfs = NULL; + esp_err_t ret = esp_vfs_make_fs_ops(vfs, &_vfs); + if (ret != ESP_OK) { + return ret; + } + + ret = esp_vfs_register_fs_common(base_path, len, _vfs, vfs->flags, ctx, vfs_index); + if (ret != ESP_OK) { + esp_vfs_free_fs_ops(_vfs); + return ret; + } + + return ESP_OK; +} + esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ctx) { return esp_vfs_register_common(base_path, strlen(base_path), vfs, ctx, NULL); @@ -134,7 +465,7 @@ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, return ESP_ERR_INVALID_ARG; } - int index = -1; + int index = 0; esp_err_t ret = esp_vfs_register_common("", LEN_PATH_PREFIX_IGNORED, vfs, ctx, &index); if (ret == ESP_OK) { @@ -164,6 +495,16 @@ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, return ret; } +esp_err_t esp_vfs_register_fs_with_id(const esp_vfs_fs_ops_t *vfs, int flags, void *ctx, esp_vfs_id_t *vfs_id) +{ + if (vfs_id == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *vfs_id = -1; + return esp_vfs_register_fs_common("", LEN_PATH_PREFIX_IGNORED, vfs, flags, ctx, vfs_id); +} + esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t *vfs_id) { if (vfs_id == NULL) { @@ -180,7 +521,7 @@ esp_err_t esp_vfs_unregister_with_id(esp_vfs_id_t vfs_id) return ESP_ERR_INVALID_ARG; } vfs_entry_t* vfs = s_vfs[vfs_id]; - free(vfs); + esp_vfs_free_entry(vfs); s_vfs[vfs_id] = NULL; _lock_acquire(&s_fd_table_lock); @@ -193,8 +534,11 @@ esp_err_t esp_vfs_unregister_with_id(esp_vfs_id_t vfs_id) _lock_release(&s_fd_table_lock); return ESP_OK; + } +esp_err_t esp_vfs_unregister_fs_with_id(esp_vfs_id_t vfs_id) __attribute__((alias("esp_vfs_unregister_with_id"))); + esp_err_t esp_vfs_unregister(const char* base_path) { const size_t base_path_len = strlen(base_path); @@ -211,6 +555,8 @@ esp_err_t esp_vfs_unregister(const char* base_path) return ESP_ERR_INVALID_STATE; } +esp_err_t esp_vfs_unregister_fs(const char* base_path) __attribute__((alias("esp_vfs_unregister"))); + esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd) { return esp_vfs_register_fd_with_local_fd(vfs_id, -1, true, fd); @@ -290,6 +636,22 @@ void esp_vfs_dump_fds(FILE *fp) _lock_release(&s_fd_table_lock); } +void esp_vfs_dump_registered_paths(FILE *fp) +{ + fprintf(fp, "------------------------------------------------------\n"); + fprintf(fp, ": -> \n"); + fprintf(fp, "------------------------------------------------------\n"); + for (size_t i = 0; i < VFS_MAX_COUNT; ++i) { + fprintf( + fp, + "%d:%s -> %p\n", + i, + s_vfs[i] ? s_vfs[i]->path_prefix : "NULL", + s_vfs[i] ? s_vfs[i]->vfs : NULL + ); + } +} + /* * Set ESP_VFS_FLAG_READONLY_FS read-only flag for a registered virtual filesystem * for given path prefix. Should be only called from the esp_vfs_*filesystem* register @@ -306,7 +668,7 @@ esp_err_t esp_vfs_set_readonly_flag(const char* base_path) } if (base_path_len == vfs->path_prefix_len && memcmp(base_path, vfs->path_prefix, vfs->path_prefix_len) == 0) { - vfs->vfs.flags |= ESP_VFS_FLAG_READONLY_FS; + vfs->flags |= ESP_VFS_FLAG_READONLY_FS; return ESP_OK; } } @@ -365,7 +727,7 @@ const vfs_entry_t* get_vfs_for_path(const char* path) size_t len = strlen(path); for (size_t i = 0; i < s_vfs_count; ++i) { const vfs_entry_t* vfs = s_vfs[i]; - if (!vfs || vfs->path_prefix_len == LEN_PATH_PREFIX_IGNORED) { + if (vfs == NULL || vfs->path_prefix_len == LEN_PATH_PREFIX_IGNORED) { continue; } // match path prefix @@ -411,37 +773,69 @@ const vfs_entry_t* get_vfs_for_path(const char* path) * It is enough to check just one of them for NULL, as both variants are part of a union. */ #define CHECK_AND_CALL(ret, r, pvfs, func, ...) \ - if (pvfs->vfs.func == NULL) { \ + if (pvfs->vfs->func == NULL) { \ __errno_r(r) = ENOSYS; \ return -1; \ } \ - if (pvfs->vfs.flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ - ret = (*pvfs->vfs.func ## _p)(pvfs->ctx, __VA_ARGS__); \ + if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ + ret = (*pvfs->vfs->func ## _p)(pvfs->ctx, __VA_ARGS__); \ } else { \ - ret = (*pvfs->vfs.func)(__VA_ARGS__);\ + ret = (*pvfs->vfs->func)(__VA_ARGS__);\ } +#define CHECK_AND_CALL_SUBCOMPONENT(ret, r, pvfs, component, func, ...) \ + if (pvfs->vfs->component == NULL || pvfs->vfs->component->func == NULL) { \ + __errno_r(r) = ENOSYS; \ + return -1; \ + } \ + if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ + ret = (*pvfs->vfs->component->func ## _p)(pvfs->ctx, __VA_ARGS__); \ + } else { \ + ret = (*pvfs->vfs->component->func)(__VA_ARGS__);\ + } #define CHECK_AND_CALLV(r, pvfs, func, ...) \ - if (pvfs->vfs.func == NULL) { \ + if (pvfs->vfs->func == NULL) { \ __errno_r(r) = ENOSYS; \ return; \ } \ - if (pvfs->vfs.flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ - (*pvfs->vfs.func ## _p)(pvfs->ctx, __VA_ARGS__); \ + if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ + (*pvfs->vfs->func ## _p)(pvfs->ctx, __VA_ARGS__); \ } else { \ - (*pvfs->vfs.func)(__VA_ARGS__);\ + (*pvfs->vfs->func)(__VA_ARGS__);\ + } + +#define CHECK_AND_CALL_SUBCOMPONENTV(r, pvfs, component, func, ...) \ + if (pvfs->vfs->component == NULL || pvfs->vfs->component->func == NULL) { \ + __errno_r(r) = ENOSYS; \ + return; \ + } \ + if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ + (*pvfs->vfs->component->func ## _p)(pvfs->ctx, __VA_ARGS__); \ + } else { \ + (*pvfs->vfs->component->func)(__VA_ARGS__);\ } #define CHECK_AND_CALLP(ret, r, pvfs, func, ...) \ - if (pvfs->vfs.func == NULL) { \ + if (pvfs->vfs->func == NULL) { \ + __errno_r(r) = ENOSYS; \ + return NULL; \ + } \ + if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ + ret = (*pvfs->vfs->func ## _p)(pvfs->ctx, __VA_ARGS__); \ + } else { \ + ret = (*pvfs->vfs->func)(__VA_ARGS__);\ + } + +#define CHECK_AND_CALL_SUBCOMPONENTP(ret, r, pvfs, component, func, ...) \ + if (pvfs->vfs->component == NULL || pvfs->vfs->component->func == NULL) { \ __errno_r(r) = ENOSYS; \ return NULL; \ } \ - if (pvfs->vfs.flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ - ret = (*pvfs->vfs.func ## _p)(pvfs->ctx, __VA_ARGS__); \ + if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \ + ret = (*pvfs->vfs->component->func ## _p)(pvfs->ctx, __VA_ARGS__); \ } else { \ - ret = (*pvfs->vfs.func)(__VA_ARGS__);\ + ret = (*pvfs->vfs->component->func)(__VA_ARGS__);\ } #define CHECK_VFS_READONLY_FLAG(flags) \ @@ -459,7 +853,7 @@ int esp_vfs_open(struct _reent *r, const char * path, int flags, int mode) } int acc_mode = flags & O_ACCMODE; - int ro_filesystem = vfs->vfs.flags & ESP_VFS_FLAG_READONLY_FS; + int ro_filesystem = vfs->flags & ESP_VFS_FLAG_READONLY_FS; if (acc_mode != O_RDONLY && ro_filesystem) { __errno_r(r) = EROFS; return -1; @@ -648,7 +1042,7 @@ int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st) } const char* path_within_vfs = translate_path(vfs, path); int ret; - CHECK_AND_CALL(ret, r, vfs, stat, path_within_vfs, st); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, stat, path_within_vfs, st); return ret; } @@ -662,7 +1056,7 @@ int esp_vfs_utime(const char *path, const struct utimbuf *times) return -1; } const char* path_within_vfs = translate_path(vfs, path); - CHECK_AND_CALL(ret, r, vfs, utime, path_within_vfs, times); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, utime, path_within_vfs, times); return ret; } @@ -679,12 +1073,12 @@ int esp_vfs_link(struct _reent *r, const char* n1, const char* n2) return -1; } - CHECK_VFS_READONLY_FLAG(vfs2->vfs.flags); + CHECK_VFS_READONLY_FLAG(vfs2->flags); const char* path1_within_vfs = translate_path(vfs, n1); const char* path2_within_vfs = translate_path(vfs, n2); int ret; - CHECK_AND_CALL(ret, r, vfs, link, path1_within_vfs, path2_within_vfs); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, link, path1_within_vfs, path2_within_vfs); return ret; } @@ -696,11 +1090,11 @@ int esp_vfs_unlink(struct _reent *r, const char *path) return -1; } - CHECK_VFS_READONLY_FLAG(vfs->vfs.flags); + CHECK_VFS_READONLY_FLAG(vfs->flags); const char* path_within_vfs = translate_path(vfs, path); int ret; - CHECK_AND_CALL(ret, r, vfs, unlink, path_within_vfs); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, unlink, path_within_vfs); return ret; } @@ -712,7 +1106,7 @@ int esp_vfs_rename(struct _reent *r, const char *src, const char *dst) return -1; } - CHECK_VFS_READONLY_FLAG(vfs->vfs.flags); + CHECK_VFS_READONLY_FLAG(vfs->flags); const vfs_entry_t* vfs_dst = get_vfs_for_path(dst); if (vfs != vfs_dst) { @@ -720,12 +1114,12 @@ int esp_vfs_rename(struct _reent *r, const char *src, const char *dst) return -1; } - CHECK_VFS_READONLY_FLAG(vfs_dst->vfs.flags); + CHECK_VFS_READONLY_FLAG(vfs_dst->flags); const char* src_within_vfs = translate_path(vfs, src); const char* dst_within_vfs = translate_path(vfs, dst); int ret; - CHECK_AND_CALL(ret, r, vfs, rename, src_within_vfs, dst_within_vfs); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, rename, src_within_vfs, dst_within_vfs); return ret; } @@ -739,7 +1133,7 @@ DIR* esp_vfs_opendir(const char* name) } const char* path_within_vfs = translate_path(vfs, name); DIR* ret; - CHECK_AND_CALLP(ret, r, vfs, opendir, path_within_vfs); + CHECK_AND_CALL_SUBCOMPONENTP(ret, r, vfs, dir, opendir, path_within_vfs); if (ret != NULL) { ret->dd_vfs_idx = vfs->offset; } @@ -755,7 +1149,7 @@ struct dirent* esp_vfs_readdir(DIR* pdir) return NULL; } struct dirent* ret; - CHECK_AND_CALLP(ret, r, vfs, readdir, pdir); + CHECK_AND_CALL_SUBCOMPONENTP(ret, r, vfs, dir, readdir, pdir); return ret; } @@ -768,7 +1162,7 @@ int esp_vfs_readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_diren return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, readdir_r, pdir, entry, out_dirent); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, readdir_r, pdir, entry, out_dirent); return ret; } @@ -781,7 +1175,7 @@ long esp_vfs_telldir(DIR* pdir) return -1; } long ret; - CHECK_AND_CALL(ret, r, vfs, telldir, pdir); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, telldir, pdir); return ret; } @@ -793,7 +1187,7 @@ void esp_vfs_seekdir(DIR* pdir, long loc) errno = EBADF; return; } - CHECK_AND_CALLV(r, vfs, seekdir, pdir, loc); + CHECK_AND_CALL_SUBCOMPONENTV(r, vfs, dir, seekdir, pdir, loc); } void esp_vfs_rewinddir(DIR* pdir) @@ -810,7 +1204,7 @@ int esp_vfs_closedir(DIR* pdir) return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, closedir, pdir); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, closedir, pdir); return ret; } @@ -823,11 +1217,11 @@ int esp_vfs_mkdir(const char* name, mode_t mode) return -1; } - CHECK_VFS_READONLY_FLAG(vfs->vfs.flags); + CHECK_VFS_READONLY_FLAG(vfs->flags); const char* path_within_vfs = translate_path(vfs, name); int ret; - CHECK_AND_CALL(ret, r, vfs, mkdir, path_within_vfs, mode); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, mkdir, path_within_vfs, mode); return ret; } @@ -840,11 +1234,11 @@ int esp_vfs_rmdir(const char* name) return -1; } - CHECK_VFS_READONLY_FLAG(vfs->vfs.flags); + CHECK_VFS_READONLY_FLAG(vfs->flags); const char* path_within_vfs = translate_path(vfs, name); int ret; - CHECK_AND_CALL(ret, r, vfs, rmdir, path_within_vfs); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, rmdir, path_within_vfs); return ret; } @@ -858,7 +1252,7 @@ int esp_vfs_access(const char *path, int amode) return -1; } const char* path_within_vfs = translate_path(vfs, path); - CHECK_AND_CALL(ret, r, vfs, access, path_within_vfs, amode); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, access, path_within_vfs, amode); return ret; } @@ -872,10 +1266,10 @@ int esp_vfs_truncate(const char *path, off_t length) return -1; } - CHECK_VFS_READONLY_FLAG(vfs->vfs.flags); + CHECK_VFS_READONLY_FLAG(vfs->flags); const char* path_within_vfs = translate_path(vfs, path); - CHECK_AND_CALL(ret, r, vfs, truncate, path_within_vfs, length); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, truncate, path_within_vfs, length); return ret; } @@ -889,10 +1283,10 @@ int esp_vfs_ftruncate(int fd, off_t length) return -1; } - CHECK_VFS_READONLY_FLAG(vfs->vfs.flags); + CHECK_VFS_READONLY_FLAG(vfs->flags); int ret; - CHECK_AND_CALL(ret, r, vfs, ftruncate, local_fd, length); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, ftruncate, local_fd, length); return ret; } @@ -905,8 +1299,12 @@ static void call_end_selects(int end_index, const fds_triple_t *vfs_fds_triple, for (int i = 0; i < end_index; ++i) { const vfs_entry_t *vfs = get_vfs_for_index(i); const fds_triple_t *item = &vfs_fds_triple[i]; - if (vfs && vfs->vfs.end_select && item->isset) { - esp_err_t err = vfs->vfs.end_select(driver_args[i]); + if (vfs != NULL + && vfs->vfs->select != NULL + && vfs->vfs->select->end_select != NULL + && item->isset + ) { + esp_err_t err = vfs->vfs->select->end_select(driver_args[i]); if (err != ESP_OK) { ESP_LOGD(TAG, "end_select failed: %s", esp_err_to_name(err)); } @@ -1023,8 +1421,8 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds esp_vfs_safe_fd_isset(fd, writefds) || esp_vfs_safe_fd_isset(fd, errorfds)) { const vfs_entry_t *vfs = s_vfs[vfs_index]; - socket_select = vfs->vfs.socket_select; - sel_sem.sem = vfs->vfs.get_socket_select_semaphore(); + socket_select = vfs->vfs->select->socket_select; + sel_sem.sem = vfs->vfs->select->get_socket_select_semaphore(); } } continue; @@ -1080,33 +1478,38 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds const vfs_entry_t *vfs = get_vfs_for_index(i); fds_triple_t *item = &vfs_fds_triple[i]; - if (vfs && !vfs->vfs.start_select) { + if (vfs == NULL || vfs->vfs->select == NULL || vfs->vfs->select->start_select == NULL) { ESP_LOGD(TAG, "start_select function callback for this vfs (s_vfs[%d]) is not defined", vfs->offset); - } else if (vfs && vfs->vfs.start_select && item->isset) { - // call start_select for all non-socket VFSs with has at least one FD set in readfds, writefds, or errorfds - // note: it can point to socket VFS but item->isset will be false for that - ESP_LOGD(TAG, "calling start_select for VFS ID %d with the following local FDs", i); - esp_vfs_log_fd_set("readfds", &item->readfds); - esp_vfs_log_fd_set("writefds", &item->writefds); - esp_vfs_log_fd_set("errorfds", &item->errorfds); - esp_err_t err = vfs->vfs.start_select(nfds, &item->readfds, &item->writefds, &item->errorfds, sel_sem, - driver_args + i); + continue; + } - if (err != ESP_OK) { - if (err != ESP_ERR_NOT_SUPPORTED) { - call_end_selects(i, vfs_fds_triple, driver_args); - } - (void) set_global_fd_sets(vfs_fds_triple, vfs_count, readfds, writefds, errorfds); - if (sel_sem.is_sem_local && sel_sem.sem) { - vSemaphoreDelete(sel_sem.sem); - sel_sem.sem = NULL; - } - free(vfs_fds_triple); - free(driver_args); - __errno_r(r) = EINTR; - ESP_LOGD(TAG, "start_select failed: %s", esp_err_to_name(err)); - return -1; + if (!item->isset) { + continue; + } + + // call start_select for all non-socket VFSs with has at least one FD set in readfds, writefds, or errorfds + // note: it can point to socket VFS but item->isset will be false for that + ESP_LOGD(TAG, "calling start_select for VFS ID %d with the following local FDs", i); + esp_vfs_log_fd_set("readfds", &item->readfds); + esp_vfs_log_fd_set("writefds", &item->writefds); + esp_vfs_log_fd_set("errorfds", &item->errorfds); + esp_err_t err = vfs->vfs->select->start_select(nfds, &item->readfds, &item->writefds, &item->errorfds, sel_sem, + driver_args + i); + + if (err != ESP_OK) { + if (err != ESP_ERR_NOT_SUPPORTED) { + call_end_selects(i, vfs_fds_triple, driver_args); } + (void) set_global_fd_sets(vfs_fds_triple, vfs_count, readfds, writefds, errorfds); + if (sel_sem.is_sem_local && sel_sem.sem) { + vSemaphoreDelete(sel_sem.sem); + sel_sem.sem = NULL; + } + free(vfs_fds_triple); + free(driver_args); + __errno_r(r) = EINTR; + ESP_LOGD(TAG, "start_select failed: %s", esp_err_to_name(err)); + return -1; } } @@ -1193,8 +1596,11 @@ void esp_vfs_select_triggered(esp_vfs_select_sem_t sem) // Note: s_vfs_count could have changed since the start of vfs_select() call. However, that change doesn't // matter here stop_socket_select() will be called for only valid VFS drivers. const vfs_entry_t *vfs = s_vfs[i]; - if (vfs != NULL && vfs->vfs.stop_socket_select != NULL) { - vfs->vfs.stop_socket_select(sem.sem); + if (vfs != NULL + && vfs->vfs->select != NULL + && vfs->vfs->select->stop_socket_select != NULL + ) { + vfs->vfs->select->stop_socket_select(sem.sem); break; } } @@ -1213,9 +1619,12 @@ void esp_vfs_select_triggered_isr(esp_vfs_select_sem_t sem, BaseType_t *woken) // Note: s_vfs_count could have changed since the start of vfs_select() call. However, that change doesn't // matter here stop_socket_select() will be called for only valid VFS drivers. const vfs_entry_t *vfs = s_vfs[i]; - if (vfs != NULL && vfs->vfs.stop_socket_select_isr != NULL) { + if (vfs != NULL + && vfs->vfs->select != NULL + && vfs->vfs->select->stop_socket_select_isr != NULL + ) { // Note: If the UART ISR resides in IRAM, the function referenced by stop_socket_select_isr should also be placed in IRAM. - vfs->vfs.stop_socket_select_isr(sem.sem, woken); + vfs->vfs->select->stop_socket_select_isr(sem.sem, woken); break; } } @@ -1236,7 +1645,7 @@ int tcgetattr(int fd, struct termios *p) return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, tcgetattr, local_fd, p); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcgetattr, local_fd, p); return ret; } @@ -1250,7 +1659,7 @@ int tcsetattr(int fd, int optional_actions, const struct termios *p) return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, tcsetattr, local_fd, optional_actions, p); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcsetattr, local_fd, optional_actions, p); return ret; } @@ -1264,7 +1673,7 @@ int tcdrain(int fd) return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, tcdrain, local_fd); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcdrain, local_fd); return ret; } @@ -1278,7 +1687,7 @@ int tcflush(int fd, int select) return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, tcflush, local_fd, select); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcflush, local_fd, select); return ret; } @@ -1292,7 +1701,7 @@ int tcflow(int fd, int action) return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, tcflow, local_fd, action); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcflow, local_fd, action); return ret; } @@ -1306,7 +1715,7 @@ pid_t tcgetsid(int fd) return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, tcgetsid, local_fd); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcgetsid, local_fd); return ret; } @@ -1320,7 +1729,7 @@ int tcsendbreak(int fd, int duration) return -1; } int ret; - CHECK_AND_CALL(ret, r, vfs, tcsendbreak, local_fd, duration); + CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcsendbreak, local_fd, duration); return ret; } #endif // CONFIG_VFS_SUPPORT_TERMIOS diff --git a/components/wifi_provisioning/include/wifi_provisioning/manager.h b/components/wifi_provisioning/include/wifi_provisioning/manager.h index b8780762f616..a3164d31a88a 100644 --- a/components/wifi_provisioning/include/wifi_provisioning/manager.h +++ b/components/wifi_provisioning/include/wifi_provisioning/manager.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -36,6 +36,13 @@ typedef enum { */ WIFI_PROV_START, + /** + * Emitted before accepting the wifi credentials to + * set the wifi configurations according to requirement. + * NOTE - In this case event_data shall be populated with a pointer to `wifi_config_t`. + */ + WIFI_PROV_SET_STA_CONFIG, + /** * Emitted when Wi-Fi AP credentials are received via `protocomm` * endpoint `wifi_config`. The event data in this case is a pointer diff --git a/components/wifi_provisioning/src/manager.c b/components/wifi_provisioning/src/manager.c index a4e4d35b6301..fd8b2e2edcfe 100644 --- a/components/wifi_provisioning/src/manager.c +++ b/components/wifi_provisioning/src/manager.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1240,6 +1240,9 @@ esp_err_t wifi_prov_mgr_configure_sta(wifi_config_t *wifi_cfg) RELEASE_LOCK(prov_ctx_lock); return ESP_FAIL; } + + execute_event_cb(WIFI_PROV_SET_STA_CONFIG, (void *)wifi_cfg, sizeof(wifi_config_t)); + if (prov_ctx->prov_state >= WIFI_PROV_STATE_CRED_RECV) { ESP_LOGE(TAG, "Wi-Fi credentials already received by provisioning app"); RELEASE_LOCK(prov_ctx_lock); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 45c256bf93a7..0716ad5952b4 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -7,6 +7,7 @@ #include "utils/includes.h" #include "utils/common.h" +#include "utils/eloop.h" #include "crypto/sha1.h" #include "common/ieee802_11_defs.h" #include "common/eapol_common.h" @@ -21,6 +22,9 @@ #include "esp_wps.h" #include "esp_wps_i.h" +#include "ap/sta_info.h" +#include "common/sae.h" +#include "ap/ieee802_11.h" #define WIFI_PASSWORD_LEN_MAX 65 struct hostapd_data *global_hapd; @@ -320,3 +324,143 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, os_free(reply); return res; } + +uint8_t wpa_status_to_reason_code(int status) +{ + switch (status) { + case WLAN_STATUS_INVALID_IE: + return WLAN_REASON_INVALID_IE; + case WLAN_STATUS_GROUP_CIPHER_NOT_VALID: + return WLAN_REASON_GROUP_CIPHER_NOT_VALID; + case WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID: + return WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; + case WLAN_STATUS_AKMP_NOT_VALID: + return WLAN_REASON_AKMP_NOT_VALID; + case WLAN_STATUS_CIPHER_REJECTED_PER_POLICY: + return WLAN_REASON_CIPHER_SUITE_REJECTED; + case WLAN_STATUS_INVALID_PMKID: + return WLAN_REASON_INVALID_PMKID; + case WLAN_STATUS_INVALID_MDIE: + return WLAN_REASON_INVALID_MDE; + default: + return WLAN_REASON_UNSPECIFIED; + } +} + +bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, + uint8_t wpa_ie_len, uint8_t *rsnxe, uint8_t rsnxe_len, + bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason) +{ + struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); + enum wpa_validate_result res = WPA_IE_OK; + int status = WLAN_STATUS_SUCCESS; + bool omit_rsnxe = false; + + if (!sta || !bssid || !wpa_ie) { + return false; + } + + if (hapd) { + if (hapd->wpa_auth->conf.wpa) { + if (sta->wpa_sm) { + wpa_auth_sta_deinit(sta->wpa_sm); + } + + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, bssid); + wpa_printf(MSG_DEBUG, "init wpa sm=%p", sta->wpa_sm); + + if (sta->wpa_sm == NULL) { + status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto send_resp; + } + + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len); + +#ifdef CONFIG_SAE + if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && + sta->sae->state == SAE_ACCEPTED) { + wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid); + } +#endif /* CONFIG_SAE */ + + status = wpa_res_to_status_code(res); + +send_resp: + if (!rsnxe) { + omit_rsnxe = true; + } + + if (esp_send_assoc_resp(hapd, bssid, status, omit_rsnxe, subtype) != WLAN_STATUS_SUCCESS) { + status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + } + + if (status != WLAN_STATUS_SUCCESS) { + *reason = wpa_status_to_reason_code(status); + return false; + } + + //Check whether AP uses Management Frame Protection for this connection + *pmf_enable = wpa_auth_uses_mfp(sta->wpa_sm); + *pairwise_cipher = GET_BIT_POSITION(sta->wpa_sm->pairwise); + } + + wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); + } + + return true; +} + +#ifdef CONFIG_WPS_REGISTRAR +static void ap_free_sta_timeout(void *ctx, void *data) +{ + struct hostapd_data *hapd = (struct hostapd_data *) ctx; + u8 *addr = (u8 *) data; + struct sta_info *sta = ap_get_sta(hapd, addr); + + if (sta) { + ap_free_sta(hapd, sta); + } + + os_free(addr); +} +#endif + +bool wpa_ap_remove(u8* bssid) +{ + struct hostapd_data *hapd = hostapd_get_hapd_data(); + + if (!hapd) { + return false; + } + struct sta_info *sta = ap_get_sta(hapd, bssid); + if (!sta) { + return false; + } + +#ifdef CONFIG_SAE + if (sta->lock) { + if (os_semphr_take(sta->lock, 0)) { + ap_free_sta(hapd, sta); + } else { + sta->remove_pending = true; + } + return true; + } +#endif /* CONFIG_SAE */ + +#ifdef CONFIG_WPS_REGISTRAR + wpa_printf(MSG_DEBUG, "wps_status=%d", wps_get_status()); + if (wps_get_status() == WPS_STATUS_PENDING) { + u8 *addr = os_malloc(ETH_ALEN); + + if (!addr) { + return false; + } + os_memcpy(addr, sta->addr, ETH_ALEN); + eloop_register_timeout(0, 10000, ap_free_sta_timeout, hapd, addr); + } else +#endif + ap_free_sta(hapd, sta); + + return true; +} diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h index d5ca7fd71636..a07650603d8a 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -144,6 +144,7 @@ struct wpa_funcs { void (*wpa_config_done)(void); uint8_t *(*owe_build_dhie)(uint16_t group); int (*owe_process_assoc_resp)(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len); + void (*wpa_sta_clear_curr_pmksa)(void); }; struct wpa2_funcs { diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index 76fa0f5f32ed..e66b2a745d86 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -647,6 +647,9 @@ bool wpa3_hostap_auth_deinit(void) static int wpa3_hostap_handle_auth(u8 *buf, size_t len, u32 auth_transaction, u16 status, u8 *bssid) { struct hostapd_data *hapd = (struct hostapd_data *)esp_wifi_get_hostap_private_internal(); + if (!hapd) { + return ESP_FAIL; + } struct sta_info *sta = ap_get_sta(hapd, bssid); if (auth_transaction == SAE_MSG_COMMIT) { if (sta && sta->sae_commit_processing) { diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index 067e09705cd6..09532deb126d 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -287,8 +287,8 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code) { switch (reason_code) { case WIFI_REASON_AUTH_EXPIRE: - case WIFI_REASON_NOT_AUTHED: - case WIFI_REASON_NOT_ASSOCED: + case WIFI_REASON_CLASS2_FRAME_FROM_NONAUTH_STA: + case WIFI_REASON_CLASS3_FRAME_FROM_NONASSOC_STA: case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: case WIFI_REASON_INVALID_PMKID: case WIFI_REASON_AUTH_FAIL: @@ -356,6 +356,7 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 { struct sta_info *sta_info = NULL; struct hostapd_data *hapd = hostapd_get_hapd_data(); + uint8_t reason = WLAN_REASON_PREV_AUTH_NOT_VALID; if (!hapd) { goto fail; @@ -413,7 +414,7 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 goto fail; } #endif - if (wpa_ap_join(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher)) { + if (hostap_new_assoc_sta(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher, &reason)) { goto done; } else { goto fail; @@ -434,7 +435,7 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 os_semphr_give(sta_info->lock); } #endif /* CONFIG_SAE */ - esp_wifi_ap_deauth_internal(bssid, WLAN_REASON_PREV_AUTH_NOT_VALID); + esp_wifi_ap_deauth_internal(bssid, reason); return false; } #endif @@ -475,6 +476,7 @@ int esp_supplicant_init(void) wpa_cb->wpa_config_bss = NULL;//wpa_config_bss; wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure; wpa_cb->wpa_config_done = wpa_config_done; + wpa_cb->wpa_sta_clear_curr_pmksa = wpa_sta_clear_curr_pmksa; esp_wifi_register_wpa3_ap_cb(wpa_cb); esp_wifi_register_wpa3_cb(wpa_cb); @@ -504,6 +506,9 @@ int esp_supplicant_deinit(void) esp_supplicant_unset_all_appie(); eloop_destroy(); wpa_cb = NULL; +#if CONFIG_ESP_WIFI_WAPI_PSK + esp_wifi_internal_wapi_deinit(); +#endif return esp_wifi_unregister_wpa_cb_internal(); } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wps.c b/components/wpa_supplicant/esp_supplicant/src/esp_wps.c index ae84728bf8a5..c67413b1271a 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wps.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wps.c @@ -930,7 +930,7 @@ int wps_start_msg_timer(void) ret = 0; } else if (sm->wps->state == RECV_M2) { msg_timeout = 5; - wpa_printf(MSG_DEBUG, "start msg timer RECV_M2 %" PRId32 " ms", msg_timeout); + wpa_printf(MSG_DEBUG, "start msg timer RECV_M2 %" PRId32 " s", msg_timeout); eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL); eloop_register_timeout(msg_timeout, 0, wifi_station_wps_msg_timeout, NULL, NULL); ret = 0; diff --git a/components/wpa_supplicant/sbom.yml b/components/wpa_supplicant/sbom.yml new file mode 100644 index 000000000000..c283feb63207 --- /dev/null +++ b/components/wpa_supplicant/sbom.yml @@ -0,0 +1,6 @@ +name: 'wpa_supplicant' +version: '2.10' +cpe: cpe:2.3:a:w1.fi:wpa_supplicant:{}:*:*:*:*:*:*:* +supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' +originator: 'Person: Jouni Malinen' +description: Espressif fork of wpa_supplicant - an open-source WPA/WPA2/WPA3/IEEE 802.1X Supplicant. diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 486d802a1193..1d11dd4816bb 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -382,9 +382,9 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, const u8 *addr, const u8 *prev_psk); int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); struct sta_info; -bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, +bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, uint8_t wpa_ie_len,uint8_t *rsnxe, uint8_t rsnxe_len, - bool *pmf_enable, int subtype, uint8_t *pairwise_cipher); + bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason); bool wpa_ap_remove(u8* bssid); #endif /* HOSTAPD_CONFIG_H */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 513ec9fa8220..58748a85ff3b 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -13,7 +13,6 @@ #include "common/ieee802_11_defs.h" #include "common/sae.h" #include "ap/sta_info.h" -#include "ap/ieee802_11.h" #include "ap/wpa_auth.h" #include "ap/wpa_auth_i.h" #include "ap/wpa_auth_ie.h" @@ -36,7 +35,6 @@ #include "esp_wifi.h" #include "esp_private/wifi.h" #include "esp_wpas_glue.h" -#include "esp_wps_i.h" #include "esp_hostap.h" #define STATE_MACHINE_DATA struct wpa_state_machine @@ -2557,97 +2555,6 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth) } -#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT -bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, - uint8_t wpa_ie_len, uint8_t *rsnxe, uint8_t rsnxe_len, - bool *pmf_enable, int subtype, uint8_t *pairwise_cipher) -{ - struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); - enum wpa_validate_result status_code = WPA_IE_OK; - int resp = WLAN_STATUS_SUCCESS; - bool omit_rsnxe = false; - - if (!sta || !bssid || !wpa_ie) { - return false; - } - - if (hapd) { - if (hapd->wpa_auth->conf.wpa) { - if (sta->wpa_sm){ - wpa_auth_sta_deinit(sta->wpa_sm); - } - - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, bssid); - wpa_printf( MSG_DEBUG, "init wpa sm=%p", sta->wpa_sm); - - if (sta->wpa_sm == NULL) { - resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto send_resp; - } - - status_code = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len); - -#ifdef CONFIG_SAE - if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && - sta->sae->state == SAE_ACCEPTED) { - wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid); - } -#endif /* CONFIG_SAE */ - - resp = wpa_res_to_status_code(status_code); - -send_resp: - if (!rsnxe) { - omit_rsnxe = true; - } - - if (esp_send_assoc_resp(hapd, bssid, resp, omit_rsnxe, subtype) != WLAN_STATUS_SUCCESS) { - resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - } - - if (resp != WLAN_STATUS_SUCCESS) { - return false; - } - - //Check whether AP uses Management Frame Protection for this connection - *pmf_enable = wpa_auth_uses_mfp(sta->wpa_sm); - *pairwise_cipher = GET_BIT_POSITION(sta->wpa_sm->pairwise); - } - - wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); - } - - return true; -} - -bool wpa_ap_remove(u8* bssid) -{ - struct hostapd_data *hapd = hostapd_get_hapd_data(); - - if (!hapd) { - return false; - } - struct sta_info *sta = ap_get_sta(hapd, bssid); - if (!sta) { - return false; - } - -#ifdef CONFIG_SAE - if (sta->lock) { - if (os_semphr_take(sta->lock, 0)) { - ap_free_sta(hapd, sta); - } else { - sta->remove_pending = true; - } - return true; - } -#endif /* CONFIG_SAE */ - ap_free_sta(hapd, sta); - - return true; -} -#endif /* CONFIG_ESP_WIFI_SOFTAP_SUPPORT */ - void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, const u8 *sta_addr) { diff --git a/components/wpa_supplicant/src/common/ieee802_11_defs.h b/components/wpa_supplicant/src/common/ieee802_11_defs.h index b496690ab78a..958bf5feeb1f 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_defs.h +++ b/components/wpa_supplicant/src/common/ieee802_11_defs.h @@ -186,6 +186,8 @@ #define WLAN_REASON_INVALID_RSN_IE_CAPAB 22 #define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23 #define WLAN_REASON_CIPHER_SUITE_REJECTED 24 +#define WLAN_REASON_INVALID_PMKID 49 +#define WLAN_REASON_INVALID_MDE 50 /* Information Element IDs (IEEE Std 802.11-2016, 9.4.2.1, Table 9-77) */ #define WLAN_EID_SSID 0 diff --git a/components/xtensa/trax/test/gdbinit b/components/xtensa/trax/test/gdbinit index 05496f4c6ebf..5f589bdcd563 100644 --- a/components/xtensa/trax/test/gdbinit +++ b/components/xtensa/trax/test/gdbinit @@ -3,7 +3,7 @@ set confirm off # Start OpenOCD and run to the entry function file test.elf -target remote | openocd -c "log_output openocd.log; set ESP_RTOS none; set ESP_FLASH_SIZE 0; set ESP32_ONLYCPU 1" -f board/esp32-ethernet-kit-3.3v.cfg -c "gdb_port pipe; init; reset halt" +target remote | openocd -c "log_output openocd.log; set ESP_RTOS none; set ESP_FLASH_SIZE 0; set ESP_ONLYCPU 1" -f board/esp32-ethernet-kit-3.3v.cfg -c "gdb_port pipe; init; reset halt" thb entry c diff --git a/docs/_static/ESP32-S3-DevKitC-1_v1-SystemBlock.png b/docs/_static/ESP32-S3-DevKitC-1_v1-SystemBlock.png deleted file mode 100644 index feb598763f37..000000000000 Binary files a/docs/_static/ESP32-S3-DevKitC-1_v1-SystemBlock.png and /dev/null differ diff --git a/docs/_static/ESP32-S3-DevKitC-1_v1-annotated-photo.png b/docs/_static/ESP32-S3-DevKitC-1_v1-annotated-photo.png deleted file mode 100644 index 8a0ae98b3955..000000000000 Binary files a/docs/_static/ESP32-S3-DevKitC-1_v1-annotated-photo.png and /dev/null differ diff --git a/docs/_static/ESP32-S3-DevKitC-1_v1.1-annotated-photo.png b/docs/_static/ESP32-S3-DevKitC-1_v1.1-annotated-photo.png deleted file mode 100644 index 753c3c189d70..000000000000 Binary files a/docs/_static/ESP32-S3-DevKitC-1_v1.1-annotated-photo.png and /dev/null differ diff --git a/docs/_static/ESP32-S3-DevKitC-1_v2-SystemBlock.png b/docs/_static/ESP32-S3-DevKitC-1_v2-SystemBlock.png deleted file mode 100644 index 58ab4f25a83c..000000000000 Binary files a/docs/_static/ESP32-S3-DevKitC-1_v2-SystemBlock.png and /dev/null differ diff --git a/docs/_static/ESP32-S3-DevKitC-1_v2-annotated-photo.png b/docs/_static/ESP32-S3-DevKitC-1_v2-annotated-photo.png deleted file mode 100644 index ce2b1ff61538..000000000000 Binary files a/docs/_static/ESP32-S3-DevKitC-1_v2-annotated-photo.png and /dev/null differ diff --git a/docs/_static/ESP32-S3-DevKitM-1_v1-annotated-photo.png b/docs/_static/ESP32-S3-DevKitM-1_v1-annotated-photo.png deleted file mode 100644 index 46b9816fdbd5..000000000000 Binary files a/docs/_static/ESP32-S3-DevKitM-1_v1-annotated-photo.png and /dev/null differ diff --git a/docs/_static/ESP32-S3-DevKitM-1_v1_SystemBlock.png b/docs/_static/ESP32-S3-DevKitM-1_v1_SystemBlock.png deleted file mode 100644 index da4ab97645b6..000000000000 Binary files a/docs/_static/ESP32-S3-DevKitM-1_v1_SystemBlock.png and /dev/null differ diff --git a/docs/_static/ESP32-S3_DevKitC-1_pinlayout.jpg b/docs/_static/ESP32-S3_DevKitC-1_pinlayout.jpg deleted file mode 100644 index f24fd6762f36..000000000000 Binary files a/docs/_static/ESP32-S3_DevKitC-1_pinlayout.jpg and /dev/null differ diff --git a/docs/_static/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg b/docs/_static/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg deleted file mode 100644 index 703145ebed75..000000000000 Binary files a/docs/_static/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg and /dev/null differ diff --git a/docs/_static/ESP32-S3_DevKitM-1_pinlayout.jpg b/docs/_static/ESP32-S3_DevKitM-1_pinlayout.jpg deleted file mode 100644 index ca39d7d2bbc5..000000000000 Binary files a/docs/_static/ESP32-S3_DevKitM-1_pinlayout.jpg and /dev/null differ diff --git a/docs/_static/ESP32_DevKitM-1_pinlayout.png b/docs/_static/ESP32_DevKitM-1_pinlayout.png deleted file mode 100644 index 359251737f67..000000000000 Binary files a/docs/_static/ESP32_DevKitM-1_pinlayout.png and /dev/null differ diff --git a/docs/_static/esp32-DevKitM-1-front.png b/docs/_static/esp32-DevKitM-1-front.png deleted file mode 100644 index 5685040471ef..000000000000 Binary files a/docs/_static/esp32-DevKitM-1-front.png and /dev/null differ diff --git a/docs/_static/esp32-DevKitM-1-isometric.png b/docs/_static/esp32-DevKitM-1-isometric.png deleted file mode 100644 index af9aa306cb8f..000000000000 Binary files a/docs/_static/esp32-DevKitM-1-isometric.png and /dev/null differ diff --git a/docs/_static/esp32-DevKitM-1_v1_SystemBlock.png b/docs/_static/esp32-DevKitM-1_v1_SystemBlock.png deleted file mode 100644 index 35eac16c8d95..000000000000 Binary files a/docs/_static/esp32-DevKitM-1_v1_SystemBlock.png and /dev/null differ diff --git a/docs/_static/esp32-devkitm-1-v1-annotated-photo.png b/docs/_static/esp32-devkitm-1-v1-annotated-photo.png deleted file mode 100644 index ffcaa4ac48f8..000000000000 Binary files a/docs/_static/esp32-devkitm-1-v1-annotated-photo.png and /dev/null differ diff --git a/docs/_static/esp32-s2-saola-1-v1.2-annotated-photo.png b/docs/_static/esp32-s2-saola-1-v1.2-annotated-photo.png deleted file mode 100644 index 0178b1612978..000000000000 Binary files a/docs/_static/esp32-s2-saola-1-v1.2-annotated-photo.png and /dev/null differ diff --git a/docs/_static/esp32-s2-saola-1-v1.2-block-diags.png b/docs/_static/esp32-s2-saola-1-v1.2-block-diags.png deleted file mode 100644 index 7cb5f2ddf239..000000000000 Binary files a/docs/_static/esp32-s2-saola-1-v1.2-block-diags.png and /dev/null differ diff --git a/docs/_static/esp32-s2-saola-1-v1.2-isometric.png b/docs/_static/esp32-s2-saola-1-v1.2-isometric.png deleted file mode 100644 index 8c1b4ce596d9..000000000000 Binary files a/docs/_static/esp32-s2-saola-1-v1.2-isometric.png and /dev/null differ diff --git a/docs/_static/esp32-s2_saola1-pinout.jpg b/docs/_static/esp32-s2_saola1-pinout.jpg deleted file mode 100644 index 3f42688751c7..000000000000 Binary files a/docs/_static/esp32-s2_saola1-pinout.jpg and /dev/null differ diff --git a/docs/_static/esp32-s3-devkitc-1-v1-isometric.png b/docs/_static/esp32-s3-devkitc-1-v1-isometric.png deleted file mode 100644 index 628672a1c3c2..000000000000 Binary files a/docs/_static/esp32-s3-devkitc-1-v1-isometric.png and /dev/null differ diff --git a/docs/_static/esp32-s3-devkitc-1-v1.1-isometric.png b/docs/_static/esp32-s3-devkitc-1-v1.1-isometric.png deleted file mode 100644 index 3eb0a731a15f..000000000000 Binary files a/docs/_static/esp32-s3-devkitc-1-v1.1-isometric.png and /dev/null differ diff --git a/docs/_static/esp32-s3-devkitm-1-v1-isometric.png b/docs/_static/esp32-s3-devkitm-1-v1-isometric.png deleted file mode 100644 index 67b4607b9673..000000000000 Binary files a/docs/_static/esp32-s3-devkitm-1-v1-isometric.png and /dev/null differ diff --git a/docs/conf_common.py b/docs/conf_common.py index 2a9a6fee84bb..c7c26263d858 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -218,7 +218,7 @@ 'api-reference/peripherals/touch_pad.rst', 'api-reference/peripherals/sd_pullup_requirements.rst', 'api-guides/RF_calibration.rst', - 'api-guides/phy.rst'] + USB_OTG_DFU_DOCS + USB_OTG_CONSOLE_DOCS + 'api-guides/phy.rst'] + USB_OTG_DFU_DOCS + USB_OTG_CONSOLE_DOCS + QEMU_DOCS # No JTAG docs for this one as it gets gated on SOC_USB_SERIAL_JTAG_SUPPORTED down below. ESP32C3_DOCS = ['hw-reference/esp32c3/**', @@ -379,6 +379,9 @@ idf_build_system = {'doxygen_component_info': True, 'component_info_ignore_file': Path(os.environ['IDF_PATH']) / 'docs' / 'component_info_ignore_file.txt'} +# Please update following list to enable Qemu doc guide (and cross references) for a new target +QEMU_TARGETS = ['esp32', 'esp32c3', 'esp32s3'] + # Callback function for user setup that needs be done after `config-init`-event # config.idf_target is not available at the initial config stage @@ -386,6 +389,10 @@ def conf_setup(app, config): config.add_warnings_content = 'This document is not updated for {} yet, so some of the content may not be correct.'.format(config.idf_target.upper()) add_warnings_file = '{}/../docs_not_updated/{}.txt'.format(app.confdir, config.idf_target) + + if config.idf_target in QEMU_TARGETS: + app.tags.add('TARGET_SUPPORT_QEMU') + try: with open(add_warnings_file) as warning_file: config.add_warnings_pages = warning_file.read().splitlines() diff --git a/docs/docs_not_updated/esp32c5.txt b/docs/docs_not_updated/esp32c5.txt index 0fdd62245da8..7a8cf3a65db4 100644 --- a/docs/docs_not_updated/esp32c5.txt +++ b/docs/docs_not_updated/esp32c5.txt @@ -1,37 +1,14 @@ -contribute/esp-idf-tests-with-pytest.rst -contribute/contributor-agreement.rst -contribute/documenting-code.rst -contribute/creating-examples.rst -contribute/style-guide.rst -contribute/copyright-guide.rst -contribute/install-pre-commit-hook.rst -contribute/index.rst api-guides/low-power-mode.rst api-guides/RF_calibration.rst api-guides/deep-sleep-stub.rst -api-guides/blufi.rst api-guides/coexist.rst api-guides/wifi.rst -api-guides/bluetooth.rst api-guides/wireshark-user-guide.rst api-guides/esp-wifi-mesh.rst api-guides/inc/external-ram-esp32-notes.rst api-guides/current-consumption-measurement-modules.rst -api-guides/esp-ble-mesh/ble-mesh-index.rst -api-guides/esp-ble-mesh/ble-mesh-feature-list.rst -api-guides/esp-ble-mesh/ble-mesh-terminology.rst -api-guides/esp-ble-mesh/ble-mesh-architecture.rst -api-guides/esp-ble-mesh/ble-mesh-faq.rst api-guides/wifi-security.rst api-guides/openthread.rst -third-party-tools/platformio.rst -third-party-tools/clion.rst -third-party-tools/visualgdb.rst -COPYRIGHT.rst -libraries-and-frameworks/libs-frameworks.rst -libraries-and-frameworks/index.rst -libraries-and-frameworks/cloud-frameworks.rst -versions.rst api-reference/template.rst api-reference/storage/vfs.rst api-reference/storage/spiffs.rst @@ -73,37 +50,9 @@ api-reference/system/async_memcpy.rst api-reference/system/power_management.rst api-reference/system/inc/power_management_esp32c5.rst api-reference/system/mm.rst -api-reference/bluetooth/esp_spp.rst -api-reference/bluetooth/esp_l2cap_bt.rst -api-reference/bluetooth/esp_hidd.rst -api-reference/bluetooth/esp_avrc.rst -api-reference/bluetooth/controller_vhci.rst -api-reference/bluetooth/esp_bt_defs.rst -api-reference/bluetooth/esp_hf_ag.rst -api-reference/bluetooth/esp_bt_main.rst -api-reference/bluetooth/esp_bt_device.rst -api-reference/bluetooth/esp_hidh.rst -api-reference/bluetooth/esp_gatts.rst -api-reference/bluetooth/esp_gattc.rst -api-reference/bluetooth/esp_sdp.rst -api-reference/bluetooth/bt_common.rst -api-reference/bluetooth/nimble/index.rst -api-reference/bluetooth/esp_hf_client.rst -api-reference/bluetooth/esp_a2dp.rst -api-reference/bluetooth/esp_blufi.rst -api-reference/bluetooth/bt_le.rst -api-reference/bluetooth/esp_hf_defs.rst -api-reference/bluetooth/esp_gap_bt.rst -api-reference/bluetooth/esp_gatt_defs.rst -api-reference/bluetooth/esp-ble-mesh.rst -api-reference/bluetooth/index.rst -api-reference/bluetooth/esp_gap_ble.rst -api-reference/bluetooth/classic_bt.rst api-reference/index.rst api-reference/protocols/esp_serial_slave_link.rst api-reference/protocols/esp_crt_bundle.rst -about.rst -resources.rst get-started/establish-serial-connection.rst get-started/linux-macos-setup.rst get-started/linux-macos-start-project.rst @@ -113,4 +62,4 @@ get-started/flashing-troubleshooting.rst get-started/windows-start-project.rst get-started/index.rst get-started/windows-setup-update.rst -index.rst +hw-reference/index.rst diff --git a/docs/docs_not_updated/esp32c61.txt b/docs/docs_not_updated/esp32c61.txt index 9f53a7c93235..43c9109f73c0 100644 --- a/docs/docs_not_updated/esp32c61.txt +++ b/docs/docs_not_updated/esp32c61.txt @@ -1,4 +1,3 @@ -api-guides/core_dump_internals.rst api-guides/performance/speed.rst api-guides/performance/size.rst api-guides/performance/ram-usage.rst @@ -8,34 +7,19 @@ api-guides/app_trace.rst api-guides/low-power-mode.rst api-guides/RF_calibration.rst api-guides/deep-sleep-stub.rst -api-guides/blufi.rst api-guides/lwip.rst api-guides/coexist.rst api-guides/wifi.rst api-guides/usb-otg-console.rst -api-guides/bluetooth.rst api-guides/wireshark-user-guide.rst api-guides/esp-wifi-mesh.rst api-guides/core_dump.rst api-guides/inc/external-ram-esp32-notes.rst api-guides/dfu.rst api-guides/current-consumption-measurement-modules.rst -api-guides/esp-ble-mesh/ble-mesh-index.rst -api-guides/esp-ble-mesh/ble-mesh-feature-list.rst -api-guides/esp-ble-mesh/ble-mesh-terminology.rst -api-guides/esp-ble-mesh/ble-mesh-architecture.rst -api-guides/esp-ble-mesh/ble-mesh-faq.rst api-guides/wifi-security.rst api-guides/index.rst api-guides/openthread.rst -third-party-tools/platformio.rst -third-party-tools/clion.rst -third-party-tools/visualgdb.rst -COPYRIGHT.rst -libraries-and-frameworks/libs-frameworks.rst -libraries-and-frameworks/index.rst -libraries-and-frameworks/cloud-frameworks.rst -versions.rst api-reference/template.rst api-reference/storage/vfs.rst api-reference/storage/spiffs.rst @@ -50,7 +34,6 @@ api-reference/storage/mass_mfg.rst api-reference/storage/fatfsgen.rst api-reference/storage/index.rst api-reference/storage/nvs_partition_parse.rst -api-reference/peripherals/sdspi_share.rst api-reference/peripherals/isp.rst api-reference/peripherals/adc_continuous.rst api-reference/peripherals/adc_oneshot.rst @@ -61,10 +44,7 @@ api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst api-reference/peripherals/usb_host/usb_host_notes_usbh.rst api-reference/peripherals/usb_host/usb_host_notes_design.rst api-reference/peripherals/usb_device.rst -api-reference/peripherals/sdspi_host.rst api-reference/peripherals/dac.rst -api-reference/peripherals/etm.rst -api-reference/peripherals/i2s.rst api-reference/peripherals/touch_element.rst api-reference/peripherals/ppa.rst api-reference/peripherals/ana_cmpr.rst @@ -140,32 +120,6 @@ api-reference/system/inc/power_management_esp32c2.rst api-reference/system/inc/show-efuse-table_ESP32-S2.rst api-reference/system/mm.rst api-reference/system/index.rst -api-reference/bluetooth/esp_spp.rst -api-reference/bluetooth/esp_l2cap_bt.rst -api-reference/bluetooth/esp_hidd.rst -api-reference/bluetooth/esp_avrc.rst -api-reference/bluetooth/controller_vhci.rst -api-reference/bluetooth/esp_bt_defs.rst -api-reference/bluetooth/esp_hf_ag.rst -api-reference/bluetooth/esp_bt_main.rst -api-reference/bluetooth/esp_bt_device.rst -api-reference/bluetooth/esp_hidh.rst -api-reference/bluetooth/esp_gatts.rst -api-reference/bluetooth/esp_gattc.rst -api-reference/bluetooth/esp_sdp.rst -api-reference/bluetooth/bt_common.rst -api-reference/bluetooth/nimble/index.rst -api-reference/bluetooth/esp_hf_client.rst -api-reference/bluetooth/esp_a2dp.rst -api-reference/bluetooth/esp_blufi.rst -api-reference/bluetooth/bt_le.rst -api-reference/bluetooth/esp_hf_defs.rst -api-reference/bluetooth/esp_gap_bt.rst -api-reference/bluetooth/esp_gatt_defs.rst -api-reference/bluetooth/esp-ble-mesh.rst -api-reference/bluetooth/index.rst -api-reference/bluetooth/esp_gap_ble.rst -api-reference/bluetooth/classic_bt.rst api-reference/error-codes.rst api-reference/index.rst api-reference/protocols/icmp_echo.rst @@ -176,8 +130,6 @@ api-reference/protocols/modbus.rst api-reference/protocols/mdns.rst api-reference/protocols/index.rst api-reference/protocols/asio.rst -about.rst -resources.rst get-started/establish-serial-connection.rst get-started/linux-macos-setup.rst get-started/linux-macos-start-project.rst @@ -187,4 +139,4 @@ get-started/flashing-troubleshooting.rst get-started/windows-start-project.rst get-started/index.rst get-started/windows-setup-update.rst -index.rst +hw-reference/index.rst diff --git a/docs/docs_not_updated/esp32p4.txt b/docs/docs_not_updated/esp32p4.txt index e11054ce4e55..158999f510af 100644 --- a/docs/docs_not_updated/esp32p4.txt +++ b/docs/docs_not_updated/esp32p4.txt @@ -6,8 +6,6 @@ api-guides/usb-otg-console.rst api-guides/esp-wifi-mesh.rst api-guides/dfu.rst api-guides/wifi-security.rst -api-reference/peripherals/adc_continuous.rst -api-reference/peripherals/adc_oneshot.rst api-reference/peripherals/touch_element.rst api-reference/peripherals/touch_pad.rst api-reference/peripherals/adc_calibration.rst diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 8a131eddecc9..8a3c7d78c245 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -212,10 +212,12 @@ INPUT = \ $(PROJECT_PATH)/components/esp_wifi/include/esp_mesh.h \ $(PROJECT_PATH)/components/esp_wifi/include/esp_now.h \ $(PROJECT_PATH)/components/esp_wifi/include/esp_smartconfig.h \ + $(PROJECT_PATH)/components/esp_wifi/include/local/esp_wifi_types_native.h \ $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_ap_get_sta_list.h \ $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_crypto_types.h \ $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_default.h \ $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_netif.h \ + $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_types_generic.h \ $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_types.h \ $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi.h \ $(PROJECT_PATH)/components/wpa_supplicant/esp_supplicant/include/esp_mbo.h \ @@ -314,6 +316,7 @@ INPUT = \ $(PROJECT_PATH)/components/vfs/include/esp_vfs_eventfd.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs_semihost.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs_null.h \ + $(PROJECT_PATH)/components/vfs/include/esp_vfs_ops.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs.h \ $(PROJECT_PATH)/components/wear_levelling/include/wear_levelling.h \ $(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/manager.h \ diff --git a/docs/doxygen/Doxyfile_esp32p4 b/docs/doxygen/Doxyfile_esp32p4 index 4f53c338f09d..3bea406c9835 100644 --- a/docs/doxygen/Doxyfile_esp32p4 +++ b/docs/doxygen/Doxyfile_esp32p4 @@ -44,5 +44,6 @@ INPUT += \ $(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_encode.h \ $(PROJECT_PATH)/components/esp_driver_ppa/include/driver/ppa.h \ $(PROJECT_PATH)/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h \ + $(PROJECT_PATH)/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h \ $(PROJECT_PATH)/components/sdmmc/include/sd_pwr_ctrl.h \ $(PROJECT_PATH)/components/sdmmc/include/sd_pwr_ctrl_by_on_chip_ldo.h \ diff --git a/docs/en/about.rst b/docs/en/about.rst index 8179b8f2ca98..b51032cb09ee 100644 --- a/docs/en/about.rst +++ b/docs/en/about.rst @@ -30,12 +30,24 @@ About The {IDF_TARGET_NAME} is a 2.4 GHz Wi-Fi Bluetooth Low Energy combo SoC, which integrates a 32-bit RISC-V RV32IMC single-core processor. +.. only:: esp32c5 + + This is documentation of `ESP-IDF `_, the framework to develop applications for {IDF_TARGET_NAME}. + + The {IDF_TARGET_NAME} is a 2.4 & 5 GHz dual-band Wi-Fi, Bluetooth Low Energy, and 802.15.4 Thread/Zigbee combo SoC, which integrates a 32-bit RISC-V RV32IMAC single-core processor. + .. only:: esp32c6 This is documentation of `ESP-IDF `_, the framework to develop applications for {IDF_TARGET_NAME}. The {IDF_TARGET_NAME} is a 2.4 GHz Wi-Fi, Bluetooth Low Energy, and 802.15.4 Thread/Zigbee combo SoC, which integrates a 32-bit RISC-V RV32IMAC single-core processor. +.. only:: esp32c61 + + This is documentation of `ESP-IDF `_, the framework to develop applications for {IDF_TARGET_NAME}. + + The {IDF_TARGET_NAME} is a 2.4 GHz Wi-Fi and Bluetooth Low Energy, which integrates a 32-bit RISC-V RV32IMAC single-core processor. + .. only:: esp32h2 This is documentation of `ESP-IDF `_, the framework to develop applications for {IDF_TARGET_NAME}. diff --git a/docs/en/api-guides/ble/ble-feature-support-status.rst b/docs/en/api-guides/ble/ble-feature-support-status.rst index 01a7aa5b3cc4..a750483ad3ff 100644 --- a/docs/en/api-guides/ble/ble-feature-support-status.rst +++ b/docs/en/api-guides/ble/ble-feature-support-status.rst @@ -162,7 +162,7 @@ If none of our chip series meet your needs, please contact `customer support tea - |experimental| - |experimental| * - - - Advertising Channel Index + - Randomized Advertising Channel Indexing - |unsupported| - |NA| - |NA| @@ -171,19 +171,19 @@ If none of our chip series meet your needs, please contact `customer support tea - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 or esp32c61 |experimental| - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 or esp32c61 |experimental| - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 or esp32c61 |experimental| * - .. centered:: |5.2| @@ -201,14 +201,14 @@ If none of our chip series meet your needs, please contact `customer support tea - .. only:: esp32 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c3 or esp32s3 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c3 or esp32s3 or esp32c5 or esp32c61 |experimental| - |unsupported| - .. only:: esp32 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c3 or esp32s3 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c3 or esp32s3 or esp32c5 or esp31c61 |experimental| * - .. centered:: |5.3| @@ -216,31 +216,31 @@ If none of our chip series meet your needs, please contact `customer support tea - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |supported| - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |supported| - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |supported| * - - LE Enhanced Connection Update (Connection Subrating) - - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 + - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |unsupported| .. only:: esp32c3 or esp32s3 |experimental| - |unsupported| - - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 + - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |unsupported| .. only:: esp32c3 or esp32s3 @@ -251,31 +251,31 @@ If none of our chip series meet your needs, please contact `customer support tea - .. only:: esp32 or esp32c3 or esp32s3 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c5 or esp32c61 |experimental| - .. only:: esp32 or esp32c3 or esp32s3 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c5 or esp32c61 |experimental| - .. only:: esp32 or esp32c3 or esp32s3 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c5 or esp32c61 |experimental| * - .. centered:: |5.4| - Advertising Coding Selection - - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 + - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |unsupported| .. only:: esp32c3 or esp32s3 |experimental| - |unsupported| - - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 + - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp31c61 |unsupported| .. only:: esp32c3 or esp32s3 diff --git a/docs/en/api-guides/ble/get-started/ble-connection.rst b/docs/en/api-guides/ble/get-started/ble-connection.rst index baeb7eedbede..54a7ad64c7b6 100644 --- a/docs/en/api-guides/ble/get-started/ble-connection.rst +++ b/docs/en/api-guides/ble/get-started/ble-connection.rst @@ -1 +1,477 @@ -.. include:: ../../../../zh_CN/api-guides/ble/get-started/ble-connection.rst +Connection +=================== + +:link_to_translation:`zh_CN:[中文]` + +This document is the third tutorial in the Getting Started series on Bluetooth Low Energy (Bluetooth LE), aiming to provide a brief overview of the connection process. Subsequently, the tutorial introduces the code implementation of peripheral devices using the :example:`NimBLE_Connection ` example based on the NimBLE host layer stack. + + +Learning Objectives +---------------------------------- + +- Understand the basic concepts of connection +- Learn about connection-related parameters +- Explore the code structure of the :example:`NimBLE_Connection ` example + + +Basic Concepts +--------------------------------- + + +Initiating a Connection +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*With the introduction of extended advertising features in Bluetooth LE 5.0, there are slight differences in the connection establishment process between Legacy ADV and Extended ADV. Below, we take the Legacy ADV connection establishment process as an example.* + +When a scanner receives an advertising packet on a specific advertising channel, if the advertiser is connectable, the scanner can send a connection request on the same advertising channel. The advertiser can set a *Filter Accept List* to filter out untrusted devices or accept connection requests from any scanner. Afterward, the advertiser becomes the peripheral device, and the scanner becomes the central device, allowing for bidirectional communication over the data channel. + +As described in the section :ref:`Scan Requests and Scan Responses `, after each advertising period on a channel, the advertiser briefly enters RX mode to receive possible scan requests. In fact, this RX phase can also accept connection requests. Thus, for the scanner, the time window for sending a connection request is similar to that for sending a scan request. + +.. figure:: ../../../../_static/ble/ble-advertiser-rx-connection-request.png + :align: center + :scale: 30% + :alt: Initiating a Connection + + Initiating a Connection + + +Connection Interval and Connection Event +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +During a connection, the central and peripheral devices periodically exchange data, with this data exchange cycle referred to as the Connection Interval. The connection interval is one of the connection parameters determined during the initial connection request and can be modified afterward. The step size for the connection interval is 1.25 ms, with a range from 7.5 ms (6 steps) to 4.0 s (3200 steps). + +A single data exchange process is termed Connection Event. During a connection event, there can be one or more data packet exchanges (when the data volume is large, it may need to be fragmented). In a data packet exchange, the central device first sends a packet to the peripheral device, followed by a packet from the peripheral device back to the central device. Even if either party does not need to send data at the start of a connection interval, it must send an empty packet to maintain the connection. + +The timing relationship between the connection interval and connection event can be referenced in the diagram below. + +.. figure:: ../../../../_static/ble/ble-connection-event-and-connection-interval.png + :align: center + :scale: 30% + :alt: Connection Interval and Connection Event + + Connection Interval and Connection Event + +It's worth noting that if a connection event requires sending a large amount of data, causing the duration of the connection event to exceed the connection interval, the connection event must be split into multiple events. This means that if there isn't enough remaining time in the connection interval to complete the next packet exchange, the next packet exchange must wait until the next connection interval begins. + +When the required data exchange frequency is low, a longer connection interval can be set; during the connection interval, the device can sleep outside of connection events to reduce power consumption. + + +Connection Parameters +------------------------------ + +As mentioned earlier, the connection interval is a connection parameter whose initial value is given by the central device in the connection request and can be modified in subsequent connections. In addition to the connection interval, there are many other important connection parameters. Below, we will explain some of these key parameters. + + +Supervision Timeout +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Supervision Timeout defines the maximum time allowed between two successful connection events. If a successful connection event is followed by a period longer than the supervision timeout without another successful connection event, the connection is considered to be disconnected. This parameter is critical for maintaining connection status; for example, if one party unexpectedly loses power or moves out of range, the other party can determine whether to disconnect to conserve communication resources by checking for a timeout. + + +Peripheral Latency +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Peripheral Latency specifies the maximum number of connection events that the peripheral device can skip when there is no data to send. + +To understand the purpose of this parameter, consider a Bluetooth mouse as an example. When a user is typing on a keyboard, the mouse may not have any data to send, so it’s preferable to reduce the frequency of data packet transmissions to save power. Conversely, during mouse usage, we want the mouse to send data as quickly as possible to minimize latency. This means that the data transmission from the Bluetooth mouse is intermittently high-frequency. If we rely solely on the connection interval for adjustments, a lower connection interval would lead to high energy consumption, while a higher connection interval would result in high latency. + +In this scenario, the peripheral latency mechanism is a perfect solution. To reduce the latency of a Bluetooth mouse, we can set a smaller connection interval, such as 10 ms, which allows a data exchange frequency of up to 100 Hz during intensive use. We can then set the peripheral latency to 100, allowing the mouse to effectively reduce the data exchange frequency to 1 Hz when idle. This design achieves variable data exchange frequency without adjusting connection parameters, maximizing user experience. + + +Maximum Transmission Unit +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Maximum Transmission Unit (MTU) refers to the maximum byte size of a single ATT data packet. Before discussing the MTU parameter, it's essential to describe the structure of the Data Channel Packet. + +The structure of the Data Channel Packet is similar to that of the :ref:`Advertising Packet `, with differences in the PDU structure. The data PDU can be divided into three parts: + +.. list-table:: + :align: center + :widths: 10 30 20 40 + :header-rows: 1 + + * - No. + - Name + - Byte Size + - Notes + * - 1 + - Header + - 2 + - + * - 2 + - Payload + - 0-27 / 0-251 + - Before Bluetooth LE 4.2, the maximum payload was 27 bytes; Bluetooth LE 4.2 introduced Data Length Extension (DLE), allowing a maximum payload of 251 bytes. + * - 3 + - Message Integrity Check, MIC + - 4 + - Optional + +The payload of the data PDU can be further divided into: + +.. list-table:: + :align: center + :widths: 10 70 20 + :header-rows: 1 + + * - No. + - Name + - Byte Size + * - 1 + - L2CAP Header + - 4 + * - 2 + - ATT Header + ATT Data + - 0-23 / 0-247 + +The default MTU value is 23 bytes, which matches the maximum ATT data byte size that can be carried in a single data PDU before Bluetooth LE 4.2. + +MTU can be set to larger values, such as 140 bytes. Before Bluetooth LE 4.2, with a maximum of 23 bytes carrying ATT data in the payload, a complete ATT data packet would need to be split across multiple data PDUs. After Bluetooth LE 4.2, a single data PDU can carry up to 247 bytes of ATT data, so an MTU of 140 bytes can still be accommodated in a single data PDU. + + +Hands-On Practice +-------------------------- + +Having understood the concepts related to connections, let’s move on to the :example:`NimBLE_Connection ` example code to learn how to build a simple peripheral device using the NimBLE stack. + + +Prerequisites +^^^^^^^^^^^^^^^^^^^^ + +1. An {IDF_TARGET_NAME} development board +2. ESP-IDF development environment +3. The **nRF Connect for Mobile** app installed on your phone + +If you have not yet completed the ESP-IDF development environment setup, please refer to :doc:`IDF Get Started <../../../get-started/index>`. + + +Try It Out +^^^^^^^^^^^^^^^^^^^^^^ + + +Building and Flashing +########################## + + +The reference example for this tutorial is :example:`NimBLE_Connection `. + +You can navigate to the example directory using the following command: + +.. code-block:: shell + + $ cd /examples/bluetooth/ble_get_started/nimble/NimBLE_Connection + +Please replace `` with your local ESP-IDF folder path. Then, you can open the NimBLE_Connection project using VSCode or another IDE you prefer. For example, after navigating to the example directory via the command line, you can open the project in VSCode using the following command: + +.. code-block:: shell + + $ code . + +Next, enter the ESP-IDF environment in the command line and set the target chip: + +.. code-block:: shell + + $ idf.py set-target + +You should see messages like: + +.. code-block:: shell + + ... + -- Configuring done + -- Generating done + -- Build files have been written to ... + +These messages indicate that the chip has been successfully configured. Then, connect the development board to your computer and run the following command to build the firmware, flash it to the board, and monitor the serial output from the {IDF_TARGET_NAME} development board: + +.. code-block:: shell + + $ idf.py flash monitor + +You should see messages like: + +.. code-block:: shell + + ... + main_task: Returned from app_main() + +Wait until the notification ends. + + +Connect and Disconnect +############################ + +Open the **nRF Connect for Mobile** app on your phone, pull down to refresh in the **SCANNER** tab, and locate the NimBLE_CONN device as shown in the image below. + +.. figure:: ../../../../_static/ble/ble-connection-device-list.jpg + :align: center + :scale: 30% + + Locate NimBLE_CONN Device + +If the device list is long, it's recommended to filter by the keyword "NimBLE" to quickly find the NimBLE_CONN device. + +Compared to :ref:`NimBLE_Beacon `, you can observe that most of the advertising data is consistent, but there is an additional Advertising Interval data with a value of 500 ms. Below the **CONNECT** button, you should also see that the advertising interval is around 510 ms. + +Click the **CONNECT** button to connect to the device, and you should be able to see the GAP service on your phone as shown below. + +.. figure:: ../../../../_static/ble/ble-connection-connected.jpg + :align: center + :scale: 30% + + Connected to NimBLE_CONN Device + +At this point, you should also see the LED on the development board light up. Click **DISCONNECT** to disconnect from the device, and the LED on the development board should turn off. + +If your development board does not have any other LEDs except the one for the power indicator, you should be able to observe the corresponding status indicators in the log output. + + +Viewing Log Output +########################## + +When connected to the device, you should see logs similar to the following: + +.. code-block:: + + I (36367) NimBLE_Connection: connection established; status=0 + I (36367) NimBLE_Connection: connection handle: 0 + I (36367) NimBLE_Connection: device id address: type=0, value=CE:4E:F7:F9:55:60 + I (36377) NimBLE_Connection: peer id address: type=1, value=7F:BE:AD:66:6F:45 + I (36377) NimBLE_Connection: conn_itvl=36, conn_latency=0, supervision_timeout=500, encrypted=0, authenticated=0, bonded=0 + + I (36397) NimBLE: GAP procedure initiated: + I (36397) NimBLE: connection parameter update; conn_handle=0 itvl_min=36 itvl_max=36 latency=3 supervision_timeout=500 min_ce_len=0 max_ce_len=0 + I (36407) NimBLE: + + I (37007) NimBLE_Connection: connection updated; status=0 + I (37007) NimBLE_Connection: connection handle: 0 + I (37007) NimBLE_Connection: device id address: type=0, value=CE:4E:F7:F9:55:60 + I (37007) NimBLE_Connection: peer id address: type=1, value=7F:BE:AD:66:6F:45 + I (37017) NimBLE_Connection: conn_itvl=36, conn_latency=3, supervision_timeout=500, encrypted=0, authenticated=0, bonded=0 + +The first part of the log shows the connection information output by the device when the connection is established, including the connection handle, the Bluetooth addresses of both the device and the mobile phone, as well as the connection parameters. Here, `conn_itvl` refers to the connection interval, `conn_latency` indicates the peripheral latency, and `supervision_timeout` is the connection timeout parameter. Other parameters can be temporarily ignored. + +The second part indicates that the device initiated an update to the connection parameters, requesting to set the peripheral latency to 3. + +The third part of the log displays the connection information after the update, showing that the peripheral latency has been successfully updated to 3, while other connection parameters remain unchanged. + +When the device disconnects, you should see logs similar to the following: + +.. code-block:: + + I (63647) NimBLE_Connection: disconnected from peer; reason=531 + I (63647) NimBLE: GAP procedure initiated: advertise; + I (63647) NimBLE: disc_mode=2 + I (63647) NimBLE: adv_channel_map=0 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=800 adv_itvl_max=801 + I (63657) NimBLE: + + I (63657) NimBLE_Connection: advertising started! + +You can observe that the device outputs the reason for disconnection when the connection is terminated, and then it initiates advertising again. + + +Code Details +------------------------------ + + +Project Structure Overview +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _nimble_connection_project_structure: + +The root directory structure of :example:`NimBLE_Connection ` is identical to that of :ref:`NimBLE_Beacon `. However, after building the firmware, you may notice an additional `managed_components` directory in the root, which contains dependencies automatically included during firmware construction; in this case, it's the `led_strip` component used to control the development board's LED. This dependency is referenced in the `main/idf_component.yml` file. + +Additionally, LED control-related source code has been introduced in the `main` folder. + + +Program Behavior Overview +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _nimble_connection_program_behavior: + +The behavior of this example is mostly consistent with that of :ref:`NimBLE_Beacon `, with the key difference being that this example can accept scan requests from scanners and enter a connected state after entering advertising mode. Furthermore, it utilizes a callback function, `gap_event_handler`, to handle connection events and respond accordingly, such as turning on the LED when a connection is established and turning it off when the connection is terminated. + +Entry Function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +.. _nimble_connection_entry_point: + +The entry function of this example is nearly the same as that of :ref:`NimBLE_Beacon `, except that before initializing NVS Flash, we call the `led_init` function to initialize the LED. + + +Starting Advertising +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The process for initiating advertising is largely similar to that of :ref:`NimBLE_Beacon `, but there are some details to note. + +First, we've added the advertising interval parameter in the scan response. We want to set the advertising interval to 500 ms, and since the unit for the advertising interval is 0.625 ms, we need to set it to `0x320`. However, NimBLE provides a unit conversion macro `BLE_GAP_ADV_ITVL_MS`, which allows us to avoid manual calculations, as shown below: + +.. code-block:: C + + static void start_advertising(void) { + ... + + /* Set advertising interval */ + rsp_fields.adv_itvl = BLE_GAP_ADV_ITVL_MS(500); + rsp_fields.adv_itvl_is_present = 1; + + ... + } + +Next, we want the device to be connectable, so we need to modify the advertising mode from non-connectable to connectable. Additionally, the advertising interval parameter set in the scan response serves only to inform other devices and does not affect the actual advertising interval. This parameter must be set in the advertising parameter structure to take effect. Here, we set the minimum and maximum values of the advertising interval to 500 ms and 510 ms, respectively. Finally, we want to handle GAP events using the callback function `gap_event_handler`, so we pass this callback to the API `ble_gap_adv_start` that starts advertising. The relevant code is as follows: + +.. code-block:: C + + static void start_advertising(void) { + ... + + /* Set non-connetable and general discoverable mode to be a beacon */ + adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; + adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; + + /* Set advertising interval */ + adv_params.itvl_min = BLE_GAP_ADV_ITVL_MS(500); + adv_params.itvl_max = BLE_GAP_ADV_ITVL_MS(510); + + /* Start advertising */ + rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, + gap_event_handler, NULL); + if (rc != 0) { + ESP_LOGE(TAG, "failed to start advertising, error code: %d", rc); + return; + } + ESP_LOGI(TAG, "advertising started!"); + + ... + } + +When the return value of `ble_gap_adv_start` is 0, it indicates that the device has successfully initiated advertising. Subsequently, the NimBLE protocol stack will call the `gap_event_handler` callback function whenever a GAP event is triggered, passing the corresponding GAP event. + +GAP Event Handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this example, we handle three different types of GAP events: + +- Connection Event `BLE_GAP_EVENT_CONNECT` +- Disconnection Event `BLE_GAP_EVENT_DISCONNECT` +- Connection Update Event `BLE_GAP_EVENT_CONN_UPDATE` + + +The connection event is triggered when a connection is successfully established or when a connection attempt fails. If the connection fails, we will restart advertising. If the connection is successful, we will log the connection information, turn on the LED, and initiate a connection parameter update to set the peripheral latency parameter to 3. Here’s how the code looks: + +.. code-block:: C + + static int gap_event_handler(struct ble_gap_event *event, void *arg) { + /* Local variables */ + int rc = 0; + struct ble_gap_conn_desc desc; + + /* Handle different GAP event */ + switch (event->type) { + + /* Connect event */ + case BLE_GAP_EVENT_CONNECT: + /* A new connection was established or a connection attempt failed. */ + ESP_LOGI(TAG, "connection %s; status=%d", + event->connect.status == 0 ? "established" : "failed", + event->connect.status); + + /* Connection succeeded */ + if (event->connect.status == 0) { + /* Check connection handle */ + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + if (rc != 0) { + ESP_LOGE(TAG, + "failed to find connection by handle, error code: %d", + rc); + return rc; + } + + /* Print connection descriptor and turn on the LED */ + print_conn_desc(&desc); + led_on(); + + /* Try to update connection parameters */ + struct ble_gap_upd_params params = {.itvl_min = desc.conn_itvl, + .itvl_max = desc.conn_itvl, + .latency = 3, + .supervision_timeout = + desc.supervision_timeout}; + rc = ble_gap_update_params(event->connect.conn_handle, ¶ms); + if (rc != 0) { + ESP_LOGE( + TAG, + "failed to update connection parameters, error code: %d", + rc); + return rc; + } + } + /* Connection failed, restart advertising */ + else { + start_advertising(); + } + return rc; + + ... + } + + return rc; + } + +The disconnection event is triggered when either party disconnects from the connection. At this point, we log the reason for the disconnection, turn off the LED, and restart advertising. Here’s the code: + +.. code-block:: C + + static int gap_event_handler(struct ble_gap_event *event, void *arg) { + ... + + /* Disconnect event */ + case BLE_GAP_EVENT_DISCONNECT: + /* A connection was terminated, print connection descriptor */ + ESP_LOGI(TAG, "disconnected from peer; reason=%d", + event->disconnect.reason); + + /* Turn off the LED */ + led_off(); + + /* Restart advertising */ + start_advertising(); + return rc; + + ... + } + +The connection update event is triggered when the connection parameters are updated. At this point, we log the updated connection information. Here’s the code: + +.. code-block:: C + + static int gap_event_handler(struct ble_gap_event *event, void *arg) { + ... + + /* Connection parameters update event */ + case BLE_GAP_EVENT_CONN_UPDATE: + /* The central has updated the connection parameters. */ + ESP_LOGI(TAG, "connection updated; status=%d", + event->conn_update.status); + + /* Print connection descriptor */ + rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc); + if (rc != 0) { + ESP_LOGE(TAG, "failed to find connection by handle, error code: %d", + rc); + return rc; + } + print_conn_desc(&desc); + return rc; + + ... + } + + +Summary +---------------------- + +Through this tutorial, you have learned the basic concepts of connections and how to use the NimBLE host stack to build a Bluetooth LE peripheral device using the :example:`NimBLE_Connection ` example. + +You can try to modify parameters in the example and observe the results in the log output. For instance, you can change the peripheral latency or connection timeout parameters to see if the modifications trigger connection update events. diff --git a/docs/en/api-guides/ble/get-started/ble-data-exchange.rst b/docs/en/api-guides/ble/get-started/ble-data-exchange.rst index 4b455a4bc149..e8a00f57ef17 100644 --- a/docs/en/api-guides/ble/get-started/ble-data-exchange.rst +++ b/docs/en/api-guides/ble/get-started/ble-data-exchange.rst @@ -1 +1,660 @@ -.. include:: ../../../../zh_CN/api-guides/ble/get-started/ble-data-exchange.rst +Data Exchange +======================== + +:link_to_translation:`zh_CN:[中文]` + +This document is the fourth tutorial in the Getting Started series on Bluetooth Low Energy (Bluetooth LE), aiming to provide a brief overview of the data exchange process within Bluetooth LE connections. Subsequently, this tutorial introduces the code implementation of a GATT server, using the :example:`NimBLE_GATT_Server ` example based on the NimBLE host layer stack. + + +Learning Objectives +---------------------------- + +- Understand the data structure details of characteristic data and services +- Learn about different data access operations in GATT +- Learn about the code structure of the :example:`NimBLE_GATT_Server ` example + + +GATT Data Characteristics and Services +-------------------------------------------------- + +GATT services are the infrastructure for data exchange between two devices in a Bluetooth LE connection, with the minimum data unit being an attribute. In the section on :ref:`Data Representation and Exchange `, we briefly introduced the attributes at the ATT layer and the characteristic data, services, and specifications at the GATT layer. Below are details regarding the attribute-based data structure. + + +Attributes +^^^^^^^^^^^^^^^^^^^^^^ + +An attribute consists of the following four parts: + +.. list-table:: + :align: center + :widths: 10 30 60 + :header-rows: 1 + + * - No. + - Name + - Description + * - 1 + - Handle + - A 16-bit unsigned integer representing the index of the attribute in the :ref:`attribute table ` + * - 2 + - Type + - ATT attributes use UUID (Universally Unique Identifier) to differentiate types + * - 3 + - Access Permission + - Indicates whether encryption/authorization is needed; whether it is readable or writable + * - 4 + - Value + - Actual user data or metadata of another attribute + +There are two types of UUIDs in Bluetooth LE: + +1. 16-bit UUIDs defined by SIG +2. 128-bit UUIDs customized by manufacturers + +Common characteristic and service UUIDs are provided in SIG's `Assigned Numbers `_ standard document, such as: + +.. list-table:: + :align: center + :widths: 20 60 20 + :header-rows: 1 + + * - Category + - Type Name + - UUID + * - Service + - Blood Pressure Service + - `0x1810` + * - Service + - Common Audio Service + - `0x1853` + * - Characteristic Data + - Age + - `0x2A80` + * - Characteristic Data + - Appearance + - `0x2A01` + +In fact, the definitions of these services and characteristic data are also provided by the SIG. For example, the value of the Heart Rate Measurement must include a flag field and a heart rate measurement field, and may include fields such as energy expended, RR-interval, and transmission interval, among others. Therefore, these definitions from SIG allow Bluetooth LE devices from different manufacturers to recognize each other's services or characteristic data, enabling cross-manufacturer communication. + +Manufacturers' customized 128-bit UUIDs are used for proprietary services or data characteristics, such as the UUID for the LED characteristic in this example: `0x00001525-1212-EFDE-1523-785FEABCD123`. + + +Characteristic Data +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _characteristic_attributes: + +A characteristic data item typically consists of the following attributes: + +.. list-table:: + :align: center + :widths: 10 30 30 30 + :header-rows: 1 + + * - No. + - Type + - Function + - Notes + * - 1 + - Characteristic Declaration + - Contains properties, handle, and UUID info for the characteristic value + - UUID is 0x2803, read-only + * - 2 + - Characteristic Value + - user data + - UUID identifies the characteristic type + * - 3 + - Characteristic Descriptor + - Additional description for the characteristic data + - Optional attribute + + +Relationship between Characteristic Declaration and Characteristic Value +################################################################################ + + +Using the Heart Rate Measurement as an example, the relationship between the characteristic declaration and characteristic value is illustrated as follows: + +The table below is an attribute table, containing two attributes of the Heart Rate Measurement characteristic. Let's first look at the attribute with handle 0. Its UUID is `0x2803`, and the access permission is read-only, indicating that this is a characteristic declaration attribute. The attribute value shows that the read/write property is read-only, and the handle points to 1, indicating that the attribute with handle 1 is the value attribute for this characteristic. The UUID is `0x2A37`, meaning that this characteristic type is Heart Rate Measurement. + +Now, let's examine the attribute with handle 1. Its UUID is `0x2A37`, and the access permission is also read-only, corresponding directly with the characteristic declaration attribute. The value of this attribute consists of flag bits and measurement values, which complies with the SIG specification for Heart Rate Measurement characteristic data. + ++-------------+--------------+-----------------+-------------------------+----------------------------+ +| Handle | UUID | Permissions | Value | Attribute Type | ++=============+==============+=================+=========================+============================+ +| 0 | `0x2803` | Read-only | Properties = Read-only | Characteristic Declaration | +| | | +-------------------------+ | +| | | | Handle = 1 | | +| | | +-------------------------+ | +| | | | UUID = `0x2A37` | | ++-------------+--------------+-----------------+-------------------------+----------------------------+ +| 1 | `0x2A37` | Read-only | Flags | Characteristic Value | +| | | +-------------------------+ | +| | | | Measurement value | | ++-------------+--------------+-----------------+-------------------------+----------------------------+ + + +Characteristic Descriptors +######################################### + +Characteristic descriptors provide supplementary information about characteristic data. The most common is the Client Characteristic Configuration Descriptor (CCCD). When a characteristic supports server-initiated :ref:`data operations ` (notifications or indications), CCCD must be used to describe the relevant information. This is a read-write attribute that allows the GATT client to inform the server whether notifications or indications should be enabled. Writing to this value is also referred to as subscribing or unsubscribing. + +The UUID for CCCD is `0x2902`, and its attribute value contains only 2 bits of information. The first bit indicates whether notifications are enabled, and the second bit indicates whether indications are enabled. By adding the CCCD to the attribute table and providing indication access permissions for the Heart Rate Measurement characteristic data, we obtain the complete form of the Heart Rate Measurement characteristic data in the attribute table as follows: + ++-------------+--------------+-----------------+-----------------------------+----------------------------+ +| Handle | UUID | Permissions | Value | Attribute Type | ++=============+==============+=================+=============================+============================+ +| 0 | `0x2803` | Read-only | Properties = Read/Indicate | Characteristic Declaration | +| | | +-----------------------------+ | +| | | | Handle = 1 | | +| | | +-----------------------------+ | +| | | | UUID = `0x2A37` | | ++-------------+--------------+-----------------+-----------------------------+----------------------------+ +| 1 | `0x2A37` | Read/Indicate | Flags | Characteristic Value | +| | | +-----------------------------+ | +| | | | Measurement value | | ++-------------+--------------+-----------------+-----------------------------+----------------------------+ +| 2 | `0x2902` | Read/Write | Notification status | Characteristic Descriptor | +| | | +-----------------------------+ | +| | | | Indication status | | ++-------------+--------------+-----------------+-----------------------------+----------------------------+ + + +Services +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The data structure of a service can be broadly divided into two parts: + +.. list-table:: + :align: center + :widths: 20 80 + :header-rows: 1 + + * - No. + - Name + * - 1 + - Service Declaration Attribute + * - 2 + - Characteristic Definition Attributes + +The three characteristic data attributes mentioned in the :ref:`Characteristic Data ` belong to characteristic definition attributes. In essence, the data structure of a service consists of several characteristic data attributes along with a service declaration attribute. + +The UUID for the service declaration attribute is 0x2800, which is read-only and holds the UUID identifying the service type. For example, the UUID for the Heart Rate Service is `0x180D`, so its service declaration attribute can be represented as follows: + +.. list-table:: + :align: center + :widths: 10 20 20 20 30 + :header-rows: 1 + + * - Handle + - UUID + - Permissions + - Value + - Attribute Type + * - 0 + - `0x2800` + - Read-only + - `0x180D` + - Service Declaration + + +Attribute Example +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _attribute_table: + +The following is an example of a possible attribute table for a GATT server, using the :example:`NimBLE_GATT_Server ` as an illustration. The example includes two services: the Heart Rate Service and the Automation IO Service. The former contains a Heart Rate Measurement characteristic, while the latter includes an LED characteristic. The complete attribute table for the GATT server is as follows: + ++-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ +| Handle | UUID | Permissions | Value | Attribute Type | ++=============+==========================================+=================+=================================================+============================+ +| 0 | `0x2800` | Read-only | UUID = `0x180D` | Service Declaration | ++-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ +| 1 | `0x2803` | Read-only | Properties = Read/Indicate | Characteristic Declaration | +| | | +-------------------------------------------------+ | +| | | | Handle = 2 | | +| | | +-------------------------------------------------+ | +| | | | UUID = `0x2A37` | | ++-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ +| 2 | `0x2A37` | Read/Indicate | Flags | Characteristic Value | +| | | +-------------------------------------------------+ | +| | | | Measurement value | | ++-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ +| 3 | `0x2902` | Read/Write | Notification status | Characteristic Descriptor | +| | | +-------------------------------------------------+ | +| | | | Indication status | | ++-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ +| 4 | `0x2800` | Read-only | UUID = `0x1815` | Service Declaration | ++-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ +| 5 | `0x2803` | Read-only | Properties = Write-only | Characteristic Declaration | +| | | +-------------------------------------------------+ | +| | | | Handle = 6 | | +| | | +-------------------------------------------------+ | +| | | | UUID = `0x00001525-1212-EFDE-1523-785FEABCD123` | | ++-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ +| 6 | `0x00001525-1212-EFDE-` |Write-only | LED status |Characteristic Value | +| | `1523-785FE` | | | | +| | `ABCD123` | | | | ++-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ + +When a GATT client first establishes communication with a GATT server, it pulls metadata from the server's attribute table to discover the available services and characteristics. This process is known as *Service Discovery*. + + +GATT Data Operations +------------------------------ + +.. _gatt_data_operation: + +Data operations refer to accessing characteristic data on a GATT server, which can be mainly categorized into two types: + +1. Client-initiated operations +2. Server-initiated operations + + +Client-initiated Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Client-initiated operations include the following three types: + +- **Read** + - A straightforward operation to pull the current value of a specific characteristic from the GATT server. +- **Write** + - Standard write operations require confirmation from the GATT server upon receiving the client's write request and data. +- **Write without response** + - This is another form of write operation that does not require server acknowledgment. + + +Server-Initiated Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Server-initiated operations are divided into two types: + +- **Notify** + - A GATT server actively pushes data to the client without requiring a confirmation response. +- **Indicate** + - Similar to notifications, but this requires confirmation from the client, which makes indication slower than notification. + +Although both notifications and indications are initiated by the server, the prerequisite for these operations is that the client has enabled notifications or indications. Therefore, the data exchange process in GATT essentially begins with a client request for data. + + +Hands-On Practice +---------------------------- + +Having grasped the relevant knowledge of GATT data exchange, let’s combine the :example:`NimBLE_GATT_Server ` example code to learn how to build a simple GATT server using the NimBLE protocol stack and put our knowledge into practice. + + +Prerequisites +^^^^^^^^^^^^^^^^^^ + +1. An {IDF_TARGET_NAME} development board +2. ESP-IDF development environment +3. The nRF Connect for Mobile application installed on your phone + +If you have not completed the ESP-IDF development environment setup, please refer to :doc:`IDF Get Started <../../../get-started/index>`. + + +Try It Out +^^^^^^^^^^^^^^^^^^ + +Please refer to :ref:`BLE Introduction Try It Out ` 。 + + +Code Explanation +------------------------------- + + +Project Structure Overview +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The root directory structure of :example:`NimBLE_GATT_Server ` is identical to that of :ref:`NimBLE_Connection `. Additionally, the `main` folder includes source code related to the GATT service and simulated heart rate generation. + + +Program Behavior Overview +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The program behavior of this example is largely consistent with that of :ref:`NimBLE_Connection `, with the difference being that this example adds GATT services and handles access to GATT characteristic data through corresponding callback functions. + + +Entry Function +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _nimble_gatt_server_entry_point: + +Based on :ref:`NimBLE_Connection `, a process to initialize the GATT service by calling the `gatt_svc_init` function has been added. Moreover, in addition to the NimBLE thread, a new `heart_rate_task` thread has been introduced, responsible for the random generation of simulated heart rate measurement data and indication handling. Relevant code is as follows: + +.. code-block:: C + + static void heart_rate_task(void *param) { + /* Task entry log */ + ESP_LOGI(TAG, "heart rate task has been started!"); + + /* Loop forever */ + while (1) { + /* Update heart rate value every 1 second */ + update_heart_rate(); + ESP_LOGI(TAG, "heart rate updated to %d", get_heart_rate()); + + /* Send heart rate indication if enabled */ + send_heart_rate_indication(); + + /* Sleep */ + vTaskDelay(HEART_RATE_TASK_PERIOD); + } + + /* Clean up at exit */ + vTaskDelete(NULL); + } + + void app_main(void) { + ... + + xTaskCreate(heart_rate_task, "Heart Rate", 4*1024, NULL, 5, NULL); + return; + } + +The `heart_rate_task` thread runs at a frequency of 1 Hz, as `HEART_RATE_TASK_PERIOD` is defined as 1000 ms. Each time it executes, the thread calls the `update_heart_rate` function to randomly generate a new heart rate measurement and then calls `send_heart_rate_indication` to handle the indication operation. + + +GATT Service Initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the `gatt_svc.c` file, there is a GATT service initialization function as follows: + +.. code-block:: C + + int gatt_svc_init(void) { + /* Local variables */ + int rc; + + /* 1. GATT service initialization */ + ble_svc_gatt_init(); + + /* 2. Update GATT services counter */ + rc = ble_gatts_count_cfg(gatt_svr_svcs); + if (rc != 0) { + return rc; + } + + /* 3. Add GATT services */ + rc = ble_gatts_add_svcs(gatt_svr_svcs); + if (rc != 0) { + return rc; + } + + return 0; + } + +This function first calls the `ble_svc_gatt_init` API to initialize the GATT Service. It's important to note that this GATT Service is a special service with the UUID `0x1801`, which is used by the GATT server to notify clients when services change (i.e., when GATT services are added or removed). In such cases, the client will re-execute the service discovery process to update its service information. + +Next, the function calls `ble_gatts_count_cfg` and `ble_gatts_add_svcs` APIs to add the services and characteristic data defined in the `gatt_svr_svcs` service table to the GATT server. + + +GATT Service Table +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `gatt_svr_svcs service` table is a crucial data structure in this example, defining all services and characteristic data used. The relevant code is as follows: + +.. code-block:: C + + /* Heart rate service */ + static const ble_uuid16_t heart_rate_svc_uuid = BLE_UUID16_INIT(0x180D); + + ... + + static uint16_t heart_rate_chr_val_handle; + static const ble_uuid16_t heart_rate_chr_uuid = BLE_UUID16_INIT(0x2A37); + + static uint16_t heart_rate_chr_conn_handle = 0; + + ... + + /* Automation IO service */ + static const ble_uuid16_t auto_io_svc_uuid = BLE_UUID16_INIT(0x1815); + static uint16_t led_chr_val_handle; + static const ble_uuid128_t led_chr_uuid = + BLE_UUID128_INIT(0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, + 0x12, 0x12, 0x25, 0x15, 0x00, 0x00); + + /* GATT services table */ + static const struct ble_gatt_svc_def gatt_svr_svcs[] = { + /* Heart rate service */ + {.type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &heart_rate_svc_uuid.u, + .characteristics = + (struct ble_gatt_chr_def[]){ + {/* Heart rate characteristic */ + .uuid = &heart_rate_chr_uuid.u, + .access_cb = heart_rate_chr_access, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_INDICATE, + .val_handle = &heart_rate_chr_val_handle}, + { + 0, /* No more characteristics in this service. */ + }}}, + + /* Automation IO service */ + { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &auto_io_svc_uuid.u, + .characteristics = + (struct ble_gatt_chr_def[]){/* LED characteristic */ + {.uuid = &led_chr_uuid.u, + .access_cb = led_chr_access, + .flags = BLE_GATT_CHR_F_WRITE, + .val_handle = &led_chr_val_handle}, + {0}}, + }, + + { + 0, /* No more services. */ + }, + }; + +The macros `BLE_UUID16_INIT` and `BLE_UUID128_INIT` provided by the NimBLE protocol stack allow for convenient conversion of 16-bit and 128-bit UUIDs from raw data into `ble_uuid16_t` and `ble_uuid128_t` type variables. + +The `gatt_svr_svcs` is an array of structures of type `ble_gatt_svc_def`. The `ble_gatt_svc_def` structure defines a service, with key fields being `type`, `uuid`, and `characteristics`. The `type` field indicates whether the service is primary or secondary, with all services in this example being primary. The `uuid` field represents the UUID of the service. The `characteristics` field is an array of `ble_gatt_chr_def` structures that stores the characteristics associated with the service. + +The `ble_gatt_chr_def` structure defines the characteristics, with key fields being `uuid`, `access_cb`, `flags`, and `val_handle`. The `uuid` field is the UUID of the characteristic. The `access_cb` field points to the access callback function for that characteristic. The `flags` field indicates the access permissions for the characteristic data. The `val_handle` field points to the variable handle address for the characteristic value. + +It's important to note that when the `BLE_GATT_CHR_F_INDICATE` flag is set for a characteristic, the NimBLE protocol stack automatically adds the CCCD, so there's no need to manually add the descriptor. + +Based on variable naming, it's clear that `gatt_svr_svcs` implements all property definitions in the :ref:`attribute table `. Additionally, access to the Heart Rate Measurement characteristic is managed through the `heart_rate_chr_access` callback function, while access to the LED characteristic is managed through the `led_chr_access` callback function. + + +Characteristic Data Access Management +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +LED Access Management +##################################### + +Access to the LED characteristic data is managed through the `led_chr_access` callback function, with the relevant code as follows: + +.. code-block:: C + + static int led_chr_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { + /* Local variables */ + int rc; + + /* Handle access events */ + /* Note: LED characteristic is write only */ + switch (ctxt->op) { + + /* Write characteristic event */ + case BLE_GATT_ACCESS_OP_WRITE_CHR: + /* Verify connection handle */ + if (conn_handle != BLE_HS_CONN_HANDLE_NONE) { + ESP_LOGI(TAG, "characteristic write; conn_handle=%d attr_handle=%d", + conn_handle, attr_handle); + } else { + ESP_LOGI(TAG, + "characteristic write by nimble stack; attr_handle=%d", + attr_handle); + } + + /* Verify attribute handle */ + if (attr_handle == led_chr_val_handle) { + /* Verify access buffer length */ + if (ctxt->om->om_len == 1) { + /* Turn the LED on or off according to the operation bit */ + if (ctxt->om->om_data[0]) { + led_on(); + ESP_LOGI(TAG, "led turned on!"); + } else { + led_off(); + ESP_LOGI(TAG, "led turned off!"); + } + } else { + goto error; + } + return rc; + } + goto error; + + /* Unknown event */ + default: + goto error; + } + + error: + ESP_LOGE(TAG, + "unexpected access operation to led characteristic, opcode: %d", + ctxt->op); + return BLE_ATT_ERR_UNLIKELY; + } + +When the GATT client initiates access to the LED characteristic data, the NimBLE protocol stack will call the `led_chr_access` callback function, passing in the handle information and access context. The `op` field of `ble_gatt_access_ctxt` is used to identify different access events. Since the LED is a write-only characteristic, we only handle the `BLE_GATT_ACCESS_OP_WRITE_CHR` event. + +In this processing branch, we first validate the attribute handle to ensure that the client is accessing the LED characteristic. Then, based on the `om` field of `ble_gatt_access_ctxt`, we verify the length of the access data. Finally, we check if the data in `om_data` is equal to 1 to either turn the LED on or off. + +If any other access events occur, they are considered unexpected, and we proceed to the error branch to return. + + +Heart Rate Measurement Read Access Management +###################################################### + +The heart rate measurement is a readable and indicative characteristic. The read access initiated by the client for heart rate measurement values is managed by the `heart_rate_chr_access` callback function, with the relevant code as follows: + +.. code-block:: C + + static int heart_rate_chr_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { + /* Local variables */ + int rc; + + /* Handle access events */ + /* Note: Heart rate characteristic is read only */ + switch (ctxt->op) { + + /* Read characteristic event */ + case BLE_GATT_ACCESS_OP_READ_CHR: + /* Verify connection handle */ + if (conn_handle != BLE_HS_CONN_HANDLE_NONE) { + ESP_LOGI(TAG, "characteristic read; conn_handle=%d attr_handle=%d", + conn_handle, attr_handle); + } else { + ESP_LOGI(TAG, "characteristic read by nimble stack; attr_handle=%d", + attr_handle); + } + + /* Verify attribute handle */ + if (attr_handle == heart_rate_chr_val_handle) { + /* Update access buffer value */ + heart_rate_chr_val[1] = get_heart_rate(); + rc = os_mbuf_append(ctxt->om, &heart_rate_chr_val, + sizeof(heart_rate_chr_val)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + goto error; + + /* Unknown event */ + default: + goto error; + } + + error: + ESP_LOGE( + TAG, + "unexpected access operation to heart rate characteristic, opcode: %d", + ctxt->op); + return BLE_ATT_ERR_UNLIKELY; + } + +Similar to the LED access management, we use the `op` field of the `ble_gatt_access_ctxt` access context to determine the access event, handling the `BLE_GATT_ACCESS_OP_READ_CHR` event. + +In the handling branch, we first validate the attribute handle to confirm that the client is accessing the heart rate measurement attribute. Then, we call the `get_heart_rate` function to retrieve the latest heart rate measurement, storing it in the measurement area of the `heart_rate_chr_val` array. Finally, we copy the data from `heart_rate_chr_val` into the `om` field of the `ble_gatt_access_ctxt` access context. The NimBLE protocol stack will send the data in this field to the client after the current callback function ends, thus achieving read access to the Heart Rate Measurement characteristic value. + + +Heart Rate Measurement Indication +############################################# + +When the client enables indications for heart rate measurements, the processing flow is a bit more complicated. First, enabling or disabling the heart rate measurement indications is a subscription or unsubscription event at the GAP layer, so we need to add a handling branch for subscription events in the `gap_event_handler` callback function, as follows: + +.. code-block:: C + + static int gap_event_handler(struct ble_gap_event *event, void *arg) { + ... + + /* Subscribe event */ + case BLE_GAP_EVENT_SUBSCRIBE: + /* Print subscription info to log */ + ESP_LOGI(TAG, + "subscribe event; conn_handle=%d attr_handle=%d " + "reason=%d prevn=%d curn=%d previ=%d curi=%d", + event->subscribe.conn_handle, event->subscribe.attr_handle, + event->subscribe.reason, event->subscribe.prev_notify, + event->subscribe.cur_notify, event->subscribe.prev_indicate, + event->subscribe.cur_indicate); + + /* GATT subscribe event callback */ + gatt_svr_subscribe_cb(event); + return rc; + } + +The subscription event is represented by `BLE_GAP_EVENT_SUBSCRIBE`. In this handling branch, we do not process the subscription event directly; instead, we call the `gatt_svr_subscribe_cb` callback function to handle the subscription event. This reflects the layered design philosophy of software, as the subscription event affects the GATT server's behavior in sending characteristic data and is not directly related to the GAP layer. Thus, it should be passed to the GATT layer for processing. + +Next, let's take a look at the operations performed in the `gatt_svr_subscribe_cb` callback function. + +.. code-block:: C + + void gatt_svr_subscribe_cb(struct ble_gap_event *event) { + /* Check connection handle */ + if (event->subscribe.conn_handle != BLE_HS_CONN_HANDLE_NONE) { + ESP_LOGI(TAG, "subscribe event; conn_handle=%d attr_handle=%d", + event->subscribe.conn_handle, event->subscribe.attr_handle); + } else { + ESP_LOGI(TAG, "subscribe by nimble stack; attr_handle=%d", + event->subscribe.attr_handle); + } + + /* Check attribute handle */ + if (event->subscribe.attr_handle == heart_rate_chr_val_handle) { + /* Update heart rate subscription status */ + heart_rate_chr_conn_handle = event->subscribe.conn_handle; + heart_rate_chr_conn_handle_inited = true; + heart_rate_ind_status = event->subscribe.cur_indicate; + } + } + +In this example, the callback handling is quite simple: it checks whether the attribute handle in the subscription event corresponds to the heart rate measurement attribute handle. If it does, it saves the corresponding connection handle and updates the indication status requested by the client. + +As mentioned in :ref:`Entry Function `, the `send_heart_rate_indication` function is called by the `heart_rate_task` thread at a frequency of 1 Hz. The implementation of this function is as follows: + +.. code-block:: C + + void send_heart_rate_indication(void) { + if (heart_rate_ind_status && heart_rate_chr_conn_handle_inited) { + ble_gatts_indicate(heart_rate_chr_conn_handle, + heart_rate_chr_val_handle); + ESP_LOGI(TAG, "heart rate indication sent!"); + } + } + +The `ble_gatts_indicate` function is an API provided by the NimBLE protocol stack for sending indications. This means that when the indication status for the heart rate measurement is true and the corresponding connection handle is available, calling the `send_heart_rate_indication` function will send the heart rate measurement to the GATT client. + +To summarize, when a GATT client subscribes to heart rate measurements, the `gap_event_handler` receives the subscription event and passes it to the `gatt_svr_subscribe_cb` callback function, which updates the subscription status for heart rate measurements. In the `heart_rate_task` thread, it checks the subscription status every second; if the status is true, it sends the heart rate measurement to the client. + +Summary +-------------------------------- + +Through this tutorial, you have learned how to create GATT services and their corresponding characteristic data using a service table, and you mastered the management of access to GATT characteristic data, including read, write, and subscription operations. You can now build more complex GATT service applications based on the :example:`NimBLE_GATT_Server ` example. diff --git a/docs/en/api-guides/ble/get-started/ble-device-discovery.rst b/docs/en/api-guides/ble/get-started/ble-device-discovery.rst index f6986844999f..10895c586b2f 100644 --- a/docs/en/api-guides/ble/get-started/ble-device-discovery.rst +++ b/docs/en/api-guides/ble/get-started/ble-device-discovery.rst @@ -1 +1,885 @@ -.. include:: ../../../../zh_CN/api-guides/ble/get-started/ble-device-discovery.rst +Device Discovery +======================= + +:link_to_translation:`zh_CN:[中文]` + +This document is the second tutorial in the Getting Started series on Bluetooth Low Energy (Bluetooth LE), aiming to provide a brief overview of the Bluetooth LE device discovery process, including basic concepts related to advertising and scanning. Following this, the tutorial introduces the code implementation of Bluetooth LE advertising, using the :example:`NimBLE_Beacon ` example based on the NimBLE host layer stack. + + +Learning Objectives +----------------------- + +- Understand the basic concepts of Advertising +- Understand the basic concepts of Scanning +- Learn about the code structure of the :example:`NimBLE_Beacon ` example + + +Advertising and Scanning are the states of Bluetooth LE devices during the device discovery phase before establishing a connection. First, let’s understand the basic concepts related to advertising. + + +Basic Concepts of Advertising +--------------------------------- + +Advertising is the process where a device sends out advertising packets via its Bluetooth antenna. Since the advertiser does not know whether there is a receiver in the environment or when the receiver will activate its antenna, it needs to send advertising packets periodically until a device responds. During this process, there are several questions for the advertiser to consider: + +1. Where should the advertising packets be sent? (Where?) +2. How long should the interval between advertising packets be? (When?) +3. What information should be included in the advertising packets? (What?) + + +Where to Send Advertising Packets? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Bluetooth Radio Frequency Band +######################################## + +The first question pertains to which radio frequency band the advertising packets should be sent on. The answer is provided by the Bluetooth Core Specification: the 2.4 GHz ISM band. This band is a globally available, license-free radio frequency band that is not controlled by any country for military or other purposes, and does not require payment to any organization. Thus, it has high availability and no usage costs. However, this also means the 2.4 GHz ISM band is very crowded and may interfere with other wireless communication protocols such as 2.4 GHz WiFi. + + +Bluetooth Channels +############################ + +Similar to Bluetooth Classic, the Bluetooth SIG has adopted Adaptive Frequency Hopping (AFH) in Bluetooth LE to address data collision issues. This technology can assess the congestion of RF channels and avoid crowded channels through frequency hopping to improve communication quality. However, unlike Bluetooth Classic, Bluetooth LE uses the 2.4 GHz ISM band divided into 40 RF channels, each with a 2 MHz bandwidth, ranging from 2402 MHz to 2480 MHz, while Bluetooth Classic uses 79 RF channels, each with a 1 MHz bandwidth. + +In the Bluetooth LE 4.2 standard, RF channels are categorized into two types, as follows: + +.. list-table:: + :align: center + :widths: 30 20 20 30 + :header-rows: 1 + + * - Type + - Quantity + - Index + - Purpose + * - Advertising Channel + - 3 + - 37-39 + - Used for sending advertising packets and scan response packets + * - Data Channel + - 37 + - 0-36 + - Used for sending data channel packets + +During advertising, the advertiser will send advertising packets on the three advertising channels (37-39). Once the advertising packets have been sent on all three channels, the advertising process is considered complete, and the advertiser will repeat the process at the next advertising interval. + + +Extended Advertising Features +################################## + +In the Bluetooth LE 4.2 standard, advertising packets are limited to a maximum of 31 bytes, which restricts the functionality of advertising. To enhance the capability of advertising, Bluetooth 5.0 introduced the Extended Advertising feature. This feature divides advertising packets into: + +.. list-table:: + :align: center + :widths: 40 20 20 20 + :header-rows: 1 + + * - Type + - Abbreviation + - Max Payload Size per Packet (Bytes) + - Max Total Payload Size (Bytes) + * - Primary Advertising Packet + - Legacy ADV + - 31 + - 31 + * - Extended Advertising Packet + - Extended ADV + - 254 + - 1650 + +Extended advertising packets are composed of `ADV_EXT_IND` and `AUX_ADV_IND`, transmitted on the primary and secondary advertising channels, respectively. The primary advertising channels correspond to channels 37-39, while the secondary advertising channels correspond to channels 0-36. Since the receiver always receives advertising data on the primary advertising channels, the advertiser must send `ADV_EXT_IND` on the primary advertising channels and `AUX_ADV_IND` on the secondary advertising channels. `ADV_EXT_IND` will indicate the secondary advertising channels where `AUX_ADV_IND` is transmitted. This mechanism allows the receiver to obtain the complete extended advertising packet by first receiving `ADV_EXT_IND` on the primary advertising channels and then going to the specified secondary advertising channels to receive `AUX_ADV_IND`. + +.. list-table:: + :align: center + :widths: 30 40 30 + :header-rows: 1 + + * - Type + - Channels + - Purpose + * - Primary Advertising Channel + - 37-39 + - Used to transmit `ADV_EXT_IND` of the extended advertising packet + * - Secondary Advertising Channel + - 0-36 + - Used to transmit `AUX_ADV_IND` of the extended advertising packet + + +How long should the advertising interval be? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Advertising Interval +######################### + +For the second question, regarding the period for sending advertising packets, the Bluetooth standard provides a clear parameter definition: Advertising Interval. The advertising interval can range from 20 ms to 10.24 s, with a step size of 0.625 ms. + +The choice of advertising interval affects both the discoverability of the advertiser and the device’s power consumption. If the advertising interval is too long, the probability of the advertising packets being received by a receiver becomes very low, which decreases the advertiser’s discoverability. Conversely, if the advertising interval is too short, frequent advertising consumes more power. Therefore, the advertiser needs to balance between discoverability and power consumption and choose the most appropriate advertising interval based on the application's needs. + +It is worth noting that if there are two advertisers with the same advertising interval in the same space, packet collision may occur, meaning both advertisers are sending advertising data to the same channel at the same time. Since advertising is a one-way process with no reception, the advertiser cannot know if a packet collision has occurred. To reduce the likelihood of such collisions, advertisers should add a random delay of 0-10 ms after each advertising event. + + +What information is included in the advertising packet? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Advertising Packet Structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For the third question, regarding the information contained in the advertising packet, the Bluetooth LE 4.2 standard defines the format of the advertising packet, as shown in the diagram below: + + +.. _adv_packet_structure: + +.. figure:: ../../../../_static/ble/ble-4.2-adv-packet-structure.png + :align: center + :scale: 35% + :alt: Advertising Packet Structure + + Bluetooth LE 4.2 Advertising Packet Structure + + +Let’s break it down step by step. The outer layer of an advertising packet contains four parts, which are: + +.. list-table:: + :align: center + :widths: 10 40 10 40 + :header-rows: 1 + + * - No. + - Name + - Byte Size + - Function + * - 1 + - Preamble + - 1 + - A special bit sequence used for device clock synchronization + * - 2 + - Access Address + - 4 + - Marks the address of the advertising packet + * - 3 + - Protocol Data Unit, PDU + - 2-39 + - The area where the actual data is stored + * - 4 + - Cyclic Redundancy Check, CRC + - 3 + - Used for cyclic redundancy checking + +The advertising packet is a type of Bluetooth packet, and its nature is determined by the type of PDU. Now, let's take a detailed look at the PDU. + + +PDU +########################## + +The PDU segment is where the actual data is stored. Its structure is as follows: + +.. list-table:: + :align: center + :widths: 10 50 40 + :header-rows: 1 + + * - No. + - Name + - Byte Size + * - 1 + - Header + - 2 + * - 2 + - Payload + - 0-37 + + +PDU Header +############## + +The PDU header contains various pieces of information, which can be broken down into six parts: + +.. list-table:: + :align: center + :widths: 10 40 10 40 + :header-rows: 1 + + * - No. + - Name + - Bit Size + - Notes + * - 1 + - PDU Type + - 4 + - + * - 2 + - Reserved for Future Use, **RFU** + - 1 + - + * - 3 + - Channel Selection Bit, **ChSel** + - 1 + - Indicates whether the advertiser supports the *LE Channel Selection Algorithm #2* + * - 4 + - TX Address, **TxAdd** + - 1 + - 0/1 indicates Public Address/Random Address + * - 5 + - Rx Address, **RxAdd** + - 1 + - 0/1 indicates Public Address/Random Address + * - 6 + - Payload Length + - 8 + - + +The PDU Type bit reflects the advertising behavior of the device. In the Bluetooth protocol, there are three pairs of advertising behaviors: + +- *Connectable* vs. *Non-connectable*: + - Whether the device accepts connection requests from others. +- *Scannable* vs. *Non-scannable*: + - Whether the device accepts scan requests from others. +- *Undirected* vs. *Directed*: + - Whether the advertising packet is sent to a specific device. + +These advertising behaviors can be combined into four common types of advertising, corresponding to four different PDU types: + +.. list-table:: + :align: center + :widths: 10 10 10 30 40 + :header-rows: 1 + + * - Connectable? + - Scannable? + - Undirected? + - PDU Type + - Purpose + * - Y + - Y + - Y + - `ADV_IND` + - The most common advertising type + * - Y + - N + - N + - `ADV_DIRECT_IND` + - Commonly used for reconnecting with known devices + * - N + - N + - Y + - `ADV_NONCONN_IND` + - Used by beacon devices to advertising data without connection + * - N + - Y + - Y + - `ADV_SCAN_IND` + - Used by beacons to advertise additional data via a scan response when packet length is insufficient + + +PDU Payload +##################### + +The PDU Payload is divided into two parts: + +.. list-table:: + :align: center + :widths: 10 50 10 30 + :header-rows: 1 + + * - No. + - Name + - Byte Size + - Notes + * - 1 + - Advertisement Address, **AdvA** + - 6 + - The 48-bit Bluetooth address of the advertiser + * - 2 + - Advertisement Data, **AdvData** + - 0-31 + - Consists of multiple Advertisement Data Structures + +The Advertisement Address can be either a: + +.. list-table:: + :align: center + :widths: 40 60 + :header-rows: 1 + + * - Type + - Description + * - Public Address + - A globally unique fixed device address that manufacturers must register and pay fees to IEEE for + * - Random Address + - A randomly generated address + +Random addresses are further divided into two categories: + +.. list-table:: + :align: center + :widths: 40 60 + :header-rows: 1 + + * - Type + - Description + * - Random Static Address + - Can be either fixed in firmware or randomly generated at startup but must not change during operation. Often used as an alternative to a Public Address. + * - Random Private Address + - Periodically changes to prevent device tracking. + +For devices using random private addresses to communicate with trusted devices, an Identity Resolving Key (IRK) should be used to generate the random address. Devices with the same IRK can resolve and obtain the true address. There are two types of random private addresses: + +.. list-table:: + :align: center + :widths: 40 60 + :header-rows: 1 + + * - Type + - Description + * - Resolvable Random Private Address + - Can be resolved with an IRK to obtain the device’s true address + * - Non-resolvable Random Private Address + - Completely random and rarely used, as it cannot be resolved and is only meant to prevent tracking + +Let's look at the **advertising data**. The format of an advertising data structure is defined as follows: + +.. list-table:: + :align: center + :widths: 10 40 20 30 + :header-rows: 1 + + * - No. + - Name + - Byte Size + - Notes + * - 1 + - AD Length + - 1 + - + * - 2 + - AD Type + - n + - Most types take 1 byte + * - 3 + - AD Data + - (AD Length - n) + - + + +Basic Concepts of Scanning +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Similar to the advertising process, scanning also raises three questions: + +1. Where to scan? (Where?) +2. When to scan and for how long? (When?) +3. What to do during scanning? (What?) + +For Bluetooth LE 4.2 devices, the advertiser only sends data on the advertising channels, which are channels 37-39. For Bluetooth LE 5.0 devices, if the advertiser has enabled extended advertising, it sends `ADV_EXT_IND` on the primary advertising channels and `AUX_ADV_IND` on the secondary advertising channels. +Thus, for Bluetooth LE 4.2 devices, scanners only need to receive advertising data on advertising channels. For Bluetooth LE 5.0 devices, scanners must first receive the `ADV_EXT_IND` on the primary advertising channels and, if it indicates a secondary channel, move to the corresponding secondary channel to receive the `AUX_ADV_IND`. + + +Scan Window and Scan Interval +##################################### + +The second question refers to the concepts of the Scan Window and the Scan Interval. + +- **Scan Window**: the duration for which the scanner continuously receives packets on a single RF channel. For example, if the scan window is set to 50 ms, the scanner continuously scans for 50 ms on each RF channel. + +- **Scan Interval**: the time between the start of two consecutive scan windows, which means the scan interval is always greater than or equal to the scan window. + +The diagram below illustrates the process of a scanner receiving advertising packets on a timeline. The scanner's scan interval is 100 ms, and the scan window is 50 ms; the advertiser's advertising interval is 50 ms, and the duration of the advertising packet transmission is for illustrative purposes only. As shown, the first scan window corresponds to channel 37, where the scanner successfully receives the advertiser's first broadcasting packet sent on channel 37, and this pattern continues. + +.. figure:: ../../../../_static/ble/ble-advertise-and-scan-sequence.png + :align: center + :scale: 30% + :alt: Advertising and Scanning Timing Diagram + + Advertising and Scanning Timing Diagram + + +.. _scan_request_and_scan_response: + +Scan Request and Scan Response +##################################### + +From the current introduction, it might seem that the advertiser only transmits and the scanner only receives during the advertising process. However, scanning behavior is divided into two types: + +- **Passive Scanning**: + - The scanner only receives advertising packets. +- **Active Scanning**: + - After receiving an advertising packet, the scanner sends a scan request to a scannable advertiser. + +When a scannable advertiser receives a scan request, it sends a scan response packet, providing more advertising information to the interested scanner. The structure of the scan response packet is identical to the advertising packet, with the difference being the PDU type in the PDU header. + +In scenarios where the advertiser operates in scannable advertising mode and the scanner in active scanning mode, the data transmission timing between the advertiser and the scanner becomes more complex. For the scanner, after a scan window ends, it briefly switches to TX mode to send a scan request, then quickly switches back to RX mode to receive a possible scan response. For the advertiser, after each advertising, it briefly switches to RX mode to receive any scan requests, and upon receiving one, it switches to TX mode to send the scan response. + +.. figure:: ../../../../_static/ble/ble-advertiser-rx-scan-request.png + :align: center + :scale: 30% + :alt: Scan Request Reception and Scan Response Transmission + + Scan Request Reception and Scan Response Transmission + + +Hands-On Practice +-------------------------- + +After learning the relevant concepts of advertising and scanning, let's apply this knowledge in practice using the :example:`NimBLE_Beacon ` example to create a simple beacon device. + + +Prerequisites +^^^^^^^^^^^^^^^^^^^^^^^ + +1. An {IDF_TARGET_NAME} development board +2. ESP-IDF development environment +3. The **nRF Connect for Mobile** app installed on your phone + +If you haven't set up the ESP-IDF development environment yet, please refer to :doc:`IDF Get Started <../../../get-started/index>`. + + +Try It Out +^^^^^^^^^^^^^^^^^^^^^^ + + +Building and Flashing +########################## + + +The reference example for this tutorial is :example:`NimBLE_Beacon `. + +You can navigate to the example directory using the following command: + +.. code-block:: shell + + $ cd /examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon + +Please replace `` with your local ESP-IDF folder path. Then, you can open the NimBLE_Beacon project using VSCode or another IDE you prefer. For example, after navigating to the example directory via the command line, you can open the project in VSCode using the following command: + +.. code-block:: shell + + $ code . + +Next, enter the ESP-IDF environment in the command line and set the target chip: + +.. code-block:: shell + + $ idf.py set-target + +You should see messages like: + +.. code-block:: shell + + ... + -- Configuring done + -- Generating done + -- Build files have been written to ... + +These messages indicate that the chip has been successfully configured. Then, connect the development board to your computer and run the following command to build the firmware, flash it to the board, and monitor the serial output from the {IDF_TARGET_NAME} development board: + +.. code-block:: shell + + $ idf.py flash monitor + +You should see messages like: + +.. code-block:: shell + + ... + main_task: Returned from app_main() + +Wait until the notification ends. + + +Viewing Beacon Device Information +######################################### + +.. _nimble_beacon_details: + +Open the **nRF Connect for Mobile** app on your phone, go to the **SCANNER** tab, and pull down to refresh. Locate the NimBLE_Beacon device, as shown in the figure below. + +.. figure:: ../../../../_static/ble/ble-scan-list-nimble-beacon.jpg + :align: center + :scale: 30% + :alt: NimBLE Beacon + + Locate NimBLE Beacon Device + +If the device list is long, it is recommended to filter by the keyword NimBLE in the device name to quickly find the NimBLE_Beacon device. + +You will notice that the NimBLE Beacon device contains rich information, including the Espressif website (this demonstrates the beacon advertising feature). Click the **RAW** button in the lower-right corner to view the raw advertising packet data, as shown below. + +.. figure:: ../../../../_static/ble/ble-adv-packet-raw-data.jpg + :align: center + :scale: 30% + :alt: ADV Packet Raw Data + + Advertising Packet Raw Data + +**Details** table summarizes all advertising data structures in the advertising data packet and the scan response data packet: + +.. list-table:: + :align: center + :widths: 30 10 10 30 20 + :header-rows: 1 + + * - Name + - Length + - Type + - Raw Data + - Resolved Information + * - Flags + - 2 Bytes + - `0x01` + - `0x06` + - General Discoverable, BR/EDR Not Supported + * - Complete Local Device Name + - 14 Bytes + - `0x09` + - `0x4E696D424C455F426561636F6E` + - NimBLE_Beacon + * - TX Power Level + - 2 Bytes + - `0x0A` + - `0x09` + - 9 dBm + * - Appearance + - 3 Bytes + - `0x19` + - `0x0002` + - Generic Tag (Generic category) + * - LE Role + - 2 Bytes + - `0x1C` + - `0x00` + - Only Peripheral Role supported + * - LE Bluetooth Device Address + - 8 Bytes + - `0x1B` + - `0x46F506BDF5F000` + - `F0:F5:BD:06:F5:46` + * - URI + - 17 Bytes + - `0x24` + - `0x172F2F6573707265737369662E636F6D` + - `https://espressif.com` + +It is worth mentioning that the total length of the first five advertising data structures is 28 bytes, leaving only 3 bytes of space in the advertising data packet, which is not enough to accommodate the last two data structures. Therefore, the last two advertising data structures must be placed in the scan response data packet. + +You may also notice that the Raw Data for the Device Appearance is `0x0002`, while in the code, the definition for Generic Tag is `0x0200`. Additionally, the Raw Data for the Device Address appears to be completely reversed, except for the last byte (`0x00`). This is because Bluetooth LE air packets follow a little-endian transmission order, meaning the lower bytes are placed at the front. + +Also, note that the **nRF Connect for Mobile** app does not provide a **CONNECT** button to connect to this device, which aligns with our expectations since a Beacon device is inherently non-connectable. Now, let's dive into the code details to see how such a Beacon device is implemented. + + +Code Explanation +--------------------------- + + +Project Structure Overview +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _nimble_beacon_project_structure: + +The root directory of :example:`NimBLE_Beacon ` is roughly divided into the following parts: + +- `README*.md` + - Documentation for the project +- `sdkconfig.defaults*` + - Default configurations for different chip development boards +- `CMakeLists.txt` + - Used to include the ESP-IDF build environment +- `main` + - The main project folder containing the source code, header files, and build configurations + + +Program Behavior Overview +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _nimble_beacon_program_behavior: + +Before diving into the code details, let's first get a macro understanding of the program behavior. + +First, we initialize the various modules used in the program, mainly including NVS Flash, the NimBLE Host Stack, and the GAP service. + +After the NimBLE Host Stack synchronizes with the Bluetooth controller, we confirm the Bluetooth address is available, then initiate an undirected, non-connectable, and scannable advertisement. + +The device remains in advertising mode continuously until a reboot occurs. + + +Entry Function +^^^^^^^^^^^^^^^^^^^^^^^ + +.. _nimble_beacon_entry_point: + +As with other projects, the entry function of the application is the `app_main` function in the `main/main.c` file, where we typically initialize the modules. In this example, we mainly do the following: + +1. Initialize NVS Flash and the NimBLE Host Stack +2. Initialize the GAP service +3. Start the FreeRTOS task for the NimBLE Host Stack + +The {IDF_TARGET_NAME} Bluetooth stack uses NVS Flash to store related configurations, so before initializing the Bluetooth stack, we must call the `nvs_flash_init` API to initialize NVS Flash. In some cases, we may need to call the `nvs_flash_erase` API to erase NVS Flash before initialization. + +.. code-block:: C + + void app_main(void) { + ... + + /* NVS flash initialization */ + ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || + ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to initialize nvs flash, error code: %d ", ret); + return; + } + + ... + } + +Next, you can call `nimble_port_init` API to initialize NimBLE host stack. + +.. code-block:: C + + void app_main(void) { + ... + + /* NimBLE host stack initialization */ + ret = nimble_port_init(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to initialize nimble stack, error code: %d ", + ret); + return; + } + + ... + } + +Then, we call the `gap_init` function defined in the `gap.c` file to initialize the GAP service and set the device name and appearance. + +.. code-block:: C + + void app_main(void) { + ... + + /* GAP service initialization */ + rc = gap_init(); + if (rc != 0) { + ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc); + return; + } + + ... + } + +Next, we configure the NimBLE host stack, which mainly involves setting some callback functions, including callbacks for when the stack is reset and when synchronization is complete, and then saving the configuration. + +.. code-block:: C + + static void nimble_host_config_init(void) { + /* Set host callbacks */ + ble_hs_cfg.reset_cb = on_stack_reset; + ble_hs_cfg.sync_cb = on_stack_sync; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + /* Store host configuration */ + ble_store_config_init(); + } + + void app_main(void) { + ... + + /* NimBLE host configuration initialization */ + nimble_host_config_init(); + + ... + } + +Finally, start the FreeRTOS thread for the NimBLE host stack. + +.. code-block:: C + + static void nimble_host_task(void *param) { + /* Task entry log */ + ESP_LOGI(TAG, "nimble host task has been started!"); + + /* This function won't return until nimble_port_stop() is executed */ + nimble_port_run(); + + /* Clean up at exit */ + vTaskDelete(NULL); + } + + void app_main(void) { + ... + + /* Start NimBLE host task thread and return */ + xTaskCreate(nimble_host_task, "NimBLE Host", 4*1024, NULL, 5, NULL); + + ... + } + + +Start Advertising +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _nimble_beacon_start_advertising: + +When developing applications using the NimBLE host stack, the programming model is event-driven. + +For example, after the NimBLE host stack synchronizes with the Bluetooth controller, a synchronization completion event will be triggered, invoking the `ble_hs_cfg.sync_cb` function. When setting up the callback function, we point the function pointer to the `on_stack_sync` function, which is the actual function called upon synchronization completion. + +In the `on_stack_sync` function, we call the `adv_init` function to initialize advertising operations. In `adv_init`, we first call the `ble_hs_util_ensure_addr` API to confirm that a usable Bluetooth address is available. Then, we call the `ble_hs_id_infer_auto` API to obtain the optimal Bluetooth address type. + +.. code-block:: C + + static void on_stack_sync(void) { + /* On stack sync, do advertising initialization */ + adv_init(); + } + + void adv_init(void) { + ... + + /* Make sure we have proper BT identity address set */ + rc = ble_hs_util_ensure_addr(0); + if (rc != 0) { + ESP_LOGE(TAG, "device does not have any available bt address!"); + return; + } + + /* Figure out BT address to use while advertising */ + rc = ble_hs_id_infer_auto(0, &own_addr_type); + if (rc != 0) { + ESP_LOGE(TAG, "failed to infer address type, error code: %d", rc); + return; + } + + ... + } + +Next, we copy the Bluetooth address data from the NimBLE stack's memory space into the local `addr_val` array, preparing it for subsequent use. + +.. code-block:: C + + void adv_init(void) { + ... + + /* Copy device address to addr_val */ + rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL); + if (rc != 0) { + ESP_LOGE(TAG, "failed to copy device address, error code: %d", rc); + return; + } + format_addr(addr_str, addr_val); + ESP_LOGI(TAG, "device address: %s", addr_str); + + ... + } + +Finally, we call the `start_advertising` function to initiate advertising. Within the `start_advertising` function, we first populate the advertising data structures, including the advertising flags, complete device name, transmission power level, device appearance, and LE role, into the advertising packet as follows: + +.. code-block:: C + + static void start_advertising(void) { + /* Local variables */ + int rc = 0; + const char *name; + struct ble_hs_adv_fields adv_fields = {0}; + + ... + + /* Set advertising flags */ + adv_fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; + + /* Set device name */ + name = ble_svc_gap_device_name(); + adv_fields.name = (uint8_t *)name; + adv_fields.name_len = strlen(name); + adv_fields.name_is_complete = 1; + + /* Set device tx power */ + adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + adv_fields.tx_pwr_lvl_is_present = 1; + + /* Set device appearance */ + adv_fields.appearance = BLE_GAP_APPEARANCE_GENERIC_TAG; + adv_fields.appearance_is_present = 1; + + /* Set device LE role */ + adv_fields.le_role = BLE_GAP_LE_ROLE_PERIPHERAL; + adv_fields.le_role_is_present = 1; + + /* Set advertiement fields */ + rc = ble_gap_adv_set_fields(&adv_fields); + if (rc != 0) { + ESP_LOGE(TAG, "failed to set advertising data, error code: %d", rc); + return; + } + + ... + } + +The `ble_hs_adv_fields` structure predefines some commonly used advertising data types. After completing the data setup, we can enable the corresponding advertising data structures by setting the relevant is_present field to 1 or by assigning a non-zero value to the corresponding length field (len). For example, in the code above, we configure the device's transmission power with `adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;`, and then enable that advertising data structure by setting `adv_fields.tx_pwr_lvl_is_present = 1;`. If we only configure the transmission power without setting the corresponding is_present field, the advertising data structure becomes invalid. Similarly, we configure the device name with `adv_fields.name = (uint8_t *)name;` and set the name's length with `adv_fields.name_len = strlen(name);` to add the device name as an advertising data structure to the advertising packet. If we only configure the device name without specifying its length, the advertising data structure will also be invalid. + +Finally, we call the `ble_gap_adv_set_fields` API to finalize the setup of the advertising data structures in the advertising packet. + +In the same way, we can fill in the device address and URI into the scan response packet as follows: + +.. code-block:: C + + static void start_advertising(void) { + ... + + struct ble_hs_adv_fields rsp_fields = {0}; + + ... + + /* Set device address */ + rsp_fields.device_addr = addr_val; + rsp_fields.device_addr_type = own_addr_type; + rsp_fields.device_addr_is_present = 1; + + /* Set URI */ + rsp_fields.uri = esp_uri; + rsp_fields.uri_len = sizeof(esp_uri); + + /* Set scan response fields */ + rc = ble_gap_adv_rsp_set_fields(&rsp_fields); + if (rc != 0) { + ESP_LOGE(TAG, "failed to set scan response data, error code: %d", rc); + return; + } + + ... + } + +Finally, we set the advertising parameters and initiate the advertising by calling the `ble_gap_adv_start` API. + +.. code-block:: C + + static void start_advertising(void) { + ... + + struct ble_gap_adv_params adv_params = {0}; + + ... + + /* Set non-connetable and general discoverable mode to be a beacon */ + adv_params.conn_mode = BLE_GAP_CONN_MODE_NON; + adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; + + /* Start advertising */ + rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, + NULL, NULL); + if (rc != 0) { + ESP_LOGE(TAG, "failed to start advertising, error code: %d", rc); + return; + } + ESP_LOGI(TAG, "advertising started!"); + } + + +Summary +--------------------- + +Through this tutorial, you have learned the basic concepts of advertising and scanning, and you mastered the method of building a Bluetooth LE Beacon device using the NimBLE host stack through the :example:`NimBLE_Beacon ` example. + +You can try to modify the data in the example and observe the changes in the **nRF Connect for Mobile** app. For instance, you might modify the `adv_fields` or `rsp_fields` structures to change the populated advertising data structures, or swap the advertising data structures between the advertising packet and the scan response packet. However, keep in mind that the maximum size for the advertising data in both the advertising packet and the scan response packet is 31 bytes; if the size of the advertising data structure exceeds this limit, calling the `ble_gap_adv_start` API will fail. diff --git a/docs/en/api-guides/ble/get-started/ble-introduction.rst b/docs/en/api-guides/ble/get-started/ble-introduction.rst index 2630c641569f..adc839ff0594 100644 --- a/docs/en/api-guides/ble/get-started/ble-introduction.rst +++ b/docs/en/api-guides/ble/get-started/ble-introduction.rst @@ -1 +1,342 @@ -.. include:: ../../../../zh_CN/api-guides/ble/get-started/ble-introduction.rst +Introduction +=================== + +:link_to_translation:`zh_CN:[中文]` + +This document is the first tutorial in the Getting Started series on Bluetooth Low Energy (Bluetooth LE). It introduces the basic concepts of Bluetooth LE and guides users through flashing a Bluetooth LE example onto an {IDF_TARGET_NAME} development board. The tutorial also instructs users on how to use the **nRF Connect for Mobile** app to control an LED and read heart rate data from the board. The tutorial offers a hands-on approach to understanding Bluetooth LE and working with the ESP-IDF framework for Bluetooth LE applications. + + +Learning Objectives +----------------------- + +- Understand the layered architecture of Bluetooth LE +- Learn the basic functions of each layer in Bluetooth LE +- Understand the functions of GAP and GATT/ATT layers +- Master the method of flashing Bluetooth LE examples on {IDF_TARGET_NAME} development board and interacting with it via a mobile phone + + +Preface +----------------- + +Most people have experienced Bluetooth technology in their daily lives—perhaps you are even wearing Bluetooth headphones right now, listening to audio from your phone or computer. However, audio transmission is a typical use case of Bluetooth Classic, while Bluetooth LE is a Bluetooth protocol that is not compatible with Bluetooth Classic and was introduced in Bluetooth 4.0. As the name suggests, Bluetooth LE is a low-power Bluetooth protocol with a lower data transfer rate compared to Bluetooth Classic. It is typically used in data communication for the Internet of Things (IoT), such as smart switches or sensors, as shown in the example in this tutorial. However, before diving into the example project, let's first understand the basic concepts of Bluetooth LE to help you get started. + + +Layered Architecture of Bluetooth LE +------------------------------------ + +The Bluetooth LE protocol defines a three-layer software architecture, listed from top to bottom: + +- Application Layer +- Host Layer +- Controller Layer + +The Application Layer is where applications are built using Bluetooth LE as the underlying communication technology, relying on the API interfaces provided by the Host Layer. + +The Host Layer implements low-level Bluetooth protocols such as L2CAP, GATT/ATT, SMP, and GAP, providing API interfaces to the Application Layer above and communicating with the Controller Layer below via the Host Controller Interface (HCI). + +The Controller Layer consists of the Physical Layer (PHY) and the Link Layer (LL), which directly interacts with the hardware below and communicates with the Host Layer above through the HCI. + +It’s worth mentioning that the Bluetooth Core Specification allows the Host Layer and Controller Layer to be physically separated, in which case the HCI is realized as a physical interface, including SDIO, USB, and UART, among others. However, the Host and Controller Layers can also coexist on the same chip for higher integration, in which case the HCI is referred to as the Virtual Host Controller Interface (VHCI). Generally, the Host Layer and Controller Layer together make up the Bluetooth LE Stack. + +The diagram below shows the layered structure of Bluetooth LE. + +.. figure:: ../../../../_static/ble/ble-architecture.png + :align: center + :scale: 50% + :alt: Bluetooth LE Layered Architecture + + Layered Architecture of Bluetooth LE + +As an application developer, during the development process, we primarily interact with the APIs provided by the Host Layer, which requires a certain understanding of the Bluetooth protocols within the Host Layer. Next, we will introduce the basic concepts of the GAP and GATT/ATT layers from two perspectives: connection and data exchange. + + +GAP Layer - Defining Device Connections +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The GAP (Generic Access Profile) layer defines the connection behaviors between Bluetooth LE devices and the roles they play in the connection. + + +GAP States and Roles +####################### + +The GAP layer defines three connection states and five different device roles, as follows: + +- Idle + - In this state, the device is in a standby state without any role. +- Device Discovery + - Advertiser + - Scanner + - Initiator +- Connection + - Peripheral + - Central + +The advertising data contains information such as the device address, indicating the advertiser's presence to external devices and informing them whether they are connectable. A scanner continuously receives advertising packets in the environment. If a scanner detects a connectable advertiser and wishes to establish a connection, it can switch its role to initiator. When the initiator receives another advertising data from the same advertiser, it immediately sends a Connection Request. If the advertiser has not enabled a Filter Accept List (also known as White List), or if the initiator is included in the advertiser's Filter Accept List, the connection will be successfully established. + +Once connected, the original advertiser becomes the peripheral device (formerly known as the slave device), and the original scanner or connection initiator becomes the central device (formerly known as the master device). + +The diagram below shows the relationship between the GAP roles. + +.. figure:: ../../../../_static/ble/ble-gap-state-diagram.png + :align: center + :scale: 50% + :alt: GAP roles relationship + + GAP Roles Relationship + + +Bluetooth LE Network Topology +################################ + +Bluetooth LE devices can connect to multiple Bluetooth LE devices simultaneously, playing multiple peripheral or central device roles, or acting as both a peripheral and a central device at the same time. For example, a Bluetooth LE gateway can act as a central device to connect with peripheral devices such as smart switches, while also functioning as a peripheral device to connect with central devices like smartphones, serving as a data intermediary. + +In a Bluetooth LE network, if all devices are connected to at least one other device and each plays only one type of role, this is referred to as a Connected Topology. If at least one device plays both peripheral and central roles simultaneously, the network is called a Multi-role Topology. + +Bluetooth LE also supports a connectionless network topology known as Broadcast Topology. In such a network, there are two roles: the device sending the data is called the Broadcaster, and the device receiving the data is called the Observer. The broadcaster only sends data and does not accept connections, while the observer only receives advertising data and does not initiate connections. For example, in a network where a sensor's data is shared by multiple devices, maintaining multiple connections can be costly, so advertising sensor data to all devices in the network is a more suitable approach. + + +Learn More +################## + +If you want to learn more about device discovery and connection, please refer to :doc:`Device Discovery <./ble-device-discovery>` and :doc:`Connection <./ble-connection>`. + + +GATT/ATT Layer - Data Representation and Exchange +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _gatt_att_introduction: + +The GATT/ATT layer defines the methods for data exchange between devices once they are connected, including how data is represented and the process of exchanging it. + + +ATT Layer +############# + +ATT stands for Attribute Protocol (ATT), which defines a basic data structure called **Attribute** and data access methods based on a server/client architecture. + +In simple terms, data is stored on a server as attributes, awaiting access by the client. For example, in a smart switch, the switch state is stored in the Bluetooth chip (server) of the smart switch as data in the form of an attribute. The user can then access the switch state attribute stored in the smart switch's Bluetooth chip (server) via their smartphone (client), to either read the current state (read access) or open and close the switch (write access). + +The attribute data structure typically consists of the following three parts: + +- Handle +- Type +- Value +- Permissions + +In the protocol stack implementation, attributes are generally managed in an array-like structure called an **Attribute Table**. The index of an attribute in this table is its handle, usually an unsigned integer. + +The type of an attribute is represented by a UUID and can be divided into three categories: 16-bit, 32-bit, and 128-bit UUIDs. The 16-bit UUIDs are universally defined by the Bluetooth Special Interest Group (Bluetooth SIG) and can be found in their publicly available `Assigned Numbers `__ document. The other two lengths of UUIDs are used for vendor-defined attribute types, with the 128-bit UUID being the most commonly used. + + +GATT Layer +############### + +GATT stands for Generic Attribute Profile (GATT), and it builds on ATT by defining the following three concepts: + +- Characteristic +- Service +- Profile + +The hierarchical relationship between these three concepts is shown in the diagram below. + +.. figure:: ../../../../_static/ble/ble-gatt-architecture.png + :align: center + :scale: 30% + :alt: GATT Hierarchical Architecture + + GATT Hierarchical Architecture + +.. _characteristic_structure: + +Both characteristics and services are composite data structures based on attributes. A characteristic is often described by two or more attributes, including: + +- Characteristic Declaration Attribute +- Characteristic Value Attribute + +In addition, a characteristic may also include several optional Characteristic Descriptor Attributes. + +A service itself is also described by an attribute, called the Service Declaration Attribute. A service can contain one or more characteristics, with a dependency relationship between them. Additionally, a service can reference another service using the `Include` mechanism, reusing its characteristic definitions to avoid redundant definitions for common characteristics, such as device names or manufacturer information. + +A profile is a predefined set of services. A device that implements all the services defined in a profile is said to comply with that profile. For example, the Heart Rate Profile includes the Heart Rate Service and the Device Information Service. Thus, a device that implements both the Heart Rate Service and Device Information Service is considered compliant with the Heart Rate Profile. + +Broadly speaking, any device that stores and manages characteristics is called a GATT Server, while any device that accesses the GATT Server to retrieve characteristics is called a GATT Client. + + +Learn More +#################### + +If you'd like to learn more about data representation and exchange, please refer to :doc:`Data Exchange <./ble-data-exchange>`. + + +Hands-On Practice +-------------------------- + + +After learning the basic concepts of Bluetooth LE, let's load a simple Bluetooth LE example onto the {IDF_TARGET_NAME} development board to experience the functionalities of LED control and heart rate data reading, and gain an intuitive understanding of Bluetooth LE technology. + + +Prerequisites +^^^^^^^^^^^^^^^^ + +1. An {IDF_TARGET_NAME} development board +2. ESP-IDF development environment +3. The **nRF Connect for Mobile** app installed on your phone + +If you haven't set up the ESP-IDF development environment yet, please refer to :doc:`IDF Get Started <../../../get-started/index>`. + + +Try It Out +^^^^^^^^^^^^^^^^^^ + +.. _nimble_gatt_server_practice: + +Building and Flashing +########################## + + +The reference example for this tutorial is :example:`NimBLE_GATT_Server `. + +You can navigate to the example directory using the following command: + +.. code-block:: shell + + $ cd /examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server + +Please replace `` with your local ESP-IDF folder path. Then, you can open the NimBLE_GATT_Server project using VSCode or another IDE you prefer. For example, after navigating to the example directory via the command line, you can open the project in VSCode using the following command: + +.. code-block:: shell + + $ code . + +Next, enter the ESP-IDF environment in the command line and set the target chip: + +.. code-block:: shell + + $ idf.py set-target + +You should see messages like: + +.. code-block:: shell + + ... + -- Configuring done + -- Generating done + -- Build files have been written to ... + +These messages indicate that the chip has been successfully configured. Then, connect the development board to your computer and run the following command to build the firmware, flash it to the board, and monitor the serial output from the {IDF_TARGET_NAME} development board: + +.. code-block:: shell + + $ idf.py flash monitor + +You should see messages like: + +.. code-block:: shell + + ... + main_task: Returned from app_main() + NimBLE_GATT_Server: Heart rate updated to 70 + +The heart rate data will update at a frequency of about 1 Hz, fluctuating between 60 and 80. + + +Connecting to the Development Board +####################################### + +Now the development board is ready. Next, open the **nRF Connect for Mobile** app on your phone, refresh the **SCANNER** tab, and find the NimBLE_GATT device, as shown in the image below. + +.. figure:: ../../../../_static/ble/ble-get-started-connect-brief.jpg + :align: center + :scale: 20% + :alt: Device Scan + + Device Scan + +If the device list is long, it is recommended to filter the device names using NimBLE as a keyword to quickly find the NimBLE_GATT device. + +Click on the **NimBLE_GATT** device entry to expand and view the detailed advertising data. + +.. figure:: ../../../../_static/ble/ble-get-started-connect-details.jpg + :align: center + :scale: 20% + :alt: Advertising Data Details + + Advertising Data Details + +Click the **CONNECT** button on the right. While the phone is connecting, you can observe many connection-related log messages in the serial output of the development board. Then, the NimBLE_GATT tab will appear on the phone, and there should be a **CONNECTED** status in the upper left corner, indicating that the phone has successfully connected to the development board via the Bluetooth LE protocol. On the CLIENT subpage, you should be able to see four GATT services, as shown in the figure. + +.. figure:: ../../../../_static/ble/ble-get-started-gatt-services-list.jpg + :align: center + :scale: 20% + :alt: GATT Services List + + GATT Services List + +The first two services are the GAP service and GATT service, which are foundational services in Bluetooth LE applications. The other two services are the Heart Rate Service and Automation IO Service, both defined by the Bluetooth SIG. They provide heart rate data reading and LED control functionality, respectively. + +Below the service names, you can see the corresponding UUIDs and the primary/secondary service designation. For example, the UUID for the Heart Rate Service is `0x180D`, which is a primary service. It’s important to note that the service names are derived from the UUIDs. In **nRF Connect for Mobile**, when implementing a GATT client, the developer preloads the database with services defined by the Bluetooth SIG or other customized services. Based on the GATT service UUID, service information is parsed. Therefore, if a service's UUID is not in the database, its information cannot be parsed, and the service name will be displayed as Unknown Service. + + +Let’s Light Up the LED! +############################### + +Now, let's try out the functionality of this example. First, click on the **Automation IO Service**, and you will see an LED characteristic under this service. + +.. figure:: ../../../../_static/ble/ble-get-started-automation-io-service-details.jpg + :align: center + :scale: 20% + :alt: Automation IO Service + + Automation IO Service + +As shown in the figure, the UUID of this LED characteristic is a 128-bit vendor-specific UUID. Click the **UPLOAD** button on the right to perform a write operation on this characteristic, as shown in the figure. + +.. figure:: ../../../../_static/ble/ble-get-started-led-write.jpg + :align: center + :scale: 20% + :alt: Write to LED Characteristic Data + + Write to LED Characteristic Data + +Select the **ON** option and send it. You should see the LED on the development board light up. Select the **OFF** option and send it, and you should observe the LED on the development board turning off again. + +If your development board does not have other LED except the one for the power indicator, you should be able to observe the corresponding status indication in the log output. + + +Receiving Heart Rate Data +############################# + +Next, click on the **Heart Rate Service**. You will see a Heart Rate Measurement characteristic under this service. + +.. figure:: ../../../../_static/ble/ble-get-started-heart-rate-service-details.jpg + :align: center + :scale: 20% + :alt: Heart Rate Service + + Heart Rate Service + +The UUID of the Heart Rate Measurement characteristic is `0x2A37`, which is a Bluetooth SIG-defined characteristic. Click the download button on the right to perform a read operation on the heart rate characteristic. You should see the latest heart rate measurement data appear in the `Value` field of the characteristic data section, as shown in the figure. + +.. figure:: ../../../../_static/ble/ble-get-started-heart-rate-read.jpg + :align: center + :scale: 20% + :alt: Read Heart Rate Characteristic Data + + Read Heart Rate Characteristic Data + +In the application, it is best for heart rate data to be synchronized to the GATT client immediately when the measurement is updated. To achieve this, we can click the **SUBSCRIPTION** button on the far right to request the heart rate characteristic to perform an indication operation. At this point, you should be able to see the heart rate measurement data continuously updating, as shown in the figure. + +.. figure:: ../../../../_static/ble/ble-get-started-heart-rate-indicate.jpg + :align: center + :scale: 20% + :alt: Subscribe to the heart rate characteristic data + + Subscribe to Heart Rate Characteristic Data + +You might have noticed that under the heart rate characteristic, there is a descriptor named *Client Characteristic Configuration* (often abbreviated as CCCD), with a UUID of `0x2902`. When you click the subscribe button, the value of this descriptor changes, which indicates that the characteristic's indications are enabled. Indeed, this descriptor is used to indicate the status of notifications or indications for the characteristic data. When you unsubscribe, the descriptor's value changes to indicate that notifications and indications are disabled. + + +Summary +----------- + +Through this tutorial, you have learned about the layered architecture of Bluetooth LE, the basic functions of the host and controller layers in the Bluetooth LE protocol stack, and the roles of the GAP and GATT/ATT layers. Additionally, using the :example:`NimBLE_GATT_Server ` example, you have mastered how to build and flash Bluetooth LE applications with the ESP-IDF framework, debug the application on your phone using **nRF Connect for Mobile**, remotely control the LED on the development board, and receive randomly generated heart rate data. You've taken the first step towards becoming a Bluetooth LE developer—congratulations! diff --git a/docs/en/api-guides/ble/host-feature-support-status.rst b/docs/en/api-guides/ble/host-feature-support-status.rst index 1900dca3a6f2..75c5c4425ece 100644 --- a/docs/en/api-guides/ble/host-feature-support-status.rst +++ b/docs/en/api-guides/ble/host-feature-support-status.rst @@ -79,7 +79,7 @@ If none of our chip series meet your needs, please contact `customer support tea - |experimental| - |experimental| * - - - Advertising Channel Index + - Randomized Advertising Channel Indexing - |NA| - |NA| * - diff --git a/docs/en/api-guides/ble/overview.rst b/docs/en/api-guides/ble/overview.rst index e360d210cd4c..9058f82c8a65 100644 --- a/docs/en/api-guides/ble/overview.rst +++ b/docs/en/api-guides/ble/overview.rst @@ -13,13 +13,13 @@ This document provides an architecture overview of the Bluetooth Low Energy (Blu {IDF_TARGET_NAME} supports Bluetooth 5.0 (LE) and is certified for Bluetooth LE 5.4. -.. only:: esp32c2 or esp32c6 or esp32h2 +.. only:: esp32c2 or esp32c6 or esp32h2 or esp32c5 or esp32c61 {IDF_TARGET_NAME} supports Bluetooth 5.0 (LE) and is certified for Bluetooth LE 5.3. The Bluetooth LE stack in ESP-IDF is a layered architecture that enables Bluetooth functionality on {IDF_TARGET_NAME} chip series. The table below shows its architecture. -.. only:: esp32 or esp32s3 or esp32c3 or esp32c6 +.. only:: esp32 or esp32s3 or esp32c3 or esp32c6 or esp32c5 or esp32c61 .. figure:: ../../../_static/bluetooth-architecture.png :align: center diff --git a/docs/en/api-guides/bootloader.rst b/docs/en/api-guides/bootloader.rst index 58b7d9ee7021..8c19b5535c12 100644 --- a/docs/en/api-guides/bootloader.rst +++ b/docs/en/api-guides/bootloader.rst @@ -3,16 +3,16 @@ Bootloader :link_to_translation:`zh_CN:[中文]` -The ESP-IDF Software Bootloader performs the following functions: +The ESP-IDF second stage bootloader performs the following functions: 1. Minimal initial configuration of internal modules; -2. Initialize :doc:`/security/flash-encryption` and/or :doc:`Secure ` features, if configured; +2. Initialize :doc:`/security/flash-encryption` and/or :doc:`Secure Boot ` features, if configured; 3. Select the application partition to boot, based on the partition table and ota_data (if any); 4. Load this image to RAM (IRAM & DRAM) and transfer management to the image that was just loaded. -Bootloader is located at the address {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} in the flash. +ESP-IDF second stage bootloader is located at the address {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} in the flash. -For a full description of the startup process including the ESP-IDF bootloader, see :doc:`startup`. +For a full description of the startup process including the ESP-IDF second stage bootloader, see :doc:`startup`. .. _bootloader-compatibility: @@ -50,7 +50,7 @@ SPI Flash Configuration Each ESP-IDF application or bootloader .bin file contains a header with :ref:`CONFIG_ESPTOOLPY_FLASHMODE`, :ref:`CONFIG_ESPTOOLPY_FLASHFREQ`, :ref:`CONFIG_ESPTOOLPY_FLASHSIZE` embedded in it. These are used to configure the SPI flash during boot. -The :ref:`first-stage-bootloader` in ROM reads the :ref:`second-stage-bootloader` header information from flash and uses this information to load the rest of the :ref:`second-stage-bootloader` from flash. However, at this time the system clock speed is lower than configured and not all flash modes are supported. When the :ref:`second-stage-bootloader` then runs, it will reconfigure the flash using values read from the currently selected app binary's header (and NOT from the :ref:`second-stage-bootloader` header). This allows an OTA update to change the SPI flash settings in use. +The :ref:`first-stage-bootloader` reads the :ref:`second-stage-bootloader` header information from flash and uses this information to load the rest of the :ref:`second-stage-bootloader` from flash. However, at this time the system clock speed is lower than configured and not all flash modes are supported. When the :ref:`second-stage-bootloader` then runs, it will reconfigure the flash using values read from the currently selected app binary's header (and NOT from the :ref:`second-stage-bootloader` header). This allows an OTA update to change the SPI flash settings in use. .. only:: esp32 diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index c22db7e76c8a..37356c0ea8b1 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -307,7 +307,14 @@ When CMake runs to configure the project, it logs the components included in the Multiple Components with the Same Name -------------------------------------- -When ESP-IDF is collecting all the components to compile, it will do this in the order specified by ``COMPONENT_DIRS``; by default, this means ESP-IDF's internal components first (``IDF_PATH/components``), then any components in directories specified in ``EXTRA_COMPONENT_DIRS``, and finally the project's components (``PROJECT_DIR/components``). If two or more of these directories contain component sub-directories with the same name, the component in the last place searched is used. This allows, for example, overriding ESP-IDF components with a modified version by copying that component from the ESP-IDF components directory to the project components directory and then modifying it there. If used in this way, the ESP-IDF directory itself can remain untouched. +When ESP-IDF is collecting all the components to compile, the search precedence is as follows (from highest to lowest): + +* Project components +* Components from ``EXTRA_COMPONENT_DIRS`` +* Project managed components, downloaded by the IDF Component Manager into ``PROJECT_DIR/managed_components``, unless the IDF Component Manager is disabled. +* ESP-IDF components (``IDF_PATH/components``) + +If two or more of these directories contain component sub-directories with the same name, the component with higher precedence is used. This allows, for example, overriding ESP-IDF components with a modified version by copying that component from the ESP-IDF components directory to the project components directory and then modifying it there. If used in this way, the ESP-IDF directory itself can remain untouched. .. note:: @@ -1257,12 +1264,26 @@ Set a :ref:`build property ` *property* with value *val* .. code-block:: none - idf_build_component(component_dir) + idf_build_component(component_dir [component_source]) Present a directory *component_dir* that contains a component to the build system. Relative paths are converted to absolute paths with respect to current directory. -All calls to this command must be performed before `idf_build_process`. -This command does not guarantee that the component will be processed during build (see the `COMPONENTS` argument description for `idf_build_process`) +An optional *component_source* argument can be specified to indicate the source of the component. (default: "project_components") + +This argument determines the overriding priority for components with the same name. For detailed information, see :ref:`cmake-components-same-name`. + +This argument supports the following values (from highest to lowest priority): + +- "project_components" - project components +- "project_extra_components" - components from ``EXTRA_COMPONENT_DIRS`` +- "project_managed_components" - custom project dependencies managed by the IDF Component Manager +- "idf_components" - ESP-IDF built-in components, typically under :idf:`/components` + +For instance, if a component named "json" is present as both "idf_components", and "project_components", the component as "project_components" takes precedence over the one as "idf_components". + +.. warning:: + + All calls to this command must be performed before `idf_build_process`. This command does not guarantee that the component will be processed during build (see the `COMPONENTS` argument description for `idf_build_process`). .. code-block:: none @@ -1422,6 +1443,7 @@ These are properties that describe a component. Values of component properties c - COMPONENT_LIB - name for created component static/interface library; set by ``idf_build_component`` and library itself is created by ``idf_component_register`` - COMPONENT_NAME - name of the component; set by ``idf_build_component`` based on the component directory name - COMPONENT_TYPE - type of the component, whether LIBRARY or CONFIG_ONLY. A component is of type LIBRARY if it specifies source files or embeds a file +- COMPONENT_SOURCE - source of the component, one of "idf_components", "project_managed_components", "project_components", "project_extra_components". This is used to determine the override precedence of components with the same name. - EMBED_FILES - list of files to embed in component; set from ``idf_component_register`` EMBED_FILES argument - EMBED_TXTFILES - list of text files to embed in component; set from ``idf_component_register`` EMBED_TXTFILES argument - INCLUDE_DIRS - list of component include directories; set from ``idf_component_register`` INCLUDE_DIRS argument @@ -1648,7 +1670,7 @@ Application Examples - :example:`build_system/wrappers` demonstrates how to use a linker feature to redefine or override any public function in both ESP-IDF and the bootloader, allowing modification or extension of a function's default behavior. -- :example:`custom_bootloader/bootloader_override` demonstrates how to override the second-stage bootloader from a regular project, providing a custom bootloader that prints an extra message on startup, with the ability to conditionally override the bootloader based on certain conditions like target-dependency or KConfig options. +- :example:`custom_bootloader/bootloader_override` demonstrates how to override the second stage bootloader from a regular project, providing a custom bootloader that prints an extra message on startup, with the ability to conditionally override the bootloader based on certain conditions like target-dependency or KConfig options. - :example:`build_system/cmake/import_lib` demonstrates how to import and use third-party libraries using ExternalProject CMake module. diff --git a/docs/en/api-guides/external-ram.rst b/docs/en/api-guides/external-ram.rst index f8cebef14d42..44a8d3bd7f1d 100644 --- a/docs/en/api-guides/external-ram.rst +++ b/docs/en/api-guides/external-ram.rst @@ -167,7 +167,7 @@ By applying the macro ``EXT_RAM_NOINIT_ATTR``, data could be moved from the inte The benefits of XiP from PSRAM is: - - PSRAM access speed may be faster than Flash access, so the overall application performance may be better. For example, if the PSRAM is an Octal mode (8-line-PSRAM) and is configured to 80 MHz, then it is faster than a Quad flash (4-line-flash) which is configured to 80 MHz. + - PSRAM access speed may be faster than flash access, so the overall application performance may be better. For example, if the PSRAM is an Octal mode (8-line PSRAM) and is configured to 80 MHz, then it is faster than a Quad flash (4-line flash) which is configured to 80 MHz. - The cache will not be disabled during an SPI1 flash operation, thus optimizing the code execution performance during SPI1 flash operations. For ISRs, ISR callbacks and data which might be accessed during this period, you do not need to place them in internal RAM, thus internal RAM usage can be optimized. This feature is useful for high throughput peripheral involved applications to improve the performance during SPI1 flash operations. @@ -186,11 +186,11 @@ By applying the macro ``EXT_RAM_NOINIT_ATTR``, data could be moved from the inte .. only:: SOC_MMU_PER_EXT_MEM_TARGET - Because {IDF_TARGET_NAME} flash and PSRAM are using two separate SPI buses, moving flash content to PSRAM will actually increase the load of the PSRAM MSPI bus, so the exact impact on performance will be dependent on your app usage of PSRAM. + Since the flash and PSRAM in {IDF_TARGET_NAME} use two separate SPI buses, moving flash content to PSRAM will actually increase the load on the PSRAM MSPI bus. Therefore, the exact impact on performance will be dependent on your app usage of PSRAM. - For example, as the PSRAM bus speed could be faster than flash bus speed (e.g., if the PSRAM is a HEX (16-line-PSRAM on ESP32P4) and is configured to 200 Mhz, then it is much faster than a Quad flash (4-line-flash) which is configured to 80 MHz.). + The PSRAM bus can operate at a higher speed than the flash bus. For example, if the PSRAM is a HEX (16-line PSRAM on ESP32P4) running at 200 MHz, it is significantly faster than a Quad flash (4-line flash) running at 80 MHz. - If the instructions and data that are used to be in flash are not accessed very frequently, you should get better performance with this option enabled. We suggest doing performance profiling to determine how enabling this option will impact your system. + If the instructions and data previously stored in flash are not accessed frequently, then enabling this option could improve performance. It is recommended to conduct performance profiling to evaluate how this option will affect your system. Restrictions ============ @@ -213,7 +213,7 @@ External RAM use has the following restrictions: - In general, external RAM will not be used as task stack memory. :cpp:func:`xTaskCreate` and similar functions will always allocate internal memory for stack and task TCBs. -The option :ref:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` can be used to allow placing task stacks into external memory. In these cases :cpp:func:`xTaskCreateStatic` must be used to specify a task stack buffer allocated from external memory, otherwise task stacks will still be allocated from internal memory. +The option :ref:`CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM` can be used to allow placing task stacks into external memory. In these cases :cpp:func:`xTaskCreateStatic` must be used to specify a task stack buffer allocated from external memory, otherwise task stacks will still be allocated from internal memory. Failure to Initialize diff --git a/docs/en/api-guides/fatal-errors.rst b/docs/en/api-guides/fatal-errors.rst index 319170810757..5f4ca99d7afd 100644 --- a/docs/en/api-guides/fatal-errors.rst +++ b/docs/en/api-guides/fatal-errors.rst @@ -288,14 +288,14 @@ RTC Watchdog Timeout -------------------- {IDF_TARGET_RTCWDT_RTC_RESET:default="Not updated", esp32="RTCWDT_RTC_RESET", esp32s2="RTCWDT_RTC_RST", esp32s3="RTCWDT_RTC_RST", esp32c3="RTCWDT_RTC_RST", esp32c2="RTCWDT_RTC_RST", esp32c6="LP_WDT_SYS", esp32h2="LP_WDT_SYS", esp32p4="LP_WDT_SYS"} -The RTC watchdog is used in the startup code to keep track of execution time and it also helps to prevent a lock-up caused by an unstable power source. It is enabled by default (see :ref:`CONFIG_BOOTLOADER_WDT_ENABLE`). If the execution time is exceeded, the RTC watchdog will restart the system. In this case, the ROM bootloader will print a message with the ``RTC Watchdog Timeout`` reason for the reboot. +The RTC watchdog is used in the startup code to keep track of execution time and it also helps to prevent a lock-up caused by an unstable power source. It is enabled by default (see :ref:`CONFIG_BOOTLOADER_WDT_ENABLE`). If the execution time is exceeded, the RTC watchdog will restart the system. In this case, the first stage (ROM) bootloader will print a message with the ``RTC Watchdog Timeout`` reason for the reboot. :: rst:0x10 ({IDF_TARGET_RTCWDT_RTC_RESET}) -The RTC watchdog covers the execution time from the first stage bootloader (ROM bootloader) to application startup. It is initially set in the ROM bootloader, then configured in the bootloader with the :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` option (9000 ms by default). During the application initialization stage, it is reconfigured because the source of the slow clock may have changed, and finally disabled right before the ``app_main()`` call. There is an option :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` which prevents the RTC watchdog from being disabled before ``app_main``. Instead, the RTC watchdog remains active and must be fed periodically in your application's code. +The RTC watchdog covers the execution time from the first stage (ROM) bootloader to application startup. It is initially set in the first stage (ROM) bootloader, then configured in the bootloader with the :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` option (9000 ms by default). During the application initialization stage, it is reconfigured because the source of the slow clock may have changed, and finally disabled right before the ``app_main()`` call. There is an option :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` which prevents the RTC watchdog from being disabled before ``app_main``. Instead, the RTC watchdog remains active and must be fed periodically in your application's code. .. _Guru-Meditation-Errors: diff --git a/docs/en/api-guides/file-system-considerations.rst b/docs/en/api-guides/file-system-considerations.rst index a57ab01c8781..9b6c05253ef0 100644 --- a/docs/en/api-guides/file-system-considerations.rst +++ b/docs/en/api-guides/file-system-considerations.rst @@ -50,7 +50,7 @@ The most significant properties and features of above-mentioned file systems are - Integrated - Integrated * - Minimum partition size - - * 128 sectors With wear levelling on (WL sector=4096B): + - * 8 sectors with wear levelling on (4 FATFS sectors + 4 WL sectors with WL sector size = 4096B) * plus 4 sectors at least * real number given by WL configuration (Safe, Perf) - * 6 logical blocks @@ -105,7 +105,7 @@ The most supported file system, recommended for common applications - file/direc **Examples:** * :example:`storage/sd_card`: access the SD card which uses the FAT file system -* :example:`storage/ext_flash_fatfs`: access the external flash chip which uses the FAT file system +* :example:`storage/fatfs/ext_flash`: access the external flash chip which uses the FAT file system .. _spiffs-fs-section: @@ -113,7 +113,7 @@ The most supported file system, recommended for common applications - file/direc SPIFFS ---------------------- -SPIFFS is a file system providing certain level of power-off safety (see repair-after-restart function :cpp:func:`esp_spiffs_check`) and built-in wear levelling. It tend to become slow down when exceeding around 70% of dedicated partition size due to its garbage collector implementation, and it also doesn't support directories. It is useful for applications depending only on few files (possibly large) and requiring high level of consistency. Generally, the SPIFFS needs less RAM resources than FatFS and supports flash chips up to 128MB in size. Please keep in mind the SPIFFS is not being developed and maintained anymore, so consider precisely whether its advantages for your project really prevail over the other file systems. +SPIFFS is a file system providing certain level of power-off safety (see repair-after-restart function :cpp:func:`esp_spiffs_check`) and built-in wear levelling. It tends to slow down when exceeding around 70% of the dedicated partition size due to its garbage collector implementation, and also doesn't support directories. It is useful for applications depending only on few files (possibly large) and requiring high level of consistency. Generally, the SPIFFS needs less RAM resources than FatFS and supports flash chips up to 128 MB in size. Please keep in mind the SPIFFS is not being developed and maintained anymore, so consider precisely whether its advantages for your project really prevail over the other file systems. **Related documents:** @@ -122,7 +122,7 @@ SPIFFS is a file system providing certain level of power-off safety (see repair- **Examples:** -* :example:`storage/spiffs`: SPIFFS examples +* :example:`storage/spiffs` demonstrates how to use SPIFFS. .. _littlefs-fs-section: @@ -143,7 +143,7 @@ LittleFS is available as external component in the ESP Registry, see `LittleFS c **Examples:** -* :example:`storage/littlefs`: ESP-IDF LittleFS example +* :example:`storage/littlefs` demonstrates how to use LittleFS. .. _nvs-fs-section: @@ -177,10 +177,10 @@ Points to keep in mind when developing NVS related code: **Examples:** -- Write a single integer value: :example:`storage/nvs_rw_value` -- Write a blob: :example:`storage/nvs_rw_blob` -- Encryption keys generation: :example:`security/nvs_encryption_hmac` -- Flash encryption workflow including NVS partition: :example:`security/flash_encryption` +- :example:`storage/nvs_rw_value` demonstrates how to use NVS to write and read a single integer value. +- :example:`storage/nvs_rw_blob` demonstrates how to use NVS to write and read a blob. +- :example:`security/nvs_encryption_hmac` demonstrates NVS encryption using the HMAC peripheral, where the encryption keys are derived from the HMAC key burnt in eFuse. +- :example:`security/flash_encryption` demonstrates the flash encryption workflow including NVS partition creation and usage. File handling design considerations @@ -205,5 +205,5 @@ Encrypting partitions Given storage security scheme and the {IDF_TARGET_NAME} chips design result into a few implications which may not be fully obvious in the main documents: * The Flash encryption applies only to the main SPI Flash memory, due to its cache module design (all the "transparent" encryption APIs run over this cache). This implies that external flash partitions cannot be encrypted using the native Flash Encryption means. -* External partition encryption can be deployed by implementing custom encrypt/decrypt code in appropriate driver APIs - either by implementing own SPI flash driver (see :example:`storage/custom_flash_driver`) or by customising higher levels in the driver stack, for instance by providing own :ref:`FatFS disk IO layer `. +* External partition encryption can be deployed by implementing custom encrypt/decrypt code in appropriate driver APIs - either by implementing own SPI flash driver (see :example:`storage/custom_flash_driver`) or by customizing higher levels in the driver stack, for instance by providing own :ref:`FatFS disk IO layer `. diff --git a/docs/en/api-guides/flash_psram_config.rst b/docs/en/api-guides/flash_psram_config.rst index bc4103cd9389..883c020cba15 100644 --- a/docs/en/api-guides/flash_psram_config.rst +++ b/docs/en/api-guides/flash_psram_config.rst @@ -73,7 +73,7 @@ To enable PSRAM, please enable the :ref:`CONFIG_SPIRAM` under ``Component config .. note:: - If a board with Octal flash resets before the second-stage bootloader, please refer to :ref:`Error Handling Chapter `. + If a board with Octal flash resets before the second stage bootloader, please refer to :ref:`Error Handling Chapter `. .. _flash-psram-combination: @@ -228,7 +228,7 @@ F4R4 Hardware Error Handling -------------- -1. If a board with Octal flash resets before the second-stage bootloader: +1. If a board with Octal flash resets before the second stage bootloader: .. code-block:: c @@ -243,7 +243,7 @@ Error Handling this may mean that the necessary eFuses are not correctly burnt. Please check the eFuse bits of the chip using ``idf.py efuse-summary``. - The ROM bootloader relies on an eFuse bit ``FLASH_TYPE`` to reset the flash into the default mode (SPI mode). If this bit is not burnt and the flash is working in OPI mode, ROM bootloader may not be able to read from the flash and load the following images. + The first stage (ROM) bootloader relies on an eFuse bit ``FLASH_TYPE`` to reset the flash into the default mode (SPI mode). If this bit is not burnt and the flash is working in OPI mode, the first stage (ROM) bootloader may not be able to read from the flash and load the following images. 2. If you enabled :ref:`CONFIG_ESPTOOLPY_OCT_FLASH`, and there's an error log saying: diff --git a/docs/en/api-guides/hlinterrupts.rst b/docs/en/api-guides/hlinterrupts.rst index 6655a13ae438..4b0dd29295d5 100644 --- a/docs/en/api-guides/hlinterrupts.rst +++ b/docs/en/api-guides/hlinterrupts.rst @@ -114,7 +114,7 @@ Then, in the component ``CMakeLists.txt``, add this name as an unresolved symbol This will ensure the linker to always includes the file defining ``ld_include_my_isr_file``, so that the ISR is always linked. -- High-priority interrupts can be routed and handled using :cpp:func:`esp_intr_alloc` and associated functions. The handler and handler arguments to :cpp:func:`esp_intr_alloc` must be NULL, however. +- High-priority interrupts can be routed and handled using :cpp:func:`esp_intr_alloc` and associated functions. However, the handler and handler arguments to :cpp:func:`esp_intr_alloc` must be NULL. - In theory, medium priority interrupts could also be handled in this way. ESP-IDF does not support this yet. diff --git a/docs/en/api-guides/inc/external-ram-esp32-notes.rst b/docs/en/api-guides/inc/external-ram-esp32-notes.rst index ac8f8d4764ce..b914ebd81657 100644 --- a/docs/en/api-guides/inc/external-ram-esp32-notes.rst +++ b/docs/en/api-guides/inc/external-ram-esp32-notes.rst @@ -1,4 +1,4 @@ -* Regarding stacks in PSRAM: For tasks that do not call ROM code in any way (directly or indirectly), the :ref:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` option will eliminate the check in :cpp:func:`xTaskCreateStatic`, allowing a task's stack to be in external RAM. However, using this is **not advised**. +* Regarding stacks in PSRAM: For tasks that do not call ROM code in any way (directly or indirectly), the :ref:`CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM` option will eliminate the check in :cpp:func:`xTaskCreateStatic`, allowing a task's stack to be in external RAM. However, using this is **not advised**. * When used at 80 MHz clock speed, external RAM must also occupy either the HSPI or VSPI bus. Select which SPI host will be used by :ref:`CONFIG_SPIRAM_OCCUPY_SPI_HOST`. diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index a1d261fa7817..26a46a389ec9 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -47,4 +47,5 @@ API Guides :SOC_USB_SERIAL_JTAG_SUPPORTED: usb-serial-jtag-console :SOC_WIFI_SUPPORTED: wifi :SOC_WIFI_SUPPORTED: wifi-security + wifi-expansion :SOC_WIFI_SUPPORTED or SOC_BT_SUPPORTED or SOC_IEEE802154_SUPPORTED: phy diff --git a/docs/en/api-guides/jtag-debugging/esp32.inc b/docs/en/api-guides/jtag-debugging/esp32.inc index d8671ea52915..c83adba3b48e 100644 --- a/docs/en/api-guides/jtag-debugging/esp32.inc +++ b/docs/en/api-guides/jtag-debugging/esp32.inc @@ -112,7 +112,7 @@ - Description * - ``ESP32_FLASH_VOLTAGE`` - When using 1.8 V flash ESP32 based modules, set this variable to ``1.8``. Refer to :ref:`jtag-debugging-tip-code-flash-voltage`. - * - ``ESP32_ONLYCPU`` + * - ``ESP_ONLYCPU`` - For multi-core targets, can be set to ``1`` to only enable single core debugging. --- diff --git a/docs/en/api-guides/jtag-debugging/esp32p4.inc b/docs/en/api-guides/jtag-debugging/esp32p4.inc index 88e2a7616c50..ea9b7d8140de 100644 --- a/docs/en/api-guides/jtag-debugging/esp32p4.inc +++ b/docs/en/api-guides/jtag-debugging/esp32p4.inc @@ -29,20 +29,25 @@ Info : only one transport option; autoselecting 'jtag' Info : esp_usb_jtag: VID set to 0x303a and PID to 0x1001 Info : esp_usb_jtag: capabilities descriptor set to 0x2000 - adapter speed: 40000 kHz - Info : esp_usb_jtag: serial (60:55:F9:F8:80:5C) + Info : Listening on port 6666 for tcl connections + Info : Listening on port 4444 for telnet connections + Info : esp_usb_jtag: serial (60:55:F9:F9:04:AD) Info : esp_usb_jtag: Device found. Base speed 24000KHz, div range 1 to 255 Info : clock speed 24000 kHz - Info : JTAG tap: esp32p4.lp.cpu tap/device found: 0x00012c25 (mfg: 0x612 (Espressif Systems), part: 0x0012, ver: 0x0) - Info : JTAG tap: esp32p4.hp.cpu tap/device found: 0x00012c25 (mfg: 0x612 (Espressif Systems), part: 0x0012, ver: 0x0) - Info : [esp32p4.hp.cpu] datacount=1 progbufsize=2 - Info : [esp32p4.hp.cpu] Examined RISC-V core; found 2 harts - Info : [esp32p4.hp.cpu] XLEN=32, misa=0x40901125 - Info : [esp32p4.hp.cpu] Examination succeed - Info : starting gdb server for esp32p4.hp.cpu on 3333 + Info : JTAG tap: esp32p4.tap0 tap/device found: 0x00012c25 (mfg: 0x612 (Espressif Systems), part: 0x0012, ver: 0x0) + Info : JTAG tap: esp32p4.tap1 tap/device found: 0x00012c25 (mfg: 0x612 (Espressif Systems), part: 0x0012, ver: 0x0) + Info : [esp32p4.hp.cpu0] datacount=1 progbufsize=2 + Info : [esp32p4.hp.cpu0] Core 0 made part of halt group 1. + Info : [esp32p4.hp.cpu0] Examined RISC-V core; found 2 harts + Info : [esp32p4.hp.cpu0] XLEN=32, misa=0x40901125 + Info : [esp32p4.hp.cpu0] Examination succeed + Info : [esp32p4.hp.cpu1] datacount=1 progbufsize=2 + Info : [esp32p4.hp.cpu1] Core 1 made part of halt group 1. + Info : [esp32p4.hp.cpu1] Examined RISC-V core; found 2 harts + Info : [esp32p4.hp.cpu1] XLEN=32, misa=0x40901125 + Info : [esp32p4.hp.cpu1] Examination succeed + Info : [esp32p4.hp.cpu0] starting gdb server on 3333 Info : Listening on port 3333 for gdb connections - Info : Listening on port 6666 for tcl connections - Info : Listening on port 4444 for telnet connections .. |run-openocd-cfg-file-err| replace:: ``Can't find board/esp32p4-builtin.cfg`` diff --git a/docs/en/api-guides/jtag-debugging/index.rst b/docs/en/api-guides/jtag-debugging/index.rst index 0ebdfb5dbd9c..f27904209b2d 100644 --- a/docs/en/api-guides/jtag-debugging/index.rst +++ b/docs/en/api-guides/jtag-debugging/index.rst @@ -226,6 +226,8 @@ OpenOCD flashing command ``program_esp`` has the following format: - ``exit`` - Optional. Finally exit OpenOCD. - ``compress`` - Optional. Compress image file before programming. - ``encrypt`` - Optional. Encrypt binary before writing to flash. Same functionality with ``idf.py encrypted-flash`` + - ``no_clock_boost`` - Optional. Disable setting target clock frequency to its maximum possible value before programming. Clock boost is enabled by default. + - ``restore_clock`` - Optional. Restore clock frequency to its initial value after programming. Disabled by default. You are now ready to start application debugging. Follow the steps described in the section below. diff --git a/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst b/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst index 65d5bb08e53c..8037f47cbf9f 100644 --- a/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst +++ b/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst @@ -83,7 +83,7 @@ GDB has a Python extension for FreeRTOS support. ESP-IDF automatically loads thi The MTDI pin of ESP32, being among four pins used for JTAG communication, is also one of ESP32's bootstrapping pins. On power up ESP32 is sampling binary level on MTDI to set it's internal voltage regulator used to supply power to external SPI flash chip. If binary level on MDTI pin on power up is low, the voltage regulator is set to deliver 3.3 V, if it is high, then the voltage is set to 1.8 V. The MTDI pin should have a pull-up or may rely on internal weak pull down resistor (see `ESP32 Series Datasheet `_ for details), depending on the type of SPI chip used. Once JTAG is connected, it overrides the pull-up or pull-down resistor that is supposed to do the bootstrapping. - To handle this issue OpenOCD's board configuration file (e.g. ``board\esp32-wrover-kit-3.3v.cfg`` for ESP-WROVER-KIT board) provides ``ESP32_FLASH_VOLTAGE`` parameter to set the idle state of the ``TDO`` line to a specified binary level, therefore reducing the chance of a bad bootup of application due to incorrect flash voltage. + To handle this issue OpenOCD's board configuration file (e.g. ``board\esp32-wrover-kit-3.3v.cfg`` for ESP-WROVER-KIT board) provides ``ESP32_FLASH_VOLTAGE`` parameter to set the idle state of the ``TDO`` line to a specified binary level, therefore reducing the chance of a bad boot-up of application due to incorrect flash voltage. Check specification of ESP32 module connected to JTAG, what is the power supply voltage of SPI flash chip. Then set ``ESP32_FLASH_VOLTAGE`` accordingly. Most WROOM modules use 3.3 V flash. WROVER earlier than ESP32-WROVER-B use 1.8 V flash, while ESP32-WROVER-B and -E modules use 3.3 V flash. @@ -178,6 +178,8 @@ It is important to set the variable before including the ESP-specific configurat - Set to ``0`` to disable Flash breakpoints support. * - ``ESP_SEMIHOST_BASEDIR`` - Set to the path (on the host) which will be the default directory for semihosting functions. + * - ``ESP_ONLYCPU`` + - For multi-core targets, can be set to ``1`` to only enable single core debugging. .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: openocd-target-specific-config-vars diff --git a/docs/en/api-guides/lwip.rst b/docs/en/api-guides/lwip.rst index 462ded4e9eb0..1920e2b03adf 100644 --- a/docs/en/api-guides/lwip.rst +++ b/docs/en/api-guides/lwip.rst @@ -31,9 +31,9 @@ Some common lwIP app APIs are supported indirectly by ESP-IDF: DNS server configuration in lwIP is global, not interface-specific. If you are using multiple network interfaces with distinct DNS servers, exercise caution to prevent inadvertent overwrites of one interface's DNS settings when acquiring a DHCP lease from another interface. -- Simple Network Time Protocol (SNTP) is also supported via the :doc:`/api-reference/network/esp_netif`, or directly via the :component_file:`lwip/include/apps/esp_sntp.h` functions, which also provide thread-safe API to :component_file:`lwip/lwip/src/include/lwip/apps/sntp.h` functions, see also :ref:`system-time-sntp-sync`. +- Simple Network Time Protocol (SNTP) is also supported via the :doc:`/api-reference/network/esp_netif`, or directly via the :component_file:`lwip/include/apps/esp_sntp.h` functions, which also provide thread-safe API to :component_file:`lwip/lwip/src/include/lwip/apps/sntp.h` functions, see also :ref:`system-time-sntp-sync`. For implementation details, see :example:`protocols/sntp`. This example demonstrates how to use the LwIP SNTP module to obtain time from internet servers, configure the synchronization method and interval, and retrieve time using the SNTP-over-DHCP module. - ICMP Ping is supported using a variation on the lwIP ping API, see :doc:`/api-reference/protocols/icmp_echo`. -- ICMPv6 Ping, supported by lwIP's ICMPv6 Echo API, is used to test IPv6 network connectivity. For more information, see :example:`protocols/sockets/icmpv6_ping`. +- ICMPv6 Ping, supported by lwIP's ICMPv6 Echo API, is used to test IPv6 network connectivity. For more information, see :example:`protocols/sockets/icmpv6_ping`. This example demonstrates how to use the network interface to discover an IPv6 address, create a raw ICMPv6 socket, send an ICMPv6 Echo Request to a destination IPv6 address, and wait for an Echo Reply from the target. - NetBIOS lookup is available using the standard lwIP API. :example:`protocols/http_server/restful_server` has the option to demonstrate using NetBIOS to look up a host on the LAN. - mDNS uses a different implementation to the lwIP default mDNS, see :doc:`/api-reference/protocols/mdns`. But lwIP can look up mDNS hosts using standard APIs such as ``gethostbyname()`` and the convention ``hostname.local``, provided the :ref:`CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES` setting is enabled. - The PPP implementation in lwIP can be used to create PPPoS (PPP over serial) interface in ESP-IDF. Please refer to the documentation of the :doc:`/api-reference/network/esp_netif` component to create and configure a PPP network interface, by means of the ``ESP_NETIF_DEFAULT_PPP()`` macro defined in :component_file:`esp_netif/include/esp_netif_defaults.h`. Additional runtime settings are provided via :component_file:`esp_netif/include/esp_netif_ppp.h`. PPPoS interfaces are typically used to interact with NBIoT/GSM/LTE modems. More application-level friendly API is supported by the `esp_modem `_ library, which uses this PPP lwIP module behind the scenes. @@ -53,17 +53,24 @@ A wide range of BSD Sockets reference materials are available, including: - `Single UNIX Specification - BSD Sockets page `_ - `Berkeley Sockets - Wikipedia page `_ -Examples -^^^^^^^^ +Application Examples +^^^^^^^^^^^^^^^^^^^^ A number of ESP-IDF examples show how to use the BSD Sockets APIs: -- :example:`protocols/sockets/tcp_server` -- :example:`protocols/sockets/tcp_client` -- :example:`protocols/sockets/udp_server` -- :example:`protocols/sockets/udp_client` -- :example:`protocols/sockets/udp_multicast` -- :example:`protocols/http_request`: this simplified example uses a TCP socket to send an HTTP request, but :doc:`/api-reference/protocols/esp_http_client` is a much better option for sending HTTP requests +- :example:`protocols/sockets/non_blocking` demonstrates how to configure and run a non-blocking TCP client and server, supporting both IPv4 and IPv6 protocols. + +- :example:`protocols/sockets/tcp_server` demonstrates how to create a TCP server that accepts client connection requests and receives data. + +- :example:`protocols/sockets/tcp_client` demonstrates how to create a TCP client that connects to a server using a predefined IP address and port. + +- :example:`protocols/sockets/tcp_client_multi_net` demonstrates how to use Ethernet and Wi-Fi interfaces together, connect to both simultaneously, create a TCP client for each interface, and send a basic HTTP request and response. + +- :example:`protocols/sockets/udp_server` demonstrates how to create a UDP server that receives client connection requests and data. + +- :example:`protocols/sockets/udp_client` demonstrates how to create a UDP client that connects to a server using a predefined IP address and port. + +- :example:`protocols/sockets/udp_multicast` demonstrates how to use the IPV4 and IPV6 UDP multicast features via the BSD-style sockets interface. Supported Functions ^^^^^^^^^^^^^^^^^^^ diff --git a/docs/en/api-guides/partition-tables.rst b/docs/en/api-guides/partition-tables.rst index 9da55858a1a8..4f95b0fd4035 100644 --- a/docs/en/api-guides/partition-tables.rst +++ b/docs/en/api-guides/partition-tables.rst @@ -30,7 +30,7 @@ Here is the summary printed for the "Single factory app, no OTA" configuration:: phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, -* At a 0x10000 (64 KB) offset in the flash is the app labelled "factory". The bootloader will run this app by default. +* At a 0x10000 (64 KB) offset in the flash is the app labelled "factory". The bootloader runs this app by default. * There are also two data regions defined in the partition table for storing NVS library partition and PHY init data. Here is the summary printed for the "Factory app, two OTA definitions" configuration:: @@ -75,9 +75,13 @@ Name field can be any meaningful name. It is not significant to the {IDF_TARGET_ Type Field ~~~~~~~~~~ -Partition type field can be specified as ``app`` (0x00) or ``data`` (0x01). Or it can be a number 0-254 (or as hex 0x00-0xFE). Types 0x00-0x3F are reserved for ESP-IDF core functions. +Partition type field can be specified as a name or a number 0-254 (or as hex 0x00-0xFE). Types 0x00-0x3F are reserved for ESP-IDF core functions. -If your app needs to store data in a format not already supported by ESP-IDF, then please add a custom partition type value in the range 0x40-0xFE. +- ``app`` (0x00), +- ``data`` (0x01), +- ``bootloader`` (0x02). By default, this partition is not included in any CSV partition table files because it is not required and does not impact the system's functionality. It is only useful for the bootloader OTA update. Even if this partition is not present in the CSV file, it is still possible to perform the OTA. Please note that if you specify this partition in the CSV file, its address and size must match Kconfigs, +- ``partition_table`` (0x03), +- 0x40-0xFE are reserved for **custom partition types**. If your app needs to store data in a format not already supported by ESP-IDF, then use a value from this range. See :cpp:type:`esp_partition_type_t` for the enum definitions for ``app`` and ``data`` partitions. @@ -85,7 +89,7 @@ If writing in C++ then specifying a application-defined partition type requires static const esp_partition_type_t APP_PARTITION_TYPE_A = (esp_partition_type_t)0x40; -The ESP-IDF bootloader ignores any partition types other than ``app`` (0x00) and ``data`` (0x01). +The bootloader ignores any partition types other than ``app`` (0x00) and ``data`` (0x01). SubType ~~~~~~~ @@ -105,6 +109,16 @@ See enum :cpp:type:`esp_partition_subtype_t` for the full list of subtypes defin - ``ota_0`` (0x10) ... ``ota_15`` (0x1F) are the OTA app slots. When :doc:`OTA <../api-reference/system/ota>` is in use, the OTA data partition configures which app slot the bootloader should boot. When using OTA, an application should have at least two OTA application slots (``ota_0`` & ``ota_1``). Refer to the :doc:`OTA documentation <../api-reference/system/ota>` for more details. - ``test`` (0x20) is a reserved subtype for factory test procedures. It will be used as the fallback boot partition if no other valid app partition is found. It is also possible to configure the bootloader to read a GPIO input during each boot, and boot this partition if the GPIO is held low, see :ref:`bootloader_boot_from_test_firmware`. +* When type is ``bootloader``, the SubType field can be specified as: + + - ``primary`` (0x00). It is the so-called 2nd stage bootloader, which is placed at the {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} address in the flash. The ``gen_esp32part.py`` does not allow to have this partition in the CSV file for now. + - ``ota`` (0x01). It is a temporary bootloader partition used by the bootloader OTA update functionality for downloading a new image. + +* When type is ``partition_table``, the SubType field can be specified as: + + - ``primary`` (0x00). It is the primary partition table, which is placed at the :ref:`CONFIG_PARTITION_TABLE_OFFSET` address in the flash. The ``gen_esp32part.py`` does not allow to have this partition in the CSV file for now. + - ``ota`` (0x01). It is a temporary partition table partition used by the partition table OTA update functionality for downloading a new image. + * When type is ``data``, the subtype field can be specified as ``ota`` (0x00), ``phy`` (0x01), ``nvs`` (0x02), nvs_keys (0x04), or a range of other component-specific subtypes (see :cpp:type:`subtype enum `). - ``ota`` (0) is the :ref:`OTA data partition ` which stores information about the currently selected OTA app slot. This partition should be 0x2000 bytes in size. Refer to the :ref:`OTA documentation ` for more details. diff --git a/docs/en/api-guides/performance/ram-usage.rst b/docs/en/api-guides/performance/ram-usage.rst index b3a0d142cf74..e6c60914fdb6 100644 --- a/docs/en/api-guides/performance/ram-usage.rst +++ b/docs/en/api-guides/performance/ram-usage.rst @@ -192,17 +192,18 @@ The following options will reduce IRAM usage of some ESP-IDF features: - Refer to the sdkconfig menu ``Auto-detect Flash chips``, and you can disable flash drivers which you do not need to save some IRAM. :SOC_GPSPI_SUPPORTED: - Enable :ref:`CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH`. Provided that :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` is not enabled and the heap functions are not incorrectly used from ISRs, this option is safe to enable in all configurations. :esp32c2: - Enable :ref:`CONFIG_BT_RELEASE_IRAM`. Release BT text section and merge BT data, bss & text into a large free heap region when ``esp_bt_mem_release`` is called. This makes Bluetooth unavailable until the next restart, but saving ~22 KB or more of IRAM. + :SOC_DEBUG_HAVE_OCD_STUB_BINS: - Disabling :ref:`CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS` frees 8 KB IRAM but overall speed of debugging might be impacted due to the added overhead of runtime stub loading especially when using flash breakpoints. .. only:: esp32 Using SRAM1 for IRAM ^^^^^^^^^^^^^^^^^^^^ - The SRAM1 memory area is normally used for DRAM, but it is possible to use parts of it for IRAM with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM`. This memory would previously be reserved for DRAM data usage (e.g., ``.bss``) by the software bootloader and later added to the heap. After this option was introduced, the bootloader DRAM size was reduced to a value closer to what it normally actually needs. + The SRAM1 memory area is normally used for DRAM, but it is possible to use parts of it for IRAM with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM`. This memory would previously be reserved for DRAM data usage (e.g., ``.bss``) by the ESP-IDF second stage bootloader and later added to the heap. After this option was introduced, the bootloader DRAM size was reduced to a value closer to what it normally actually needs. - To use this option, ESP-IDF should be able to recognize that the new SRAM1 area is also a valid load address for an image segment. If the software bootloader was compiled before this option existed, then the bootloader will not be able to load the app that has code placed in this new extended IRAM area. This would typically happen if you are doing an OTA update, where only the app would be updated. + To use this option, ESP-IDF should be able to recognize that the new SRAM1 area is also a valid load address for an image segment. If the second stage bootloader was compiled before this option existed, then the bootloader will not be able to load the app that has code placed in this new extended IRAM area. This would typically happen if you are doing an OTA update, where only the app would be updated. - If the IRAM section were to be placed in an invalid area, then this would be detected during the boot-up process, and result in a failed boot: + If the IRAM section were to be placed in an invalid area, then this would be detected during the boot up process, and result in a failed boot: .. code-block:: text @@ -210,7 +211,7 @@ The following options will reduce IRAM usage of some ESP-IDF features: .. warning:: - Apps compiled with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` may fail to boot, if used together with a software bootloader that was compiled before this config option was introduced. If you are using an older bootloader and updating over OTA, please test carefully before pushing any updates. + Apps compiled with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` may fail to boot, if used together with a second stage bootloader that was compiled before this config option was introduced. If you are using an older bootloader and updating over OTA, please test carefully before pushing any updates. Any memory that ends up unused for static IRAM will be added to the heap. diff --git a/docs/en/api-guides/performance/size.rst b/docs/en/api-guides/performance/size.rst index f88f8a38bc94..f7e627bfdde6 100644 --- a/docs/en/api-guides/performance/size.rst +++ b/docs/en/api-guides/performance/size.rst @@ -194,6 +194,7 @@ These include: - :ref:`CONFIG_MBEDTLS_HAVE_TIME` - :ref:`CONFIG_MBEDTLS_ECDSA_DETERMINISTIC` - :ref:`CONFIG_MBEDTLS_SHA512_C` +- :ref:`CONFIG_MBEDTLS_SHA3_C` - :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS` - :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS` - :ref:`CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION` diff --git a/docs/en/api-guides/performance/speed.rst b/docs/en/api-guides/performance/speed.rst index 0cce05a57178..c374a3274622 100644 --- a/docs/en/api-guides/performance/speed.rst +++ b/docs/en/api-guides/performance/speed.rst @@ -301,9 +301,9 @@ Improving I/O Performance Using standard C library functions like ``fread`` and ``fwrite`` instead of platform-specific unbuffered syscalls such as ``read`` and ``write``, may result in slower performance. -The ``fread`` and ``fwrite`` functions are designed for portability rather than speed, introducing some overhead due to their buffered nature. Check the example :example:`storage/fatfsgen` to see how to use these two functions. +The ``fread`` and ``fwrite`` functions are designed for portability rather than speed, introducing some overhead due to their buffered nature. Check the example :example:`storage/fatfs/getting_started` to see how to use these two functions. -In contrast, the ``read`` and ``write`` functions are standard POSIX APIs that can be used directly when working with FatFs through VFS, with ESP-IDF handling the underlying implementation. Check the example :example:`storage/perf_benchmark` to see how to use the two functions. +In contrast, the ``read`` and ``write`` functions are standard POSIX APIs that can be used directly when working with FatFs through VFS, with ESP-IDF handling the underlying implementation. Check the example :example:`storage/fatfs/fs_operations` to see how to use the two functions. Additional tips are provided below, and further details can be found in :doc:`/api-reference/storage/fatfs`. diff --git a/docs/en/api-guides/startup.rst b/docs/en/api-guides/startup.rst index 91e1c425c0ee..47555130a9f7 100644 --- a/docs/en/api-guides/startup.rst +++ b/docs/en/api-guides/startup.rst @@ -9,7 +9,7 @@ The high level view of startup process is as follows: .. list:: - 1. :ref:`first-stage-bootloader` in ROM loads second-stage bootloader image to RAM (IRAM & DRAM) from flash offset {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH}. + 1. :ref:`first-stage-bootloader` loads the second stage bootloader image to RAM (IRAM & DRAM) from flash offset {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH}. 2. :ref:`second-stage-bootloader` loads partition table and main app image from flash. Main app incorporates both RAM segments and read-only segments mapped via flash cache. @@ -21,8 +21,8 @@ This process is explained in detail in the following sections. .. _first-stage-bootloader: -First Stage Bootloader -^^^^^^^^^^^^^^^^^^^^^^ +First stage (ROM) bootloader +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES @@ -71,7 +71,7 @@ Second Stage Bootloader In ESP-IDF, the binary image which resides at offset {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} in flash is the second stage bootloader. Second stage bootloader source code is available in :idf:`components/bootloader` directory of ESP-IDF. Second stage bootloader is used in ESP-IDF to add flexibility to flash layout (using partition tables), and allow for various flows associated with flash encryption, secure boot, and over-the-air updates (OTA) to take place. -When the first stage bootloader is finished checking and loading the second stage bootloader, it jumps to the second stage bootloader entry point found in the binary image header. +When the first stage (ROM) bootloader is finished checking and loading the second stage bootloader, it jumps to the second stage bootloader entry point found in the binary image header. Second stage bootloader reads the partition table found by default at offset {IDF_TARGET_CONFIG_PARTITION_TABLE_OFFSET} (:ref:`configurable value `). See :doc:`partition tables ` documentation for more information. The bootloader finds factory and OTA app partitions. If OTA app partitions are found in the partition table, the bootloader consults the ``otadata`` partition to determine which one should be booted. See :doc:`/api-reference/system/ota` for more information. diff --git a/docs/en/api-guides/tools/idf-monitor.rst b/docs/en/api-guides/tools/idf-monitor.rst index 5c4408209ded..9505a76210df 100644 --- a/docs/en/api-guides/tools/idf-monitor.rst +++ b/docs/en/api-guides/tools/idf-monitor.rst @@ -252,63 +252,7 @@ Custom Reset Sequence For more advanced users or specific use cases, IDF Monitor supports the configuration of a custom reset sequence using :ref:`configuration-file`. This is particularly useful in extreme edge cases where the default sequence may not suffice. -The sequence is defined with a string in the following format: - -- Consists of individual commands divided by ``|`` (e.g. ``R0|D1|W0.5``). -- Commands (e.g. ``R0``) are defined by a code (``R``) and an argument (``0``). - -.. list-table:: - :header-rows: 1 - :widths: 15 50 35 - :align: center - - * - Code - - Action - - Argument - * - D - - Set DTR control line - - ``1``/``0`` - * - R - - Set RTS control line - - ``1``/``0`` - * - U - - Set DTR and RTS control lines at the same time (Unix-like systems only) - - ``0,0``/``0,1``/``1,0``/``1,1`` - * - W - - Wait for ``N`` seconds (where ``N`` is a float) - - N - -Example: - -.. code-block:: ini - - [esp-idf-monitor] - custom_reset_sequence = U0,1|W0.1|D1|R0|W0.5|D0 - -Refer to `custom reset sequence`_ from Esptool documentation for further details. Please note that ``custom_reset_sequence`` is the only used value from the Esptool configuration, and others will be ignored in IDF Monitor. - -Share Configuration Across Tools --------------------------------- - -The configuration for the custom reset sequence can be specified in a shared configuration file between IDF Monitor and Esptool. In this case, your configuration file name should be either ``setup.cfg`` or ``tox.ini`` so it would be recognized by both tools. - -Example of a shared configuration file: - -.. code-block:: ini - - [esp-idf-monitor] - menu_key = T - skip_menu_key = True - - [esptool] - custom_reset_sequence = U0,1|W0.1|D1|R0|W0.5|D0 - -.. note:: - - When using the ``custom_reset_sequence`` parameter in both the ``[esp-idf-monitor]`` section and the ``[esptool]`` section, the configuration from the ``[esp-idf-monitor]`` section will take precedence in IDF Monitor. Any conflicting configuration in the ``[esptool]`` section will be ignored. - - This precedence rule also applies when the configuration is spread across multiple files. The global esp-idf-monitor configuration will take precedence over the local esptool configuration. - +If you would like to use a custom reset sequence, take a look at the `IDF Monitor documentation`_ for more details. Launching GDB with GDBStub ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -397,107 +341,9 @@ The options ``--print_filter="light_driver:D esp_image:N boot:N cpu_start:N vfs: Configuration File ================== -``esp-idf-monitor`` is using `C0 control codes`_ to interact with the console. Characters from the config file are converted to their C0 control codes. Available characters include the English alphabet (A-Z) and special symbols: ``[``, ``]``, ``\``, ``^``, ``_``. - -.. warning:: +``esp-idf-monitor`` offers option to change its default behavior with configuration file. This file can be used for example to set custom key bindings, or set a custom reset sequence for resetting the chip into bootloader mode. - Please note that some characters may not work on all platforms or can be already reserved as a shortcut for something else. Use this feature with caution! - - -File Location -~~~~~~~~~~~~~ - -The default name for a configuration file is ``esp-idf-monitor.cfg``. First, the same directory ``esp-idf-monitor`` is being run if is inspected. - -If a configuration file is not found here, the current user's OS configuration directory is inspected next: - - - Linux: ``/home//.config/esp-idf-monitor/`` - - MacOS ``/Users//.config/esp-idf-monitor/`` - - Windows: ``c:\Users\\AppData\Local\esp-idf-monitor\`` - -If a configuration file is still not found, the last inspected location is the home directory: - - - Linux: ``/home//`` - - MacOS ``/Users//`` - - Windows: ``c:\Users\\`` - -On Windows, the home directory can be set with the ``HOME`` or ``USERPROFILE`` environment variables. Therefore, the Windows configuration directory location also depends on these. - -A different location for the configuration file can be specified with the ``ESP_IDF_MONITOR_CFGFILE`` environment variable, e.g., ``ESP_IDF_MONITOR_CFGFILE = ~/custom_config.cfg``. This overrides the search priorities described above. - -``esp-idf-monitor`` will read settings from other usual configuration files if no other configuration file is used. It automatically reads from ``setup.cfg`` or ``tox.ini`` if they exist. - -Configuration Options -~~~~~~~~~~~~~~~~~~~~~ - -Below is a table listing the available configuration options: - -.. list-table:: - :header-rows: 1 - :widths: 30 50 20 - :align: center - - * - Option Name - - Description - - Default Value - * - menu_key - - Key to access the main menu. - - ``T`` - * - exit_key - - Key to exit the monitor. - - ``]`` - * - chip_reset_key - - Key to initiate a chip reset. - - ``R`` - * - recompile_upload_key - - Key to recompile and upload. - - ``F`` - * - recompile_upload_app_key - - Key to recompile and upload just the application. - - ``A`` - * - toggle_output_key - - Key to toggle the output display. - - ``Y`` - * - toggle_log_key - - Key to toggle the logging feature. - - ``L`` - * - toggle_timestamp_key - - Key to toggle timestamp display. - - ``I`` - * - chip_reset_bootloader_key - - Key to reset the chip to bootloader mode. - - ``P`` - * - exit_menu_key - - Key to exit the monitor from the menu. - - ``X`` - * - skip_menu_key - - Pressing the menu key can be skipped for menu commands. - - ``False`` - * - custom_reset_sequence - - Custom reset sequence for resetting into the bootloader. - - N/A - - -Syntax -~~~~~~ - -The configuration file is in .ini file format: it must be introduced by an ``[esp-idf-monitor]`` header to be recognized as valid. This section then contains name = value entries. Lines beginning with ``#`` or ``;`` are ignored as comments. - -.. code-block:: ini - - # esp-idf-monitor.cfg file to configure internal settings of esp-idf-monitor - [esp-idf-monitor] - menu_key = T - exit_key = ] - chip_reset_key = R - recompile_upload_key = F - recompile_upload_app_key = A - toggle_output_key = Y - toggle_log_key = L - toggle_timestamp_key = I - chip_reset_bootloader_key = P - exit_menu_key = X - skip_menu_key = False +For more details on the configuration file, see the `IDF Monitor documentation`_. Known Issues with IDF Monitor @@ -505,10 +351,6 @@ Known Issues with IDF Monitor If you encounter any issues while using IDF Monitor, check our `GitHub repository `_ for a list of known issues and their current status. If you come across a problem that hasn't been documented yet, we encourage you to create a new issue report. -.. _addr2line: https://sourceware.org/binutils/docs/binutils/addr2line.html .. _esp-idf-monitor: https://github.com/espressif/esp-idf-monitor +.. _IDF Monitor documentation: https://github.com/espressif/esp-idf-monitor/blob/v1.5.0/README.md#documentation .. _gdb: https://sourceware.org/gdb/download/onlinedocs/ -.. _pySerial: https://github.com/pyserial/pyserial -.. _miniterm: https://pyserial.readthedocs.org/en/latest/tools.html#module-serial.tools.miniterm -.. _C0 control codes: https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C0_controls -.. _custom reset sequence: https://docs.espressif.com/projects/esptool/en/latest/{IDF_TARGET_PATH_NAME}/esptool/configuration-file.html#custom-reset-sequence diff --git a/docs/en/api-guides/tools/index.rst b/docs/en/api-guides/tools/index.rst index 1b25030209ff..f5d1801ab77c 100644 --- a/docs/en/api-guides/tools/index.rst +++ b/docs/en/api-guides/tools/index.rst @@ -12,4 +12,4 @@ Tools idf-clang-tidy idf-tools idf-size - :esp32 or esp32c3: qemu + :TARGET_SUPPORT_QEMU: qemu diff --git a/docs/en/api-guides/tools/qemu.rst b/docs/en/api-guides/tools/qemu.rst index 697f45ca7cd4..f88766a4a3c7 100644 --- a/docs/en/api-guides/tools/qemu.rst +++ b/docs/en/api-guides/tools/qemu.rst @@ -1,6 +1,8 @@ QEMU Emulator ============= +{IDF_TARGET_CRYPT_CNT:default="SPI_BOOT_CRYPT_CNT",esp32="FLASH_CRYPT_CNT"} + :link_to_translation:`zh_CN:[中文]` Espressif maintains a `fork `_ of the QEMU emulator with support for {IDF_TARGET_NAME}. This fork implements emulation of the CPU, memory, and several peripherals of {IDF_TARGET_NAME}. For more information about QEMU for {IDF_TARGET_NAME}, see the `QEMU README documentation `_. @@ -119,13 +121,52 @@ QEMU supports emulation of eFuses. This can be a convenient way to test security You can use :doc:`idf.py` eFuse-related commands to program eFuses. When you run any of these commands together with ``qemu`` command, the eFuses are programmed in QEMU, and the ``qemu_efuse.bin`` file is updated. For example, +.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES + + .. code-block:: console + + idf.py qemu efuse-burn {IDF_TARGET_CRYPT_CNT} 1 + idf.py qemu efuse-burn-key flash_encryption my_flash_encryption_key.bin + +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES + + .. code-block:: console + + idf.py qemu efuse-burn {IDF_TARGET_CRYPT_CNT} 1 + idf.py qemu efuse-burn-key BLOCK my_flash_encryption_key.bin KEYPURPOSE + + For details regarding the ``BLOCK`` and ``KEYPURPOSE``, please refer to the :doc:`../../security/flash-encryption` guide. + +To dump the eFuse summary, please use the following command: + .. code-block:: console - idf.py qemu efuse-burn FLASH_CRYPT_CNT 1 + idf.py qemu efuse-summary By default, the values of eFuses are read from and written to the ``qemu_efuse.bin`` file in the build directory. You can specify a different file using the ``--efuse-file`` option. For example, .. code-block:: console - idf.py qemu --efuse-file my_efuse.bin efuse-burn FLASH_CRYPT_CNT 1 + idf.py qemu --efuse-file my_efuse.bin efuse-burn {IDF_TARGET_CRYPT_CNT} 1 idf.py qemu --efuse-file my_efuse.bin monitor + +Specifying Flash Image +~~~~~~~~~~~~~~~~~~~~~~ + +By default, QEMU uses the ``qemu_flash.bin`` file in the build directory as the flash image. This file is generated based on the information available about the project from the ``flash_args`` file present in the build directory. If you want to use a different flash image file, you can specify it using the ``--flash-file`` option. For example, + +.. code-block:: console + + idf.py qemu --flash-file my_flash.bin monitor + + +The provided flash image must meet the following requirements for proper emulation: + +- The flash file size matches the value specified by :ref:`CONFIG_ESPTOOLPY_FLASHSIZE` in the project configuration. +- The flash file includes all required binaries, such as the bootloader, partition table, and application firmware, placed at their respective memory offsets. + + +Emulating Secure Boot +~~~~~~~~~~~~~~~~~~~~~ + +QEMU supports emulation of secure boot v2 scheme. Please keep :ref:`CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT` enabled to include signed bootloader image into the QEMU image artifact. diff --git a/docs/en/api-guides/wifi-expansion.rst b/docs/en/api-guides/wifi-expansion.rst new file mode 100644 index 000000000000..8c11b7704ba5 --- /dev/null +++ b/docs/en/api-guides/wifi-expansion.rst @@ -0,0 +1,27 @@ +Wi-Fi Expansion +=============== + +:link_to_translation:`zh_CN:[中文]` + +.. only:: not SOC_WIFI_SUPPORTED + + {IDF_TARGET_NAME} does not support Wi-Fi functionality natively, but it is possible to use the same Wi-Fi API and features using Wi-Fi expansion. + +.. only:: SOC_WIFI_SUPPORTED + + {IDF_TARGET_NAME} does support Wi-Fi functionality natively, please refer to :doc:`wifi` documentation. Even though Wi-Fi is supported on {IDF_TARGET_NAME}, it is possible to expand it and use another instance of Wi-Fi expansion interfaces using esp_wifi_remote `_ component. + + +The principle of Wi-Fi Expansion operation is to add another ESP32 series, Wi-Fi capable, target connected to the {IDF_TARGET_NAME} in a pre-defined way. Your project could then include the `esp_wifi_remote `_ component using: + +.. code:: bash + + idf.py add-dependency esp_wifi_remote + + +Please follow the instructions described in the `esp_wifi_remote documentation `_. + + +.. only:: not SOC_WIFI_SUPPORTED + + To explore the Wi-Fi Expansion functionality on {IDF_TARGET_NAME}, you can get started with this example: :idf_file:`examples/protocols/mqtt/tcp/README.md` and choose Wi-Fi connection in the project configuration menu. diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst index 6c87032e0e94..f2a0deb5e918 100644 --- a/docs/en/api-guides/wifi.rst +++ b/docs/en/api-guides/wifi.rst @@ -839,7 +839,7 @@ Association Phase +++++++++++++++++++++ - s3.1: The association request is sent and the association timer is enabled. - - s3.2: If the association response is not received before the association timer times out, `WIFI_EVENT_STA_DISCONNECTED`_ will arise and the reason code will be ``WIFI_REASON_ASSOC_EXPIRE``. Refer to `Wi-Fi Reason Code`_. + - s3.2: If the association response is not received before the association timer times out, `WIFI_EVENT_STA_DISCONNECTED`_ will arise and the reason code will be ``WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY``. Refer to `Wi-Fi Reason Code`_. - s3.3: The association response is received and the association timer is stopped. - s3.4: The AP rejects the association in the response and `WIFI_EVENT_STA_DISCONNECTED`_ arises, while the reason code is the one specified in the association response. Refer to `Wi-Fi Reason Code`_. @@ -904,19 +904,15 @@ Following reason codes are renamed to their shorter form to wrap the table in pa For the ESP station, this reason is reported when: - it is received from the AP. - * - ASSOC_EXPIRE + * - DISASSOC_DUE_TO_INACTIVITY - 4 - Disassociated due to inactivity. For the ESP station, this reason is reported when: + - assoc is timed out. - it is received from the AP. - For the ESP AP, this reason is reported when: - - - the AP has not received any packets from the station in the past five minutes. - - the AP is stopped by calling :cpp:func:`esp_wifi_stop()`. - - the station is de-authed by calling :cpp:func:`esp_wifi_deauth_sta()`. * - ASSOC_TOOMANY - 5 - Disassociated, because the AP is unable to handle all currently associated STAs at the same time. @@ -928,7 +924,7 @@ Following reason codes are renamed to their shorter form to wrap the table in pa For the ESP AP, this reason is reported when: - the stations associated with the AP reach the maximum number that the AP can support. - * - NOT_AUTHED + * - CLASS2_FRAME_FROM_NONAUTH_STA - 6 - Class-2 frame received from a non-authenticated STA. @@ -939,7 +935,7 @@ Following reason codes are renamed to their shorter form to wrap the table in pa For the ESP AP, this reason is reported when: - the AP receives a packet with data from a non-authenticated station. - * - NOT_ASSOCED + * - CLASS3_FRAME_FROM_NONASSOC_STA - 7 - Class-3 frame received from a non-associated STA. @@ -1166,7 +1162,7 @@ Following reason codes are renamed to their shorter form to wrap the table in pa - Espressif-specific Wi-Fi reason code: the authentication fails, but not because of a timeout. * - ASSOC_FAIL - 203 - - Espressif-specific Wi-Fi reason code: the association fails, but not because of ASSOC_EXPIRE or ASSOC_TOOMANY. + - Espressif-specific Wi-Fi reason code: the association fails, but not because of DISASSOC_DUE_TO_INACTIVITY or ASSOC_TOOMANY. * - HANDSHAKE_TIMEOUT - 204 - Espressif-specific Wi-Fi reason code: the handshake fails for the same reason as that in WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT. diff --git a/docs/en/api-reference/network/esp_eth.rst b/docs/en/api-reference/network/esp_eth.rst index bf22ff5b8c39..0b1ee221755a 100644 --- a/docs/en/api-reference/network/esp_eth.rst +++ b/docs/en/api-reference/network/esp_eth.rst @@ -269,6 +269,10 @@ Configuration for PHY is described in :cpp:class:`eth_phy_config_t`, including: * :cpp:member:`eth_phy_config_t::reset_gpio_num`: if your board also connects the PHY reset pin to one of the GPIO, then set it here. Otherwise, set this field to ``-1``. + * :cpp:member:`eth_phy_config_t::hw_reset_assert_time_us`: Time the PHY reset pin is asserted in usec. Set this field to ``0`` to use chip specific default timing. + + * :cpp:member:`eth_phy_config_t::post_hw_reset_delay_ms`: Time to wait after the PHY hardware reset is done in msec. Set this field to ``0`` to use chip specific default timing. Set this field to ``-1`` to not wait after the PHY hardware reset. + ESP-IDF provides a default configuration for MAC and PHY in macro :c:macro:`ETH_MAC_DEFAULT_CONFIG` and :c:macro:`ETH_PHY_DEFAULT_CONFIG`. @@ -288,19 +292,23 @@ The Ethernet driver is implemented in an Object-Oriented style. Any operation on eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default common MAC configuration eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); // apply default vendor-specific MAC configuration - esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; // alter the GPIO used for MDC signal - esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; // alter the GPIO used for MDIO signal + esp32_emac_config.smi_gpio.mdc_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; // alter the GPIO used for MDC signal + esp32_emac_config.smi_gpio.mdio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; // alter the GPIO used for MDIO signal esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // create MAC instance eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; // alter the PHY address according to your board design phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO; // alter the GPIO used for PHY reset - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance - // ESP-IDF officially supports several different Ethernet PHY chip driver + esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config); // create generic PHY instance + // ESP-IDF officially supports several different specific Ethernet PHY chip driver + // esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config); // esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); // esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config); + .. note:: + Any Ethernet PHY chip compliant with IEEE 802.3 can be used when creating new PHY instance with :cpp:func:`esp_eth_phy_new_generic`. However, while basic functionality should always work, some specific features might be limited, even if the PHY meets IEEE 802.3 standard. A typical example is loopback functionality, where certain PHYs may require setting a specific speed mode to operate correctly. If this is the concern and you need PHY driver specifically tailored to your chip needs, use drivers for PHY chips the ESP-IDF already officially supports or consult with :ref:`Custom PHY Driver ` section to create a new custom driver. + Optional Runtime MAC Clock Configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -557,10 +565,12 @@ Application Examples Advanced Topics --------------- +.. _custom-phy-driver: + Custom PHY Driver ^^^^^^^^^^^^^^^^^ -There are multiple PHY manufacturers with wide portfolios of chips available. The ESP-IDF already supports several PHY chips however one can easily get to a point where none of them satisfies the user's actual needs due to price, features, stock availability, etc. +There are multiple PHY manufacturers with wide portfolios of chips available. The ESP-IDF supports ``Generic PHY`` and also several specific PHY chips however one can easily get to a point where none of them satisfies the user's actual needs due to price, features, stock availability, etc. Luckily, a management interface between EMAC and PHY is standardized by IEEE 802.3 in Section 22.2.4 Management Functions. It defines provisions of the so-called "MII Management Interface" to control the PHY and gather status from the PHY. A set of management registers is defined to control chip behavior, link properties, auto-negotiation configuration, etc. This basic management functionality is addressed by :component_file:`esp_eth/src/phy/esp_eth_phy_802_3.c` in ESP-IDF and so it makes the creation of a new custom PHY chip driver quite a simple task. diff --git a/docs/en/api-reference/network/esp_netif.rst b/docs/en/api-reference/network/esp_netif.rst index 70faff41a154..e9ffb448beaa 100644 --- a/docs/en/api-reference/network/esp_netif.rst +++ b/docs/en/api-reference/network/esp_netif.rst @@ -82,20 +82,19 @@ Common Network Interfaces As the initialization of network interfaces could be quite complex, ESP-NETIF provides some convenient methods of creating the most common ones, such as Wi-Fi and Ethernet. -Please refer to the following example to understand the initialization process of the default interface: +Please refer to the following examples to understand the initialization process of the default interface: +.. list:: -.. only:: SOC_WIFI_SUPPORTED - - - Wi-Fi Station: :example_file:`wifi/getting_started/station/main/station_example_main.c` + :SOC_WIFI_SUPPORTED: - :example:`wifi/getting_started/station` demonstrates how to use the station functionality to connect {IDF_TARGET_NAME} to an AP. -- Ethernet: :example_file:`ethernet/basic/main/ethernet_example_main.c` + :CONFIG_ESP_WIFI_SOFTAP_SUPPORT: - :example:`wifi/getting_started/softAP` demonstrates how to use the SoftAP functionality to configure {IDF_TARGET_NAME} as an AP. -- L2 TAP: :example_file:`protocols/l2tap/main/l2tap_main.c` + - :example:`ethernet/basic` demonstrates how to use the Ethernet driver, attach it to `esp_netif`, and obtain an IP address that can be pinged. -.. only:: CONFIG_ESP_WIFI_SOFTAP_SUPPORT + - :example:`protocols/l2tap` demonstrates how to use the ESP-NETIF L2 TAP interface to access the Data Link Layer for receiving and transmitting frames, implement non-IP protocols, and echo Ethernet frames with specific EthTypes. - - Wi-Fi Access Point: :example_file:`wifi/getting_started/softAP/main/softap_example_main.c` + - :example:`protocols/static_ip` demonstrates how to configure Wi-Fi as a station, including setting up a static IP, netmask, gateway and DNS server. .. only:: SOC_WIFI_SUPPORTED diff --git a/docs/en/api-reference/network/esp_smartconfig.rst b/docs/en/api-reference/network/esp_smartconfig.rst index d94091e81909..f7159fc64108 100644 --- a/docs/en/api-reference/network/esp_smartconfig.rst +++ b/docs/en/api-reference/network/esp_smartconfig.rst @@ -3,10 +3,17 @@ SmartConfig :link_to_translation:`zh_CN:[中文]` +Introduction +------------ + The SmartConfig\ :sup:`TM` is a provisioning technology developed by TI to connect a new Wi-Fi device to a Wi-Fi network. It uses a mobile application to broadcast the network credentials from a smartphone, or a tablet, to an un-provisioned Wi-Fi device. The advantage of this technology is that the device does not need to directly know SSID or password of an Access Point (AP). This information is provided using the smartphone. This is particularly important to headless device and systems, due to their lack of a user interface. +Currently, {IDF_TARGET_NAME} support three types of SmartConfig: Airkiss, ESPTouch, and ESPTouch v2. ESPTouch v2 has been supported since SmartConfig v3.0 (the version of SmartConfig can be get from :cpp:func:`esp_smartconfig_get_version()`), and it employs a completely different algorithm compared to ESPTouch, resulting in faster setup times. Additionally, ESPTouch v2 introduces AES encryption and custom data fields. + +Starting from SmartConfig v3.0.2, ESPTouch v2 introduces support for random IV in AES encryption. On the application side, when the option for random IV is disabled, the default IV is set to 0, maintaining consistency with previous versions. When the random IV option is enabled, the IV will be a random value. It is important to note that when AES encryption is enabled with a random IV, the provision time will be extended due to the need of transmitting the IV to the provisioning device. On the provisioning device side, the device will identify whether the random IV for AES is enabled based on the flag in the provisioning packet. + If you are looking for other options to provision your {IDF_TARGET_NAME} devices, check :doc:`../provisioning/index`. diff --git a/docs/en/api-reference/network/esp_wifi.rst b/docs/en/api-reference/network/esp_wifi.rst index 2fc5e14890b4..5b119e3c8dea 100644 --- a/docs/en/api-reference/network/esp_wifi.rst +++ b/docs/en/api-reference/network/esp_wifi.rst @@ -28,6 +28,7 @@ API Reference .. include-build-file:: inc/esp_wifi.inc .. include-build-file:: inc/esp_wifi_types.inc +.. include-build-file:: inc/esp_wifi_types_generic.inc .. include-build-file:: inc/esp_eap_client.inc .. include-build-file:: inc/esp_wps.inc .. include-build-file:: inc/esp_rrm.inc diff --git a/docs/en/api-reference/peripherals/adc_continuous.rst b/docs/en/api-reference/peripherals/adc_continuous.rst index 32dc9b5c7bf1..853f82314d35 100644 --- a/docs/en/api-reference/peripherals/adc_continuous.rst +++ b/docs/en/api-reference/peripherals/adc_continuous.rst @@ -290,39 +290,19 @@ To do further calibration to convert the ADC raw result to voltage in mV, please Hardware Limitations ^^^^^^^^^^^^^^^^^^^^ -- A specific ADC unit can only work under one operating mode at any one time, either continuous mode or one-shot mode. :cpp:func:`adc_continuous_start` has provided the protection. - -- Random Number Generator (RNG) uses ADC as an input source. When ADC continuous mode driver works, the random number generated from RNG will be less random. - -.. only:: esp32 or esp32s2 - - - ADC2 is also used by Wi-Fi. :cpp:func:`adc_continuous_start` has provided the protection between Wi-Fi driver and ADC continuous mode driver. - -.. only:: esp32 - - - ADC continuous mode driver uses I2S0 peripheral as hardware DMA FIFO. Therefore, if I2S0 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. - - - ESP32 DevKitC: GPIO 0 cannot be used due to external auto program circuits. - - - ESP-WROVER-KIT: GPIO 0, 2, 4, and 15 cannot be used due to external connections for different purposes. - -.. only:: esp32s2 - - - ADC continuous mode driver uses SPI3 peripheral as hardware DMA FIFO. Therefore, if SPI3 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. - -.. only:: esp32c3 - - - ADC2 DMA functionality is no longer supported to retrieve ADC conversion results due to hardware limitations, as unstable results have been observed. This issue can be found in `ESP32C3 Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. - -.. only:: esp32s3 - - - ADC2 DMA functionality is no longer supported to retrieve ADC conversion results due to hardware limitations, as unstable results have been observed. This issue can be found in `ESP32S3 Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. - - .. _adc-continuous-power-management: - -.. only:: not esp32s3 - - .. _adc-continuous-power-management: +.. list:: + + - A specific ADC unit can only work under one operating mode at any one time, either continuous mode or one-shot mode. :cpp:func:`adc_continuous_start` has provided the protection. + - Random Number Generator (RNG) uses ADC as an input source. When ADC continuous mode driver works, the random number generated from RNG will be less random. + :esp32 or esp32s2: - ADC2 is also used by Wi-Fi. :cpp:func:`adc_continuous_start` has provided the protection between Wi-Fi driver and ADC continuous mode driver. + :esp32: - ADC continuous mode driver uses I2S0 peripheral as hardware DMA FIFO. Therefore, if I2S0 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. + :esp32: - ESP32 DevKitC: GPIO 0 cannot be used due to external auto program circuits. + :esp32: - ESP-WROVER-KIT: GPIO 0, 2, 4, and 15 cannot be used due to external connections for different purposes. + :esp32s2: - ADC continuous mode driver uses SPI3 peripheral as hardware DMA FIFO. Therefore, if SPI3 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. + :esp32c3: - ADC2 DMA functionality is no longer supported to retrieve ADC conversion results due to hardware limitations, as unstable results have been observed. This issue can be found in `ESP32C3 Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. + :esp32s3: - ADC2 DMA functionality is no longer supported to retrieve ADC conversion results due to hardware limitations, as unstable results have been observed. This issue can be found in `ESP32S3 Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. + +.. _adc-continuous-power-management: Power Management ^^^^^^^^^^^^^^^^ diff --git a/docs/en/api-reference/peripherals/adc_oneshot.rst b/docs/en/api-reference/peripherals/adc_oneshot.rst index c7dfec41d001..24fee32be510 100644 --- a/docs/en/api-reference/peripherals/adc_oneshot.rst +++ b/docs/en/api-reference/peripherals/adc_oneshot.rst @@ -3,20 +3,17 @@ Analog to Digital Converter (ADC) Oneshot Mode Driver :link_to_translation:`zh_CN:[中文]` -{IDF_TARGET_ADC_NUM:default="two", esp32c2="one", esp32c6="one", esp32h2="one", esp32c5="one"} - Introduction ------------ The Analog to Digital Converter is integrated on the chip and is capable of measuring analog signals from specific analog IO pins. -{IDF_TARGET_NAME} has {IDF_TARGET_ADC_NUM} ADC unit(s), which can be used in scenario(s) like: - -- Generate one-shot ADC conversion result +{IDF_TARGET_NAME} has {SOC_ADC_PERIPH_NUM} ADC unit(s), which can be used in scenario(s) like: -.. only:: SOC_ADC_DMA_SUPPORTED +.. list:: - - Generate continuous ADC conversion results + - Generate one-shot ADC conversion result + :SOC_ADC_DMA_SUPPORTED: - Generate continuous ADC conversion results This guide introduces ADC oneshot mode conversion. @@ -164,31 +161,16 @@ Read Raw Result Hardware Limitations ^^^^^^^^^^^^^^^^^^^^ -- Random Number Generator (RNG) uses ADC as an input source. When ADC :cpp:func:`adc_oneshot_read` works, the random number generated from RNG will be less random. - -.. only:: SOC_ADC_DMA_SUPPORTED - - - A specific ADC unit can only work under one operating mode at any one time, either continuous mode or oneshot mode. :cpp:func:`adc_oneshot_read` has provided the protection. - -.. only:: esp32 or esp32s2 or esp32s3 - - - ADC2 is also used by Wi-Fi. :cpp:func:`adc_oneshot_read` has provided protection between the Wi-Fi driver and ADC oneshot mode driver. - -.. only:: esp32c3 - - - ADC2 oneshot mode is no longer supported, due to hardware limitations. The results are not stable. This issue can be found in `ESP32-C3 Series SoC Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3` to force use ADC2. - -.. only:: esp32 - - - ESP32-DevKitC: GPIO0 cannot be used in oneshot mode, because the DevKit has used it for auto-flash. - - - ESP-WROVER-KIT: GPIO 0, 2, 4, and 15 cannot be used due to external connections for different purposes. - - .. _adc-oneshot-power-management: +.. list:: -.. only:: not esp32 + - Random Number Generator (RNG) uses ADC as an input source. When ADC :cpp:func:`adc_oneshot_read` works, the random number generated from RNG will be less random. + :SOC_ADC_DMA_SUPPORTED: - A specific ADC unit can only work under one operating mode at any one time, either continuous mode or oneshot mode. :cpp:func:`adc_oneshot_read` has provided the protection. + :esp32 or esp32s2 or esp32s3: - ADC2 is also used by Wi-Fi. :cpp:func:`adc_oneshot_read` has provided protection between the Wi-Fi driver and ADC oneshot mode driver. + :esp32c3: - ADC2 oneshot mode is no longer supported, due to hardware limitations. The results are not stable. This issue can be found in `ESP32-C3 Series SoC Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3` to force use ADC2. + :esp32: - ESP32-DevKitC: GPIO0 cannot be used in oneshot mode, because the DevKit has used it for auto-flash. + :esp32: - ESP-WROVER-KIT: GPIO 0, 2, 4, and 15 cannot be used due to external connections for different purposes. - .. _adc-oneshot-power-management: +.. _adc-oneshot-power-management: Power Management ^^^^^^^^^^^^^^^^ diff --git a/docs/en/api-reference/peripherals/dac.rst b/docs/en/api-reference/peripherals/dac.rst index 4cb3eb12b3d0..06b5cc55f0ec 100644 --- a/docs/en/api-reference/peripherals/dac.rst +++ b/docs/en/api-reference/peripherals/dac.rst @@ -96,7 +96,7 @@ Power Management When the power management is enabled (i.e., :ref:`CONFIG_PM_ENABLE` is on), the system will adjust or stop the clock source of DAC before entering Light-sleep mode, thus potential influence to the DAC signals may lead to false data conversion. -When using DAC driver in continuous mode, it can prevent the system from changing or stopping the clock source in DMA or cosine mode by acquiring a power management lock. When the clock source is generated from APB, the lock type will be set to :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`. When the clock source is APLL (only in DMA mode), it will be set to :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`. Whenever the DAC is converting (i.e., DMA or cosine wave generator is working), the driver guarantees that the power management lock is acquired after calling :cpp:func:`dac_continuous_enable`. Likewise, the driver will release the lock when :cpp:func:`dac_continuous_disable` is called. +When using DAC driver in continuous mode, it can prevent the system from changing or stopping the clock source in DMA or cosine mode by acquiring a power management lock. The power lock type will be set to :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`. Whenever the DAC is converting (i.e., DMA or cosine wave generator is working), the driver guarantees that the power management lock is acquired after calling :cpp:func:`dac_continuous_enable`. Likewise, the driver will release the lock when :cpp:func:`dac_continuous_disable` is called. IRAM Safe ^^^^^^^^^ diff --git a/docs/en/api-reference/peripherals/dedic_gpio.rst b/docs/en/api-reference/peripherals/dedic_gpio.rst index 319586f4f66b..108abd73e182 100644 --- a/docs/en/api-reference/peripherals/dedic_gpio.rst +++ b/docs/en/api-reference/peripherals/dedic_gpio.rst @@ -16,32 +16,21 @@ A GPIO bundle is a group of GPIOs, which can be manipulated at the same time in .. note:: - Dedicated GPIO is more of a CPU peripheral, so it has a strong relationship with CPU core. It's highly recommended to install and operate GPIO bundle in a pin-to-core task. For example, if GPIOA is connected to CPU0, and the dedicated GPIO instruction is issued from CPU1, then it's impossible to control GPIOA. + Dedicated GPIO is more like a CPU peripheral, it has a strong relationship with CPU core. It's highly recommended to install and operate GPIO bundle in the same task, and the task should be pined to a CPU core. For example, if GPIO_A is connected to CPU_0, but the dedicated GPIO instruction is issued from CPU_1, then it's impossible to control GPIO_A. To install a GPIO bundle, one needs to call :cpp:func:`dedic_gpio_new_bundle` to allocate the software resources and connect the dedicated channels to user selected GPIOs. Configurations for a GPIO bundle are covered in :cpp:type:`dedic_gpio_bundle_config_t` structure: -- :cpp:member:`gpio_array`: An array that contains GPIO number. -- :cpp:member:`array_size`: Element number of :cpp:member:`gpio_array`. -- :cpp:member:`flags`: Extra flags to control the behavior of GPIO Bundle. +- :cpp:member:`dedic_gpio_bundle_config_t::gpio_array`: An array that contains GPIO number. +- :cpp:member:`dedic_gpio_bundle_config_t::array_size`: Element number of :cpp:member:`dedic_gpio_bundle_config_t::gpio_array`. +- :cpp:member:`dedic_gpio_bundle_config_t::in_en` and :cpp:member:`dedic_gpio_bundle_config_t::out_en` are used to configure whether to enable the input and output ability of the GPIO(s). +- :cpp:member:`dedic_gpio_bundle_config_t::in_invert` and :cpp:member:`dedic_gpio_bundle_config_t::out_invert` are used to configure whether to invert the GPIO signal. - - :cpp:member:`in_en` and :cpp:member:`out_en` are used to select whether to enable the input and output function (note, they can be enabled together). - - :cpp:member:`in_invert` and :cpp:member:`out_invert` are used to select whether to invert the GPIO signal. - -The following code shows how to install a output only GPIO bundle: +The following code shows how to install an output only GPIO bundle: .. highlight:: c :: - // configure GPIO - const int bundleA_gpios[] = {0, 1}; - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - }; - for (int i = 0; i < sizeof(bundleA_gpios) / sizeof(bundleA_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundleA_gpios[i]; - gpio_config(&io_conf); - } // Create bundleA, output only dedic_gpio_bundle_handle_t bundleA = NULL; dedic_gpio_bundle_config_t bundleA_config = { @@ -53,11 +42,7 @@ The following code shows how to install a output only GPIO bundle: }; ESP_ERROR_CHECK(dedic_gpio_new_bundle(&bundleA_config, &bundleA)); -To uninstall the GPIO bundle, one needs to call :cpp:func:`dedic_gpio_del_bundle`. - -.. note:: - - :cpp:func:`dedic_gpio_new_bundle` doesn't cover any GPIO pad configuration (e.g., pull up/down, drive ability, output/input enable), so before installing a dedicated GPIO bundle, you have to configure the GPIO separately using GPIO driver API (e.g., :cpp:func:`gpio_config`). For more information about GPIO driver, please refer to :doc:`GPIO API Reference `. +To uninstall the GPIO bundle, you should call :cpp:func:`dedic_gpio_del_bundle`. GPIO Bundle Operations @@ -92,13 +77,13 @@ For advanced users, they can always manipulate the GPIOs by writing assembly cod 3. Call CPU LL apis (e.g., `dedic_gpio_cpu_ll_write_mask`) or write assembly code with that mask 4. The fastest way of toggling IO is to use the dedicated "set/clear" instructions: - .. only:: esp32s2 or esp32s3 + .. only:: CONFIG_IDF_TARGET_ARCH_XTENSA - Set bits of GPIO: ``set_bit_gpio_out imm[7:0]`` - Clear bits of GPIO: ``clr_bit_gpio_out imm[7:0]`` - Note: Immediate value width depends on the number of dedicated GPIO channels - .. only:: esp32c2 or esp32c3 or esp32c6 or esp32h2 + .. only:: CONFIG_IDF_TARGET_ARCH_RISCV - Set bits of GPIO: ``csrrsi rd, csr, imm[4:0]`` - Clear bits of GPIO: ``csrrci rd, csr, imm[4:0]`` diff --git a/docs/en/api-reference/peripherals/etm.rst b/docs/en/api-reference/peripherals/etm.rst index b5a6a963dddd..a462082e83c7 100644 --- a/docs/en/api-reference/peripherals/etm.rst +++ b/docs/en/api-reference/peripherals/etm.rst @@ -32,6 +32,7 @@ The following sections of this document cover the typical steps to configure and - :ref:`etm-event` - describes how to allocate a new ETM event handle or fetch an existing handle from various peripherals. - :ref:`etm-task` - describes how to allocate a new ETM task handle or fetch an existing handle from various peripherals. - :ref:`etm-channel-control` - describes common ETM channel control functions. +- :ref:`etm-power-management` - describes the options and strategies provided by the driver in order to save power. - :ref:`etm-thread-safety` - lists which APIs are guaranteed to be thread-safe by the driver. - :ref:`etm-kconfig-options` - lists the supported Kconfig options that can be used to make a different effect on driver behavior. @@ -131,6 +132,17 @@ To check if the ETM channels are set with proper events and tasks, you can call The digital ID printed in the dump information is defined in the ``soc/soc_etm_source.h`` file. +.. _etm-power-management: + +Power Management +^^^^^^^^^^^^^^^^ + +When power management is enabled, i.e., :ref:`CONFIG_PM_ENABLE` is on, the system may adjust or disable the clock source, and power off the ETM peripheral before going to sleep. As a result, the existing connection between events and tasks will be lost, and the ETM channels can't work correctly after wake up. So by default, the driver will acquire a power management lock internally to forbid the system from powering off the ETM peripheral. + +.. only:: SOC_ETM_SUPPORT_SLEEP_RETENTION + + If you want to save more power, you can set :cpp:member:`esp_etm_channel_config_t::etm_chan_flags::allow_pd` to ``true``. Then ETM registers will be backed up before sleep and restored after wake up. Please note, enabling this option will increase the memory consumption for saving the register context. + .. _etm-thread-safety: Thread Safety diff --git a/docs/en/api-reference/peripherals/i2c.rst b/docs/en/api-reference/peripherals/i2c.rst index a592b2508641..ded149bb2e5a 100644 --- a/docs/en/api-reference/peripherals/i2c.rst +++ b/docs/en/api-reference/peripherals/i2c.rst @@ -44,7 +44,7 @@ I2C Clock Configuration - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_DEFAULT`: Default I2C source clock. :SOC_I2C_SUPPORT_XTAL: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_XTAL`: External crystal for I2C clock source. - :SOC_I2C_SUPPORT_RTC: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_RC_FAST`: Internal 20 MHz RC oscillator for I2C clock source. + :SOC_I2C_SUPPORT_RTC: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_RC_FAST`: Internal 20 MHz RC oscillator for I2C clock source. :SOC_I2C_SUPPORT_APB: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_APB`: APB clock as I2C clock source. :SOC_I2C_SUPPORT_REF_TICK: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_REF_TICK`: 1 MHZ clock. @@ -88,7 +88,7 @@ The I2C driver offers following services: Resource Allocation ^^^^^^^^^^^^^^^^^^^ -Both I2C master bus and I2C slave bus, when supported, are represented by :cpp:type:`i2c_bus_handle_t` in the driver. The available ports are managed in a resource pool that allocates a free port on request. +The I2C master bus is represented by :cpp:type:`i2c_master_bus_handle_t` in the driver. The available ports are managed in a resource pool that allocates a free port on request. Install I2C master bus and device ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -111,7 +111,7 @@ I2C master bus requires the configuration that specified by :cpp:type:`i2c_maste - :cpp:member:`i2c_master_bus_config_t::intr_priority` sets the priority of the interrupt. If set to ``0`` , then the driver will use a interrupt with low or medium priority (priority level may be one of 1, 2 or 3), otherwise use the priority indicated by :cpp:member:`i2c_master_bus_config_t::intr_priority`. Please use the number form (1, 2, 3) , not the bitmask form ((1<<1), (1<<2), (1<<3)). - :cpp:member:`i2c_master_bus_config_t::trans_queue_depth` sets the depth of internal transfer queue. Only valid in asynchronous transaction. - :cpp:member:`i2c_master_bus_config_t::enable_internal_pullup` enables internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. A suitable external pullup is recommended. - +- :cpp:member:`i2c_master_bus_config_t::allow_pd` configures if the driver allows the system to power down the peripheral in light sleep mode. Before entering sleep, the system will backup the I2C register context, which will be restored later when the system exit the sleep mode. Powering down the peripheral can save more power, but at the cost of more memory consumed to save the register context. It's a tradeoff between power consumption and memory consumption. This configuration option relies on specific hardware feature, if you enable it on an unsupported chip, you will see error message like ``not able to power down in light sleep``. If the configurations in :cpp:type:`i2c_master_bus_config_t` is specified, then :cpp:func:`i2c_new_master_bus` can be called to allocate and initialize an I2C master bus. This function will return an I2C bus handle if it runs correctly. Specifically, when there are no more I2C port available, this function will return :c:macro:`ESP_ERR_NOT_FOUND` error. @@ -166,7 +166,6 @@ When the I2C master handle has been initialized in one module (e.g. the audio mo ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); // Source File 2 - #include "esp_private/i2c_platform.h" #include "driver/i2c_master.h" i2c_master_bus_handle_t handle; ESP_ERROR_CHECK(i2c_master_get_bus_handle(0, &handle)); @@ -452,20 +451,20 @@ Simple example for writing data to FIFO: i2c_slave_config_t i2c_slv_config = { .addr_bit_len = I2C_ADDR_BIT_LEN_7, // 7-bit address .clk_source = I2C_CLK_SRC_DEFAULT, // set the clock source - .i2c_port = 0, // set I2C port number + .i2c_port = TEST_I2C_PORT, // set I2C port number .send_buf_depth = 256, // set TX buffer length - .scl_io_num = 2, // SCL GPIO number - .sda_io_num = 1, // SDA GPIO number + .scl_io_num = I2C_SLAVE_SCL_IO, // SCL GPIO number + .sda_io_num = I2C_SLAVE_SDA_IO, // SDA GPIO number .slave_addr = 0x58, // slave address }; - i2c_bus_handle_t i2c_bus_handle; - ESP_ERROR_CHECK(i2c_new_slave_device(&i2c_slv_config, &i2c_bus_handle)); + i2c_slave_dev_handle_t slave_handle; + ESP_ERROR_CHECK(i2c_new_slave_device(&i2c_slv_config, &slave_handle)); for (int i = 0; i < DATA_LENGTH; i++) { data_wr[i] = i; } - ESP_ERROR_CHECK(i2c_slave_transmit(i2c_bus_handle, data_wr, DATA_LENGTH, 10000)); + ESP_ERROR_CHECK(i2c_slave_transmit(slave_handle, data_wr, DATA_LENGTH, 10000)); I2C Slave Read ~~~~~~~~~~~~~~ diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index c1415498f3cc..ea3dd9467bd1 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -78,6 +78,10 @@ Clock Source - :cpp:enumerator:`i2s_clock_src_t::I2S_CLK_SRC_PLL_160M`: 160 MHz PLL clock. +.. only:: SOC_I2S_SUPPORTS_PLL_F120M + + - :cpp:enumerator:`i2s_clock_src_t::I2S_CLK_SRC_PLL_120M`: 120 MHz PLL clock. + .. only:: SOC_I2S_SUPPORTS_PLL_F96M - :cpp:enumerator:`i2s_clock_src_t::I2S_CLK_SRC_PLL_96M`: 96 MHz PLL clock. @@ -232,7 +236,16 @@ Power Management When the power management is enabled (i.e., :ref:`CONFIG_PM_ENABLE` is on), the system will adjust or stop the source clock of I2S before entering Light-sleep, thus potentially changing the I2S signals and leading to transmitting or receiving invalid data. -The I2S driver can prevent the system from changing or stopping the source clock by acquiring a power management lock. When the source clock is generated from APB, the lock type will be set to :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX` and when the source clock is APLL (if supported), it will be set to :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`. Whenever the user is reading or writing via I2S (i.e., calling :cpp:func:`i2s_channel_read` or :cpp:func:`i2s_channel_write`), the driver guarantees that the power management lock is acquired. Likewise, the driver releases the lock after the reading or writing finishes. +The I2S driver can prevent the system from changing or stopping the source clock by acquiring a power management lock. The power lock type will be set to :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`. Whenever the user is reading or writing via I2S (i.e., calling :cpp:func:`i2s_channel_read` or :cpp:func:`i2s_channel_write`), the driver guarantees that the power management lock is acquired. Likewise, the driver releases the lock after the reading or writing finishes. + +.. only:: SOC_I2S_SUPPORT_SLEEP_RETENTION + + Sleep Retention + """"""""""""""" + + {IDF_TARGET_NAME} supports to retain the I2S register context before entering **light sleep** and restore them after woke up. Which means you don't have to re-init the I2S driver even the peripheral is power off during the light sleep. + + This feature can be enabled by setting the flag :cpp:member:`i2s_chan_config_t::allow_pd`. It will allow the system to power down the I2S in light sleep, meanwhile save the I2S register context. It can help to save more power consumption with some extra cost of the memory. Finite State Machine ^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst index 0666f2c774b4..c44c288bfa05 100644 --- a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst @@ -60,7 +60,7 @@ MIPI DSI Interfaced LCD - :cpp:member:`esp_lcd_dpi_panel_config_t::virtual_channel` sets the virtual channel number to use. Like the DBI interface, we also need to set the virtual channel for the DPI interface. If you only have one LCD connected, you can set this to ``0``. - :cpp:member:`esp_lcd_dpi_panel_config_t::dpi_clk_src` sets the clock source for the DPI interface. The available clock sources are listed in :cpp:type:`mipi_dsi_dpi_clock_source_t`. - :cpp:member:`esp_lcd_dpi_panel_config_t::dpi_clock_freq_mhz` sets the DPI clock frequency in MHz. Higher pixel clock frequency results in higher refresh rate, but may cause flickering if the DMA bandwidth is not sufficient or the LCD controller chip does not support high pixel clock frequency. - - :cpp:member:`esp_lcd_dpi_panel_config_t::pixel_format` sets the pixel format of the pixel data. The available pixel formats are listed in :cpp:type:`lcd_color_rgb_pixel_format_t`. We usually use **RGB888** for MIPI LCD to get the best color depth. + - :cpp:member:`esp_lcd_dpi_panel_config_t::in_color_format` sets the pixel format of the input pixel data. The available pixel formats are listed in :cpp:type:`lcd_color_format_t`. We usually use **RGB888** for MIPI LCD to get the best color depth. - :cpp:member:`esp_lcd_dpi_panel_config_t::video_timing` sets the LCD panel specific timing parameters. All required parameters are listed in the :cpp:type:`esp_lcd_video_timing_t`, including the LCD resolution and blanking porches. Please fill them according to the datasheet of your LCD. - :cpp:member:`esp_lcd_dpi_panel_config_t::extra_dpi_panel_flags::use_dma2d` sets whether to use the 2D DMA peripheral to copy the user data to the frame buffer, asynchronously. @@ -71,7 +71,7 @@ MIPI DSI Interfaced LCD .virtual_channel = 0, .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = 1 * 1000, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888, + .in_color_format = LCD_COLOR_FMT_RGB888, .video_timing = { .h_size = EXAMPLE_MIPI_DSI_LCD_H_RES, .v_size = EXAMPLE_MIPI_DSI_LCD_V_RES, diff --git a/docs/en/api-reference/peripherals/lcd/rgb_lcd.rst b/docs/en/api-reference/peripherals/lcd/rgb_lcd.rst index 4d4d9ece4862..b099a090b97a 100644 --- a/docs/en/api-reference/peripherals/lcd/rgb_lcd.rst +++ b/docs/en/api-reference/peripherals/lcd/rgb_lcd.rst @@ -3,17 +3,17 @@ RGB Interfaced LCD :link_to_translation:`zh_CN:[中文]` -RGB LCD panel is allocated in one step: :cpp:func:`esp_lcd_new_rgb_panel`, with various configurations specified by :cpp:type:`esp_lcd_rgb_panel_config_t`. - - - :cpp:member:`esp_lcd_rgb_panel_config_t::clk_src` selects the clock source for the RGB LCD controller. The available clock sources are listed in :cpp:type:`lcd_clock_source_t`. - - :cpp:member:`esp_lcd_rgb_panel_config_t::data_width` sets number of data lines used by the RGB interface. Currently, the supported value can be 8 or 16. - - :cpp:member:`esp_lcd_rgb_panel_config_t::bits_per_pixel` sets the number of bits per pixel. This is different from :cpp:member:`esp_lcd_rgb_panel_config_t::data_width`. By default, if you set this field to 0, the driver will automatically adjust the bpp to the value set in :cpp:member:`esp_lcd_rgb_panel_config_t::data_width`. But in some cases, these two values must be different. For example, a serial RGB interfaced LCD only needs ``8`` data lines, but the color width can reach to ``RGB888``, i.e., the :cpp:member:`esp_lcd_rgb_panel_config_t::bits_per_pixel` should be set to ``24``. - - :cpp:member:`esp_lcd_rgb_panel_config_t::hsync_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::vsync_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::de_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::pclk_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::disp_gpio_num` and :cpp:member:`esp_lcd_rgb_panel_config_t::data_gpio_nums` are GPIO pins used by the RGB LCD controller. If any of them are not used, please set them to `-1`. - - :cpp:member:`esp_lcd_rgb_panel_config_t::dma_burst_size` sets the DMA transfer burst size. The value must be a power of 2. - - :cpp:member:`esp_lcd_rgb_panel_config_t::bounce_buffer_size_px` sets the size of bounce buffer. This is only necessary for a so-called "bounce buffer" mode. Please refer to :ref:`bounce_buffer_with_single_psram_frame_buffer` for more information. - - :cpp:member:`esp_lcd_rgb_panel_config_t::timings` sets the LCD panel specific timing parameters. All required parameters are listed in the :cpp:type:`esp_lcd_rgb_timing_t`, including the LCD resolution and blanking porches. Please fill them according to the datasheet of your LCD. - - :cpp:member:`esp_lcd_rgb_panel_config_t::fb_in_psram` sets whether to allocate the frame buffer from PSRAM or not. Please refer to :ref:`single_frame_buffer_in_psram` for more information. - - :cpp:member:`esp_lcd_rgb_panel_config_t::num_fbs` sets the number of frame buffers allocated by the driver. For backward compatibility, ``0`` means to allocate ``one`` frame buffer. Please use :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` if you do not want to allocate any frame buffer. +RGB LCD panel is created by :cpp:func:`esp_lcd_new_rgb_panel`, with various configurations specified in :cpp:type:`esp_lcd_rgb_panel_config_t`. + + - :cpp:member:`esp_lcd_rgb_panel_config_t::clk_src` selects the clock source of the RGB LCD controller. The available clock sources are listed in :cpp:type:`lcd_clock_source_t`. + - :cpp:member:`esp_lcd_rgb_panel_config_t::data_width` sets number of data lines consumed by the RGB interface. It can be 8/16/24. + - :cpp:member:`esp_lcd_rgb_panel_config_t::bits_per_pixel` specifies the number of bits per pixel. This differs from :cpp:member:`esp_lcd_rgb_panel_config_t::data_width`. By default, if this field is set to 0, the driver will automatically match the bpp to the value set in :cpp:member:`esp_lcd_rgb_panel_config_t::data_width`. However, in some scenarios, these values need to be different. For instance, a serial RGB interfaced LCD might only require ``8`` data lines, but the color depth could be ``RGB888``, meaning :cpp:member:`esp_lcd_rgb_panel_config_t::bits_per_pixel` should be set to ``24``. + - :cpp:member:`esp_lcd_rgb_panel_config_t::hsync_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::vsync_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::de_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::pclk_gpio_num`, :cpp:member:`esp_lcd_rgb_panel_config_t::disp_gpio_num` and :cpp:member:`esp_lcd_rgb_panel_config_t::data_gpio_nums` are GPIO pins consumed by the RGB LCD controller. If any of them are not used, please set them to ``-1``. + - :cpp:member:`esp_lcd_rgb_panel_config_t::dma_burst_size` specifies the size of the DMA transfer burst. Ensure this value is a power of 2. + - :cpp:member:`esp_lcd_rgb_panel_config_t::bounce_buffer_size_px` specifies the size of the bounce buffer. This is required only for the "bounce buffer" mode. For more details, see :ref:`bounce_buffer_with_single_psram_frame_buffer`. + - :cpp:member:`esp_lcd_rgb_panel_config_t::timings` specifies the timing parameters unique to the LCD panel. These parameters, detailed in :cpp:type:`esp_lcd_rgb_timing_t`, include the LCD resolution and blanking porches. Ensure they are set according to your LCD's datasheet. + - :cpp:member:`esp_lcd_rgb_panel_config_t::fb_in_psram` determines if the frame buffer should be allocated from PSRAM. For further details, see :ref:`single_frame_buffer_in_psram`. + - :cpp:member:`esp_lcd_rgb_panel_config_t::num_fbs` specifies how many frame buffers the driver should allocate. For backward compatibility, setting this to ``0`` will allocate a single frame buffer. If you don't want to allocate any frame buffer, use :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` instead. - :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` determines whether frame buffer will be allocated. When it is set, no frame buffer will be allocated. This is also called the :ref:`bounce_buffer_only` mode. RGB LCD Frame Buffer Operation Modes @@ -65,7 +65,7 @@ This is the default and simplest and you do not have to specify flags or bounce Single Frame Buffer in PSRAM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If you have PSRAM and want to store the frame buffer there rather than in the limited internal memory, the LCD peripheral will use EDMA to fetch frame data directly from the PSRAM, bypassing the internal cache. You can enable this feature by setting the :cpp:member:`esp_lcd_rgb_panel_config_t::fb_in_psram` to ``true``. The downside of this is that when both the CPU as well as EDMA need access to the PSRAM, the bandwidth will be **shared** between them, that is, EDMA gets half and the CPU gets the other half. If there are other peripherals using EDMA as well, with a high enough pixel clock, they may cause starvation of the LCD peripheral, resulting in display corruption. However, if the pixel clock is low enough to avoid this issue, it provides a solution with minimal CPU intervention. +If you have PSRAM and prefer to store the frame buffer there instead of using the limited internal memory, the LCD peripheral can utilize EDMA to fetch frame data directly from PSRAM, bypassing the internal cache. This can be enabled by setting :cpp:member:`esp_lcd_rgb_panel_config_t::fb_in_psram` to ``true``. The trade-off is that when both the CPU and EDMA need access to PSRAM, the bandwidth is **shared** between them, meaning EDMA and the CPU each get half. If other peripherals are also using EDMA, a high pixel clock might cause LCD peripheral starvation, leading to display corruption. However, with a sufficiently low pixel clock, this approach minimizes CPU intervention. .. only:: esp32s3 @@ -112,7 +112,7 @@ If you have PSRAM and want to store the frame buffer there rather than in the li Double Frame Buffer in PSRAM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To avoid tearing effect, using two screen sized frame buffers is the easiest approach. In this mode, the frame buffer can only be allocated from PSRAM, because of the limited internal memory. The frame buffer that the CPU write to and the frame buffer that the EDMA read from are guaranteed to be different and independent. The EDMA will only switch between the two frame buffers when the previous write operation is finished and the current frame has been sent to the LCD. The downside of this mode is that, you have to maintain the synchronization between the two frame buffers. +To prevent tearing effects, the simplest method is to use two screen-sized frame buffers. Given the limited internal memory, these buffers must be allocated from PSRAM. This ensures that the frame buffer being written to by the CPU and the one being read by the EDMA are always distinct and independent. The EDMA will only switch between the two buffers once the current write operation is complete and the frame has been fully transmitted to the LCD. The main drawback of this approach is the need to maintain synchronization between the two frame buffers. .. code:: c @@ -155,15 +155,15 @@ To avoid tearing effect, using two screen sized frame buffers is the easiest app Bounce Buffer with Single PSRAM Frame Buffer ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This mode allocates two so-called ``bounce buffers`` from the internal memory, and a main frame buffer that is still in PSRAM. This mode is selected by setting the :cpp:member:`esp_lcd_rgb_panel_config_t::fb_in_psram` flag and additionally specifying a non-zero :cpp:member:`esp_lcd_rgb_panel_config_t::bounce_buffer_size_px` value. The bounce buffers only need to be large enough to hold a few lines of display data, which is significantly less than the main frame buffer. The LCD peripheral uses DMA to read data from one of the bounce buffers, and meanwhile an interrupt routine uses the CPU DCache to copy data from the main PSRAM frame buffer into the other bounce buffer. Once the LCD peripheral has finished reading the bounce buffer, the two buffers change place and the CPU can fill the others. The advantage of this mode is that, you can achieve higher pixel clock frequency. As the bounce buffers are larger than the FIFOs in the EDMA path, this method is also more robust against short bandwidth spikes. The downside is a major increase in CPU use and that the LCD **CAN NOT** work if we disable the cache of the external memory, via e.g., OTA or NVS write to the main flash. +This mode allocates two "bounce buffers" from internal memory and a main frame buffer in PSRAM. To enable this mode, set the :cpp:member:`esp_lcd_rgb_panel_config_t::fb_in_psram` flag and specify a non-zero value for :cpp:member:`esp_lcd_rgb_panel_config_t::bounce_buffer_size_px`. The bounce buffers only need to hold a few lines of display data, which is much smaller than the main frame buffer. The LCD peripheral uses DMA to read data from one bounce buffer while an interrupt routine uses the CPU DCache to copy data from the main PSRAM frame buffer into the other bounce buffer. Once the LCD peripheral finishes reading from the bounce buffer, the buffers swap roles, allowing the CPU to fill the other one. The advantage of this mode is achieving a higher pixel clock frequency. Since the bounce buffers are larger than the FIFOs in the EDMA path, this method is also more robust against short bandwidth spikes. The downside is a significant increase in CPU usage, and the LCD **CANNOT** function if the external memory cache is disabled, such as during OTA or NVS writes to the main flash. .. note:: - It is highly recommended to turn on the "PSRAM XIP (Execute In Place)" feature in this mode by enabling the Kconfig options: :ref:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` and :ref:`CONFIG_SPIRAM_RODATA`, which allows the CPU to fetch instructions and readonly data from the PSRAM instead of the main flash. What is more, the external memory cache will not be disabled even if you attempt to write to the main flash through SPI 1. This makes it possible to display an OTA progress bar for your application. + For optimal performance in this mode, it is highly recommended to enable the "PSRAM XIP (Execute In Place)" feature by turning on the Kconfig option: :ref:`CONFIG_SPIRAM_XIP_FROM_PSRAM`. This allows the CPU to fetch instructions and read-only data directly from PSRAM instead of the main flash. Additionally, the external memory cache remains active even when writing to the main flash via SPI 1, making it feasible to display an OTA progress bar during your application updates. .. note:: - This mode still has another problem which is also caused by insufficient PSRAM bandwidth. For example, when your draw buffers are allocated from PSRAM, and their contents are copied into the internal frame buffer on CPU Core 1, on CPU Core 0, there is another memory copy happening in the DMA EOF ISR. In this situation, both CPUs are accessing the PSRAM by cache and sharing the bandwidth of the PSRAM. This increases the memory copy time that spent in the DMA EOF ISR significantly. The driver can not switch the bounce buffer in time, thus leading to a shift on the LCD screen. Although the driver can detect such a condition and perform a restart in the LCD's VSYNC interrupt handler, you still can see a flickering on the screen. + This mode also faces issues due to limited PSRAM bandwidth. For instance, if your draw buffers are in PSRAM and their contents are copied to the internal frame buffer by CPU Core 1, while CPU Core 0 is performing another memory copy in the DMA EOF ISR, both CPUs will be accessing PSRAM via cache, sharing its bandwidth. This significantly increases the memory copy time in the DMA EOF ISR, causing the driver to fail in switching the bounce buffer promptly, resulting in a screen shift. Although the driver can detect this condition and restart in the LCD's VSYNC interrupt handler, you may still notice flickering on the screen. .. code:: c @@ -201,8 +201,6 @@ This mode allocates two so-called ``bounce buffers`` from the internal memory, a }; ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle)); -Note that this mode also allows for a :cpp:member:`esp_lcd_rgb_panel_config_t::bb_invalidate_cache` flag to be set. Enabling this frees up the cache lines after they are used to read out the frame buffer data from PSRAM, but it may lead to slight corruption if the other core writes data to the frame buffer at the exact time the cache lines are freed up. (Technically, a write to the frame buffer can be ignored if it falls between the cache writeback and the cache invalidate calls.) - .. _bounce_buffer_only: Bounce Buffer Only @@ -212,8 +210,8 @@ This mode is similar to :ref:`bounce_buffer_with_single_psram_frame_buffer`, but .. note:: - In a well-designed embedded application, situations where the DMA can not deliver data as fast as the LCD consumes it should be avoided. However, such scenarios can happen in theory. In the {IDF_TARGET_NAME} hardware, this leads to the LCD simply outputting dummy bytes while DMA waits for data. If we were to run DMA in a stream fashion, a desynchronization between the LCD address for which the DMA reads the data and the LCD address for which the LCD peripheral outputs data would occur, leading to a **permanently** shifted image. - In order to stop this from happening, you can either enable the :ref:`CONFIG_LCD_RGB_RESTART_IN_VSYNC` option, so the driver can restart the DMA in the VBlank interrupt automatically, or call :cpp:func:`esp_lcd_rgb_panel_restart` to restart the DMA manually. Note that :cpp:func:`esp_lcd_rgb_panel_restart` does not restart the DMA immediately; instead, the DMA will be restarted in the next VSYNC event. + In a well-designed embedded application, situations where the DMA cannot deliver data as fast as the LCD consumes it should be avoided. However, such scenarios can theoretically occur. In the {IDF_TARGET_NAME} hardware, this results in the LCD outputting dummy bytes while the DMA waits for data. If the DMA were to run in a continuous stream, it could cause a desynchronization between the LCD address from which the DMA reads data and the address from which the LCD peripheral outputs data, leading to a **permanently** shifted image. + To prevent this, you can either enable the :ref:`CONFIG_LCD_RGB_RESTART_IN_VSYNC` option, allowing the driver to automatically restart the DMA during the VBlank interrupt, or call :cpp:func:`esp_lcd_rgb_panel_restart` to manually restart the DMA. Note that :cpp:func:`esp_lcd_rgb_panel_restart` does not restart the DMA immediately; instead, the DMA will be restarted at the next VSYNC event. API Reference ------------- diff --git a/docs/en/api-reference/peripherals/ledc.rst b/docs/en/api-reference/peripherals/ledc.rst index cc50f2c0d7a0..8005b6b55825 100644 --- a/docs/en/api-reference/peripherals/ledc.rst +++ b/docs/en/api-reference/peripherals/ledc.rst @@ -88,7 +88,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f * - RC_FAST_CLK - ~ 8 MHz - Low - - Dynamic Frequency Scaling compatible, Light sleep compatible + - Dynamic Frequency Scaling compatible, Light-sleep compatible .. only:: esp32s2 @@ -107,7 +107,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f - Dynamic Frequency Scaling compatible * - RC_FAST_CLK - ~ 8 MHz - - Dynamic Frequency Scaling compatible, Light sleep compatible + - Dynamic Frequency Scaling compatible, Light-sleep compatible * - XTAL_CLK - 40 MHz - Dynamic Frequency Scaling compatible @@ -126,7 +126,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f - / * - RC_FAST_CLK - ~ 20 MHz - - Dynamic Frequency Scaling compatible, Light sleep compatible + - Dynamic Frequency Scaling compatible, Light-sleep compatible * - XTAL_CLK - 40 MHz - Dynamic Frequency Scaling compatible @@ -145,7 +145,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f - / * - RC_FAST_CLK - ~ 20 MHz - - Dynamic Frequency Scaling compatible, Light sleep compatible + - Dynamic Frequency Scaling compatible, Light-sleep compatible * - XTAL_CLK - 40/26 MHz - Dynamic Frequency Scaling compatible @@ -164,7 +164,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f - / * - RC_FAST_CLK - ~ 17.5 MHz - - Dynamic Frequency Scaling compatible, Light sleep compatible + - Dynamic Frequency Scaling compatible, Light-sleep compatible * - XTAL_CLK - 48 MHz - Dynamic Frequency Scaling compatible @@ -183,7 +183,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f - / * - RC_FAST_CLK - ~ 17.5 MHz - - Dynamic Frequency Scaling compatible, Light sleep compatible + - Dynamic Frequency Scaling compatible, Light-sleep compatible * - XTAL_CLK - 40 MHz - Dynamic Frequency Scaling compatible @@ -202,7 +202,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f - / * - RC_FAST_CLK - ~ 8 MHz - - Dynamic Frequency Scaling compatible, Light sleep compatible + - Dynamic Frequency Scaling compatible, Light-sleep compatible * - XTAL_CLK - 32 MHz - Dynamic Frequency Scaling compatible @@ -337,6 +337,18 @@ When configuring an LEDC channel, one of the parameters selected within :cpp:typ For registration of a handler to address this interrupt, call :cpp:func:`ledc_isr_register`. +Power Management +---------------- + +LEDC driver does not utilize power management lock to prevent the system from going into Light-sleep. Instead, the LEDC peripheral power domain state and the PWM signal output behavior during sleep can be chosen by configuring :cpp:member:`ledc_channel_config_t::sleep_mode`. The default mode is :cpp:enumerator:`LEDC_SLEEP_MODE_NO_ALIVE_NO_PD`, which stands for no signal output and LEDC power domain will not be powered down during sleep. + +If signal output needs to be maintained in Light-sleep, then select :cpp:enumerator:`LEDC_SLEEP_MODE_KEEP_ALIVE`. As long as the binded LEDC timer clock source is Light-sleep compatible, the PWM signal can continue its output even the system enters Light-sleep. The cost is a higher power consumption in sleep, since the clock source and the power domain where LEDC belongs to cannot be powered down. Note that, if there is an unfinished fade before entering sleep, the fade can also continue during sleep, but the target duty might not be reached exactly. It will adjust to the target duty after wake-up. + +.. only:: SOC_LEDC_SUPPORT_SLEEP_RETENTION + + There is another sleep mode, :cpp:enumerator:`LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD`, can save some power consumption in sleep, but at the expense of more memory being consumed. The system retains LEDC register context before entering Light-sleep and restores them after waking up, so that the LEDC power domain can be powered down during sleep. Any unfinished fade will not resume upon waking up from sleep, instead, it will output a PWM signal with a fixed duty cycle that matches the duty cycle just before entering sleep. + + .. only:: esp32 .. _ledc-api-high_low_speed_mode: diff --git a/docs/en/api-reference/peripherals/mcpwm.rst b/docs/en/api-reference/peripherals/mcpwm.rst index 3a6de1476e0f..7e80c519c564 100644 --- a/docs/en/api-reference/peripherals/mcpwm.rst +++ b/docs/en/api-reference/peripherals/mcpwm.rst @@ -122,8 +122,6 @@ You can allocate a MCPWM generator object by calling the :cpp:func:`mcpwm_new_ge - :cpp:member:`mcpwm_generator_config_t::gen_gpio_num` sets the GPIO number used by the generator. - :cpp:member:`mcpwm_generator_config_t::invert_pwm` sets whether to invert the PWM signal. -- :cpp:member:`mcpwm_generator_config_t::io_loop_back` sets whether to enable the Loop-back mode. It is for debugging purposes only. It enables both the GPIO's input and output ability through the GPIO matrix peripheral. -- :cpp:member:`mcpwm_generator_config_t::io_od_mode` configures the PWM GPIO as open-drain output. - :cpp:member:`mcpwm_generator_config_t::pull_up` and :cpp:member:`mcpwm_generator_config_t::pull_down` controls whether to enable the internal pull-up and pull-down resistors accordingly. The :cpp:func:`mcpwm_new_generator` will return a pointer to the allocated generator object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free generators in the MCPWM operator, this function will return the :c:macro:`ESP_ERR_NOT_FOUND` error. [1]_ @@ -142,7 +140,6 @@ To allocate a GPIO fault object, you can call the :cpp:func:`mcpwm_new_gpio_faul - :cpp:member:`mcpwm_gpio_fault_config_t::gpio_num` sets the GPIO number used by the fault. - :cpp:member:`mcpwm_gpio_fault_config_t::active_level` sets the active level of the fault signal. - :cpp:member:`mcpwm_gpio_fault_config_t::pull_up` and :cpp:member:`mcpwm_gpio_fault_config_t::pull_down` set whether to pull up and/or pull down the GPIO internally. -- :cpp:member:`mcpwm_gpio_fault_config_t::io_loop_back` sets whether to enable the loopback mode. It is for debugging purposes only. It enables both the GPIO's input and output ability through the GPIO matrix peripheral. The :cpp:func:`mcpwm_new_gpio_fault` will return a pointer to the allocated fault object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free GPIO faults in the MCPWM group, this function will return the :c:macro:`ESP_ERR_NOT_FOUND` error. [1]_ @@ -163,7 +160,6 @@ To allocate a GPIO sync source, you can call the :cpp:func:`mcpwm_new_gpio_sync_ - :cpp:member:`mcpwm_gpio_sync_src_config_t::gpio_num` sets the GPIO number used by the sync source. - :cpp:member:`mcpwm_gpio_sync_src_config_t::active_neg` sets whether the sync signal is active on falling edges. - :cpp:member:`mcpwm_gpio_sync_src_config_t::pull_up` and :cpp:member:`mcpwm_gpio_sync_src_config_t::pull_down` set whether to pull up and/or pull down the GPIO internally. -- :cpp:member:`mcpwm_gpio_sync_src_config_t::io_loop_back` sets whether to enable the Loop-back mode. It is for debugging purposes only. It enables both the GPIO's input and output ability through the GPIO matrix peripheral. The :cpp:func:`mcpwm_new_gpio_sync_src` will return a pointer to the allocated sync source object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free GPIO sync sources in the MCPWM group, this function will return the :c:macro:`ESP_ERR_NOT_FOUND` error. [1]_ @@ -207,8 +203,6 @@ Next, to allocate a capture channel, you can call the :cpp:func:`mcpwm_new_captu - :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::pos_edge` and :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::neg_edge` set whether to capture on the positive and/or falling edge of the input signal. - :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::pull_up` and :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::pull_down` set whether to pull up and/or pull down the GPIO internally. - :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::invert_cap_signal` sets whether to invert the capture signal. -- :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::io_loop_back` sets whether to enable the Loop-back mode. It is for debugging purposes only. It enables both the GPIO's input and output ability through the GPIO matrix peripheral. -- :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::keep_io_conf_at_exit` sets whether to keep the GPIO configuration when the capture channel is deleted. The :cpp:func:`mcpwm_new_capture_channel` will return a pointer to the allocated capture channel object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there is no free capture channel left in the capture timer, this function will return the :c:macro:`ESP_ERR_NOT_FOUND` error. @@ -529,7 +523,7 @@ Dead time specific configuration is listed in the :cpp:type:`mcpwm_dead_time_con // NOTE: This is invalid, you can not apply the posedge delay to another generator mcpwm_generator_set_dead_time(mcpwm_gen_b, mcpwm_gen_b, &dt_config); - However, you can apply ``posedge delay`` to generator A and ``negedge delay`` to generator B. You can also set both ``posedge delay`` and ``negedge delay`` for generator A, while letting generator B bypass the dead time module. + However, you can apply ``posedge delay`` to generator A and ``negedge delay`` to generator B. You can also set both ``posedge delay`` and ``negedge delay`` for generator B, while letting generator A bypass the dead time module. Note that if ``negedge delay`` and ``posedge delay`` are both set for generator A, generator B will not be available. Where generator A is the first generator requested through the operator handle and generator B is the second generator requested through an operator handle. .. note:: diff --git a/docs/en/api-reference/peripherals/pcnt.rst b/docs/en/api-reference/peripherals/pcnt.rst index 15478424fe15..3f7d9a12c089 100644 --- a/docs/en/api-reference/peripherals/pcnt.rst +++ b/docs/en/api-reference/peripherals/pcnt.rst @@ -226,7 +226,7 @@ This function should be called when the unit is in the init state. Otherwise, it .. note:: - The glitch filter is clocked from APB. For the counter not to miss any pulses, the maximum glitch width should be longer than one APB_CLK cycle (usually 12.5 ns if APB equals 80 MHz). As the APB frequency would be changed after DFS (Dynamic Frequency Scaling) enabled, which means the filter does not work as expect in that case. So the driver installs a PM lock for PCNT unit during the first time you enable the glitch filter. For more information related to power management strategy used in PCNT driver, please see :ref:`pcnt-power-management`. + The glitch filter operates using the APB clock. To ensure the counter does not miss any pulses, the maximum glitch width should be longer than one APB_CLK cycle (typically 12.5 ns if APB is 80 MHz). Since the APB frequency can change with Dynamic Frequency Scaling (DFS), the filter may not function as expected in such cases. Therefore, the driver installs a power management lock for each PCNT unit. For more details on the power management strategy used in the PCNT driver, please refer to :ref:`pcnt-power-management`. .. code:: c @@ -269,7 +269,7 @@ Before doing IO control to the PCNT unit, you need to enable it first, by callin * switches the PCNT driver state from **init** to **enable**. * enables the interrupt service if it has been lazy installed in :cpp:func:`pcnt_unit_register_event_callbacks`. -* acquires a proper power management lock if it has been lazy installed in :cpp:func:`pcnt_unit_set_glitch_filter`. See also :ref:`pcnt-power-management` for more information. +* acquires a proper power management lock if it has been installed. See also :ref:`pcnt-power-management` for more information. On the contrary, calling :cpp:func:`pcnt_unit_disable` will do the opposite, that is, put the PCNT driver back to the **init** state, disable the interrupts service and release the power management lock. @@ -327,9 +327,9 @@ The internal hardware counter will be cleared to zero automatically when it reac Power Management ^^^^^^^^^^^^^^^^ -When power management is enabled (i.e., :ref:`CONFIG_PM_ENABLE` is on), the system will adjust the APB frequency before going into light sleep, thus potentially changing the behavior of PCNT glitch filter and leading to valid signal being treated as noise. +When power management is enabled (i.e., :ref:`CONFIG_PM_ENABLE` is on), the system adjusts the APB frequency before entering light sleep, which can cause the PCNT glitch filter to misinterpret valid signals as noise. -However, the driver can prevent the system from changing APB frequency by acquiring a power management lock of type :cpp:enumerator:`ESP_PM_APB_FREQ_MAX`. Whenever you enable the glitch filter by :cpp:func:`pcnt_unit_set_glitch_filter`, the driver guarantees that the power management lock is acquired after the PCNT unit is enabled by :cpp:func:`pcnt_unit_enable`. Likewise, the driver releases the lock after :cpp:func:`pcnt_unit_disable` is called. +To prevent this, the driver can acquire a power management lock of type :cpp:enumerator:`ESP_PM_APB_FREQ_MAX`, ensuring the APB frequency remains constant. This lock is acquired when the PCNT unit is enabled via :cpp:func:`pcnt_unit_enable` and released when the unit is disabled via :cpp:func:`pcnt_unit_disable`. .. _pcnt-iram-safe: diff --git a/docs/en/api-reference/peripherals/sd_pullup_requirements.rst b/docs/en/api-reference/peripherals/sd_pullup_requirements.rst index 399d5f424ac3..21e8e1e5ed93 100644 --- a/docs/en/api-reference/peripherals/sd_pullup_requirements.rst +++ b/docs/en/api-reference/peripherals/sd_pullup_requirements.rst @@ -1,9 +1,11 @@ SD Pull-up Requirements ======================= +:link_to_translation:`zh_CN:[中文]` + Espressif hardware products are designed for multiple use cases which may require different pull states on pins. For this reason, the pull state of particular pins on certain products needs to be adjusted to provide the pull-ups required in the SD bus. -SD pull-up requirements apply to cases where {IDF_TARGET_NAME} uses the SPI or SDMMC controller to communicate with SD cards. When an SD card is operating in SPI mode or 1-bit SD mode, the CMD and DATA (DAT0 - DAT3) lines of the SD bus must be pulled up by 10 kOhm resistors. SD cards and SDIO devices should also have pull-ups on all above-mentioned lines (regardless of whether these lines are connected to the host) in order to prevent them from entering a wrong state. +SD pull-up requirements apply to cases where {IDF_TARGET_NAME} uses the SPI or SDMMC controller to communicate with SD cards. When an SD card is operating in SPI mode or 1-bit SD mode, the CMD and DATA (DAT0 - DAT3) lines of the SD bus must be pulled up by 10 kΩ resistors. SD cards and SDIO devices should also have pull-ups on all above-mentioned lines (regardless of whether these lines are connected to the host) in order to prevent them from entering a wrong state. .. only:: esp32 @@ -11,13 +13,13 @@ SD pull-up requirements apply to cases where {IDF_TARGET_NAME} uses the SPI or S .. todo:: - Add a diagram of the Bus lines and pullups + Add a diagram of the bus lines and pullups This document has the following structure: -- `Overview of compatibility`_ between the default pull states on pins of Espressif's products and the states required by the SD bus -- `Solutions`_ - ideas on how to resolve compatibility issues -- `Related information`_ - other relevant information +- :ref:`compatibility_overview_espressif_hw_sdio` between the default pull states on pins of Espressif's products and the states required by the SD bus +- :ref:`sdio_solutions` - ideas on how to resolve compatibility issues +- :ref:`related_info_sdio` - other relevant information .. _compatibility_overview_espressif_hw_sdio: @@ -28,11 +30,11 @@ Overview of Compatibility This section provides an overview of compatibility issues that might occur when using SDIO (secure digital input output). Since the SD bus needs to be connected to pull-ups, these issues should be resolved regardless of whether they are related to master (host) or slave (device). Each issue has links to its respective solution. A solution for a host and device may differ. -Systems on a Chip (SoCs) -^^^^^^^^^^^^^^^^^^^^^^^^ - .. only:: esp32 + Systems on a Chip (SoCs) + ^^^^^^^^^^^^^^^^^^^^^^^^ + - ESP32 (except for D2WD versions, see `ESP32 datasheet `_): - :ref:`sd_pull-up_no_pull-ups` @@ -45,33 +47,34 @@ Systems on a Chip (SoCs) .. only:: SOC_SDMMC_USE_GPIO_MATRIX - {IDF_TARGET_NAME} SDMMC host controller allows using any of GPIOs for any of SD interface signals. However, it is recommended to avoid using strapping GPIOs, GPIOs with internal weak pull-downs and GPIOs commonly used for other purposes to prevent conflicts: + Systems on a Chip (SoCs) + ^^^^^^^^^^^^^^^^^^^^^^^^ -.. only:: esp32s3 + {IDF_TARGET_NAME} SDMMC host controller allows using any of GPIOs for any of SD interface signals. However, it is recommended to avoid using strapping GPIOs, GPIOs with internal weak pull-downs and GPIOs commonly used for other purposes to prevent conflicts. - - GPIO0 (strapping pin) - - GPIO45, GPIO46 (strapping pins, internal weak pulldown) - - GPIO26 - GPIO32 (commonly used for SPI Flash and PSRAM) - - GPIO33 - GPIO37 (when using chips and modules with Octal SPI Flash or Octal PSRAM) - - GPIO43, GPIO44 (GPIOs used for UART0 by default) - - GPIO19, GPIO20 (GPIOs used for USB by default) + .. only:: esp32s3 + - GPIO0 (strapping pin) + - GPIO45, GPIO46 (strapping pins, internal weak pulldown) + - GPIO26 - GPIO32 (commonly used for SPI flash and PSRAM) + - GPIO33 - GPIO37 (when using chips and modules with octal SPI flash or octal PSRAM) + - GPIO43, GPIO44 (GPIOs used for UART0 by default) + - GPIO19, GPIO20 (GPIOs used for USB by default) -Systems in Packages (SIP) -^^^^^^^^^^^^^^^^^^^^^^^^^ .. only:: esp32 + Systems in Packages (SIP) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + - ESP32-PICO-D4: - :ref:`sd_pull-up_no_pull-ups` - :ref:`strapping_conflicts_dat2` -Modules -^^^^^^^ - -.. only:: esp32 + Modules + ^^^^^^^ - ESP32-WROOM-32 Series, including ESP32-WROOM-32, ESP32-WROOM-32D, ESP32-WROOM-32U, and ESP32-SOLO-1 @@ -88,12 +91,12 @@ Modules - :ref:`strapping_conflicts_dat2` -.. _sdio_dev_kits: +.. only:: esp32 -Development Boards -^^^^^^^^^^^^^^^^^^ + .. _sdio_dev_kits: -.. only:: esp32 + Development Boards + ^^^^^^^^^^^^^^^^^^ - ESP32-PICO-KIT, including PICO-KIT v4.1, v4.0, and v3 @@ -132,6 +135,11 @@ Development Boards .. only:: esp32s3 + .. _sdio_dev_kits: + + Development Boards + ^^^^^^^^^^^^^^^^^^ + - ESP32-S3-DevKitC-1 - :ref:`sd_pull-up_no_pull-ups` @@ -154,6 +162,8 @@ Development Boards Please make sure that your SDIO host provides necessary pull-ups for all SD bus signals. +.. _sdio_solutions: + Solutions --------- @@ -162,10 +172,19 @@ Solutions No Pull-ups ^^^^^^^^^^^ -If you use a development board without pull-ups, you can do the following: +.. only:: esp32 or esp32s3 -- If your host and slave device are on separate boards, replace one of them with a board that has pull-ups. For the list of Espressif's development boards with pull-ups, go to :ref:`sdio_dev_kits`. -- Attach external pull-ups by connecting each pin which requires a pull-up to VDD via a 10 kOhm resistor. + When using a development board without pull-ups: + + - If your host and slave device are on separate boards, replace one of them with a board that has pull-ups. For the list of Espressif's development boards with pull-ups, go to :ref:`sdio_dev_kits`. + - Attach external pull-ups by connecting each pin which requires a pull-up to VDD via a 10 kΩ resistor. + +.. only:: not esp32 and not esp32s3 + + When using a development board without pull-ups: + + - If your host and slave device are on separate boards, replace one of them with a board that has pull-ups. + - Attach external pull-ups by connecting each pin which requires a pull-up to VDD via a 10 kΩ resistor. .. only:: esp32 @@ -180,7 +199,7 @@ If you use a development board without pull-ups, you can do the following: - Use SPI mode - Perform one of the following actions on the GPIO13 pin: - Remove the pull-down resistors - - Attach a pull-up resistor of less than 5 kOhm (2 kOhm suggested) + - Attach a pull-up resistor of less than 5 kΩ (2 kΩ suggested) - Pull it up or drive it high either by using the host or with 3.3 V on VDD in 1-bit SD mode @@ -219,20 +238,20 @@ If you use a development board without pull-ups, you can do the following: BURN VDD_SDIO setting complete. - To check the status of the eFuses, run:: + To check the status of the eFuses, run: - .. code-block:: + .. code-block:: none idf.py efuse-summary - If running from an automated flashing script, it is better to use standalone eFuse tool, ``espefuse.py``. This tool also has an option ``--do-not-confirm`` to burn eFuses without confirmation. + If running from an automated flashing script, it is better to use standalone eFuse tool ``espefuse.py``. This tool also has an option ``--do-not-confirm`` to burn eFuses without confirmation. For more details, see **{IDF_TARGET_NAME} Technical Reference Manual** [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__]. - 2. **If using 1-bit SD mode or SPI mode**, disconnect the DAT2 pin and make sure it is pulled high. For this, do one the following: + 2. **If using 1-bit SD mode or SPI mode**, disconnect the DAT2 pin and make sure it is pulled high. For this, you have the following options: - - Leave the host's DAT2 floating and directly connect the slave's DAT2 to VDD. - - For a slave device, build a firmware with the option ``SDIO_SLAVE_FLAG_DAT2_DISABLED`` and re-flash your device. This option helps avoid slave detecting on the DAT2 line. Note that 4-bit SD mode is no longer supported by the standard Card Common Control Register (CCCR); however, the host is not aware of that. The use of 4-bit SD mode has to be disabled on the host's side. + - Leave the host's DAT2 floating and directly connect the slave's DAT2 to VDD. + - For a slave device, build a firmware with the option ``SDIO_SLAVE_FLAG_DAT2_DISABLED`` and re-flash your device. This option helps avoid slave detecting on the DAT2 line. Note that 4-bit SD mode is no longer supported by the standard Card Common Control Register (CCCR); however, the host is not aware of that. The use of 4-bit SD mode has to be disabled on the host's side. .. _no_pull-up_on_gpio12: @@ -240,7 +259,7 @@ If you use a development board without pull-ups, you can do the following: No Pull-up on GPIO12 ^^^^^^^^^^^^^^^^^^^^ - Your module is compatible with the SDIO protocol. Just connect GPIO12 to VDD via a 10 kOhm resistor. + Your module is compatible with the SDIO protocol. Just connect GPIO12 to VDD via a 10 kΩ resistor. .. _gpio2_strapping_pin: @@ -248,25 +267,25 @@ If you use a development board without pull-ups, you can do the following: Download Mode Not Working (minor issue) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - When the GPIO2 pin is pulled high in accordance with the SD pull-up requirements, you cannot enter Download mode because GPIO2 is a bootstrapping pin which in this case must be pulled low. + When the GPIO2 pin is pulled high in accordance with the SD pull-up requirements, you can not enter download mode because GPIO2 is a bootstrapping pin which in this case must be pulled low. - There are the following solutions: + There are following solutions: - - For boards that require shorting the GPIO0 and GPIO2 pins with a jumper, put the jumper in place, and the auto-reset circuit pulls GPIO2 low along with GPIO0 before entering Download mode. + - For boards that require shorting the GPIO0 and GPIO2 pins with a jumper, put the jumper in place, and the auto-reset circuit pulls GPIO2 low along with GPIO0 before entering download mode. - For boards with components attached to their GPIO2 pin (such as pull-down resistors and/or LEDs), check the schematic of your development board for anything connected to GPIO2. - **LEDs** would not affect operation in most cases. - **Pull-down resistors** can interfere with DAT0 signals and must be removed. - If the above solutions do not work for you, please determine if it is the host or slave device that has pull-ups affecting their GPIO2, then locate these pull-ups and remove them. + If above solutions do not work for you, please determine if it is the host or slave device that has pull-ups affecting their GPIO2, then locate these pull-ups and remove them. -.. _related_info_sdio: +.. only:: esp32 -Related Information -------------------- + .. _related_info_sdio: -.. only:: esp32 + Related Information + ------------------- .. _mtdi_strapping_pin: @@ -287,9 +306,9 @@ Related Information Internal Pull-ups and Strapping Requirements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Using external resistors is always preferable. However, Espressif's products have internal weak pull-up and pull-down resistors which can be enabled and used instead of external ones. Please keep in mind that this solution cannot guarantee reliable SDIO communication. + Using external resistors is always preferable. However, Espressif's products have internal weak pull-up and pull-down resistors which can be enabled and used instead of external ones. Please keep in mind that this solution can not guarantee reliable SDIO communication. - With that said, the information about these internal pull-ups and strapping requirements can still be useful. Espressif hardware products have different weak internal pull-ups/pull-downs connected to CMD and DATA pins. The table below shows the default pull-up and pull-down states of the CMD and DATA pins. + With that said, the information about these internal pull-ups and strapping requirements can still be useful. Espressif hardware products have different weak internal pull-ups and pull-downs connected to CMD and DATA pins. The table below shows the default pull-up and pull-down states of the CMD and DATA pins. The following abbreviations are used in the table: @@ -325,3 +344,17 @@ Related Information - DAT3 - WPU - + +.. only:: not esp32 + + .. _related_info_sdio: + + Related Information + ------------------- + + Internal Pull-ups and Strapping Requirements + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Using external resistors is always preferable. However, Espressif's products have internal weak pull-up and pull-down resistors which can be enabled and used instead of external ones. Please keep in mind that this solution can not guarantee reliable SDIO communication. + + Generally it's not recommended to reuse strapping pins for SDIO purposes. The pullup and pulldown requirements of SD and strapping may conflict with each other. See datasheet for the strapping pins of {IDF_TARGET}. diff --git a/docs/en/api-reference/peripherals/sdm.rst b/docs/en/api-reference/peripherals/sdm.rst index 85edb53f73ad..32dc851fe649 100644 --- a/docs/en/api-reference/peripherals/sdm.rst +++ b/docs/en/api-reference/peripherals/sdm.rst @@ -42,7 +42,6 @@ To install an SDM channel, you should call :cpp:func:`sdm_new_channel` to get a - :cpp:member:`sdm_config_t::clk_src` selects the source clock for the SDM module. Note that, all channels should select the same clock source. - :cpp:member:`sdm_config_t::sample_rate_hz` sets the sample rate of the SDM module. A higher sample rate can help to output signals with higher SNR (Signal to Noise Ratio), and easier to restore the original signal after the filter. - :cpp:member:`sdm_config_t::invert_out` sets whether to invert the output signal. -- :cpp:member:`sdm_config_t::io_loop_back` is for debugging purposes only. It enables both the GPIO's input and output ability through the GPIO matrix peripheral. The function :cpp:func:`sdm_new_channel` can fail due to various errors such as insufficient memory, invalid arguments, etc. Specifically, when there are no more free channels (i.e., all hardware SDM channels have been used up), :c:macro:`ESP_ERR_NOT_FOUND` will be returned. diff --git a/docs/en/api-reference/peripherals/spi_flash/index.rst b/docs/en/api-reference/peripherals/spi_flash/index.rst index 9b1c4053a68c..631a5a804620 100644 --- a/docs/en/api-reference/peripherals/spi_flash/index.rst +++ b/docs/en/api-reference/peripherals/spi_flash/index.rst @@ -116,7 +116,7 @@ Generally, try to avoid using the raw SPI flash functions to the "main" SPI flas SPI Flash Size -------------- -The SPI flash size is configured by writing a field in the software bootloader image header, flashed at offset 0x1000. +The SPI flash size is configured by writing a field in the ESP-IDF second stage bootloader image header, flashed at offset 0x1000. By default, the SPI flash size is detected by ``esptool.py`` when this bootloader is written to flash, and the header is updated with the correct size. Alternatively, it is possible to generate a fixed flash size by setting :ref:`CONFIG_ESPTOOLPY_FLASHSIZE` in the project configuration. diff --git a/docs/en/api-reference/peripherals/spi_flash/spi_flash_override_driver.rst b/docs/en/api-reference/peripherals/spi_flash/spi_flash_override_driver.rst index 7af6fb199d26..1d461737074a 100644 --- a/docs/en/api-reference/peripherals/spi_flash/spi_flash_override_driver.rst +++ b/docs/en/api-reference/peripherals/spi_flash/spi_flash_override_driver.rst @@ -64,7 +64,7 @@ Steps For Creating Custom Chip Drivers and Overriding the ESP-IDF Default Driver .get_chip_caps = spi_flash_chip_eon_get_caps, }; - - You also can see how to implement this in the example :example:`storage/custom_flash_driver`. + - You also can see how to implement this in the example :example:`storage/custom_flash_driver`. This example demonstrates how to override the default chip driver list. 4. Write a new ``CMakeLists.txt`` file for the ``custom_chip_driver`` component, including an additional line to add a linker dependency from ``spi_flash`` to ``custom_chip_driver``:: @@ -80,8 +80,3 @@ Steps For Creating Custom Chip Drivers and Overriding the ESP-IDF Default Driver 5. The ``linker.lf`` is used to put every chip driver that you are going to use whilst cache is disabled into internal RAM. See :doc:`/api-guides/linker-script-generation` for more details. Make sure this file covers all the source files that you add. 6. Build your project, and you will see the new flash driver is used. - -Example -------- - -See also :example:`storage/custom_flash_driver`. diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 71ef262c433d..7932212719e0 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -305,6 +305,14 @@ Bus Acquiring Sometimes you might want to send SPI transactions exclusively and continuously so that it takes as little time as possible. For this, you can use bus acquiring, which helps to suspend transactions (both polling or interrupt) to other Devices until the bus is released. To acquire and release a bus, use the functions :cpp:func:`spi_device_acquire_bus` and :cpp:func:`spi_device_release_bus`. +.. only:: SOC_SPI_SUPPORT_SLEEP_RETENTION + + Sleep Retention + ^^^^^^^^^^^^^^^ + + {IDF_TARGET_NAME} supports to retain the SPI register context before entering **light sleep** and restore them after waking up. This means you don't have to re-init the SPI driver after the light sleep. + + This feature can be enabled by setting the flag :c:macro:`SPICOMMON_BUSFLAG_SLP_ALLOW_PD`. It will allow the system to power down the SPI in light sleep, meanwhile save the register context. It can help to save more power consumption with some extra cost of the memory. Driver Usage ------------ diff --git a/docs/en/api-reference/peripherals/temp_sensor.rst b/docs/en/api-reference/peripherals/temp_sensor.rst index 22b7e1a6ce3d..ca7231e6e1e2 100644 --- a/docs/en/api-reference/peripherals/temp_sensor.rst +++ b/docs/en/api-reference/peripherals/temp_sensor.rst @@ -59,6 +59,7 @@ In order to install a built-in temperature sensor instance, the first thing is t - :cpp:member:`range_min`: The minimum value of the testing range you have evaluated. - :cpp:member:`range_max`: The maximum value of the testing range you have evaluated. +- :cpp:member:`allow_pd` configures if the driver allows the system to power down the peripheral in light sleep mode. Before entering sleep, the system will backup the temperature sensor register context, which will be restored later when the system exit the sleep mode. Powering down the peripheral can save more power, but at the cost of more memory consumed to save the register context. It's a tradeoff between power consumption and memory consumption. This configuration option relies on specific hardware feature, if you enable it on an unsupported chip, you will see error message like ``not able to power down in light sleep``. After the ranges are set, the structure could be passed to :cpp:func:`temperature_sensor_install`, which will instantiate the temperature sensor instance and return a handle. diff --git a/docs/en/api-reference/peripherals/twai.rst b/docs/en/api-reference/peripherals/twai.rst index 00c90529cf4e..310f9126c52e 100644 --- a/docs/en/api-reference/peripherals/twai.rst +++ b/docs/en/api-reference/peripherals/twai.rst @@ -599,6 +599,14 @@ Application Examples **Self-Test Example:** :example:`peripherals/twai/twai_self_test` demonstrates how a node can transmit TWAI messages to itself using the TWAI driver's "No Acknowledgement" mode and Self Reception Requests, testing the proper connection of a target to a working external transceiver. +.. only:: SOC_TWAI_SUPPORT_SLEEP_RETENTION + + Sleep Retention + ^^^^^^^^^^^^^^^ + + {IDF_TARGET_NAME} supports to retain the TWAI register context before entering **light sleep** and restore them after waking up. This means you don't have to re-init the TWAI driver after the light sleep. + + This feature can be enabled by setting the flag :cpp:member:`twai_general_config_t::sleep_allow_pd`. It will allow the system to power down the TWAI in light sleep, meanwhile saving the register context. It can help save more power consumption with some extra cost of the memory. .. ---------------------------- API Reference ---------------------------------- diff --git a/docs/en/api-reference/protocols/esp_serial_slave_link.rst b/docs/en/api-reference/protocols/esp_serial_slave_link.rst index af35ba5ed084..b3ab831180a9 100644 --- a/docs/en/api-reference/protocols/esp_serial_slave_link.rst +++ b/docs/en/api-reference/protocols/esp_serial_slave_link.rst @@ -91,7 +91,7 @@ ESP SDIO Slave The ESP SDIO slave link (ESSL SDIO) devices relies on the SDMMC component. It includes the usage of communicating with ESP SDIO Slave device via the SDMMC Host or SDSPI Host feature. The ESSL device should be initialized as below: -1. Initialize a SDMMC card (see :doc:` Document of SDMMC driver `) structure. +1. Initialize a SDMMC card (see :doc:`Document of SDMMC driver `) structure. 2. Call :cpp:func:`sdmmc_card_init` to initialize the card. diff --git a/docs/en/api-reference/protocols/icmp_echo.rst b/docs/en/api-reference/protocols/icmp_echo.rst index 929211088b47..5aa1451133aa 100644 --- a/docs/en/api-reference/protocols/icmp_echo.rst +++ b/docs/en/api-reference/protocols/icmp_echo.rst @@ -109,10 +109,10 @@ Get Runtime Statistics As the example code above, you can call ``esp_ping_get_profile`` to get different runtime statistics of ping session in the callback function. -Application Example -------------------- +Application Examples +-------------------- -ICMP echo example: :example:`protocols/icmp_echo` +- :example:`protocols/icmp_echo` demonstrates how to implement a simple ping command line utility to test if a remote host is reachable on the IP network, using ICMP echo request packets. API Reference ------------- diff --git a/docs/en/api-reference/protocols/mbedtls.rst b/docs/en/api-reference/protocols/mbedtls.rst index 67d4ee0f1d9c..b02fd595d7c0 100644 --- a/docs/en/api-reference/protocols/mbedtls.rst +++ b/docs/en/api-reference/protocols/mbedtls.rst @@ -9,7 +9,7 @@ Mbed TLS ESP-IDF uses a `fork `_ of Mbed TLS which includes a few patches (related to hardware routines of certain modules like ``bignum (MPI)`` and ``ECC``) over vanilla Mbed TLS. -Mbed TLS supports SSL 3.0 up to TLS 1.3 and DTLS 1.0 to 1.2 communication by providing the following: +Mbed TLS supports TLS 1.2, TLS 1.3 and DTLS 1.2 communication by providing the following: - TCP/IP communication functions: listen, connect, accept, read/write. - SSL/TLS communication functions: init, handshake, read/write. @@ -18,8 +18,9 @@ Mbed TLS supports SSL 3.0 up to TLS 1.3 and DTLS 1.0 to 1.2 communication by pro - Hashing - Encryption/decryption -Supported TLS versions include SSL 3.0, TLS 1.0, TLS 1.1, TLS 1.2, and TLS 1.3, but on the latest ESP-IDF, SSL 3.0, TLS 1.0, and TLS 1.1 have been removed from Mbed TLS. Supported DTLS versions include DTLS 1.0, DTLS 1.1, and DTLS 1.2, but on the latest ESP-IDF, DTLS 1.0 has been removed from Mbed TLS. +.. note:: + Mbed TLS v3.x.x series supports only TLS 1.2 and TLS 1.3 protocols. Support for SSL 3.0, TLS 1.0/1.1 and DTLS 1.0 has been removed (deprecated). TLS 1.3 is fully supported starting Mbed TLS v3.6.0 release, before this release some features were still in experimental state. Please refer to :component_file:`Mbed TLS ChangeLog ` for more details. Mbed TLS Documentation ---------------------- @@ -73,11 +74,6 @@ Following is a brief list of important config options accessible at ``Component :SOC_MPI_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_MPI`: Support for hardware MPI (bignum) acceleration :SOC_ECC_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_ECC`: Support for hardware ECC acceleration -.. note:: - - Mbed TLS v3.0.0 and later support only TLS 1.2 and TLS 1.3 (SSL 3.0, TLS 1.0, TLS 1.1, and DTLS 1.0 are not supported). The support for TLS 1.3 is experimental and only supports the client-side. More information about this can be found out `here `__. - - Performance and Memory Tweaks ----------------------------- @@ -122,5 +118,5 @@ Reducing Binary Size Under ``Component Config -> mbedTLS``, there are multiple Mbed TLS features which are enabled by default but can be disabled if not needed to save code size. More information can be about this can be found in :ref:`Minimizing Binary Size ` docs. -.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.4.1/ +.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.6.2/ .. _`Knowledge Base`: https://mbed-tls.readthedocs.io/en/latest/kb/ diff --git a/docs/en/api-reference/protocols/modbus.rst b/docs/en/api-reference/protocols/modbus.rst index c74978e2f246..529f3c8b4143 100644 --- a/docs/en/api-reference/protocols/modbus.rst +++ b/docs/en/api-reference/protocols/modbus.rst @@ -14,15 +14,18 @@ The documentation can be found through the link below: * `ESP-Modbus documentation (English) `__ -Application Example -------------------- +Application Examples +-------------------- The examples below demonstrate the ESP-Modbus library of serial and TCP ports for both slave and master implementations respectively. -- :example:`protocols/modbus/serial/mb_slave` -- :example:`protocols/modbus/serial/mb_master` -- :example:`protocols/modbus/tcp/mb_tcp_slave` -- :example:`protocols/modbus/tcp/mb_tcp_master` +- :example:`protocols/modbus/serial/mb_slave` demonstrates how to use {IDF_TARGET_NAME} as a Modbus serial slave device with the esp-modbus stack, enabling an external Modbus host to read and write device parameters using the Modbus protocol. + +- :example:`protocols/modbus/serial/mb_master` demonstrates how to use the esp-modbus stack port on {IDF_TARGET_NAME} as a Modbus serial master device, capable of reading and writing values from slave devices in a Modbus segment. + +- :example:`protocols/modbus/tcp/mb_tcp_slave` demonstrates the esp-modbus TCP slave stack port, allowing an external Modbus host to read and write device parameters via the Modbus protocol. + +- :example:`protocols/modbus/tcp/mb_tcp_master` demonstrates how to use the esp-modbus stack port on {IDF_TARGET_NAME} as a Modbus TCP master device, capable of reading and writing values from slave devices in a Modbus network. Please refer to the ``README.md`` documents of each specific example for details. @@ -30,5 +33,3 @@ Protocol References ------------------- - For the detailed protocol specifications, see `The Modbus Organization `_. - - diff --git a/docs/en/api-reference/protocols/mqtt.rst b/docs/en/api-reference/protocols/mqtt.rst index 7c5899de56c9..b408c3bc2d8a 100644 --- a/docs/en/api-reference/protocols/mqtt.rst +++ b/docs/en/api-reference/protocols/mqtt.rst @@ -19,16 +19,25 @@ Features Application Examples ---------------------- - - * :example:`protocols/mqtt/tcp`: MQTT over TCP, default port 1883 - * :example:`protocols/mqtt/ssl`: MQTT over TLS, default port 8883 - * :example:`protocols/mqtt/ssl_ds`: MQTT over TLS using digital signature peripheral for authentication, default port 8883 - * :example:`protocols/mqtt/ssl_mutual_auth`: MQTT over TLS using certificates for authentication, default port 8883 - * :example:`protocols/mqtt/ssl_psk`: MQTT over TLS using pre-shared keys for authentication, default port 8883 - * :example:`protocols/mqtt/ws`: MQTT over WebSocket, default port 80 - * :example:`protocols/mqtt/wss`: MQTT over WebSocket Secure, default port 443 - * :example:`protocols/mqtt5`: Uses ESP-MQTT library to connect to broker with MQTT v5.0 +-------------------- + + - :example:`protocols/mqtt/tcp` demonstrates how to implement MQTT communication over TCP (default port 1883). + + - :example:`protocols/mqtt/ssl` demonstrates how to use SSL transport to implement MQTT communication over TLS (default port 8883). + + - :example:`protocols/mqtt/ssl_ds` demonstrates how to use digital signature peripheral for authentication to implement MQTT communication over TLS (default port 8883). + + - :example:`protocols/mqtt/ssl_mutual_auth` demonstrates how to use certificates for authentication to implement MQTT communication (default port 8883). + + - :example:`protocols/mqtt/ssl_psk` demonstrates how to use pre-shared keys for authentication to implement MQTT communication over TLS (default port 8883). + + - :example:`protocols/mqtt/ws` demonstrates how to implement MQTT communication over WebSocket (default port 80). + + - :example:`protocols/mqtt/wss` demonstrates how to implement MQTT communication over WebSocket Secure (default port 443). + + - :example:`protocols/mqtt5` demonstrates how to use ESP-MQTT library to connect to broker with MQTT v5.0. + + - :example:`protocols/mqtt/custom_outbox` demonstrates how to customize the outbox in the ESP-MQTT library. MQTT Message Retransmission --------------------------- diff --git a/docs/en/api-reference/storage/fatfs.rst b/docs/en/api-reference/storage/fatfs.rst index f45007607ce4..8a3f2b3d0c5b 100644 --- a/docs/en/api-reference/storage/fatfs.rst +++ b/docs/en/api-reference/storage/fatfs.rst @@ -123,7 +123,7 @@ If you decide for any reason to use ``fatfs_create_rawflash_image`` (without wea The arguments of the function are as follows: -#. partition - the name of the partition as defined in the partition table (e.g., :example_file:`storage/fatfsgen/partitions_example.csv`). +#. partition - the name of the partition as defined in the partition table (e.g., :example_file:`storage/fatfs/fatfsgen/partitions_example.csv`). #. base_dir - the directory that will be encoded to FatFs partition and optionally flashed into the device. Beware that you have to specify the suitable size of the partition in the partition table. @@ -139,7 +139,7 @@ For example:: If FLASH_IN_PROJECT is not specified, the image will still be generated, but you will have to flash it manually using ``esptool.py`` or a custom build system target. -For an example, see :example:`storage/fatfsgen`. +For an example, see :example:`storage/fatfs/fatfsgen`. .. _fatfs-partition-analyzer: @@ -157,6 +157,40 @@ Usage:: Parameter --verbose prints detailed information from boot sector of the FatFs image to the terminal before folder structure is generated. +FATFS Minimum Partition Size and Limits +--------------------------------------- + +The FATFS component supports FAT12, FAT16, and FAT32 file system types. The file system type is determined by the number of clusters (calculated as data sectors divided by sectors per cluster) on the volume. The minimum partition size is defined by the number of sectors allocated to FAT tables, root directories and data clusters. + +* The minimum supported size for a FAT partition with wear leveling enabled is 32 KB for a sector size of 4096 bytes. For a sector size of 512 bytes, the minimum partition size varies based on the WL configuration: 20 KB for Performance mode and 28 KB for Safety mode (requiring 2 extra sectors). +* For a partition with wear leveling enabled, 4 sectors will be reserved for wear-leveling operations, and 4 sectors will be used by the FATFS (1 reserved sector, 1 FAT sector, 1 root directory sector and 1 data sector). +* Increasing the partition size will allocate additional data sectors, allowing for more storage space. +* For partition sizes less than 528 KB, 1 root directory sector will be allocated; for larger partitions, 4 root directory sectors will be used. +* By default, two FAT sectors are created, increasing the partition size by one sector to accommodate the extra FAT sector. To enable a single FAT sector, configure the `use_one_fat` option in `struct esp_vfs_fat_mount_config_t` (see :component_file:`fatfs/vfs/esp_vfs_fat.h`). Enabling this option allows the minimum partition size to be reduced to 32 KB. +* The general formula for calculating the partition size for a wear-leveled partition is:: + + partition_size = Wear-levelling sectors * FLASH_SEC_SIZE + FATFS partition sectors * FAT_SEC_SIZE + + Where: + + - Wear-leveling sectors are fixed at 4 + - FLASH_SEC_SIZE is 4096 bytes + - FATFS partition sectors include: 1 reserved sector + FAT sectors + root directory sectors + data sectors + - FAT_SEC_SIZE can be either 512 bytes or 4096 bytes, depending on the configuration + +* For read-only partitions without wear leveling enabled and a sector size of 512 bytes, the minimum partition size can be reduced to as low as 2 KB. + +Please refer :doc:`File System Considerations <../../api-guides/file-system-considerations>` for further details. + +Application Examples +-------------------- + +- :example:`storage/fatfs/getting_started` demonstrates the minimal setup required to store persistent data on SPI flash using the FatFS, including mounting the file system, opening a file, performing basic read and write operations, and unmounting the file system. + +- :example:`storage/fatfs/fs_operations` demonstrates more advanced FatFS operations, including reading and writing files, creating, moving, and deleting files and directories, and inspecting file details. + +- :example:`storage/fatfs/ext_flash` demonstrates how to operate an external SPI flash formatted with FatFS, including initializing the SPI bus, configuring the flash chip, registering it as a partition, and performing read and write operations. + High-level API Reference ------------------------ diff --git a/docs/en/api-reference/storage/fatfsgen.rst b/docs/en/api-reference/storage/fatfsgen.rst index 0d6218e96073..4bbbd1e2ebcf 100644 --- a/docs/en/api-reference/storage/fatfsgen.rst +++ b/docs/en/api-reference/storage/fatfsgen.rst @@ -219,3 +219,8 @@ Date and Time in FAT File System The FAT file system protocol used by ESP-IDF does not preserve the date or time on the chips' media, so all the images extracted from the device have the same default timestamp for all the FAT-specified date-time fields (creation and the last modification timestamp as well as creation, last modification and last access dates). There are a couple of fields in the SFN entry describing time, such as **DIR_CrtTime** and **DIR_WrtTime**. Some fields are ignored by the FAT implementation used by ESP-IDF (see the file ``entry.py``). However, changes in the fields **DIR_WrtTime** and **DIR_WrtDate** are preserved in the chip. Both time and data entry are 16-bit, where the granularity of the time is 2 seconds. + +Application Examples +-------------------- + +- :example:`storage/fatfs/fatfsgen` demonstrates how to use the FatFS partition generation tool to automatically create a FatFS image from a host folder during the building process. diff --git a/docs/en/api-reference/storage/index.rst b/docs/en/api-reference/storage/index.rst index 19bf5b6b9291..f3f184270f26 100644 --- a/docs/en/api-reference/storage/index.rst +++ b/docs/en/api-reference/storage/index.rst @@ -37,22 +37,15 @@ For information about storage security, please refer to :doc:`Storage Security < wear-levelling storage-security.rst -.. list-table:: Code Examples for Storage API +Examples +-------- + +.. list-table:: NVS API examples :widths: 25 75 :header-rows: 0 * - **Code Example** - **Description** - * - :doc:`fatfs` - - - * - :example:`wear_leveling ` - - Demonstrates using FATFS over wear leveling on internal flash. - * - :example:`ext_flash_fatfs ` - - Demonstrates using FATFS over wear leveling on external flash. - * - :example:`fatfsgen ` - - Demonstrates the capabilities of Python-based tooling for FATFS images available on host computers. - * - :doc:`nvs_flash` - - * - :example:`nvs_rw_blob ` - Shows the use of the C-style API to read and write blob data types in NVS flash. * - :example:`nvs_rw_value ` @@ -61,20 +54,59 @@ For information about storage security, please refer to :doc:`Storage Security < - Shows the use of the C++-style API to read and write integer data types in NVS flash. * - :example:`nvsgen ` - Demonstrates how to use the Python-based NVS image generation tool to create an NVS partition image from the contents of a CSV file. - * - :doc:`spiffs` - - + +.. list-table:: Common Filesystem API + :widths: 25 75 + :header-rows: 0 + + * - **Code Example** + - **Description** + * - :example:`fatfs/getting_started ` + - Demonstrates basic common file API (stdio.h) usage over internal flash using FATFS. + * - :example:`fatfs/fs_operations ` + - Demonstrates POSIX API for filesystem manipulation, such as moving, removing and renaming files. + +.. list-table:: FATFS API examples + :widths: 25 75 + :header-rows: 0 + + * - **Code Example** + - **Description** + * - :example:`fatfsgen ` + - Demonstrates the capabilities of Python-based tooling for FATFS images available on host computers. + * - :example:`ext_flash_fatfs ` + - Demonstrates using FATFS over wear leveling on external flash. + * - :example:`wear_leveling ` + - Demonstrates using FATFS over wear leveling on internal flash. + +.. list-table:: SPIFFS API examples + :widths: 25 75 + :header-rows: 0 + + * - **Code Example** + - **Description** * - :example:`spiffs ` - Shows the use of the SPIFFS API to initialize the filesystem and work with files using POSIX functions. * - :example:`spiffsgen ` - Demonstrates the capabilities of Python-based tooling for SPIFFS images available on host computers. - * - :doc:`partition` - - + +.. list-table:: Partition API examples + :widths: 25 75 + :header-rows: 0 + + * - **Code Example** + - **Description** * - :example:`partition_api ` - Provides an overview of API functions to look up particular partitions, perform basic I/O operations, and use partitions via CPU memory mapping. * - :example:`parttool ` - Demonstrates the capabilities of Python-based tooling for partition images available on host computers. - * - :doc:`vfs` - - + +.. list-table:: VFS related examples + :widths: 25 75 + :header-rows: 0 + + * - **Code Example** + - **Description** * - :example:`littlefs ` - Shows the use of the LittleFS component to initialize the filesystem and work with a file using POSIX functions. * - :example:`semihost_vfs ` diff --git a/docs/en/api-reference/storage/partition.rst b/docs/en/api-reference/storage/partition.rst index 173f5e08b651..9a38235e865e 100644 --- a/docs/en/api-reference/storage/partition.rst +++ b/docs/en/api-reference/storage/partition.rst @@ -24,6 +24,16 @@ This component provides API functions to enumerate partitions found in the parti - :cpp:func:`esp_partition_find_first` is a convenience function which returns the structure describing the first partition found by :cpp:func:`esp_partition_find`. - :cpp:func:`esp_partition_read`, :cpp:func:`esp_partition_write`, :cpp:func:`esp_partition_erase_range` are equivalent to :cpp:func:`esp_flash_read`, :cpp:func:`esp_flash_write`, :cpp:func:`esp_flash_erase_region`, but operate within partition boundaries. +Application Examples +-------------------- + +- :example:`storage/partition_api/partition_ops` demonstrates how to perform read, write, and erase operations on a partition table. + +- :example:`storage/parttool` demonstrates how to use the partitions tool to perform operations such as reading, writing, erasing partitions, retrieving partition information, and dumping the entire partition table. + +- :example:`storage/partition_api/partition_find` demonstrates how to search the partition table and return matching partitions based on set constraints such as partition type, subtype, and label/name. + +- :example:`storage/partition_api/partition_mmap` demonstrates how to configure the MMU, map a partition into memory address space for read operations, and verify the data written and read. See Also -------- diff --git a/docs/en/api-reference/storage/sdmmc.rst b/docs/en/api-reference/storage/sdmmc.rst index ec00684ecafe..f90ba43625f5 100644 --- a/docs/en/api-reference/storage/sdmmc.rst +++ b/docs/en/api-reference/storage/sdmmc.rst @@ -29,10 +29,16 @@ Host layer driver(s) implement the protocol layer driver by supporting these fun :align: center -Application Example -------------------- +Application Examples +-------------------- -An example which combines the SDMMC driver with the FATFS library is provided in the :example:`storage/sd_card` directory of ESP-IDF examples. This example initializes the card, then writes and reads data from it using POSIX and C library APIs. See README.md file in the example directory for more information. +.. list:: + + :SOC_SDMMC_HOST_SUPPORTED: - :example:`storage/sd_card/sdmmc` demonstrates how to operate an SD card formatted with the FatFS file system via the SDMMC interface. + + :SOC_SDMMC_HOST_SUPPORTED: - :example:`storage/emmc` demonstrates how to operate an eMMC chip formatted with the FatFS file system via the SDMMC interface. + + :SOC_GPSPI_SUPPORTED: - :example:`storage/sd_card/sdspi` demonstrates how to operate an SD card formatted with the FatFS file system via the SPI interface. Protocol Layer API ------------------ diff --git a/docs/en/api-reference/storage/spiffs.rst b/docs/en/api-reference/storage/spiffs.rst index 2104ce9dc04b..28ab0704556f 100644 --- a/docs/en/api-reference/storage/spiffs.rst +++ b/docs/en/api-reference/storage/spiffs.rst @@ -65,7 +65,7 @@ There are cases where the contents of the base directory itself is generated at spiffs_create_partition_image(my_spiffs_partition my_folder DEPENDS dep) -For an example, see :example:`storage/spiffsgen`. +For an example, see :example:`storage/spiffsgen`. This example demonstrates how to use the SPIFFS image generation tool to automatically create an SPIFFS image from a host folder during building. ``mkspiffs`` ^^^^^^^^^^^^ diff --git a/docs/en/api-reference/storage/vfs.rst b/docs/en/api-reference/storage/vfs.rst index 44b130754634..b8e4bd3c7537 100644 --- a/docs/en/api-reference/storage/vfs.rst +++ b/docs/en/api-reference/storage/vfs.rst @@ -44,7 +44,7 @@ Case 1: API functions are declared without an extra context pointer (the FS driv .write = &myfs_write, // ... other members initialized - // When registering FS, context pointer (third argument) is NULL: + // When registering FS, context pointer (the third argument) is NULL: ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL)); Case 2: API functions are declared with an extra context pointer (the FS driver supports multiple instances):: @@ -141,7 +141,9 @@ A socket VFS driver needs to be registered with the following functions defined: Please see :component_file:`lwip/port/esp32xx/vfs_lwip.c` for a reference socket driver implementation using LWIP. .. note:: + If you use :cpp:func:`select` for socket file descriptors only then you can disable the :ref:`CONFIG_VFS_SUPPORT_SELECT` option to reduce the code size and improve performance. + You should not change the socket driver during an active :cpp:func:`select` call or you might experience some undefined behavior. Paths @@ -192,6 +194,17 @@ Standard I/O streams (``stdin``, ``stdout``, ``stderr``) are mapped to file desc Note that creating an eventfd with ``EFD_SUPPORT_ISR`` will cause interrupts to be temporarily disabled when reading, writing the file and during the beginning and the ending of the ``select()`` when this file is set. + +Minified VFS +------------ + +To minimize RAM usage, an alternative version of :cpp:func:`esp_vfs_register` function, :cpp:func:`esp_vfs_register_fs` is provided. This version accepts :cpp:class:`esp_vfs_fs_ops_t` instead of :cpp:class:`esp_vfs_t` alongside separate argument for OR-ed flags. Unlike :cpp:func:`esp_vfs_register`, it can handle statically allocated struct, as long as the ``ESP_VFS_FLAG_STATIC`` is provided. + +The :cpp:class:`esp_vfs_fs_ops_t` is split into separate structs based on features (directory operations, select support, termios support, ...). The main struct contains the basic functions (``read``, ``write``, ...), alongside pointers to the feature-specific structs. These pointers can be ``NULL`` indicating lack of support for all the functions provided by that struct, which decreases the required memory. + +Internally the VFS component uses this version of API, with additional steps to convert the :cpp:class:`esp_vfs_t` to :cpp:class:`esp_vfs_fs_ops_t` upon registration. + + Well Known VFS Devices ---------------------- @@ -208,11 +221,15 @@ Application Examples - :example:`system/select` demonstrates how to use synchronous I/O multiplexing with the ``select()`` function, using UART and socket file descriptors, and configuring both to act as loopbacks to receive messages sent from other tasks. +- :example:`storage/semihost_vfs` demonstrates how to use the semihosting VFS driver, including registering a host directory, redirecting stdout from UART to a file on the host, and reading and printing the content of a text file. + API Reference ------------- .. include-build-file:: inc/esp_vfs.inc +.. include-build-file:: inc/esp_vfs_ops.inc + .. include-build-file:: inc/esp_vfs_dev.inc .. include-build-file:: inc/uart_vfs.inc diff --git a/docs/en/api-reference/storage/wear-levelling.rst b/docs/en/api-reference/storage/wear-levelling.rst index b1f46f3f1228..67d01488c9a7 100644 --- a/docs/en/api-reference/storage/wear-levelling.rst +++ b/docs/en/api-reference/storage/wear-levelling.rst @@ -6,10 +6,10 @@ See Also - :doc:`./fatfs` - :doc:`../../api-guides/partition-tables` -Application Example -------------------- +Application Examples +-------------------- -An example that combines the wear levelling driver with the FATFS library is provided in the :example:`storage/wear_levelling` directory. This example initializes the wear levelling driver, mounts FatFs partition, as well as writes and reads data from it using POSIX and C library APIs. See :example_file:`storage/wear_levelling/README.md` for more information. +- :example:`storage/wear_levelling` demonstrates how to use the wear levelling library and FatFS library to store files in a partition, as well as write and read data from these files using POSIX and C library APIs. High-level API Reference ------------------------ diff --git a/docs/en/api-reference/system/chip_revision.rst b/docs/en/api-reference/system/chip_revision.rst index 1af4903cc3fe..e3e489555842 100644 --- a/docs/en/api-reference/system/chip_revision.rst +++ b/docs/en/api-reference/system/chip_revision.rst @@ -110,7 +110,7 @@ Below is the information about troubleshooting when the chip revision fails the Troubleshooting ^^^^^^^^^^^^^^^ -1. If the 2nd stage bootloader is run on a chip revision smaller than minimum revision specified in the image (i.e., the application), a reboot occurs. The following message will be printed: +1. If the second stage bootloader is run on a chip revision smaller than minimum revision specified in the image (i.e., the application), a reboot occurs. The following message will be printed: .. code-block:: none @@ -132,7 +132,7 @@ To resolve this issue, update ESP-IDF to a newer version that supports the chip' Representing Revision Requirements of a Binary Image ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For the chip revision, the 2nd stage bootloader and the application binary images contain the :cpp:type:`esp_image_header_t` header, which stores information specifying the chip revisions that the image is permitted to run on. This header has 3 fields related to the chip revisions: +For the chip revision, the second stage bootloader and the application binary images contain the :cpp:type:`esp_image_header_t` header, which stores information specifying the chip revisions that the image is permitted to run on. This header has 3 fields related to the chip revisions: - ``min_chip_rev`` - Minimum chip MAJOR revision required by image (but for ESP32-C3 it is MINOR revision). Its value is determined by :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN`. - ``min_chip_rev_full`` - Minimum chip MINOR revision required by image in format: ``major * 100 + minor``. Its value is determined by :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN`. @@ -148,11 +148,11 @@ Maximum And Minimum Revision Restrictions The order for checking the minimum and maximum revisions during application boot up is as follows: -1. The 1st stage bootloader (ROM bootloader) does not check minimum and maximum revision fields from :cpp:type:`esp_image_header_t` before running the 2nd stage bootloader. +1. The first stage (ROM) bootloader does not check minimum and maximum revision fields from :cpp:type:`esp_image_header_t` before running the 2nd stage bootloader. -2. The initialization phase of the 2nd stage bootloader checks that the 2nd stage bootloader itself can be launched on the chip of this revision. It extracts the minimum revision from the header of the bootloader image and checks against the chip revision from eFuses. If the chip revision is less than the minimum revision, the bootloader refuses to boot up and aborts. The maximum revision is not checked at this phase. +2. The initialization phase of the second stage bootloader checks that the second stage bootloader itself can be launched on the chip of this revision. It extracts the minimum revision from the header of the bootloader image and checks against the chip revision from eFuses. If the chip revision is less than the minimum revision, the bootloader refuses to boot up and aborts. The maximum revision is not checked at this phase. -3. Then the 2nd stage bootloader checks the revision requirements of the application. It extracts the minimum and maximum revisions of the chip from the application image header, and the eFuse block from the segment header. Then the bootloader checks these versions against the chip and eFuse block revision from eFuses. If the these revisions are less than their minimum revision or higher than the maximum revision, the bootloader refuses to boot up and aborts. However, if the ignore maximum revision bit is set, the maximum revision constraint can be ignored. The ignore bits are set by the customer themselves when there is confirmation that the software is able to work with this chip revision or eFuse block revision. +3. Then the second stage bootloader checks the revision requirements of the application. It extracts the minimum and maximum revisions of the chip from the application image header, and the eFuse block from the segment header. Then the bootloader checks these versions against the chip and eFuse block revision from eFuses. If the these revisions are less than their minimum revision or higher than the maximum revision, the bootloader refuses to boot up and aborts. However, if the ignore maximum revision bit is set, the maximum revision constraint can be ignored. The ignore bits are set by the customer themselves when there is confirmation that the software is able to work with this chip revision or eFuse block revision. 4. Furthermore, at the OTA update stage, the running application checks if the new software matches the chip revision and eFuse block revision. It extracts the minimum and maximum chip revisions from the header of the new application image and the eFuse block constraints from the application description to check against the these revisions from eFuses. It checks for revisions matching in the same way that the bootloader does, so that the chip and eFuse block revisions are between their min and max revisions (logic of ignoring max revision also applies). diff --git a/docs/en/api-reference/system/mem_alloc.rst b/docs/en/api-reference/system/mem_alloc.rst index 5641ef8254be..dbe30659a0b8 100644 --- a/docs/en/api-reference/system/mem_alloc.rst +++ b/docs/en/api-reference/system/mem_alloc.rst @@ -105,7 +105,7 @@ DMA-Capable Memory Use the ``MALLOC_CAP_DMA`` flag to allocate memory which is suitable for use with hardware DMA engines (for example SPI and I2S). This capability flag excludes any external PSRAM. -.. only SOC_SPIRAM_SUPPORTED and not esp32:: +.. only:: SOC_SPIRAM_SUPPORTED and not esp32 The EDMA hardware feature allows DMA buffers to be placed in external PSRAM, but there may be additional alignment constraints. Consult the {IDF_TARGET_NAME} Technical Reference Manual for details. To allocate a DMA-capable external memory buffer, use the ``MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA`` capabilities flags; the heap allocator will take care of alignment requirements imposed by the cache and DMA subsystems. If a peripheral has additional alignment requirements, you can use :cpp:func:`heap_caps_aligned_alloc` with the necessary alignment specified. diff --git a/docs/en/api-reference/system/ota.rst b/docs/en/api-reference/system/ota.rst index e446a5ce88d5..b2b903e735e7 100644 --- a/docs/en/api-reference/system/ota.rst +++ b/docs/en/api-reference/system/ota.rst @@ -19,7 +19,7 @@ OTA Data Partition An OTA data partition (type ``data``, subtype ``ota``) must be included in the :doc:`../../api-guides/partition-tables` of any project which uses the OTA functions. -For factory boot settings, the OTA data partition should contain no data (all bytes erased to 0xFF). In this case, the ESP-IDF software bootloader will boot the factory app if it is present in the partition table. If no factory app is included in the partition table, the first available OTA slot (usually ``ota_0``) is booted. +For factory boot settings, the OTA data partition should contain no data (all bytes erased to 0xFF). In this case, the ESP-IDF second stage bootloader boots the factory app if it is present in the partition table. If no factory app is included in the partition table, the first available OTA slot (usually ``ota_0``) is booted. After the first OTA update, the OTA data partition is updated to specify which OTA app slot partition should be booted next. @@ -344,7 +344,7 @@ See Also Application Examples -------------------- -- :example:`system/ota/native_ota_example` demonstrates how to use the `app_update` component's APIs for native Over-the-Air (OTA) updates on {IDF_TARGET_NAME}. For the applicable SoCs, please refer to :example_file:`system/ota/native_ota_example/README.md`. +- :example:`system/ota/native_ota_example` demonstrates how to use the `app_update` component's APIs for native over-the-air (OTA) updates on {IDF_TARGET_NAME}. For applicable SoCs, please refer to :example_file:`system/ota/native_ota_example/README.md`. - :example:`system/ota/otatool` demonstrates how to use the OTA tool to perform operations such as reading, writing, and erasing OTA partitions, switching boot partitions, and switching to factory partition. For more information, please refer to :example_file:`system/ota/otatool/README.md`. diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index da52d19b09f8..2c203fbd65cb 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -141,40 +141,44 @@ The following peripheral drivers are not aware of DFS yet. Applications need to If :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` is enabled, when the driver initializes the peripheral, the driver will register the working register context of the peripheral to the sleep retention link. Before entering sleep, the ``REG_DMA`` peripheral reads the configuration in the sleep retention link, and back up the register context to memory according to the configuration. ``REG_DMA`` also restores context from memory to peripheral registers on wakeup. - Currently ESP-IDF supports Light-sleep context retention for the following peripherals: + Currently ESP-IDF supports Light-sleep context retention for the following peripherals. Their context is automatically restored, or they provide some option for the user to enable this feature and goes into peripheral power down mode. .. list:: - INT_MTX - TEE/APM - IO_MUX / GPIO - - Timer Group 0 & Timer Group 1 - - SPI0/1 + - MSPI (SPI0/1) - SYSTIMER + :SOC_TIMER_SUPPORT_SLEEP_RETENTION: - GPTimer :SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT + :SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM + :SOC_LEDC_SUPPORT_SLEEP_RETENTION: - LEDC :SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C + :SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S :SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs + :SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION: - Temperature Sensor + :SOC_TWAI_SUPPORT_SLEEP_RETENTION: - All TWAIs + :SOC_PARLIO_SUPPORT_SLEEP_RETENTION: - PARL_IO + :SOC_SPI_SUPPORT_SLEEP_RETENTION: - All GPSPIs - The following peripherals are not yet supported: + Some peripherals haven't support Light-sleep context retention, or it cannot survive from the register lose. They will prevent the power-down of peripherals even when the feature is enabled. + + .. list:: + + :SOC_SDIO_SLAVE_SUPPORTED: - SDIO Slave + + The following peripherals (and those not listed in any group of this section) are not yet supported. If your application uses these peripherals, they may not work well after waking up from sleep. .. list:: - - ETM - ASSIST_DEBUG - Trace - Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA - - SPI2 - - I2S - PCNT - USB-Serial-JTAG - - TWAI - - LEDC - MCPWM - SARADC - - SDIO - - PARL_IO - - For peripherals that do not support Light-sleep context retention, if the Power management is enabled, the ``ESP_PM_NO_LIGHT_SLEEP`` lock should be held when the peripheral is working to avoid losing the working context of the peripheral when entering sleep. .. note:: diff --git a/docs/en/api-reference/system/pthread.rst b/docs/en/api-reference/system/pthread.rst index f78a8fbe6e78..894e1a659efa 100644 --- a/docs/en/api-reference/system/pthread.rst +++ b/docs/en/api-reference/system/pthread.rst @@ -183,6 +183,7 @@ Message Queues ^^^^^^^^^^^^^^ The message queue implementation is based on the `FreeRTOS-Plus-POSIX `_ project. Message queues are not made available in any filesystem on ESP-IDF. Message priorities are not supported. + The following API functions of the POSIX message queue specification are implemented: * `mq_open() `_ @@ -191,7 +192,7 @@ The following API functions of the POSIX message queue specification are impleme - It has to begin with a leading slash. - It has to be no more than 255 + 2 characters long (including the leading slash, excluding the terminating null byte). However, memory for ``name`` is dynamically allocated internally, so the shorter it is, the fewer memory it will consume. - The ``mode`` argument is not implemented and is ignored. - - Supported ``oflags``: ``O_RDWR``, ``O_CREAT``, ``O_EXCL``, and ``O_NONBLOCK`` + - Supported ``oflags``: ``O_RDWR``, ``O_CREAT``, ``O_EXCL``, and ``O_NONBLOCK``. * `mq_close() `_ * `mq_unlink() `_ @@ -218,7 +219,7 @@ The following API functions of the POSIX message queue specification are impleme Building ........ -To use the POSIX message queue API, please add ``rt`` as a requirement in your component's ``CMakeLists.txt`` +To use the POSIX message queue API, please add ``rt`` as a requirement in your component's ``CMakeLists.txt``. .. note:: diff --git a/docs/en/api-reference/system/ulp-lp-core.rst b/docs/en/api-reference/system/ulp-lp-core.rst index 1e91c49c69d2..0e8a7ca2fec1 100644 --- a/docs/en/api-reference/system/ulp-lp-core.rst +++ b/docs/en/api-reference/system/ulp-lp-core.rst @@ -1,11 +1,11 @@ -ULP LP-Core Coprocessor Programming +ULP LP Core Coprocessor Programming =================================== :link_to_translation:`zh_CN:[中文]` -The ULP LP-Core (Low-power core) coprocessor is a variant of the ULP present in {IDF_TARGET_NAME}. It features ultra-low power consumption while also being able to stay powered on while the main CPU stays in low-power modes. This enables the LP-Core coprocessor to handle tasks like GPIO or sensor readings while the main CPU is in sleep mode, resulting in significant overall power savings for the entire system. +The ULP LP core (Low-power core) coprocessor is a variant of the ULP present in {IDF_TARGET_NAME}. It features ultra-low power consumption while also being able to stay powered on while the main CPU stays in low-power modes. This enables the LP core coprocessor to handle tasks like GPIO or sensor readings while the main CPU is in sleep mode, resulting in significant overall power savings for the entire system. -The ULP LP-Core coprocessor has the following features: +The ULP LP core coprocessor has the following features: * A RV32I (32-bit RISC-V ISA) processor, with the multiplication/division (M), atomic (A), and compressed (C) extensions. * Interrupt controller. @@ -13,15 +13,15 @@ The ULP LP-Core coprocessor has the following features: * Can access all of the High-power (HP) SRAM and peripherals when the entire system is active. * Can access the Low-power (LP) SRAM and peripherals when the HP system is in sleep mode. -Compiling Code for the ULP LP-Core +Compiling Code for the ULP LP Core ---------------------------------- -The ULP LP-Core code is compiled together with your ESP-IDF project as a separate binary and automatically embedded into the main project binary. There are two ways to achieve this: +The ULP LP core code is compiled together with your ESP-IDF project as a separate binary and automatically embedded into the main project binary. There are two ways to achieve this: Using ``ulp_embed_binary`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -1. Place the ULP LP-Core code, written in C or assembly (with the ``.S`` extension), in a dedicated directory within the component directory, such as ``ulp/``. +1. Place the ULP LP core code, written in C or assembly (with the ``.S`` extension), in a dedicated directory within the component directory, such as ``ulp/``. 2. After registering the component in the ``CMakeLists.txt`` file, call the ``ulp_embed_binary`` function. Here is an example: @@ -41,7 +41,7 @@ The first argument to ``ulp_embed_binary`` specifies the ULP binary name. The na Using a Custom CMake Project ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -It is also possible to create a custom CMake project for the LP-Core. This gives more control over the build process and allows you to set compile options, link external libraries and all other things that are possible with a regular CMake project. +It is also possible to create a custom CMake project for the LP core. This gives more control over the build process and allows you to set compile options, link external libraries and all other things that are possible with a regular CMake project. To do this, add the ULP project as an external project in your component ``CMakeLists.txt`` file: @@ -90,7 +90,7 @@ Building Your Project To compile and build your project: -1. Enable both :ref:`CONFIG_ULP_COPROC_ENABLED` and :ref:`CONFIG_ULP_COPROC_TYPE` in menuconfig, and set :ref:`CONFIG_ULP_COPROC_TYPE` to ``CONFIG_ULP_COPROC_TYPE_LP_CORE``. The :ref:`CONFIG_ULP_COPROC_RESERVE_MEM` option reserves RTC memory for the ULP, and must be set to a value big enough to store both the ULP LP-Core code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one. +1. Enable both :ref:`CONFIG_ULP_COPROC_ENABLED` and :ref:`CONFIG_ULP_COPROC_TYPE` in menuconfig, and set :ref:`CONFIG_ULP_COPROC_TYPE` to ``CONFIG_ULP_COPROC_TYPE_LP_CORE``. The :ref:`CONFIG_ULP_COPROC_RESERVE_MEM` option reserves RTC memory for the ULP, and must be set to a value big enough to store both the ULP LP core code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one. 2. Build the application as usual (e.g., ``idf.py app``). @@ -113,12 +113,12 @@ During the build process, the following steps are taken to build ULP program: .. _ulp-lp-core-access-variables: -Accessing the ULP LP-Core Program Variables +Accessing the ULP LP Core Program Variables ------------------------------------------- -Global symbols defined in the ULP LP-Core program may be used inside the main program. +Global symbols defined in the ULP LP core program may be used inside the main program. -For example, the ULP LP-Core program may define a variable ``measurement_count`` which defines the number of GPIO measurements the program needs to make before waking up the chip from Deep-sleep. +For example, the ULP LP core program may define a variable ``measurement_count`` which defines the number of GPIO measurements the program needs to make before waking up the chip from Deep-sleep. .. code-block:: c @@ -132,7 +132,7 @@ For example, the ULP LP-Core program may define a variable ``measurement_count`` ...do something. } -The main program can access the global ULP LP-Core program variables as the build system makes this possible by generating the ``${ULP_APP_NAME}.h`` and ``${ULP_APP_NAME}.ld`` files which define the global symbols present in the ULP LP-Core program. Each global symbol defined in the ULP LP-Core program is included in these files and are prefixed with ``ulp_``. +The main program can access the global ULP LP core program variables as the build system makes this possible by generating the ``${ULP_APP_NAME}.h`` and ``${ULP_APP_NAME}.ld`` files which define the global symbols present in the ULP LP core program. Each global symbol defined in the ULP LP core program is included in these files and are prefixed with ``ulp_``. The header file contains the declaration of the symbol: @@ -148,7 +148,7 @@ The generated linker script file defines the locations of symbols in LP_MEM: PROVIDE ( ulp_measurement_count = 0x50000060 ); -To access the ULP LP-Core program variables from the main program, the generated header file should be included using an ``include`` statement. This allows the ULP LP-Core program variables to be accessed as regular variables. +To access the ULP LP core program variables from the main program, the generated header file should be included using an ``include`` statement. This allows the ULP LP core program variables to be accessed as regular variables. .. code-block:: c @@ -160,15 +160,15 @@ To access the ULP LP-Core program variables from the main program, the generated .. note:: - Variables declared in the global scope of the LP-Core program reside in either the ``.bss`` or ``.data`` section of the binary. These sections are initialized when the LP-Core binary is loaded and executed. Accessing these variables from the main program on the HP-Core before the first LP-Core run may result in undefined behavior. + Variables declared in the global scope of the LP core program reside in either the ``.bss`` or ``.data`` section of the binary. These sections are initialized when the LP core binary is loaded and executed. Accessing these variables from the main program on the HP-Core before the first LP core run may result in undefined behavior. -Starting the ULP LP-Core Program +Starting the ULP LP Core Program -------------------------------- -To run a ULP LP-Core program, the main application needs to load the ULP program into RTC memory using the :cpp:func:`ulp_lp_core_load_binary` function, and then start it using the :cpp:func:`ulp_lp_core_run` function. +To run a ULP LP core program, the main application needs to load the ULP program into RTC memory using the :cpp:func:`ulp_lp_core_load_binary` function, and then start it using the :cpp:func:`ulp_lp_core_run` function. -Each ULP LP-Core program is embedded into the ESP-IDF application as a binary blob. The application can reference this blob and load it in the following way (supposed ULP_APP_NAME was defined to ``ulp_app_name``): +Each ULP LP core program is embedded into the ESP-IDF application as a binary blob. The application can reference this blob and load it in the following way (supposed ULP_APP_NAME was defined to ``ulp_app_name``): .. code-block:: c @@ -191,17 +191,17 @@ Once the program is loaded into LP memory, the application can be configured and ESP_ERROR_CHECK( ulp_lp_core_run(&cfg) ); -ULP LP-Core Program Flow +ULP LP Core Program Flow ------------------------ -How the ULP LP-Core coprocessor is started depends on the wake-up source selected in :cpp:type:`ulp_lp_core_cfg_t`. The most common use-case is for the ULP to periodically wake up, do some measurements before either waking up the main CPU or going back to sleep again. +How the ULP LP core coprocessor is started depends on the wake-up source selected in :cpp:type:`ulp_lp_core_cfg_t`. The most common use-case is for the ULP to periodically wake up, do some measurements before either waking up the main CPU or going back to sleep again. The ULP has the following wake-up sources: - * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU` - LP Core can be woken up by the HP CPU. - * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER` - LP Core can be woken up by the LP timer. - * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_ETM` - LP Core can be woken up by a ETM event. (Not yet supported) - * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_IO` - LP Core can be woken up when LP IO level changes. (Not yet supported) - * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_UART` - LP Core can be woken up after receiving a certain number of UART RX pulses. (Not yet supported) + * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU` - LP core can be woken up by the HP CPU. + * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER` - LP core can be woken up by the LP timer. + * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_ETM` - LP core can be woken up by a ETM event. (Not yet supported) + * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_IO` - LP core can be woken up when LP IO level changes. (Not yet supported) + * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_UART` - LP core can be woken up after receiving a certain number of UART RX pulses. (Not yet supported) When the ULP is woken up, it will go through the following steps: @@ -215,10 +215,10 @@ When the ULP is woken up, it will go through the following steps: #. Call :cpp:func:`ulp_lp_core_halt` -ULP LP-Core Peripheral Support +ULP LP Core Peripheral Support ------------------------------ -To enhance the capabilities of the ULP LP-Core coprocessor, it has access to peripherals that operate in the low-power domain. The ULP LP-Core coprocessor can interact with these peripherals when the main CPU is in sleep mode, and can wake up the main CPU once a wake-up condition is reached. The following peripherals are supported: +To enhance the capabilities of the ULP LP core coprocessor, it has access to peripherals that operate in the low-power domain. The ULP LP core coprocessor can interact with these peripherals when the main CPU is in sleep mode, and can wake up the main CPU once a wake-up condition is reached. The following peripherals are supported: .. list:: @@ -229,10 +229,10 @@ To enhance the capabilities of the ULP LP-Core coprocessor, it has access to per .. only:: CONFIG_ESP_ROM_HAS_LP_ROM - ULP LP-Core ROM + ULP LP Core ROM --------------- - The ULP LP-Core ROM is a small pre-built piece of code located in LP-ROM, which can't be modified. Similar to the bootloader ROM code ran by the main CPU, this code is executed when the ULP LP-Core coprocessor is started. The ROM code initializes the ULP LP-Core coprocessor and then jumps to the user program. The ROM code also prints boot messages if the LP UART has been initialized. + The ULP LP core ROM is a small pre-built piece of code located in LP-ROM, which can't be modified. Similar to the bootloader ROM code ran by the main CPU, this code is executed when the ULP LP core coprocessor is started. The ROM code initializes the ULP LP core coprocessor and then jumps to the user program. The ROM code also prints boot messages if the LP UART has been initialized. The ROM code is not executed if :cpp:member:`ulp_lp_core_cfg_t::skip_lp_rom_boot` is set to true. This is useful when you need the ULP to wake-up as quickly as possible and the extra overhead of initializing and printing is unwanted. @@ -244,12 +244,12 @@ To enhance the capabilities of the ULP LP-Core coprocessor, it has access to per Since these functions are already present in LP-ROM no matter what, using these in your program allows you to reduce the RAM footprint of your ULP application. -ULP LP-Core Interrupts +ULP LP Core Interrupts ---------------------- -The LP-Core coprocessor can be configured to handle interrupts from various sources. Examples of such interrupts could be LP IO low/high or LP timer interrupts. To register a handler for an interrupt, simply override any of the weak handlers provided by IDF. A complete list of handlers can be found in :component_file:`ulp_lp_core_interrupts.h `. For details on which interrupts are available on a specific target, please consult **{IDF_TARGET_NAME} Technical Reference Manual** [`PDF <{IDF_TARGET_TRM_EN_URL}#ulp>`__]. +The LP core coprocessor can be configured to handle interrupts from various sources. Examples of such interrupts could be LP IO low/high or LP timer interrupts. To register a handler for an interrupt, simply override any of the weak handlers provided by IDF. A complete list of handlers can be found in :component_file:`ulp_lp_core_interrupts.h `. For details on which interrupts are available on a specific target, please consult **{IDF_TARGET_NAME} Technical Reference Manual** [`PDF <{IDF_TARGET_TRM_EN_URL}#ulp>`__]. -For example, to override the handler for the LP IO interrupt, you can define the following function in your ULP LP-Core code: +For example, to override the handler for the LP IO interrupt, you can define the following function in your ULP LP core code: .. code-block:: c @@ -260,39 +260,40 @@ For example, to override the handler for the LP IO interrupt, you can define the :c:macro:`LP_CORE_ISR_ATTR` is a macro that is used to define the interrupt handler function. This macro ensures that registers are saved and restored correctly when the interrupt handler is called. -In addition to configuring the interrupt related registers for the interrupt source you want to handle, you also need to enable the interrupts globally in the LP-Core interrupt controller. This can be done using the :cpp:func:`ulp_lp_core_intr_enable` function. +In addition to configuring the interrupt related registers for the interrupt source you want to handle, you also need to enable the interrupts globally in the LP core interrupt controller. This can be done using the :cpp:func:`ulp_lp_core_intr_enable` function. -ULP LP-Core Clock Configuration +ULP LP Core Clock Configuration ------------------------------- + {IDF_TARGET_XTAL_FREQ:default="Not updated", esp32c5="48 MHz", esp32p4="40 MHz"} -The ULP LP-Core clock source is based on the system clock ``LP_FAST_CLK``, see `TRM <{IDF_TARGET_TRM_EN_URL}>`__ > ``Reset and Clock`` for more details. +The ULP LP Core clock source is based on the system clock ``LP_FAST_CLK``, see `TRM <{IDF_TARGET_TRM_EN_URL}>`__ > ``Reset and Clock`` for more details. .. only:: SOC_CLK_LP_FAST_SUPPORT_XTAL - On {IDF_TARGET_NAME} ``LP_FAST_CLK`` supports using the external {IDF_TARGET_XTAL_FREQ} crystal (XTAL) as the source for ``LP_FAST_CLK``, which allows the ULP LP-Core to run at a higher frequency than with the default ``RTC_FAST_CLOCK`` which runs at around 20 MHz. The drawback is that this clock is normally powered down during sleep to reduce power consumption, with it selected XTAL will also stay powered on during sleep, increasing power consumption. If you only plan to use the LP-Core as a co-processor while the HP-Core is active, then this option can be used to increase both the performance and the frequency stability of the LP-Core. + On {IDF_TARGET_NAME}, ``LP_FAST_CLK`` supports using the external {IDF_TARGET_XTAL_FREQ} crystal (XTAL) as its clock source. This allows the ULP LP Core to run at a higher frequency than with the default ``RTC_FAST_CLOCK``, which runs at around 20 MHz. However, there is a trade-off: this clock is normally powered down during sleep to reduce power consumption, but if XTAL is selected as the source, it will remain powered up during sleep, which increases power consumption. If you only plan to use the LP Core as a coprocessor while the HP Core is active, then selecting XTAL can enhance both the performance and frequency stability of the LP Core. - To enable this feature set :ref:`CONFIG_RTC_FAST_CLK_SRC` to ``CONFIG_RTC_FAST_CLK_SRC_XTAL``. + To enable this feature, set :ref:`CONFIG_RTC_FAST_CLK_SRC` to ``CONFIG_RTC_FAST_CLK_SRC_XTAL``. Debugging ULP LP-Core Applications ---------------------------------- -When programming the LP-Core, it can sometimes be challenging to figure out why the program is not behaving as expected. Here are some strategies to help you debug your LP-Core program: +When programming the LP core, it can sometimes be challenging to figure out why the program is not behaving as expected. Here are some strategies to help you debug your LP core program: -* Use the LP-UART to print: the LP-Core has access to the LP-UART peripheral, which can be used for printing information independently of the main CPU sleep state. See :example:`system/ulp/lp_core/lp_uart/lp_uart_print` for an example of how to use this driver. +* Use the LP-UART to print: the LP core has access to the LP-UART peripheral, which can be used for printing information independently of the main CPU sleep state. See :example:`system/ulp/lp_core/lp_uart/lp_uart_print` for an example of how to use this driver. -* Routing :cpp:func:`lp_core_printf` to the HP-Core console UART with :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`. This allows you to easily print LP-Core information to the already connected HP-Core console UART. The drawback of this approach is that it requires the main CPU to be awake and since there is no synchronization between the LP and HP cores, the output may be interleaved. +* Routing :cpp:func:`lp_core_printf` to the HP-Core console UART with :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`. This allows you to easily print LP core information to the already connected HP-Core console UART. The drawback of this approach is that it requires the main CPU to be awake and since there is no synchronization between the LP and HP cores, the output may be interleaved. * Share program state through shared variables: as described in :ref:`ulp-lp-core-access-variables`, both the main CPU and the ULP core can easily access global variables in RTC memory. Writing state information to such a variable from the ULP and reading it from the main CPU can help you discern what is happening on the ULP core. The downside of this approach is that it requires the main CPU to be awake, which will not always be the case. Keeping the main CPU awake might even, in some cases, mask problems, as some issues may only occur when certain power domains are powered down. -* Panic handler: the LP-Core has a panic handler that can dump the state of the LP-Core registers by the LP-UART when an exception is detected. To enable the panic handler, set the :ref:`CONFIG_ULP_PANIC_OUTPUT_ENABLE` option to ``y``. This option can be kept disabled to reduce LP-RAM usage by the LP-Core application. To recover a backtrace from the panic dump, it is possible to use esp-idf-monitor_., e.g.: +* Panic handler: the LP core has a panic handler that can dump the state of the LP core registers by the LP-UART when an exception is detected. To enable the panic handler, set the :ref:`CONFIG_ULP_PANIC_OUTPUT_ENABLE` option to ``y``. This option can be kept disabled to reduce LP-RAM usage by the LP core application. To recover a backtrace from the panic dump, it is possible to use esp-idf-monitor_., e.g.: .. code-block:: bash python -m esp_idf_monitor --toolchain-prefix riscv32-esp-elf- --target {IDF_TARGET_NAME} --decode-panic backtrace PATH_TO_ULP_ELF_FILE -Debugging ULP LP-Core Applications with GDB and OpenOCD +Debugging ULP LP Core Applications with GDB and OpenOCD ------------------------------------------------------- It is also possible to debug code running on LP core using GDB and OpenOCD as you usually do for HP cores, but it has some specifics and limitations. @@ -307,7 +308,7 @@ Run OpenOCD with special config file for LP core debugging support. And then run openocd -f board/{IDF_TARGET_PATH_NAME}-lpcore-builtin.cfg riscv32-esp-elf-gdb -x gdbinit -``gdbinit`` file contents with inline comments is below. For more details see the next section. +Below is the ``gdbinit`` file content with inline comments. For more details, see the next section. .. code-block:: bash @@ -339,17 +340,17 @@ LP Core Debugging Specifics .. list:: - #. For convenient debugging you may need to add `-O0` compile option for ULP app in its CMakeLists.txt. See :example:`system/ulp/lp_core/debugging/` how to do this. - :not esp32p4: #. LP core supports limited set of HW exceptions, so, for example, writing at address `0x0` will not cause a panic as it would be for the code running on HP core. This can be overcome to some extent by enabling undefined behavior sanitizer for LP core application, so `ubsan` can help to catch some errors. But note that it will increase code size significantly and it can happen that application won't fit into RTC RAM. To enable `ubsan` for ULP app add `-fsanitize=undefined -fno-sanitize=shift-base` compile option to its CMakeLists.txt. See :example:`system/ulp/lp_core/debugging/` how to do this. - #. To be able to debug program running on LP core debug info and symbols need to be loaded to GDB. It can be done via GDB command line or in ``gdbinit`` file. See section above. - #. Upon startup LP core application is loaded into RAM, so all SW breakpoints set before that moment will get overwritten. The best moment to set breakpoints for LP core application is to do this when LP core program reaches `main` function. - #. When using IDEs it can be that it does not support breakpoint actions/commands configuration shown in ``gdbinit`` above, so in this case you have to preset all breakpoints before debug session start and disable all of them except for ``main``. When program is stopped at ``main`` manually enable remaining breakpoints and resume execution. + #. For convenient debugging, you may need to add ``-O0`` compile option for ULP app in its ``CMakeLists.txt``. See :example:`system/ulp/lp_core/debugging/` on how to do this. + :not esp32p4: #. LP core supports limited set of HW exceptions, so, for example, writing at address `0x0` will not cause a panic as it would be for the code running on HP core. This can be overcome to some extent by enabling undefined behavior sanitizer for LP core application, so `ubsan` can help to catch some errors. But note that it will increase code size significantly and it can happen that application won't fit into RTC RAM. To enable `ubsan` for ULP app, add ``-fsanitize=undefined -fno-sanitize=shift-base`` compile option to its ``CMakeLists.txt``. See :example:`system/ulp/lp_core/debugging/` on how to do this. + #. To be able to debug program running on LP core, debugging information and symbols need to be loaded to GDB. It can be done via GDB command line or in ``gdbinit`` file. See section above. + #. Upon startup, LP core application is loaded into RAM, so all SW breakpoints set before that moment will get overwritten. The best moment to set breakpoints for LP core application is to do this when LP core program reaches `main` function. + #. When using IDEs, it may lack support for configuring breakpoint actions or commands shown in ``gdbinit`` above. Consequently, you have to preset all breakpoints before debug session start and disable all of them except for ``main``. When program stops at ``main``, enable the remaining breakpoints and resume execution manually. Limitations ~~~~~~~~~~~ -#. Currently debugging is not supported when either HP or LP core enters any sleep mode. So it limits available debugging scenarios. -#. FreeRTOS support in OpenOCD is disabled when debugging LP core, so you won't be able to see tasks running in the system. Instead there will be several threads representing HP and LP cores: +#. Currently, debugging is not supported when either HP or LP core enters any sleep mode. So it limits available debugging scenarios. +#. FreeRTOS support in OpenOCD is disabled when debugging LP core, so you won't be able to see tasks running in the system. Instead, there will be several threads representing HP and LP cores: .. code-block:: bash @@ -360,28 +361,23 @@ Limitations * 2 Thread 2 "{IDF_TARGET_PATH_NAME}.cpu1" (Name: {IDF_TARGET_PATH_NAME}.cpu1, state: breakpoint) do_things (max=1000000000) at /home/user/projects/esp/esp-idf/examples/system/ulp/lp_core/debugging/main/lp_core/main.c:21 -#. When setting HW breakpoint in GDB it is set on both cores, so the number of available HW breakpoints is limited to the number of them supported by LP core ({IDF_TARGET_SOC_CPU_BREAKPOINTS_NUM} for {IDF_TARGET_NAME}). -#. OpenOCD flash support is disabled. It does not matter for LP core application because it is run completely from RAM and GDB can use SW breakpoints for it. But if you want to set a breakpoint on function from flash used by the code running on HP core (e.g. `app_main`) you should request to set HW breakpoint explicitly via ``hb`` / ``thb`` GDB commands. -#. Since main and ULP programs are linked as separate binaries it is possible for them to have global symbols (functions, variables) with the same name. When you set breakpoint for such a functions using its name GDB will set breakpoints for all of them. It could lead to the problems when one of the function is located in the flash because currently flash support is disabled in OpenOCD when debugging LP core. In that case you can use source line or address based breakpoints. +#. When setting HW breakpoint in GDB, it is set on both cores, so the number of available HW breakpoints is limited to the number of them supported by LP core ({IDF_TARGET_SOC_CPU_BREAKPOINTS_NUM} for {IDF_TARGET_NAME}). +#. OpenOCD flash support is disabled. It does not matter for LP core application because it is run completely from RAM and GDB can use SW breakpoints for it. But if you want to set a breakpoint on function from flash used by the code running on HP core (e.g., `app_main`), you should request to set HW breakpoint explicitly via ``hb`` and ``thb`` GDB commands. +#. Since the main and ULP programs are linked as separate binaries, it is possible for them to have global symbols (such as functions or variables) with the same name. If you set a breakpoint using the function name, GDB will apply it to all instances of that function. This can cause issues if one of the functions is located in the flash, as OpenOCD currently doesn't support flash when debugging the LP core. In such cases, you can set breakpoints using the source line or the function's memory address instead. Application Examples -------------------- -* :example:`system/ulp/lp_core/gpio` polls GPIO while main CPU is in Deep-sleep. - -.. only:: esp32c6 - - * :example:`system/ulp/lp_core/lp_i2c` reads external I2C ambient light sensor (BH1750) while the main CPU is in Deep-sleep and wakes up the main CPU once a threshold is met. - -* :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` reads data written to a serial console and echoes it back. This example demonstrates the usage of the LP UART driver running on the LP core. - -* :example:`system/ulp/lp_core/lp_uart/lp_uart_print` shows how to print various statements from a program running on the LP core. - -* :example:`system/ulp/lp_core/interrupt` shows how to register an interrupt handler on the LP core to receive an interrupt triggered by the main CPU. -* :example:`system/ulp/lp_core/gpio_intr_pulse_counter` shows how to use GPIO interrupts to count pulses while the main CPU is in Deep-sleep mode. +.. list:: -* :example:`system/ulp/lp_core/build_system/` demonstrates how to include custom ``CMakeLists.txt`` file for the ULP app. -* :example:`system/ulp/lp_core/debugging` shows how to debug code running on LP core using GDB and OpenOCD. + - :example:`system/ulp/lp_core/gpio` polls GPIO while main CPU is in Deep-sleep. + :esp32c6: - :example:`system/ulp/lp_core/lp_i2c` reads external I2C ambient light sensor (BH1750) while the main CPU is in Deep-sleep and wakes up the main CPU once a threshold is met. + - :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` reads data written to a serial console and echoes it back. This example demonstrates the usage of the LP UART driver running on the LP core. + - :example:`system/ulp/lp_core/lp_uart/lp_uart_print` shows how to print various statements from a program running on the LP core. + - :example:`system/ulp/lp_core/interrupt` shows how to register an interrupt handler on the LP core to receive an interrupt triggered by the main CPU. + - :example:`system/ulp/lp_core/gpio_intr_pulse_counter` shows how to use GPIO interrupts to count pulses while the main CPU is in Deep-sleep mode. + - :example:`system/ulp/lp_core/build_system/` demonstrates how to include custom ``CMakeLists.txt`` file for the ULP app. + - :example:`system/ulp/lp_core/debugging` shows how to debug code running on LP core using GDB and OpenOCD. API Reference ------------- diff --git a/docs/en/get-started/flashing-troubleshooting.rst b/docs/en/get-started/flashing-troubleshooting.rst index 8664fe1ede6b..3c8ad87575ca 100644 --- a/docs/en/get-started/flashing-troubleshooting.rst +++ b/docs/en/get-started/flashing-troubleshooting.rst @@ -8,7 +8,7 @@ Failed to Connect {IDF_TARGET_STRAP_GPIO:default="[NEEDS TO BE UPDATED]", esp32="GPIO0", esp32s2="GPIO0", esp32s3="GPIO0", esp32c2="GPIO9", esp32c3="GPIO9", esp32c6="GPIO9", esp32h2="GPIO9", esp32p4="GPIO35"} -If you run the given command and see errors such as "Failed to connect", there might be several reasons for this. One of the reasons might be issues encountered by ``esptool.py``, the utility that is called by the build system to reset the chip, interact with the ROM bootloader, and flash firmware. One simple solution to try is to manually reset as described below. If it does not help, you can find more details about possible issues in the `esptool troubleshooting `_ page. +If you run the given command and see errors such as "Failed to connect", there might be several reasons for this. One of the reasons might be issues encountered by ``esptool.py``, the utility that is called by the build system to reset the chip, interact with the first stage (ROM) bootloader, and flash firmware. One simple solution to try is to manually reset as described below. If it does not help, you can find more details about possible issues in the `esptool troubleshooting `_ page. ``esptool.py`` resets {IDF_TARGET_NAME} automatically by asserting DTR and RTS control lines of the USB-to-UART bridge, i.e., FTDI or CP210x (for more information, see :doc:`establish-serial-connection`). The DTR and RTS control lines are in turn connected to ``{IDF_TARGET_STRAP_GPIO}`` and ``CHIP_PU`` (EN) pins of {IDF_TARGET_NAME}, thus changes in the voltage levels of DTR and RTS will boot {IDF_TARGET_NAME} into Firmware Download mode. As an example, check the `schematic `_ for the ESP32 DevKitC development board. diff --git a/docs/en/get-started/index.rst b/docs/en/get-started/index.rst index 31051267b3cd..935370c4b95a 100644 --- a/docs/en/get-started/index.rst +++ b/docs/en/get-started/index.rst @@ -108,19 +108,19 @@ If you have one of {IDF_TARGET_NAME} official development boards listed below, y :maxdepth: 1 ESP32-DevKitC + ESP32-DevKitM-1 ESP-WROVER-KIT ESP32-PICO-KIT ESP32-Ethernet-Kit ESP32-PICO-KIT-1 ESP32-PICO-DevKitM-2 - ESP32-DevKitM-1 <../hw-reference/esp32/user-guide-devkitm-1> .. only:: esp32s2 .. toctree:: :maxdepth: 1 - ESP32-S2-Saola-1 <../hw-reference/esp32s2/user-guide-saola-1-v1.2> + ESP32-S2-Saola-1 ESP32-S2-DevKitM-1 ESP32-S2-DevKitC-1 ESP32-S2-Kaluga-Kit @@ -139,8 +139,8 @@ If you have one of {IDF_TARGET_NAME} official development boards listed below, y .. toctree:: :maxdepth: 1 - ESP32-S3-DevKitC-1 <../hw-reference/esp32s3/user-guide-devkitc-1> - ESP32-S3-DevKitM-1 <../hw-reference/esp32s3/user-guide-devkitm-1> + ESP32-S3-DevKitC-1 + ESP32-S3-DevKitM-1 .. only:: esp32c2 diff --git a/docs/en/hw-reference/esp32/user-guide-devkitm-1.rst b/docs/en/hw-reference/esp32/user-guide-devkitm-1.rst deleted file mode 100644 index e0500316264d..000000000000 --- a/docs/en/hw-reference/esp32/user-guide-devkitm-1.rst +++ /dev/null @@ -1,335 +0,0 @@ -=============== -ESP32-DevKitM-1 -=============== - -:link_to_translation:`zh_CN:[中文]` - -This user guide will help you get started with ESP32-DevKitM-1 and will also provide more in-depth information. - -ESP32-DevKitM-1 is an ESP32-MINI-1/1U-based development board produced by Espressif. Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. Users can either connect peripherals with jumper wires or mount ESP32-DevKitM-1 on a breadboard. - - -+---------------------------+-------------------------------+ -| |ESP32-DevKitM-1 - front| | |ESP32-DevKitM-1 - isometric| | -+---------------------------+-------------------------------+ -| ESP32-DevKitM-1 - front | ESP32-DevKitM-1 - isometric | -+---------------------------+-------------------------------+ - -.. |ESP32-DevKitM-1 - front| image:: ../../../_static/esp32-DevKitM-1-front.png - -.. |ESP32-DevKitM-1 - isometric| image:: ../../../_static/esp32-DevKitM-1-isometric.png - - -The document consists of the following major sections: - -- `Getting started`_: Provides an overview of the ESP32-DevKitM-1 and hardware/software setup instructions to get started. -- `Hardware reference`_: Provides more detailed information about the ESP32-DevKitM-1's hardware. -- `Related Documents`_: Gives links to related documentation. - - -Getting Started -=============== - -This section describes how to get started with ESP32-DevKitM-1. It begins with a few introductory sections about the ESP32-DevKitM-1, then Section `Start Application Development`_ provides instructions on how to do the initial hardware setup and then how to flash firmware onto the ESP32-DevKitM-1. - - -Overview --------- - -This is a small and convenient development board that features: - -- `ESP32-MINI-1, or ESP32-MINI-1U module `_ -- USB-to-serial programming interface that also provides power supply for the board -- pin headers -- pushbuttons for reset and activation of Firmware Download mode -- a few other components - - -Contents and Packaging ----------------------- - -Retail Orders -^^^^^^^^^^^^^ - -If you order a few samples, each ESP32-DevKitM-1 comes in an individual package in either antistatic bag or any packaging depending on your retailer. - -For retail orders, please go to https://www.espressif.com/en/contact-us/get-samples. - - -Wholesale Orders -^^^^^^^^^^^^^^^^ - -If you order in bulk, the boards come in large cardboard boxes. - -For wholesale orders, please go to https://www.espressif.com/en/contact-us/sales-questions. - - -Description of Components -------------------------- - -The following figure and the table below describe the key components, interfaces and controls of the ESP32-DevKitM-1 board. We take the board with a ESP32-MINI-1 module as an example in the following sections. - - -.. figure:: ../../../_static/esp32-devkitm-1-v1-annotated-photo.png - :align: center - :alt: ESP32-DevKitM-1 - front - :figclass: align-center - - ESP32-DevKitM-1 - front - - -.. list-table:: - :widths: 25 75 - :header-rows: 1 - - * - Key Component - - Description - * - On-board module - - ESP32-MINI-1 module or ESP32-MINI-1U module. ESP32-MINI-1 comes with an on-board PCB antenna. ESP32-MINI-1U comes with an external antenna connector. The two modules both have a 4 MB flash in chip package. For details, please see `ESP32-MINI-1 & ESP32-MINI-1U Datasheet `_. - * - 5 V to 3.3 V LDO - - Power regulator converts 5 V to 3.3 V. - * - Boot Button - - Download button. Holding down **Boot** and then pressing **Reset** initiates Firmware Download mode for downloading firmware through the serial port. - * - Reset Button - - Reset Button - * - Micro-USB Port - - USB interface. Power supply for the board as well as the communication interface between a computer and the ESP32 chip. - * - USB-to-UART Bridge - - Single USB-UART bridge chip provides transfer rates up to 3 Mbps. - * - 3.3 V Power On LED - - Turns on when the USB is connected to the board. For details, please see the schematics in `Related Documents`_. - * - I/O Connector - - All available GPIO pins (except for the SPI bus for flash) are broken out to the pin headers on the board. Users can program ESP32 chip to enable multiple functions. - - -Start Application Development ------------------------------ - -Before powering up your ESP32-DevKitM-1, please make sure that it is in good condition with no obvious signs of damage. - - -Required Hardware -^^^^^^^^^^^^^^^^^ - -- ESP32-DevKitM-1 -- USB 2.0 cable (Standard-A to Micro-B) -- Computer running Windows, Linux, or macOS - - -Software Setup -^^^^^^^^^^^^^^ - -Please proceed to :doc:`../../get-started/index`, where Section :ref:`get-started-step-by-step` will quickly help you set up the development environment and then flash an application example onto your ESP32-DevKitM-1. - -.. attention:: - - ESP32-DevKitM-1 boards manufactured before December 2, 2021 have a single core module installed. To verify what module you have, please check module marking information in `PCN-2021-021 `_ . If your board has a single core module installed, please enable single core mode (:ref:`CONFIG_FREERTOS_UNICORE`) in :ref:`menuconfig ` before flashing your applications. - - -Hardware Reference -================== - -Block Diagram -------------- - -A block diagram below shows the components of ESP32-DevKitM-1 and their interconnections. - -.. figure:: ../../../_static/esp32-DevKitM-1_v1_SystemBlock.png - :align: center - :alt: ESP32-DevKitM-1 - :figclass: align-center - - ESP32-DevKitM-1 - - -Power Source Select -------------------- - -There are three mutually exclusive ways to provide power to the board: - -* Micro USB port, default power supply -* 5V and GND header pins -* 3V3 and GND header pins - -.. warning:: - - - The power supply must be provided using **one and only one of the options above**, otherwise the board and/or the power supply source can be damaged. - - Power supply by micro USB port is recommended. - - -Pin Descriptions ----------------- - -The table below provides the Name and Function of pins on both sides of the board. For peripheral pin configurations, please refer to `ESP32 Datasheet`_. - -.. list-table:: - :header-rows: 1 - :widths: 10 12 12 66 - - - * - No. - - Name - - Type [1]_ - - Function - * - 1 - - GND - - P - - Ground - * - 2 - - 3V3 - - P - - 3.3 V power supply - * - 3 - - I36 - - I - - GPIO36, ADC1_CH0, RTC_GPIO0 - * - 4 - - I37 - - I - - GPIO37, ADC1_CH1, RTC_GPIO1 - * - 5 - - I38 - - I - - GPIO38, ADC1_CH2, RTC_GPIO2 - * - 6 - - I39 - - I - - GPIO39, ADC1_CH3, RTC_GPIO3 - * - 7 - - RST - - I - - Reset; High: enable; Low: powers off - * - 8 - - I34 - - I - - GPIO34, ADC1_CH6, RTC_GPIO4 - * - 9 - - I35 - - I - - GPIO35, ADC1_CH7, RTC_GPIO5 - * - 10 - - IO32 - - I/O - - GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9 - * - 11 - - IO33 - - I/O - - GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8 - * - 12 - - IO25 - - I/O - - GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0 - * - 13 - - IO26 - - I/O - - GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1 - * - 14 - - IO27 - - I/O - - GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV - * - 15 - - IO14 - - I/O - - GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2 - * - 16 - - 5V - - P - - 5 V power supply - * - 17 - - IO12 - - I/O - - GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI [2]_, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 - * - 18 - - IO13 - - I/O - - GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER - * - 19 - - IO15 - - I/O - - GPIO15, ADC2_CH3, TOUCH3, RTC_GPIO13, MTDO [2]_, HSPICS0, HS2_CMD, SD_CMD, EMAC_RXD3 - * - 20 - - IO2 - - I/O - - GPIO2 [2]_, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0 - * - 21 - - IO0 - - I/O - - GPIO0 [2]_, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK - * - 22 - - IO4 - - I/O - - GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER - * - 23 - - IO9 - - I/O - - GPIO9, HS1_DATA2, U1RXD, SD_DATA2 - * - 24 - - IO10 - - I/O - - GPIO10, HS1_DATA3, U1TXD, SD_DATA3 - * - 25 - - IO5 - - I/O - - GPIO5 [2]_, HS1_DATA6, VSPICS0, EMAC_RX_CLK - * - 26 - - IO18 - - I/O - - GPIO18, HS1_DATA7, VSPICLK - * - 27 - - IO23 - - I/O - - GPIO23, HS1_STROBE, VSPID - * - 28 - - IO19 - - I/O - - GPIO19, VSPIQ, U0CTS, EMAC_TXD0 - * - 29 - - IO22 - - I/O - - GPIO22, VSPIWP, U0RTS, EMAC_TXD1 - * - 30 - - IO21 - - I/O - - GPIO21, VSPIHD, EMAC_TX_EN - * - 31 - - TXD0 - - I/O - - GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2 - * - 32 - - RXD0 - - I/O - - GPIO3, U0RXD, CLK_OUT2 - -.. [1] P: Power supply; I: Input; O: Output. -.. [2] MTDI, GPIO0, GPIO2, MTDO, and GPIO5 are strapping pins. These pins are used to control several chip functions depending on binary voltage values applied to the pins during chip power-up or system reset. For description and application of the strapping pins, please refer to `ESP32 Datasheet`_ > Section *Strapping Pins*. - - -Pin Layout -^^^^^^^^^^ - -.. figure:: ../../../_static/ESP32_DevKitM-1_pinlayout.png - :align: center - :scale: 43% - :alt: ESP32-DevKitM-1 (click to enlarge) - :figclass: align-center - - ESP32-DevKitM-1 (click to enlarge) - - -Hardware Revision Details -========================= - -No previous versions available. - - -Related Documents -================= - -* `ESP32-MINI-1 & ESP32-MINI-1U Datasheet `_ (PDF) -* `ESP32-DevKitM-1 Schematics `_ (PDF) -* `ESP32-DevKitM-1 PCB layout `_ (PDF) -* `ESP32-DevKitM-1 layout `_ (DXF) - You can view it with `Autodesk Viewer `_ online -* `ESP32 Datasheet `_ (PDF) -* `ESP Product Selector `_ - -For other design documentation for the board, please contact us at sales@espressif.com. diff --git a/docs/en/hw-reference/esp32s2/user-guide-saola-1-v1.2.rst b/docs/en/hw-reference/esp32s2/user-guide-saola-1-v1.2.rst deleted file mode 100644 index 7e24b7fcba71..000000000000 --- a/docs/en/hw-reference/esp32s2/user-guide-saola-1-v1.2.rst +++ /dev/null @@ -1,262 +0,0 @@ -================ -ESP32-S2-Saola-1 -================ - -:link_to_translation:`zh_CN:[中文]` - -This user guide provides information on ESP32-S2-Saola-1, a small-sized `ESP32-S2 Datasheet`_ based development board produced by Espressif. - -.. figure:: ../../../_static/esp32-s2-saola-1-v1.2-isometric.png - :align: center - :alt: ESP32-S2-Saola-1 - :figclass: align-center - - ESP32-S2-Saola-1 - -The document consists of the following major sections: - -- `Getting started`_: Provides an overview of the ESP32-S2-Saola-1 and hardware/software setup instructions to get started. -- `Hardware reference`_: Provides more detailed information about the ESP32-S2-Saola-1's hardware. -- `Hardware Revision Details`_: Revision history, known issues, and links to user guides for previous versions (if any) of ESP32-S2-Saola-1. -- `Related Documents`_: Gives links to related documentation. - - -Getting Started -=============== - -This section describes how to get started with ESP32-S2-Saola-1. It begins with a few introductory sections about the ESP32-S2-Saola-1, then Section `Start Application Development`_ provides instructions on how to get the ESP32-S2-Saola-1 ready and flash firmware into it. - - -Overview --------- - -ESP32-S2-Saola-1 is a small-sized ESP32-S2 based development board produced by Espressif. Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. Developers can either connect peripherals with jumper wires or mount ESP32-S2-Saola-1 on a breadboard. - -To cover a wide range of users' needs, ESP32-S2-Saola-1 supports: - -- `ESP32-S2-WROVER `_ -- `ESP32-S2-WROVER-I `_ -- `ESP32-S2-WROOM `_ -- `ESP32-S2-WROOM-I `_ - -In this guide, we take ESP32-S2-Saola-1 equipped with ESP32-S2-WROVER as an example. - - -Contents and Packaging ----------------------- - -Retail Orders -^^^^^^^^^^^^^ - -If you order a few samples, each ESP32-S2-Saola-1 comes in an individual package in either antistatic bag or any packaging depending on your retailer. - -For retail orders, please go to https://www.espressif.com/en/contact-us/get-samples. - - -Wholesale Orders -^^^^^^^^^^^^^^^^ - -If you order in bulk, the boards come in large cardboard boxes. - -For wholesale orders, please go to https://www.espressif.com/en/contact-us/sales-questions. - - -Description of Components -------------------------- - -.. _user-guide-saola-1-v1.2-board-front: - -.. figure:: ../../../_static/esp32-s2-saola-1-v1.2-annotated-photo.png - :align: center - :alt: ESP32-S2-Saola-1 - front/back - :figclass: align-center - - ESP32-S2-Saola-1 - front - -The key components of the board are described in a clockwise direction. - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - Key Component - - Description - * - ESP32-S2-WROVER - - ESP32-S2-WROVER is a powerful, generic Wi-Fi MCU module that integrates ESP32-S2. It has a PCB antenna, a 4 MB external SPI flash and an additional 2 MB PSRAM. - * - Pin Headers - - All available GPIO pins (except for the SPI bus for flash and PSRAM) are broken out to the pin headers on the board. Users can program ESP32-S2 chip to enable multiple functions such as SPI, I2S, UART, I2C, touch sensors, PWM etc. - * - 3.3 V Power On LED - - Turns on when the USB power is connected to the board. - * - USB-to-UART Bridge - - Single USB-UART bridge chip provides transfer rates up to 3 Mbps. - * - Reset Button - - Reset button. - * - Micro-USB Port - - USB interface. Power supply for the board as well as the communication interface between a computer and the ESP32-S2 chip. - * - Boot Button - - Download button. Holding down **Boot** and then pressing **Reset** initiates Firmware Download mode for downloading firmware through the serial port. - * - RGB LED - - Addressable RGB LED (WS2812), driven by GPIO18. - - -Start Application Development ------------------------------ - -Before powering up your ESP32-S2-Saola-1, please make sure that it is in good condition with no obvious signs of damage. - - -Required Hardware -^^^^^^^^^^^^^^^^^ - -- ESP32-S2-Saola-1 -- USB 2.0 cable (Standard-A to Micro-B) -- Computer running Windows, Linux, or macOS - -.. note:: - - Be sure to use an appropriate USB cable. Some cables are for charging only and do not provide the needed data lines nor work for programming the boards. - - -Software Setup -^^^^^^^^^^^^^^ - -Please proceed to :doc:`../../get-started/index`, where Section :ref:`get-started-step-by-step` will quickly help you set up the development environment and then flash an application example into your ESP32-S2-Saola-1. - -.. note:: - - ESP32-S2 series of chips only supports ESP-IDF master or version v4.2 and higher. - - -Hardware Reference -================== - -Block Diagram -------------- - -A block diagram below shows the components of ESP32-S2-Saola-1 and their interconnections. - -.. figure:: ../../../_static/esp32-s2-saola-1-v1.2-block-diags.png - :align: center - :scale: 70% - :alt: ESP32-S2-Saola-1 (click to enlarge) - :figclass: align-center - - ESP32-S2-Saola-1 (click to enlarge) - - -Power Supply Options -^^^^^^^^^^^^^^^^^^^^ - -There are three mutually exclusive ways to provide power to the board: - -- Micro-USB port, default power supply -- 5V and GND pin headers -- 3V3 and GND pin headers - -It is recommended to use the first option: Micro-USB Port. - - -Header Block ------------- - -The two tables below provide the **Name** and **Function** of the pin headers on both sides of the board (J2 and J3). The pin header names are shown in :ref:`user-guide-saola-1-v1.2-board-front`. The numbering is the same as in the `ESP32-S2-Saola-1 Schematics`_ (PDF). - - -J2 -^^^ - -=== ==== ========== ====================================== -No. Name Type [#]_ Function -=== ==== ========== ====================================== -1 3V3 P 3.3 V power supply -2 IO0 I/O GPIO0, Boot -3 IO1 I/O GPIO1, ADC1_CH0, TOUCH_CH1 -4 IO2 I/O GPIO2, ADC1_CH1, TOUCH_CH2 -5 IO3 I/O GPIO3, ADC1_CH2, TOUCH_CH3 -6 IO4 I/O GPIO4, ADC1_CH3, TOUCH_CH4 -7 IO5 I/O GPIO5, ADC1_CH4, TOUCH_CH5 -8 IO6 I/O GPIO6, ADC1_CH5, TOUCH_CH6 -9 IO7 I/O GPIO7, ADC1_CH6, TOUCH_CH7 -10 IO8 I/O GPIO8, ADC1_CH7, TOUCH_CH8 -11 IO9 I/O GPIO9, ADC1_CH8, TOUCH_CH9 -12 IO10 I/O GPIO10, ADC1_CH9, TOUCH_CH10 -13 IO11 I/O GPIO11, ADC2_CH0, TOUCH_CH11 -14 IO12 I/O GPIO12, ADC2_CH1, TOUCH_CH12 -15 IO13 I/O GPIO13, ADC2_CH2, TOUCH_CH13 -16 IO14 I/O GPIO14, ADC2_CH3, TOUCH_CH14 -17 IO15 I/O GPIO15, ADC2_CH4, XTAL_32K_P -18 IO16 I/O GPIO16, ADC2_CH5, XTAL_32K_N -19 IO17 I/O GPIO17, ADC2_CH6, DAC_1 -20 5V0 P 5 V power supply -21 GND G Ground -=== ==== ========== ====================================== - - -J3 -^^^ - -=== ==== ===== ==================================== -No. Name Type Function -=== ==== ===== ==================================== -1 GND G Ground -2 RST I CHIP_PU, Reset -3 IO46 I GPIO46 -4 IO45 I/O GPIO45 -5 IO44 I/O GPIO44, U0RXD -6 IO43 I/O GPIO43, U0TXD -7 IO42 I/O GPIO42, MTMS -8 IO41 I/O GPIO41, MTDI -9 IO40 I/O GPIO40, MTDO -10 IO39 I/O GPIO39, MTCK -11 IO38 I/O GPIO38 -12 IO37 I/O GPIO37 -13 IO36 I/O GPIO36 -14 IO35 I/O GPIO35 -16 IO34 I/O GPIO34 -17 IO33 I/O GPIO33 -17 IO26 I/O GPIO26 -18 IO21 I/O GPIO21 -19 IO20 I/O GPIO20, ADC2_CH9, USB_D+ -20 IO19 I/O GPIO19, ADC2_CH8, USB_D- -21 IO18 I/O GPIO18, ADC2_CH7, DAC_2, RGB LED -=== ==== ===== ==================================== - -.. [#] P: Power supply; I: Input; O: Output; T: High impedance. - - -Pin Layout -^^^^^^^^^^^ - -.. figure:: ../../../_static/esp32-s2_saola1-pinout.jpg - :align: center - :scale: 45% - :alt: ESP32-S2-Saola-1 (click to enlarge) - :figclass: align-center - - ESP32-S2 Saola-1 Pin Layout (click to enlarge) - - -Hardware Revision Details -========================= - -This is the first revision of this board released. - - -Related Documents -================= - -* `ESP32-S2-Saola-1 Schematics`_ (PDF) -* `ESP32-S2-Saola-1 Dimensions`_ (PDF) -* `ESP32-S2 Datasheet`_ (PDF) -* `ESP32-S2-WROVER and ESP32-S2-WROVER-I Datasheet`_ (PDF) -* `ESP32-S2-WROOM and ESP32-S2-WROOM-I Datasheet`_ (PDF) -* `ESP Product Selector`_ - -For other design documentation for the board, please contact us at `sales@espressif.com `_. - -.. _ESP32-S2-Saola-1 Schematics: https://dl.espressif.com/dl/schematics/ESP32-S2-SAOLA-1_V1.1_schematics.pdf -.. _ESP32-S2-Saola-1 Dimensions: https://dl.espressif.com/dl/schematics/ESP32-S2-Saola-1_V1.2_Dimensions.pdf -.. _ESP32-S2 Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf -.. _ESP32-S2-WROVER and ESP32-S2-WROVER-I Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-s2-wrover_esp32-s2-wrover-i_datasheet_en.pdf -.. _ESP32-S2-WROOM and ESP32-S2-WROOM-I Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-s2-wroom_esp32-s2-wroom-i_datasheet_en.pdf -.. _ESP Product Selector: https://products.espressif.com/#/product-selector?names= diff --git a/docs/en/hw-reference/esp32s3/user-guide-devkitc-1-v1.0.rst b/docs/en/hw-reference/esp32s3/user-guide-devkitc-1-v1.0.rst deleted file mode 100644 index ca62c3f1c1cd..000000000000 --- a/docs/en/hw-reference/esp32s3/user-guide-devkitc-1-v1.0.rst +++ /dev/null @@ -1,320 +0,0 @@ -================== -ESP32-S3-DevKitC-1 -================== - -:link_to_translation:`zh_CN:[中文]` - -The latest version: :doc:`user-guide-devkitc-1` - -This user guide will help you get started with ESP32-S3-DevKitC-1 and will also provide more in-depth information. - -The ESP32-S3-DevKitC-1 is an entry-level development board equipped with ESP32-S3-WROOM-1, ESP32-S3-WROOM-1U, or ESP32-S3-WROOM-2, a general-purpose Wi-Fi + Bluetooth® Low Energy MCU module that integrates complete Wi-Fi and Bluetooth Low Energy functions. - -Most of the I/O pins on the module are broken out to the pin headers on both sides of this board for easy interfacing. Developers can either connect peripherals with jumper wires or mount ESP32-S3-DevKitC-1 on a breadboard. - -.. figure:: ../../../_static/esp32-s3-devkitc-1-v1-isometric.png - :align: center - :alt: ESP32-S3-DevKitC-1 with ESP32-S3-WROOM-1 Module - - ESP32-S3-DevKitC-1 with ESP32-S3-WROOM-1 Module - - -The document consists of the following major sections: - -- `Getting started`_: Overview of the board and hardware/software setup instructions to get started. -- `Hardware Reference`_: More detailed information about the board's hardware. -- `Hardware Revision Details`_: Revision history, known issues, and links to user guides for previous versions (if any) of the board. -- `Related Documents`_: Links to related documentation. - - -Getting Started -=============== - -This section provides a brief introduction of ESP32-S3-DevKitC-1, instructions on how to do the initial hardware setup and how to flash firmware onto it. - - -Description of Components -------------------------- - -.. _user-guide-s3-devkitc-1-v1-board-front: - -.. figure:: ../../../_static/ESP32-S3-DevKitC-1_v2-annotated-photo.png - :align: center - :alt: ESP32-S3-DevKitC-1 - front - - ESP32-S3-DevKitC-1 - front - -The key components of the board are described in a counter-clockwise direction. - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - Key Component - - Description - * - ESP32-S3-WROOM-1/1U/2 - - ESP32-S3-WROOM-1, ESP32-S3-WROOM-1U, and ESP32-S3-WROOM-2 are powerful, generic Wi-Fi + Bluetooth Low Energy MCU modules that have a rich set of peripherals. They provide acceleration for neural network computing and signal processing workloads. ESP32-S3-WROOM-1 and ESP32-S3-WROOM-2 comes with a PCB antenna. ESP32-S3-WROOM-1U comes with an external antenna connector. - * - 5 V to 3.3 V LDO - - Power regulator that converts a 5 V supply into a 3.3 V output. - * - Pin Headers - - All available GPIO pins (except for the SPI bus for flash) are broken out to the pin headers on the board for easy interfacing and programming. For details, please see :ref:`user-guide-s3-devkitc-1-v1-header-blocks`. - * - USB-to-UART Port - - A Micro-USB port used for power supply to the board, for flashing applications to the chip, as well as for communication with the chip via the on-board USB-to-UART bridge. - * - Boot Button - - Download button. Holding down **Boot** and then pressing **Reset** initiates Firmware Download mode for downloading firmware through the serial port. - * - Reset Button - - Press this button to restart the system. - * - ESP32-S3 USB Port - - ESP32-S3 full-speed USB OTG interface, compliant with the USB 1.1 specification. The interface is used for power supply to the board, for flashing applications to the chip, for communication with the chip using USB 1.1 protocols, as well as for JTAG debugging. - * - USB-to-UART Bridge - - Single USB-to-UART bridge chip provides transfer rates up to 3 Mbps. - * - RGB LED - - Addressable RGB LED, driven by GPIO48. - * - 3.3 V Power On LED - - Turns on when the USB power is connected to the board. - -.. note:: - - For boards with Octal SPI flash/PSRAM memory embedded ESP32-S3-WROOM-1/1U modules, and boards with ESP32-S3-WROOM-2 modules, the pins GPIO35, GPIO36 and GPIO37 are used for the internal communication between ESP32-S3 and SPI flash/PSRAM memory, thus not available for external use. - - -Start Application Development ------------------------------ - -Before powering up your board, please make sure that it is in good condition with no obvious signs of damage. - - -Required Hardware -^^^^^^^^^^^^^^^^^ - -- ESP32-S3-DevKitC-1 -- USB 2.0 cable (Standard-A to Micro-B) -- Computer running Windows, Linux, or macOS - -.. note:: - - Be sure to use an appropriate USB cable. Some cables are for charging only and do not provide the needed data lines nor work for programming the boards. - - -Hardware Setup -^^^^^^^^^^^^^^ - -Connect the board with the computer using **USB-to-UART Port**. Connection using **ESP32-S3 USB Port** is not fully implemented in software. In subsequent steps, **USB-to-UART Port** will be used by default. - - -Software Setup -^^^^^^^^^^^^^^ - -Please proceed to :doc:`../../get-started/index`, where Section :ref:`get-started-step-by-step` will quickly help you set up the development environment and then flash an application example onto your board. - - -Contents and Packaging ----------------------- - -Ordering Information -^^^^^^^^^^^^^^^^^^^^ - -The development board has a variety of variants to choose from, as shown in the table below. - -.. list-table:: - :widths: 28 29 19 17 15 - :header-rows: 1 - - * - Ordering Code - - Module Integrated - - Flash - - PSRAM - - SPI Voltage - * - ESP32-S3-DevKitC-1-N8 - - ESP32-S3-WROOM-1-N8 - - 8 MB QD - - — - - 3.3 V - * - ESP32-S3-DevKitC-1-N8R2 - - ESP32-S3-WROOM-1-N8R2 - - 8 MB QD - - 2 MB QD - - 3.3 V - * - ESP32-S3-DevKitC-1-N8R8 - - ESP32-S3-WROOM-1-N8R8 - - 8 MB QD - - 8 MB OT - - 3.3 V - * - ESP32-S3-DevKitC-1-N16R8V - - ESP32-S3-WROOM-2-N16R8V - - 16 MB OT - - 8 MB OT - - 1.8 V - * - ESP32-S3-DevKitC-1-N32R8V - - ESP32-S3-WROOM-2-N32R8V - - 32 MB OT - - 8 MB OT - - 1.8 V - * - ESP32-S3-DevKitC-1U-N8 - - ESP32-S3-WROOM-1U-N8 - - 8 MB QD - - — - - 3.3 V - * - ESP32-S3-DevKitC-1U-N8R2 - - ESP32-S3-WROOM-1U-N8R2 - - 8 MB QD - - 2 MB QD - - 3.3 V - * - ESP32-S3-DevKitC-1U-N8R8 - - ESP32-S3-WROOM-1U-N8R8 - - 8 MB QD - - 8 MB OT - - 3.3 V - -.. note:: - - In the table above, QD stands for Quad SPI and OT stands for Octal SPI. - - -Retail Orders -^^^^^^^^^^^^^ - -If you order a few samples, each board comes in an individual package in either antistatic bag or any packaging depending on your retailer. - -For retail orders, please go to https://www.espressif.com/en/company/contact/buy-a-sample. - - -Wholesale Orders -^^^^^^^^^^^^^^^^ - -If you order in bulk, the boards come in large cardboard boxes. - -For wholesale orders, please go to https://www.espressif.com/en/contact-us/sales-questions. - - -Hardware Reference -================== - -Block Diagram -------------- - -The block diagram below shows the components of ESP32-S3-DevKitC-1 and their interconnections. - -.. figure:: ../../../_static/ESP32-S3-DevKitC-1_v2-SystemBlock.png - :align: center - :scale: 70% - :alt: ESP32-S3-DevKitC-1 (click to enlarge) - - ESP32-S3-DevKitC-1 (click to enlarge) - - -Power Supply Options -^^^^^^^^^^^^^^^^^^^^ - -There are three mutually exclusive ways to provide power to the board: - -- USB-to-UART Port and ESP32-S3 USB Port (either one or both), default power supply (recommended) -- 5V and G (GND) pins -- 3V3 and G (GND) pins - - -.. _user-guide-s3-devkitc-1-v1-header-blocks: - -Header Block ------------- - -The two tables below provide the **Name** and **Function** of the pins on both sides of the board (J1 and J3). The pin names are shown in :ref:`user-guide-s3-devkitc-1-v1-board-front`. The numbering is the same as in the `Board Schematic `_ (PDF). - - -J1 -^^^ - -=== ==== ========== =================================== -No. Name Type [#]_ Function -=== ==== ========== =================================== -1 3V3 P 3.3 V power supply -2 3V3 P 3.3 V power supply -3 RST I EN -4 4 I/O/T RTC_GPIO4, GPIO4, TOUCH4, ADC1_CH3 -5 5 I/O/T RTC_GPIO5, GPIO5, TOUCH5, ADC1_CH4 -6 6 I/O/T RTC_GPIO6, GPIO6, TOUCH6, ADC1_CH5 -7 7 I/O/T RTC_GPIO7, GPIO7, TOUCH7, ADC1_CH6 -8 15 I/O/T RTC_GPIO15, GPIO15, U0RTS, ADC2_CH4, XTAL_32K_P -9 16 I/O/T RTC_GPIO16, GPIO16, U0CTS, ADC2_CH5, XTAL_32K_N -10 17 I/O/T RTC_GPIO17, GPIO17, U1TXD, ADC2_CH6 -11 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, CLK_OUT3 -12 8 I/O/T RTC_GPIO8, GPIO8, TOUCH8, ADC1_CH7, SUBSPICS1 -13 3 I/O/T RTC_GPIO3, GPIO3, TOUCH3, ADC1_CH2 -14 46 I/O/T GPIO46 -15 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD, SUBSPIHD -16 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4, SUBSPICS0 -17 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5, SUBSPID -18 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6, SUBSPICLK -19 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7, SUBSPIQ -20 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS, SUBSPIWP -21 5V P 5 V power supply -22 G G Ground -=== ==== ========== =================================== - - -J3 -^^^ - -=== ==== ===== ==================================== -No. Name Type Function -=== ==== ===== ==================================== -1 G G Ground -2 TX I/O/T U0TXD, GPIO43, CLK_OUT1 -3 RX I/O/T U0RXD, GPIO44, CLK_OUT2 -4 1 I/O/T RTC_GPIO1, GPIO1, TOUCH1, ADC1_CH0 -5 2 I/O/T RTC_GPIO2, GPIO2, TOUCH2, ADC1_CH1 -6 42 I/O/T MTMS, GPIO42 -7 41 I/O/T MTDI, GPIO41, CLK_OUT1 -8 40 I/O/T MTDO, GPIO40, CLK_OUT2 -9 39 I/O/T MTCK, GPIO39, CLK_OUT3, SUBSPICS1 -10 38 I/O/T GPIO38, FSPIWP, SUBSPIWP -11 37 I/O/T SPIDQS, GPIO37, FSPIQ, SUBSPIQ -12 36 I/O/T SPIIO7, GPIO36, FSPICLK, SUBSPICLK -13 35 I/O/T SPIIO6, GPIO35, FSPID, SUBSPID -14 0 I/O/T RTC_GPIO0, GPIO0 -15 45 I/O/T GPIO45 -16 48 I/O/T GPIO48, SPICLK_N, SUBSPICLK_N_DIFF, RGB LED -17 47 I/O/T GPIO47, SPICLK_P, SUBSPICLK_P_DIFF -18 21 I/O/T RTC_GPIO21, GPIO21 -19 20 I/O/T RTC_GPIO20, GPIO20, U1CTS, ADC2_CH9, CLK_OUT1, USB_D+ -20 19 I/O/T RTC_GPIO19, GPIO19, U1RTS, ADC2_CH8, CLK_OUT2, USB_D- -21 G G Ground -22 G G Ground -=== ==== ===== ==================================== - - -.. [#] P: Power supply; I: Input; O: Output; T: High impedance. - - -For description of function names, please refer to `Chip Datasheet `_ (PDF). - - -Pin Layout -^^^^^^^^^^ - -.. figure:: ../../../_static/ESP32-S3_DevKitC-1_pinlayout.jpg - :align: center - :scale: 50% - :alt: ESP32-S3-DevKitC-1 (click to enlarge) - - ESP32-S3-DevKitC-1 Pin Layout (click to enlarge) - - -Hardware Revision Details -========================= - -This is the first revision of this board released. - - -Related Documents -================= - -- `ESP32-S3 Datasheet `_ (PDF) -- `ESP32-S3-WROOM-1 & ESP32-S3-WROOM-1U Datasheet `_ (PDF) -- `ESP32-S3-WROOM-2 Datasheet `_ (PDF) -- `ESP32-S3-DevKitC-1 Schematic `_ (PDF) -- `ESP32-S3-DevKitC-1 PCB layout `_ (PDF) -- `ESP32-S3-DevKitC-1 Dimensions `_ (PDF) -- `ESP32-S3-DevKitC-1 Dimensions source file `_ (DXF) - You can view it with `Autodesk Viewer `_ online - -For further design documentation for the board, please contact us at `sales@espressif.com `_. diff --git a/docs/en/hw-reference/esp32s3/user-guide-devkitc-1.rst b/docs/en/hw-reference/esp32s3/user-guide-devkitc-1.rst deleted file mode 100644 index 2b7923086eb8..000000000000 --- a/docs/en/hw-reference/esp32s3/user-guide-devkitc-1.rst +++ /dev/null @@ -1,329 +0,0 @@ -======================= -ESP32-S3-DevKitC-1 v1.1 -======================= - -:link_to_translation:`zh_CN:[中文]` - -The older version: :doc:`user-guide-devkitc-1-v1.0` - -This user guide will help you get started with ESP32-S3-DevKitC-1 and will also provide more in-depth information. - -The ESP32-S3-DevKitC-1 is an entry-level development board equipped with ESP32-S3-WROOM-1, ESP32-S3-WROOM-1U, or ESP32-S3-WROOM-2, a general-purpose Wi-Fi + Bluetooth® Low Energy MCU module that integrates complete Wi-Fi and Bluetooth Low Energy functions. - -Most of the I/O pins on the module are broken out to the pin headers on both sides of this board for easy interfacing. Developers can either connect peripherals with jumper wires or mount ESP32-S3-DevKitC-1 on a breadboard. - -.. figure:: ../../../_static/esp32-s3-devkitc-1-v1.1-isometric.png - :align: center - :alt: ESP32-S3-DevKitC-1 with ESP32-S3-WROOM-1 Module - - ESP32-S3-DevKitC-1 with ESP32-S3-WROOM-1 Module - - -The document consists of the following major sections: - -- `Getting started`_: Overview of the board and hardware/software setup instructions to get started. -- `Hardware Reference`_: More detailed information about the board's hardware. -- `Hardware Revision Details`_: Revision history, known issues, and links to user guides for previous versions (if any) of the board. -- `Related Documents`_: Links to related documentation. - - -Getting Started -=============== - -This section provides a brief introduction of ESP32-S3-DevKitC-1, instructions on how to do the initial hardware setup and how to flash firmware onto it. - - -Description of Components -------------------------- - -.. _user-guide-s3-devkitc-1-v1.1-board-front: - -.. figure:: ../../../_static/ESP32-S3-DevKitC-1_v2-annotated-photo.png - :align: center - :alt: ESP32-S3-DevKitC-1 - front - - ESP32-S3-DevKitC-1 - front - -The key components of the board are described in a counter-clockwise direction. - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - Key Component - - Description - * - ESP32-S3-WROOM-1/1U/2 - - ESP32-S3-WROOM-1, ESP32-S3-WROOM-1U, and ESP32-S3-WROOM-2 are powerful, generic Wi-Fi + Bluetooth Low Energy MCU modules that have a rich set of peripherals. They provide acceleration for neural network computing and signal processing workloads. ESP32-S3-WROOM-1 and ESP32-S3-WROOM-2 comes with a PCB antenna. ESP32-S3-WROOM-1U comes with an external antenna connector. - * - 5 V to 3.3 V LDO - - Power regulator that converts a 5 V supply into a 3.3 V output. - * - Pin Headers - - All available GPIO pins (except for the SPI bus for flash) are broken out to the pin headers on the board for easy interfacing and programming. For details, please see :ref:`user-guide-s3-devkitc-1-v1.1-header-blocks`. - * - USB-to-UART Port - - A Micro-USB port used for power supply to the board, for flashing applications to the chip, as well as for communication with the chip via the on-board USB-to-UART bridge. - * - Boot Button - - Download button. Holding down **Boot** and then pressing **Reset** initiates Firmware Download mode for downloading firmware through the serial port. - * - Reset Button - - Press this button to restart the system. - * - USB Port - - ESP32-S3 full-speed USB OTG interface, compliant with the USB 1.1 specification. The interface is used for power supply to the board, for flashing applications to the chip, for communication with the chip using USB 1.1 protocols, as well as for JTAG debugging. - * - USB-to-UART Bridge - - Single USB-to-UART bridge chip provides transfer rates up to 3 Mbps. - * - RGB LED - - Addressable RGB LED, driven by GPIO38. - * - 3.3 V Power On LED - - Turns on when the USB power is connected to the board. - -.. note:: - - For boards with Octal SPI flash/PSRAM memory embedded ESP32-S3-WROOM-1/1U modules, and boards with ESP32-S3-WROOM-2 modules, the pins GPIO35, GPIO36 and GPIO37 are used for the internal communication between ESP32-S3 and SPI flash/PSRAM memory, thus not available for external use. - - -Start Application Development ------------------------------ - -Before powering up your board, please make sure that it is in good condition with no obvious signs of damage. - - -Required Hardware -^^^^^^^^^^^^^^^^^ - -- ESP32-S3-DevKitC-1 -- USB 2.0 cable (Standard-A to Micro-B) -- Computer running Windows, Linux, or macOS - -.. note:: - - Be sure to use an appropriate USB cable. Some cables are for charging only and do not provide the needed data lines nor work for programming the boards. - - -Hardware Setup -^^^^^^^^^^^^^^ - -Connect the board with the computer using **USB-to-UART Port** or **ESP32-S3 USB Port**. In subsequent steps, **USB-to-UART Port** will be used by default. - - -Software Setup -^^^^^^^^^^^^^^ - -Please proceed to :doc:`../../get-started/index`, where Section :ref:`get-started-step-by-step` will quickly help you set up the development environment and then flash an application example onto your board. - - -Contents and Packaging ----------------------- - -Ordering Information -^^^^^^^^^^^^^^^^^^^^ - -The development board has a variety of variants to choose from, as shown in the table below. - -.. list-table:: - :widths: 28 29 19 17 15 - :header-rows: 1 - - * - Ordering Code - - Module Integrated - - Flash - - PSRAM - - SPI Voltage - * - ESP32-S3-DevKitC-1-N8 - - ESP32-S3-WROOM-1-N8 - - 8 MB QD - - — - - 3.3 V - * - ESP32-S3-DevKitC-1-N8R2 - - ESP32-S3-WROOM-1-N8R2 - - 8 MB QD - - 2 MB QD - - 3.3 V - * - ESP32-S3-DevKitC-1-N8R8 - - ESP32-S3-WROOM-1-N8R8 - - 8 MB QD - - 8 MB OT - - 3.3 V - * - ESP32-S3-DevKitC-1-N16R8V - - ESP32-S3-WROOM-2-N16R8V - - 16 MB OT - - 8 MB OT - - 1.8 V - * - ESP32-S3-DevKitC-1-N32R8V - - ESP32-S3-WROOM-2-N32R8V - - 32 MB OT - - 8 MB OT - - 1.8 V - * - ESP32-S3-DevKitC-1U-N8 - - ESP32-S3-WROOM-1U-N8 - - 8 MB QD - - — - - 3.3 V - * - ESP32-S3-DevKitC-1U-N8R2 - - ESP32-S3-WROOM-1U-N8R2 - - 8 MB QD - - 2 MB QD - - 3.3 V - * - ESP32-S3-DevKitC-1U-N8R8 - - ESP32-S3-WROOM-1U-N8R8 - - 8 MB QD - - 8 MB OT - - 3.3 V - -.. note:: - - In the table above, QD stands for Quad SPI and OT stands for Octal SPI. - - -Retail Orders -^^^^^^^^^^^^^ - -If you order a few samples, each board comes in an individual package in either antistatic bag or any packaging depending on your retailer. - -For retail orders, please go to https://www.espressif.com/en/contact-us/get-samples. - - -Wholesale Orders -^^^^^^^^^^^^^^^^ - -If you order in bulk, the boards come in large cardboard boxes. - -For wholesale orders, please go to https://www.espressif.com/en/contact-us/sales-questions. - - -Hardware Reference -================== - -Block Diagram -------------- - -The block diagram below shows the components of ESP32-S3-DevKitC-1 and their interconnections. - -.. figure:: ../../../_static/ESP32-S3-DevKitC-1_v2-SystemBlock.png - :align: center - :scale: 70% - :alt: ESP32-S3-DevKitC-1 (click to enlarge) - - ESP32-S3-DevKitC-1 (click to enlarge) - - -Power Supply Options -^^^^^^^^^^^^^^^^^^^^ - -There are three mutually exclusive ways to provide power to the board: - -- USB-to-UART Port and ESP32-S3 USB Port (either one or both), default power supply (recommended) -- 5V and G (GND) pins -- 3V3 and G (GND) pins - - -.. _user-guide-s3-devkitc-1-v1.1-header-blocks: - -Header Block ------------- - -The two tables below provide the **Name** and **Function** of the pins on both sides of the board (J1 and J3). The pin names are shown in :ref:`user-guide-s3-devkitc-1-v1.1-board-front`. The numbering is the same as in the `Board Schematic `_ (PDF). - - -J1 -^^^ - -=== ==== ========== =================================== -No. Name Type [#]_ Function -=== ==== ========== =================================== -1 3V3 P 3.3 V power supply -2 3V3 P 3.3 V power supply -3 RST I EN -4 4 I/O/T RTC_GPIO4, GPIO4, TOUCH4, ADC1_CH3 -5 5 I/O/T RTC_GPIO5, GPIO5, TOUCH5, ADC1_CH4 -6 6 I/O/T RTC_GPIO6, GPIO6, TOUCH6, ADC1_CH5 -7 7 I/O/T RTC_GPIO7, GPIO7, TOUCH7, ADC1_CH6 -8 15 I/O/T RTC_GPIO15, GPIO15, U0RTS, ADC2_CH4, XTAL_32K_P -9 16 I/O/T RTC_GPIO16, GPIO16, U0CTS, ADC2_CH5, XTAL_32K_N -10 17 I/O/T RTC_GPIO17, GPIO17, U1TXD, ADC2_CH6 -11 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, CLK_OUT3 -12 8 I/O/T RTC_GPIO8, GPIO8, TOUCH8, ADC1_CH7, SUBSPICS1 -13 3 I/O/T RTC_GPIO3, GPIO3, TOUCH3, ADC1_CH2 -14 46 I/O/T GPIO46 -15 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD, SUBSPIHD -16 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4, SUBSPICS0 -17 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5, SUBSPID -18 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6, SUBSPICLK -19 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7, SUBSPIQ -20 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS, SUBSPIWP -21 5V P 5 V power supply -22 G G Ground -=== ==== ========== =================================== - - -J3 -^^^ - -=== ==== ===== ==================================== -No. Name Type Function -=== ==== ===== ==================================== -1 G G Ground -2 TX I/O/T U0TXD, GPIO43, CLK_OUT1 -3 RX I/O/T U0RXD, GPIO44, CLK_OUT2 -4 1 I/O/T RTC_GPIO1, GPIO1, TOUCH1, ADC1_CH0 -5 2 I/O/T RTC_GPIO2, GPIO2, TOUCH2, ADC1_CH1 -6 42 I/O/T MTMS, GPIO42 -7 41 I/O/T MTDI, GPIO41, CLK_OUT1 -8 40 I/O/T MTDO, GPIO40, CLK_OUT2 -9 39 I/O/T MTCK, GPIO39, CLK_OUT3, SUBSPICS1 -10 38 I/O/T GPIO38, FSPIWP, SUBSPIWP, RGB LED -11 37 I/O/T SPIDQS, GPIO37, FSPIQ, SUBSPIQ -12 36 I/O/T SPIIO7, GPIO36, FSPICLK, SUBSPICLK -13 35 I/O/T SPIIO6, GPIO35, FSPID, SUBSPID -14 0 I/O/T RTC_GPIO0, GPIO0 -15 45 I/O/T GPIO45 -16 48 I/O/T GPIO48, SPICLK_N, SUBSPICLK_N_DIFF -17 47 I/O/T GPIO47, SPICLK_P, SUBSPICLK_P_DIFF -18 21 I/O/T RTC_GPIO21, GPIO21 -19 20 I/O/T RTC_GPIO20, GPIO20, U1CTS, ADC2_CH9, CLK_OUT1, USB_D+ -20 19 I/O/T RTC_GPIO19, GPIO19, U1RTS, ADC2_CH8, CLK_OUT2, USB_D- -21 G G Ground -22 G G Ground -=== ==== ===== ==================================== - - -.. [#] P: Power supply; I: Input; O: Output; T: High impedance. - - -For description of function names, please refer to `ESP32-S3 Series Datasheet `_ (PDF). - - -Pin Layout -^^^^^^^^^^ - -.. figure:: ../../../_static/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg - :align: center - :scale: 50% - :alt: ESP32-S3-DevKitC-1 (click to enlarge) - - ESP32-S3-DevKitC-1 Pin Layout (click to enlarge) - - -Hardware Revision Details -========================= - -:doc:`Initial release ` - -.. note:: - - Both the initial and v1.1 versions of ESP32-S3-DevKitC-1 are available on the market. The main difference lies in the GPIO assignment for the RGB LED: the initial version uses GPIO48, whereas v1.1 uses GPIO38. - - -Related Documents -================= - -- `ESP32-S3 Datasheet `_ (PDF) -- `ESP32-S3-WROOM-1 & ESP32-S3-WROOM-1U Datasheet `_ (PDF) -- `ESP32-S3-WROOM-2 Datasheet `_ (PDF) -- `ESP32-S3-DevKitC-1 Schematic `_ (PDF) -- `ESP32-S3-DevKitC-1 PCB layout `_ (PDF) -- `ESP32-S3-DevKitC-1 Dimensions `_ (PDF) -- `ESP32-S3-DevKitC-1 Dimensions source file `_ (DXF) - You can view it with `Autodesk Viewer `_ online - -For further design documentation for the board, please contact us at `sales@espressif.com `_. - -.. toctree:: - :hidden: - - user-guide-devkitc-1-v1.0 diff --git a/docs/en/hw-reference/esp32s3/user-guide-devkitm-1.rst b/docs/en/hw-reference/esp32s3/user-guide-devkitm-1.rst deleted file mode 100644 index 850cc939d70f..000000000000 --- a/docs/en/hw-reference/esp32s3/user-guide-devkitm-1.rst +++ /dev/null @@ -1,258 +0,0 @@ -================== -ESP32-S3-DevKitM-1 -================== - -:link_to_translation:`zh_CN:[中文]` - -This user guide will help you get started with ESP32-S3-DevKitM-1 and will also provide more in-depth information. - -The ESP32-S3-DevKitM-1 is an entry-level development board equipped with either ESP32-S3-MINI-1 or ESP32-S3-MINI-1U, a module named for its small size. This board integrates complete Wi-Fi and Bluetooth® Low Energy functions. - -Most of the I/O pins on the module are broken out to the pin headers on both sides of this board for easy interfacing. Developers can either connect peripherals with jumper wires or mount ESP32-S3-DevKitM-1 on a breadboard. - -.. figure:: ../../../_static/esp32-s3-devkitm-1-v1-isometric.png - :align: center - :scale: 70% - :alt: ESP32-S3-DevKitM-1 with ESP32-S3-MINI-1 Module - :figclass: align-center - - ESP32-S3-DevKitM-1 with ESP32-S3-MINI-1 Module - - -The document consists of the following major sections: - -- `Getting Started`_: Overview of the board and hardware/software setup instructions to get started. -- `Hardware Reference`_: More detailed information about the board's hardware. -- `Related Documents`_: Links to related documentation. - - -Getting Started -=============== - -This section provides a brief introduction of ESP32-S3-DevKitM-1, instructions on how to do the initial hardware setup and how to flash firmware onto it. - - -Description of Components -------------------------- - -.. _user-guide-s3-devkitm-1-v1-board-front: - -.. figure:: ../../../_static/ESP32-S3-DevKitM-1_v1-annotated-photo.png - :align: center - :alt: ESP32-S3-DevKitM-1 - front - :figclass: align-center - - ESP32-S3-DevKitM-1 - front - -The key components of the board are described in a counter-clockwise direction, starting from the ESP32-S3-MINI-1/1U module. - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - Key Component - - Description - * - ESP32-S3-MINI-1/1U - - ESP32-S3-MINI-1 and ESP32-S3-MINI-1U are two general-purpose Wi-Fi and Bluetooth Low Energy combo modules that have a rich set of peripherals. ESP32-S3-MINI-1 comes with a PCB antenna. ESP32-S3-MINI-1U comes with an external antenna connector. At the core of the modules is ESP32-S3FN8, a chip equipped with an 8 MB flash. Since flash is packaged in the chip, rather than integrated into the module, ESP32-S3-MINI-1/1U has a smaller package size. - * - 5 V to 3.3 V LDO - - Power regulator that converts a 5 V supply into a 3.3 V output. - * - Pin Headers - - All available GPIO pins (except for the SPI bus for flash) are broken out to the pin headers on the board for easy interfacing and programming. For details, please see :ref:`user-guide-s3-devkitm-1-v1-header-blocks`. - * - USB-to-UART Port - - A Micro-USB port used for power supply to the board, for flashing applications to the chip, as well as for communication with the chip via the on-board USB-to-UART bridge. - * - Boot Button - - Download button. Holding down **Boot** and then pressing **Reset** initiates Firmware Download mode for downloading firmware through the serial port. - * - Reset Button - - Press this button to restart ESP32-S3. - * - ESP32-S3 USB Port - - ESP32-S3 full-speed USB OTG interface, compliant with the USB 1.1 specification. The interface is used for power supply to the board, for flashing applications to the chip, for communication with the chip using USB 1.1 protocols, as well as for JTAG debugging. - * - USB-to-UART Bridge - - Single USB-to-UART bridge chip provides transfer rates up to 3 Mbps. - * - RGB LED - - Addressable RGB LED, driven by GPIO48. - * - 3.3 V Power On LED - - Turns on when the USB power is connected to the board. - - -Start Application Development ------------------------------ - -Before powering up your board, please make sure that it is in good condition with no obvious signs of damage. - - -Required Hardware -^^^^^^^^^^^^^^^^^ - -- ESP32-S3-DevKitM-1 -- USB 2.0 cable (Standard-A to Micro-B) -- Computer running Windows, Linux, or macOS - -.. note:: - - Be sure to use an appropriate USB cable. Some cables are for charging only and do not provide the needed data lines nor work for programming the boards. - - -Hardware Setup -^^^^^^^^^^^^^^ - -Connect the board with the computer using **USB-to-UART Port** or **ESP32-S3 USB Port**. In subsequent steps, **USB-to-UART Port** will be used by default. - - -Software Setup -^^^^^^^^^^^^^^ - -Please proceed to :doc:`../../get-started/index`, where Section :ref:`get-started-step-by-step` will quickly help you set up the development environment and then flash an application example onto your board. - - -Contents and Packaging ----------------------- - -Retail Orders -^^^^^^^^^^^^^ - -If you order a few samples, each board comes in an individual package in either antistatic bag or any packaging depending on your retailer. - -For retail orders, please go to https://www.espressif.com/en/contact-us/get-samples. - - -Wholesale Orders -^^^^^^^^^^^^^^^^ - -If you order in bulk, the boards come in large cardboard boxes. - -For wholesale orders, please go to https://www.espressif.com/en/contact-us/sales-questions. - - -Hardware Reference -================== - -Block Diagram -------------- - -The block diagram below shows the components of ESP32-S3-DevKitM-1 and their interconnections. - -.. figure:: ../../../_static/ESP32-S3-DevKitM-1_v1_SystemBlock.png - :align: center - :scale: 70% - :alt: ESP32-S3-DevKitM-1 (click to enlarge) - :figclass: align-center - - ESP32-S3-DevKitM-1 (click to enlarge) - - -Power Supply Options -^^^^^^^^^^^^^^^^^^^^ - -There are three mutually exclusive ways to provide power to the board: - -- USB-to-UART Port and ESP32-S3 USB Port (either one or both), default power supply (recommended) -- 5V and G (GND) pins -- 3V3 and G (GND) pins - - -.. _user-guide-s3-devkitm-1-v1-header-blocks: - -Header Block ------------- - -The two tables below provide the **Name** and **Function** of the pins on both sides of the board (J1 and J3). The pin names are shown in :ref:`user-guide-s3-devkitm-1-v1-board-front`. The numbering is the same as in the `Board Schematic `_ (PDF). - - -J1 -^^^ - -=== ==== ========== =================================== -No. Name Type [#]_ Function -=== ==== ========== =================================== -1 3V3 P 3.3 V power supply -2 0 I/O/T RTC_GPIO0, GPIO0 -3 1 I/O/T RTC_GPIO1, GPIO1, TOUCH1, ADC1_CH0 -4 2 I/O/T RTC_GPIO2, GPIO2, TOUCH2, ADC1_CH1 -5 3 I/O/T RTC_GPIO3, GPIO3, TOUCH3, ADC1_CH2 -6 4 I/O/T RTC_GPIO4, GPIO4, TOUCH4, ADC1_CH3 -7 5 I/O/T RTC_GPIO5, GPIO5, TOUCH5, ADC1_CH4 -8 6 I/O/T RTC_GPIO6, GPIO6, TOUCH6, ADC1_CH5 -9 7 I/O/T RTC_GPIO7, GPIO7, TOUCH7, ADC1_CH6 -10 8 I/O/T RTC_GPIO8, GPIO8, TOUCH8, ADC1_CH7, SUBSPICS1 -11 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD, SUBSPIHD -12 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4, SUBSPICS0 -13 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5, SUBSPID -14 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6, SUBSPICLK -15 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7, SUBSPIQ -16 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS, SUBSPIWP -17 15 I/O/T RTC_GPIO15, GPIO15, U0RTS, ADC2_CH4, XTAL_32K_P -18 16 I/O/T RTC_GPIO16, GPIO16, U0CTS, ADC2_CH5, XTAL_32K_N -19 17 I/O/T RTC_GPIO17, GPIO17, U1TXD, ADC2_CH6 -20 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, CLK_OUT3 -21 5V P 5 V power supply -22 G G Ground -=== ==== ========== =================================== - - -J3 -^^^ - -=== ==== ===== ==================================== -No. Name Type Function -=== ==== ===== ==================================== -1 G G Ground -2 RST I EN -3 46 I/O/T GPIO46 -4 45 I/O/T GPIO45 -5 RX I/O/T U0RXD, GPIO44, CLK_OUT2 -6 TX I/O/T U0TXD, GPIO43, CLK_OUT1 -7 42 I/O/T MTMS, GPIO42 -8 41 I/O/T MTDI, GPIO41, CLK_OUT1 -9 40 I/O/T MTDO, GPIO40, CLK_OUT2 -10 39 I/O/T MTCK, GPIO39, CLK_OUT3, SUBSPICS1 -11 38 I/O/T GPIO38, FSPIWP, SUBSPIWP -12 37 I/O/T SPIDQS, GPIO37, FSPIQ, SUBSPIQ -13 36 I/O/T SPIIO7, GPIO36, FSPICLK, SUBSPICLK -14 35 I/O/T SPIIO6, GPIO35, FSPID, SUBSPID -15 34 I/O/T SPIIO5, GPIO34, FSPICS0, SUBSPICS0 -16 33 I/O/T SPIIO4, GPIO33, FSPIHD, SUBSPIHD -17 26 I/O/T SPICS1, GPIO26 -18 21 I/O/T RTC_GPIO21, GPIO21 -19 20 I/O/T RTC_GPIO20, GPIO20, U1CTS, ADC2_CH9, CLK_OUT1, USB_D+ -20 19 I/O/T RTC_GPIO19, GPIO19, U1RTS, ADC2_CH8, CLK_OUT2, USB_D- -21 48 I/O/T SPICLK_N, GPIO48, SUBSPICLK_N_DIFF, RGB LED -22 47 I/O/T SPICLK_P, GPIO47, SUBSPICLK_P_DIFF -=== ==== ===== ==================================== - - -.. [#] P: Power supply; I: Input; O: Output; T: High impedance. - - - -For description of function names, please refer to `ESP32-S3 Datasheet `_ (PDF). - - -Pin Layout -^^^^^^^^^^ - -.. figure:: ../../../_static/ESP32-S3_DevKitM-1_pinlayout.jpg - :align: center - :scale: 50% - :alt: ESP32-S3-DevKitM-1 (click to enlarge) - :figclass: align-center - - ESP32-S3-DevKitM-1 Pin Layout (click to enlarge) - - -Hardware Revision Details -========================= - -This is the first revision of this board released. - - -Related Documents -================= - -- `ESP32-S3 Datasheet `_ (PDF) -- `ESP32-S3-MINI-1 & ESP32-S3-MINI-1U Datasheet `_ (PDF) -- `ESP32-S3-DevKitM-1 Schematic `_ (PDF) -- `ESP32-S3-DevKitM-1 PCB layout `_ (PDF) -- `ESP32-S3-DevKitM-1 Dimensions `_ (PDF) -- `ESP32-S3-DevKitM-1 Dimensions source file `_ (DXF) - You can view it with `Autodesk Viewer `_ online - -For further design documentation for the board, please contact us at `sales@espressif.com `_. diff --git a/docs/en/libraries-and-frameworks/libs-frameworks.rst b/docs/en/libraries-and-frameworks/libs-frameworks.rst index 5aa8fe3d2c3c..0793fd7726f0 100644 --- a/docs/en/libraries-and-frameworks/libs-frameworks.rst +++ b/docs/en/libraries-and-frameworks/libs-frameworks.rst @@ -96,6 +96,8 @@ ESP-Protocols components: * `asio `_ is a cross-platform C++ library, see https://think-async.com/Asio/. It provides a consistent asynchronous model using a modern C++ approach. See the `asio documentation `_. +* `esp_wifi_remote `_ is a Wi-Fi communication library that provides standard Wi-Fi API and networking of an external, Wi-Fi capable ESP32 chipset connected to the target device via a specified transport interface. See the :doc:`../api-guides/wifi-expansion`. + ESP-BSP ------- diff --git a/docs/en/migration-guides/release-5.x/5.4/index.rst b/docs/en/migration-guides/release-5.x/5.4/index.rst index cab9e7ac4eec..f6b85cb5e7e5 100644 --- a/docs/en/migration-guides/release-5.x/5.4/index.rst +++ b/docs/en/migration-guides/release-5.x/5.4/index.rst @@ -9,3 +9,5 @@ Migration from 5.3 to 5.4 gcc system bluetooth-classic + storage + wifi diff --git a/docs/en/migration-guides/release-5.x/5.4/storage.rst b/docs/en/migration-guides/release-5.x/5.4/storage.rst new file mode 100644 index 000000000000..41360c019e69 --- /dev/null +++ b/docs/en/migration-guides/release-5.x/5.4/storage.rst @@ -0,0 +1,7 @@ +Storage +======= + +SPI Flash Driver +^^^^^^^^^^^^^^^^ + +XMC-C series flash suspend support has been removed. According to feedback from the flash manufacturer, in some situations the XMC-C flash would require a 1ms interval between resume and next command. This is too long for a software request. Based on the above reason, in order to use suspend safely, we decide to remove flash suspend support from XMC-C series. But you can still force enable it via `CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND`. If you have any questions, please contact espressif business support. diff --git a/docs/en/migration-guides/release-5.x/5.4/system.rst b/docs/en/migration-guides/release-5.x/5.4/system.rst index e6e0ede0156a..f845786e6e47 100644 --- a/docs/en/migration-guides/release-5.x/5.4/system.rst +++ b/docs/en/migration-guides/release-5.x/5.4/system.rst @@ -3,11 +3,17 @@ System :link_to_translation:`zh_CN:[中文]` +ESP-Common +---------- + +``__VA_NARG__`` and its related macros have been re-named to avoid naming collisions, use the new name with ``ESP`` pre-fix, e.g. ``ESP_VA_NARG`` instead. + Log --- - `esp_log_buffer_hex` is deprecated, use `ESP_LOG_BUFFER_HEX` instead. - `esp_log_buffer_char` is deprecated, use `ESP_LOG_BUFFER_CHAR` instead. +- The default value for ``CONFIG_LOG_COLORS`` is now set to false. Colors are added on the host side by default in IDF Monitor. If you want to enable colors in the log output for other console monitors, set ``CONFIG_LOG_COLORS`` to true in your project configuration. To disable automatic coloring in IDF Monitor, run the following command: ``idf.py monitor --disable-auto-color``. ESP ROM --------- diff --git a/docs/en/migration-guides/release-5.x/5.4/wifi.rst b/docs/en/migration-guides/release-5.x/5.4/wifi.rst new file mode 100644 index 000000000000..ddcc2c49f17b --- /dev/null +++ b/docs/en/migration-guides/release-5.x/5.4/wifi.rst @@ -0,0 +1,22 @@ +Wi-Fi +====== + +:link_to_translation:`zh_CN:[中文]` + + +Wi-Fi Scan and Connect +------------------------ + + The following types have been modified: + + - :component_file:`esp_wifi/include/esp_wifi_he_types.h` + + - :cpp:struct:`esp_wifi_htc_omc_t`: + + - ``uph_id``, ``ul_pw_headroom``, ``min_tx_pw_flag`` are deprecated. + + - :component_file:`esp_wifi/include/esp_wifi_types_generic.h` + + - :cpp:struct:`wifi_ap_record_t`: + + - The type of ``bandwidth`` has been changed from ``uint8_t`` to ``wifi_bandwidth_t`` diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index 6600c7eba2e3..b5c07b2b76b8 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -39,7 +39,7 @@ Encrypted Partitions With flash encryption enabled, the following types of data are encrypted by default: -- :ref:`second-stage-bootloader` (Firmware Bootloader) +- :ref:`second-stage-bootloader` - Partition Table - :ref:`nvs_encr_key_partition` - Otadata @@ -175,39 +175,39 @@ Read and write access to eFuse bits is controlled by appropriate fields in the r Flash Encryption Process ------------------------ -Assuming that the eFuse values are in their default states and the firmware bootloader is compiled to support flash encryption, the flash encryption process executes as shown below: +Assuming that the eFuse values are in their default states and the second stage bootloader is compiled to support flash encryption, the flash encryption process executes as shown below: .. only:: not SOC_FLASH_ENCRYPTION_XTS_AES - 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. + 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The first stage (ROM) bootloader loads the second stage bootloader. - 2. Firmware bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b0000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* > *Flash Encryption Block* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__]. + 2. Second stage bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b0000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* > *Flash Encryption Block* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__]. - 3. Firmware bootloader first checks if a valid key is already present in the eFuse (e.g., burned using espefuse tool), then the process of key generation is skipped and the same key is used for flash encryption process. Otherwise, Firmware bootloader uses RNG (random) module to generate an AES-256 bit key and then writes it into the ``flash_encryption`` eFuse. The key cannot be accessed via software as the write and read protection bits for the ``flash_encryption`` eFuse are set. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software. + 3. Second stage bootloader first checks if a valid key is already present in the eFuse (e.g., burned using espefuse tool), then the process of key generation is skipped and the same key is used for flash encryption process. Otherwise, Second stage bootloader uses RNG (random) module to generate an AES-256 bit key and then writes it into the ``flash_encryption`` eFuse. The key cannot be accessed via software as the write and read protection bits for the ``flash_encryption`` eFuse are set. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software. - 4. Flash encryption block encrypts the flash contents - the firmware bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. + 4. Flash encryption block encrypts the flash contents - the second stage bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. - 5. Firmware bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b0000001) to mark the flash contents as encrypted. Odd number of bits is set. + 5. Second stage bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b0000001) to mark the flash contents as encrypted. Odd number of bits is set. - 6. For :ref:`flash-enc-development-mode`, the firmware bootloader sets only the eFuse bits ``DISABLE_DL_DECRYPT`` and ``DISABLE_DL_CACHE`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. + 6. For :ref:`flash-enc-development-mode`, the second stage bootloader sets only the eFuse bits ``DISABLE_DL_DECRYPT`` and ``DISABLE_DL_CACHE`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. - 7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets the eFuse bits ``DISABLE_DL_ENCRYPT``, ``DISABLE_DL_DECRYPT``, and ``DISABLE_DL_CACHE`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. + 7. For :ref:`flash-enc-release-mode`, the second stage bootloader sets the eFuse bits ``DISABLE_DL_ENCRYPT``, ``DISABLE_DL_DECRYPT``, and ``DISABLE_DL_CACHE`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. - 8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. + 8. The device is then rebooted to start executing the encrypted image. The second stage bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. .. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256 - 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. + 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The first stage (ROM) bootloader loads the second stage bootloader. - 2. Firmware bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* > *Auto Encryption Block* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__]. + 2. Second stage bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* > *Auto Encryption Block* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__]. - 3. Firmware bootloader first checks if a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process. Otherwise, Firmware bootloader uses RNG (random) module to generate an 256 bit or 512 bit key, depending on the value of :ref:`Size of generated XTS-AES key `, and then writes it into respectively one or two `BLOCK_KEYN` eFuses. The software also updates the ``KEY_PURPOSE_N`` for the blocks where the keys were stored. The key cannot be accessed via software as the write and read protection bits for one or two `BLOCK_KEYN` eFuses are set. ``KEY_PURPOSE_N`` field is write-protected as well. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software. + 3. Second stage bootloader first checks if a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process. Otherwise, second stage bootloader uses RNG (random) module to generate an 256 bit or 512 bit key, depending on the value of :ref:`Size of generated XTS-AES key `, and then writes it into respectively one or two `BLOCK_KEYN` eFuses. The software also updates the ``KEY_PURPOSE_N`` for the blocks where the keys were stored. The key cannot be accessed via software as the write and read protection bits for one or two `BLOCK_KEYN` eFuses are set. ``KEY_PURPOSE_N`` field is write-protected as well. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software. - 4. Flash encryption block encrypts the flash contents - the firmware bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. + 4. Flash encryption block encrypts the flash contents - the second stage bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. - 5. Firmware bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set. + 5. Second stage bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set. - 6. For :ref:`flash-enc-development-mode`, the firmware bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the firmware bootloader by default sets the following eFuse bits: + 6. For :ref:`flash-enc-development-mode`, the second stage bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the second stage bootloader by default sets the following eFuse bits: .. list:: @@ -217,45 +217,45 @@ Assuming that the eFuse values are in their default states and the firmware boot - ``HARD_DIS_JTAG`` - ``DIS_LEGACY_SPI_BOOT`` - 7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. + 7. For :ref:`flash-enc-release-mode`, the second stage bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. - 8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. + 8. The device is then rebooted to start executing the encrypted image. The second stage bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. .. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and not SOC_FLASH_ENCRYPTION_XTS_AES_256 and not SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK - 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. + 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The first stage (ROM) bootloader loads the second stage bootloader. - 2. Firmware bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_. + 2. Second stage bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_. - 3. Firmware bootloader uses RNG (random) module to generate an 256 bit key and then writes it into `BLOCK_KEYN` eFuse. The software also updates the ``KEY_PURPOSE_N`` for the block where the key is stored. The key cannot be accessed via software as the write and read protection bits for `BLOCK_KEYN` eFuse are set. ``KEY_PURPOSE_N`` field is write-protected as well. The flash encryption is completely conducted by hardware, and the key cannot be accessed via software. If a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process. + 3. Second stage bootloader uses RNG (random) module to generate an 256 bit key and then writes it into `BLOCK_KEYN` eFuse. The software also updates the ``KEY_PURPOSE_N`` for the block where the key is stored. The key cannot be accessed via software as the write and read protection bits for `BLOCK_KEYN` eFuse are set. ``KEY_PURPOSE_N`` field is write-protected as well. The flash encryption is completely conducted by hardware, and the key cannot be accessed via software. If a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process. - 4. Flash encryption block encrypts the flash contents - the firmware bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. + 4. Flash encryption block encrypts the flash contents - the second stage bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. - 5. Firmware bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set. + 5. Second stage bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set. - 6. For :ref:`flash-enc-development-mode`, the firmware bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the firmware bootloader by default sets the eFuse bits ``DIS_DOWNLOAD_ICACHE``, ``DIS_PAD_JTAG``, ``DIS_USB_JTAG`` and ``DIS_LEGACY_SPI_BOOT``. + 6. For :ref:`flash-enc-development-mode`, the second stage bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the second stage bootloader by default sets the eFuse bits ``DIS_DOWNLOAD_ICACHE``, ``DIS_PAD_JTAG``, ``DIS_USB_JTAG`` and ``DIS_LEGACY_SPI_BOOT``. - 7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. + 7. For :ref:`flash-enc-release-mode`, the second stage bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. - 8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. + 8. The device is then rebooted to start executing the encrypted image. The second stage bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. .. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK - 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader. + 1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The first stage (ROM) bootloaders loads the second stage bootloader. - 2. Firmware bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_. + 2. The second stage bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_. - 3. Firmware bootloader uses RNG (random) module to generate an 256 or 128 bit key (depends on :ref:`Size of generated XTS-AES key `) and then writes it into `BLOCK_KEY0` eFuse. The software also updates the ``XTS_KEY_LENGTH_256`` according to the chosen option. The key cannot be accessed via software as the write and read protection bits for ``BLOCK_KEY0`` eFuse are set. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software. If 128-bit flash encryption key is used, then only the lower 128 bits of the eFuse key block are read-protected, the remaining 128 bits are readable, which is required for secure boot. The entire eFuse block is write-protected. If the FE key is 256 bits long, then ``XTS_KEY_LENGTH_256`` is 1, otherwise it is 0. To prevent this eFuse from being accidentally changed in the future (from 0 to 1), we set a write-protect bit for the RELEASE mode. If a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process. + 3. The second stage bootloader uses RNG (random) module to generate an 256 or 128 bit key (depends on :ref:`Size of generated XTS-AES key `) and then writes it into `BLOCK_KEY0` eFuse. The software also updates the ``XTS_KEY_LENGTH_256`` according to the chosen option. The key cannot be accessed via software as the write and read protection bits for ``BLOCK_KEY0`` eFuse are set. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software. If 128-bit flash encryption key is used, then only the lower 128 bits of the eFuse key block are read-protected, the remaining 128 bits are readable, which is required for secure boot. The entire eFuse block is write-protected. If the FE key is 256 bits long, then ``XTS_KEY_LENGTH_256`` is 1, otherwise it is 0. To prevent this eFuse from being accidentally changed in the future (from 0 to 1), we set a write-protect bit for the RELEASE mode. If a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process. - 4. Flash encryption block encrypts the flash contents - the firmware bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. + 4. Flash encryption block encrypts the flash contents - the second stage bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions. - 5. Firmware bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set. + 5. The second stage bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set. - 6. For :ref:`flash-enc-development-mode`, the firmware bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the firmware bootloader by default sets the eFuse bits ``DIS_DOWNLOAD_ICACHE``, ``DIS_PAD_JTAG``, and ``DIS_DIRECT_BOOT``. + 6. For :ref:`flash-enc-development-mode`, the second stage bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the second stage bootloader by default sets the eFuse bits ``DIS_DOWNLOAD_ICACHE``, ``DIS_PAD_JTAG``, and ``DIS_DIRECT_BOOT``. - 7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. + 7. For :ref:`flash-enc-release-mode`, the second stage bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`. - 8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. + 8. The device is then rebooted to start executing the encrypted image. The second stage bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM. During the development stage, there is a frequent need to program different plaintext flash images and test the flash encryption process. This requires that Firmware Download mode is able to load new plaintext images as many times as it might be needed. However, during manufacturing or production stages, Firmware Download mode should not be allowed to access flash contents for security reasons. @@ -316,7 +316,7 @@ Enabling flash encryption will increase the size of bootloader, which might requ This command does not include any user files which should be written to the partitions on the flash memory. Please write them manually before running this command otherwise the files should be encrypted separately before writing. - This command will write to flash memory unencrypted images: the firmware bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the firmware bootloader encrypts: the firmware bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed. + This command will write to flash memory unencrypted images: the second stage bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the second stage bootloader encrypts: the second stage bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed. A sample output of the first {IDF_TARGET_NAME} boot after enabling flash encryption is given below: @@ -486,7 +486,7 @@ Enabling flash encryption will increase the size of bootloader, which might requ This command does not include any user files which should be written to the partitions on the flash memory. Please write them manually before running this command otherwise the files should be encrypted separately before writing. - This command will write to flash memory unencrypted images: the firmware bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the firmware bootloader encrypts: the firmware bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed. + This command will write to flash memory unencrypted images: the second stage bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the second stage bootloader encrypts: the second stage bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed. If using Development Mode, then the easiest way to update and re-flash binaries is :ref:`encrypt-partitions`. @@ -549,7 +549,7 @@ Enabling flash encryption will increase the size of bootloader, which might requ This command does not include any user files which should be written to the partitions on the flash memory. Please write them manually before running this command otherwise the files should be encrypted separately before writing. - This command will write to flash memory unencrypted images: the firmware bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the firmware bootloader encrypts: the firmware bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed. + This command will write to flash memory unencrypted images: the second stage bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the second stage bootloader encrypts: the second stage bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed. Once the flash encryption is enabled in Release mode, the bootloader will write-protect the ``{IDF_TARGET_CRYPT_CNT}`` eFuse. @@ -576,14 +576,14 @@ When using Flash Encryption in production: Enable Flash Encryption Externally ---------------------------------- -In the process mentioned above, flash encryption related eFuses which ultimately enable flash encryption are programmed through the firmware bootloader. Alternatively, all the eFuses can be programmed with the help of ``espefuse`` tool. Please refer :ref:`enable-flash-encryption-externally` for more details. +In the process mentioned above, flash encryption related eFuses which ultimately enable flash encryption are programmed through the second stage bootloader. Alternatively, all the eFuses can be programmed with the help of ``espefuse`` tool. Please refer :ref:`enable-flash-encryption-externally` for more details. Possible Failures ----------------- Once flash encryption is enabled, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value will have an odd number of bits set. It means that all the partitions marked with the encryption flag are expected to contain encrypted ciphertext. Below are the three typical failure cases if the {IDF_TARGET_NAME} is erroneously loaded with plaintext data: -1. If the bootloader partition is re-flashed with a **plaintext firmware bootloader image**, the ROM bootloader will fail to load the firmware bootloader resulting in the following failure: +1. If the bootloader partition is re-flashed with a **plaintext second stage bootloader image**, the first stage (ROM) bootloader will fail to load the second stage bootloader resulting in the following failure: .. only:: esp32 @@ -635,7 +635,7 @@ Once flash encryption is enabled, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value wil This error also appears if the flash contents are erased or corrupted. -2. If the firmware bootloader is encrypted, but the partition table is re-flashed with a **plaintext partition table image**, the bootloader will fail to read the partition table resulting in the following failure: +2. If the second stage bootloader is encrypted, but the partition table is re-flashed with a **plaintext partition table image**, the bootloader will fail to read the partition table resulting in the following failure: .. code-block:: bash @@ -727,7 +727,7 @@ Whenever the ``{IDF_TARGET_CRYPT_CNT}`` eFuse is set to a value with an odd numb - Executable application code in flash (IROM). - All read-only data stored in flash (DROM). - Any data accessed via :cpp:func:`spi_flash_mmap`. -- The firmware bootloader image when it is read by the ROM bootloader. +- The second stage bootloader image when it is read by the first stage (ROM) bootloader. .. important:: @@ -776,7 +776,7 @@ OTA updates to encrypted partitions will automatically write encrypted data if t Before building the application image for OTA updating of an already encrypted device, enable the option :ref:`Enable flash encryption on boot ` in project configuration menu. -For general information about ESP-IDF OTA updates, please refer to :doc:`OTA <../api-reference/system/ota>` +For general information about ESP-IDF OTA updates, please refer to :doc:`OTA <../api-reference/system/ota>`. .. _updating-encrypted-flash-serial: @@ -976,7 +976,7 @@ However, before the first boot you can choose to keep any of these features enab The eFuse ``FLASH_CRYPT_CONFIG`` determines the number of bits in the flash encryption key which are "tweaked" with the block offset. For details, see :ref:`flash-encryption-algorithm`. - On the first boot of the firmware bootloader, this value is set to the maximum ``0xF``. + On the first boot of the second stage bootloader, this value is set to the maximum ``0xF``. It is possible to burn this eFuse manually and write protect it before the first boot in order to select different tweak values. However, this is not recommended. diff --git a/docs/en/security/secure-boot-v1.rst b/docs/en/security/secure-boot-v1.rst index 4d618af1fa7f..d67b75999a86 100644 --- a/docs/en/security/secure-boot-v1.rst +++ b/docs/en/security/secure-boot-v1.rst @@ -30,7 +30,7 @@ Background - To understand the secure boot process, please familiarize yourself with the standard :doc:`../api-guides/startup`. -- Both stages of the boot process, including initial software bootloader load and subsequent partition & app loading, are verified by the secure boot process, in a chain of trust relationship. +- Both stages of the boot process, including initial second stage bootloader load and subsequent partition & app loading, are verified by the secure boot process, in a chain of trust relationship. Secure Boot Process Overview @@ -42,18 +42,18 @@ This is a high-level overview of the secure boot process. Step-by-step instructi 2. Secure boot defaults to signing images and partition table data during the build process. The ``Secure boot private signing key`` config item is a file path to an ECDSA public/private key pair in a PEM format file. -3. The software bootloader image is built by ESP-IDF with secure boot support enabled, and the public key for signature verification is integrated into the bootloader image. This software bootloader image is flashed at offset 0x1000. +3. The second stage bootloader image is built by ESP-IDF with secure boot support enabled, and the public key for signature verification is integrated into the bootloader image. This second stage bootloader image is flashed at offset 0x1000. -4. On the first boot, the software bootloader follows the following process to enable a secure boot: +4. On the first boot, the second stage bootloader follows the following process to enable a secure boot: - Hardware secure boot support generates a device-secure bootloader key and a secure digest. The secure bootloader key is generated with the help of the hardware RNG, and then stored in eFuse with read and write protection enabled. The digest is derived from the key, an initialization vector (IV), and the bootloader image contents. - The secure digest is flashed at offset 0x0 in the flash. - Depending on Secure Boot Configuration, eFuses are burned to disable JTAG and the ROM BASIC interpreter. It is **strongly recommended** that these options are turned on. - - Bootloader permanently enables secure boot by burning the ABS_DONE_0 eFuse. The software bootloader then becomes protected. After this point, the chip will only boot a bootloader image if the digest matches. + - Bootloader permanently enables secure boot by burning the ABS_DONE_0 eFuse. The second stage bootloader then becomes protected. After this point, the chip will only boot a bootloader image if the digest matches. -5. On subsequent boots, the ROM bootloader sees that the secure boot eFuse is burned, reads the saved digest at 0x0, and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see :ref:`secure-boot-hardware-support`. +5. On subsequent boots, the first stage (ROM) bootloader sees that the secure boot eFuse is burned, reads the saved digest at 0x0, and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see :ref:`secure-boot-hardware-support`. -6. When running in secure boot mode, the software bootloader uses the secure boot signing key, the public key of which is embedded in the bootloader itself and therefore validated as part of the bootloader, to verify the signature appended to all subsequent partition tables and app images before they are booted. +6. When running in secure boot mode, the second stage bootloader uses the secure boot signing key, the public key of which is embedded in the bootloader itself and therefore validated as part of the bootloader, to verify the signature appended to all subsequent partition tables and app images before they are booted. Keys @@ -73,7 +73,7 @@ The following keys are used by the secure boot process: - ``secure boot signing key`` is a standard ECDSA public/private key pair in PEM format, see :ref:`secure-boot-image-signing-algorithm`. - - The public key from this key pair is compiled into the software bootloader. It is only used for signature verification purposes and not signature creation. This public key is used to verify the second stage of booting, including the partition table and app image, before booting continues. The public key can be freely distributed; it does not need to be kept secret. + - The public key from this key pair is compiled into the second stage bootloader. It is only used for signature verification purposes and not signature creation. This public key is used to verify the second stage of booting, including the partition table and app image, before booting continues. The public key can be freely distributed; it does not need to be kept secret. - The private key from this key pair **must be securely kept private**, as anyone who has this key can authenticate to any bootloader that is configured with a secure boot and the matching public key. @@ -117,7 +117,7 @@ How to Enable Secure Boot ``idf.py flash`` does not flash the bootloader if secure boot is enabled. -8. Reset the {IDF_TARGET_NAME} and it will boot the software bootloader you flashed. The software bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the {IDF_TARGET_NAME} to verify that secure boot is enabled and no errors have occurred due to the build configuration. +8. Reset the {IDF_TARGET_NAME} and it will boot the second stage bootloader you flashed. The second stage bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the {IDF_TARGET_NAME} to verify that secure boot is enabled and no errors have occurred due to the build configuration. .. note:: @@ -127,13 +127,13 @@ How to Enable Secure Boot If {IDF_TARGET_NAME} is reset or powered down during the first boot, it will start the process again on the next boot. -9. On subsequent boots, the secure boot hardware will verify the software bootloader has not changed using the secure bootloader key, and then the software bootloader will verify the signed partition table and app image using the public key portion of the secure boot signing key. +9. On subsequent boots, the secure boot hardware will verify the second stage bootloader has not changed using the secure bootloader key, and then the second stage bootloader will verify the signed partition table and app image using the public key portion of the secure boot signing key. .. _secure-boot-reflashable: -Reflashable Software Bootloader -------------------------------- +Reflashable Second Stage Bootloader +----------------------------------- Configuration ``Secure Boot: One-Time Flash`` is the recommended configuration for production devices. In this mode, each device gets a unique key that is never stored outside the device. @@ -229,7 +229,7 @@ The following sections contain low-level reference descriptions of various secur Secure Boot Hardware Support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The first stage of secure boot verification, i.e., checking the software bootloader, is done via hardware. The {IDF_TARGET_NAME}'s secure boot support hardware can perform three basic operations: +The first stage of secure boot verification, i.e., checking the second stage bootloader, is done via hardware. The {IDF_TARGET_NAME}'s secure boot support hardware can perform three basic operations: 1. Generate a random sequence of bytes from a hardware random number generator. diff --git a/docs/en/security/secure-boot-v2.rst b/docs/en/security/secure-boot-v2.rst index 7cc0a8d22774..dda65530e18b 100644 --- a/docs/en/security/secure-boot-v2.rst +++ b/docs/en/security/secure-boot-v2.rst @@ -31,7 +31,7 @@ Secure Boot v2 For ESP32 before chip revision v3.0, refer to :doc:`secure-boot-v1`. It is recommended to use Secure Boot v2 if you have a chip revision that supports it. Secure Boot v2 is safer and more flexible than Secure Boot V1. - Secure Boot v2 uses {IDF_TARGET_SBV2_SCHEME} based app and bootloader :ref:`second-stage-bootloader` verification. This document can also be used as a reference for signing apps using the {IDF_TARGET_SBV2_SCHEME} scheme without signing the bootloader. + Secure Boot v2 uses {IDF_TARGET_SBV2_SCHEME} based app and :ref:`second-stage-bootloader` verification. This document can also be used as a reference for signing apps using the {IDF_TARGET_SBV2_SCHEME} scheme without signing the bootloader. .. only:: esp32 @@ -49,7 +49,7 @@ Secure Boot v2 Background ---------- -Secure Boot protects a device from running any unauthorized (i.e., unsigned) code by checking that each piece of software that is being booted is signed. On an {IDF_TARGET_NAME}, these pieces of software include the second stage bootloader and each application binary. Note that the first stage bootloader does not require signing as it is ROM code and thus cannot be changed. +Secure Boot protects a device from running any unauthorized (i.e., unsigned) code by checking that each piece of software that is being booted is signed. On an {IDF_TARGET_NAME}, these pieces of software include the second stage bootloader and each application binary. Note that the first stage (ROM) bootloader does not require signing as it is ROM code and thus cannot be changed. .. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC) @@ -65,7 +65,7 @@ Secure Boot protects a device from running any unauthorized (i.e., unsigned) cod The Secure Boot process on {IDF_TARGET_NAME} involves the following steps: -1. The first stage bootloader (i.e. ROM boot), which is residing in ROM, loads the second stage bootloader, and the second stage bootloader's {IDF_TARGET_SBV2_SCHEME} signature is verified. Only if the verification is successful, the second stage bootloader is executed. +1. The first stage (ROM) bootloader loads the second stage bootloader, and the second stage bootloader's {IDF_TARGET_SBV2_SCHEME} signature is verified. Only if the verification is successful, the second stage bootloader is executed. 2. When the second stage bootloader loads a particular application image, the application's {IDF_TARGET_SBV2_SCHEME} signature is verified. If the verification is successful, the application image is executed. @@ -88,7 +88,7 @@ Advantages - Conservatively: The old key is revoked after the bootloader and application have successfully migrated to a new key. - Aggressively: The key is revoked as soon as verification with this key fails. -- The same image format and signature verification method is applied for applications and the software bootloader. +- The same image format and signature verification method is applied for applications and the second stage bootloader. - No secrets are stored on the device. Therefore, it is immune to passive side-channel attacks, e.g., timing or power analysis. @@ -415,7 +415,7 @@ How To Enable Secure Boot v2 ``idf.py flash`` does not flash the bootloader if Secure Boot is enabled. -10. Reset the {IDF_TARGET_NAME} and it will boot the software bootloader you flashed. The software bootloader will enable Secure Boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the {IDF_TARGET_NAME} to verify that Secure Boot is enabled and no errors have occurred due to the build configuration. +10. Reset the {IDF_TARGET_NAME} and it will boot the second stage bootloader you flashed. The second stage bootloader will enable Secure Boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the {IDF_TARGET_NAME} to verify that Secure Boot is enabled and no errors have occurred due to the build configuration. .. note:: @@ -425,7 +425,7 @@ How To Enable Secure Boot v2 If the {IDF_TARGET_NAME} is reset or powered down during the first boot, it will start the process again on the next boot. -11. On subsequent boots, the Secure Boot hardware will verify the software bootloader has not changed and the software bootloader will verify the signed app image using the validated public key portion of its appended signature block. +11. On subsequent boots, the Secure Boot hardware will verify that the second stage bootloader has not changed, and the second stage bootloader will verify the signed app image using the validated public key portion of its appended signature block. Restrictions After Secure Boot Is Enabled @@ -435,17 +435,17 @@ Restrictions After Secure Boot Is Enabled - Please note that enabling Secure Boot or flash encryption disables the USB-OTG USB stack in the ROM, disallowing updates via the serial emulation or Device Firmware Update (DFU) on that port. +- After Secure Boot is enabled, further read-protection of eFuse keys is not possible. This is done to prevent an attacker from read-protecting the eFuse block that contains the Secure Boot public key digest, which could result in immediate denial of service and potentially enable a fault injection attack to bypass the signature verification. For further information on read-protected keys, see the details below. + Burning read-protected keys ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -After Secure Boot is enabled, no further eFuses can be read-protected, because this might allow an attacker to read-protect the efuse block holding the public key digest, causing an immediate denial of service and possibly allowing an additional fault injection attack to bypass the signature protection. - -If :doc:`/security/flash-encryption` is enabled by the 2nd stage bootloader, it ensures that the flash encryption key generated on the first boot shall already be read-protected. - -In case you need to read-protect a key after Secure Boot has been enabled on the device, for example, +**Read protected keys**: +The following keys must be read-protected on the device, the respective hardware will have access them directly (not readable by software): .. list:: - :SOC_FLASH_ENC_SUPPORTED:* the flash encryption key + + :SOC_FLASH_ENC_SUPPORTED:* Flash encryption key :SOC_HMAC_SUPPORTED:* HMAC keys @@ -453,12 +453,21 @@ In case you need to read-protect a key after Secure Boot has been enabled on the :SOC_KEY_MANAGER_SUPPORTED:* Key Manager keys - you need to enable the config :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS` at the same time when you enable Secure Boot to prevent disabling the ability to read-protect further efuses. +**Non-read protected keys**: +The following keys must not be read-protected on the device as the software needs to access them (readable by software): -It is highly recommended that all such keys must been burned before enabling secure boot. +.. list:: -In case you need to enable :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`, make sure that you burn the efuse {IDF_TARGET_EFUSE_WR_DIS_RD_DIS}, using ``esp_efuse_write_field_bit()`` API from ``esp_efuse.h``, once all the read-protected efuse keys have been programmed. + :SOC_SECURE_BOOT_SUPPORTED:* Secure boot public key digest + * User data + +When Secure Boot is enabled, it shall disable the ability to read-protect further eFuses by default. If you want keep the ability to read-protect an eFuse later in the application (e.g, a key mentioned in the above list of read-protected keys) then you need to enable the config :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS` at the same time when you enable Secure Boot. + +Ideally, it is strongly recommended that all such keys must been burned before enabling secure boot. However, if you need to enable :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`, make sure that you burn the eFuse {IDF_TARGET_EFUSE_WR_DIS_RD_DIS}, using :cpp:func:`esp_efuse_write_field_bit`, once all the read-protected eFuse keys have been programmed. + +.. note:: + If :doc:`/security/flash-encryption` is enabled by the 2nd stage bootloader at the time of enabling Secure Boot, it ensures that the flash encryption key generated on the first boot shall already be read-protected. .. _secure-boot-v2-generate-key: @@ -580,9 +589,9 @@ Secure Boot Best Practices * Between 1 and 3 {IDF_TARGET_SBV2_KEY} public key pairs (Keys #0, #1, #2) should be computed independently and stored separately. * The KEY_DIGEST eFuses should be write-protected after being programmed. * The unused KEY_DIGEST slots must have their corresponding KEY_REVOKE eFuse burned to permanently disable them. This must happen before the device leaves the factory. - * The eFuses can either be written by the software bootloader during first boot after enabling ``Secure Boot v2`` from menuconfig or can be done using ``espefuse.py`` which communicates with the serial bootloader program in ROM. + * The eFuses can either be written by the second stage bootloader during first boot after enabling ``Secure Boot v2`` from menuconfig or can be done using ``espefuse.py`` which communicates with the serial bootloader program in ROM. * The KEY_DIGESTs should be numbered sequentially beginning at key digest #0. If key digest #1 is used, key digest #0 should be used. If key digest #2 is used, key digest #0 & #1 must be used. - * The software bootloader is non-OTA upgradeable, and is signed using at least one, possibly all three, private keys and flashed in the factory. + * The second stage bootloader is non-OTA upgradeable, and is signed using at least one, possibly all three, private keys and flashed in the factory. * Apps should only be signed with a single private key, with the others being stored securely elsewhere. However, they may be signed with multiple private keys if some are being revoked, see :ref:`secure-boot-v2-key-revocation` below. @@ -631,14 +640,13 @@ Secure Boot Best Practices 4. The active partition is set to the new OTA application's partition. 5. The device resets and loads the bootloader that is verified with key #N-1, which then boots the new app verified with key #N. 6. The new app verifies the bootloader with key #N as a final check, and then runs code to revoke key #N-1, i.e., sets KEY_REVOKE eFuse bit. - 7. The API `esp_ota_revoke_secure_boot_public_key()` can be used to revoke the key #N-1. + 7. The API :cpp:func:`esp_ota_revoke_secure_boot_public_key` can be used to revoke the key #N-1. * A similar approach can also be used to physically re-flash with a new key. For physical re-flashing, the bootloader content can also be changed at the same time. .. note:: - It may be necessary to revoke a key that isn't currently being used. - For example, if the active application is signed with key #0, but key #1 becomes compromised, you should revoke key #1 by using the above approach. The new OTA update should continue to be signed with key #0, and the API `esp_ota_revoke_secure_boot_public_key(SECURE_BOOT_PUBLIC_KEY_INDEX_[N])` can be used to revoke the key #N (N would be 1 in this case). After revoking, all remaining unrevoked keys can still be used to sign future applications. + It may be necessary to revoke a key that isn't currently being used. For example, if the active application is signed with key #0, but key #1 becomes compromised, you should revoke key #1 by using the above approach. The new OTA update should continue to be signed with key #0, and the API `esp_ota_revoke_secure_boot_public_key (SECURE_BOOT_PUBLIC_KEY_INDEX_[N])` can be used to revoke the key #N (N would be 1 in this case). After revoking, all remaining unrevoked keys can still be used to sign future applications. .. _secure-boot-v2-aggressive-key-revocation: @@ -664,8 +672,7 @@ The following sections contain low-level reference descriptions of various Secur Secure Boot is integrated into the ESP-IDF build system, so ``idf.py build`` will sign an app image, and ``idf.py bootloader`` will produce a signed bootloader if :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` is enabled. -However, it is possible to use the ``idf.py`` or the ``openssl`` tool to generate standalone signatures and verify them. Using ``idf.py`` is recommended, but in case you need to generate or verify signatures in non-ESP-IDF environments, -you could also use the ``openssl`` commands as the Secure Boot V2 signature generation is compliant with the standard signing algorithms. +However, it is possible to use the ``idf.py`` or the ``openssl`` tool to generate standalone signatures and verify them. Using ``idf.py`` is recommended, but in case you need to generate or verify signatures in non-ESP-IDF environments, you could also use the ``openssl`` commands as the Secure Boot v2 signature generation is compliant with the standard signing algorithms. Generating and Verifying signatures using ``idf.py`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/en/security/security-features-enablement-workflows.rst b/docs/en/security/security-features-enablement-workflows.rst index 35e36344b837..973c7305b17d 100644 --- a/docs/en/security/security-features-enablement-workflows.rst +++ b/docs/en/security/security-features-enablement-workflows.rst @@ -18,6 +18,11 @@ When enabling security features on ESP32 SoCs, it is recommended that power supp This guide describes a set of workflows to enable security features on the device with the assistance of an external host machine. These workflows are broken down into various stages, with each stage generating signing/encryption keys on the host machine. This allows for greater chances of recovery in case of power or other failures. Furthermore, these workflows expedites the overall provisioning process via the use of the host machine (e.g., encrypting firmware on the host is quicker than on the device). +.. only:: TARGET_SUPPORT_QEMU + + .. important:: + + It is possible to try out the security features for {IDF_TARGET_NAME} target SoC under :doc:`../api-guides/tools/qemu` virtually. Once the security workflow is established, you can then proceed to the real hardware. Goals ----- @@ -25,7 +30,7 @@ Goals #. Simplify the traditional workflow for enabling security features with stepwise instructions. #. Design a more flexible workflow when compared to the traditional firmware-based workflow. #. Improve reliability by dividing the workflow into small operations. -#. Eliminate dependency on :ref:`second-stage-bootloader` (firmware bootloader). +#. Eliminate dependency on :ref:`second-stage-bootloader`. Prerequisites ------------- @@ -324,7 +329,7 @@ In this case all the eFuses related to Flash Encryption are written with help of .. only:: esp32 - If your ESP32 uses non-default :ref:`FLASH_CRYPT_CONFIG value in eFuse ` then you will need to pass the ``--flash_crypt_conf`` argument to ``espsecure.py`` to set the matching value. This will not happen when the Flash Encryption is enabled by the firmware bootloader but may happen when burning eFuses manually to enable Flash Encryption. + If your ESP32 uses non-default :ref:`FLASH_CRYPT_CONFIG value in eFuse ` then you will need to pass the ``--flash_crypt_conf`` argument to ``espsecure.py`` to set the matching value. This will not happen when the Flash Encryption is enabled by the second stage bootloader but may happen when burning eFuses manually to enable Flash Encryption. The command ``espsecure.py decrypt_flash_data`` can be used with the same options (and different input or output files), to decrypt ciphertext flash contents or a previously encrypted file. @@ -518,7 +523,7 @@ In this workflow we shall use ``espsecure`` tool to generate signing keys and us 6. Configure the project - By default, the ROM bootloader would only verify the :ref:`second-stage-bootloader` (firmware bootloader). The firmware bootloader would verify the app partition only when the :ref:`CONFIG_SECURE_BOOT` option is enabled (and :ref:`CONFIG_SECURE_BOOT_VERSION` is set to ``SECURE_BOOT_V2_ENABLED``) while building the bootloader. + By default, the first stage (ROM) bootloader would only verify the :ref:`second-stage-bootloader`. The second stage bootloader would verify the app partition only when the :ref:`CONFIG_SECURE_BOOT` option is enabled (and :ref:`CONFIG_SECURE_BOOT_VERSION` is set to ``SECURE_BOOT_V2_ENABLED``) while building the bootloader. A) Open the :ref:`project-configuration-menu`, in ``Security features`` set ``Enable hardware Secure Boot in bootloader`` to enable Secure Boot. diff --git a/docs/en/security/security.rst b/docs/en/security/security.rst index 07e3ef2b2620..d834e7c9d4b0 100644 --- a/docs/en/security/security.rst +++ b/docs/en/security/security.rst @@ -13,6 +13,12 @@ This guide provides an overview of the overall security features available in va In this guide, most used commands are in the form of ``idf.py secure-``, which is a wrapper around corresponding ``espsecure.py ``. The ``idf.py`` based commands provides more user-friendly experience, although may lack some of the advanced functionality of their ``espsecure.py`` based counterparts. +.. only:: TARGET_SUPPORT_QEMU + + .. important:: + + It is possible to try out the security features for {IDF_TARGET_NAME} target SoC under :doc:`../api-guides/tools/qemu` virtually. Once the security workflow is established, you can then proceed to the real hardware. + Goals ----- diff --git a/docs/en/security/vulnerabilities.rst b/docs/en/security/vulnerabilities.rst index a8629f945e98..00d87aad5ff3 100644 --- a/docs/en/security/vulnerabilities.rst +++ b/docs/en/security/vulnerabilities.rst @@ -10,6 +10,15 @@ This page briefly lists all of the vulnerabilities that are discovered and fixed CVE-2024 -------- +CVE-2024-30949 +~~~~~~~~~~~~~~ + +RISC-V gettimeofday system call vulnerability in Newlib's + +* Impact: ESP-IDF does not use system call implementations from Newlib +* Resolution: NA + + CVE-2024-28183 ~~~~~~~~~~~~~~ diff --git a/docs/en/versions.rst b/docs/en/versions.rst index b18ed5dd266e..b6eec4d8be27 100644 --- a/docs/en/versions.rst +++ b/docs/en/versions.rst @@ -125,7 +125,7 @@ The local ESP-IDF version can be checked by using idf.py:: idf.py --version -The ESP-IDF version is also compiled into the firmware and can be accessed (as a string) via the macro ``IDF_VER``. The default ESP-IDF bootloader will print the version on boot (the version information is not always updated if the code in the GitHub repo is updated, it only changes if there is a clean build or if that particular source file is recompiled). +The ESP-IDF version is also compiled into the firmware and can be accessed (as a string) via the macro ``IDF_VER``. The default ESP-IDF bootloader prints the version on boot (The version information is not always updated if the code in the GitHub repo is updated, it only changes if there is a clean build or if that particular source file is recompiled). If writing code that needs to support multiple ESP-IDF versions, the version can be checked at compile time using :ref:`compile-time macros `. diff --git a/docs/zh_CN/about.rst b/docs/zh_CN/about.rst index e9b8aa3a37cc..80d668ed1370 100644 --- a/docs/zh_CN/about.rst +++ b/docs/zh_CN/about.rst @@ -30,12 +30,24 @@ {IDF_TARGET_NAME} 是一款支持 2.4 GHz Wi-Fi 和低功耗蓝牙的芯片,搭载 RISC-V RV32IMAC 32 位单核处理器。 +.. only:: esp32c5 + + 本指南为 {IDF_TARGET_NAME} 官方应用开发框架 `ESP-IDF `_ 的配套文档。 + + {IDF_TARGET_NAME} 是一款支持 2.4 & 5 GHz 双频 Wi-Fi、低功耗蓝牙和 802.15.4 Thread/Zigbee 的芯片,搭载 RISC-V RV32IMAC 32 位单核处理器。 + .. only:: esp32c6 本指南为 {IDF_TARGET_NAME} 官方应用开发框架 `ESP-IDF `_ 的配套文档。 {IDF_TARGET_NAME} 是一款支持 2.4 GHz Wi-Fi, 802.15.4 Thread/Zigbee 和低功耗蓝牙的芯片,搭载 RISC-V RV32IMAC 32 位单核处理器。 +.. only:: esp32c61 + + 本指南为 {IDF_TARGET_NAME} 官方应用开发框架 `ESP-IDF `_ 的配套文档。 + + {IDF_TARGET_NAME} 是一款支持 2.4 GHz Wi-Fi 和低功耗蓝牙的芯片,搭载 RISC-V RV32IMAC 32 位单核处理器。 + .. only:: esp32h2 本指南为 {IDF_TARGET_NAME} 官方应用开发框架 `ESP-IDF `_ 的配套文档。 diff --git a/docs/zh_CN/api-guides/ble/ble-feature-support-status.rst b/docs/zh_CN/api-guides/ble/ble-feature-support-status.rst index 60d3919ebb2a..288f0edfe733 100644 --- a/docs/zh_CN/api-guides/ble/ble-feature-support-status.rst +++ b/docs/zh_CN/api-guides/ble/ble-feature-support-status.rst @@ -162,7 +162,7 @@ - |experimental| - |experimental| * - - - Advertising Channel Index + - Randomized Advertising Channel Indexing - |unsupported| - |NA| - |NA| @@ -171,19 +171,19 @@ - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 or esp32c61 |experimental| - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 or esp32c61 |experimental| - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c2 or esp32c5 or esp32c61 |experimental| * - .. centered:: |5.2| @@ -201,14 +201,14 @@ - .. only:: esp32 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c3 or esp32s3 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c3 or esp32s3 or esp32c5 or esp32c61 |experimental| - |unsupported| - .. only:: esp32 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c3 or esp32s3 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c3 or esp32s3 or esp32c5 or esp32c61 |experimental| * - .. centered:: |5.3| @@ -216,31 +216,31 @@ - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |supported| - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |supported| - .. only:: esp32 or esp32c3 or esp32s3 |unsupported| - .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |supported| * - - LE Enhanced Connection Update (Connection Subrating) - - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 + - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |unsupported| .. only:: esp32c3 or esp32s3 |experimental| - |unsupported| - - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 + - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |unsupported| .. only:: esp32c3 or esp32s3 @@ -251,31 +251,31 @@ - .. only:: esp32 or esp32c3 or esp32s3 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c5 or esp32c61 |experimental| - .. only:: esp32 or esp32c3 or esp32s3 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c5 or esp32c61 |experimental| - .. only:: esp32 or esp32c3 or esp32s3 or esp32c2 |unsupported| - .. only:: esp32c6 or esp32h2 or esp32c5 + .. only:: esp32c6 or esp32h2 or esp32c5 or esp32c61 |experimental| * - .. centered:: |5.4| - Advertising Coding Selection - - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 + - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |unsupported| .. only:: esp32c3 or esp32s3 |experimental| - |unsupported| - - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 + - .. only:: esp32 or esp32c6 or esp32c2 or esp32h2 or esp32c5 or esp32c61 |unsupported| .. only:: esp32c3 or esp32s3 diff --git a/docs/zh_CN/api-guides/ble/get-started/ble-connection.rst b/docs/zh_CN/api-guides/ble/get-started/ble-connection.rst index b34bb9fdeb9e..83ae7b84c300 100644 --- a/docs/zh_CN/api-guides/ble/get-started/ble-connection.rst +++ b/docs/zh_CN/api-guides/ble/get-started/ble-connection.rst @@ -11,7 +11,7 @@ - 学习连接的基本概念 - 学习连接相关的参数 -- 学习 NimBLE_Connection 例程的代码结构 +- 学习 :example:`NimBLE_Connection ` 例程的代码结构 连接的基本概念 @@ -23,7 +23,7 @@ *在 Bluetooth LE 5.0 引入扩展广播特性以后, Legacy ADV 和 Extended ADV 对应的连接建立过程略有差异,下以 Legacy ADV 对应的连接建立过程为例。* -当扫描者在某一个广播信道接收到一个广播数据包时,若该广播者是可连接的,那么扫描者可以在同一广播信道发送连接请求 (Connection Request)。对于广播者来说,它可以设置 *接受列表 (Accept List)* 以过滤不受信任的设备,或接受任一扫描者的连接请求。随后,广播者转变为外围设备,扫描者转变为中央设备,两者之间可以在数据信道进行双向通信。 +当扫描者在某一个广播信道接收到一个广播数据包时,若该广播者是可连接的,那么扫描者可以在同一广播信道发送连接请求 (Connection Request)。对于广播者来说,它可以设置 *接受列表 (Filter Accept List)* 以过滤不受信任的设备,或接受任一扫描者的连接请求。随后,广播者转变为外围设备,扫描者转变为中央设备,两者之间可以在数据信道进行双向通信。 如 :ref:`扫描请求与扫描响应 ` 所述,广播者在每一个信道的广播结束以后,都会短暂进入 RX 模式,以接收可能的扫描请求。实际上,这个 RX 过程中还可以接受连接请求。所以对于扫描者来说,发送连接请求的时间窗口和发送扫描请求的时间窗口是类似的。 @@ -73,7 +73,7 @@ 外围设备延迟 (Peripheral Latency) 规定了外围设备在无需发送数据的前提下,最多可忽略的连接事件数量。 -为了理解这个连接参数的作用,让我们以蓝牙鼠标为例,分析其应用场景。用户在使用键盘的过程中,鼠标并没有需要发送的有效数据,此时最好降低数据包发送的频率以节省电量;在使用鼠标的过程中,我们希望鼠标能够尽可能快地发送数据,以降低使用延迟。也就是说,蓝牙鼠标的数据发送是间歇性高频率的。此时,如果仅靠连接间隔参数进行连接调节,则那么较低的连接间隔会导致高能耗,较高的连接间隔会导致高延迟。 +为了理解这个连接参数的作用,让我们以蓝牙鼠标为例。用户在使用键盘的过程中,鼠标并没有需要发送的有效数据,此时最好降低数据包发送的频率以节省电量;在使用鼠标的过程中,我们希望鼠标能够尽可能快地发送数据,以降低使用延迟。也就是说,蓝牙鼠标的数据发送是间歇性高频率的。此时,如果仅靠连接间隔参数进行连接调节,则那么较低的连接间隔会导致高能耗,较高的连接间隔会导致高延迟。 在这种场景下,外围设备延迟机制将是一个完美的解决方案。为了降低蓝牙鼠标的延迟,我们可以将连接间隔设为一个较小的值,例如 10 ms ,那么在密集使用时数据交换频率可达 100 Hz ;随后,我们将外围设备延迟设定为 100 ,那么蓝牙鼠标在不使用的状态下,实际的数据交换频率可降低至 1 Hz 。通过这种设计,我们在不调整连接参数的前提下,实现了可变的数据交换频率,在最大程度上提升了用户体验。 @@ -132,17 +132,17 @@ MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以 例程实践 ------------------------------------------- -在掌握了连接的相关知识以后,接下来让我们结合 NimBLE_Connection 例程代码,学习如何使用 NimBLE 协议栈构建一个简单的外围设备,对学到的知识进行实践。 +在掌握了连接的相关知识以后,接下来让我们结合 :example:`NimBLE_Connection ` 例程代码,学习如何使用 NimBLE 协议栈构建一个简单的外围设备,对学到的知识进行实践。 前提条件 ^^^^^^^^^^^^^^^ -1. 一块支持 Bluetooth LE 的 {IDF_TARGET_NAME} 开发板 +1. 一块 {IDF_TARGET_NAME} 开发板 2. ESP-IDF 开发环境 -3. 在手机上安装 nRF Connect for Mobile 应用程序 +3. 在手机上安装 **nRF Connect for Mobile** 应用程序 -若你尚未完成 ESP-IDF 开发环境的配置,请参考 :doc:`API 参考 <../../../get-started/index>`。 +若你尚未完成 ESP-IDF 开发环境的配置,请参考 :doc:`IDF 快速入门 <../../../get-started/index>`。 动手试试 @@ -173,7 +173,7 @@ MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以 $ idf.py set-target -你应该能看到命令行以 +你应该能看到以下命令行 .. code-block:: shell @@ -188,7 +188,7 @@ MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以 $ idf.py flash monitor -你应该能看到命令行以 +你应该能看到以下命令行以 .. code-block:: shell @@ -201,7 +201,7 @@ MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以 连接,然后断开 ############################## -打开手机上的 nRF Connect for Mobile 程序,在 SCANNER 标签页中下拉刷新,找到 NimBLE_CONN 设备,如下图所示 +打开手机上的 **nRF Connect for Mobile** 程序,在 **SCANNER** 标签页中下拉刷新,找到 NimBLE_CONN 设备,如下图所示 .. figure:: ../../../../_static/ble/ble-connection-device-list.jpg :align: center @@ -211,9 +211,9 @@ MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以 若设备列表较长,建议以 NimBLE 为关键字进行设备名过滤,快速找到 NimBLE_CONN 设备。 -与 :ref:`NimBLE_Beacon ` 相比,可以观察到大部分广播数据是一致的,但多了一项 `Advertising Interval` 数据,其值为 500 ms ;在 `CONNECT` 按钮下方,确实也可以观察到广播间隔为 510 ms 左右。 +与 :ref:`NimBLE_Beacon ` 相比,可以观察到大部分广播数据是一致的,但多了一项 `Advertising Interval` 数据,其值为 500 ms ;在 **CONNECT** 按钮下方,确实也可以观察到广播间隔为 510 ms 左右。 -点击 `CONNECT` 按钮连接到设备,在手机上应能够看到 GAP 服务,如下 +点击 **CONNECT** 按钮连接到设备,在手机上应能够看到 GAP 服务,如下 .. figure:: ../../../../_static/ble/ble-connection-connected.jpg :align: center @@ -221,7 +221,7 @@ MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以 连接到 NimBLE_CONN 设备 -此时应该还能观察到开发板上的 LED 亮起。点击 `DISCONNECT`,断开与设备的连接,此时应能观察到开发板上的 LED 熄灭。 +此时应该还能观察到开发板上的 LED 亮起。点击 **DISCONNECT**,断开与设备的连接,此时应能观察到开发板上的 LED 熄灭。 若你的开发板上没有电源指示灯以外的 LED ,你应该能在日志输出中观察到对应的状态指示。 @@ -279,7 +279,7 @@ MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以 .. _nimble_connection_project_structure: -NimBLE_Connection 的根目录结构与 :ref:`NimBLE_Beacon ` 完全一致,不过在完成了固件的构建以后,你可能会观察到根目录下多了一个 `managed_components` 目录,里面含有固件构建时自动引入的依赖;本例中为 `led_strip` 组件,用于控制开发板的 LED。该依赖项在 `main/idf_component.yml` 文件中被引入。 +:example:`NimBLE_Connection ` 的根目录结构与 :ref:`NimBLE_Beacon ` 完全一致,不过在完成了固件的构建以后,你可能会观察到根目录下多了一个 `managed_components` 目录,里面含有固件构建时自动引入的依赖;本例中为 `led_strip` 组件,用于控制开发板的 LED。该依赖项在 `main/idf_component.yml` 文件中被引入。 另外,在 `main` 文件夹中引入了 LED 控制相关的源代码。 @@ -472,6 +472,6 @@ GAP 事件处理 总结 ---------------- -通过本教程,你了解了连接的基本概念,并通过 NimBLE_Connection 例程掌握了使用 NimBLE 主机层协议栈构建 Bluetooth LE 外围设备的方法。 +通过本教程,你了解了连接的基本概念,并通过 :example:`NimBLE_Connection ` 例程掌握了使用 NimBLE 主机层协议栈构建 Bluetooth LE 外围设备的方法。 你可以尝试对例程中的参数进行修改,并在日志输出中观察修改结果。例如,你可以修改外围设备延迟或连接超时参数,观察连接参数的修改是否能够触发连接更新事件。 diff --git a/docs/zh_CN/api-guides/ble/get-started/ble-data-exchange.rst b/docs/zh_CN/api-guides/ble/get-started/ble-data-exchange.rst index 91a4a96cbe12..dc0450ccb6f1 100644 --- a/docs/zh_CN/api-guides/ble/get-started/ble-data-exchange.rst +++ b/docs/zh_CN/api-guides/ble/get-started/ble-data-exchange.rst @@ -3,7 +3,7 @@ :link_to_translation:`en:[English]` -本文档为低功耗蓝牙 (Bluetooth Low Energy, Bluetooth LE) 入门教程其四,旨在对 Bluetooth LE 连接中的数据交换过程进行简要介绍。随后,本教程会结合 NimBLE_GATT_Server 例程,基于 NimBLE 主机层协议栈,对 GATT 服务器的代码实现进行介绍。 +本文档为低功耗蓝牙 (Bluetooth Low Energy, Bluetooth LE) 入门教程其四,旨在对 Bluetooth LE 连接中的数据交换过程进行简要介绍。随后,本教程会结合 :example:`NimBLE_GATT_Server ` 例程,基于 NimBLE 主机层协议栈,对 GATT 服务器的代码实现进行介绍。 学习目标 @@ -11,7 +11,7 @@ - 学习特征数据和服务的数据结构细节 - 学习 GATT 的不同数据访问操作 -- 学习 NimBLE_GATT_Server 例程的代码结构 +- 学习 :example:`NimBLE_GATT_Server ` 例程的代码结构 GATT 数据特征与服务 @@ -203,7 +203,7 @@ CCCD 的 UUID 是 `0x2902`,属性值中仅含 2 比特信息。第一个比特 .. _attribute_table: -下面以 NimBLE_GATT_Server 为例,展示一个 GATT 服务器可能的属性表形态。例程中含有两个服务,分别是 Heart Rate Service 和 Automation IO Service ;前者含有一个 Heart Rate Measurement 特征数据,后者含有一个 LED 特征数据。整个 GATT 服务器有属性表如下 +下面以 :example:`NimBLE_GATT_Server ` 为例,展示一个 GATT 服务器可能的属性表形态。例程中含有两个服务,分别是 Heart Rate Service 和 Automation IO Service ;前者含有一个 Heart Rate Measurement 特征数据,后者含有一个 LED 特征数据。整个 GATT 服务器有属性表如下 +-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ | Handle | UUID | Permissions | Value | Attribute Type | @@ -232,7 +232,9 @@ CCCD 的 UUID 是 `0x2902`,属性值中仅含 2 比特信息。第一个比特 | | | +-------------------------------------------------+ | | | | | UUID = `0x00001525-1212-EFDE-1523-785FEABCD123` | | +-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ -| 6 | `0x00001525-1212-EFDE-1523-785FEABCD123` | Write-only | LED status | Characteristic Value | +| 6 | `0x00001525-1212-EFDE-` |Write-only | LED status |Characteristic Value | +| | `1523-785FE` | | | | +| | `ABCD123` | | | | +-------------+------------------------------------------+-----------------+-------------------------------------------------+----------------------------+ GATT 客户端在与 GATT 服务器初次建立通信时,会从 GATT 服务器拉取属性表中的元信息,从而获取 GATT 服务器上可用的服务以及数据特征。这一过程被称为 *服务发现 (Service Discovery)*。 @@ -243,26 +245,23 @@ GATT 数据操作 .. _gatt_data_operation: -数据操作指的是对 GATT 服务器上的特征数据进行访问的操作,主要可以分为 +数据操作指的是对 GATT 服务器上的特征数据进行访问的操作,主要可以分为以下两类: 1. 由客户端发起的操作 2. 由服务器发起的操作 -两类。 - 由客户端发起的操作 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 由客户端发起的操作有以下三种 -1. 读 (Read) -2. 写 (Write) -3. 写(无需响应) (Write without response) - -读操作比较简单,单纯是从 GATT 服务器上拉取某一特征数据的当前值。 - -写操作分两种。普通的写操作要求 GATT 服务器在收到客户端的写请求以及对应数据以后,进行确认响应;快速写操作则不需要服务器进行确认响应。 +- **读 (Read)** + - 从 GATT 服务器上拉取某一特征数据的当前值。 +- **写 (Write)** + - 普通的写操作要求 GATT 服务器在收到客户端的写请求以及对应数据以后,进行确认响应。 +- **写(无需响应) (Write without response)** + - 快速写操作则不需要服务器进行确认响应。 由服务器发起的操作 @@ -270,10 +269,10 @@ GATT 数据操作 由服务器发起的操作分两种 -1. 通知 (Notify) -2. 指示 (Indicate) - -通知和指示都是 GATT 服务器主动向客户端推送数据的操作,区别在于通知无需客户端回复确认响应,而指示需要。所以,指示的数据推送速度比通知慢。 +- **通知 (Notify)** + - 通知是 GATT 服务器主动向客户端推送数据的操作,不需要客户端回复确认响应。 +- **指示 (Indicate)** + - 与通知相似,区别在于指示需要客户端回复确认,因此数据推送速度比通知慢。 虽然通知和指示都是由服务器发起的操作,但是服务器发起操作的前提是,客户端启用了通知或指示。所以,本质上 GATT 的数据交换过程总是以客户端请求数据开始。 @@ -281,23 +280,23 @@ GATT 数据操作 例程实践 ------------------------------------------- -在掌握了 GATT 数据交换的相关知识以后,接下来让我们结合 NimBLE_GATT_Server 例程代码,学习如何使用 NimBLE 协议栈构建一个简单的 GATT 服务器,对学到的知识进行实践。 +在掌握了 GATT 数据交换的相关知识以后,接下来让我们结合 :example:`NimBLE_GATT_Server ` 例程代码,学习如何使用 NimBLE 协议栈构建一个简单的 GATT 服务器,对学到的知识进行实践。 前提条件 ^^^^^^^^^^^^^^^ -1. 一块支持 Bluetooth LE 的 {IDF_TARGET_NAME} 开发板 +1. 一块 {IDF_TARGET_NAME} 开发板 2. ESP-IDF 开发环境 3. 在手机上安装 nRF Connect for Mobile 应用程序 -若你尚未完成 ESP-IDF 开发环境的配置,请参考 :doc:`API 参考 <../../../get-started/index>`。 +若你尚未完成 ESP-IDF 开发环境的配置,请参考 :doc:`IDF 快速入门 <../../../get-started/index>`。 动手试试 ^^^^^^^^^^^^^^^^^^ -请参考 :ref:`动手试试 ` 。 +请参考 :ref:`BLE 介绍 动手试试 ` 。 代码详解 @@ -307,7 +306,7 @@ GATT 数据操作 工程结构综述 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -NimBLE_GATT_Server 的根目录结构与 :ref:`NimBLE_Connection ` 完全一致。另外,在 `main` 文件夹中引入了与 GATT 服务以及模拟心率生成相关的源代码。 +:example:`NimBLE_GATT_Server ` 的根目录结构与 :ref:`NimBLE_Connection ` 完全一致。另外,在 `main` 文件夹中引入了与 GATT 服务以及模拟心率生成相关的源代码。 程序行为综述 @@ -659,6 +658,4 @@ LED 特征数据的访问通过 `led_chr_access` 回调函数管理,相关代 总结 ---------------------------- -通过本教程,你了解了如何通过服务表创建 GATT 服务以及相应的特征数据,并掌握了 GATT 特征数据的访问管理方式,包括读、写和订阅操作的实现。你可以在 NimBLE_GATT_Server 例程的基础上,开发更加复杂的 GATT 服务应用。 - - +通过本教程,你了解了如何通过服务表创建 GATT 服务以及相应的特征数据,并掌握了 GATT 特征数据的访问管理方式,包括读、写和订阅操作的实现。你可以在 :example:`NimBLE_GATT_Server ` 例程的基础上,开发更加复杂的 GATT 服务应用。 diff --git a/docs/zh_CN/api-guides/ble/get-started/ble-device-discovery.rst b/docs/zh_CN/api-guides/ble/get-started/ble-device-discovery.rst index 245eee9a6d03..19ca21b428fd 100644 --- a/docs/zh_CN/api-guides/ble/get-started/ble-device-discovery.rst +++ b/docs/zh_CN/api-guides/ble/get-started/ble-device-discovery.rst @@ -3,7 +3,7 @@ :link_to_translation:`en:[English]` -本文档为低功耗蓝牙 (Bluetooth Low Energy, Bluetooth LE) 入门教程其二,旨在对 Bluetooth LE 设备发现过程进行简要介绍,包括广播与扫描相关的基本概念。随后,本教程会结合 NimBLE_Beacon 例程,基于 NimBLE 主机层协议栈,对 Bluetooth LE 广播的代码实现进行介绍。 +本文档为低功耗蓝牙 (Bluetooth Low Energy, Bluetooth LE) 入门教程其二,旨在对 Bluetooth LE 设备发现过程进行简要介绍,包括广播与扫描相关的基本概念。随后,本教程会结合 :example:`NimBLE_Beacon ` 例程,基于 NimBLE 主机层协议栈,对 Bluetooth LE 广播的代码实现进行介绍。 学习目标 @@ -11,7 +11,7 @@ - 学习广播的基本概念 - 学习扫描的基本概念 -- 学习 NimBLE_Beacon 例程的代码结构 +- 学习 :example:`NimBLE_Beacon ` 例程的代码结构 广播 (Advertising) 与扫描 (Scanning) 是 Bluetooth LE 设备在进入连接前在设备发现 (Device Discovery) 阶段的工作状态。下面,我们先了解与广播有关的基本概念。 @@ -33,7 +33,7 @@ 蓝牙的无线电频段 ################################ -第一个问题指向的是,广播数据包应发送到哪一无线电频段。这个回答由蓝牙核心规范给出,答案是 2.4 GHz ISM 频段。选择该频段的理由是, 2.4 GHz ISM 频段是一个全球可用的免费无线电频段,不被任何国家以军事用途等理由管控,也无需向任何组织支付许可费用,因此该频段的可用性极高,且没有任何使用成本。不过,这也意味着 2.4 GHz ISM 频段非常拥挤,可能会与其他无线通信协议发生数据冲突,如 2.4 GHz WiFi。 +第一个问题指向的是,广播数据包应发送到哪一无线电频段。这个回答由蓝牙核心规范给出,答案是 2.4 GHz ISM 频段。2.4 GHz ISM 频段是一个全球可用的免费无线电频段,不被任何国家以军事用途等理由管控,也无需向任何组织支付许可费用,因此该频段的可用性极高,且没有任何使用成本。不过,这也意味着 2.4 GHz ISM 频段非常拥挤,可能会与其他无线通信协议发生数据冲突,如 2.4 GHz WiFi。 蓝牙信道 @@ -87,7 +87,7 @@ Bluetooth LE 4.2 标准中,广播数据包允许搭载最多 31 字节广播 - 254 - 1650 -扩展广播数据包由 ADV_EXT_IND 和 AUX_ADV_IND 组成,分别在主广播信道 (Primary Advertising Channel) 和次广播信道 (Secondary Advertising Channel) 上传输。其中,主广播信道对应于信道 37-39 ,次广播信道对应于信道 0-36 。由于接收方总是在主广播信道中接收广播数据,因此发送方在发送扩展广播数据包时,应在主广播信道中发送 ADV_EXT_IND ,在次广播信道中发送 AUX_ADV_IND ,并在 ADV_EXT_IND 中指示 AUX_ADV_IND 所在的次广播信道;通过这种机制,接收方能够在接收到主广播信道的 ADV_EXT_IND 以后,根据指示到指定的次广播信道去接收 AUX_ADV_IND ,从而得到完整的扩展广播数据包。 +扩展广播数据包由 `ADV_EXT_IND` 和 `AUX_ADV_IND` 组成,分别在主广播信道 (Primary Advertising Channel) 和次广播信道 (Secondary Advertising Channel) 上传输。其中,主广播信道对应于信道 37-39 ,次广播信道对应于信道 0-36 。由于接收方总是在主广播信道中接收广播数据,因此发送方在发送扩展广播数据包时,应在主广播信道中发送 `ADV_EXT_IND` ,在次广播信道中发送 `AUX_ADV_IND` ,并在 `ADV_EXT_IND` 中指示 `AUX_ADV_IND` 所在的次广播信道;通过这种机制,接收方能够在接收到主广播信道的 `ADV_EXT_IND` 以后,根据指示到指定的次广播信道去接收 `AUX_ADV_IND` ,从而得到完整的扩展广播数据包。 .. list-table:: :align: center @@ -99,10 +99,10 @@ Bluetooth LE 4.2 标准中,广播数据包允许搭载最多 31 字节广播 - 作用 * - 主广播信道 (Primary Advertising Channel) - 37-39 - - 用于传输扩展广播数据包的 ADV_EXT_IND + - 用于传输扩展广播数据包的 `ADV_EXT_IND` * - 次广播信道 (Secondary Advertising Channel) - 0-36 - - 用于传输扩展广播数据包的 AUX_ADV_IND + - 用于传输扩展广播数据包的 `AUX_ADV_IND` 发送广播数据包的周期取多久? @@ -111,11 +111,11 @@ Bluetooth LE 4.2 标准中,广播数据包允许搭载最多 31 字节广播 广播间隔 ################## -对于第二个问题,即发送广播数据包的周期怎么取,蓝牙标准中也给出了一个明确的参数定义,即广播间隔 (Advertising Interval)。广播间隔可取的范围为 20 ms 到 10.24 s ,取值步长为 0.625 ms。 +对于第二个问题,即发送广播数据包的周期怎么取,蓝牙标准中也给出了一个明确的参数定义,即广播间隔 (Advertising Interval)。广播间隔可取的范围为 20 ms 到 10.24 s ,取值步长为 0.625 ms。 -广播间隔的取值决定了广播者的可发现性 (Discoverability)以及设备功耗。当广播间隔取得太长时,广播数据包被接收方接收到的概率就会变得很低,此时广播者的可发现性就会变差。同时,广播间隔也不宜取得太短,因此频繁发送广播数据需要消耗更多的电量。所以,广播者需要在可发现性和能耗之间进行取舍,根据应用场景的需求选择最合适的广播间隔。 +广播间隔的取值决定了广播者的可发现性 (Discoverability) 以及设备功耗。当广播间隔取得太长时,广播数据包被接收方接收到的概率就会变得很低,此时广播者的可发现性就会变差。同时,广播间隔也不宜取得太短,因此频繁发送广播数据需要消耗更多的电量。所以,广播者需要在可发现性和能耗之间进行取舍,根据应用场景的需求选择最合适的广播间隔。 -值得一提的是,如果在同一空间中存在两个广播间隔相同的广播者,那么有概率出现重复性的撞包 (Packet Collision) 现象,即两个广播者总是在同一时刻向同一信道发送广播数据。由于广播是一个只发不收的过程,广播者无法得知是否发生了广播撞包。为了降低上述问题的发生概率,广播者应在每一次广播事件后添加 0-10 ms 的随机时延。 +值得一提的是,如果在同一空间中存在两个广播间隔相同的广播者,那么有概率出现重复性的撞包 (Packet Collision) 现象,即两个广播者总是在同一时刻向同一信道发送广播数据。由于广播是一个只发不收的过程,广播者无法得知是否发生了广播撞包。为了降低上述问题的发生概率,广播者应在每一次广播事件后添加 0-10 ms 的随机时延。 广播数据包里包含哪些信息? @@ -201,7 +201,7 @@ PDU 头中含有较多信息,可以分为以下六个部分 * - 序号 - 名称 - - 位数 + - 比特位数 - 备注 * - 1 - PDU 类型 (PDU Type) @@ -222,7 +222,7 @@ PDU 头中含有较多信息,可以分为以下六个部分 * - 5 - 接收地址类型 (Rx Address, **RxAdd**) - 1 - - 同上 + - 0/1 分别表示公共地址/随机地址 * - 6 - 有效负载长度 (Payload Length) - 8 @@ -336,7 +336,7 @@ PDU 有效负载也分为两部分 * - 不可解析随机私有地址 (Non-resolvable Random Private Address) - 完全随机的地址,仅用于防止设备被追踪,非常少用 -然后看广播数据。一个广播数据结构的格式定义如下 +然后看**广播数据**。一个广播数据结构的格式定义如下 .. list-table:: :align: center @@ -370,7 +370,8 @@ PDU 有效负载也分为两部分 2. 多久扫描一次?一次扫描多久? (When?) 3. 扫描的过程中需要做什么? (What?) -第一个问题已经在广播的介绍中说明了。对于 Bluetooth LE 4.2 设备来说,广播者只会在广播信道,即编号为 37-39 的三个信道发送广播数据;对于 Bluetooth LE 5.0 设备来说,如果广播者启用了扩展广播特性,则会在主广播信道发送 ADV_EXT_IND ,在次广播信道发送 AUX_ADV_IND ,并在 ADV_EXT_IND 指示 AUX_ADV_IND 所在的次广播信道。所以相应的,对于 Bluetooth LE 4.2 设备来说,扫描者只需在广播信道接收广播数据包即可。对于 Bluetooth LE 5.0 设备来说,扫描者应在主广播信道接收主广播数据包和扩展广播数据包的 ADV_EXT_IND ; 若扫描者接收到了 ADV_EXT_IND ,且 ADV_EXT_IND 指示了一个次广播信道,那么还需要到对应的次广播信道去接收 AUX_ADV_IND ,以获取完整的扩展广播数据包。 +第一个问题已经在广播的介绍中说明了。对于 Bluetooth LE 4.2 设备来说,广播者只会在广播信道,即编号为 37-39 的三个信道发送广播数据;对于 Bluetooth LE 5.0 设备来说,如果广播者启用了扩展广播特性,则会在主广播信道发送 `ADV_EXT_IND` ,在次广播信道发送 `AUX_ADV_IND` ,并在 `ADV_EXT_IND` 指示 `AUX_ADV_IND` 所在的次广播信道。 +所以相应的,对于 Bluetooth LE 4.2 设备来说,扫描者只需在广播信道接收广播数据包即可。对于 Bluetooth LE 5.0 设备来说,扫描者应在主广播信道接收主广播数据包和扩展广播数据包的 `ADV_EXT_IND` ; 若扫描者接收到了 `ADV_EXT_IND` ,且 `ADV_EXT_IND` 指示了一个次广播信道,那么还需要到对应的次广播信道去接收 `AUX_ADV_IND` ,以获取完整的扩展广播数据包。 扫描窗口与扫描间隔 @@ -378,9 +379,9 @@ PDU 有效负载也分为两部分 第二个问题分别指向扫描窗口 (Scan Window) 和 扫描间隔 (Scan Interval) 概念。 -首先对扫描窗口进行说明。扫描窗口指的是扫描者在同一个 RF 信道持续接收蓝牙数据包的持续时间,例如扫描窗口参数设定为 50 ms 时,扫描者在每个 RF 信道都会不间断地扫描 50 ms。 +- **扫描窗口**:扫描者在同一个 RF 信道持续接收蓝牙数据包的持续时间,例如扫描窗口参数设定为 50 ms 时,扫描者在每个 RF 信道都会不间断地扫描 50 ms。 -扫描间隔则指的是相邻两个扫描窗口开始时刻之间的时间间隔,所以扫描间隔必然大于等于扫描窗口。 +- **扫描间隔**:相邻两个扫描窗口开始时刻之间的时间间隔,所以扫描间隔必然大于等于扫描窗口。 下图在时间轴上展示了扫描者的广播数据包接收过程,其中扫描者的扫描间隔为 100 ms ,扫描窗口为 50 ms ;广播者的广播间隔为 50 ms ,广播数据包的发送时长仅起到示意作用。可以看到,第一个扫描窗口对应 37 信道,此时扫描者恰好接收到了广播者第一次在 37 信道发送的广播数据包,以此类推。 @@ -419,17 +420,17 @@ PDU 有效负载也分为两部分 例程实践 ------------------------------------------- -在掌握了广播与扫描的相关知识以后,接下来让我们结合 NimBLE_Beacon 例程代码,学习如何使用 NimBLE 协议栈构建一个简单的 Beacon 设备,对学到的知识进行实践。 +在掌握了广播与扫描的相关知识以后,接下来让我们结合 :example:`NimBLE_Beacon ` 例程代码,学习如何使用 NimBLE 协议栈构建一个简单的 Beacon 设备,对学到的知识进行实践。 前提条件 ^^^^^^^^^^^^^^^ -1. 一块支持 Bluetooth LE 的 {IDF_TARGET_NAME} 开发板 +1. 一块 {IDF_TARGET_NAME} 开发板 2. ESP-IDF 开发环境 -3. 在手机上安装 nRF Connect for Mobile 应用程序 +3. 在手机上安装 **nRF Connect for Mobile** 应用程序 -若你尚未完成 ESP-IDF 开发环境的配置,请参考 :doc:`API 参考 <../../../get-started/index>`。 +若你尚未完成 ESP-IDF 开发环境的配置,请参考 :doc:`IDF 快速入门 <../../../get-started/index>`。 动手试试 @@ -460,7 +461,7 @@ PDU 有效负载也分为两部分 $ idf.py set-target -你应该能看到命令行以 +你应该能看到以下命令行 .. code-block:: shell @@ -475,7 +476,7 @@ PDU 有效负载也分为两部分 $ idf.py flash monitor -你应该能看到命令行以 +你应该能看到以下命令行 .. code-block:: shell @@ -490,7 +491,7 @@ PDU 有效负载也分为两部分 .. _nimble_beacon_details: -打开手机上的 nRF Connect for Mobile 程序,在 SCANNER 标签页中下拉刷新,找到 NimBLE_Beacon 设备,如下图所示 +打开手机上的 **nRF Connect for Mobile** 程序,在 SCANNER 标签页中下拉刷新,找到 NimBLE_Beacon 设备,如下图所示 .. figure:: ../../../../_static/ble/ble-scan-list-nimble-beacon.jpg :align: center @@ -501,7 +502,7 @@ PDU 有效负载也分为两部分 若设备列表较长,建议以 NimBLE 为关键字进行设备名过滤,快速找到 NimBLE_Beacon 设备。 -观察到 NimBLE Beacon 设备下带有丰富的设备信息,甚至还带有乐鑫的网址(这就是信标广告功能的体现)。点击右下角的 `RAW` 按钮,可以看到广播数据包的原始信息,如下 +观察到 NimBLE Beacon 设备下带有丰富的设备信息,甚至还带有乐鑫的网址(这就是信标广告功能的体现)。点击右下角的 **RAW** 按钮,可以看到广播数据包的原始信息,如下 .. figure:: ../../../../_static/ble/ble-adv-packet-raw-data.jpg :align: center @@ -510,7 +511,7 @@ PDU 有效负载也分为两部分 广播数据包原始信息 -Details 表格即广播数据包和扫描响应数据包中的所有广播数据结构,可以整理如下 +**Details** 表格即广播数据包和扫描响应数据包中的所有广播数据结构,可以整理如下 .. list-table:: :align: center @@ -523,37 +524,37 @@ Details 表格即广播数据包和扫描响应数据包中的所有广播数据 - 原始数据 - 解析值 * - 标志位 - - 2 + - 2 Bytes - `0x01` - `0x06` - General Discoverable, BR/EDR Not Supported * - 完整设备名称 - - 14 + - 14 Bytes - `0x09` - `0x4E696D424C455F426561636F6E` - NimBLE_Beacon * - 发送功率等级 - - 2 + - 2 Bytes - `0x0A` - `0x09` - 9 dBm * - 设备外观 - - 3 + - 3 Bytes - `0x19` - `0x0002` - 通用标签 * - LE 角色 - - 2 + - 2 Bytes - `0x1C` - `0x00` - 仅支持外设设备 * - 设备地址 - - 8 + - 8 Bytes - `0x1B` - `0x46F506BDF5F000` - `F0:F5:BD:06:F5:46` * - URI - - 17 + - 17 Bytes - `0x24` - `0x172F2F6573707265737369662E636F6D` - `https://espressif.com` @@ -562,7 +563,7 @@ Details 表格即广播数据包和扫描响应数据包中的所有广播数据 你可能还注意到,对应于设备外观的 Raw Data 为 `0x0002`,而代码中对 Generic Tag 的定义是 `0x0200`;还有,设备地址的 Raw Data 除了最后一个字节 `0x00` 以外,似乎与实际地址完全颠倒。这是因为, Bluetooth LE 的空中数据包遵循小端 (Little Endian) 传输的顺序,所以低字节的数据反而会在靠前的位置。 -另外,注意到 nRF Connect for Mobile 程序并没有为我们提供 `CONNECT` 按钮以连接至此设备。这符合我们的预期,因为 Beacon 设备本来就应该是不可连接的。下面,让我们深入代码细节,看看这样的一个 Beacon 设备是怎样实现的。 +另外,注意到 **nRF Connect for Mobile** 程序并没有为我们提供 **CONNECT** 按钮以连接至此设备。这符合我们的预期,因为 Beacon 设备本来就应该是不可连接的。下面,让我们深入代码细节,看看这样的一个 Beacon 设备是怎样实现的。 代码详解 @@ -574,7 +575,7 @@ Details 表格即广播数据包和扫描响应数据包中的所有广播数据 .. _nimble_beacon_project_structure: -NimBLE_Beacon 的根目录大致分为以下几部分 +:example:`NimBLE_Beacon ` 的根目录大致分为以下几部分 - `README*.md` - 工程的说明文档 @@ -611,7 +612,7 @@ NimBLE_Beacon 的根目录大致分为以下几部分 2. 初始化 GAP 服务 3. 启动 NimBLE 主机层的 FreeRTOS 线程 -ESP32 的蓝牙协议栈使用 NVS Flash 存储相关配置,所以在初始化蓝牙协议栈之前,必须调用 `nvs_flash_init` API 以初始化 NVS Flash ,某些情况下需要调用 `nvs_flash_erase` API 对 NVS Flash 进行擦除后再初始化。 +{IDF_TARGET_NAME} 的蓝牙协议栈使用 NVS Flash 存储相关配置,所以在初始化蓝牙协议栈之前,必须调用 `nvs_flash_init` API 以初始化 NVS Flash ,某些情况下需要调用 `nvs_flash_erase` API 对 NVS Flash 进行擦除后再初始化。 .. code-block:: C @@ -879,6 +880,6 @@ ESP32 的蓝牙协议栈使用 NVS Flash 存储相关配置,所以在初始化 总结 --------- -通过本教程,你了解了广播和扫描的基本概念,并通过 NimBLE_Beacon 例程掌握了使用 NimBLE 主机层协议栈构建 Bluetooth LE Beacon 设备的方法。 +通过本教程,你了解了广播和扫描的基本概念,并通过 :example:`NimBLE_Beacon ` 例程掌握了使用 NimBLE 主机层协议栈构建 Bluetooth LE Beacon 设备的方法。 你可以尝试对例程中的数据进行修改,并在 nRF Connect for Mobile 调试工具中查看修改结果。例如,你可以尝试修改 `adv_fields` 或 `rsp_fields` 结构体,以修改被填充的广播数据结构,或者交换广播数据包和扫描响应数据包中的广播数据结构。但需要注意的一点是,广播数据包和扫描响应数据包的广播数据上限为 31 字节,若设定的广播数据结构大小超过该限值,调用 `ble_gap_adv_start` API 将会失败。 diff --git a/docs/zh_CN/api-guides/ble/get-started/ble-introduction.rst b/docs/zh_CN/api-guides/ble/get-started/ble-introduction.rst index 430e41f5995e..d37d28ce31ef 100644 --- a/docs/zh_CN/api-guides/ble/get-started/ble-introduction.rst +++ b/docs/zh_CN/api-guides/ble/get-started/ble-introduction.rst @@ -47,7 +47,7 @@ Bluetooth LE 协议定义了三层软件结构,自上而下分别是 Bluetooth LE 分层结构 -作为应用开发者,在开发过程中我们主要与主机层提供的 API 接口打交道,这要求我们对主机层中的蓝牙协议有一定的了解。接下来,我们会从连接和数据交互两个角度,对 GAP 和 GATT/ATT 层的基本概念进行介绍。 +作为应用开发者,在开发过程中我们主要与主机层提供的 API 接口打交道,这要求我们对主机层中的蓝牙协议有一定的了解。接下来,我们会从连接和数据交换两个角度,对 GAP 和 GATT/ATT 层的基本概念进行介绍。 GAP 层 - 定义设备的连接 @@ -71,7 +71,7 @@ GAP 中共定义了三种设备的连接状态以及五种不同的设备角色 - 外围设备 (Peripheral) - 中央设备 (Central) -广播者向外广播的数据中包含设备地址等信息,用于向外界设备表明广播者的存在,并告知其他设备是否可以连接。扫描者则持续接收环境中的广播数据包。若某一个扫描者发现了一个可连接的广播者,并希望与之建立连接,可以将角色切换为连接发起者。当连接发起者再次收到该广播者的广播数据,会立即发起连接请求 (Connection Request);在广播者未开启白名单 (White List, 又称 Accept List) 或连接发起者在广播者的白名单之中时,连接将被成功建立。 +广播者向外广播的数据中包含设备地址等信息,用于向外界设备表明广播者的存在,并告知其他设备是否可以连接。扫描者则持续接收环境中的广播数据包。若某一个扫描者发现了一个可连接的广播者,并希望与之建立连接,可以将角色切换为连接发起者。当连接发起者再次收到该广播者的广播数据,会立即发起连接请求 (Connection Request);在广播者未开启白名单 (Filter Accept List, 又称 White List) 或连接发起者在广播者的白名单之中时,连接将被成功建立。 进入连接以后,原广播者转变为外围设备(旧称从设备 Slave ),原扫描者或连接初始化者转变为中央设备(旧称主设备 Master )。 @@ -112,7 +112,7 @@ GATT/ATT 层定义了进入连接状态后,设备之间的数据交换方式 ATT 层 ############# -ATT 的全称是属性协议 (Attribute Protocol, ATT),定义了一种称为属性 (Attribute) 的基本数据结构,以及基于服务器/客户端架构的数据访问方式。 +ATT 的全称是属性协议 (Attribute Protocol, ATT),定义了一种称为**属性 (Attribute)** 的基本数据结构,以及基于服务器/客户端架构的数据访问方式。 简单来说,数据以属性的形式存储在服务器上,等待客户端的访问。以智能开关为例,开关量作为数据,以属性的形式存储在智能开关内的蓝牙芯片(服务器)中,此时用户可以通过手机(客户端)访问智能开关蓝牙芯片(服务器)上存放的开关量属性,获取当前的开关状态(读访问),或控制开关的闭合与断开(写访问)。 @@ -123,7 +123,7 @@ ATT 的全称是属性协议 (Attribute Protocol, ATT),定义了一种称为 - 值 (Value) - 访问权限 (Permissions) -在协议栈实现中,属性一般被放在称为属性表 (Attribute Table) 的结构体数组中管理。一个属性在这张表中的索引,就是属性的句柄,常为一无符号整型。 +在协议栈实现中,属性一般被放在称为**属性表 (Attribute Table)** 的结构体数组中管理。一个属性在这张表中的索引,就是属性的句柄,常为一无符号整型。 属性的类型由 UUID 表示,可以分为 16 位、32 位与 128 位 UUID 三类。 16 位 UUID 由蓝牙技术联盟 (Bluetooth Special Interest Group, Bluetooth SIG) 统一定义,可以在其公开发布的 `Assigned Numbers `__ 文件中查询;其他两种长度的 UUID 用于表示厂商自定义的属性类型,其中 128 位 UUID 较为常用。 @@ -155,7 +155,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 除此以外,特征数据中还可能包含若干可选的描述符属性 (Characteristic Descriptor Attribute)。 -一个服务本身也由一个属性进行描述,称为服务声明属性 (Service Declaration Attribute)。一个服务中可以存在一个或多个特征数据,它们之间体现为从属关系。另外,一个服务可以通过 Include 机制引用另一个服务,复用其特性定义,避免如设备名称、制造商信息等相同特性的重复定义。 +一个服务本身也由一个属性进行描述,称为服务声明属性 (Service Declaration Attribute)。一个服务中可以存在一个或多个特征数据,它们之间体现为从属关系。另外,一个服务可以通过 `Include` 机制引用另一个服务,复用其特性定义,避免如设备名称、制造商信息等相同特性的重复定义。 规范是一个预定义的服务集合,实现了某规范中所定义的所有服务的设备即满足该规范。例如 Heart Rate Profile 规范由 Heart Rate Service 和 Device Information Service 两个服务组成,那么可以称实现了 Heart Rate Service 和 Device Information Service 服务的设备符合 Heart Rate Profile 规范。 @@ -178,11 +178,11 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 前提条件 ^^^^^^^^^^^^^^^ -1. 一块支持 Bluetooth LE 的 {IDF_TARGET_NAME} 开发板 +1. 一块 {IDF_TARGET_NAME} 开发板 2. ESP-IDF 开发环境 -3. 在手机上安装 nRF Connect for Mobile 应用程序 +3. 在手机上安装 **nRF Connect for Mobile** 应用程序 -若你尚未完成 ESP-IDF 开发环境的配置,请参考 :doc:`API 参考 <../../../get-started/index>`。 +若你尚未完成 ESP-IDF 开发环境的配置,请参考 :doc:`IDF 快速入门 <../../../get-started/index>`。 动手试试 @@ -214,7 +214,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 $ idf.py set-target -你应该能看到命令行以 +你应该能看到以下命令行 .. code-block:: shell @@ -229,7 +229,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 $ idf.py flash monitor -你应该能看到命令行以 +你应该能看到以下命令行 .. code-block:: shell @@ -243,7 +243,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 连接到开发板 ####################### -现在开发板已准备就绪。接下来,打开手机上的 nRF Connect for Mobile 程序,在 SCANNER 标签页中下拉刷新,找到 NimBLE_GATT 设备,如下图所示 +现在开发板已准备就绪。接下来,打开手机上的 **nRF Connect for Mobile** 程序,在 **SCANNER** 标签页中下拉刷新,找到 NimBLE_GATT 设备,如下图所示 .. figure:: ../../../../_static/ble/ble-get-started-connect-brief.jpg :align: center @@ -254,7 +254,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 若设备列表较长,建议以 NimBLE 为关键字进行设备名过滤,快速找到 NimBLE_GATT 设备。 -点击 NimBLE_GATT 设备条目,可以展开看到广播数据的详细信息。 +点击 **NimBLE_GATT** 设备条目,可以展开看到广播数据的详细信息。 .. figure:: ../../../../_static/ble/ble-get-started-connect-details.jpg :align: center @@ -263,7 +263,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 广播数据详情 -点击右侧的 CONNECT 按钮,在手机连接的同时,可以在开发板的串口输出中观察到许多与连接相关的日志信息。随后,手机上会显示 NimBLE_GATT 标签页,左上角应有 CONNECTED 状态,说明手机已成功通过 Bluetooth LE 协议连接至开发板。在 CLIENT 子页中,你应该能够看到四个 GATT 服务,如图所示 +点击右侧的 **CONNECT** 按钮,在手机连接的同时,可以在开发板的串口输出中观察到许多与连接相关的日志信息。随后,手机上会显示 NimBLE_GATT 标签页,左上角应有 **CONNECTED** 状态,说明手机已成功通过 Bluetooth LE 协议连接至开发板。在 CLIENT 子页中,你应该能够看到四个 GATT 服务,如图所示 .. figure:: ../../../../_static/ble/ble-get-started-gatt-services-list.jpg :align: center @@ -274,13 +274,13 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 前两个服务是 GAP 服务和 GATT 服务,这两个服务是 Bluetooth LE 应用中的基础服务。后两个服务是 Bluetooth SIG 定义的 Heart Rate Service 服务和 Automation IO Service 服务,分别提供心率数据读取和 LED 控制功能。 -在服务名的下方,对应有各个服务的 UUID 以及服务主次标识。如 Heart Rate Service 服务的 UUID 为 `0x180D`,是一个主服务 (Primary Service)。需要注意的是,服务的名称是通过 UUID 解析得到的。以 nRF Connect for Mobile 为例,在实现 GATT 客户端时,开发者会将 Bluetooth SIG 定义的服务,以及开发商 Nordic Semiconductor 自定义的服务预先写入数据库中,然后根据 GATT 服务的 UUID 进行服务信息解析。所以,假如某一服务的 UUID 不在数据库中,那么该服务的服务信息就无法被解析,服务名称将会显示为未知服务 (Unknown Service)。 +在服务名的下方,对应有各个服务的 UUID 以及服务主次标识。如 Heart Rate Service 服务的 UUID 为 `0x180D`,是一个主服务 (Primary Service)。需要注意的是,服务的名称是通过 UUID 解析得到的。以 nRF Connect for Mobile 为例,在实现 GATT 客户端时,开发者会将 Bluetooth SIG 定义的服务,以及例程自定义的服务预先写入数据库中,然后根据 GATT 服务的 UUID 进行服务信息解析。所以,假如某一服务的 UUID 不在数据库中,那么该服务的服务信息就无法被解析,服务名称将会显示为未知服务 (Unknown Service)。 把灯点亮! ################## -下面体验一下本例程的功能。首先,点击 Automation IO Service 服务,可以看到该服务下有一个 LED 特征数据。 +下面体验一下本例程的功能。首先,点击 **Automation IO Service** 服务,可以看到该服务下有一个 LED 特征数据。 .. figure:: ../../../../_static/ble/ble-get-started-automation-io-service-details.jpg :align: center @@ -289,7 +289,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 Automation IO Service -如图,该 LED 特征数据的 UUID 为 128 位的厂商自定义 UUID 。实际上,这是 Nordic Semiconductor 自定义的 LED 特征数据,在 nRF Connect for Mobile 上有专门的控制页面适配。点击右侧的上传按钮,可以对该特征数据进行写访问,如下图所示。 +如图,该 LED 特征数据的 UUID 为 128 位的厂商自定义 UUID 。 点击右侧的**UPLOAD**按钮,可以对该特征数据进行写访问,如下图所示。 .. figure:: ../../../../_static/ble/ble-get-started-led-write.jpg :align: center @@ -298,7 +298,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 对 LED 特征数据进行写访问 -选择 ON 选项,然后发送,你应该能看到开发板上的 LED 被点亮了。选择 OFF 选项,然后发送,你应该能观察到开发板上的 LED 又熄灭了。 +选择 **ON** 选项,然后发送,你应该能看到开发板上的 LED 被点亮了。选择 **OFF** 选项,然后发送,你应该能观察到开发板上的 LED 又熄灭了。 若你的开发板上没有电源指示灯以外的 LED ,你应该能在日志输出中观察到对应的状态指示。 @@ -306,7 +306,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基 接收心率数据 ####################### -接下来,点击 Heart Rate Service 服务,可以看到该服务下有一个 Heart Rate Measurement 特征数据。 +接下来,点击 **Heart Rate Service** 服务,可以看到该服务下有一个 Heart Rate Measurement 特征数据。 .. figure:: ../../../../_static/ble/ble-get-started-heart-rate-service-details.jpg :align: center @@ -339,4 +339,4 @@ Heart Rate Measurement 特征数据的 UUID 是 `0x2A37`,这是一个 Bluetoot 总结 --------- -通过本教程,你了解了 Bluetooth LE 的分层架构、Bluetooth LE 协议栈中主机层和控制器层的基本功能以及 GAP 层与 GATT/ATT 层的作用。随后,通过 NimBLE_GATT_Server 例程,你掌握了如何使用 ESP-IDF 开发框架进行 Bluetooth LE 应用的构建与烧录,能够在手机上使用 nRF Connect for Mobile 调试程序,远程控制开发板上 LED 的点亮与熄灭,以及接收随机生成的心率数据。你已经迈出了走向 Bluetooth LE 开发者的第一步,恭喜! +通过本教程,你了解了 Bluetooth LE 的分层架构、Bluetooth LE 协议栈中主机层和控制器层的基本功能以及 GAP 层与 GATT/ATT 层的作用。随后,通过 :example:`NimBLE_GATT_Server ` 例程,你掌握了如何使用 ESP-IDF 开发框架进行 Bluetooth LE 应用的构建与烧录,能够在手机上使用 **nRF Connect for Mobile** 调试程序,远程控制开发板上 LED 的点亮与熄灭,以及接收随机生成的心率数据。你已经迈出了走向 Bluetooth LE 开发者的第一步,恭喜! diff --git a/docs/zh_CN/api-guides/ble/host-feature-support-status.rst b/docs/zh_CN/api-guides/ble/host-feature-support-status.rst index 2acb0855b376..d1134e17e5b9 100644 --- a/docs/zh_CN/api-guides/ble/host-feature-support-status.rst +++ b/docs/zh_CN/api-guides/ble/host-feature-support-status.rst @@ -79,7 +79,7 @@ ESP 主机主要功能支持状态 - |experimental| - |experimental| * - - - Advertising Channel Index + - Randomized Advertising Channel Indexing - |NA| - |NA| * - diff --git a/docs/zh_CN/api-guides/ble/overview.rst b/docs/zh_CN/api-guides/ble/overview.rst index 62dbc36db09f..d9997eef481b 100644 --- a/docs/zh_CN/api-guides/ble/overview.rst +++ b/docs/zh_CN/api-guides/ble/overview.rst @@ -13,13 +13,13 @@ {IDF_TARGET_NAME} 支持蓝牙 5.0 (LE),并且已经获得蓝牙 LE 5.4 认证。 -.. only:: esp32c2 or esp32c6 or esp32h2 +.. only:: esp32c2 or esp32c6 or esp32h2 or esp32c5 or esp32c61 {IDF_TARGET_NAME} 支持蓝牙 5.0 (LE),并且已经获得蓝牙 LE 5.3 认证。 ESP-IDF 中的低功耗蓝牙协议栈是一个分层架构,可在 {IDF_TARGET_NAME} 系列芯片上实现低功耗蓝牙功能,详见下。 -.. only:: esp32 or esp32s3 or esp32c3 or esp32c6 +.. only:: esp32 or esp32s3 or esp32c3 or esp32c6 or esp32c5 or esp32c61 .. figure:: ../../../_static/bluetooth-architecture.png :align: center diff --git a/docs/zh_CN/api-guides/bootloader.rst b/docs/zh_CN/api-guides/bootloader.rst index 29277188a714..a8537c1b9f49 100644 --- a/docs/zh_CN/api-guides/bootloader.rst +++ b/docs/zh_CN/api-guides/bootloader.rst @@ -3,16 +3,16 @@ :link_to_translation:`en:[English]` -ESP-IDF 软件引导加载程序 (Bootloader) 主要执行以下任务: +ESP-IDF 二级引导加载程序 (second stage bootloader) 主要执行以下任务: 1. 内部模块的最小化初始配置; -2. 如果配置了 :doc:`/security/flash-encryption` 和/或 :doc:`Secure `,则对其进行初始化。 +2. 如果配置了 :doc:`/security/flash-encryption` 和/或 :doc:`Secure Boot `,则对其进行初始化。 3. 根据分区表和 ota_data(如果存在)选择需要引导的应用程序 (app) 分区; 4. 将此应用程序镜像加载到 RAM(IRAM 和 DRAM)中,最后把控制权转交给此应用程序。 -引导加载程序位于 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处。 +ESP-IDF 二级引导加载程序位于 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处。 -关于启动过程以及 ESP-IDF 引导加载程序的更多信息,请参考 :doc:`startup`。 +如需了解包括 ESP-IDF 二级引导加载程序在内的完整启动过程,请参考 :doc:`startup`。 .. _bootloader-compatibility: @@ -21,11 +21,11 @@ ESP-IDF 软件引导加载程序 (Bootloader) 主要执行以下任务: 建议使用最新发布的 :doc:`ESP-IDF 版本 `。OTA(空中升级)更新可以在现场烧录新的应用程序,但不能烧录一个新的引导加载程序。因此,引导加载程序支持引导从 ESP-IDF 新版本中构建的应用程序。 -但不支持引导从 ESP-IDF 旧版本中构建的程序。如果现有产品可能需要将应用程序降级到旧版本,那么在手动更新 ESP-IDF 时,请继续使用旧版本 ESP-IDF 引导加载程序的二进制文件。 +但不支持引导从 ESP-IDF 旧版本中构建的程序。如果现有产品可能需要将应用程序降级到旧版本,那么在手动更新 ESP-IDF 时,请继续使用旧版本引导加载程序的二进制文件。 .. note:: - 如果在生产中测试现有产品的 OTA 更新,请确保测试中使用的 ESP-IDF 引导加载程序二进制文件与生产中部署的相同。 + 如果在生产中测试现有产品的 OTA 更新,请确保测试中使用的引导加载程序二进制文件与生产中部署的相同。 .. only:: esp32 @@ -50,11 +50,11 @@ ESP-IDF 软件引导加载程序 (Bootloader) 主要执行以下任务: 每个 ESP-IDF 应用程序或引导加载程序的二进制文件中都包含一个文件头,其中内置了 :ref:`CONFIG_ESPTOOLPY_FLASHMODE`、:ref:`CONFIG_ESPTOOLPY_FLASHFREQ`、和 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`。这些是用于在启动时配置 SPI flash。 -ROM 中的 :ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage-bootloader` 文件头中的配置信息,并使用这些信息来加载剩余的 :ref:`second-stage-bootloader`。然而,此时系统的时钟速度低于其被配置的速度,并且在这个阶段,只支持部分 flash 模式。因此,当 :ref:`second-stage-bootloader` 运行时,它会从当前应用程序的二进制文件头中读取数据(而不是从引导加载程序的文件头中读取数据),并使用这些数据重新配置 flash。这样的配置流程可让 OTA 更新去更改当前使用的 SPI flash 的配置。 +:ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage-bootloader` 文件头中的配置信息,并使用这些信息来加载剩余的 :ref:`second-stage-bootloader`。然而,此时系统的时钟速度低于其被配置的速度,并且在这个阶段,只支持部分 flash 模式。因此,当 :ref:`second-stage-bootloader` 运行时,它会从当前应用程序的二进制文件头中读取数据(而不是从 :ref:`second-stage-bootloader` 的文件头中读取数据),并使用这些数据重新配置 flash。这样的配置流程可让 OTA 更新去更改当前使用的 SPI flash 的配置。 .. only:: esp32 - ESP-IDF V4.0 版本之前的引导加载程序使用其自身的文件头来配置 SPI flash,这意味着无法在 OTA 更新时更改 SPI flash 配置。为了与旧引导加载程序兼容,应用程序在其启动期间使用应用程序文件头中的配置信息重新初始化 flash 配置。 + ESP-IDF V4.0 版本之前的引导加载程序使用其自身的文件头来配置 SPI flash,这意味着无法在 OTA 更新时更改 SPI flash 配置。为了与旧版本的引导加载程序兼容,应用程序在其启动期间使用应用程序文件头中的配置信息重新初始化 flash 配置。 日志级别 --------- @@ -125,7 +125,7 @@ ROM 中的 :ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage- 回滚 -------- -回滚和反回滚功能也必须在引导程序中配置。 +回滚和反回滚功能也必须在引导加载程序中配置。 请参考 :doc:`OTA API 参考文档 ` 中的 :ref:`app_rollback` 和 :ref:`anti-rollback` 章节。 @@ -157,7 +157,7 @@ ROM 中的 :ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage- 可以使用如下方法解决此问题: -- 将 :ref:`bootloader 编译器优化 ` 重新设置回默认值“Size”。 +- 将 :ref:`引导加载程序编译器优化 ` 重新设置回默认值“Size”。 - 降低 :ref:`引导加载程序日志级别 `。将日志级别设置为 Warning, Error 或 None 都会显著减少最终二进制文件的大小(但也可能会让调试变得更加困难)。 - 将 :ref:`CONFIG_PARTITION_TABLE_OFFSET` 设置为高于 0x8000 的值,以便稍后将分区表放置在 flash 中,这样可以增加引导加载程序的可用空间。如果 :doc:`分区表 ` 的 CSV 文件包含明确的分区偏移量,则需要修改这些偏移量,从而保证没有分区的偏移量低于 ``CONFIG_PARTITION_TABLE_OFFSET + 0x1000``。(这包括随 ESP-IDF 提供的默认分区 CSV 文件) @@ -186,4 +186,4 @@ ROM 中的 :ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage- 在引导加载程序的代码中,用户不能使用其他组件提供的驱动和函数,如果确实需要,请将该功能的实现部分放在项目的 `bootloader_components` 目录中(注意,这会增加引导加载程序的大小)。 -如果引导加载程序过大,则可能与内存中的分区表重叠,分区表默认烧录在偏移量 0x8000 处。增加 :ref:`分区表偏移量 ` ,将分区表放在 flash 中靠后的区域,这样可以增加引导程序的可用空间。 +如果引导加载程序过大,则可能与内存中的分区表重叠,分区表默认烧录在偏移量 0x8000 处。增加 :ref:`分区表偏移量 ` ,将分区表放在 flash 中靠后的区域,这样可以增加引导加载程序的可用空间。 diff --git a/docs/zh_CN/api-guides/build-system.rst b/docs/zh_CN/api-guides/build-system.rst index 569a3818dd6a..05620dded907 100644 --- a/docs/zh_CN/api-guides/build-system.rst +++ b/docs/zh_CN/api-guides/build-system.rst @@ -25,11 +25,11 @@ ESP-IDF 可以显式地指定和配置每个组件。在构建项目的时候, 概念 ---- -- ``项目`` 特指一个目录,其中包含了构建可执行应用程序所需的全部文件和配置,以及其他支持型文件,例如分区表、数据/文件系统分区和引导程序。 +- ``项目`` 特指一个目录,其中包含了构建可执行应用程序所需的全部文件和配置,以及其他支持型文件,例如分区表、数据/文件系统分区和引导加载程序。 - ``项目配置`` 保存在项目根目录下名为 ``sdkconfig`` 的文件中,可以通过 ``idf.py menuconfig`` 进行修改,且一个项目只能包含一个项目配置。 -- ``应用程序`` 是由 ESP-IDF 构建得到的可执行文件。一个项目通常会构建两个应用程序:项目应用程序(可执行的主文件,即用户自定义的固件)和引导程序(启动并初始化项目应用程序)。 +- ``应用程序`` 是由 ESP-IDF 构建得到的可执行文件。一个项目通常会构建两个应用程序:项目应用程序(可执行的主文件,即用户自定义的固件)和引导加载程序(启动并初始化项目应用程序)。 - ``组件`` 是模块化且独立的代码,会被编译成静态库(.a 文件)并链接到应用程序。部分组件由 ESP-IDF 官方提供,其他组件则来源于其它开源项目。 @@ -97,7 +97,7 @@ idf.py make app-flash -可用的目标还包括:``flash``、``app-flash`` (仅用于 app)、``bootloader-flash`` (仅用于 bootloader)。 +可用的目标还包括:``flash``、``app-flash`` (仅用于 app)、``bootloader-flash`` (仅用于引导加载程序)。 以这种方式烧录时,可以通过设置 ``ESPPORT`` 和 ``ESPBAUD`` 环境变量来指定串口设备和波特率。可以在操作系统或 IDE 项目中设置该环境变量,或者直接在命令行中进行设置:: @@ -307,9 +307,16 @@ ESP-IDF 适用于 Python 3.8 以上版本。 同名组件 -------- -ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指定的顺序依次进行,这意味着在默认情况下,首先搜索 ESP-IDF 内部组件(``IDF_PATH/components``),然后是 ``EXTRA_COMPONENT_DIRS`` 中的组件,最后是项目组件(``PROJECT_DIR/components``)。如果这些目录中的两个或者多个包含具有相同名字的组件,则使用搜索到的最后一个位置的组件。这就允许将组件复制到项目目录中再修改以覆盖 ESP-IDF 组件,如果使用这种方式,ESP-IDF 目录本身可以保持不变。 +ESP-IDF 在搜索所有待构建的组件时,会按照以下优先级搜索组件目录(从高到低): -.. 注解:: +* 项目目录下的组件 +* ``EXTRA_COMPONENT_DIRS`` 中的组件 +* 项目目录下 ``managed_components`` 目录中的组件。这些组件由 IDF Component Manager 下载并管理。(除非 IDF Component Manager 被禁用) +* ``IDF_PATH/components`` 目录下的组件 + +如果有两个及以上同名组件,构建系统会使用优先级更高的组件。这使得我们可以在项目中覆盖 ESP-IDF 提供的组件。只需要复制 ESP-IDF 组件到项目目录下,然后修改它。这样可以在修改组件的同时,不修改 ESP-IDF 的源代码。 + +.. note:: 如果在现有项目中通过将组件移动到一个新位置来覆盖它,项目不会自动看到新组件的路径。请运行 ``idf.py reconfigure`` 命令后(或删除项目构建文件夹)再重新构建。 @@ -1086,9 +1093,9 @@ flash 参数 运行项目构建之后,构建目录将包含项目二进制输出文件(``.bin`` 文件),同时也包含以下烧录数据文件: -- ``flash_project_args`` 包含烧录整个项目的参数,包括应用程序 (app)、引导程序 (bootloader)、分区表,如果设置了 PHY 数据,也会包含此数据。 +- ``flash_project_args`` 包含烧录整个项目的参数,包括应用程序 (app)、引导加载程序 (bootloader)、分区表,如果设置了 PHY 数据,也会包含此数据。 - ``flash_app_args`` 只包含烧录应用程序的参数。 -- ``flash_bootloader_args`` 只包含烧录引导程序的参数。 +- ``flash_bootloader_args`` 只包含烧录引导加载程序的参数。 .. highlight:: bash @@ -1101,12 +1108,12 @@ flash 参数 构建目录中还包含生成的 ``flasher_args.json`` 文件,此文件包含 JSON 格式的项目烧录信息,可用于 ``idf.py`` 和其它需要项目构建信息的工具。 -构建 Bootloader -=============== +构建引导加载程序 +================ -引导程序是 :idf:`/components/bootloader/subproject` 内部独特的“子项目”,它有自己的项目 CMakeLists.txt 文件,能够构建独立于主项目的 ``.ELF`` 和 ``.BIN`` 文件,同时它又与主项目共享配置和构建目录。 +引导加载程序是 :idf:`/components/bootloader/subproject` 内部独特的“子项目”,它有自己的项目 CMakeLists.txt 文件,能够构建独立于主项目的 ``.ELF`` 和 ``.BIN`` 文件,同时它又与主项目共享配置和构建目录。 -子项目通过 :idf_file:`/components/bootloader/project_include.cmake` 文件作为外部项目插入到项目的顶层,主构建进程会运行子项目的 CMake,包括查找组件(主项目使用的组件的子集),生成引导程序专用的配置文件(从主 ``sdkconfig`` 文件中派生)。 +子项目通过 :idf_file:`/components/bootloader/project_include.cmake` 文件作为外部项目插入到项目的顶层,主构建进程会运行子项目的 CMake,包括查找组件(主项目使用的组件的子集),生成引导加载程序专用的配置文件(从主 ``sdkconfig`` 文件中派生)。 .. _write-pure-component: @@ -1257,23 +1264,37 @@ ESP-IDF 构建命令 .. code-block:: none - idf_build_component(component_dir) + idf_build_component(component_dir [component_source]) 向构建系统提交一个包含组件的 *component_dir* 目录。相对路径会被转换为相对于当前目录的绝对路径。 -所有对该命令的调用必须在`idf_build_process`之前执行。 -该命令并不保证组件在构建过程中会被处理(参见 `idf_build_process` 中 `COMPONENTS` 参数说明) +一个可选的 *component_source* 参数可以用于指定组件源。(默认为 "project_components") + +这个参数决定了同名组件的优先级。详细信息请参考 :ref:`cmake-components-same-name`。 + +该参数可以指定如下组件源(优先级从高到低排序): + +- "project_components" - 项目目录中的组件 +- "project_extra_components" - 通过 ``EXTRA_COMPONENT_DIRS`` 指定的额外组件 +- "project_managed_components" - 通过 IDF Component Manager 管理的组件 +- "idf_components" - ESP-IDF 中的组件,通常在 :idf:`/components` 目录中 + +举个例子,如果有两个组件,组件名都为 "json"。一个组件源被定义为 "project_components",另一个组件源被定义为 "idf_components",那么 "project_components" 中的 "json" 组件会被优先选择。 + +.. warning:: + + 所有对该命令的调用必须在 `idf_build_process` 之前执行。该命令并不保证组件在构建过程中会被处理(参见 `idf_build_process` 中 `COMPONENTS` 参数说明)。 .. code-block:: none - idf_build_process(target - [PROJECT_DIR project_dir] - [PROJECT_VER project_ver] - [PROJECT_NAME project_name] - [SDKCONFIG sdkconfig] - [SDKCONFIG_DEFAULTS sdkconfig_defaults] - [BUILD_DIR build_dir] - [COMPONENTS component1 component2 ...]) + idf_build_process(target + [PROJECT_DIR project_dir] + [PROJECT_VER project_ver] + [PROJECT_NAME project_name] + [SDKCONFIG sdkconfig] + [SDKCONFIG_DEFAULTS sdkconfig_defaults] + [BUILD_DIR build_dir] + [COMPONENTS component1 component2 ...]) 为导入 ESP-IDF 组件执行大量的幕后工作,包括组件配置、库创建、依赖性扩展和解析。在这些功能中,对于用户最重要的可能是通过调用每个组件的 ``idf_component_register`` 来创建库。该命令为每个组件创建库,这些库可以使用别名来访问,其形式为 idf::*component_name*。 这些别名可以用来将组件链接到用户自己的目标、库或可执行文件上。 @@ -1422,6 +1443,7 @@ ESP-IDF 组件属性 - COMPONENT_LIB - 所创建的组件静态/接口库的名称;由 ``idf_build_component`` 设置,库本身由 ``idf_component_register`` 创建。 - COMPONENT_NAME - 组件的名称;由 ``idf_build_component`` 根据组件的目录名设置。 - COMPONENT_TYPE - 组件的类型(LIBRARY 或 CONFIG_ONLY)。如果一个组件指定了源文件或嵌入了一个文件,那么它的类型就是 LIBRARY。 +- COMPONENT_SOURCE - 组件源。可选值为 "idf_components","project_managed_components","project_components","project_extra_components". 用于决定同名组件的优先级。 - EMBED_FILES - 要嵌入组件的文件列表;由 ``idf_component_register`` EMBED_FILES 参数设置。 - EMBED_TXTFILES - 要嵌入组件的文本文件列表;由 ``idf_component_register`` EMBED_TXTFILES 参数设置。 - INCLUDE_DIRS - 组件 include 目录列表;由 ``idf_component_register`` INCLUDE_DIRS 参数设置。 @@ -1646,9 +1668,9 @@ CMake 中不可用的功能 应用示例 -------------------- -- :example:`build_system/wrappers` 演示了如何使用链接器功能在 ESP-IDF 和引导程序中重新定义或覆盖任何公共函数,以修改或扩展函数的默认行为。 +- :example:`build_system/wrappers` 演示了如何使用链接器功能在 ESP-IDF 和引导加载程序中重新定义或覆盖任何公共函数,以修改或扩展函数的默认行为。 -- :example:`custom_bootloader/bootloader_override` 演示了如何从常规项目中覆盖二级引导程序,提供一个自定义引导程序,在启动时打印额外的消息,并能够基于某些条件(如目标依赖性或 KConfig 选项)有条件地覆盖引导程序。 +- :example:`custom_bootloader/bootloader_override` 演示了如何从常规项目中覆盖二级引导加载程序,提供一个自定义引导加载程序,在启动时打印额外的消息,并能够基于某些条件(如目标依赖性或 KConfig 选项)有条件地覆盖引导加载程序。 - :example:`build_system/cmake/import_lib` 演示了如何使用 ExternalProject CMake 模块导入和使用第三方库。 diff --git a/docs/zh_CN/api-guides/cplusplus.rst b/docs/zh_CN/api-guides/cplusplus.rst index 5968ef272283..ba0c833e9071 100644 --- a/docs/zh_CN/api-guides/cplusplus.rst +++ b/docs/zh_CN/api-guides/cplusplus.rst @@ -193,12 +193,3 @@ ESP-IDF 支持 ``iostream`` 功能,但应注意: ------------- 请勿在 C++ 中使用 ``setjmp``/``longjmp``。``longjmp`` 会在不调用任何析构函数的情况下盲目跳出堆栈,容易引起未定义的行为和内存泄漏。请改用 C++ 异常处理,这类程序可以确保正确调用析构函数。如果无法使用 C++ 异常处理,请使用其他替代方案( ``setjmp``/``longjmp`` 除外),如简单的返回码。 - -应用示例 --------------------- - -- :example:`cxx/pthread` - -- :example:`cxx/exceptions` 演示了如何在 {IDF_TARGET_NAME} 中启用和使用 C++ 异常。该示例声明了一个类,当提供的参数等于 0 时,这个类会在构造函数中抛出异常。 - -- :example:`cxx/rtti` diff --git a/docs/zh_CN/api-guides/external-ram.rst b/docs/zh_CN/api-guides/external-ram.rst index 92bfa9eafcd6..51a8af1b9d3e 100644 --- a/docs/zh_CN/api-guides/external-ram.rst +++ b/docs/zh_CN/api-guides/external-ram.rst @@ -167,7 +167,7 @@ ESP-IDF 启动过程中,片外 RAM 被映射到数据虚拟地址空间,该 在 PSRAM 中直接执行代码的好处包括: - - PSRAM 访问速度可能快于 flash,因此性能更好。例如,如果使用的 PSRAM 是八线的,且被配置为 80 MHz,而 flash 是4线的,且被配置为 80 Mhz,那么 PSRAM 的访问速度是快于 flash 的。 + - PSRAM 的访问速度可能快于 flash,因此性能更好。例如,如果使用的 PSRAM 是八线的,且被配置为 80 MHz,而 flash 是四线的,且被配置为 80 Mhz,那么 PSRAM 的访问速度将快于 flash。 - 在进行 SPI1 flash 操作期间,cache 仍然保持启用状态,这样可以优化代码执行性能。由于无需把中断服务程序 (ISR)、ISR 回调和在此期间可能被访问的数据放置在片上 RAM 中,片上 RAM 可用于其他用途,从而提高了使用效率。这个特性适用于需要处理大量数据的高吞吐量外设应用,能显著提高 SPI1 flash 操作期间的性能。 @@ -188,7 +188,9 @@ ESP-IDF 启动过程中,片外 RAM 被映射到数据虚拟地址空间,该 由于 {IDF_TARGET_NAME} flash 和 PSRAM 使用两个独立的 SPI 总线,将 flash 内容移动到 PSRAM 实际上增加了 PSRAM MSPI 总线的负载, - 例如,PSRAM 的访问速度可能快于 flash (比如在 ESP32-P4 上,选择的 PSRAM 是十六线的并将其配置为 200 MHz, 此时 PSRAM 的访问速度是远快于一颗被配置为 80 MHz 的四线 flash 芯片),如果这些之前在 flash 中被就地执行的指令和数据不是十分频繁地被访问,则使能这个选项会增加系统的性能。建议先进行性能分析以确定启用此选项是否会显著影响应用程序性能。 + PSRAM 的访问速度可能快于 flash。比如在 ESP32-P4 上,选择十六线 PSRAM 并将其配置为 200 MHz,此时 PSRAM 的访问速度远快于被配置为 80 MHz 的四线 flash 芯片。 + + 如果这些之前在 flash 中被就地执行的指令和数据不会被频繁访问,则使能该选项可能会提高系统的性能。建议先进行性能分析,评估启用此选项是否会显著影响应用程序的性能。 片外 RAM 使用限制 =================== @@ -211,7 +213,7 @@ ESP-IDF 启动过程中,片外 RAM 被映射到数据虚拟地址空间,该 - 一般来说,片外 RAM 不会用作任务堆栈存储器。:cpp:func:`xTaskCreate` 及类似函数始终会为堆栈和任务 TCB 分配片上储存器。 -可以使用 :ref:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` 选项将任务堆栈放入片外存储器。这时,必须使用 :cpp:func:`xTaskCreateStatic` 指定从片外存储器分配的任务堆栈缓冲区,否则任务堆栈将仍从片上存储器分配。 +可以使用 :ref:`CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM` 选项将任务堆栈放入片外存储器。这时,必须使用 :cpp:func:`xTaskCreateStatic` 指定从片外存储器分配的任务堆栈缓冲区,否则任务堆栈将仍从片上存储器分配。 初始化失败 diff --git a/docs/zh_CN/api-guides/fatal-errors.rst b/docs/zh_CN/api-guides/fatal-errors.rst index 6426732ae499..dc679e345bce 100644 --- a/docs/zh_CN/api-guides/fatal-errors.rst +++ b/docs/zh_CN/api-guides/fatal-errors.rst @@ -288,14 +288,14 @@ RTC 看门狗超时 ---------------- {IDF_TARGET_RTCWDT_RTC_RESET:default="Not updated", esp32="RTCWDT_RTC_RESET", esp32s2="RTCWDT_RTC_RST", esp32s3="RTCWDT_RTC_RST", esp32c3="RTCWDT_RTC_RST", esp32c2="RTCWDT_RTC_RST", esp32c6="LP_WDT_SYS", esp32h2="LP_WDT_SYS", esp32p4="LP_WDT_SYS"} -RTC 看门狗在启动代码中用于跟踪执行时间,也有助于防止由于电源不稳定引起的锁定。RTC 看门狗默认启用,参见 :ref:`CONFIG_BOOTLOADER_WDT_ENABLE`。如果执行时间超时,RTC 看门狗将自动重启系统。此时,ROM 引导加载程序将打印消息 ``RTC Watchdog Timeout`` 说明重启原因。 +RTC 看门狗在启动代码中用于跟踪执行时间,也有助于防止由于电源不稳定引起的锁定。RTC 看门狗默认启用,参见 :ref:`CONFIG_BOOTLOADER_WDT_ENABLE`。如果执行时间超时,RTC 看门狗将自动重启系统。此时,一级 (ROM) 引导加载程序将打印消息 ``RTC Watchdog Timeout`` 说明重启原因。 :: rst:0x10 ({IDF_TARGET_RTCWDT_RTC_RESET}) -RTC 看门狗涵盖了从一级引导程序(ROM 引导程序)到应用程序启动的执行时间,最初在 ROM 引导程序中设置,而后在引导程序中使用 :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` 选项进行配置(默认 9000 ms)。在应用初始化阶段,由于慢速时钟源可能已更改,RTC 看门狗将被重新配置,最后在调用 ``app_main()`` 之前被禁用。可以使用选项 :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 以保证 RTC 看门狗在调用 ``app_main`` 之前不被禁用,而是保持运行状态,用户需要在应用代码中定期“喂狗”。 +RTC 看门狗涵盖了从一级 (ROM) 引导加载程序到应用程序启动的执行时间,最初在一级 (ROM) 引导加载程序中设置,而后在引导加载程序中使用 :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` 选项进行配置(默认 9000 ms)。在应用初始化阶段,由于慢速时钟源可能已更改,RTC 看门狗将被重新配置,最后在调用 ``app_main()`` 之前被禁用。可以使用选项 :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 以保证 RTC 看门狗在调用 ``app_main`` 之前不被禁用,而是保持运行状态,用户需要在应用代码中定期“喂狗”。 .. _Guru-Meditation-Errors: diff --git a/docs/zh_CN/api-guides/flash_psram_config.rst b/docs/zh_CN/api-guides/flash_psram_config.rst index d121056091b2..0dafd6a52f96 100644 --- a/docs/zh_CN/api-guides/flash_psram_config.rst +++ b/docs/zh_CN/api-guides/flash_psram_config.rst @@ -73,7 +73,7 @@ SPI Flash 和片外 SPI RAM 配置 .. note:: - 如果配有八线 flash 的开发板在第二阶段引导加载程序之前复位,请参考 :ref:`错误处理章节 `。 + 如果配有八线 flash 的开发板在二级引导加载程序之前复位,请参考 :ref:`错误处理章节 `。 .. _flash-psram-combination: @@ -228,7 +228,7 @@ F4R4 硬件 错误处理 -------- -1. 如果配有八线 flash 的开发板在第二阶段引导加载程序之前复位: +1. 如果配有八线 flash 的开发板在二级引导加载程序之前复位: .. code-block:: c @@ -243,7 +243,7 @@ F4R4 硬件 这可能意味着必要的 efuse 未得到正确烧录。请使用命令 ``espefuse.py summary``,检查芯片的 eFuse 位。 - ROM 引导加载程序可通过 eFuse 位 ``FLASH_TYPE`` 将 flash 复位为默认模式(SPI 模式)。如果未烧录此位,且 flash 处于 OPI 模式,则 ROM 引导加载程序可能无法从 flash 中读取并加载以下图像。 + 一级 (ROM) 引导加载程序可通过 eFuse 位 ``FLASH_TYPE`` 将 flash 复位为默认模式(SPI 模式)。如果未烧录此位,且 flash 处于 OPI 模式,则一级 (ROM) 引导加载程序可能无法从 flash 中读取并加载以下图像。 2. 如果启用 :ref:`CONFIG_ESPTOOLPY_OCT_FLASH` 后出现如下错误日志: diff --git a/docs/zh_CN/api-guides/hlinterrupts.rst b/docs/zh_CN/api-guides/hlinterrupts.rst index 7f78e1a3d9cc..07fec7119e7b 100644 --- a/docs/zh_CN/api-guides/hlinterrupts.rst +++ b/docs/zh_CN/api-guides/hlinterrupts.rst @@ -119,3 +119,5 @@ Xtensa 架构支持 32 个中断处理程序,这些中断分为从 1 到 7 的 - 中等优先级的中断理论上也可以通过上述方式处理,但 ESP-IDF 尚不支持此功能。 - 要检查 Xtensa 指令集架构 (ISA),请参阅 `Xtensa ISA 摘要 `_。 + +:example:`system/nmi_isr` 提供了一个示例,可以在基于 Xtensa 架构的目标平台上实现自定义 NMI 处理程序。 diff --git a/docs/zh_CN/api-guides/inc/external-ram-esp32-notes.rst b/docs/zh_CN/api-guides/inc/external-ram-esp32-notes.rst index 6d93693c8de2..6c7186a32817 100644 --- a/docs/zh_CN/api-guides/inc/external-ram-esp32-notes.rst +++ b/docs/zh_CN/api-guides/inc/external-ram-esp32-notes.rst @@ -1,4 +1,4 @@ -* PSRAM 中的栈:对于不以任何直接或间接方式调用 ROM 中代码的任务,选项 :ref:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` 会取消 :cpp:func:`xTaskCreateStatic` 中的检查,允许任务栈存放在外部 RAM 中。但 **不建议** 使用此选项。 +* PSRAM 中的栈:对于不以任何直接或间接方式调用 ROM 中代码的任务,选项 :ref:`CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM` 会取消 :cpp:func:`xTaskCreateStatic` 中的检查,允许任务栈存放在外部 RAM 中。但 **不建议** 使用此选项。 * 在以 80 MHz 时钟速度运行时,外部 RAM 还必须占用 HSPI 或 VSPI 总线。设置 :ref:`CONFIG_SPIRAM_OCCUPY_SPI_HOST` 选项可以选择使用的 SPI 主机。 diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index c999a822afe0..7dbe29957f22 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -47,4 +47,5 @@ API 指南 :SOC_USB_SERIAL_JTAG_SUPPORTED: usb-serial-jtag-console :SOC_WIFI_SUPPORTED: wifi :SOC_WIFI_SUPPORTED: wifi-security + wifi-expansion :SOC_WIFI_SUPPORTED or SOC_BT_SUPPORTED or SOC_IEEE802154_SUPPORTED: phy diff --git a/docs/zh_CN/api-guides/jtag-debugging/esp32.inc b/docs/zh_CN/api-guides/jtag-debugging/esp32.inc index 09ef978a2e1e..44ed93766502 100644 --- a/docs/zh_CN/api-guides/jtag-debugging/esp32.inc +++ b/docs/zh_CN/api-guides/jtag-debugging/esp32.inc @@ -112,7 +112,7 @@ - 描述 * - ``ESP32_FLASH_VOLTAGE`` - 如果 ESP32 模组集成的是 1.8 V 的 flash,将该变量设置为 ``1.8``,详情请参考 :ref:`jtag-debugging-tip-code-flash-voltage` - * - ``ESP32_ONLYCPU`` + * - ``ESP_ONLYCPU`` - 对于多核芯片,将该值设置为 ``1`` 可以仅启用单核调试功能 --- diff --git a/docs/zh_CN/api-guides/jtag-debugging/esp32p4.inc b/docs/zh_CN/api-guides/jtag-debugging/esp32p4.inc index 88e2a7616c50..ea9b7d8140de 100644 --- a/docs/zh_CN/api-guides/jtag-debugging/esp32p4.inc +++ b/docs/zh_CN/api-guides/jtag-debugging/esp32p4.inc @@ -29,20 +29,25 @@ Info : only one transport option; autoselecting 'jtag' Info : esp_usb_jtag: VID set to 0x303a and PID to 0x1001 Info : esp_usb_jtag: capabilities descriptor set to 0x2000 - adapter speed: 40000 kHz - Info : esp_usb_jtag: serial (60:55:F9:F8:80:5C) + Info : Listening on port 6666 for tcl connections + Info : Listening on port 4444 for telnet connections + Info : esp_usb_jtag: serial (60:55:F9:F9:04:AD) Info : esp_usb_jtag: Device found. Base speed 24000KHz, div range 1 to 255 Info : clock speed 24000 kHz - Info : JTAG tap: esp32p4.lp.cpu tap/device found: 0x00012c25 (mfg: 0x612 (Espressif Systems), part: 0x0012, ver: 0x0) - Info : JTAG tap: esp32p4.hp.cpu tap/device found: 0x00012c25 (mfg: 0x612 (Espressif Systems), part: 0x0012, ver: 0x0) - Info : [esp32p4.hp.cpu] datacount=1 progbufsize=2 - Info : [esp32p4.hp.cpu] Examined RISC-V core; found 2 harts - Info : [esp32p4.hp.cpu] XLEN=32, misa=0x40901125 - Info : [esp32p4.hp.cpu] Examination succeed - Info : starting gdb server for esp32p4.hp.cpu on 3333 + Info : JTAG tap: esp32p4.tap0 tap/device found: 0x00012c25 (mfg: 0x612 (Espressif Systems), part: 0x0012, ver: 0x0) + Info : JTAG tap: esp32p4.tap1 tap/device found: 0x00012c25 (mfg: 0x612 (Espressif Systems), part: 0x0012, ver: 0x0) + Info : [esp32p4.hp.cpu0] datacount=1 progbufsize=2 + Info : [esp32p4.hp.cpu0] Core 0 made part of halt group 1. + Info : [esp32p4.hp.cpu0] Examined RISC-V core; found 2 harts + Info : [esp32p4.hp.cpu0] XLEN=32, misa=0x40901125 + Info : [esp32p4.hp.cpu0] Examination succeed + Info : [esp32p4.hp.cpu1] datacount=1 progbufsize=2 + Info : [esp32p4.hp.cpu1] Core 1 made part of halt group 1. + Info : [esp32p4.hp.cpu1] Examined RISC-V core; found 2 harts + Info : [esp32p4.hp.cpu1] XLEN=32, misa=0x40901125 + Info : [esp32p4.hp.cpu1] Examination succeed + Info : [esp32p4.hp.cpu0] starting gdb server on 3333 Info : Listening on port 3333 for gdb connections - Info : Listening on port 6666 for tcl connections - Info : Listening on port 4444 for telnet connections .. |run-openocd-cfg-file-err| replace:: ``Can't find board/esp32p4-builtin.cfg`` diff --git a/docs/zh_CN/api-guides/jtag-debugging/index.rst b/docs/zh_CN/api-guides/jtag-debugging/index.rst index 86e626117de5..c15da0375f4b 100644 --- a/docs/zh_CN/api-guides/jtag-debugging/index.rst +++ b/docs/zh_CN/api-guides/jtag-debugging/index.rst @@ -226,6 +226,8 @@ OpenOCD 安装完成后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG - ``exit`` - 烧写完成后退出 OpenOCD(可选) - ``compress`` - 烧写开始前压缩镜像文件(可选) - ``encrypt`` - 烧写到 flash 前加密二进制文件,与 ``idf.py encrypted-flash`` 功能相同(可选) +- ``no_clock_boost`` - 禁用在烧写前将目标时钟频率设置为其最大可能值(可选)。默认情况下禁用该选项,即默认启用时钟提升。 +- ``restore_clock`` - 可选。烧写完成后将时钟频率恢复到初始值。默认情况下不启用。 现在可以调试应用程序了,请按照以下章节中的步骤进行操作。 diff --git a/docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst b/docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst index a42c79c5f16f..ba785b5cd608 100644 --- a/docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst +++ b/docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst @@ -178,6 +178,8 @@ TCL 语言中为变量赋值的语法是: - 设置成 ``0`` 可以关闭对 flash 断点的支持。 * - ``ESP_SEMIHOST_BASEDIR`` - 设置 semihosting 在主机端的默认目录。 + * - ``ESP_ONLYCPU`` + - 对于多核芯片,将该值设置为 ``1`` 可以仅启用单核调试功能 .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: openocd-target-specific-config-vars @@ -230,7 +232,7 @@ JTAG 管脚是否能用于其他功能 JTAG 与 flash 加密和安全引导 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -默认情况下,开启了 flash 加密和(或者)安全引导后,系统在首次启动时,引导程序会烧写 eFuse 的某个比特,从而将 JTAG 永久关闭。 +默认情况下,开启了 flash 加密和(或者)安全引导后,系统在首次启动时,引导加载程序会烧写 eFuse 的某个比特,从而将 JTAG 永久关闭。 .. only:: SOC_HMAC_SUPPORTED @@ -247,7 +249,7 @@ Kconfig 配置项 :ref:`CONFIG_SECURE_BOOT_ALLOW_JTAG` 可以改变这个默认 .. note:: - 同样地,当启用该选项,并且在调试过程中设置了软件断点,引导程序将无法校验通过应用程序的签名。 + 同样地,当启用该选项,并且在调试过程中设置了软件断点,引导加载程序将无法校验通过应用程序的签名。 .. only:: esp32 diff --git a/docs/zh_CN/api-guides/low-power-mode/low-power-mode-wifi.rst b/docs/zh_CN/api-guides/low-power-mode/low-power-mode-wifi.rst index 3ed8b54f1803..2ffe3331e918 100644 --- a/docs/zh_CN/api-guides/low-power-mode/low-power-mode-wifi.rst +++ b/docs/zh_CN/api-guides/low-power-mode/low-power-mode-wifi.rst @@ -14,14 +14,13 @@ Wi-Fi 场景下低功耗模式介绍 在介绍具体内容前先给出 Wi-Fi 场景下低功耗模式总结表,以方便用户根据需求快速选择想要了解的内容,选择合适的低功耗模式。 - .. include:: ../sleep-current/{IDF_TARGET_PATH_NAME}_summary.inc .. note:: 上表中所有电流均为平均电流,所测数据均在屏蔽箱中测试得出。表中术语在下文均有介绍,用户可根据需求进行查看。 -.. _Wi-Fi 省电的基本原理: +.. _Basic Principles of Wi-Fi Power Saving: Wi-Fi 省电的基本原理 --------------------- @@ -90,9 +89,9 @@ Wi-Fi 省电的基本原理 可以看出影响功耗表现的主要有三点:interval、period 和 base current。 - - **interval** 是 station Wi-Fi 相关模块工作的间隔,既可以由低功耗模式自定义,也可根据 Wi-Fi 协议省电机制(详细内容请见 :ref:`Wi-Fi 省电的基本原理`),由 DTIM 周期决定。可以看出在同等情下,interval 越大,功耗表现会更好,但是响应会更慢,影响通信的及时性。 + - **interval** 是 station Wi-Fi 相关模块工作的间隔,既可以由低功耗模式自定义,也可根据 Wi-Fi 协议省电机制(详细内容请见 :ref:`Basic Principles of Wi-Fi Power Saving`),由 DTIM 周期决定。可以看出在同等情下,interval 越大,功耗表现会更好,但是响应会更慢,影响通信的及时性。 - - **period** 可以看作每次 station Wi-Fi 工作的时间,这段时间的长度也会影响功耗的表现。period 不是一个固定的时长(详细内容请见 :ref:`Wi-Fi 省电的基本原理`),在保证 Wi-Fi 通信正常的情况下,period 持续时间越短,功耗表现越好。但是减少 period 时间,必然会影响通信的可靠性。 + - **period** 可以看作每次 station Wi-Fi 工作的时间,这段时间的长度也会影响功耗的表现。period 不是一个固定的时长(详细内容请见 :ref:`Basic Principles of Wi-Fi Power Saving`),在保证 Wi-Fi 通信正常的情况下,period 持续时间越短,功耗表现越好。但是减少 period 时间,必然会影响通信的可靠性。 - **base current** 是 Wi-Fi 相关模块不工作时芯片的电流,影响其大小的因素很多,不同的功耗模式下休眠策略不同。所以,在满足功能的情况下,优化配置降低该电流大小可以提高功耗表现,但同时关闭其余模块会影响相关功能和芯片的唤醒时间。 @@ -106,7 +105,7 @@ Modem-sleep 模式主要工作原理基于 DTIM 机制,周期性的醒来处 Modem-sleep 模式会在 Wi-Fi 任务结束后自动进入休眠无需调用 API,休眠时仅会关闭 Wi-Fi 相关模块 (PHY),其余模块均处在正常上电状态。 -Modem-sleep 模式默认会根据 DTIM 周期或 listen interval(于 :ref:`Modem-sleep 模式配置` 中介绍)醒来,相当于系统自动设置了一个 Wi-Fi 唤醒源,因此用户无需再配置唤醒源,同时系统主动发包时也可以唤醒。 +Modem-sleep 模式默认会根据 DTIM 周期或 listen interval(于 :ref:`Modem-sleep Mode Configuration` 中介绍)醒来,相当于系统自动设置了一个 Wi-Fi 唤醒源,因此用户无需再配置唤醒源,同时系统主动发包时也可以唤醒。 Modem-sleep 模式是一个开关型的模式,调用 API 开启后一直自动运行,其工作流程十分简单,具体如下图。 @@ -121,7 +120,7 @@ Modem-sleep 模式是一个开关型的模式,调用 API 开启后一直自动 Modem-sleep 模式工作流程图 -根据上文的基本电流图,结合 Modem-sleep 模式的工作原理,以 Min Modem 模式(于 :ref:`Modem-sleep 模式配置` 中介绍)为例可得理想情况下电流变化图。 +根据上文的基本电流图,结合 Modem-sleep 模式的工作原理,以 Min Modem 模式(于 :ref:`Modem-sleep Mode Configuration` 中介绍)为例可得理想情况下电流变化图。 .. code-block:: text @@ -294,7 +293,7 @@ Deep-sleep 模式在 Wi-Fi 场景下与纯系统下基本相同,详情可以 - 丢失 beacon 时睡眠优化 (:ref:`CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT`) -.. _Modem-sleep 模式配置: +.. _Modem-sleep Mode Configuration: Modem-sleep 模式配置 +++++++++++++++++++++++ diff --git a/docs/zh_CN/api-guides/lwip.rst b/docs/zh_CN/api-guides/lwip.rst index 34e8b485fe21..4ebc5975531f 100644 --- a/docs/zh_CN/api-guides/lwip.rst +++ b/docs/zh_CN/api-guides/lwip.rst @@ -31,9 +31,9 @@ ESP-IDF 间接支持以下常见的 lwIP 应用程序 API: lwIP 中的 DNS 服务器配置为全局配置,而非针对特定接口的配置。如需同时使用不同 DNS 服务器的多个网络接口,在从一个接口获取 DHCP 租约时,请注意避免意外覆盖另一个接口的 DNS 设置。 -- 简单网络时间协议 (SNTP),由 :doc:`/api-reference/network/esp_netif` 功能间接支持,或通过 :component_file:`lwip/include/apps/esp_sntp.h` 中的函数直接支持。该函数还为 :component_file:`lwip/lwip/src/include/lwip/apps/sntp.h` 函数提供了线程安全的 API,请参阅 :ref:`system-time-sntp-sync`。 +- 简单网络时间协议 (SNTP),由 :doc:`/api-reference/network/esp_netif` 功能间接支持,或通过 :component_file:`lwip/include/apps/esp_sntp.h` 中的函数直接支持。该函数还为 :component_file:`lwip/lwip/src/include/lwip/apps/sntp.h` 函数提供了线程安全的 API,请参阅 :ref:`system-time-sntp-sync`。有关详细信息,请见 :example:`protocols/sntp`。该示例演示了如何使用 LwIP SNTP 模块从互联网服务器获取时间、配置同步方法与时间间隔,并使用 SNTP-over-DHCP 模块检索时间。 - ICMP Ping,由 lwIP ping API 的变体支持,请参阅 :doc:`/api-reference/protocols/icmp_echo`。 -- ICMPv6 Ping,由 lwIP 的 ICMPv6 Echo API 支持,用于测试 IPv6 网络连接情况。有关详细信息,请参阅 :example:`protocols/sockets/icmpv6_ping`。 +- ICMPv6 Ping,由 lwIP 的 ICMPv6 Echo API 支持,用于测试 IPv6 网络连接情况。有关详细信息,请参阅 :example:`protocols/sockets/icmpv6_ping`。该示例演示了如何使用网络接口发现 IPv6 地址,创建原始 ICMPv6 套接字,向目标 IPv6 地址发送 ICMPv6 Echo 请求,并等待目标返回 Echo 回复。 - NetBIOS 查找,由标准的 lwIP API 支持,:example:`protocols/http_server/restful_server` 示例中提供了使用 NetBIOS 在局域网中查找主机的选项。 - mDNS 与 lwIP 的默认 mDNS 使用不同实现方式,请参阅 :doc:`/api-reference/protocols/mdns`。但启用 :ref:`CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES` 设置项后,lwIP 可以使用 ``gethostbyname()`` 等标准 API 和 ``hostname.local`` 约定查找 mDNS 主机。 - lwIP 中的 PPP 实现可用于在 ESP-IDF 中创建 PPPoS(串行 PPP)接口。请参阅 :doc:`/api-reference/network/esp_netif` 组件文档,使用 :component_file:`esp_netif/include/esp_netif_defaults.h` 中定义的 ``ESP_NETIF_DEFAULT_PPP()`` 宏创建并配置 PPP 网络接口。:component_file:`esp_netif/include/esp_netif_ppp.h` 中提供了其他的运行时设置。PPPoS 接口通常用于与 NBIoT/GSM/LTE 调制解调器交互。`esp_modem `_ 仓库还支持更多应用层友好的 API,该仓库内部使用了上述 PPP lwIP 模块。 @@ -58,12 +58,19 @@ BSD 套接字的相关参考资料十分丰富,包括但不限于: 以下为 ESP-IDF 中使用 BSD 套接字 API 的部分示例: -- :example:`protocols/sockets/tcp_server` -- :example:`protocols/sockets/tcp_client` -- :example:`protocols/sockets/udp_server` -- :example:`protocols/sockets/udp_client` -- :example:`protocols/sockets/udp_multicast` -- :example:`protocols/http_request`:此简化示例使用 TCP 套接字发送 HTTP 请求,但更推荐使用 :doc:`/api-reference/protocols/esp_http_client` 发送 HTTP 请求 +- :example:`protocols/sockets/non_blocking` 演示了如何配置和运行一个支持 IPv4 和 IPv6 协议的非阻塞 TCP 客户端和服务器。 + +- :example:`protocols/sockets/tcp_server` 演示了如何创建一个 TCP 服务器,该服务器可以接受客户端的连接请求并接收数据。 + +- :example:`protocols/sockets/tcp_client` 演示了如何创建一个 TCP 客户端,该客户端使用预定义的 IP 地址和端口连接到服务器。 + +- :example:`protocols/sockets/tcp_client_multi_net` 演示了如何同时使用以太网和 Wi-Fi 接口连接,在每个接口上创建一个 TCP 客户端,并发送一个简单的 HTTP 请求和响应。 + +- :example:`protocols/sockets/udp_server` 演示了如何创建一个 UDP 服务器,该服务器可以接收客户端的连接请求和数据。 + +- :example:`protocols/sockets/udp_client` 演示了如何创建一个 UDP 客户端,该客户端使用预定义的 IP 地址和端口连接到服务器。 + +- :example:`protocols/sockets/udp_multicast` 演示了如何通过 BSD 风格的套接字接口使用 IPV4 和 IPV6 的 UDP 组播功能。 支持的函数 ^^^^^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-guides/partition-tables.rst b/docs/zh_CN/api-guides/partition-tables.rst index 7297ccf52842..2b47491940af 100644 --- a/docs/zh_CN/api-guides/partition-tables.rst +++ b/docs/zh_CN/api-guides/partition-tables.rst @@ -30,7 +30,7 @@ phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, -- flash 的 0x10000 (64 KB) 偏移地址处存放一个标记为 "factory" 的二进制应用程序,且启动加载器将默认加载这个应用程序。 +- flash 的 0x10000 (64 KB) 偏移地址处存放一个标记为 "factory" 的二进制应用程序。引导加载程序默认加载这个应用程序。 - 分区表中还定义了两个数据区域,分别用于存储 NVS 库专用分区和 PHY 初始化数据。 以下是 "Factory app, two OTA definitions" 选项的分区表信息摘要:: @@ -45,7 +45,7 @@ ota_1, app, ota_1, 0x210000, 1M, - 分区表中定义了三个应用程序分区,这三个分区的类型都被设置为 “app”,但具体 app 类型不同。其中,位于 0x10000 偏移地址处的为出厂应用程序 (factory),其余两个为 OTA 应用程序(ota_0,ota_1)。 -- 新增了一个名为 “otadata” 的数据分区,用于保存 OTA 升级时需要的数据。启动加载器会查询该分区的数据,以判断该从哪个 OTA 应用程序分区加载程序。如果 “otadata” 分区为空,则会执行出厂程序。 +- 新增了一个名为 “otadata” 的数据分区,用于保存 OTA 升级时需要的数据。引导加载程序会查询该分区的数据,以判断该从哪个 OTA 应用程序分区加载程序。如果 “otadata” 分区为空,则会执行出厂程序。 创建自定义分区表 ---------------- @@ -85,7 +85,7 @@ Type 字段可以指定为 app (0x00) 或者 data (0x01),也可以直接使用 static const esp_partition_type_t APP_PARTITION_TYPE_A = (esp_partition_type_t)0x40; -注意,启动加载器将忽略 ``app`` (0x00) 和 ``data`` (0x01) 以外的其他分区类型。 +注意,引导加载程序会忽略 ``app`` (0x00) 和 ``data`` (0x01) 以外的其他分区类型。 SubType 字段 ~~~~~~~~~~~~ @@ -97,13 +97,13 @@ SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp * 当 Type 定义为 ``app`` 时,SubType 字段可以指定为 ``factory`` (0x00)、 ``ota_0`` (0x10) … ``ota_15`` (0x1F) 或者 ``test`` (0x20)。 - - ``factory`` (0x00) 是默认的 app 分区。启动加载器将默认加载该应用程序。但如果存在类型为 data/ota 分区,则启动加载器将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。 + - ``factory`` (0x00) 是默认的 app 分区。引导加载程序默认加载该应用程序。但如果存在类型为 data/ota 的分区,则引导加载程序将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。 - OTA 升级永远都不会更新 factory 分区中的内容。 - 如果你希望在 OTA 项目中预留更多 flash,可以删除 factory 分区,转而使用 ota_0 分区。 - - ota_0 (0x10) … ota_15 (0x1F) 为 OTA 应用程序分区,启动加载器将根据 OTA 数据分区中的数据来决定加载哪个 OTA 应用程序分区中的程序。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(``ota_0`` 和 ``ota_1``)。更多详细信息,请参考 :doc:`OTA 文档 ` 。 - - ``test`` (0x20) 为预留的子类型,用于工厂测试流程。如果没有其他有效 app 分区,test 将作为备选启动分区使用。也可以配置启动加载器在每次启动时读取 GPIO,如果 GPIO 被拉低则启动该分区。详细信息请查阅 :ref:`bootloader_boot_from_test_firmware`。 + - ota_0 (0x10) … ota_15 (0x1F) 为 OTA 应用程序分区,引导加载程序将根据 OTA 数据分区中的数据来决定加载哪个 OTA 应用程序分区中的程序。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(``ota_0`` 和 ``ota_1``)。更多详细信息,请参考 :doc:`OTA 文档 ` 。 + - ``test`` (0x20) 为预留的子类型,用于工厂测试流程。如果没有其他有效 app 分区,test 将作为备选启动分区使用。也可以配置引导加载程序在每次启动时读取 GPIO,如果 GPIO 被拉低则启动该分区。详细信息请查阅 :ref:`bootloader_boot_from_test_firmware`。 * 当 Type 定义为 ``data`` 时,SubType 字段可以指定为 ``ota`` (0x00)、``phy`` (0x01)、``nvs`` (0x02)、``nvs_keys`` (0x04) 或者其他组件特定的子类型(请参考 :cpp:type:`子类型枚举 `). diff --git a/docs/zh_CN/api-guides/performance/ram-usage.rst b/docs/zh_CN/api-guides/performance/ram-usage.rst index 44839f698ee1..a79501851bfe 100644 --- a/docs/zh_CN/api-guides/performance/ram-usage.rst +++ b/docs/zh_CN/api-guides/performance/ram-usage.rst @@ -192,15 +192,16 @@ IRAM 优化 - 要禁用不需要的 flash 驱动程序,节省 IRAM 空间,请参阅 sdkconfig 菜单中的 ``Auto-detect Flash chips`` 选项。 :SOC_GPSPI_SUPPORTED: - 启用 :ref:`CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH`。只要未启用 :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` 选项,且没有从 ISR 中错误地调用堆函数,就可以在所有配置中安全启用此选项。 :esp32c2: - 启用 :ref:`CONFIG_BT_RELEASE_IRAM`。 蓝牙所使用的 data,bss 和 text 段已经被分配在连续的RAM区间。当调用 ``esp_bt_mem_release`` 时,这些段都会被添加到 Heap 中。 这将节省约 22 KB 的 RAM。但要再次使用蓝牙功能,需要重启程序。 + :SOC_DEBUG_HAVE_OCD_STUB_BINS: - 禁用 :ref:`CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS` 选项可以释放 8 KB 的 IRAM, 但由于运行时加载存根的额外开销,特别是在使用 flash 断点时,可能会影响调试的整体速度。 .. only:: esp32 将 SRAM1 用于 IRAM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SRAM1 内存区域通常用于 DRAM 存储,但可以设置 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` 选项,将其中一部分用作 IRAM 存储。引入该选项前,这个内存区域通常预留给 DRAM 数据使用(如 ``.bss`` ),随后由软件引导加载程序加入到堆中。引入该选项后,引导加载程序的 DRAM 大小会减少到更接近实际需要的值。 + SRAM1 内存区域通常用于 DRAM 存储,但可以设置 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` 选项,将其中一部分用作 IRAM 存储。引入该选项前,这个内存区域通常预留给 DRAM 数据使用(如 ``.bss``),随后由二级引导加载程序加入到堆中。引入该选项后,二级引导加载程序的 DRAM 大小会减少到更接近实际需要的值。 - 要使用以上选项,ESP-IDF 应能够将新的 SRAM1 区域识别为有效镜像段的加载地址。部分应用程序的代码置于新扩展的 IRAM 区域,如果软件引导加载程序在引入该选项前编译,将无法加载这类应用程序。这类情况通常在进行 OTA 更新时发生,此时仅会更新应用程序。 + 要使用以上选项,ESP-IDF 应能够将新的 SRAM1 区域识别为有效镜像段的加载地址。部分应用程序的代码置于新扩展的 IRAM 区域,如果二级引导加载程序在引入该选项前编译,将无法加载这类应用程序。这类情况通常在进行 OTA 更新时发生,此时仅会更新应用程序。 如果 IRAM 段放置在无效区域,在启动过程中将检测到以下问题,并导致启动失败: @@ -210,7 +211,7 @@ IRAM 优化 .. warning:: - 若与在引入以上配置选项前编译的软件引导加载程序一同使用,使用 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` 选项编译的应用程序很可能无法启动。若使用旧版本的引导加载程序,并进行 OTA 更新,请在提交任何更新前仔细测试。 + 若与在引入以上配置选项前编译的二级引导加载程序一同使用,使用 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` 选项编译的应用程序很可能无法启动。若使用旧版本的引导加载程序,并进行 OTA 更新,请在提交任何更新前仔细测试。 任何最终未用于静态 IRAM 的内存都将添加到堆内存中。 diff --git a/docs/zh_CN/api-guides/performance/size.rst b/docs/zh_CN/api-guides/performance/size.rst index 1a9545e7dcf4..3d52af653e57 100644 --- a/docs/zh_CN/api-guides/performance/size.rst +++ b/docs/zh_CN/api-guides/performance/size.rst @@ -194,6 +194,7 @@ MbedTLS 功能 - :ref:`CONFIG_MBEDTLS_HAVE_TIME` - :ref:`CONFIG_MBEDTLS_ECDSA_DETERMINISTIC` - :ref:`CONFIG_MBEDTLS_SHA512_C` +- :ref:`CONFIG_MBEDTLS_SHA3_C` - :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS` - :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS` - :ref:`CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION` @@ -260,7 +261,7 @@ MbedTLS 功能 本文档仅涉及 ESP-IDF 应用程序的二进制文件大小,而不涉及 ESP-IDF :ref:`second-stage-bootloader`。 -关于 ESP-IDF 引导加载程序二进制文件大小的讨论,参阅 :ref:`bootloader-size`。 +关于 ESP-IDF 引导加载程序二进制文件大小的讨论,请参阅 :ref:`bootloader-size`。 IRAM 二进制文件大小 ------------------------------------ diff --git a/docs/zh_CN/api-guides/performance/speed.rst b/docs/zh_CN/api-guides/performance/speed.rst index 25601b4dadf8..55f0a2da747f 100644 --- a/docs/zh_CN/api-guides/performance/speed.rst +++ b/docs/zh_CN/api-guides/performance/speed.rst @@ -301,9 +301,9 @@ ESP-IDF 支持动态 :doc:`/api-reference/system/intr_alloc` 和中断抢占。 使用标准 C 库函数,如 ``fread`` 和 ``fwrite``,相较于使用平台特定的不带缓冲系统调用,如 ``read`` 和 ``write``,可能会导致 I/O 性能下降。 -``fread`` 与 ``fwrite`` 函数是为可移植性而设计的,而非速度,其缓冲性质会引入一些额外的开销。关于如何使用这两个函数,请参考示例 :example:`storage/fatfsgen`。 +``fread`` 与 ``fwrite`` 函数是为可移植性而设计的,而非速度,其缓冲性质会引入一些额外的开销。关于如何使用这两个函数,请参考示例 :example:`storage/fatfs/getting_started`。 -与之相比,``read`` 与 ``write`` 函数是标准的 POSIX API,可直接通过 VFS 处理 FatFs,由 ESP-IDF 负责底层实现。关于如何使用这两个函数,请参考示例 :example:`storage/perf_benchmark`。 +与之相比,``read`` 与 ``write`` 函数是标准的 POSIX API,可直接通过 VFS 处理 FatFs,由 ESP-IDF 负责底层实现。关于如何使用这两个函数,请参考示例 :example:`storage/fatfs/fs_operations`。 下面提供了一些提示,更多信息请见 :doc:`/api-reference/storage/fatfs`。 diff --git a/docs/zh_CN/api-guides/startup.rst b/docs/zh_CN/api-guides/startup.rst index b51c2d2a4f43..2f7dcc060318 100644 --- a/docs/zh_CN/api-guides/startup.rst +++ b/docs/zh_CN/api-guides/startup.rst @@ -9,7 +9,7 @@ .. list:: - 1. :ref:`first-stage-bootloader` 被固化在了 {IDF_TARGET_NAME} 内部的 ROM 中,它会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载二级引导程序至 RAM (IRAM & DRAM) 中。 + 1. :ref:`first-stage-bootloader` 被固化在了 {IDF_TARGET_NAME} 内部的 ROM 中,它会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载二级引导加载程序至 RAM (IRAM & DRAM) 中。 2. :ref:`second-stage-bootloader` 从 flash 中加载分区表和主程序镜像至内存中,主程序中包含了 RAM 段和通过 flash 高速缓存映射的只读段。 @@ -21,8 +21,8 @@ .. _first-stage-bootloader: -一级引导程序 -~~~~~~~~~~~~ +一级 (ROM) 引导加载程序 +~~~~~~~~~~~~~~~~~~~~~~~ .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES @@ -48,45 +48,45 @@ .. only:: esp32 - 二级引导程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。如果正在使用 :doc:`/security/secure-boot-v1`,则 flash 的第一个 4 kB 扇区用于存储安全启动 IV 以及引导程序镜像的摘要,否则不使用该扇区。 + 二级引导加载程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。如果正在使用 :doc:`/security/secure-boot-v1`,则 flash 的第一个 4 kB 扇区用于存储安全启动 IV 以及引导加载程序镜像的摘要,否则不使用该扇区。 .. only:: esp32s2 - 二级引导程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。该地址前面的 flash 4 kB 扇区未使用。 + 二级引导加载程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。该地址前面的 flash 4 kB 扇区未使用。 .. only:: SOC_KEY_MANAGER_SUPPORTED - 二级引导程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。该地址前面的 flash 8 kB 扇区将为密钥管理器保留,用于与 flash 加密 (AES-XTS) 相关的操作。 + 二级引导加载程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。该地址前面的 flash 8 kB 扇区将为密钥管理器保留,用于与 flash 加密 (AES-XTS) 相关的操作。 .. only:: not (esp32 or esp32s2 or SOC_KEY_MANAGER_SUPPORTED) - 二级引导程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。 + 二级引导加载程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。 .. TODO: describe application binary image format, describe optional flash configuration commands. .. _second-stage-bootloader: -二级引导程序 -~~~~~~~~~~~~ +二级引导加载程序 +~~~~~~~~~~~~~~~~ -在 ESP-IDF 中,存放在 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处的二进制镜像就是二级引导程序。二级引导程序的源码可以在 ESP-IDF 的 :idf:`components/bootloader` 目录下找到。ESP-IDF 使用二级引导程序可以增加 flash 分区的灵活性(使用分区表),并且方便实现 flash 加密,安全引导和空中升级 (OTA) 等功能。 +在 ESP-IDF 中,存放在 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处的二进制镜像就是二级引导加载程序。二级引导加载程序的源码可以在 ESP-IDF 的 :idf:`components/bootloader` 目录下找到。ESP-IDF 使用二级引导加载程序可以增加 flash 分区的灵活性(使用分区表),并且方便实现 flash 加密,安全引导和空中升级 (OTA) 等功能。 -当一级引导程序校验并加载完二级引导程序后,它会从二进制镜像的头部找到二级引导程序的入口点,并跳转过去运行。 +当一级 (ROM) 引导加载程序校验并加载完二级引导加载程序后,它会从二进制镜像的头部找到二级引导加载程序的入口点,并跳转过去运行。 -二级引导程序默认从 flash 的 {IDF_TARGET_CONFIG_PARTITION_TABLE_OFFSET} 偏移地址处(:ref:`可配置的值 `)读取分区表。请参考 :doc:`分区表 ` 获取详细信息。引导程序会寻找工厂分区和 OTA 应用程序分区。如果在分区表中找到了 OTA 应用程序分区,引导程序将查询 ``otadata`` 分区以确定应引导哪个分区。更多信息请参考 :doc:`/api-reference/system/ota`。 +二级引导加载程序默认从 flash 的 {IDF_TARGET_CONFIG_PARTITION_TABLE_OFFSET} 偏移地址处(:ref:`可配置的值 `)读取分区表。请参考 :doc:`分区表 ` 获取详细信息。引导加载程序会寻找工厂分区和 OTA 应用程序分区。如果在分区表中找到了 OTA 应用程序分区,引导加载程序将查询 ``otadata`` 分区以确定应引导哪个分区。更多信息请参考 :doc:`/api-reference/system/ota`。 -关于 ESP-IDF 引导程序可用的配置选项,请参考 :doc:`bootloader`。 +关于 ESP-IDF 引导加载程序可用的配置选项,请参考 :doc:`bootloader`。 -对于选定的分区,二级引导程序将从 flash 逐段读取二进制镜像: +对于选定的分区,二级引导加载程序将从 flash 逐段读取二进制镜像: - 对于在内部 :ref:`iram` 或 :ref:`dram` 中具有加载地址的段,将把数据从 flash 复制到它们的加载地址处。 - 对于一些加载地址位于 :ref:`drom` 或 :ref:`irom` 区域的段,通过配置 flash MMU,可为从 flash 到加载地址提供正确的映射。 .. only:: esp32 - 请注意,二级引导程序同时为 PRO CPU 和 APP CPU 配置 flash MMU,但仅使能 PRO CPU 的 flash MMU。原因是二级引导程序代码已加载到 APP CPU 的高速缓存使用的内存区域中。因此使能 APP CPU 高速缓存的任务就交给了应用程序。 + 请注意,二级引导加载程序同时为 PRO CPU 和 APP CPU 配置 flash MMU,但仅使能 PRO CPU 的 flash MMU。原因是二级引导加载程序代码已加载到 APP CPU 的高速缓存使用的内存区域中。因此使能 APP CPU 高速缓存的任务就交给了应用程序。 -一旦处理完所有段(即加载了代码并设置了 flash MMU),二级引导程序将验证应用程序的完整性,并从二进制镜像文件的头部寻找入口地址,然后跳转到该地址处运行。 +一旦处理完所有段(即加载了代码并设置了 flash MMU),二级引导加载程序将验证应用程序的完整性,并从二进制镜像文件的头部寻找入口地址,然后跳转到该地址处运行。 .. _application-startup: @@ -108,7 +108,7 @@ ESP-IDF 应用程序的入口是 :idf_file:`components/esp_system/port/cpu_start.c` 文件中的 ``call_start_cpu0`` 函数。这个函数由二级引导加载程序执行,并且从不返回。 -该端口层的初始化功能会初始化基本的 C 运行环境 ("CRT"),并对 SoC 的内部硬件进行了初始配置。 +该端口层的初始化功能会初始化基本的 C 运行环境 ("CRT"),并对 SoC 的内部硬件进行了初始配置。 .. list:: @@ -119,7 +119,7 @@ ESP-IDF 应用程序的入口是 :idf_file:`components/esp_system/port/cpu_start :SOC_SPIRAM_SUPPORTED: - 如果配置了 PSRAM,则使能 PSRAM。 - 将 CPU 时钟设置为项目配置的频率。 :SOC_MEMPROT_SUPPORTED: - 如果配置了内存保护,则初始化内存保护。 - :esp32: - 根据应用程序头部设置重新配置主 SPI flash,这是为了与 ESP-IDF V4.0 之前的引导程序版本兼容,请参考 :ref:`bootloader-compatibility`。 + :esp32: - 根据应用程序头部设置重新配置主 SPI flash,这是为了与 ESP-IDF V4.0 之前的引导加载程序版本兼容,请参考 :ref:`bootloader-compatibility`。 :SOC_HP_CPU_HAS_MULTIPLE_CORES: - 如果应用程序被配置为在多个内核上运行,则启动另一个内核并等待其初始化(在类似的“端口层”初始化函数 ``call_start_cpu1`` 内)。 .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES diff --git a/docs/zh_CN/api-guides/tools/idf-monitor.rst b/docs/zh_CN/api-guides/tools/idf-monitor.rst index 7e38c5a187c1..8c186f6539f6 100644 --- a/docs/zh_CN/api-guides/tools/idf-monitor.rst +++ b/docs/zh_CN/api-guides/tools/idf-monitor.rst @@ -252,63 +252,7 @@ IDF 监视器的默认复位序列可在大多数环境中使用。使用默认 对于高级用户或特定用例,IDF 监视器支持使用 :ref:`configuration-file` 配置自定义复位序列。这在默认序列可能不足的极端情况下特别有用。 -复位序列可通过以下格式的字符串定义: - -- 各个命令由 ``|`` 分隔(例如 ``R0|D1|W0.5``)。 -- 命令(例如 ``R0``)由代码(``R``)和参数(``0``)定义。 - -.. list-table:: - :header-rows: 1 - :widths: 15 50 35 - :align: center - - * - 代码 - - 操作 - - 参数 - * - D - - 设置 DTR 控制线 - - ``1``/``0`` - * - R - - 设置 RTS 控制线 - - ``1``/``0`` - * - U - - 同时设置 DTR 和 RTS 控制线(仅适用于类 Unix 系统) - - ``0,0``/``0,1``/``1,0``/``1,1`` - * - W - - 等待 ``N`` 秒(其中 ``N`` 为浮点数) - - N - -示例: - -.. code-block:: ini - - [esp-idf-monitor] - custom_reset_sequence = U0,1|W0.1|D1|R0|W0.5|D0 - -有关更多详细信息,请参阅 Esptool 文档中 `custom reset sequence`_ 章节。请注意,IDF 监视器只使用了 Esptool 配置中的 ``custom_reset_sequence`` 值,其他值会被 IDF 监视器忽略。 - -IDF 监视器和 Esptool 之间共享配置 ----------------------------------------------- - -自定义复位序列的配置可以在 IDF 监视器和 Esptool 之间的共享配置文件中指定。在这种情况下,为了使两个工具都能识别配置文件,其名称应为 ``setup.cfg`` 或 ``tox.ini``。 - -共享配置文件的示例: - -.. code-block:: ini - - [esp-idf-monitor] - menu_key = T - skip_menu_key = True - - [esptool] - custom_reset_sequence = U0,1|W0.1|D1|R0|W0.5|D0 - -.. note:: - - 当在 ``[esp-idf-monitor]`` 部分和 ``[esptool]`` 部分都使用 ``custom_reset_sequence`` 参数时,IDF 监视器会优先使用 ``[esp-idf-monitor]`` 部分的配置。``[esptool]`` 部分中任何与之冲突的配置都将被忽略。 - - 当配置分散在多个文件中时,此优先规则也适用。全局 esp-idf-monitor 配置将优先于本地 esptool 配置。 - +如需使用自定义复位序列,请参阅 `IDF 监视器文档`_ 获取更多详细信息。 配置 GDBStub 以启用 GDB ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -397,118 +341,16 @@ GDBStub 支持在运行时进行调试。GDBStub 在目标上运行,并通过 配置文件 ======== -``esp-idf-monitor`` 使用 `C0 控制字符`_ 与控制台进行交互。配置文件中的字符会被转换为对应的 C0 控制代码。可用字符包括英文字母 (A-Z) 和特殊符号:``[``、``]``、``\``、``^``、和 ``_``. - -.. warning:: - - 注意,一些字符可能无法在所有平台通用,或被保留作为其他用途的快捷键。请谨慎使用此功能。 - - -文件位置 -~~~~~~~~~~ - -配置文件的默认名称为 ``esp-idf-monitor.cfg``。首先,在 ``esp-idf-monitor`` 路径中检测配置文件并运行。 - -如果此目录中没有检测到配置文件,则检查当前用户操作系统的配置目录: - - - Linux: ``/home//.config/esp-idf-monitor/`` - - MacOS ``/Users//.config/esp-idf-monitor/`` - - Windows: ``c:\Users\\AppData\Local\esp-idf-monitor\`` +``esp-idf-monitor`` 支持通过配置文件更改其默认行为。该配置文件可用于设置自定义快捷键,或设置自定义复位序列以重置芯片进入引导加载程序。 -如仍未检测到配置文件,会最后再检查主目录: - - - Linux: ``/home//`` - - MacOS ``/Users//`` - - Windows: ``c:\Users\\`` - -在 Windows 中,可以使用 ``HOME`` 或 ``USERPROFILE`` 环境变量设置主目录,因此,Windows 配置目录的位置也取决于这些变量。 - -还可以使用 ``ESP_IDF_MONITOR_CFGFILE`` 环境变量为配置文件指定一个不同的位置,例如 ``ESP_IDF_MONITOR_CFGFILE = ~/custom_config.cfg``。这一设置的检测优先级高于上述所有位置检测的优先级。 - -如果没有使用其他配置文件,``esp-idf-monitor`` 会从其他常用的配置文件中读取设置。如果存在 ``setup.cfg`` 或 ``tox.ini`` 文件,``esp-idf-monitor`` 会自动从这些文件中读取设置。 - -配置选项 -~~~~~~~~~~ - -下表列出了可用的配置选项: - -.. list-table:: - :header-rows: 1 - :widths: 30 50 20 - :align: center - - * - 选项名称 - - 描述 - - 默认值 - * - menu_key - - 访问主菜单 - - ``T`` - * - exit_key - - 退出监视器 - - ``]`` - * - chip_reset_key - - 初始化芯片重置 - - ``R`` - * - recompile_upload_key - - 重新编译并上传 - - ``F`` - * - recompile_upload_app_key - - 仅重新编译并上传应用程序 - - ``A`` - * - toggle_output_key - - 切换输出显示 - - ``Y`` - * - toggle_log_key - - 切换日志功能 - - ``L`` - * - toggle_timestamp_key - - 切换时间戳显示 - - ``I`` - * - chip_reset_bootloader_key - - 将芯片重置为引导加载模式 - - ``P`` - * - exit_menu_key - - 从菜单中退出监视器 - - ``X`` - * - skip_menu_key - - 设置使用菜单命令时无需按下主菜单键 - - ``False`` - * - custom_reset_sequence - - 复位目标到引导加载程序的自定义复位序列 - - 无默认值 - - -语法 -~~~~ - -配置文件为 .ini 文件格式,必须以 ``[esp-idf-monitor]`` 标头引入才能被识别为有效文件。以下语法以“配置名称 = 配置值”形式列出。以 ``#`` 或 ``;`` 开头的行是注释,将被忽略。 - -.. code-block:: ini - - # esp-idf-monitor.cfg file to configure internal settings of esp-idf-monitor - [esp-idf-monitor] - menu_key = T - exit_key = ] - chip_reset_key = R - recompile_upload_key = F - recompile_upload_app_key = A - toggle_output_key = Y - toggle_log_key = L - toggle_timestamp_key = I - chip_reset_bootloader_key = P - exit_menu_key = X - skip_menu_key = False +有关配置文件的更多详细信息,请参阅 `IDF 监视器文档`_。 IDF 监视器已知问题 ================================= -如果在使用 IDF 监视器过程中遇到任何问题,请查看我们的 `GitHub 仓库 `_ 以获取已知问题列表及其当前状态。如果遇到的问题没有相关记录,请创建一个新的问题报告。 +如果在使用 IDF 监视器过程中遇到任何问题,请查看 `GitHub 仓库 `_ 以获取已知问题列表及其当前状态。如果遇到的问题没有相关记录,请创建一个新的问题报告。 -.. _addr2line: https://sourceware.org/binutils/docs/binutils/addr2line.html .. _esp-idf-monitor: https://github.com/espressif/esp-idf-monitor +.. _IDF 监视器文档: https://github.com/espressif/esp-idf-monitor/blob/v1.5.0/README.md#documentation .. _gdb: https://sourceware.org/gdb/download/onlinedocs/ -.. _pySerial: https://github.com/pyserial/pyserial -.. _miniterm: https://pyserial.readthedocs.org/en/latest/tools.html#module-serial.tools.miniterm -.. _C0 控制字符: https://zh.wikipedia.org/wiki/C0%E4%B8%8EC1%E6%8E%A7%E5%88%B6%E5%AD%97%E7%AC%A6#C0_(ASCII%E5%8F%8A%E5%85%B6%E6%B4%BE%E7%94%9F) -.. _custom reset sequence: https://docs.espressif.com/projects/esptool/en/latest/{IDF_TARGET_PATH_NAME}/esptool/configuration-file.html#custom-reset-sequence diff --git a/docs/zh_CN/api-guides/tools/idf-py.rst b/docs/zh_CN/api-guides/tools/idf-py.rst index b281e3531f18..deab76320590 100644 --- a/docs/zh_CN/api-guides/tools/idf-py.rst +++ b/docs/zh_CN/api-guides/tools/idf-py.rst @@ -250,7 +250,7 @@ uf2 二进制文件也可以通过 :ref:`idf.py uf2 ` 生 在 ESP 芯片上运行 `ESP USB Bridge `_ 项目将创建一个 USB 大容量存储设备,用户可以将生成的 UF2 文件复制到该 USB 设备中,桥接 MCU 将使用该文件来烧录目标 MCU。这一操作十分简单,只需将文件复制(或“拖放”)到文件资源管理器访问的公开磁盘中即可。 -如需仅为应用程序生成 UF2 二进制文件,即不包含加载引导程序和分区表,请使用 ``uf2-app`` 命令。 +如需仅为应用程序生成 UF2 二进制文件,即不包含引导加载程序和分区表,请使用 ``uf2-app`` 命令。 ``idf.py uf2`` 命令在功能上与 :ref:`上述 ` ``idf.py merge-bin -f uf2`` 命令等效。而将二进制文件合并为除 uf2 以外的各种格式时,``idf.py merge-bin`` 命令更具灵活性和可选性。 diff --git a/docs/zh_CN/api-guides/tools/index.rst b/docs/zh_CN/api-guides/tools/index.rst index 44916de2606e..e6b4d2158fcc 100644 --- a/docs/zh_CN/api-guides/tools/index.rst +++ b/docs/zh_CN/api-guides/tools/index.rst @@ -12,4 +12,4 @@ idf-clang-tidy idf-tools idf-size - :esp32 or esp32c3: qemu + :TARGET_SUPPORT_QEMU: qemu diff --git a/docs/zh_CN/api-guides/tools/qemu.rst b/docs/zh_CN/api-guides/tools/qemu.rst index 14f962dbcfef..3d4465f70055 100644 --- a/docs/zh_CN/api-guides/tools/qemu.rst +++ b/docs/zh_CN/api-guides/tools/qemu.rst @@ -1,6 +1,8 @@ QEMU 模拟器 =========== +{IDF_TARGET_CRYPT_CNT:default="SPI_BOOT_CRYPT_CNT",esp32="FLASH_CRYPT_CNT"} + :link_to_translation:`en:[English]` 乐鑫维护了一个 QEMU 模拟器的 `分支 `_,支持 {IDF_TARGET_NAME}。这个分支实现了对 {IDF_TARGET_NAME} 的 CPU、内存和多个外设的模拟。更多有关 {IDF_TARGET_NAME} 的 QEMU 的信息,请参阅 `QEMU README 文档 `_。 @@ -119,13 +121,52 @@ QEMU 支持 eFuse 的仿真,可用来测试安全启动和 flash 加密等与 使用 :doc:`idf.py` eFuse 相关命令来编程 eFuse。当这些命令与 ``qemu`` 命令一起运行时,eFuse 会在 QEMU 中编程,并且 ``qemu_efuse.bin`` 文件会更新。例如, +.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES + + .. code-block:: console + + idf.py qemu efuse-burn {IDF_TARGET_CRYPT_CNT} 1 + idf.py qemu efuse-burn-key flash_encryption my_flash_encryption_key.bin + +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES + + .. code-block:: console + + idf.py qemu efuse-burn {IDF_TARGET_CRYPT_CNT} 1 + idf.py qemu efuse-burn-key BLOCK my_flash_encryption_key.bin KEYPURPOSE + + 有关 ``BLOCK`` 和 ``KEYPURPOSE`` 的详细信息,请参阅 :doc:`../../security/flash-encryption` 指南。 + +如需导出 eFuse 概要,使用以下命令: + .. code-block:: console - idf.py qemu efuse-burn FLASH_CRYPT_CNT 1 + idf.py qemu efuse-summary 默认情况下,eFuse 的值从编译文件夹里的 ``qemu_efuse.bin`` 文件中读取和写入。也可以使用 ``--efuse-file`` 选项指定不同的文件。例如, .. code-block:: console - idf.py qemu --efuse-file my_efuse.bin efuse-burn FLASH_CRYPT_CNT 1 + idf.py qemu --efuse-file my_efuse.bin efuse-burn {IDF_TARGET_CRYPT_CNT} 1 idf.py qemu --efuse-file my_efuse.bin monitor + +指定 flash 映像 +~~~~~~~~~~~~~~~ + +默认情况下,QEMU 使用构建目录中的 ``qemu_flash.bin`` 文件作为 flash 映像。该文件是根据构建目录中 ``flash_args`` 文件提供的项目信息生成的。如果想使用其他 flash 映像,可通过 ``--flash-file`` 选项进行指定。例如: + +.. code-block:: console + + idf.py qemu --flash-file my_flash.bin monitor + + +所提供的 flash 映像必须满足以下要求,以确保正确模拟: + +- flash 文件大小与项目配置中 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE` 的指定值相同。 +- flash 文件包括所有必需的二进制文件,如引导加载程序、分区表和应用程序固件,这些文件位于各自的内存偏移量处。 + + +模拟安全启动 +~~~~~~~~~~~~~ + +QEMU 支持模拟安全启动 v2 机制。请保持 :ref:`CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT` 处于启用状态,将签名的引导加载程序镜像嵌入到 QEMU 的镜像文件中。 diff --git a/docs/zh_CN/api-guides/wifi-expansion.rst b/docs/zh_CN/api-guides/wifi-expansion.rst new file mode 100644 index 000000000000..b4430caa4f57 --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-expansion.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-guides/wifi-expansion.rst diff --git a/docs/zh_CN/api-guides/wifi.rst b/docs/zh_CN/api-guides/wifi.rst index e64e4e65ec4b..93cce80a0fda 100644 --- a/docs/zh_CN/api-guides/wifi.rst +++ b/docs/zh_CN/api-guides/wifi.rst @@ -839,7 +839,7 @@ Wi-Fi 驱动程序内部扫描阶段 +++++++++++++++++++++ - s3.1:发送关联请求并使能关联计时器。 - - s3.2:如果在关联计时器超时之前未接收到关联响应,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,且原因代码为 ``WIFI_REASON_ASSOC_EXPIRE``。请参阅 `Wi-Fi 原因代码`_。 + - s3.2:如果在关联计时器超时之前未接收到关联响应,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,且原因代码为 ``WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY``。请参阅 `Wi-Fi 原因代码`_。 - s3.3:接收到关联响应,且关联计时器终止。 - s3.4:AP 在响应中拒绝关联且产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,原因代码将在关联响应中指定。请参阅 `Wi-Fi 原因代码`_。 @@ -896,7 +896,7 @@ Wi-Fi 原因代码 对于 ESP station,出现以下情况时报告该代码: - 从 AP 接收到该代码。 - * - ASSOC_EXPIRE + * - DISASSOC_DUE_TO_INACTIVITY - 4 - 4 - 因为 AP 不活跃,association 取消。 @@ -922,7 +922,7 @@ Wi-Fi 原因代码 对于 ESP AP,出现以下情况时将报告该代码: - 与 AP 相关联的 station 数量已到达 AP 可支持的最大值。 - * - NOT_AUTHED + * - CLASS2_FRAME_FROM_NONAUTH_STA - 6 - 6 - 从一个未认证 station 接收到 class-2 frame。 @@ -934,7 +934,7 @@ Wi-Fi 原因代码 对于 ESP AP,出现以下情况时将报告该代码: - AP 从一个未认证 station 接收到数据包。 - * - NOT_ASSOCED + * - CLASS3_FRAME_FROM_NONASSOC_STA - 7 - 7 - 从一个未关联 station 接收到的 class-3 frame。 @@ -1199,7 +1199,7 @@ Wi-Fi 原因代码 * - ASSOC_FAIL - 203 - 保留 - - 乐鑫特有的 Wi-Fi 原因代码: association 失败,但并非由 ASSOC_EXPIRE 或 ASSOC_TOOMANY 引发。 + - 乐鑫特有的 Wi-Fi 原因代码: association 失败,但并非由 DISASSOC_DUE_TO_INACTIVITY 或 ASSOC_TOOMANY 引发。 * - HANDSHAKE_TIMEOUT - 204 - 保留 diff --git a/docs/zh_CN/api-reference/network/esp_eth.rst b/docs/zh_CN/api-reference/network/esp_eth.rst index d4acdfb6d133..96ffa63b23cb 100644 --- a/docs/zh_CN/api-reference/network/esp_eth.rst +++ b/docs/zh_CN/api-reference/network/esp_eth.rst @@ -269,6 +269,10 @@ PHY 的相关配置可以在 :cpp:class:`eth_phy_config_t` 中找到,具体包 * :cpp:member:`eth_phy_config_t::reset_gpio_num`:如果开发板同时将 PHY 复位管脚连接至了任意 GPIO 管脚,请使用该字段进行配置。否则,配置为 ``-1``。 + * :cpp:member:`eth_phy_config_t::hw_reset_assert_time_us`:PHY 复位引脚被置为有效状态的时间(以微秒为单位)。将该值配置为 ``0``,即可使用芯片默认的复位时长。 + + * :cpp:member:`eth_phy_config_t::post_hw_reset_delay_ms`:PHY 硬件复位完成后的等待时间(以毫秒为单位)。将该值配置为 ``0``,即可使用芯片默认的等待时长,配置为 ``-1``,表示执行 PHY 硬件复位后不等待。 + ESP-IDF 在宏 :c:macro:`ETH_MAC_DEFAULT_CONFIG` 和 :c:macro:`ETH_PHY_DEFAULT_CONFIG` 中为 MAC 和 PHY 提供了默认配置。 @@ -288,19 +292,23 @@ ESP-IDF 在宏 :c:macro:`ETH_MAC_DEFAULT_CONFIG` 和 :c:macro:`ETH_PHY_DEFAULT_C eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // 应用默认的通用 MAC 配置 eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); // 应用默认的供应商特定 MAC 配置 - esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; // 更改用于 MDC 信号的 GPIO - esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; // 更改用于 MDIO 信号的 GPIO + esp32_emac_config.smi_gpio.mdc_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; // 更改用于 MDC 信号的 GPIO + esp32_emac_config.smi_gpio.mdio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; // 更改用于 MDIO 信号的 GPIO esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // 创建 MAC 实例 eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // 应用默认的 PHY 配置 phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; // 根据开发板设计更改 PHY 地址 phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO; // 更改用于 PHY 复位的 GPIO - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // 创建 PHY 实例 - // ESP-IDF 为数种以太网 PHY 芯片驱动提供官方支持 + esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config); // 创建通用 PHY 实例 + // ESP-IDF 为数种特定以太网 PHY 芯片驱动提供官方支持 + // esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config); // esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); // esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config); + .. note:: + 使用 :cpp:func:`esp_eth_phy_new_generic` 创建新的 PHY 实例时,可以使用任何符合 IEEE 802.3 标准的以太网 PHY 芯片。然而,尽管 PHY 芯片符合 IEEE 802.3 标准,能提供基本功能,但某些特定的功能可能无法完全实现。例如,某些以太网 PHY 芯片可能需要配置特定的速度模式才能启用环回功能。遇到这种情况,需要配置 PHY 驱动程序以满足特定芯片需求,请使用 ESP-IDF 官方支持的 PHY 芯片驱动程序,或参阅 :ref:`Custom PHY Driver ` 小节以创建新的自定义驱动程序。 + 可选的运行时 MAC 时钟配置 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -557,10 +565,12 @@ ESP-IDF 在宏 :c:macro:`ETH_DEFAULT_CONFIG` 中为安装驱动程序提供了 进阶操作 --------------- +.. _custom-phy-driver: + 自定义 PHY 驱动程序 ^^^^^^^^^^^^^^^^^^^^^^^^^ -市面上有多家 PHY 芯片制造商提供各种类型的芯片。ESP-IDF 现已支持数种 PHY 芯片,但是由于价格、功能、库存等原因,有时用户还是无法找到一款能满足其实际需求的芯片。 +市面上有多家 PHY 芯片制造商提供各种类型的芯片。ESP-IDF 现已支持 ``通用 PHY`` 和数种特定的 PHY 芯片,但是由于价格、功能、库存等原因,有时用户还是无法找到一款能满足其实际需求的芯片。 好在 IEEE 802.3 在其 22.2.4 管理功能部分对 EMAC 和 PHY 之间的管理接口进行了标准化。该部分定义了所谓的 ”MII 管理接口”规范,用于控制 PHY 和收集 PHY 的状态,还定义了一组管理寄存器来控制芯片行为、链接属性、自动协商配置等。在 ESP-IDF 中,这项基本的管理功能是由 :component_file:`esp_eth/src/phy/esp_eth_phy_802_3.c` 实现的,这也大大降低了创建新的自定义 PHY 芯片驱动的难度。 diff --git a/docs/zh_CN/api-reference/network/esp_netif.rst b/docs/zh_CN/api-reference/network/esp_netif.rst index 00c0d6fe750f..596ecdf4f1e6 100644 --- a/docs/zh_CN/api-reference/network/esp_netif.rst +++ b/docs/zh_CN/api-reference/network/esp_netif.rst @@ -82,20 +82,20 @@ ESP-NETIF 组件使用了系统事件,典型的网络启动代码如下所示 初始化网络接口可能有些复杂,ESP-NETIF 提供了一些创建常见接口(例如 Wi-Fi 和以太网)的快捷方式。 -以下示例展示了默认接口的初始化过程: +请参考以下示例来了解如何初始化默认接口: -.. only:: SOC_WIFI_SUPPORTED +.. list:: - - Wi-Fi 站点::example_file:`wifi/getting_started/station/main/station_example_main.c` + :SOC_WIFI_SUPPORTED: - :example:`wifi/getting_started/station` 演示了如何使用 station 功能将 {IDF_TARGET_NAME} 连接到 AP。 -- 以太网::example_file:`ethernet/basic/main/ethernet_example_main.c` + :CONFIG_ESP_WIFI_SOFTAP_SUPPORT: - :example:`wifi/getting_started/softAP` 演示了如何使用 SoftAP 功能将 {IDF_TARGET_NAME} 配置为 AP。 -- L2 TAP: :example_file:`protocols/l2tap/main/l2tap_main.c` + - :example:`ethernet/basic` 演示了如何使用以太网驱动程序,将其添加到 `esp_netif`,并获取一个可 ping 的 IP 地址。 -.. only:: CONFIG_ESP_WIFI_SOFTAP_SUPPORT + - :example:`protocols/l2tap` 演示了如何使用 ESP-NETIF L2 TAP 接口访问数据链路层,以接收和传输帧,实现非 IP 协议,并使用特定的 EthTypes 回显以太网帧。 - - Wi-Fi 接入点::example_file:`wifi/getting_started/softAP/main/softap_example_main.c` + - :example:`protocols/static_ip` 演示了如何将 Wi-Fi 配置为 station,包括设置静态 IP、子网掩码、网关和 DNS 服务器。 .. only:: SOC_WIFI_SUPPORTED diff --git a/docs/zh_CN/api-reference/network/esp_smartconfig.rst b/docs/zh_CN/api-reference/network/esp_smartconfig.rst index 70f77b0d698a..56185702cba2 100644 --- a/docs/zh_CN/api-reference/network/esp_smartconfig.rst +++ b/docs/zh_CN/api-reference/network/esp_smartconfig.rst @@ -3,10 +3,17 @@ SmartConfig :link_to_translation:`en:[English]` +概述 +----- + SmartConfig\ :sup:`TM` 是由 TI 开发的配网技术,用于将新的 Wi-Fi 设备连接到 Wi-Fi 网络。它使用移动应用程序将无线网凭据从智能手机或平板电脑端广播给未配网的 Wi-Fi 设备。 这项技术的优势在于,设备无需直接获知 AP 的 SSID 或密码,而是通过智能手机获取。这对于没有用户界面的无头设备和系统而言十分重要。 +目前, {IDF_TARGET_NAME} 支持三种类型的 SmartConfig 配网: Airkiss、ESPTouch 和 ESPTouch v2。ESPTouch v2 自 SmartConfig v3.0 (SmartConfig 的版本可以从 :cpp:func:`esp_smartconfig_get_version()` 获取)起开始支持,ESPTouch v2 和 vESPTouch 采用完全不同的配网算法,因此配网速度更快。此外,ESPTouch v2 还增加了 AES 加密功能和自定义数据字段。 + +从 SmartConfig v3.0.2 开始,ESPTouch v2 的 AES 加密支持随机 IV。在应用程序端,当随机 IV 的选项关闭的时候,默认的 IV 为 0,与旧版本保持一致,当随机 IV 的选项打开的时候,IV 为随机值。需要注意的是,当启用 AES 加密且 IV 为随机值时,配网时间会延长,因为需要将 IV 传输到配网设备。在配网设备端,设备会根据配网包中的 flag 来识别 AES 的随机 IV 是否开启。 + 如需通过其他方式为 {IDF_TARGET_NAME} 设备配网,请参阅 :doc:`../provisioning/index`。 diff --git a/docs/zh_CN/api-reference/network/esp_wifi.rst b/docs/zh_CN/api-reference/network/esp_wifi.rst index f54c64241124..f2c0509d1210 100644 --- a/docs/zh_CN/api-reference/network/esp_wifi.rst +++ b/docs/zh_CN/api-reference/network/esp_wifi.rst @@ -28,6 +28,7 @@ API 参考 .. include-build-file:: inc/esp_wifi.inc .. include-build-file:: inc/esp_wifi_types.inc +.. include-build-file:: inc/esp_wifi_types_generic.inc .. include-build-file:: inc/esp_eap_client.inc .. include-build-file:: inc/esp_wps.inc .. include-build-file:: inc/esp_rrm.inc diff --git a/docs/zh_CN/api-reference/peripherals/adc_continuous.rst b/docs/zh_CN/api-reference/peripherals/adc_continuous.rst index e1f33caf5564..5ebd83dabad4 100644 --- a/docs/zh_CN/api-reference/peripherals/adc_continuous.rst +++ b/docs/zh_CN/api-reference/peripherals/adc_continuous.rst @@ -290,39 +290,19 @@ ADC 连续转换模式驱动使用内部缓冲池保存转换结果,缓冲池 硬件限制 ^^^^^^^^^^^^^^^^^^^^ -- 一个 ADC 单元一次只能运行一种操作模式,即连续模式或单次模式。:cpp:func:`adc_continuous_start` 提供了保护措施。 - -- 随机数生成器 (RNG) 以 ADC 为输入源。使用 ADC 连续转换模式驱动从 RNG 生成随机数时,随机性会减弱。 - -.. only:: esp32 or esp32s2 - - - Wi-Fi 也使用 ADC2,:cpp:func:`adc_continuous_start` 提供了 Wi-Fi 驱动和 ADC 连续转换模式驱动之间的保护。 - -.. only:: esp32 - - - ADC 连续转换模式驱动使用 I2S0 外设作为硬件 DMA FIFO。因此,如果 I2S0 已在使用中,:cpp:func:`adc_continuous_new_handle` 将返回 :c:macro:`ESP_ERR_NOT_FOUND`。 - - - ESP32 DevKitC:由于存在外部自动烧录电路,GPIO 0 不能用于 ADC 连续转换模式。 - - - ESP-WROVER-KIT:由于部分 GPIO 管脚可能已经用于其他目的,GPIO 0、2、4 和 15 不能用于 ADC 连续转换模式。 - -.. only:: esp32s2 - - - ADC 连续转换模式驱动使用 SPI3 外设作为硬件 DMA FIFO。因此,如果 SPI3 已在使用中,:cpp:func:`adc_continuous_new_handle` 将返回 :c:macro:`ESP_ERR_NOT_FOUND`。 - -.. only:: esp32c3 - - - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 `__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。 - -.. only:: esp32s3 - - - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-S3 系列芯片勘误表 `__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。 - - .. _adc-continuous-power-management: - -.. only:: not esp32s3 - - .. _adc-continuous-power-management: +.. list:: + + - 一个 ADC 单元一次只能运行一种操作模式,即连续模式或单次模式。:cpp:func:`adc_continuous_start` 提供了保护措施。 + - 随机数生成器 (RNG) 以 ADC 为输入源。使用 ADC 连续转换模式驱动从 RNG 生成随机数时,随机性会减弱。 + :esp32 or esp32s2: - Wi-Fi 也使用 ADC2,:cpp:func:`adc_continuous_start` 提供了 Wi-Fi 驱动和 ADC 连续转换模式驱动之间的保护。 + :esp32: - ADC 连续转换模式驱动使用 I2S0 外设作为硬件 DMA FIFO。因此,如果 I2S0 已在使用中,:cpp:func:`adc_continuous_new_handle` 将返回 :c:macro:`ESP_ERR_NOT_FOUND`。 + :esp32: - ESP32 DevKitC:由于存在外部自动烧录电路,GPIO 0 不能用于 ADC 连续转换模式。 + :esp32: - ESP-WROVER-KIT:由于部分 GPIO 管脚可能已经用于其他目的,GPIO 0、2、4 和 15 不能用于 ADC 连续转换模式。 + :esp32s2: - ADC 连续转换模式驱动使用 SPI3 外设作为硬件 DMA FIFO。因此,如果 SPI3 已在使用中,:cpp:func:`adc_continuous_new_handle` 将返回 :c:macro:`ESP_ERR_NOT_FOUND`。 + :esp32c3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 `__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。 + :esp32s3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-S3 系列芯片勘误表 `__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。 + +.. _adc-continuous-power-management: 电源管理 ^^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-reference/peripherals/adc_oneshot.rst b/docs/zh_CN/api-reference/peripherals/adc_oneshot.rst index 0f7a2bfbb030..8365bb49e99c 100644 --- a/docs/zh_CN/api-reference/peripherals/adc_oneshot.rst +++ b/docs/zh_CN/api-reference/peripherals/adc_oneshot.rst @@ -3,20 +3,17 @@ :link_to_translation:`en:[English]` -{IDF_TARGET_ADC_NUM:default="两", esp32c2="一", esp32c6="一", esp32h2="一", esp32c5="一"} - 简介 ---- 模数转换器集成于芯片,支持测量特定模拟 IO 管脚的模拟信号。 -{IDF_TARGET_NAME} 有 {IDF_TARGET_ADC_NUM} 个 ADC 单元,可以在以下场景使用: - -- 生成 ADC 单次转换结果 +{IDF_TARGET_NAME} 有 {SOC_ADC_PERIPH_NUM} 个 ADC 单元,可以在以下场景使用: -.. only:: SOC_ADC_DMA_SUPPORTED +.. list:: - - 生成连续 ADC 转换结果 + - 生成 ADC 单次转换结果 + :SOC_ADC_DMA_SUPPORTED: - 生成连续 ADC 转换结果 本指南介绍了 ADC 单次转换模式。 @@ -164,31 +161,16 @@ ADC 单次转换模式驱动基于 {IDF_TARGET_NAME} SAR ADC 模块实现,不 硬件限制 ^^^^^^^^^^^^^^^^^^^^ -- 随机数生成器 (RNG) 以 ADC 为输入源。使用 ADC 单次转换模式驱动从 RNG 生成随机数时,随机性会减弱。 - -.. only:: SOC_ADC_DMA_SUPPORTED - - - 一个 ADC 单元每次只能在一种操作模式下运行,可以是连续模式或单次模式。:cpp:func:`adc_oneshot_start` 提供了保护措施。 - -.. only:: esp32 or esp32s2 or esp32s3 - - - Wi-Fi 也使用 ADC2,:cpp:func:`adc_oneshot_read` 提供了 Wi-Fi 驱动与 ADC 单次转换模式驱动间的保护。 - -.. only:: esp32c3 - - - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 单次转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 `__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3`,强制使用 ADC2。 - -.. only:: esp32 - - - ESP32-DevKitC:GPIO0 已用于自动烧录功能,不能用于 ADC 单次转换模式。 - - - ESP-WROVER-KIT:GPIO0、GPIO2、GPIO4 和 GPIO15 已有其他用途,不能用于 ADC 单次转换模式。 - - .. _adc-oneshot-power-management: +.. list:: -.. only:: not esp32 + - 随机数生成器 (RNG) 以 ADC 为输入源。使用 ADC 单次转换模式驱动从 RNG 生成随机数时,随机性会减弱。 + :SOC_ADC_DMA_SUPPORTED: - 一个 ADC 单元每次只能在一种操作模式下运行,可以是连续模式或单次模式。:cpp:func:`adc_oneshot_start` 提供了保护措施。 + :esp32 or esp32s2 or esp32s3: - Wi-Fi 也使用 ADC2,:cpp:func:`adc_oneshot_read` 提供了 Wi-Fi 驱动与 ADC 单次转换模式驱动间的保护。 + :esp32c3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 单次转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 `__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3`,强制使用 ADC2。 + :esp32: - ESP32-DevKitC:GPIO0 已用于自动烧录功能,不能用于 ADC 单次转换模式。 + :esp32: - ESP-WROVER-KIT:GPIO0、GPIO2、GPIO4 和 GPIO15 已有其他用途,不能用于 ADC 单次转换模式。 - .. _adc-oneshot-power-management: +.. _adc-oneshot-power-management: 电源管理 ^^^^^^^^ diff --git a/docs/zh_CN/api-reference/peripherals/dac.rst b/docs/zh_CN/api-reference/peripherals/dac.rst index 1c45cbf8c5d5..d96ce61213da 100644 --- a/docs/zh_CN/api-reference/peripherals/dac.rst +++ b/docs/zh_CN/api-reference/peripherals/dac.rst @@ -96,7 +96,7 @@ DAC 外设中包含一个余弦波发生器,可以在通道上产生余弦波 启用电源管理时(即开启 :ref:`CONFIG_PM_ENABLE`),系统会在进入 Light-sleep 模式前调整或停止 DAC 时钟源,这可能会影响 DAC 信号,从而导致数据无法正确转换。 -在连续模式下使用 DAC 驱动时,可以通过获取电源管理锁来防止系统在 DMA 或余弦波模式下改变或停止时钟源。时钟源为 APB 时,锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`。时钟源为 APLL 时(仅在 DMA 模式下),锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`。在进行 DAC 转换时(即 DMA 或余弦波发生器运行时),驱动程序会保证在调用 :cpp:func:`dac_continuous_enable` 后获取电源管理锁。同样地,在调用 :cpp:func:`dac_continuous_disable` 时,驱动程序会释放锁。 +在连续模式下使用 DAC 驱动时,可以通过获取电源管理锁来防止系统在 DMA 或余弦波模式下改变或停止时钟源。电源锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`。在进行 DAC 转换时(即 DMA 或余弦波发生器运行时),驱动程序会保证在调用 :cpp:func:`dac_continuous_enable` 后获取电源管理锁。同样地,在调用 :cpp:func:`dac_continuous_disable` 时,驱动程序会释放锁。 IRAM 安全 ^^^^^^^^^ diff --git a/docs/zh_CN/api-reference/peripherals/dedic_gpio.rst b/docs/zh_CN/api-reference/peripherals/dedic_gpio.rst index 68d58211dbbf..37f4979bf97b 100644 --- a/docs/zh_CN/api-reference/peripherals/dedic_gpio.rst +++ b/docs/zh_CN/api-reference/peripherals/dedic_gpio.rst @@ -16,16 +16,14 @@ GPIO 捆绑包是一组 GPIO,该组 GPIO 可以在一个 CPU 周期内同时 .. note:: - 专用 GPIO 更像是 CPU 外设,因此与 CPU 内核关系密切。强烈建议在 pin-to-core 任务中安装和操作 GPIO 捆绑包。例如,如果 GPIOA 连接到了 CPU0,而专用的 GPIO 指令却是从 CPU1 发出的,那么就无法控制 GPIOA。 + 专用 GPIO 更像是 CPU 外设,因此与 CPU 内核关系密切。强烈建议在 pin-to-core 任务中安装和操作 GPIO 捆绑包。例如,如果 GPIO_A 连接到了 CPU_0,而专用的 GPIO 指令却是从 CPU_1 发出的,那么就无法控制 GPIO_A。 安装 GPIO 捆绑包需要调用 :cpp:func:`dedic_gpio_new_bundle` 来分配软件资源并将专用通道连接到用户选择的 GPIO。GPIO 捆绑包的配置在 :cpp:type:`dedic_gpio_bundle_config_t` 结构体中: -- :cpp:member:`gpio_array`:包含 GPIO 编号的数组。 -- :cpp:member:`array_size`::cpp:member:`gpio_array` 的元素个数。 -- :cpp:member:`flags`:用于控制 GPIO 捆绑包行为的标志。 - - - :cpp:member:`in_en` 和 :cpp:member:`out_en` 用于选择是否开启输入输出功能(这两个功能可以同时开启)。 - - :cpp:member:`in_invert` 和 :cpp:member:`out_invert` 用于选择是否反转 GPIO 信号。 +- :cpp:member:`dedic_gpio_bundle_config_t::gpio_array`:包含 GPIO 编号的数组。 +- :cpp:member:`dedic_gpio_bundle_config_t::array_size`: :cpp:member:`dedic_gpio_bundle_config_t::gpio_array` 的元素个数。 +- :cpp:member:`dedic_gpio_bundle_config_t::in_en` 和 :cpp:member:`dedic_gpio_bundle_config_t::out_en` 用于选择是否开启输入输出功能(这两个功能可以同时开启)。 +- :cpp:member:`dedic_gpio_bundle_config_t::in_invert` 和 :cpp:member:`dedic_gpio_bundle_config_t::out_invert` 用于选择是否反转 GPIO 信号。 以下代码展示了如何安装只有输出功能的 GPIO 捆绑包: @@ -33,15 +31,6 @@ GPIO 捆绑包是一组 GPIO,该组 GPIO 可以在一个 CPU 周期内同时 :: - // 配置 GPIO - const int bundleA_gpios[] = {0, 1}; - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - }; - for (int i = 0; i < sizeof(bundleA_gpios) / sizeof(bundleA_gpios[0]); i++) { - io_conf.pin_bit_mask = 1ULL << bundleA_gpios[i]; - gpio_config(&io_conf); - } // 创建 bundleA,仅输出 dedic_gpio_bundle_handle_t bundleA = NULL; dedic_gpio_bundle_config_t bundleA_config = { @@ -55,10 +44,6 @@ GPIO 捆绑包是一组 GPIO,该组 GPIO 可以在一个 CPU 周期内同时 如需卸载 GPIO 捆绑包,可调用 :cpp:func:`dedic_gpio_del_bundle`。 -.. note:: - - :cpp:func:`dedic_gpio_new_bundle` 不包含任何 GPIO pad 配置(例如上拉/下拉、驱动能力、输出/输入使能)。因此,在安装专用 GPIO 捆绑包之前,必须使用 GPIO 驱动程序 API(如 :cpp:func:`gpio_config`)单独配置 GPIO。更多关于 GPIO 驱动的信息,请参考 :doc:`GPIO API 参考 `。 - GPIO 捆绑包操作 ---------------------- @@ -92,13 +77,13 @@ GPIO 捆绑包操作 3. 调用 CPU LL apis(如 `cpu_ll_write_dedic_gpio_mask`)或使用该掩码编写汇编代码 4. 切换 IO 的最快捷方式是使用专用的“设置/清除”指令: - .. only:: esp32s2 or esp32s3 + .. only:: CONFIG_IDF_TARGET_ARCH_XTENSA - 设置 GPIO 位:``set_bit_gpio_out imm[7:0]`` - 清除 GPIO 位:``clr_bit_gpio_out imm[7:0]`` - 注意:立即数宽度取决于专用 GPIO 通道的数量 - .. only:: esp32c2 or esp32c3 or esp32c6 or esp32h2 + .. only:: CONFIG_IDF_TARGET_ARCH_RISCV - 设置 GPIO 位:``csrrsi rd, csr, imm[4:0]`` - 清除 GPIO 位:``csrrci rd, csr, imm[4:0]`` diff --git a/docs/zh_CN/api-reference/peripherals/etm.rst b/docs/zh_CN/api-reference/peripherals/etm.rst index 9c1967dcadd3..448b1be6c69a 100644 --- a/docs/zh_CN/api-reference/peripherals/etm.rst +++ b/docs/zh_CN/api-reference/peripherals/etm.rst @@ -32,6 +32,7 @@ ETM 模块具有多个通道,这些通道支持用户根据需要进行配置 - :ref:`etm-event` - 介绍如何分配新的 ETM 事件句柄,以及如何从不同外设获取现有句柄。 - :ref:`etm-task` - 介绍如何分配新的 ETM 任务句柄,以及如何从不同外设获取现有句柄。 - :ref:`etm-channel-control` - 介绍常见的 ETM 通道控制函数。 +- :ref:`etm-power-management` - 介绍了驱动针对功耗管理提供的选项和策略。 - :ref:`etm-thread-safety` - 列出了驱动程序中始终线程安全的 API。 - :ref:`etm-kconfig-options` - 列出了 ETM 支持的 Kconfig 选项,这些选项对驱动程序的行为会产生不同影响。 @@ -131,6 +132,17 @@ ETM 通道分析 以上输出信息打印的数字 ID 在 ``soc/soc_etm_source.h`` 文件中定义。 +.. _etm-power-management: + +电源管理 +^^^^^^^^ + +当启用电源管理时,即 :ref:`CONFIG_PM_ENABLE` 打开的时候,系统可能会调整或禁用时钟源,并在进入睡眠前关闭 ETM 外设依赖的电源。这会导致事件和任务之间的连接信息被丢失,ETM 通道在唤醒后无法正常工作。因此,默认情况下,驱动程序会获取电源管理锁,以禁止系统关闭 ETM 外设。 + +.. only:: SOC_ETM_SUPPORT_SLEEP_RETENTION + + 如果你想节省更多电量,可以将 :cpp:member:`esp_etm_channel_config_t::etm_chan_flags::allow_pd` 设置为 ``true``。ETM 寄存器将在睡眠前备份,并在唤醒后恢复。请注意,启用此选项会增加内存消耗,用于保存寄存器上下文。 + .. _etm-thread-safety: 线程安全 diff --git a/docs/zh_CN/api-reference/peripherals/gpio.rst b/docs/zh_CN/api-reference/peripherals/gpio.rst index 761fdcd7c882..4fc0489c3d7b 100644 --- a/docs/zh_CN/api-reference/peripherals/gpio.rst +++ b/docs/zh_CN/api-reference/peripherals/gpio.rst @@ -85,7 +85,7 @@ GPIO 驱动提供了一个函数 :cpp:func:`gpio_dump_io_configuration` 用来 如果 IO 管脚通过 GPIO 交换矩阵连接到内部外设信号,输出信息打印中的外设信号 ID 定义可以在 :component_file:`soc/{IDF_TARGET_PATH_NAME}/include/soc/gpio_sig_map.h` 头文件中查看。``**RESERVED**`` 字样则表示此 IO 用于连接 SPI flash 或 PSRAM,强烈建议不要重新配置这些管脚用于其他功能。 -请不要依赖技术参考手册中记录的 GPIO 默认配置状态,因为特殊用途的 GPIO 可能会在 app_main 之前被引导程序或应用程序启动阶段的代码更改。 +请不要依赖技术参考手册中记录的 GPIO 默认配置状态,因为特殊用途的 GPIO 可能会在 app_main 之前被引导加载程序或应用程序启动阶段的代码更改。 .. only:: esp32c3 or esp32c6 or esp32h2 or esp32p4 or esp32s2 or esp32s3 or esp32c5 or esp32c61 diff --git a/docs/zh_CN/api-reference/peripherals/i2c.rst b/docs/zh_CN/api-reference/peripherals/i2c.rst index 0b545cf773e3..51979a91ab63 100644 --- a/docs/zh_CN/api-reference/peripherals/i2c.rst +++ b/docs/zh_CN/api-reference/peripherals/i2c.rst @@ -1,4 +1,4 @@ -集成电路总线 (I2C) +I2C 接口 ================== :link_to_translation:`en:[English]` @@ -44,7 +44,7 @@ I2C 时钟配置 - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_DEFAULT`:默认的 I2C 时钟源。 :SOC_I2C_SUPPORT_XTAL: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_XTAL`:以外部晶振作为 I2C 时钟源。 - :SOC_I2C_SUPPORT_RTC: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_RC_FAST`:以内部 20 MHz RC 振荡器作为 I2C 时钟源。 + :SOC_I2C_SUPPORT_RTC: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_RC_FAST`:以内部 20 MHz RC 振荡器作为 I2C 时钟源。 :SOC_I2C_SUPPORT_APB: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_APB`:以 APB 时钟作为 I2C 时钟源。 :SOC_I2C_SUPPORT_REF_TICK: - :cpp:enumerator:`i2c_clock_source_t::I2C_CLK_SRC_REF_TICK`:1 MHZ 时钟。 @@ -88,7 +88,7 @@ I2C 驱动程序提供以下服务: 资源分配 ^^^^^^^^^ -若系统支持 I2C 主机总线和 I2C 从机总线,则由驱动程序中的 :cpp:type:`i2c_bus_handle_t` 来表示。资源池管理可用的端口,并在有请求时分配空闲端口。 +若系统支持 I2C 主机总线,由驱动程序中的 :cpp:type:`i2c_master_bus_handle_t` 来表示。资源池管理可用的端口,并在有请求时分配空闲端口。 安装 I2C 主机总线和设备 ~~~~~~~~~~~~~~~~~~~~~~~ @@ -111,7 +111,7 @@ I2C 主机总线需要 :cpp:type:`i2c_master_bus_config_t` 指定的配置: - :cpp:member:`i2c_master_bus_config_t::intr_priority` 设置中断的优先级。如果设置为 ``0``,则驱动程序将使用低或中优先级的中断(优先级可设为 1、2 或 3 中的一个),若未设置,则将使用 :cpp:member:`i2c_master_bus_config_t::intr_priority` 指示的优先级。请使用数字形式(1、2、3),不要用位掩码形式((1<<1)、(1<<2)、(1<<3))。 - :cpp:member:`i2c_master_bus_config_t::trans_queue_depth` 设置内部传输队列的深度,但仅在异步传输中有效。 - :cpp:member:`i2c_master_bus_config_t::enable_internal_pullup` 启用内部上拉电阻。注意:该设置无法在高速频率下拉高总线,此时建议使用合适的外部上拉电阻。 - +- :cpp:member:`i2c_master_bus_config_t::allow_pd` 配置驱动程序是否允许系统在睡眠模式下关闭外设电源。在进入睡眠之前,系统将备份 I2C 寄存器上下文,当系统退出睡眠模式时,这些上下文将被恢复。关闭外设可以节省更多功耗,但代价是消耗更多内存来保存寄存器上下文。你需要在功耗和内存消耗之间做权衡。此配置选项依赖于特定的硬件功能,如果在不支持的芯片上启用它,你将看到类似 ``not able to power down in light sleep`` 的错误消息。 如果在 :cpp:type:`i2c_master_bus_config_t` 中指定了配置,则可调用 :cpp:func:`i2c_new_master_bus` 来分配和初始化 I2C 主机总线。如果函数运行正确,则将返回一个 I2C 总线句柄。若没有可用的 I2C 端口,此函数将返回 :c:macro:`ESP_ERR_NOT_FOUND` 错误。 @@ -166,7 +166,6 @@ I2C 主机设备需要 :cpp:type:`i2c_device_config_t` 指定的配置: ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); // 源文件 2 - #include "esp_private/i2c_platform.h" #include "driver/i2c_master.h" i2c_master_bus_handle_t handle; ESP_ERROR_CHECK(i2c_master_get_bus_handle(0, &handle)); @@ -452,20 +451,20 @@ I2C 从机的发送 buffer 可作为 FIFO 来存储要发送的数据。在主 i2c_slave_config_t i2c_slv_config = { .addr_bit_len = I2C_ADDR_BIT_LEN_7, // 7 位地址 .clk_source = I2C_CLK_SRC_DEFAULT, // 设置时钟源 - .i2c_port = 0, // 设置 I2C 端口编号 + .i2c_port = TEST_I2C_PORT, // 设置 I2C 端口编号 .send_buf_depth = 256, // 设置 TX buffer 长度 - .scl_io_num = 2, // SCL 管脚编号 - .sda_io_num = 1, // SDA 管脚编号 + .scl_io_num = I2C_SLAVE_SCL_IO, // SCL 管脚编号 + .sda_io_num = I2C_SLAVE_SDA_IO, // SDA 管脚编号 .slave_addr = 0x58, // 从机地址 }; - i2c_bus_handle_t i2c_bus_handle; - ESP_ERROR_CHECK(i2c_new_slave_device(&i2c_slv_config, &i2c_bus_handle)); + i2c_slave_dev_handle_t slave_handle; + ESP_ERROR_CHECK(i2c_new_slave_device(&i2c_slv_config, &slave_handle)); for (int i = 0; i < DATA_LENGTH; i++) { data_wr[i] = i; } - ESP_ERROR_CHECK(i2c_slave_transmit(i2c_bus_handle, data_wr, DATA_LENGTH, 10000)); + ESP_ERROR_CHECK(i2c_slave_transmit(slave_handle, data_wr, DATA_LENGTH, 10000)); I2C 从机读取 ~~~~~~~~~~~~~ diff --git a/docs/zh_CN/api-reference/peripherals/i2s.rst b/docs/zh_CN/api-reference/peripherals/i2s.rst index 369f1d24b0af..ae166b6fa27b 100644 --- a/docs/zh_CN/api-reference/peripherals/i2s.rst +++ b/docs/zh_CN/api-reference/peripherals/i2s.rst @@ -78,6 +78,10 @@ I2S 时钟 - :cpp:enumerator:`i2s_clock_src_t::I2S_CLK_SRC_PLL_160M`:160 MHz PLL 时钟。 +.. only:: SOC_I2S_SUPPORTS_PLL_F120M + + - :cpp:enumerator:`i2s_clock_src_t::I2S_CLK_SRC_PLL_120M`:120 MHz PLL 时钟。 + .. only:: SOC_I2S_SUPPORTS_PLL_F96M - :cpp:enumerator:`i2s_clock_src_t::I2S_CLK_SRC_PLL_96M`:96 MHz PLL 时钟。 @@ -232,7 +236,16 @@ I2S 驱动中的资源可分为三个级别: 电源管理启用(即开启 :ref:`CONFIG_PM_ENABLE`)时,系统将在进入 Light-sleep 前调整或停止 I2S 时钟源,这可能会影响 I2S 信号,从而导致传输或接收的数据无效。 -I2S 驱动可以获取电源管理锁,从而防止系统设置更改或时钟源被禁用。时钟源为 APB 时,锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`。时钟源为 APLL(若支持)时,锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`。用户通过 I2S 读写时(即调用 :cpp:func:`i2s_channel_read` 或 :cpp:func:`i2s_channel_write`),驱动程序将获取电源管理锁,并在读写完成后释放锁。 +I2S 驱动可以获取电源管理锁,从而防止系统设置更改或时钟源被禁用。电源锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`。用户通过 I2S 读写时(即调用 :cpp:func:`i2s_channel_read` 或 :cpp:func:`i2s_channel_write`),驱动程序将获取电源管理锁,并在读写完成后释放锁。 + +.. only:: SOC_I2S_SUPPORT_SLEEP_RETENTION + + 睡眠保留 + """""""" + + {IDF_TARGET_NAME} 支持在进入 **轻度睡眠** 之前保留 I2S 寄存器中的内容,并在唤醒后恢复。也就是说外设若因进入 **轻度睡眠** 而掉电,程序不需要在唤醒后重新配置 I2S。 + + 该特性可以通过置位配置中的 :cpp:member:`i2s_chan_config_t::allow_pd` 标志位启用。启用后驱动允许系统在轻度睡眠时对 I2S 掉电,同时保存 I2S 的寄存器内容。它可以帮助降低轻度睡眠时的功耗,但需要花费一些额外的存储来保存寄存器的配置。 有限状态机 ^^^^^^^^^^ diff --git a/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst index 874c8b051a34..ace7b536cab5 100644 --- a/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst @@ -60,7 +60,7 @@ MIPI DSI 接口的 LCD - :cpp:member:`esp_lcd_dpi_panel_config_t::virtual_channel` 设置虚拟通道号。与 DBI 接口类似,DPI 接口也需要设置虚拟通道。如果只连接了一个 LCD,则将此值设置为 ``0``。 - :cpp:member:`esp_lcd_dpi_panel_config_t::dpi_clk_src` 设置 DPI 接口的时钟源。可用的时钟源列表见 :cpp:type:`mipi_dsi_dpi_clock_source_t`。 - :cpp:member:`esp_lcd_dpi_panel_config_t::dpi_clock_freq_mhz` 设置 DPI 时钟频率 (MHz)。像素时钟频率越高,刷新率越高,但如果 DMA 带宽不足或 LCD 控制器芯片不支持高像素时钟频率,则可能会导致闪烁。 - - :cpp:member:`esp_lcd_dpi_panel_config_t::pixel_format` 设置像素数据的像素格式。可用的像素格式见 :cpp:type:`lcd_color_rgb_pixel_format_t`。MIPI LCD 通常使用 **RGB888** 来获得最佳色彩深度。 + - :cpp:member:`esp_lcd_dpi_panel_config_t::in_color_format` 设置输入的像素数据的格式。可用的像素格式见 :cpp:type:`lcd_color_format_t`。MIPI LCD 通常使用 **RGB888** 来获得最佳色彩深度。 - :cpp:member:`esp_lcd_dpi_panel_config_t::video_timing` 设置 LCD 面板的特定时序参数。包括 LCD 分辨率和消隐间隔在内的必要参数列表见 :cpp:type:`esp_lcd_video_timing_t`,请依据 LCD 技术规格书填写参数。 - :cpp:member:`esp_lcd_dpi_panel_config_t::extra_dpi_panel_flags::use_dma2d` 设置是否用 2D DMA 将用户数据异步复制到帧 buffer 中。 @@ -71,7 +71,7 @@ MIPI DSI 接口的 LCD .virtual_channel = 0, .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = 1 * 1000, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888, + .in_color_format = LCD_COLOR_FMT_RGB888, .video_timing = { .h_size = EXAMPLE_MIPI_DSI_LCD_H_RES, .v_size = EXAMPLE_MIPI_DSI_LCD_V_RES, diff --git a/docs/zh_CN/api-reference/peripherals/lcd/rgb_lcd.rst b/docs/zh_CN/api-reference/peripherals/lcd/rgb_lcd.rst index 6890194ee67d..f73e2a6cbb54 100644 --- a/docs/zh_CN/api-reference/peripherals/lcd/rgb_lcd.rst +++ b/docs/zh_CN/api-reference/peripherals/lcd/rgb_lcd.rst @@ -159,7 +159,7 @@ bounce buffer 与 PSRAM frame buffer .. note:: - 强烈建议在此模式下启用 Kconfig 选项::ref:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` 和 :ref:`CONFIG_SPIRAM_RODATA`,开启“PSRAM XIP(就地执行)”功能,使 CPU 能从 PSRAM 里而不是主 flash 中提取指令和只读数据。此外,即使想通过 SPI 1 写入主 flash,外部存储器 cache 也不会被禁用,应用程序便能正常显示 OTA 进度条。 + 强烈建议在此模式下启用 Kconfig 选项::ref:`CONFIG_SPIRAM_XIP_FROM_PSRAM`,开启“PSRAM XIP(就地执行)”功能,使 CPU 能从 PSRAM 里而不是主 flash 中提取指令和只读数据。此外,即使想通过 SPI 1 写入主 flash,外部存储器 cache 也不会被禁用,应用程序便能正常显示 OTA 进度条。 .. note:: @@ -201,8 +201,6 @@ bounce buffer 与 PSRAM frame buffer }; ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle)); -请注意,此模式下还可以设置 :cpp:member:`esp_lcd_rgb_panel_config_t::bb_invalidate_cache` 标志。启用此功能,从 PSRAM 中读取 frame buffer 数据后可以释放 cache 行。但如果在 cache 行被释放时,另一个内核恰好将数据写入 frame buffer 中,则可能导致轻微的损坏(从技术上讲,在 cache 写回和调用失效之间的时间窗口内,对 frame buffer 的写入操作会被忽略)。 - .. _bounce_buffer_only: 只应用 bounce buffer diff --git a/docs/zh_CN/api-reference/peripherals/ledc.rst b/docs/zh_CN/api-reference/peripherals/ledc.rst index e068936f540c..51ce5785ecc7 100644 --- a/docs/zh_CN/api-reference/peripherals/ledc.rst +++ b/docs/zh_CN/api-reference/peripherals/ledc.rst @@ -337,6 +337,18 @@ LED PWM 控制器 API 有多种方式即时改变 PWM 频率: 要注册处理程序来处理中断,可调用函数 :cpp:func:`ledc_isr_register`。 +电源管理 +-------- + +LEDC 驱动不使用电源管理锁来防止系统进入 Light-sleep 。相反,可以通过配置 :cpp:member:`ledc_channel_config_t::sleep_mode` 来选择 LEDC 外设电源域状态和 PWM 信号在睡眠期间的输出行为。默认模式是 :cpp:enumerator:`LEDC_SLEEP_MODE_NO_ALIVE_NO_PD`,它表示没有信号输出,并且 LEDC 电源域在睡眠期间不会下电。 + +如果需要在 Light-sleep 中保持信号输出,则可以选择 :cpp:enumerator:`LEDC_SLEEP_MODE_KEEP_ALIVE` 模式。只要绑定的 LEDC 定时器时钟源兼容 Light-sleep , PWM 信号就可以在系统进入 Light-sleep 期间继续输出。其代价是睡眠期间的功耗会更高,这是由于时钟源和 LEDC 所属的电源域无法被下电。值得注意的是,在入睡前未完成的渐变也可以在睡眠期间继续,只是有可能没法准确停在目标占空比上。系统被唤醒后,驱动会调整 PWM 占空比到原来设定的目标占空比上。 + +.. only:: SOC_LEDC_SUPPORT_SLEEP_RETENTION + + 此外还有另一种睡眠模式,:cpp:enumerator:`LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD` 。选择此模式可以在睡眠中节省一些功耗,但会消耗更多内存。在进入 Light-sleep 之前,系统会保存 LEDC 寄存器上下文,并在唤醒后恢复它们,从而使 LEDC 电源域可以在睡眠期间被下电。任何未完成的渐变在从睡眠状态唤醒后都不会继续进行,而是输出一个固定占空比的 PWM 信号,该占空比与进入睡眠前的当下占空比相匹配。 + + .. only:: esp32 .. _ledc-api-high_low_speed_mode: diff --git a/docs/zh_CN/api-reference/peripherals/mcpwm.rst b/docs/zh_CN/api-reference/peripherals/mcpwm.rst index f90ba9cd4299..78f29d6983ca 100644 --- a/docs/zh_CN/api-reference/peripherals/mcpwm.rst +++ b/docs/zh_CN/api-reference/peripherals/mcpwm.rst @@ -122,8 +122,6 @@ MCPWM 生成器 - :cpp:member:`mcpwm_generator_config_t::gen_gpio_num` 设置生成器使用的 GPIO 编号。 - :cpp:member:`mcpwm_generator_config_t::invert_pwm` 设置是否反相 PWM 信号。 -- :cpp:member:`mcpwm_generator_config_t::io_loop_back` 设置是否启用回环模式。该模式仅用于调试,使用 GPIO 交换矩阵外设同时启用 GPIO 输入和输出。 -- :cpp:member:`mcpwm_generator_config_t::io_od_mode` 设置是否启用漏极开路输出。 - :cpp:member:`mcpwm_generator_config_t::pull_up` 和 :cpp:member:`mcpwm_generator_config_t::pull_down` 用来设置是否启用内部上下拉电阻。 分配成功后,:cpp:func:`mcpwm_new_generator` 将返回一个指向已分配生成器的指针。否则,函数将返回错误代码。具体来说,当 MCPWM 操作器中没有空闲生成器时,将返回 :c:macro:`ESP_ERR_NOT_FOUND` 错误。[1]_ @@ -142,7 +140,6 @@ MCPWM 故障分为两种类型:来自 GPIO 的故障信号和软件故障。 - :cpp:member:`mcpwm_gpio_fault_config_t::gpio_num` 设置故障所使用的 GPIO 编号。 - :cpp:member:`mcpwm_gpio_fault_config_t::active_level` 设置故障信号的有效电平。 - :cpp:member:`mcpwm_gpio_fault_config_t::pull_up` 和 :cpp:member:`mcpwm_gpio_fault_config_t::pull_down` 设置是否在内部拉高和/或拉低 GPIO。 -- :cpp:member:`mcpwm_gpio_fault_config_t::io_loop_back` 设置是否启用回环模式。该模式仅用于调试,使用 GPIO 交换矩阵外设同时启用 GPIO 输入和输出。 分配成功后,:cpp:func:`mcpwm_new_gpio_fault` 将返回一个指向已分配故障的指针。否则,函数将返回错误代码。具体来说,当指定 MCPWM 组中没有空闲 GPIO 故障时,将返回 :c:macro:`ESP_ERR_NOT_FOUND` 错误。[1]_ @@ -163,7 +160,6 @@ MCPWM 同步源 - :cpp:member:`mcpwm_gpio_sync_src_config_t::gpio_num` 设置同步源使用的 GPIO 编号。 - :cpp:member:`mcpwm_gpio_sync_src_config_t::active_neg` 设置同步信号在下降沿是否有效。 - :cpp:member:`mcpwm_gpio_sync_src_config_t::pull_up` 和 :cpp:member:`mcpwm_gpio_sync_src_config_t::pull_down` 设置是否在内部拉高和/或拉低 GPIO。 -- :cpp:member:`mcpwm_gpio_sync_src_config_t::io_loop_back` 设置是否启用回环模式。该模式仅用于调试,使用 GPIO 交换矩阵外设同时启用 GPIO 输入和输出。 分配成功后,:cpp:func:`mcpwm_new_gpio_sync_src` 将返回一个指向已分配同步源的指针。否则,函数将返回错误代码。具体来说,当 MCPWM 组中没有空闲 GPIO 时钟源时,将返回 :c:macro:`ESP_ERR_NOT_FOUND` 错误。[1]_ @@ -207,8 +203,6 @@ MCPWM 组有一个专用定时器,用于捕获特定事件发生时的时间 - :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::pos_edge` 和 :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::neg_edge` 设置是否在输入信号的上升沿和/或下降沿捕获时间戳。 - :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::pull_up` 和 :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::pull_down` 设置是否在内部拉高和/或拉低 GPIO。 - :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::invert_cap_signal` 设置是否取反捕获信号。 -- :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::io_loop_back` 设置是否启用回环模式。该模式仅用于调试,使用 GPIO 交换矩阵外设同时启用 GPIO 输入和输出。 -- :cpp:member:`mcpwm_capture_channel_config_t::extra_capture_channel_flags::keep_io_conf_at_exit` 设置是否在删除通道时保留 GPIO 的相关配置。 分配成功后,:cpp:func:`mcpwm_new_capture_channel` 将返回一个指向已分配捕获通道的指针。否则,函数将返回错误代码。具体来说,当捕获定时器中没有空闲捕获通道时,将返回 :c:macro:`ESP_ERR_NOT_FOUND` 错误。 @@ -529,7 +523,7 @@ MCPWM 比较器可以在定时器计数器等于比较值时发送通知。若 // NOTE: 下面的操作是无效的,不能将同一种 delay 应用于不同的 generator 上 mcpwm_generator_set_dead_time(mcpwm_gen_b, mcpwm_gen_b, &dt_config); - 然而,你可以为生成器 A 设置 ``posedge delay``,为生成器 B 设置 ``negedge delay``。另外,也可以为生成器 A 同时设置 ``posedge delay`` 和 ``negedge delay``,而让生成器 B 绕过死区模块。 + 然而,你可以为生成器 A 设置 ``posedge delay``,为生成器 B 设置 ``negedge delay``。另外,也可以为生成器 B 同时设置 ``posedge delay`` 和 ``negedge delay``,而让生成器 A 绕过死区模块。注意,如果对生成器 A 同时设置 ``negedge delay`` 和 ``posedge delay``,生成器 B 将无法正常工作。其中,生成器 A 为通过操作器句柄申请的第一个生成器,生成器 B 为通过操作器句柄申请的第二个生成器。 .. note:: diff --git a/docs/zh_CN/api-reference/peripherals/pcnt.rst b/docs/zh_CN/api-reference/peripherals/pcnt.rst index 4f4cc2b08580..acd8ed550548 100644 --- a/docs/zh_CN/api-reference/peripherals/pcnt.rst +++ b/docs/zh_CN/api-reference/peripherals/pcnt.rst @@ -226,7 +226,7 @@ PCNT 单元的滤波器可滤除信号中的短时毛刺,:cpp:type:`pcnt_glitc .. note:: - 毛刺滤波器的时钟信息来自 APB。为确保 PCNT 单元不会滤除脉冲信号,最大毛刺宽度应大于一个 APB_CLK 周期(如果 APB 的频率为 80 MHz,则最大毛刺宽度为 12.5 ns)。使能动态频率缩放 (DFS) 后,APB 的频率会发生变化,从而最大毛刺宽度也会发生变化,这会导致计数器无法正常工作。因此,第一次使能毛刺滤波器时,驱动会为 PCNT 单元安装 PM 锁。关于 PCNT 驱动的电源管理的更多信息,请参考 :ref:`pcnt-power-management`。 + 毛刺滤波器的时钟信息来自 APB。为确保 PCNT 单元不会滤除脉冲信号,最大毛刺宽度应大于一个 APB_CLK 周期(如果 APB 的频率为 80 MHz,则最大毛刺宽度为 12.5 ns)。使能动态频率缩放 (DFS) 后,APB 的频率会发生变化,从而最大毛刺宽度也会发生变化,这会导致计数器无法正常工作。因此,驱动会为每个 PCNT 单元安装电源锁。关于 PCNT 驱动的电源管理的更多信息,请参考 :ref:`pcnt-power-management`。 .. code:: c @@ -269,7 +269,7 @@ PCNT 单元的滤波器可滤除信号中的短时毛刺,:cpp:type:`pcnt_glitc * 将 PCNT 单元的驱动状态从 **初始** 切换到 **使能** 。 * 如果中断服务已经在 :cpp:func:`pcnt_unit_register_event_callbacks` 延迟安装,使能中断服务。 -* 如果电源管理锁已经在 :cpp:func:`pcnt_unit_set_glitch_filter` 延迟安装,获取该电源管理锁。请参考 :ref:`pcnt-power-management` 获取更多信息。 +* 如果电源管理锁已经安装,获取该电源管理锁。请参考 :ref:`pcnt-power-management` 获取更多信息。 调用函数 :cpp:func:`pcnt_unit_disable` 会进行相反的操作,即将 PCNT 单元的驱动状态切换回 **初始** 状态,禁用中断服务并释放电源管理锁。 @@ -327,9 +327,9 @@ PCNT 内部的硬件计数器会在计数达到高/低门限的时候自动清 电源管理 ^^^^^^^^^^ -使能电源管理(即 :ref:`CONFIG_PM_ENABLE` 开启)后,在进入 Light-sleep 模式之前,系统会调整 APB 的频率。这会改变 PCNT 毛刺滤波器的参数,从而可能导致有效信号被滤除。 +当电源管理使能(即 :ref:`CONFIG_PM_ENABLE` 开启)时,系统会在进入 Light-sleep 模式之前调整 APB 的频率,这可能导致 PCNT 毛刺滤波器将有效信号误认为噪声。 -驱动通过获取 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 类型的电源管理锁来防止系统修改 APB 频率。每当通过 :cpp:func:`pcnt_unit_set_glitch_filter` 使能毛刺滤波器时,驱动可以保证系统在 :cpp:func:`pcnt_unit_enable` 使能 PCNT 单元后获取电源管理锁。而系统调用 :cpp:func:`pcnt_unit_disable` 之后,驱动会释放电源管理锁。 +为了防止这种情况发生,驱动程序可以获取类型为 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 的电源管理锁,以确保 APB 频率保持不变。该锁在通过 :cpp:func:`pcnt_unit_enable` 使能 PCNT 单元时获取,并在通过 :cpp:func:`pcnt_unit_disable` 禁用单元时释放。 .. _pcnt-iram-safe: diff --git a/docs/zh_CN/api-reference/peripherals/sd_pullup_requirements.rst b/docs/zh_CN/api-reference/peripherals/sd_pullup_requirements.rst index 4b57be13f5da..16f88d6884e8 100644 --- a/docs/zh_CN/api-reference/peripherals/sd_pullup_requirements.rst +++ b/docs/zh_CN/api-reference/peripherals/sd_pullup_requirements.rst @@ -1 +1,360 @@ -.. include:: ../../../en/api-reference/peripherals/sd_pullup_requirements.rst +SD 上拉需求 +=========== + +:link_to_translation:`en:[English]` + +乐鑫硬件产品适用于多种场景,这些场景可能需要不同的管脚上拉状态。因此,要调整某些产品的特定管脚上拉状态,为 SD 总线提供所需的上拉电阻。 + +{IDF_TARGET_NAME} 使用 SPI 或 SDMMC 控制器与 SD 卡通信时,需要满足 SD 卡的上拉需求。当 SD 卡在 SPI 模式或 1 位 SD 模式下运行时,SD 总线的 CMD 和 DATA (DAT0 - DAT3) 线必须通过 10 kΩ 电阻上拉。SD 卡和 SDIO 设备也应在上述所有管脚(无论是否连接到主机)上有上拉电阻,以防设备进入错误状态。 + +.. only:: esp32 + + 默认情况下,如果 flash 电压为 3.3 V,则 MTDI strapping 管脚与 DAT2 线的上拉电阻不兼容。详情请参阅 :ref:`mtdi_strapping_pin`。 + +.. todo:: + + Add a diagram of the bus lines and pullups + +本文档涵盖以下章节内容: + +- :ref:`compatibility_overview_espressif_hw_sdio` - 简要介绍乐鑫产品管脚的默认上拉状态与 SD 总线所需状态之间的兼容性 +- :ref:`sdio_solutions` - 解决兼容性问题的方案 +- :ref:`related_info_sdio` - 其他相关信息 + + +.. _compatibility_overview_espressif_hw_sdio: + +兼容性概述 +---------- + +本节概述了在使用安全数字输入输出 (SDIO) 时可能出现的兼容性问题。SD 总线需要连接上拉电阻,因此要妥善解决与主机设备及从机设备有关的兼容性问题。下面每个问题都有相应解决方案的链接,主机设备和从机设备的解决方案可能有所不同。 + + +.. only:: esp32 + + 片上系统 (SoCs) + ^^^^^^^^^^^^^^^ + + - ESP32(除 D2WD 版本外,请参阅 `ESP32 技术规格书 `_): + + - :ref:`sd_pull-up_no_pull-ups` + - 带有 3.3 V flash 芯片的模组,请参阅 :ref:`strapping_conflicts_dat2` + + - ESP32-D2WD: + + - :ref:`sd_pull-up_no_pull-ups` + - :ref:`no_pull-up_on_gpio12` + +.. only:: SOC_SDMMC_USE_GPIO_MATRIX + + 片上系统 (SoCs) + ^^^^^^^^^^^^^^^ + + {IDF_TARGET_NAME} SDMMC 主机控制器允许 SD 接口信号使用所有 GPIO。但建议避免使用 strapping GPIO、带内部弱下拉的 GPIO 以及通常用于其他用途的 GPIO,以防出现冲突。 + + .. only:: esp32s3 + + - GPIO0(strapping 管脚) + - GPIO45、GPIO46(strapping 管脚,内部弱下拉) + - GPIO26 - GPIO32(通常用于 SPI flash 和 PSRAM) + - GPIO33 - GPIO37(用于带有八线 SPI flash 或八线 PSRAM 的芯片和模组) + - GPIO43、GPIO44(默认用于 UART0 的 GPIO) + - GPIO19、GPIO20(默认用于 USB 的 GPIO) + + +.. only:: esp32 + + 系统级封装 (SIP) + ^^^^^^^^^^^^^^^^ + + - ESP32-PICO-D4: + + - :ref:`sd_pull-up_no_pull-ups` + - :ref:`strapping_conflicts_dat2` + + + 模组 + ^^^^ + + - ESP32-WROOM-32 系列模组,包括 ESP32-WROOM-32、ESP32-WROOM-32D、ESP32-WROOM-32U 和 ESP32-SOLO-1 + + - :ref:`sd_pull-up_no_pull-ups` + - :ref:`strapping_conflicts_dat2` + + - ESP32-WROVER 系列模组,包括 ESP32-WROVER 和 ESP32-WROVER-I + + - :ref:`sd_pull-up_no_pull-ups` + + - ESP32-WROVER-B 系列模组,包括 ESP32-WROVER-B 和 ESP32-WROVER-IB + + - :ref:`sd_pull-up_no_pull-ups` + - :ref:`strapping_conflicts_dat2` + + +.. only:: esp32 + + .. _sdio_dev_kits: + + 开发板 + ^^^^^^ + + - ESP32-PICO-KIT,包括 PICO-KIT v4.1、v4.0 和 v3 + + - :ref:`sd_pull-up_no_pull-ups` + - :ref:`strapping_conflicts_dat2` + - :ref:`gpio2_strapping_pin` + + - ESP32-DevKitC,包括 ESP32-DevKitC v4 和 v2 + + - :ref:`sd_pull-up_no_pull-ups` + - :ref:`strapping_conflicts_dat2` + - :ref:`gpio2_strapping_pin` + + - ESP-WROVER-KIT + + - 提供所需的上拉电阻 + - :ref:`pull-up_conflicts_on_gpio13` (v4.1、v3、v2 和 v1) + - :ref:`strapping_conflicts_dat2` (v4.1、v2 和 v1) + - :ref:`gpio2_strapping_pin` (v2 和 v1) + + 通过查看安装在开发板上的模组,可以确定所使用的 ESP32-WROVER-KIT 的版本: + + - ESP32-WROVER-B 对应 v4.1 版本 + - ESP32-WROVER 对应 v3 版本 + - ESP32-WROOM-32 对应 v1 和 v2 版本 + + - ESP32-LyraTD-MSC + + - 提供所需的上拉电阻 + - :ref:`strapping_conflicts_dat2` + + - ESP32-LyraT + + - 提供所需的上拉电阻 + - :ref:`pull-up_conflicts_on_gpio13` + +.. only:: esp32s3 + + .. _sdio_dev_kits: + + 开发板 + ^^^^^^ + + - ESP32-S3-DevKitC-1 + + - :ref:`sd_pull-up_no_pull-ups` + + - ESP32-S3-USB-OTG + + - 该开发板可在单线和四线 SD 模式或 SPI 模式下使用。 + - 在 GPIO 33-38 上提供所需的上拉电阻。 + + - ESP32-S3-EYE + + - 该开发板仅限于单线 SD 模式下使用。 + - 在 GPIO 38-40 上提供所需的上拉电阻。 + +.. only:: SOC_SDIO_SLAVE_SUPPORTED + + 非乐鑫主机 + ^^^^^^^^^^ + + 请确保 SDIO 主机为所有 SD 总线信号提供必要的上拉电阻。 + + +.. _sdio_solutions: + +解决方案 +-------- + +.. _sd_pull-up_no_pull-ups: + +无上拉电阻 +^^^^^^^^^^ + +.. only:: esp32 or esp32s3 + + 如果所使用的开发板没有上拉电阻,可以执行以下操作: + + - 如果主机设备和从机设备在不同的开发板上,将其中一块开发板换为带有上拉电阻的开发板。如需了解哪些乐鑫开发板带有上拉电阻,请参阅 :ref:`sdio_dev_kits`。 + - 用一个 10 kΩ 的电阻将每个需要上拉的管脚连接到 VDD,从而附加外部上拉电阻。 + +.. only:: not esp32 and not esp32s3 + + 如果所使用的开发板没有上拉电阻,可以执行以下操作: + + - 如果主机设备和从机设备在不同的开发板上,将其中一块开发板换为带有上拉电阻的开发板。 + - 用一个 10 kΩ 的电阻将每个需要上拉的管脚连接到 VDD,从而附加外部上拉电阻。 + +.. only:: esp32 + + .. _pull-up_conflicts_on_gpio13: + + GPIO13 上拉冲突 + ^^^^^^^^^^^^^^^ + + 如果所用设备的 DAT3 没有正确上拉,可以参考下列操作: + + - 使用 1 位 SD 模式并将设备的 DAT3 连接到 VDD + - 使用 SPI 模式 + - 对 GPIO13 管脚执行以下操作之一: + - 移除下拉电阻 + - 附加小于 5 kΩ 的上拉电阻(建议使用 2 kΩ 的电阻) + - 在 1 位 SD 模式下,通过主机、或是通过 VDD 上的 3.3 V 电压,将管脚拉高或驱动到高电平。 + + + .. _strapping_conflicts_dat2: + + Bootstrap 与 SDIO 在 DAT2 上的冲突 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ESP32 的启动 strapping 需求与 SDIO 协议之间存在冲突。详情请参阅 :ref:`mtdi_strapping_pin`。 + + 要解决此冲突,可参考以下选项: + + 1.(推荐)烧录选择 flash 电压的 eFuse。该操作会将内部调节器的输出电压永久配置为 3.3 V,并且 GPIO12 将不再用作 strapping 管脚。烧录完成后,将上拉电阻连接到 GPIO12。 + + .. warning:: + + 烧录 eFuse 是不可逆的!上述问题清单可能已经过时,因此请确保要烧录的模组内嵌 3.3 V flash 芯片,可前往 https://www.espressif.com/ 进行确认。如果在带有 1.8 V flash 芯片的模组上烧录 3.3 V eFuse,模组将停止工作。 + + 如果确定要烧录 eFuse,请转到 ESP-IDF 目录下,通过 ``espefuse.py`` 工具运行以下命令: + + .. code-block:: bash + + components/esptool_py/esptool/espefuse.py set_flash_voltage 3.3V + + 此命令将烧录 ``XPD_SDIO_TIEH``、``XPD_SDIO_FORCE`` 和 ``XPD_SDIO_REG`` eFuse。当以上三个 eFuse 被烧录为 1 时,内部 VDD_SDIO flash 电压调节器将被永久设置为 3.3 V。如果烧录成功,将看到以下日志: + + .. code-block:: bash + + espefuse.py v2.6 + Connecting.... + + Enable internal flash voltage regulator (VDD_SDIO) to 3.3 V. + The following eFuses are burned: XPD_SDIO_FORCE, XPD_SDIO_REG, XPD_SDIO_TIEH. + This is an irreversible operation. + Type 'BURN' (all capitals) to continue. + BURN + VDD_SDIO setting complete. + + 要检查 eFuse 的状态,请运行: + + .. code-block:: none + + idf.py efuse-summary + + 如果运行自动烧录脚本,最好使用独立的 eFuse 工具 ``espefuse.py``。此工具还具有 ``--do-not-confirm`` 选项,可在无需确认的情况下烧录 eFuse。 + + 有关烧录 eFuse 的更多信息,请参阅 **{IDF_TARGET_NAME} 技术参考手册** [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。 + + 2. **如果使用 1 位 SD 模式或 SPI 模式**,请断开 DAT2 管脚并确保其被拉高。可以采取下列两个选项之一: + + - 使主机的 DAT2 管脚悬空,并将从机设备的 DAT2 直接连接到 VDD。 + - 对于从机设备,构建具有 ``SDIO_SLAVE_FLAG_DAT2_DISABLED`` 选项的固件并重新烧录设备,此选项可避免从机设备检测 DAT2 线。请注意,CCCR 寄存器将不再支持 4 位 SD 模式,但主机并不知晓这一点,因此必须在主机端禁用 4 位 SD 模式。 + + + .. _no_pull-up_on_gpio12: + + GPIO12 无上拉电阻 + ^^^^^^^^^^^^^^^^^ + + 所用模组与 SDIO 协议兼容,只需通过 10 kΩ 电阻将 GPIO12 连接到 VDD 即可。 + + + .. _gpio2_strapping_pin: + + 下载模式不起效(次要问题) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + 当 GPIO2 管脚根据 SD 上拉需求被拉高时,将无法进入下载模式,因为 GPIO2 是一个 strapping 管脚,下载模式下必须被拉低。 + + 可参考以下解决方案: + + - 对于需要用跳线短接 GPIO0 和 GPIO2 管脚的开发板,跳线连接完成后,自动复位电路会在进入下载模式前将 GPIO2 与 GPIO0 一起拉低。 + - 对于 GPIO2 管脚上连有组件(例如下拉电阻和/或 LED)的开发板,请查看开发板的原理图,确认连接到 GPIO2 上组件的具体情况。 + + - **LED** 大多数情况下不会影响操作。 + - **下拉电阻** 可能会干扰 DAT0 信号,必须移除。 + + 如果上述解决方案无效,请检查主机或从机设备是否带有会影响 GPIO2 的上拉电阻,如有,将其移除。 + + +.. only:: esp32 + + .. _related_info_sdio: + + 相关信息 + -------- + + .. _mtdi_strapping_pin: + + MTDI strapping 管脚 + ^^^^^^^^^^^^^^^^^^^ + + MTDI (GPIO12) 为 strapping 管脚,用于选择内部调节器 (VDD_SDIO) 的输出电压,为 flash 芯片供电。该管脚带有内部下拉电阻,因此若处于未连接状态,MTDI 管脚将在启动时读取低电平,选择默认的 3.3 V 操作。 + + 除 ESP32-WROVER-B 外的所有 ESP32-WROVER 模组都使用 1.8 V flash,并在 GPIO12 上有内部上拉电阻。使用 3.3 V flash 的其他模组在 GPIO12 管脚上没有上拉电阻,并在芯片内部 GPIO12 管脚默认使能弱下拉。 + + 为 GPIO12 添加上拉电阻以进行 SD 卡操作时,请考虑以下事项: + + - 在不使用内部调节器 (VDD_SDIO) 为 flash 供电的开发板上,GPIO12 可以被拉高。 + - 在使用 1.8 V flash 芯片的开发板上,复位时 GPIO12 需要被拉高,这与 SD 卡操作完全兼容。 + - 在使用内部调节器和 3.3 V flash 芯片的开发板上,复位时 GPIO12 必须被拉低,这与 SD 卡操作不兼容。有关乐鑫开发板与 SD 卡操作之间的兼容性问题,详情请参阅 :ref:`compatibility_overview_espressif_hw_sdio`。 + + + 内部上拉和 strapping 需求 + ^^^^^^^^^^^^^^^^^^^^^^^^^ + + 使用外部电阻始终是更优选择。乐鑫产品中的内部弱上拉和下拉电阻启用后可以代替外部电阻,但此解决方案并不能保证可靠的 SDIO 通信。 + + 话虽如此,有关内部上拉和 strapping 需求的信息仍有一些参考价值。乐鑫硬件产品不同管脚(CMD 和 DATA 等)的内部弱上拉和弱下拉电阻的默认连接情况不同。下表展示了 CMD 和 DATA 管脚的默认上拉和下拉状态。 + + 表中使用了以下缩写: + + - **WPU**:SoC 内部的弱上拉电阻 + - **WPD**:SoC 内部的弱下拉电阻 + - **PU**:位于乐鑫模组内部、SoC 外部的上拉电阻 + + .. list-table:: CMD 和 DATA 管脚的默认上拉和下拉状态 + :widths: 25 25 25 25 + :header-rows: 1 + + * - GPIO 编号 + - 管脚名 + - 启动状态 + - strapping 需求 + * - **15** + - CMD + - WPU + - + * - **2** + - DAT0 + - WPD + - 下载模式要求低电平 + * - **4** + - DAT1 + - WPD + - + * - **12** + - DAT2 + - 使用 1.8 V flash 时为 PU;3.3 V flash 时为 WPD + - 使用 1.8 V flash 时要求高电平;3.3 V flash 时要求低电平 + * - **13** + - DAT3 + - WPU + - + +.. only:: not esp32 + + .. _related_info_sdio: + + 相关信息 + -------- + + 内部上拉和 strapping 需求 + ^^^^^^^^^^^^^^^^^^^^^^^^^ + + 使用外部电阻始终是更优选择。乐鑫产品中的内部弱上拉和下拉电阻启用后可以代替外部电阻,但此解决方案并不能保证可靠的 SDIO 通信。 + + 通常不建议将 strapping 管脚重复用于 SDIO 功能。SD 和 strapping 管脚的上拉、下拉需求可能会相互冲突。有关 {IDF_TARGET} strapping 管脚的详细信息,请参阅技术规格书。 diff --git a/docs/zh_CN/api-reference/peripherals/sdm.rst b/docs/zh_CN/api-reference/peripherals/sdm.rst index 0547cd99c792..5230e67e1a48 100644 --- a/docs/zh_CN/api-reference/peripherals/sdm.rst +++ b/docs/zh_CN/api-reference/peripherals/sdm.rst @@ -42,7 +42,6 @@ Sigma-Delta 调制通道通常应用于以下场景: - :cpp:member:`sdm_config_t::clk_src` 选择 SDM 模块的时钟源。注意,所有通道选择的时钟源应保持一致。 - :cpp:member:`sdm_config_t::sample_rate_hz` 设置 SDM 模块的采样率。提高采样率可以提高输出信号的信噪比,更容易在后级通过滤波获取高精度的原始信号。 - :cpp:member:`sdm_config_t::invert_out` 设置是否反转输出信号。 -- :cpp:member:`sdm_config_t::io_loop_back` 通过 GPIO 矩阵外设,启用 GPIO 的输入和输出功能。注意,该字段仅供调试使用。 函数 :cpp:func:`sdm_new_channel` 可能因为各种原因失败,如内存不足、参数无效等。当缺少空闲通道(即所有的硬件 SDM 通道均在使用中)时,将返回 :c:macro:`ESP_ERR_NOT_FOUND`。 diff --git a/docs/zh_CN/api-reference/peripherals/spi_flash/index.rst b/docs/zh_CN/api-reference/peripherals/spi_flash/index.rst index 89e899569ebe..56632c71a08b 100644 --- a/docs/zh_CN/api-reference/peripherals/spi_flash/index.rst +++ b/docs/zh_CN/api-reference/peripherals/spi_flash/index.rst @@ -118,7 +118,7 @@ SPI flash 容量 SPI flash 容量由引导加载程序镜像头部(烧录偏移量为 0x1000)的一个字段进行配置。 -默认情况下,引导程序被写入 flash 时,``esptool.py`` 会自动检测 SPI flash 容量,同时使用正确容量更新引导程序的头部。也可以在工程配置中设置 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。 +默认情况下,引导加载程序被写入 flash 时,``esptool.py`` 会自动检测 SPI flash 容量,同时使用正确容量更新引导加载程序的头部。也可以在工程配置中设置 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。 如需在运行时覆盖已配置的 flash 容量,请配置 ``g_rom_flashchip`` 结构中的 ``chip_size``。``esp_flash_*`` 函数使用此容量(于软件和 ROM 中)进行边界检查。 diff --git a/docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_override_driver.rst b/docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_override_driver.rst index 24b3f5843b97..691d4c75129d 100644 --- a/docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_override_driver.rst +++ b/docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_override_driver.rst @@ -64,7 +64,7 @@ .get_chip_caps = spi_flash_chip_eon_get_caps, }; - - 也可以在示例 :example:`storage/custom_flash_driver` 中查看如何实现此功能。 + - 也可以在示例 :example:`storage/custom_flash_driver` 中查看如何实现此功能。该示例演示了如何覆盖默认芯片驱动列表。 4. 为 ``custom_chip_driver`` 组件编写一个新的 ``CMakeLists.txt`` 文件,其中包含额外的一行,添加了从 ``spi_flash`` 到 ``custom_chip_driver`` 的链接依赖项:: @@ -80,8 +80,3 @@ 5. ``linker.lf`` 用于在禁用缓存时,把要使用的每个芯片驱动程序都放入内部 RAM 中。详情请参阅 :doc:`/api-guides/linker-script-generation`。请确保此文件包含所有添加的源文件。 6. 构建你的项目,将会看到新的 flash 驱动程序已投入使用。 - -示例 ----- - -参考 :example:`storage/custom_flash_driver`。 diff --git a/docs/zh_CN/api-reference/peripherals/spi_master.rst b/docs/zh_CN/api-reference/peripherals/spi_master.rst index 9868ee66baef..764f7bc82a1a 100644 --- a/docs/zh_CN/api-reference/peripherals/spi_master.rst +++ b/docs/zh_CN/api-reference/peripherals/spi_master.rst @@ -305,6 +305,14 @@ SPI 总线传输事务由五个阶段构成,详见下表(任意阶段均可 若需连续发送专门的 SPI 传输事务以提高效率,可采用获取总线的方式。获取总线后,与其他设备间的传输事务(包括轮询传输事务或中断传输事务)将处于待处理状态,直到总线被释放。要获取和释放总线,请调用函数 :cpp:func:`spi_device_acquire_bus` 和 :cpp:func:`spi_device_release_bus`。 +.. only:: SOC_SPI_SUPPORT_SLEEP_RETENTION + + 睡眠保留 + ^^^^^^^^ + + {IDF_TARGET_NAME} 支持在进入 **Light Sleep** 之前保留 SPI 寄存器中的内容,并在唤醒后恢复。即程序不需要在 **Light Sleep** 唤醒后重新配置 SPI。 + + 该特性可以通过置位配置中的 :c:macro:`SPICOMMON_BUSFLAG_SLP_ALLOW_PD` 标志位启用。启用后驱动允许系统在 Light Sleep 时对 SPI 掉电,同时保存寄存器配置。它可以帮助降低轻度睡眠时的功耗,但需要花费一些额外的存储来保存寄存器的配置。 使用驱动程序 ----------------- diff --git a/docs/zh_CN/api-reference/peripherals/temp_sensor.rst b/docs/zh_CN/api-reference/peripherals/temp_sensor.rst index bffe7b669438..a53aace2fbd3 100644 --- a/docs/zh_CN/api-reference/peripherals/temp_sensor.rst +++ b/docs/zh_CN/api-reference/peripherals/temp_sensor.rst @@ -59,6 +59,7 @@ - :cpp:member:`range_min`:所测量温度范围的最小值。 - :cpp:member:`range_max`:所测量温度范围的最大值。 +- :cpp:member:`allow_pd` 配置驱动程序是否允许系统在睡眠模式下关闭外设电源。在进入睡眠之前,系统将备份温度传感器寄存器上下文,当系统退出睡眠模式时,这些上下文将被恢复。关闭外设可以节省更多功耗,但代价是消耗更多内存来保存寄存器上下文。你需要在功耗和内存消耗之间做权衡。此配置选项依赖于特定的硬件功能,如果在不支持的芯片上启用它,你将看到类似 ``not able to power down in light sleep`` 的错误消息。 设置好温度范围后,将配置结构体传递给 :cpp:func:`temperature_sensor_install`,该函数将创建温度传感器模块并返回句柄。 diff --git a/docs/zh_CN/api-reference/peripherals/twai.rst b/docs/zh_CN/api-reference/peripherals/twai.rst index b8c1af990a1b..4bd78d2fe12b 100644 --- a/docs/zh_CN/api-reference/peripherals/twai.rst +++ b/docs/zh_CN/api-reference/peripherals/twai.rst @@ -599,6 +599,14 @@ TWAI 驱动程序通过 :cpp:type:`twai_message_t` 结构体的不同位字段 **自测示例:** :example:`peripherals/twai/twai_self_test` 演示了节点如何使用 TWAI 驱动程序的无应答模式和自接收请求,向自身传输 TWAI 消息。此示例可用于测试目标芯片与外部收发器之间的连接是否正常。 +.. only:: SOC_TWAI_SUPPORT_SLEEP_RETENTION + + 睡眠保留 + ^^^^^^^^ + + {IDF_TARGET_NAME} 支持在进入 **Light Sleep** 之前保留 TWAI 寄存器中的内容,并在唤醒后恢复。即程序不需要在 **Light Sleep** 唤醒后重新配置 TWAI + + 该特性可以通过置位配置中的 :cpp:member:`twai_general_config_t::sleep_allow_pd` 标志位启用。启用后驱动允许系统在 Light Sleep 时对 TWAI 掉电,同时保存寄存器配置。它可以帮助降低轻度睡眠时的功耗,但需要花费一些额外的存储来保存寄存器的配置。 .. ---------------------------- API Reference ---------------------------------- diff --git a/docs/zh_CN/api-reference/protocols/esp_crt_bundle.rst b/docs/zh_CN/api-reference/protocols/esp_crt_bundle.rst index a08e012377e5..2fdb0d4c4ad5 100644 --- a/docs/zh_CN/api-reference/protocols/esp_crt_bundle.rst +++ b/docs/zh_CN/api-reference/protocols/esp_crt_bundle.rst @@ -16,7 +16,7 @@ ESP x509 证书包 API 提供了一种简便的方法,帮助你安装自定义 生成证书包时,你需选择: -* 来自 Mozilla 的完整根证书包,包含超过 130 份证书。目前提供的证书包更新于 2024 年 3 月 11 日,星期一,15:25:27 (GMT)。 +* 来自 Mozilla 的完整根证书包,包含超过 130 份证书。目前提供的证书包更新于 2024 年 9 月 24 日,星期二,03:12:04 (GMT)。 * 一组预先筛选的常用根证书。其中仅包含约 41 份证书,但根据 SSL 证书颁发机构统计数据,其绝对使用率约达到 90%,市场覆盖率约达 99%。 此外,还可指定证书文件的路径或包含证书的目录,将其他证书添加到生成的证书包中。 diff --git a/docs/zh_CN/api-reference/protocols/icmp_echo.rst b/docs/zh_CN/api-reference/protocols/icmp_echo.rst index 87dea76943a7..38bb987ac052 100644 --- a/docs/zh_CN/api-reference/protocols/icmp_echo.rst +++ b/docs/zh_CN/api-reference/protocols/icmp_echo.rst @@ -112,7 +112,7 @@ IoT 设备通常需要检查远程服务器是否可用。如果服务器离线 应用示例 ---------- -ICMP echo 示例: :example:`protocols/icmp_echo` +- :example:`protocols/icmp_echo` 演示了如何实现一个简单的 ping 命令行工具,使用 ICMP 回显请求数据包测试远程主机在 IP 网络上的可达性。 API 参考 -------------- diff --git a/docs/zh_CN/api-reference/protocols/mbedtls.rst b/docs/zh_CN/api-reference/protocols/mbedtls.rst index 976d039ac400..f109476f8685 100644 --- a/docs/zh_CN/api-reference/protocols/mbedtls.rst +++ b/docs/zh_CN/api-reference/protocols/mbedtls.rst @@ -9,7 +9,7 @@ Mbed TLS ESP-IDF 使用的 Mbed TLS `复刻仓库 `_ 中包含对原生 Mbed TLS 的补丁。这些补丁与某些模块的硬件例程有关,如 ``bignum (MPI)`` 和 ``ECC``。 -Mbed TLS 提供以下功能: +Mbed TLS 通过提供以下内容支持 TLS 1.2、TLS 1.3 和 DTLS 1.2 通信: - TCP/IP 通信功能:监听、连接、接收、读/写。 - SSL/TLS 通信功能:初始化、握手、读/写。 @@ -18,8 +18,9 @@ Mbed TLS 提供以下功能: - 哈希 - 加密/解密 -TLS 版本支持 SSL 3.0, TLS 1.0、TLS 1.1、TLS 1.2 和 TLS 1.3,但是最新的 ESP-IDF 上 Mbed TLS 已经移除了 SSL 3.0、TLS 1.0 和 TLS 1.1。DTLS 版本支持 DTLS 1.0、DTLS 1.1 和 DTLS 1.2,但最新的 ESP-IDF 上 Mbed TLS 已经移除了 DTLS 1.0。 +.. note:: + Mbed TLS v3.x.x 系列仅支持 TLS 1.2 和 TLS 1.3 协议。对 SSL 3.0、TLS 1.0/1.1 和 DTLS 1.0 的支持已被删除(弃用)。从 Mbed TLS v3.6.0 版本开始完全支持 TLS 1.3,在此版本之前,某些功能仍处于试验状态。有关更多详细信息,请参阅 :component_file:`Mbed TLS ChangeLog `。 Mbed TLS 文档 ------------------ @@ -73,11 +74,6 @@ ESP-IDF 中的示例使用 :doc:`/api-reference/protocols/esp_tls`,为访问 :SOC_MPI_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_MPI`: 支持硬件 MPI (bignum) 加速 :SOC_ECC_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_ECC`: 支持硬件 ECC 加速 -.. note:: - - Mbed TLS v3.0.0 及其更新版本仅支持 TLS 1.2 和 TLS 1.3,不支持 SSL 3.0、TLS 1.0、TLS 1.1、和 DTLS 1.0)。TLS 1.3 尚在试验阶段,仅支持客户端。要了解更多信息,请点击 `此处 `__。 - - 性能和内存调整 ------------------ @@ -122,5 +118,5 @@ ESP-IDF 中的示例使用 :doc:`/api-reference/protocols/esp_tls`,为访问 在 ``Component Config -> mbedTLS`` 中,有多个 Mbed TLS 功能默认为启用状态。如果不需要这些功能,可将其禁用以减小固件大小。要了解更多信息,请参考 :ref:`Minimizing Binary Size ` 文档。 -.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.4.1/ +.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.6.2/ .. _`Knowledge Base`: https://mbed-tls.readthedocs.io/en/latest/kb/ diff --git a/docs/zh_CN/api-reference/protocols/modbus.rst b/docs/zh_CN/api-reference/protocols/modbus.rst index 3d88cbcfba89..11234ae48437 100644 --- a/docs/zh_CN/api-reference/protocols/modbus.rst +++ b/docs/zh_CN/api-reference/protocols/modbus.rst @@ -19,10 +19,13 @@ ESP-Modbus 以下示例分别介绍了 ESP-Modbus 库的串行端口、TCP 端口的从机和主机实现。 -- :example:`protocols/modbus/serial/mb_slave` -- :example:`protocols/modbus/serial/mb_master` -- :example:`protocols/modbus/tcp/mb_tcp_slave` -- :example:`protocols/modbus/tcp/mb_tcp_master` +- :example:`protocols/modbus/serial/mb_slave` 演示了如何使用 {IDF_TARGET_NAME} 作为 Modbus 串行从设备,通过 esp-modbus 栈,使外部 Modbus 主机能够使用 Modbus 协议读取和写入设备参数。 + +- :example:`protocols/modbus/serial/mb_master` 演示了如何在 {IDF_TARGET_NAME} 上使用 esp-modbus 栈端口作为 Modbus 串行主设备,读取和写入 Modbus 网络中从设备的值。 + +- :example:`protocols/modbus/tcp/mb_tcp_slave` 演示了 esp-modbus TCP 从设备栈端口,允许外部 Modbus 主机通过 Modbus 协议读取和写入设备参数。 + +- :example:`protocols/modbus/tcp/mb_tcp_master` 演示了如何在 {IDF_TARGET_NAME} 上使用 esp-modbus 栈端口作为 Modbus TCP 主设备,读取和写入 Modbus 网络中从设备的值。 详情请参阅具体示例的 ``README.md`` 。 diff --git a/docs/zh_CN/api-reference/protocols/mqtt.rst b/docs/zh_CN/api-reference/protocols/mqtt.rst index 9365dfe850a7..7ad56ec21e23 100644 --- a/docs/zh_CN/api-reference/protocols/mqtt.rst +++ b/docs/zh_CN/api-reference/protocols/mqtt.rst @@ -21,14 +21,23 @@ ESP-MQTT 是 `MQTT `__ 协议客户端的实现,MQTT 是一 应用示例 ------------------- - * :example:`protocols/mqtt/tcp`:基于 TCP 的 MQTT,默认端口 1883 - * :example:`protocols/mqtt/ssl`:基于 TLS 的 MQTT,默认端口 8883 - * :example:`protocols/mqtt/ssl_ds`:基于 TLS 的 MQTT,使用数字签名外设进行身份验证,默认端口 8883 - * :example:`protocols/mqtt/ssl_mutual_auth`:基于 TLS 的 MQTT,使用证书进行身份验证,默认端口 8883 - * :example:`protocols/mqtt/ssl_psk`:基于 TLS 的 MQTT,使用预共享密钥进行身份验证,默认端口 8883 - * :example:`protocols/mqtt/ws`:基于 WebSocket 的 MQTT,默认端口 80 - * :example:`protocols/mqtt/wss`:基于 WebSocket Secure 的 MQTT,默认端口 443 - * :example:`protocols/mqtt5`: 使用 ESP-MQTT 库连接 MQTT v5.0 的服务器 + - :example:`protocols/mqtt/tcp` 演示了如何通过 TCP 实现 MQTT 通信(默认端口 1883)。 + + - :example:`protocols/mqtt/ssl` 演示了如何使用 SSL 传输来实现基于 TLS 的 MQTT 通信(默认端口 8883)。 + + - :example:`protocols/mqtt/ssl_ds` 演示了如何使用数字签名外设进行身份验证,以实现基于 TLS 的 MQTT 通信(默认端口 8883)。 + + - :example:`protocols/mqtt/ssl_mutual_auth` 演示了如何使用证书进行身份验证实现 MQTT 通信(默认端口 8883)。 + + - :example:`protocols/mqtt/ssl_psk` 演示了如何使用预共享密钥进行身份验证,以实现基于 TLS 的 MQTT 通信(默认端口 8883)。 + + - :example:`protocols/mqtt/ws` 演示了如何通过 WebSocket 实现 MQTT 通信(默认端口 80)。 + + - :example:`protocols/mqtt/wss` 演示了如何通过 WebSocket Secure 实现 MQTT 通信(默认端口 443)。 + + - :example:`protocols/mqtt5` 演示了如何使用 ESP-MQTT 库通过 MQTT v5.0 连接到代理。 + + - :example:`protocols/mqtt/custom_outbox` 演示了如何自定义 ESP-MQTT 库中的 outbox。 MQTT 消息重传 -------------------------- diff --git a/docs/zh_CN/api-reference/storage/fatfs.rst b/docs/zh_CN/api-reference/storage/fatfs.rst index 65f281bd790c..a5d7e6e8b2b2 100644 --- a/docs/zh_CN/api-reference/storage/fatfs.rst +++ b/docs/zh_CN/api-reference/storage/fatfs.rst @@ -99,7 +99,7 @@ FatFs 分区生成器 该生成器可以在主机上创建文件系统镜像,并用指定的主机文件夹内容对其进行填充。 -该脚本是建立在分区生成器的基础上 (:component_file:`fatfsgen.py`),目前除了可以生成分区外,也可以初始化磨损均衡。 +该脚本是建立在分区生成器的基础上 (:component_file:`fatfsgen.py`),目前除了可以生成分区外,也可以初始化损耗均衡。 目前的最新版本支持短文件名、长文件名、FAT12 和 FAT16。长文件名的上限是 255 个字符,文件名中可以包含多个 ``.`` 字符以及其他字符,如 ``+``、``,``、``;``、``=``、``[`` and ``]`` 等。 @@ -112,18 +112,18 @@ FatFs 分区生成器 fatfs_create_spiflash_image( [FLASH_IN_PROJECT]) -如果不希望在生成分区时使用磨损均衡,可以使用 ``fatfs_create_rawflash_image``:: +如果不希望在生成分区时使用损耗均衡,可以使用 ``fatfs_create_rawflash_image``:: fatfs_create_rawflash_image( [FLASH_IN_PROJECT]) ``fatfs_create_spiflash_image`` 以及 ``fatfs_create_rawflash_image`` 必须从项目的 CMakeLists.txt 中调用。 -如果决定使用 ``fatfs_create_rawflash_image`` (不支持磨损均衡),请注意它仅支持在设备中以只读模式安装。 +如果决定使用 ``fatfs_create_rawflash_image`` (不支持损耗均衡),请注意它仅支持在设备中以只读模式安装。 该函数的参数如下: -#. partition - 分区的名称,需要在分区表中定义(如 :example_file:`storage/fatfsgen/partitions_example.csv`)。 +#. partition - 分区的名称,需要在分区表中定义(如 :example_file:`storage/fatfs/fatfsgen/partitions_example.csv`)。 #. base_dir - 目录名称,该目录会被编码为 FatFs 分区,也可以选择将其被烧录进设备。但注意必须在分区表中指定合适的分区大小。 @@ -139,7 +139,8 @@ FatFs 分区生成器 没有指定 FLASH_IN_PROJECT 时也可以生成分区镜像,但是用户需要使用 ``esptool.py`` 或自定义的构建系统目标对其手动烧录。 -相关示例请查看 :example:`storage/fatfsgen`。 +相关示例请查看 :example:`storage/fatfs/fatfsgen`。 + .. _fatfs-partition-analyzer: @@ -156,6 +157,40 @@ FatFs 分区分析器 生成文件夹结构之前,参数 --verbose 将根据 FatFs 镜像的引导扇区在终端打印详细信息。 +FATFS 最小分区大小及限制 +------------------------ + +FATFS 组件支持 FAT12、FAT16 和 FAT32 文件系统类型。文件系统类型取决于卷上簇的数量(簇数通过数据扇区数量除以每簇包含的扇区数计算得出)。最小分区大小由分配给 FAT 表、根目录和数据簇的扇区数量决定。 + +* 对于 4096 字节的扇区,启用损耗均衡的 FAT 分区大小最小支持 32 KB。对于 512 字节的扇区,最小分区大小取决于损耗均衡的配置:性能模式下,最小支持 20 KB,安全模式下最小支持 28 KB(需要额外的 2 个扇区)。 +* 启用了损耗均衡的分区会预留 4 个扇区用于损耗均衡操作。此外,FATFS 本身也会使用 4 个扇区,分别为 1 个保留扇区、1 个 FAT 扇区、1 个根目录扇区和 1 个数据扇区。 +* 增加分区大小将分配更多的数据扇区,提供更大的存储空间。 +* 对小于 528 KB 的分区,将分配 1 个根目录扇区;对于更大的分区,将分配 4 个根目录扇区。 +* 默认会创建两个 FAT 扇区,因此分区大小会增加一个扇区来容纳这个额外的 FAT 扇区。如要启用单个 FAT 扇区,可以在 `struct esp_vfs_fat_mount_config_t` 中(参见 :component_file:`fatfs/vfs/esp_vfs_fat.h`)设置 `use_one_fat` 选项。启用此选项后,最小分区大小可减少至 32 KB。 +* 计算损耗均衡分区大小的一般公式为:: + + partition_size = 损耗均衡扇区数 * FLASH_SEC_SIZE + FATFS 分区扇区数量 * FAT_SEC_SIZE + + 其中: + + - 损耗均衡扇区数固定为 4 个 + - FLASH_SEC_SIZE 为 4096 字节 + - FATFS 分区扇区包括:1 个保留扇区 + FAT 扇区 + 根目录扇区 + 数据扇区 + - FAT_SEC_SIZE 根据不同的配置,可以是 512 字节或 4096 字节 + +* 对于未启用损耗均衡、扇区大小为 512 字节的只读分区,最小分区大小可减少至 2 KB。 + +更多详情请参考 :doc:`文件系统注意事项 <../../api-guides/file-system-considerations>`。 + +应用示例 +----------------- + +- :example:`storage/fatfs/getting_started` 演示了如何使用 FatFS 在 SPI flash 上存储永久数据的基本设置,包括挂载文件系统、打开文件、执行基本的读写操作以及卸载文件系统。 + +- :example:`storage/fatfs/fs_operations` 演示了更全面的 FatFS 操作,包括读取和写入文件、创建、移动和删除文件及目录,以及检查文件详细信息。 + +- :example:`storage/fatfs/ext_flash` 演示了如何操作使用 FatFS 格式化的外部 SPI flash,包括初始化 SPI 总线、配置 flash、将其注册为分区以及执行读写操作。 + 高级 API 参考 ------------------------ diff --git a/docs/zh_CN/api-reference/storage/fatfsgen.rst b/docs/zh_CN/api-reference/storage/fatfsgen.rst index af83bcba2952..e45b21c765a3 100644 --- a/docs/zh_CN/api-reference/storage/fatfsgen.rst +++ b/docs/zh_CN/api-reference/storage/fatfsgen.rst @@ -219,3 +219,8 @@ FAT 文件系统中的日期和时间 ESP-IDF 使用的 FAT 文件系统协议不保留芯片介质上的日期或时间,因此,从设备中提取的所有映像都具有相同的默认时间戳,这个时间戳会应用到所有 FAT 相关的日期和时间字段上,包括创建、最后修改时间戳,以及创建、最后修改和最后访问日期。 SFN 条目中有几个描述时间的字段,如 **DIR_CrtTime** 和 **DIR_WrtTime**。ESP-IDF 的 FAT 实现过程会忽略一些字段(参见文件 ``entry.py``),然而 **DIR_WrtTime** 和 **DIR_WrtDate** 字段的更改会保留在芯片中。时间和数据条目都是 16 位的,其中时间粒度为 2 秒。 + +应用示例 +--------------- + +- :example:`storage/fatfs/fatfsgen` 演示了如何在构建过程中使用 FatFS 分区生成工具从主机文件夹自动创建 FatFS 镜像。 diff --git a/docs/zh_CN/api-reference/storage/index.rst b/docs/zh_CN/api-reference/storage/index.rst index 0687d98c054e..3b71db1be00f 100644 --- a/docs/zh_CN/api-reference/storage/index.rst +++ b/docs/zh_CN/api-reference/storage/index.rst @@ -37,44 +37,76 @@ wear-levelling storage-security.rst +示例 +---- + .. list-table:: 存储 API 相关例程 :widths: 25 75 :header-rows: 0 * - **例程** - **描述** - * - :doc:`fatfs` - - - * - :example:`wear_leveling ` - - 演示了如何在内部 flash 上使用 FATFS 磨损均衡。 - * - :example:`ext_flash_fatfs ` - - 演示了如何在外部 flash 上使用 FATFS 磨损均衡。 - * - :example:`fatfsgen ` - - 演示了在主机计算机上使用 Python 工具生成 FATFS 镜像的功能。 - * - :doc:`nvs_flash` - - * - :example:`nvs_rw_blob ` - 演示了如何在 NVS flash 中使用 C 语言 API 读写 blob 数据类型。 * - :example:`nvs_rw_value ` - 演示了如何在 NVS flash 中使用 C 语言 API 读写整数数据类型。 - * - :example:`nvs_rw_value_cxx ` + * - :example:`nvs_rw_value ` - 演示了如何在 NVS flash 中使用 C++ 语言 API 读写整数数据类型。 * - :example:`nvsgen ` - 演示了如何使用基于 Python 的 NVS 镜像生成工具,根据 CSV 文件内容创建 NVS 分区镜像。 - * - :doc:`spiffs` - - + +.. list-table:: 常用文件系统 API + :widths: 25 75 + :header-rows: 0 + + * - **代码示例** + - **描述** + * - :example:`fatfs/getting_started ` + - 演示了如何使用 FATFS 库在内部 flash 上应用标准文件 API (stdio.h)。 + * - :example:`fatfs/fs_operations ` + - 演示了如何使用 POSIX API 进行文件系统操作,如移动、删除和重命名文件等。 + +.. list-table:: FATFS API 示例 + :widths: 25 75 + :header-rows: 0 + + * - **代码示例** + - **描述** + * - :example:`fatfsgen ` + - 演示了在主机上使用 Python 工具生成 FATFS 镜像的相关功能。 + * - :example:`ext_flash_fatfs ` + - 演示了在外部 flash 上使用带有磨损均衡功能的 FATFS。 + * - :example:`wear_leveling ` + - 演示了在内部 flash 上使用带有磨损均衡功能的 FATFS。 + +.. list-table:: SPIFFS API 示例 + :widths: 25 75 + :header-rows: 0 + + * - **代码示例** + - **描述** * - :example:`spiffs ` - 演示了如何使用 SPIFFS API 初始化文件系统,并使用 POSIX 函数处理文件。 * - :example:`spiffsgen ` - 演示了在主机计算机上使用 Python 工具生成 SPIFFS 镜像的功能。 - * - :doc:`partition` - - + +.. list-table:: 分区 API 示例 + :widths: 25 75 + :header-rows: 0 + + * - **代码示例** + - **描述** * - :example:`partition_api ` - 介绍了用于查找特定分区、执行基本 I/O 操作以及通过 CPU 内存映射使用分区的 API 函数。 * - :example:`parttool ` - 演示了在主机计算机上使用 Python 工具生成分区镜像的功能。 - * - :doc:`vfs` - - + +.. list-table:: VFS 相关示例 + :widths: 25 75 + :header-rows: 0 + + * - **代码示例** + - **描述** * - :example:`littlefs ` - 演示了如何使用 LittleFS 组件初始化文件系统,并使用 POSIX 函数处理文件。 * - :example:`semihost_vfs ` diff --git a/docs/zh_CN/api-reference/storage/nvs_encryption.rst b/docs/zh_CN/api-reference/storage/nvs_encryption.rst index f0565d02de4e..13c3bb59d308 100644 --- a/docs/zh_CN/api-reference/storage/nvs_encryption.rst +++ b/docs/zh_CN/api-reference/storage/nvs_encryption.rst @@ -98,7 +98,7 @@ NVS 密钥分区 # "Active security features detected, erasing flash is disabled as a safety measure. Use --force to override ..." parttool.py --esptool-erase-args=force --esptool-write-args encrypt --port PORT --partition-table-file=PARTITION_TABLE_FILE --partition-table-offset PARTITION_TABLE_OFFSET write_partition --partition-name="name of nvs_key partition" --input NVS_KEY_PARTITION_FILE -由于密钥分区被标记为 ``encrypted``,且 :doc:`../../security/flash-encryption` 已启用,引导程序会在首次启动时使用 flash 加密密钥对此分区进行加密。 +由于密钥分区被标记为 ``encrypted``,且 :doc:`../../security/flash-encryption` 已启用,引导加载程序会在首次启动时使用 flash 加密密钥对此分区进行加密。 一个应用程序可以使用不同的密钥对不同的 NVS 分区进行加密,从而拥有多个密钥分区。应用程序应为加密或解密操作提供正确的密钥分区和密钥信息。 diff --git a/docs/zh_CN/api-reference/storage/partition.rst b/docs/zh_CN/api-reference/storage/partition.rst index 4a1a4a6269dc..eafe918215eb 100644 --- a/docs/zh_CN/api-reference/storage/partition.rst +++ b/docs/zh_CN/api-reference/storage/partition.rst @@ -13,7 +13,7 @@ 分区表 API ------------------- -ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序、各种应用程序二进制文件、数据及文件系统等。请参阅 :doc:`/api-guides/partition-tables`,查看详细信息。 +ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导加载程序、各种应用程序二进制文件、数据及文件系统等。请参阅 :doc:`/api-guides/partition-tables`,查看详细信息。 该组件在 ``esp_partition.h`` 中声明了一些 API 函数,用以枚举在分区表中找到的分区,并对这些分区执行操作: @@ -24,9 +24,19 @@ ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序 - :cpp:func:`esp_partition_find_first`:返回描述 :cpp:func:`esp_partition_find` 中找到的第一个分区的结构; - :cpp:func:`esp_partition_read`、:cpp:func:`esp_partition_write` 和 :cpp:func:`esp_partition_erase_range` 等同于 :cpp:func:`esp_flash_read`、:cpp:func:`esp_flash_write` 和 :cpp:func:`esp_flash_erase_region`,但在分区边界内执行。 +应用示例 +------------- -另请参考 ------------- +- :example:`storage/partition_api/partition_ops` 演示了如何对分区表执行读、写和擦除操作。 + +- :example:`storage/parttool` 演示了如何使用分区工具执行读、写、擦除分区、检索分区信息和转储整个分区表等操作。 + +- :example:`storage/partition_api/partition_find` 演示了如何搜索分区表,并根据分区类型、子类型和标签/名称等约束条件返回匹配的分区。 + +- :example:`storage/partition_api/partition_mmap` 演示了如何配置 MMU,将分区映射到内存地址空间以进行读操作,并验证写入和读取的数据。 + +其他资源 +------------- - :doc:`../../api-guides/partition-tables` - :doc:`../system/ota` 提供了高层 API 用于更新存储在 flash 中的 app 固件。 diff --git a/docs/zh_CN/api-reference/storage/sdmmc.rst b/docs/zh_CN/api-reference/storage/sdmmc.rst index e870f7e95303..fa23ff479ae2 100644 --- a/docs/zh_CN/api-reference/storage/sdmmc.rst +++ b/docs/zh_CN/api-reference/storage/sdmmc.rst @@ -32,7 +32,13 @@ SD/SDIO/MMC 驱动支持 SD 存储器、SDIO 卡和 eMMC 芯片。这是一个 应用示例 ------------------- -ESP-IDF :example:`storage/sd_card` 目录下提供了 SDMMC 驱动与 FatFs 库组合使用的示例,演示了先初始化卡,然后使用 POSIX 和 C 库 API 向卡读写数据。请参考示例目录下 README.md 文件,查看更多详细信息。 +.. list:: + + :SOC_SDMMC_HOST_SUPPORTED: - :example:`storage/sd_card/sdmmc` 演示了如何通过 SDMMC 接口操作使用 FatFS 文件系统格式化的 SD 卡。 + + :SOC_SDMMC_HOST_SUPPORTED: - :example:`storage/emmc` 演示了如何通过 SDMMC 接口操作使用 FatFS 文件系统格式化的 eMMC 芯片。 + + :SOC_GPSPI_SUPPORTED: - :example:`storage/sd_card/sdspi` 演示了如何通过 SPI 接口操作使用 FatFS 文件系统格式化的 SD 卡。 协议层 API ------------------ diff --git a/docs/zh_CN/api-reference/storage/spiffs.rst b/docs/zh_CN/api-reference/storage/spiffs.rst index 76a61ef9deaf..da68b7a6703d 100644 --- a/docs/zh_CN/api-reference/storage/spiffs.rst +++ b/docs/zh_CN/api-reference/storage/spiffs.rst @@ -65,7 +65,7 @@ SPIFFS 是一个用于 SPI NOR flash 设备的嵌入式文件系统,支持磨 spiffs_create_partition_image(my_spiffs_partition my_folder DEPENDS dep) -请参考 :example:`storage/spiffsgen`,查看示例。 +请参考 :example:`storage/spiffsgen`,查看示例。该示例演示了如何使用 SPIFFS 镜像生成工具在构建过程中自动从主机文件夹创建 SPIFFS 镜像。 ``mkspiffs`` ^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-reference/storage/vfs.rst b/docs/zh_CN/api-reference/storage/vfs.rst index ff633c189c13..cdd0a7a0a7e6 100644 --- a/docs/zh_CN/api-reference/storage/vfs.rst +++ b/docs/zh_CN/api-reference/storage/vfs.rst @@ -39,34 +39,34 @@ VFS 组件支持 C 库函数(如 fopen 和 fprintf 等)与文件系统 (FS) ssize_t myfs_write(int fd, const void * data, size_t size); - // In definition of esp_vfs_t: + // 在 esp_vfs_t 的定义中: .flags = ESP_VFS_FLAG_DEFAULT, .write = &myfs_write, - // ... other members initialized + // ... 其他成员已初始化 - // When registering FS, context pointer (third argument) is NULL: + // 注册文件系统时,上下文指针(第三个参数)为 NULL: ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL)); 示例 2:声明 API 函数时需要一个额外的上下文指针作为参数,即可支持多个 FS 驱动程序实例,此时使用 ``write_p`` :: ssize_t myfs_write(myfs_t* fs, int fd, const void * data, size_t size); - // In definition of esp_vfs_t: + // 在 esp_vfs_t 的定义中: .flags = ESP_VFS_FLAG_CONTEXT_PTR, .write_p = &myfs_write, - // ... other members initialized + // ... 其他成员已初始化 - // When registering FS, pass the FS context pointer into the third argument - // (hypothetical myfs_mount function is used for illustrative purposes) + // 注册文件系统时,将文件系统上下文指针传递给第三个参数 + // (使用假设的 myfs_mount 函数进行示例说明) myfs_t* myfs_inst1 = myfs_mount(partition1->offset, partition1->size); ESP_ERROR_CHECK(esp_vfs_register("/data1", &myfs, myfs_inst1)); - // Can register another instance: + // 可以注册另一个实例: myfs_t* myfs_inst2 = myfs_mount(partition2->offset, partition2->size); ESP_ERROR_CHECK(esp_vfs_register("/data2", &myfs, myfs_inst2)); 同步输入/输出多路复用 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^ VFS 组件支持通过 :cpp:func:`select` 进行同步输入/输出多路复用,其实现方式如下: @@ -91,16 +91,17 @@ VFS 组件支持通过 :cpp:func:`select` 进行同步输入/输出多路复用 :: - // In definition of esp_vfs_t: + // 在 esp_vfs_t 的定义中: .start_select = &uart_start_select, .end_select = &uart_end_select, - // ... other members initialized + // ... 其他成员已初始化 调用 :cpp:func:`start_select` 函数可以设置环境,检测指定 VFS 驱动的文件描述符读取/写入/错误条件。 调用 :cpp:func:`end_select` 函数可以终止/取消初始化/释放由 :cpp:func:`start_select` 设置的环境。 .. note:: + 在少数情况下,在调用 :cpp:func:`end_select` 之前可能并没有调用过 :cpp:func:`start_select`。因此 :cpp:func:`end_select` 的实现必须在该情况下返回错误而不能崩溃。 如需获取更多信息,请参考 :component_file:`esp_driver_uart/src/uart_vfs.c` 中 UART 外设的 VFS 驱动,尤其是函数 :cpp:func:`uart_vfs_dev_register`、:cpp:func:`uart_start_select` 和 :cpp:func:`uart_end_select`。 @@ -122,12 +123,12 @@ VFS 组件支持通过 :cpp:func:`select` 进行同步输入/输出多路复用 :: - // In definition of esp_vfs_t: + // 在 esp_vfs_t 的定义中: .socket_select = &lwip_select, .get_socket_select_semaphore = &lwip_get_socket_select_semaphore, .stop_socket_select = &lwip_stop_socket_select, .stop_socket_select_isr = &lwip_stop_socket_select_isr, - // ... other members initialized + // ... 其他成员已初始化 函数 :cpp:func:`socket_select` 是套接字驱动对 :cpp:func:`select` 的内部实现。该函数只对套接字 VFS 驱动的文件描述符起作用。 @@ -142,6 +143,7 @@ VFS 组件支持通过 :cpp:func:`select` 进行同步输入/输出多路复用 .. note:: 如果 :cpp:func:`select` 用于套接字文件描述符,可以禁用 :ref:`CONFIG_VFS_SUPPORT_SELECT` 选项来减少代码量,提高性能。 + 不要在 :cpp:func:`select` 调用过程中更改套接字驱动,否则会出现一些未定义行为。 路径 @@ -192,6 +194,17 @@ VFS 对文件路径长度没有限制,但文件系统路径前缀受 ``ESP_VFS 注意,用 ``EFD_SUPPORT_ISR`` 创建 eventfd 将导致在读取、写入文件时,以及在设置这个文件的 ``select()`` 开始和结束时,暂时禁用中断。 + +精简版 VFS +------------ + +为尽量减少 RAM 使用,提供了另一版本的 :cpp:func:`esp_vfs_register` 函数,即 :cpp:func:`esp_vfs_register_fs`。这个版本的函数接受 :cpp:class:`esp_vfs_fs_ops_t` 而不是 :cpp:class:`esp_vfs_t`,并且还接受按位或 (OR-ed) 的标志参数。与 :cpp:func:`esp_vfs_register` 函数不同,只要在调用时提供 ``ESP_VFS_FLAG_STATIC`` 标志,该函数就可以处理静态分配的结构体。 + +:cpp:class:`esp_vfs_fs_ops_t` 根据功能(如,目录操作、选择支持、termios 支持等)被拆分为不同的结构体。主结构体包含基本功能,如 ``read``、``write`` 等,并包含指向特定功能结构体的指针。这些指针可以设置为 ``NULL``,表示不支持该结构体中提供的所有功能,从而减少所需内存。 + +在内部,VFS 组件使用的是该版本的 API,并在注册时通过额外步骤将 :cpp:class:`esp_vfs_t` 转换为 :cpp:class:`esp_vfs_fs_ops_t`。 + + 常用 VFS 设备 ------------- @@ -208,11 +221,15 @@ IDF 定义了多个可供应用程序使用的 VFS 设备。这些设备包括 - :example:`system/select` 演示了如何使用 ``select()`` 函数进行同步 I/O 多路复用,使用 UART 和套接字文件描述符,并将二者配置为回环模式,以接收来自其他任务发送的消息。 +- :example:`storage/semihost_vfs` 演示了如何使用半托管 VFS 驱动程序,包括注册主机目录、将 UART 的 stdout 重定向到主机上的文件,并读取和打印文本文件的内容。 + API 参考 ------------- .. include-build-file:: inc/esp_vfs.inc +.. include-build-file:: inc/esp_vfs_ops.inc + .. include-build-file:: inc/esp_vfs_dev.inc .. include-build-file:: inc/uart_vfs.inc diff --git a/docs/zh_CN/api-reference/storage/wear-levelling.rst b/docs/zh_CN/api-reference/storage/wear-levelling.rst index 830bcc077ece..68a22aa6fbfb 100644 --- a/docs/zh_CN/api-reference/storage/wear-levelling.rst +++ b/docs/zh_CN/api-reference/storage/wear-levelling.rst @@ -9,7 +9,7 @@ 应用示例 ------------------- -:example:`storage/wear_levelling` 中提供了一款磨损均衡驱动与 FatFs 库结合使用的示例。该示例初始化磨损均衡驱动,挂载 FAT 文件系统分区,并使用 POSIX(可移植操作系统接口)和 C 库 API 从中写入和读取数据。如需了解更多信息,请参考 :example_file:`storage/wear_levelling/README.md`。 +:example:`storage/wear_levelling` 演示了如何使用磨损均衡库和 FatFS 库在分区中存储文件,并使用 POSIX 和 C 库 API 从中写入和读取数据。 高级 API 参考 ------------------------ diff --git a/docs/zh_CN/api-reference/system/chip_revision.rst b/docs/zh_CN/api-reference/system/chip_revision.rst index 0c584539e347..c700d56946b3 100644 --- a/docs/zh_CN/api-reference/system/chip_revision.rst +++ b/docs/zh_CN/api-reference/system/chip_revision.rst @@ -110,7 +110,7 @@ EFuse 块版本号与芯片版本号类似,但是它主要影响在 eFuse 中 故障排除 ^^^^^^^^^^^^^^^ -1. 如果第二阶段引导加载程序所运行的芯片版本低于镜像(如软件镜像)中指定的最小版本,会发生重启并显示以下消息: +1. 如果二级引导加载程序所运行的芯片版本低于镜像(如软件镜像)中指定的最小版本,会发生重启并显示以下消息: .. code-block:: none @@ -132,13 +132,13 @@ EFuse 块版本号与芯片版本号类似,但是它主要影响在 eFuse 中 二进制镜像的常见版本需求 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -芯片版本号检查主要根据二级引导程序和应用程序二进制镜像中包含的 :cpp:type:`esp_image_header_t` 标头,其中记录了可以运行该软件的芯片版本号。这一标头有 3 个与版本相关的字段: +芯片版本号检查主要根据二级引导加载程序和应用程序二进制镜像中包含的 :cpp:type:`esp_image_header_t` 标头,其中记录了可以运行该软件的芯片版本号。这一标头有 3 个与版本相关的字段: - ``min_chip_rev`` - 镜像所需芯片的最小主版本号(但对于 ESP32-C3,该字段指次版本号)。其值由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 确定。 - ``min_chip_rev_full`` - 镜像所需芯片的最小版本号,格式为 ``major * 100 + minor``。其值由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 确定。 - ``max_chip_rev_full`` - 镜像所需芯片的最大版本号,格式为 ``major * 100 + minor``。其值由 ``CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MAX_FULL`` 确定。用户无法对其进行修改,仅当 ESP-IDF 支持新版本时由乐鑫官方进行更改。 -而 eFuse 块版本的要求则存储在 :cpp:type:`esp_app_desc_t` 结构体中。该结构体对象位于应用程序的二进制进项文件中。由于 eFuse 块版本信息主要影响 ADC 校准,而二级引导程序的镜像不涉及 ADC,因此我们只需要检查应用程序镜像的 eFuse 块版本信息。有 2 个与 eFuse 块版本相关的字段: +而 eFuse 块版本的要求则存储在 :cpp:type:`esp_app_desc_t` 结构体中。该结构体对象位于应用程序的二进制进项文件中。由于 eFuse 块版本信息主要影响 ADC 校准,而二级引导加载程序的镜像不涉及 ADC,因此我们只需要检查应用程序镜像的 eFuse 块版本信息。有 2 个与 eFuse 块版本相关的字段: - ``min_efuse_blk_rev_full`` - 镜像所需 eFuse 块的最小版本号,格式为 ``major * 100 + minor``。其值由 ``CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL`` 确定。 - ``max_efuse_blk_rev_full`` - 镜像所需 eFuse 块的最大版本号,格式为 ``major * 100 + minor``。其值由 ``CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL`` 确定。它反映了当前 ESP-IDF 版本能支持的最大 eFuse 块版本号,不应由用户修改。 @@ -148,36 +148,36 @@ EFuse 块版本号与芯片版本号类似,但是它主要影响在 eFuse 中 应用启动过程中,检查最小和最大版本的顺序如下: -1. 在运行第 2 阶段引导启动程序前,第 1 阶段引导启动程序(ROM 引导启动程序)不会在 :cpp:type:`esp_image_header_t` 中检查最小和最大版本字段。 +1. 在运行二级引导加载程序前,一级 (ROM) 引导加载程序不会在 :cpp:type:`esp_image_header_t` 中检查最小和最大版本字段。 -2. 在第 2 阶段引导启动程序的初始化阶段,会检查引导程序自身是否可以在此版本的芯片上启动。它从引导启动程序镜像的标头中读取最小版本,并与 eFuse 中的芯片版本进行比较。如果芯片版本低于最小版本,引导启动程序会拒绝启动并中止运行。此阶段不检查最大版本。 +2. 在二级引导加载程序的初始化阶段,会检查引导加载程序自身是否可以在此版本的芯片上启动。它从引导加载程序镜像的标头中读取最小版本,并与 eFuse 中的芯片版本进行比较。如果芯片版本低于最小版本,引导加载程序会拒绝启动并中止运行。此阶段不检查最大版本。 -3. 然后,第 2 阶段引导启动程序会检查应用程序的版本要求。它从应用程序镜像的标头中读取支持的芯片最小和最大版本,以及从段的标头中读取 eFuse 块版本信息,并与 eFuse 中的芯片版本进行比较。如果该芯片版本或 eFuse 块版本低于各自的最小版本或高于最大版本,引导程序会拒绝启动并中止。然而,如果设置了忽略最大版本位,则可以忽略最大版本限制。软件确定可以使用此芯片版本时,用户可以自行设置忽略位。 +3. 然后,二级引导加载程序会检查应用程序的版本要求。它从应用程序镜像的标头中读取支持的芯片最小和最大版本,以及从段的标头中读取 eFuse 块版本信息,并与 eFuse 中的芯片版本进行比较。如果该芯片版本或 eFuse 块版本低于各自的最小版本或高于最大版本,引导加载程序会拒绝启动并中止。然而,如果设置了忽略最大版本位,则可以忽略最大版本限制。软件确定可以使用此芯片版本时,用户可以自行设置忽略位。 -4. 在空中升级 (OTA) 阶段,运行中的应用程序会检查新软件是否与芯片版本及 eFuse 块版本相匹配。它会从新应用程序镜像的标头中提取最小和最大芯片版本,以及应用程序描述中提取最大和最小 eFuse 块版本,并与 eFuse 中的芯片版本和块版本进行比较。应用程序检查版本匹配的方式与引导启动程序相同,即芯片版本和 eFuse 块版本须处在最小和最大版本之间(忽略最大版本的逻辑也相同)。 +4. 在空中升级 (OTA) 阶段,运行中的应用程序会检查新软件是否与芯片版本及 eFuse 块版本相匹配。它会从新应用程序镜像的标头中提取最小和最大芯片版本,以及应用程序描述中提取最大和最小 eFuse 块版本,并与 eFuse 中的芯片版本和块版本进行比较。应用程序检查版本匹配的方式与引导加载程序相同,即芯片版本和 eFuse 块版本须处在最小和最大版本之间(忽略最大版本的逻辑也相同)。 -向后兼容旧版 ESP-IDF 构建的引导启动程序 +向后兼容旧版 ESP-IDF 构建的引导加载程序 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. only:: esp32 or esp32c3 or esp32s2 or esp32s3 - 主要版本号和次版本号的 eFuse 位对于旧版引导启动程序(由早于 v5.0 版本的 ESP-IDF 进行构建)而言是未知的。旧版启动引导程序只使用一个 eFuse 位来表示芯片版本。 + 主要版本号和次版本号的 eFuse 位对于旧版引导加载程序(由早于 v5.0 版本的 ESP-IDF 进行构建)而言是未知的。旧版引导加载程序只使用一个 eFuse 位来表示芯片版本。 .. only:: esp32 - 旧版引导启动程序不读取次版本号的 eFuse 位,且主版本号只能低于或等于 v3。这表明,旧版引导启动程序只能正确检测范围在 ``v0.0`` 至 ``v3.0`` 的芯片版本,其中,次版本号总是设置为 ``0``。 + 旧版引导加载程序不读取次版本号的 eFuse 位,且主版本号只能低于或等于 v3。这表明,旧版引导加载程序只能正确检测范围在 ``v0.0`` 至 ``v3.0`` 的芯片版本,其中,次版本号总是设置为 ``0``。 .. only:: esp32c2 - ESP-IDF v5.0 中添加了对 {IDF_TARGET_NAME} 芯片的支持。引导启动程序能够检测范围在 ``v0.0`` 至 ``v3.15`` 内的所有芯片版本。 + ESP-IDF v5.0 中添加了对 {IDF_TARGET_NAME} 芯片的支持。引导加载程序能够检测范围在 ``v0.0`` 至 ``v3.15`` 内的所有芯片版本。 .. only:: esp32c3 - 在 ESP-IDF v4.3 中添加了对 {IDF_TARGET_NAME} 芯片的支持。旧版引导启动程序无法读取晶圆版本 eFuse 的所有位,只能读取前 3 个最低有效位。因此,旧版引导启动程序无法正确检测芯片版本。具体而言,只能正确检测 ``v0.0`` 至 ``v0.8`` 范围内的芯片版本,其他芯片版本则会被错误识别为该范围内的某个版本。 + 在 ESP-IDF v4.3 中添加了对 {IDF_TARGET_NAME} 芯片的支持。旧版引导加载程序无法读取晶圆版本 eFuse 的所有位,只能读取前 3 个最低有效位。因此,旧版引导加载程序无法正确检测芯片版本。具体而言,只能正确检测 ``v0.0`` 至 ``v0.8`` 范围内的芯片版本,其他芯片版本则会被错误识别为该范围内的某个版本。 .. only:: esp32s2 or esp32s3 - 在 ESP-IDF v4.2 中添加了对 {IDF_TARGET_NAME} 芯片的支持。 由于 ``Minimum Supported ESP32-S2 Revision`` Kconfig 选项未引入,{IDF_TARGET_NAME} 芯片在 :cpp:type:`esp_image_header_t` 头文件中将 ``rev_min`` 设置为 0。这表明旧版引导启动程序不会检查芯片版本。在 v0.0 至 v3.15 范围内,任何应用程序都可以通过此类引导加载程序加载。 + 在 ESP-IDF v4.2 中添加了对 {IDF_TARGET_NAME} 芯片的支持。 由于 ``Minimum Supported ESP32-S2 Revision`` Kconfig 选项未引入,{IDF_TARGET_NAME} 芯片在 :cpp:type:`esp_image_header_t` 头文件中将 ``rev_min`` 设置为 0。这表明旧版引导加载程序不会检查芯片版本。在 v0.0 至 v3.15 范围内,任何应用程序都可以通过此类引导加载程序加载。 请使用 ``esptool chip_id`` 命令查看芯片版本。 diff --git a/docs/zh_CN/api-reference/system/efuse.rst b/docs/zh_CN/api-reference/system/efuse.rst index 941e3472c263..c3b4bd624f47 100644 --- a/docs/zh_CN/api-reference/system/efuse.rst +++ b/docs/zh_CN/api-reference/system/efuse.rst @@ -555,7 +555,7 @@ flash 加密测试 flash 加密是一项硬件功能,需要物理烧录 eFuse ``key`` 和 ``FLASH_CRYPT_CNT``。如果 flash 加密实际未启用,那么启用 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项只是提供了测试的可能性,而不会加密 flash 中的任何内容,即使日志中显示了加密操作。 -为此,可使用 :cpp:func:`bootloader_flash_write` 函数。但是,如果运行应用程序时芯片已启用 flash 加密,或者以 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项创建了启动加载程序,则 flash 加密/解密操作会正常进行。这意味着数据写入加密 flash 分区时被加密,从加密分区读取时被解密。 +为此,可使用 :cpp:func:`bootloader_flash_write` 函数。但是,如果运行应用程序时芯片已启用 flash 加密,或者以 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项创建了引导加载程序,则 flash 加密/解密操作会正常进行。这意味着数据写入加密 flash 分区时被加密,从加密分区读取时被解密。 ``espefuse.py`` ^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-reference/system/mem_alloc.rst b/docs/zh_CN/api-reference/system/mem_alloc.rst index 12fef6b8f119..ed203af3abd9 100644 --- a/docs/zh_CN/api-reference/system/mem_alloc.rst +++ b/docs/zh_CN/api-reference/system/mem_alloc.rst @@ -105,7 +105,7 @@ DMA 存储器 使用 ``MALLOC_CAP_DMA`` 标志分配适合与硬件 DMA 引擎(如 SPI 和 I2S)配合使用的内存,此属性标志不包括外部 PSRAM。 -.. only SOC_SPIRAM_SUPPORTED and not esp32:: +.. only:: SOC_SPIRAM_SUPPORTED and not esp32 EDMA 硬件功能可以将 DMA buffer 放置在外部 PSRAM,但可能存在一定的对齐限制,详情请参阅 {IDF_TARGET_NAME} 技术参考手册。若要分配一个可用 DMA 的外部 buffer,请使用 ``MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA`` 属性标志,堆分配器将处理 cache 及 DMA 子系统的对齐要求。如果某个外设有额外的对齐要求,可以调用 :cpp:func:heap_caps_aligned_alloc 并指定必要的对齐方式。 diff --git a/docs/zh_CN/api-reference/system/misc_system_api.rst b/docs/zh_CN/api-reference/system/misc_system_api.rst index 21e3a22973e3..455c0594f3d3 100644 --- a/docs/zh_CN/api-reference/system/misc_system_api.rst +++ b/docs/zh_CN/api-reference/system/misc_system_api.rst @@ -9,7 +9,7 @@ 软件复位 ------------ -函数 :cpp:func:`esp_restart` 用于执行芯片的软件复位。调用此函数时,程序停止执行,{IDF_TARGET_CPU_RESET_DES},应用程序由 bootloader 加载并重启。 +函数 :cpp:func:`esp_restart` 用于执行芯片的软件复位。调用此函数时,程序停止执行,{IDF_TARGET_CPU_RESET_DES},应用程序由引导加载程序加载并重启。 函数 :cpp:func:`esp_register_shutdown_handler` 用于注册复位前会自动调用的例程(复位过程由 :cpp:func:`esp_restart` 函数触发),这与 ``atexit`` POSIX 函数的功能类似。 diff --git a/docs/zh_CN/api-reference/system/ota.rst b/docs/zh_CN/api-reference/system/ota.rst index 53d0d1b67233..0ba597fcb831 100644 --- a/docs/zh_CN/api-reference/system/ota.rst +++ b/docs/zh_CN/api-reference/system/ota.rst @@ -19,7 +19,7 @@ OTA 数据分区 所有使用 OTA 功能项目,其 :doc:`../../api-guides/partition-tables` 必须包含一个 OTA 数据分区(类型为 ``data``,子类型为 ``ota``)。 -工厂启动设置下,OTA 数据分区中应没有数据(所有字节擦写成 0xFF)。如果分区表中有工厂应用程序,ESP-IDF 软件引导加载程序会启动工厂应用程序。如果分区表中没有工厂应用程序,则启动第一个可用的 OTA 分区(通常是 ``ota_0``)。 +工厂启动设置下,OTA 数据分区中应没有数据(所有字节擦写成 0xFF)。如果分区表中有工厂应用程序,ESP-IDF 二级引导加载程序会启动工厂应用程序。如果分区表中没有工厂应用程序,则启动第一个可用的 OTA 分区(通常是 ``ota_0``)。 第一次 OTA 升级后,OTA 数据分区更新,指定下一次启动哪个 OTA 应用程序分区。 @@ -344,7 +344,9 @@ Python API 应用示例 ------------ -- :example:`system/ota/otatool` 演示了如何使用 OTA 工具执行读取、写入和擦除 OTA 分区、切换启动分区以及切换到出厂分区等操作。有关更多信息,请参考 :example_file:`system/ota/otatool/README.md`。 +- :example:`system/ota/native_ota_example` 演示了如何在 {IDF_TARGET_NAME} 上使用 `app_update` 组件的 API 进行原生空中升级 (OTA)。适用的 SoC 请参阅 :example_file:`system/ota/native_ota_example/README.md`。 + +- :example:`system/ota/otatool` 演示了如何使用 OTA 工具执行读取、写入和擦除 OTA 分区、切换启动分区以及切换到工厂分区等操作。详情请参阅 :example_file:`system/ota/otatool/README.md`。 API 参考 -------- diff --git a/docs/zh_CN/api-reference/system/power_management.rst b/docs/zh_CN/api-reference/system/power_management.rst index 3762008505d0..4ca140e21e50 100644 --- a/docs/zh_CN/api-reference/system/power_management.rst +++ b/docs/zh_CN/api-reference/system/power_management.rst @@ -141,40 +141,44 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 如果在 menuconfig 中启用了 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,在初始化外设时,驱动会将外设工作的寄存器上下文注册到休眠备份链表中,在进入休眠前,``REG_DMA`` 外设会读取休眠备份链表中的配置,根据链表中的配置将外设的寄存器上下文备份至内存,``REG_DMA`` 也会在唤醒时将上下文从内存恢复到外设寄存中。 - 目前 IDF 支持以下外设的 Light-sleep 上下文备份: + 目前 IDF 支持以下外设的 Light-sleep 上下文备份,它们的上下文会自动恢复,或者提供了相关的选项允许用户进入外设下电模式: .. list:: - INT_MTX - TEE/APM - IO_MUX / GPIO - - Timer Group 0 & Timer Group 1 - - SPI0/1 + - MSPI (SPI0/1) - SYSTIMER + :SOC_TIMER_SUPPORT_SLEEP_RETENTION: - GPTimer :SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT - :SOC_I2C_SUPPORT_SLEEP_RETENTION:- I2C + :SOC_LEDC_SUPPORT_SLEEP_RETENTION: - LEDC + :SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C + :SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S + :SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM :SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs + :SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION: - Temperature Sensor + :SOC_TWAI_SUPPORT_SLEEP_RETENTION: - All TWAIs + :SOC_PARLIO_SUPPORT_SLEEP_RETENTION: - PARL_IO + :SOC_SPI_SUPPORT_SLEEP_RETENTION: - All GPSPIs - 以下外设尚未支持: + 一些外设尚未支持睡眠上下文恢复,或者寄存器丢失后根本无法恢复。即使外设下电功能被启用,它们也会阻止外设下电的发生: + + .. list:: + + :SOC_SDIO_SLAVE_SUPPORTED: - SDIO Slave + + 以下外设(以及一些未在本章节任意一组中列出的外设)尚未支持外设下电功能。如果您的应用使用了这些外设,它们可能无法在从睡眠中醒来后仍然正常工作: .. list:: - - ETM - ASSIST_DEBUG - Trace - Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA - - SPI2 - - I2S - PCNT - USB-Serial-JTAG - - TWAI - - LEDC - MCPWM - SARADC - - SDIO - - PARL_IO - - 对于未支持 Light-sleep 上下文备份的外设,若启用了电源管理功能,应在外设工作时持有 ``ESP_PM_NO_LIGHT_SLEEP`` 锁以避免进入休眠导致外设工作上下文丢失。 .. note:: diff --git a/docs/zh_CN/api-reference/system/pthread.rst b/docs/zh_CN/api-reference/system/pthread.rst index 218c647ec214..48af7bf9b891 100644 --- a/docs/zh_CN/api-reference/system/pthread.rst +++ b/docs/zh_CN/api-reference/system/pthread.rst @@ -1,5 +1,5 @@ -POSIX Thread -============ +POSIX 支持(包括 POSIX 线程支持) +================================= :link_to_translation:`en:[English]` @@ -12,7 +12,11 @@ ESP-IDF 基于 FreeRTOS,但提供了一系列与 POSIX 兼容的 API,以便 添加标准 ``pthread.h`` 头文件后可以在 ESP-IDF 中使用 pthread,该头文件已包含在工具链 libc 中。还有另一个专用于 ESP-IDF 的头文件 ``esp_pthread.h``,其中提供了一些额外的非 POSIX API,以便通过 pthread 使用一些 ESP-IDF 功能。 -C++ 标准库中的 ``std::thread``、``std::mutex``、``std::condition_variable`` 等功能也是通过 pthread(利用 GCC libstdc++)实现的。因此,本文档提到的限制条件也同样适用于 C++ 标准库中等效功能。 +除了 POSIX 线程,ESP-IDF 还支持 :ref:`POSIX 消息队列 `。 + +C++ 标准库中的 ``std::thread``、``std::mutex``、``std::condition_variable`` 等功能也是通过 pthread 和其他 POSIX API(利用 GCC libstdc++)实现的。因此,本文档提到的限制条件也同样适用于 C++ 标准库中的等效功能。 + +如果希望 ESP-IDF 支持某个尚未实现的 API,请 `在 GitHub 上发起功能请求 `_ 并提供详细信息。 RTOS 集成 ---------------- @@ -23,6 +27,10 @@ RTOS 集成 如果调用 C 标准库或 C++ sleep 函数,例如在 ``unistd.h`` 中定义的 ``usleep``,那么只有当睡眠时间超过 :ref:`一个 FreeRTOS 滴答周期 ` 时,任务才会阻塞并让出内核。如果时间较短,线程将处于忙等待状态,不会让步给另一个 RTOS 任务。 +.. note:: + + POSIX 的 ``errno`` 由 ESP-IDF 中的 newlib 提供。因此,配置项 ``configUSE_POSIX_ERRNO`` 并未被使用,应该保持禁用状态。 + 默认情况下,所有 pthread 具有相同的 RTOS 优先级,但可以通过调用 :ref:`ESP-IDF 提供的扩展 API ` 对此优先级进行更改。 标准功能 @@ -169,15 +177,65 @@ ESP-IDF 中实现了 POSIX 读写锁规范的以下 API 函数: ESP-IDF 中还有其他的线程本地存储选项,包括性能更高的选项。参见 :doc:`/api-guides/thread-local-storage`。 +.. _posix_message_queues: + +消息队列 +^^^^^^^^ + +消息队列的实现基于 `FreeRTOS-Plus-POSIX `_ 项目,ESP-IDF 的文件系统不提供消息队列,不支持消息优先级。 + +以下 POSIX 消息队列规范中的 API 函数已被实现: + +* `mq_open() `_ + + - 除了要符合 POSIX 规范,``name`` 参数还有以下额外限制: + - 必须以斜杠开头。 + - 长度不得超过 255 + 2 个字符(包括开头的斜杠,除去终止的空字符)。但 ``name`` 的内存是在内部动态分配的,所以名称越短,消耗的内存越少。 + - ``mode`` 参数未实现且被忽略。 + - 支持的 ``oflags``:``O_RDWR``、``O_CREAT``、``O_EXCL`` 和 ``O_NONBLOCK``。 + +* `mq_close() `_ +* `mq_unlink() `_ +* `mq_receive() `_ + + - 不支持消息优先级,因此 ``msg_prio`` 未被使用。 + +* `mq_timedreceive() `_ + + - 不支持消息优先级,因此 ``msg_prio`` 未被使用。 + +* `mq_send() `_ + + - 不支持消息优先级,因此 ``msg_prio`` 无效。 + +* `mq_timedsend() `_ + + - 不支持消息优先级,因此 ``msg_prio`` 无效。 + +* `mq_getattr() `_ + +尚未实现 `mq_notify() `_ 和 `mq_setattr() `_。 + +构建 +.... + +要使用 POSIX 消息队列 API,请在组件的 ``CMakeLists.txt`` 文件中添加 ``rt`` 作为依赖项。 + +.. note:: + + 请注意,如果曾在其他 FreeRTOS 项目中使用过 `FreeRTOS-Plus-POSIX `_,则 IDF 中的包含路径是 POSIX 风格的。因此,应用程序应直接包含 ``mqueue.h``,而不是使用子目录来包含 ``FreeRTOS_POSIX/mqueue.h``。 + 未实现 API --------------- ``pthread.h`` 头文件是一个标准头文件,包含了在 ESP-IDF 中未实现的额外 API 和功能,包括: -* 如果调用 ``pthread_cancel()``,返回 ``ENOSYS``。 -* ``pthread_condattr_init()`` 如果被调用,返回 ``ENOSYS``。 +* 若调用 ``pthread_cancel()``,则返回 ``ENOSYS``。 +* 若调用 ``pthread_condattr_init()``,则返回 ``ENOSYS``。 +* 若调用 `mq_notify() `_,则返回 ``ENOSYS``。 +* 若调用 `mq_setattr() `_,则返回 ``ENOSYS``。 -其他未列出的 pthread 函数未在 ESP-IDF 中实现,如果从 ESP-IDF 应用程序中直接引用,将产生编译器错误或链接器错误。如果希望 ESP-IDF 支持某个尚未实现的 API,请 `在 GitHub 上发起功能请求 `_ 并提供详细信息。 +其他未列出的 pthread 函数未在 ESP-IDF 中实现,如果从 ESP-IDF 应用程序中直接引用,将产生编译器错误或链接器错误。 .. _esp-pthread: diff --git a/docs/zh_CN/api-reference/system/random.rst b/docs/zh_CN/api-reference/system/random.rst index d10a9433b85e..dc1117b698ba 100644 --- a/docs/zh_CN/api-reference/system/random.rst +++ b/docs/zh_CN/api-reference/system/random.rst @@ -46,7 +46,7 @@ .. note:: - ESP-IDF 第二阶段引导加载程序在启动过程中启用的熵源会用熵来初始化内部 RNG 状态。但是,内部硬件 RNG 状态的大小并不足以提供连续的真随机数流。因此,在需要真随机数时必须启用连续的熵源。 + ESP-IDF 二级引导加载程序在启动过程中启用的熵源会用熵来初始化内部 RNG 状态。但是,内部硬件 RNG 状态的大小并不足以提供连续的真随机数流。因此,在需要真随机数时必须启用连续的熵源。 .. note:: diff --git a/docs/zh_CN/api-reference/system/ulp-lp-core.rst b/docs/zh_CN/api-reference/system/ulp-lp-core.rst index 70cd7ec870b9..4ffeca4ad747 100644 --- a/docs/zh_CN/api-reference/system/ulp-lp-core.rst +++ b/docs/zh_CN/api-reference/system/ulp-lp-core.rst @@ -1,11 +1,11 @@ -ULP LP-Core 协处理器编程 -=================================== +ULP LP 内核协处理器编程 +======================= :link_to_translation:`en:[English]` -ULP LP-Core(低功耗内核)协处理器是 {IDF_TARGET_NAME} 中 ULP 的一个变型。它具有超低功耗,同时还能在主 CPU 处于低功耗模式时保持运行。因此,LP-Core 协处理器能够在主 CPU 处于睡眠模式时处理 GPIO 或传感器读取等任务,从而显著降低整个系统的整体功耗。 +ULP LP 内核 (Low-power core) 协处理器是 {IDF_TARGET_NAME} 中 ULP 的一个变型。它具有超低功耗,同时还能在主 CPU 处于低功耗模式时保持运行。因此,LP 内核协处理器能够在主 CPU 处于睡眠模式时处理 GPIO 或传感器读取等任务,从而显著降低整个系统的整体功耗。 -ULP LP-Core 协处理器具有以下功能: +ULP LP 内核协处理器具有以下功能: * RV32I 处理器(32 位 RISC-V ISA),支持乘法/除法 (M)、原子 (A) 和压缩 (C) 扩展。 * 中断控制器。 @@ -13,17 +13,17 @@ ULP LP-Core 协处理器具有以下功能: * 当整个系统处于 active 模式时,可以访问所有的高功耗 (HP) SRAM 和外设。 * 当 HP 系统处于睡眠模式时,可以访问低功耗 (LP) SRAM 和外设。 -编译 ULP LP-Core 代码 ----------------------------------- +编译 ULP LP 内核代码 +-------------------- -ULP LP-Core 代码会与 ESP-IDF 项目共同编译,生成一个单独的二进制文件,并自动嵌入到主项目的二进制文件中。编译可通过以下两种方式实现: +ULP LP 内核代码会与 ESP-IDF 项目共同编译,生成一个单独的二进制文件,并自动嵌入到主项目的二进制文件中。编译可通过以下两种方式实现: 使用 ``ulp_embed_binary`` ~~~~~~~~~~~~~~~~~~~~~~~~~ -1. 将用 C 语言或汇编语言编写的 ULP LP-Core 代码(带有 ``.S`` 扩展名)放在组件目录下的专用目录中,例如 ``ulp/``。 +1. 将用 C 语言或汇编语言编写的 ULP LP 内核代码(带有 ``.S`` 扩展名)放在组件目录下的专用目录中,例如 ``ulp/``。 -2. 在 CMakeLists.txt 文件中注册组件后,调用 ``ulp_embed_binary`` 函数。例如: +2. 在 ``CMakeLists.txt`` 文件中注册组件后,调用 ``ulp_embed_binary`` 函数。例如: .. code-block:: cmake @@ -41,7 +41,7 @@ ULP LP-Core 代码会与 ESP-IDF 项目共同编译,生成一个单独的二 使用自定义的 CMake 项目 ~~~~~~~~~~~~~~~~~~~~~~~ -也可以为 LP-Core 创建自定义的 CMake 项目,从而更好地控制构建过程,并实现常规 CMake 项目的操作,例如设置编译选项、链接外部库等。 +也可以为 LP 内核创建自定义的 CMake 项目,从而更好地控制构建过程,并实现常规 CMake 项目的操作,例如设置编译选项、链接外部库等。 请在组件的 ``CMakeLists.txt`` 文件中将 ULP 项目添加为外部项目: @@ -90,7 +90,7 @@ ULP LP-Core 代码会与 ESP-IDF 项目共同编译,生成一个单独的二 若想编译和构建项目,请执行以下操作: -1. 在 menuconfig 中启用 :ref:`CONFIG_ULP_COPROC_ENABLED` 和 :ref:`CONFIG_ULP_COPROC_TYPE` 选项,并将 :ref:`CONFIG_ULP_COPROC_TYPE` 设置为 ``CONFIG_ULP_COPROC_TYPE_LP_CORE``。:ref:`CONFIG_ULP_COPROC_RESERVE_MEM` 选项为 ULP 保留 RTC 内存,因此必须设置为一个足够大的值,以存储 ULP LP-Core 代码和数据。如果应用程序组件包含多个 ULP 程序,那么 RTC 内存的大小必须足够容纳其中最大的程序。 +1. 在 menuconfig 中启用 :ref:`CONFIG_ULP_COPROC_ENABLED` 和 :ref:`CONFIG_ULP_COPROC_TYPE` 选项,并将 :ref:`CONFIG_ULP_COPROC_TYPE` 设置为 ``CONFIG_ULP_COPROC_TYPE_LP_CORE``。:ref:`CONFIG_ULP_COPROC_RESERVE_MEM` 选项为 ULP 保留 RTC 内存,因此必须设置为一个足够大的值,以存储 ULP LP 内核代码和数据。如果应用程序组件包含多个 ULP 程序,那么 RTC 内存的大小必须足够容纳其中最大的程序。 2. 按照常规步骤构建应用程序(例如 ``idf.py app``)。 @@ -113,12 +113,12 @@ ULP LP-Core 代码会与 ESP-IDF 项目共同编译,生成一个单独的二 .. _ulp-lp-core-access-variables: -访问 ULP LP-Core 程序变量 -------------------------------------------- +访问 ULP LP 内核程序变量 +------------------------ -在主程序中可以使用在 ULP LP-Core 程序中定义的全局符号。 +在主程序中可以使用在 ULP LP 内核程序中定义的全局符号。 -例如,ULP LP-Core 程序定义了一个变量 ``measurement_count``,用来表示程序从深度睡眠中唤醒芯片前所需的 GPIO 测量次数。 +例如,ULP LP 内核程序定义了一个变量 ``measurement_count``,用来表示程序从深度睡眠中唤醒芯片前所需的 GPIO 测量次数。 .. code-block:: c @@ -132,7 +132,7 @@ ULP LP-Core 代码会与 ESP-IDF 项目共同编译,生成一个单独的二 ...do something. } -主程序可以访问 ULP LP-Core 程序全局变量,这是因为构建系统生成了 ``${ULP_APP_NAME}.h`` 和 ``${ULP_APP_NAME}.ld`` 文件,文件中定义了 ULP LP-Core 程序中现有的的全局符号。在 ULP LP-Core 程序中定义的每个全局符号都包含在这两个文件中,并具有前缀 ``ulp_``。 +主程序可以访问 ULP LP 内核程序全局变量,这是因为构建系统生成了 ``${ULP_APP_NAME}.h`` 和 ``${ULP_APP_NAME}.ld`` 文件,文件中定义了 ULP LP 内核程序中现有的的全局符号。在 ULP LP 内核程序中定义的每个全局符号都包含在这两个文件中,并具有前缀 ``ulp_``。 头文件中包含符号的声明: @@ -148,7 +148,7 @@ ULP LP-Core 代码会与 ESP-IDF 项目共同编译,生成一个单独的二 PROVIDE ( ulp_measurement_count = 0x50000060 ); -要从主程序访问 ULP LP-Core 程序变量,应使用 ``include`` 语句将生成的头文件包含在主程序中,这样就可以像访问常规变量一样访问 ULP LP-Core 程序变量。 +要从主程序访问 ULP LP 内核程序变量,应使用 ``include`` 语句将生成的头文件包含在主程序中,这样就可以像访问常规变量一样访问 ULP LP 内核程序变量。 .. code-block:: c @@ -160,15 +160,15 @@ ULP LP-Core 代码会与 ESP-IDF 项目共同编译,生成一个单独的二 .. note:: - LP-Core 程序全局变量存储在二进制文件的 ``.bss`` 或者 ``.data`` 部分。这些部分在加载和执行 LP-Core 二进制文件时被初始化。在首次运行 LP-Core 之前,从 HP-Core 主程序访问这些变量可能会导致未定义行为。 + LP 内核程序全局变量存储在二进制文件的 ``.bss`` 或者 ``.data`` 部分。这些部分在加载和执行 LP 内核二进制文件时被初始化。在首次运行 LP 内核之前,从 HP-Core 主程序访问这些变量可能会导致未定义行为。 -启动 ULP LP-Core 程序 --------------------------------- +启动 ULP LP 内核程序 +-------------------- -要运行 ULP LP-Core 程序,主应用程序需要先使用 :cpp:func:`ulp_lp_core_load_binary` 函数将 ULP 程序加载到 RTC 内存中,然后使用 :cpp:func:`ulp_lp_core_run` 函数进行启动。 +要运行 ULP LP 内核程序,主应用程序需要先使用 :cpp:func:`ulp_lp_core_load_binary` 函数将 ULP 程序加载到 RTC 内存中,然后使用 :cpp:func:`ulp_lp_core_run` 函数进行启动。 -每个 ULP LP-Core 程序以二进制 blob 的形式嵌入到 ESP-IDF 应用程序中。应用程序可以按照如下方式引用和加载该 blob(假设 ULP_APP_NAME 被定义为 ``ulp_app_name``): +每个 ULP LP 内核程序以二进制 blob 的形式嵌入到 ESP-IDF 应用程序中。应用程序可以按照如下方式引用和加载该 blob(假设 ULP_APP_NAME 被定义为 ``ulp_app_name``): .. code-block:: c @@ -191,10 +191,10 @@ ULP LP-Core 代码会与 ESP-IDF 项目共同编译,生成一个单独的二 ESP_ERROR_CHECK( ulp_lp_core_run(&cfg) ); -ULP LP-Core 程序流程 ------------------------- +ULP LP 内核程序流程 +------------------- -ULP LP-Core 协处理器如何启动取决于 :cpp:type:`ulp_lp_core_cfg_t` 中选择的唤醒源。最常见的用例是 ULP 定期唤醒,在进行一些测量后唤醒主 CPU,或者再次进入睡眠状态。 +ULP LP 内核协处理器如何启动取决于 :cpp:type:`ulp_lp_core_cfg_t` 中选择的唤醒源。最常见的用例是 ULP 定期唤醒,在进行一些测量后唤醒主 CPU,或者再次进入睡眠状态。 ULP 有以下唤醒源: * :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU` - LP 内核可以被 HP CPU 唤醒。 @@ -215,10 +215,10 @@ ULP 被唤醒时会经历以下步骤: #. 调用 :cpp:func:`ulp_lp_core_halt` -ULP LP-Core 支持的外设 ------------------------------- +ULP LP 内核支持的外设 +--------------------- -为了增强 ULP LP-Core 协处理器的功能,它可以访问在低功耗电源域运行的外设。ULP LP-Core 协处理器可以在主 CPU 处于睡眠模式时与这些外设进行交互,并在达到唤醒条件时唤醒主 CPU。以下为支持的外设: +为了增强 ULP LP 内核协处理器的功能,它可以访问在低功耗电源域运行的外设。ULP LP 内核协处理器可以在主 CPU 处于睡眠模式时与这些外设进行交互,并在达到唤醒条件时唤醒主 CPU。以下为支持的外设: .. list:: @@ -229,14 +229,14 @@ ULP LP-Core 支持的外设 .. only:: CONFIG_ESP_ROM_HAS_LP_ROM - ULP LP-Core ROM + ULP LP 内核 ROM --------------- - ULP LP-Core ROM 是位于 LP-ROM 中的一小段预编译代码,用户无法修改。与主 CPU 运行的引导加载程序 ROM 代码类似,ULP LP-Core ROM 也在 ULP LP-Core 协处理器启动时执行。该 ROM 代码会初始化 ULP LP-Core 协处理器,随后跳转到用户程序。如果已初始化 LP UART,该 ROM 代码还会打印启动信息。 + ULP LP 内核 ROM 是位于 LP-ROM 中的一小段预编译代码,用户无法修改。与主 CPU 运行的引导加载程序 ROM 代码类似,ULP LP 内核 ROM 也在 ULP LP 内核协处理器启动时执行。该 ROM 代码会初始化 ULP LP 内核协处理器,随后跳转到用户程序。如果已初始化 LP UART,该 ROM 代码还会打印启动信息。 - 如果已将 :cpp:member:`ulp_lp_core_cfg_t::skip_lp_rom_boot` 设置为真,则不会执行 ULP LP-Core ROM 代码。如需尽快唤醒 ULP,同时避免初始化和信息打印产生额外开销,则可使用这一功能。 + 如果已将 :cpp:member:`ulp_lp_core_cfg_t::skip_lp_rom_boot` 设置为真,则不会执行 ULP LP 内核 ROM 代码。如需尽快唤醒 ULP,同时避免初始化和信息打印产生额外开销,则可使用这一功能。 - 除上述启动代码,ULP LP-Core ROM 代码还提供以下功能和接口: + 除上述启动代码,ULP LP 内核 ROM 代码还提供以下功能和接口: * :component_file:`ROM.ld 接口 ` * :component_file:`newlib.ld 接口 ` @@ -244,12 +244,12 @@ ULP LP-Core 支持的外设 在任何情况下,这些函数都存在于 LP-ROM 中,因此在程序中使用这些函数可以减少 ULP 应用程序的 RAM 占用。 -ULP LP-Core 中断 ----------------- +ULP LP 内核中断 +--------------- -配置 LP-Core 协处理器,可以处理各种类型的中断,例如 LP IO 低/高电平中断或是 LP 定时器中断。只需重写 IDF 提供的任何一个弱处理函数,就可以注册一个中断处理程序。所有处理程序可见 :component_file:`ulp_lp_core_interrupts.h `。有关特定目标可使用的中断的详细信息,请参阅 **{IDF_TARGET_NAME} 技术参考手册** [`PDF <{IDF_TARGET_TRM_CN_URL}#ulp>`__]。 +配置 LP 内核协处理器,可以处理各种类型的中断,例如 LP IO 低/高电平中断或是 LP 定时器中断。只需重写 IDF 提供的任何一个弱处理函数,就可以注册一个中断处理程序。所有处理程序可见 :component_file:`ulp_lp_core_interrupts.h `。有关特定目标可使用的中断的详细信息,请参阅 **{IDF_TARGET_NAME} 技术参考手册** [`PDF <{IDF_TARGET_TRM_CN_URL}#ulp>`__]。 -例如,要重写 LP IO 中断的处理程序,可以在 ULP LP-Core 代码中定义以下函数: +例如,要重写 LP IO 中断的处理程序,可以在 ULP LP 内核代码中定义以下函数: .. code-block:: c @@ -260,50 +260,130 @@ ULP LP-Core 中断 :c:macro:`LP_CORE_ISR_ATTR` 宏用于定义中断处理函数,可确保调用中断处理程序时妥善保存并恢复寄存器。 -除了为需要处理的中断源配置相关的中断寄存器外,还要调用 :cpp:func:`ulp_lp_core_intr_enable` 函数,在 LP-Core 中断控制器中使能全局中断。 +除了为需要处理的中断源配置相关的中断寄存器外,还要调用 :cpp:func:`ulp_lp_core_intr_enable` 函数,在 LP 内核中断控制器中使能全局中断。 + +ULP LP 内核时钟配置 +------------------- -调试 ULP LP-Core 应用程序 -------------------------- +{IDF_TARGET_XTAL_FREQ:default="未更新", esp32c5="48 MHz", esp32p4="40 MHz"} -在编程 LP-Core 时,有时很难弄清楚程序未按预期运行的原因。请参考以下策略,调试 LP-Core 程序: +ULP LP 内核的时钟源来自系统时钟 ``LP_FAST_CLK``,详情请参见 `技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`__ > ``复位和时钟``。 -* 使用 LP-UART 打印:LP-Core 可以访问 LP-UART 外设,在主 CPU 处于睡眠状态时独立打印信息。有关使用此驱动程序的示例,请参阅 :example:`system/ulp/lp_core/lp_uart/lp_uart_print`。 +.. only:: SOC_CLK_LP_FAST_SUPPORT_XTAL -* 通过 :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`,将 :cpp:func:`lp_core_printf` 路由到 HP-Core 控制台 UART,可以轻松地将 LP-Core 信息打印到已经连接的 HP-Core 控制台 UART。此方法的缺点是需要主 CPU 处于唤醒状态,并且由于 LP 核与 HP 核未同步,输出可能会交错。 + 在 {IDF_TARGET_NAME} 上,``LP_FAST_CLK`` 支持使用外部 {IDF_TARGET_XTAL_FREQ} 晶振 (XTAL) 作为其时钟源。默认时钟源 ``RTC_FAST_CLOCK`` 的运行频率约为 20 MHz,使用外部晶振时钟后,ULP LP 内核将以更高的频率运行。缺点在于,``LP_FAST_CLK`` 在休眠期间通常会断电以减少功耗,而选择 XTAL 作为时钟源后,休眠期间时钟仍将保持通电,造成功耗增加。因此,如果仅希望在 HP 内核活动时将 LP 内核用作协处理器,则可以使用 XTAL 以提高 LP 内核的性能和频率稳定性。 + + 要启用此功能,请将 :ref:`CONFIG_RTC_FAST_CLK_SRC` 设置为 ``CONFIG_RTC_FAST_CLK_SRC_XTAL``。 + + +调试 ULP LP 内核应用程序 +------------------------ + +在编程 LP 内核时,有时很难弄清楚程序未按预期运行的原因。请参考以下策略,调试 LP 内核程序: + +* 使用 LP-UART 打印:LP 内核可以访问 LP-UART 外设,在主 CPU 处于睡眠状态时独立打印信息。有关使用此驱动程序的示例,请参阅 :example:`system/ulp/lp_core/lp_uart/lp_uart_print`。 + +* 通过 :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`,将 :cpp:func:`lp_core_printf` 路由到 HP-Core 控制台 UART,可以轻松地将 LP 内核信息打印到已经连接的 HP-Core 控制台 UART。此方法的缺点是需要主 CPU 处于唤醒状态,并且由于 LP 内核与 HP 内未同步,输出可能会交错。 * 通过共享变量共享程序状态:如 :ref:`ulp-lp-core-access-variables` 所述,主 CPU 和 ULP 内核都可以轻松访问 RTC 内存中的全局变量。若想了解 ULP 内核的运行状态,可以将状态信息从 ULP 写入变量中,并通过主 CPU 读取信息。这种方法的缺点在于它需要主 CPU 一直处于唤醒状态,而这通常很难实现。另外,若主 CPU 一直处于唤醒状态,可能会掩盖某些问题,因为部分问题只会在特定电源域断电时发生。 -* 紧急处理程序:当检测到异常时,LP-Core 的紧急处理程序会把 LP-Core 寄存器的状态通过 LP-UART 发送出去。将 :ref:`CONFIG_ULP_PANIC_OUTPUT_ENABLE` 选项设置为 ``y``,可以启用紧急处理程序。禁用此选项将减少 LP-Core 应用程序的 LP-RAM 使用量。若想从紧急转储中解析栈回溯,可以使用 esp-idf-monitor_,例如: +* 紧急处理程序:当检测到异常时,LP 内核的紧急处理程序会把 LP 内核寄存器的状态通过 LP-UART 发送出去。将 :ref:`CONFIG_ULP_PANIC_OUTPUT_ENABLE` 选项设置为 ``y``,可以启用紧急处理程序。禁用此选项将减少 LP 内核应用程序的 LP-RAM 使用量。若想从紧急转储中解析栈回溯,可以使用 esp-idf-monitor_,例如: .. code-block:: bash python -m esp_idf_monitor --toolchain-prefix riscv32-esp-elf- --target {IDF_TARGET_NAME} --decode-panic backtrace PATH_TO_ULP_ELF_FILE +调试 ULP LP 内核应用程序:使用 GDB 和 OpenOCD +---------------------------------------------- -应用示例 --------- +与调试 HP 内核类似,也可以用 GDB 和 OpenOCD 来调试 LP 内核上的代码,但要注意其特殊之处和限制条件。 + +调试会话 +~~~~~~~~ -* :example:`system/ulp/lp_core/gpio` 展示了 ULP LP-Core 协处理器在主 CPU 深度睡眠时轮询 GPIO。 +使用支持 LP 内核调试的特殊配置文件来运行 OpenOCD,然后用特殊的 ``gdbinit`` 文件运行 GDB。 + +.. code-block:: bash + + openocd -f board/{IDF_TARGET_PATH_NAME}-lpcore-builtin.cfg + riscv32-esp-elf-gdb -x gdbinit + +以下是带有内联注释的 ``gdbinit`` 文件内容,详细信息请参考下一章节。 + +.. code-block:: bash + + # 连接到目标 + target extended-remote :3333 + # 重置芯片 + mon reset halt + maintenance flush register-cache + # 添加 ULP 程序的符号和调试信息 + add-symbol + # 设置临时硬件断点 + # 如果需要的断点数量超过硬件支持的数量 + thb main + commands + # 在这里设置断点 + # 此时 ULP 程序已加载到 RAM 中 + # 若无可用的硬件断点插槽,GDB 将设置软件断点 + b func1 + b func2 + b func3 + # 恢复执行 + c + end + # 重置后启动主程序 + c + +LP 内核调试特性 +~~~~~~~~~~~~~~~ -.. only:: esp32c6 +.. list:: - * :example:`system/ulp/lp_core/lp_i2c` 展示了 ULP LP-Core 协处理器在主 CPU 深度睡眠时读取外部 I2C 环境光传感器 (BH1750),并在达到阈值时唤醒主 CPU。 + #. 为了方便调试,请在 ULP 应用的 ``CMakeLists.txt`` 文件中添加 ``-O0`` 编译选项。具体操作步骤请参见 :example:`system/ulp/lp_core/debugging/`。 + :not esp32p4: #. LP 内核支持的硬件异常类型有限,例如,写入地址 `0x0` 不会像在 HP 内核上一样造成系统崩溃。启用 LP 内核应用程序的未定义行为检测器 (`ubsan`) 可以捕捉一些错误,从而在一定程度上弥补这一限制。但请注意,这将显著增加代码量,可能会导致应用程序超出 RTC RAM 的容量限制。要启用 `ubsan`,请在 ``CMakeLists.txt`` 文件中添加 ``-fsanitize=undefined -fno-sanitize=shift-base`` 编译选项。具体操作步骤请参见 :example:`system/ulp/lp_core/debugging/`。 + #. 为了调试运行在 LP 内核上的程序,需要先将调试信息和符号加载到 GDB 中。这可以通过 GDB 命令行或在 ``gdbinit`` 文件中完成。具体操作步骤请参见上文。 + #. LP 内核应用程序会在启时会加载到 RAM 中,在此之前设置的所有软件断点都会被覆盖。设置 LP 内核应用断点的最佳时机是在 LP 内核程序运行至 ``main`` 函数之时。 + #. 使用 IDE 时,可能无法配置上述 ``gdbinit`` 文件中的断点操作或命令。因此,请在调试会话开始前预设并禁用所有断点,只保留 ``main`` 函数处的断点。当程序在 ``main`` 处停止时,手动启用其余断点并恢复执行。 -* :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` 展示了低功耗内核上运行的 LP UART 驱动程序如何读取并回显写入串行控制台的数据。 +限制 +~~~~ -* :example:`system/ulp/lp_core/lp_uart/lp_uart_print` 展示了如何在低功耗内核上使用串口打印功能。 +#. 调试场景有限制:目前,当 HP 内核或 LP 内核进入睡眠模式时,将无法调适。 +#. 调试 内核时,OpenOCD 不支持 FreeRTOS,因此无法看到系统中正在运行的任务,但会有几个线程代表 HP 和 LP 内核: -* :example:`system/ulp/lp_core/interrupt` 展示了如何在 LP 内核上注册中断处理程序,接收由主 CPU 触发的中断。 +.. code-block:: bash -* :example:`system/ulp/lp_core/gpio_intr_pulse_counter` 展示了如何在主 CPU 处于 Deep-sleep 模式时,使用 GPIO 中断为脉冲计数。 + (gdb) info thread + Id Target Id Frame + 1 Thread 1 "{IDF_TARGET_PATH_NAME}.cpu0" (Name: {IDF_TARGET_PATH_NAME}.cpu0, state: debug-request) 0x40803772 in esp_cpu_wait_for_intr () + at /home/user/projects/esp/esp-idf/components/esp_hw_support/cpu.c:64 + * 2 Thread 2 "{IDF_TARGET_PATH_NAME}.cpu1" (Name: {IDF_TARGET_PATH_NAME}.cpu1, state: breakpoint) do_things (max=1000000000) + at /home/user/projects/esp/esp-idf/examples/system/ulp/lp_core/debugging/main/lp_core/main.c:21 -* :example:`system/ulp/lp_core/build_system/` 演示了如何为 ULP 应用程序添加自定义的 ``CMakeLists.txt`` 文件。 +#. 在 GDB 中设置硬件断点时,这些断点会同时应用到两个内核上,因此可用的硬件断点数量受 LP 内核支持数量({IDF_TARGET_NAME} 有 {IDF_TARGET_SOC_CPU_BREAKPOINTS_NUM} 个)所限。 +#. OpenOCD 的 flash 支持被禁用。LP 内核应用程序完全在 RAM 中运行,且 GDB 可以为其使用软件断点,因而该限制无关紧要。但若想在 HP 内核运行的代码中调用的 flash 函数(例如 `app_main`)上设置断点,则需要通过 ``hb`` 和 ``thb`` GDB 命令显式请求设置硬件断点。 +#. 由于主程序和 ULP 程序被链接为独立的二进制文件,它们可能会拥有相同名称的全局符号(如函数或变量)。若通过函数名称设置断点,则 GDB 将为所有同名函数设置断点。在调试 LP 内核时,OpenOCD 不支持 flash,因此如果上述函数位于 flash 中,可能会引发问题。此时建议通过源代码行号或函数的内存地址来设置断点。 + +应用示例 +-------- + +.. list:: + + - :example:`system/ulp/lp_core/gpio` 展示了 ULP LP 内核协处理器在主 CPU 深度睡眠时轮询 GPIO。 + :esp32c6: - :example:`system/ulp/lp_core/lp_i2c` 展示了 ULP LP 内核协处理器在主 CPU 深度睡眠时读取外部 I2C 环境光传感器 (BH1750),并在达到阈值时唤醒主 CPU。 + - :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` 展示了低功耗内核上运行的 LP UART 驱动程序如何读取并回显写入串行控制台的数据。 + - :example:`system/ulp/lp_core/lp_uart/lp_uart_print` 展示了如何在低功耗内核上使用串口打印功能。 + - :example:`system/ulp/lp_core/interrupt` 展示了如何在 LP 内核上注册中断处理程序,接收由主 CPU 触发的中断。 + - :example:`system/ulp/lp_core/gpio_intr_pulse_counter` 展示了如何在主 CPU 处于 Deep-sleep 模式时,使用 GPIO 中断为脉冲计数。 + - :example:`system/ulp/lp_core/build_system/` 演示了如何为 ULP 应用程序添加自定义的 ``CMakeLists.txt`` 文件。 + - :example:`system/ulp/lp_core/debugging` 演示了如何使用 GDB 和 OpenOCD 来调试运行在 LP 内核上的代码。 API 参考 -------------- +-------- 主 CPU API 参考 -~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~ .. include-build-file:: inc/ulp_lp_core.inc .. include-build-file:: inc/lp_core_i2c.inc @@ -320,7 +400,7 @@ API 参考 .. include-build-file:: inc/lp_core_types.inc LP 内核 API 参考 -~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ .. include-build-file:: inc/ulp_lp_core_utils.inc .. include-build-file:: inc/ulp_lp_core_gpio.inc diff --git a/docs/zh_CN/get-started/index.rst b/docs/zh_CN/get-started/index.rst index 76fd2d31309f..cb6a1ad58fc2 100644 --- a/docs/zh_CN/get-started/index.rst +++ b/docs/zh_CN/get-started/index.rst @@ -108,19 +108,19 @@ :maxdepth: 1 ESP32-DevKitC + ESP32-DevKitM-1 ESP-WROVER-KIT ESP32-PICO-KIT ESP32-Ethernet-Kit ESP32-PICO-KIT-1 ESP32-PICO-DevKitM-2 - ESP32-DevKitM-1 <../hw-reference/esp32/user-guide-devkitm-1> .. only:: esp32s2 .. toctree:: :maxdepth: 1 - ESP32-S2-Saola-1 <../hw-reference/esp32s2/user-guide-saola-1-v1.2> + ESP32-S2-Saola-1 ESP32-S2-DevKitM-1 ESP32-S2-DevKitC-1 ESP32-S2-Kaluga-Kit @@ -139,8 +139,8 @@ .. toctree:: :maxdepth: 1 - ESP32-S3-DevKitC-1 <../hw-reference/esp32s3/user-guide-devkitc-1> - ESP32-S3-DevKitM-1 <../hw-reference/esp32s3/user-guide-devkitm-1> + ESP32-S3-DevKitC-1 + ESP32-S3-DevKitM-1 .. only:: esp32c2 diff --git a/docs/zh_CN/hw-reference/esp32/user-guide-devkitm-1.rst b/docs/zh_CN/hw-reference/esp32/user-guide-devkitm-1.rst deleted file mode 100644 index f23f4d7c6a54..000000000000 --- a/docs/zh_CN/hw-reference/esp32/user-guide-devkitm-1.rst +++ /dev/null @@ -1,335 +0,0 @@ -=================== -ESP32-DevKitM-1 -=================== - -:link_to_translation:`en: [English]` - -本指南将介绍如何使用 ESP32-DevKitM-1,并提供更多关于此开发板的信息。 - -ESP32-DevKitM-1 是乐鑫推出的一款基于 ESP32-MINI-1/1U 模组的入门级开发板。板上模组大部分管脚均已引出至两侧排针,用户可根据实际需求,通过跳线轻松连接多种外围设备,同时也可将开发板插在面包板上使用。 - - -+------------------------+-------------------------+ -| |ESP32-DevKitM-1-正面| | |ESP32-DevKitM-1-侧面| | -+------------------------+-------------------------+ -| ESP32-DevKitM-1-正面 | ESP32-DevKitM-1-侧面 | -+------------------------+-------------------------+ - -.. |ESP32-DevKitM-1-正面| image:: ../../../_static/esp32-DevKitM-1-front.png - -.. |ESP32-DevKitM-1-侧面| image:: ../../../_static/esp32-DevKitM-1-isometric.png - - -本指南包括: - -- `快速入门`_:提供 ESP32-DevKitM-1 的简要概述及必要的硬件和软件信息。 -- `硬件参考`_:提供 ESP32-DevKitM-1 的详细硬件信息。 -- `相关文档`_:提供相关文档的链接。 - - -快速入门 -=========== - -本节介绍如何开始使用 ESP32-DevKitM-1,主要包括三大部分:首先,介绍一些关于 ESP32-DevKitM-1 的基本信息,然后在 `应用程序开发`_ 章节介绍如何进行硬件初始化,最后介绍如何为 ESP32-DevKitM-1 烧录固件。 - - -概述 -------- - -ESP32-DevKitM-1 开发板是一款小巧实用的开发板,具备以下特色功能: - -- 集成了 `ESP32-MINI-1 或 ESP32-MINI-1U `_ 模组 -- USB 转串口编程接口同时可为开发板供电 -- 设有排针 -- 设有重置按钮和固件下载模式激活按钮 -- 以及其他组件 - - -内含组件和包装 ---------------- - -零售订单 -^^^^^^^^^^^ - -如购买样品,每个 ESP32-DevKitM-1 开发板将以防静电袋或零售商选择的其他方式包装。 - -零售订单请前往 https://www.espressif.com/zh-hans/company/contact/buy-a-sample。 - - -批量订单 -^^^^^^^^^^^ - -如批量购买,ESP32-DevKitM-1 开发板将以大纸板箱包装。 - -批量订单请前往 https://www.espressif.com/zh-hans/contact-us/sales-questions。 - - -组件介绍 ------------ - -ESP32-DevKitM-1 开发板的主要组件、接口及控制方式见下图。下文以板载 ESP32-MINI-1 的开发板为例进行说明。 - - -.. figure:: ../../../_static/esp32-devkitm-1-v1-annotated-photo.png - :align: center - :alt: ESP32-DevKitM-1 - 正面 - :figclass: align-center - - ESP32-DevKitM-1 - 正面 - - -.. list-table:: - :widths: 25 75 - :header-rows: 1 - - * - 主要组件 - - 基本介绍 - * - 板载模组 - - ESP32-MINI-1 模组或 ESP32-MINI-1U 模组。ESP32-MINI-1 带有板载 PCB 天线;ESP32-MINI-1U 带有外部天线连接器。两款模组内置的芯片均叠封 4 MB flash。更多详情,请见 `《ESP32-MINI-1 & ESP32-MINI-1U 技术规格书》 `_ - * - 5 V 转 3.3 V LDO - - 电源转换器,输入 5 V,输出 3.3 V - * - Boot 键 - - 下载按键。按下 **Boot** 键的同时按一下 **Reset** 键进入“固件下载”模式,通过串口下载固件 - * - Reset 键 - - 复位按键 - * - Micro-USB 接口 - - USB 接口,可用作开发板的供电电源或 PC 和 ESP32 芯片的通信接口 - * - USB 至 UART 桥接器 - - 单芯片 USB 至 UART 桥接器,可提供高达 3 Mbps 的传输速率 - * - 3.3 V 电源指示灯 - - 开发板连接 USB 电源后,该指示灯亮起。更多信息,请见 `相关文档`_ 中的原理图 - * - I/O 连接器 - - 所有可用 GPIO 管脚(除 Flash 的 SPI 总线)均已引出至开发板的排针。用户可对 ESP32 芯片编程,开发多种功能 - - -应用程序开发 ---------------- - -ESP32-DevKitM-1 上电前,请首先确认开发板完好无损。 - - -硬件准备 -^^^^^^^^^^^^ - -- ESP32-DevKitM-1 开发板 -- USB A / micro USB B 数据线 -- PC(Windows、Linux 或 macS) - - -软件设置 -^^^^^^^^^^^ - -现在,请前往 :doc:`../../get-started/index` 中的 :ref:`get-started-step-by-step` 章节,查看如何设置开发环境,并尝试将示例项目烧录至你的开发板。 - -.. attention:: - - 对于 2021 年 12 月 2 日之前生产的 ESP32-DevKitM-1,其搭载的模组为单核 MCU 模组。请查看 `PCN-2021-021 `_ 以确定开发板上搭载的模组是否为单核模组。对于搭载单核模组的开发板,烧录应用程序前,需要在 :ref:`menuconfig ` 中启用单核模式 (:ref:`CONFIG_FREERTOS_UNICORE`)。 - - -硬件参考 -=========== - -功能框图 ----------- - -ESP32-DevKitM-1 的主要组件和连接方式如下图所示。 - -.. figure:: ../../../_static/esp32-DevKitM-1_v1_SystemBlock.png - :align: center - :alt: ESP32-DevKitM-1 - :figclass: align-center - - ESP32-DevKitM-1 - - -电源选项 ----------- - -开发板可从以下三种供电方式中任选其一: - -* Micro USB 供电(默认) -* 5V / GND 管脚供电 -* 3V3 / GND 管脚供电 - -.. warning:: - - - 上述供电模式 **不可同时连接**,否则可能会损坏开发板和/或电源。 - - 建议选择第一种供电方式:Micro USB 端口供电。 - - -管脚描述 ----------- - -开发板两侧 I/O 管脚,其具体名称和功能见下表。外设管脚分配请参考 `《ESP32 技术规格书》`_。 - -.. list-table:: - :header-rows: 1 - :widths: 10 12 12 66 - - - * - 编号 - - 名称 - - 类型 [1]_ - - 功能 - * - 1 - - GND - - P - - 接地 - * - 2 - - 3V3 - - P - - 3.3 V 电源 - * - 3 - - I36 - - I - - GPIO36, ADC1_CH0, RTC_GPIO0 - * - 4 - - I37 - - I - - GPIO37, ADC1_CH1, RTC_GPIO1 - * - 5 - - I38 - - I - - GPIO38, ADC1_CH2, RTC_GPIO2 - * - 6 - - I39 - - I - - GPIO39, ADC1_CH3, RTC_GPIO3 - * - 7 - - RST - - I - - 复位;高电平:使能;低电平:关闭 - * - 8 - - I34 - - I - - GPIO34, ADC1_CH6, RTC_GPIO4 - * - 9 - - I35 - - I - - GPIO35, ADC1_CH7, RTC_GPIO5 - * - 10 - - IO32 - - I/O - - GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9 - * - 11 - - IO33 - - I/O - - GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8 - * - 12 - - IO25 - - I/O - - GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0 - * - 13 - - IO26 - - I/O - - GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1 - * - 14 - - IO27 - - I/O - - GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV - * - 15 - - IO14 - - I/O - - GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2 - * - 16 - - 5V - - P - - 5 V 电源 - * - 17 - - IO12 - - I/O - - GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI [2]_, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 - * - 18 - - IO13 - - I/O - - GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER - * - 19 - - IO15 - - I/O - - GPIO15, ADC2_CH3, TOUCH3, RTC_GPIO13, MTDO [2]_, HSPICS0, HS2_CMD, SD_CMD, EMAC_RXD3 - * - 20 - - IO2 - - I/O - - GPIO2 [2]_, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0 - * - 21 - - IO0 - - I/O - - GPIO0 [2]_, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK - * - 22 - - IO4 - - I/O - - GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER - * - 23 - - IO9 - - I/O - - GPIO9, HS1_DATA2, U1RXD, SD_DATA2 - * - 24 - - IO10 - - I/O - - GPIO10, HS1_DATA3, U1TXD, SD_DATA3 - * - 25 - - IO5 - - I/O - - GPIO5 [2]_, HS1_DATA6, VSPICS0, EMAC_RX_CLK - * - 26 - - IO18 - - I/O - - GPIO18, HS1_DATA7, VSPICLK - * - 27 - - IO23 - - I/O - - GPIO23, HS1_STROBE, VSPID - * - 28 - - IO19 - - I/O - - GPIO19, VSPIQ, U0CTS, EMAC_TXD0 - * - 29 - - IO22 - - I/O - - GPIO22, VSPIWP, U0RTS, EMAC_TXD1 - * - 30 - - IO21 - - I/O - - GPIO21, VSPIHD, EMAC_TX_EN - * - 31 - - TXD0 - - I/O - - GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2 - * - 32 - - RXD0 - - I/O - - GPIO3, U0RXD, CLK_OUT2 - -.. [1] P:电源;I:输入;O:输出。 -.. [2] MTDI、GPIO0、GPIO2、MTDO 和 GPIO5 为 Strapping 管脚。在芯片上电和系统复位过程中,Strapping 管脚根据管脚的二进制电压值控制芯片功能。Strapping 管脚的具体描述和应用,请参考 `《ESP32 技术规格书》`_ > 章节 Strapping 管脚。 - - -管脚布局 -^^^^^^^^ - -.. figure:: ../../../_static/ESP32_DevKitM-1_pinlayout.png - :align: center - :scale: 43% - :alt: ESP32-DevKitM-1 (点击放大) - :figclass: align-center - - ESP32-DevKitM-1 (点击放大) - - -硬件修订历史 -=============== - -尚无版本升级历史。 - - -相关文档 -============ - -* `《ESP32-MINI-1 & ESP32-MINI-1U 技术规格书》 `_ (PDF) -* `ESP32-DevKitM-1 原理图 `_ (PDF) -* `ESP32-DevKitM-1 PCB 布局图 `_ (PDF) -* `ESP32-DevKitM-1 布局图 `_ (DXF) - 可使用 `Autodesk Viewer `_ 查看 -* `乐鑫产品选型工具 `_ -* `《ESP32 技术规格书》 `_ (PDF) - -有关本开发板的更多设计文档,请联系我们的商务部门 sales@espressif.com。 diff --git a/docs/zh_CN/hw-reference/esp32s2/user-guide-saola-1-v1.2.rst b/docs/zh_CN/hw-reference/esp32s2/user-guide-saola-1-v1.2.rst deleted file mode 100644 index fbde889144d0..000000000000 --- a/docs/zh_CN/hw-reference/esp32s2/user-guide-saola-1-v1.2.rst +++ /dev/null @@ -1,262 +0,0 @@ -================ -ESP32-S2-Saola-1 -================ - -:link_to_translation:`en: [English]` - -本指南介绍了乐鑫一款基于 `ESP32-S2 `_ 的小型开发板 ESP32-S2-Saola-1。 - -.. figure:: ../../../_static/esp32-s2-saola-1-v1.2-isometric.png - :align: center - :alt: ESP32-S2-Saola-1 - :figclass: align-center - - ESP32-S2-Saola-1 - -本指南包括如下内容: - -- `入门指南`_:简要介绍了 ESP32-S2-Saola-1 和硬件、软件设置指南。 -- `硬件参考`_:详细介绍了 ESP32-S2-Saola-1 的硬件。 -- `硬件版本`_:介绍硬件历史版本和已知问题,并提供链接至历史版本开发板的入门指南(如有)。 -- `相关文档`_:列出了相关文档的链接。 - - -入门指南 -======== - -本节介绍了如何快速上手 ESP32-S2-Saola-1。开头部分介绍了 ESP32-S2-Saola-1,`开始开发应用`_ 小节介绍了怎样在 ESP32-S2-Saola-1 上安装模组、设置及烧录固件。 - - -概述 ----- - -ESP32-S2-Saola-1 是乐鑫一款基于 ESP32-S2 的小型开发板。板上的绝大部分管脚均已引出,开发人员可根据实际需求,轻松通过跳线连接多种外围器件,或将开发板插在面包板上使用。 - -为了更好地满足不同用户需求,ESP32-S2-Saola-1 支持以下模组: - -- `ESP32-S2-WROVER `_ -- `ESP32-S2-WROVER-I `_ -- `ESP32-S2-WROOM `_ -- `ESP32-S2-WROOM-I `_ - -本指南以搭载 ESP32-S2-WROVER 模组的 ESP32-S2-Saola-1 为例。 - - -内含组件和包装 --------------- - -零售订单 -^^^^^^^^ - -如购买样品,每个 ESP32-S2-Saola-1 开发板将以防静电袋或零售商选择的其他方式包装。 - -零售订单请前往 https://www.espressif.com/zh-hans/company/contact/buy-a-sample。 - - -批量订单 -^^^^^^^^ - -如批量购买,ESP32-S2-Saola-1 开发板将以大纸板箱包装。 - -批量订单请前往 https://www.espressif.com/zh-hans/contact-us/sales-questions。 - - -组件介绍 --------- - -.. _user-guide-saola-1-v1.2-board-front: - -.. figure:: ../../../_static/esp32-s2-saola-1-v1.2-annotated-photo.png - :align: center - :alt: ESP32-S2-Saola-1 - 正面 - :figclass: align-center - - ESP32-S2-Saola-1 - 正面 - -以下按照顺时针的顺序依次介绍开发板上的主要组件。 - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - 主要组件 - - 介绍 - * - ESP32-S2-WROVER - - ESP32-S2-WROVER 集成 ESP32-S2,是通用型 Wi-Fi MCU 模组,功能强大。该模组采用 PCB 板载天线,配置了 4 MB SPI flash 和 2 MB SPI PSRAM。 - * - Pin Headers(排针) - - 所有可用 GPIO 管脚(除 Flash 和 PSRAM 的 SPI 总线)均已引出至开发板的排针。用户可对 ESP32-S2 芯片编程,使能 SPI、I2S、UART、I2C、触摸传感器、PWM 等多种功能。 - * - 3.3 V Power On LED(3.3 V 电源指示灯) - - 开发板连接 USB 电源后,该指示灯亮起。 - * - USB-to-UART Bridge(USB 转 UART 桥接器) - - 单芯片 USB 至 UART 桥接器,可提供高达 3 Mbps 的传输速率。 - * - Reset Button(Reset 键) - - 复位按键。 - * - Micro-USB Port(Micro-USB 接口) - - USB 接口。可用作开发板的供电电源或 PC 和 ESP32-S2 芯片的通信接口。 - * - Boot Button(Boot 键) - - 下载按键。按住 **Boot** 键的同时按一下 **Reset** 键进入“固件下载”模式,通过串口下载固件。 - * - RGB LED - - 可寻址 RGB 发光二极管 (WS2812),由 GPIO18 驱动。 - - -开始开发应用 ------------- - -通电前,请确保 ESP32-S2-Saola-1 完好无损。 - - -必备硬件 -^^^^^^^^ - -- ESP32-S2-Saola-1 -- USB 2.0 数据线(标准 A 型转 Micro-B 型) -- 电脑(Windows、Linux 或 macOS) - -.. 注解:: - - 请确保使用适当的 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 - - -软件设置 -^^^^^^^^ - -请前往 :doc:`../../get-started/index`,在 :ref:`get-started-step-by-step` 一节查看如何快速设置开发环境,将应用程序烧录至 ESP32-S2-Saola-1。 - -.. 注解:: - - ESP32-S2 系列芯片仅支持 ESP-IDF master 分支或 v4.2 以上版本。 - - -硬件参考 -======== - -功能框图 --------- - -ESP32-S2-Saola-1 的主要组件和连接方式如下图所示。 - -.. figure:: ../../../_static/esp32-s2-saola-1-v1.2-block-diags.png - :align: center - :scale: 70% - :alt: ESP32-S2-Saola-1 (点击放大) - :figclass: align-center - - ESP32-S2-Saola-1 (点击放大) - - -电源选项 -^^^^^^^^ - -以下任一供电方式均可给 ESP32-S2-Saola-1 供电: - -- Micro-USB 接口供电(默认) -- 5V 和 GND 排针供电 -- 3V3 和 GND 排针供电 - -建议选择第一种供电方式:Micro-USB 接口供电。 - - -排针 ----- - -下表列出了开发板两侧排针(J2 和 J3)的 **名称** 和 **功能**,排针的名称如图 :ref:`user-guide-saola-1-v1.2-board-front` 所示,排针的序号与 `ESP32-S2-Saola-1 原理图`_ (PDF) 一致。 - - -J2 -^^^ - -==== ==== ========= ====================================== -序号 名称 类型 [#]_ 功能 -==== ==== ========= ====================================== -1 3V3 P 3.3 V 电源 -2 IO0 I/O GPIO0, 启动 -3 IO1 I/O GPIO1, ADC1_CH0, TOUCH_CH1 -4 IO2 I/O GPIO2, ADC1_CH1, TOUCH_CH2 -5 IO3 I/O GPIO3, ADC1_CH2, TOUCH_CH3 -6 IO4 I/O GPIO4, ADC1_CH3, TOUCH_CH4 -7 IO5 I/O GPIO5, ADC1_CH4, TOUCH_CH5 -8 IO6 I/O GPIO6, ADC1_CH5, TOUCH_CH6 -9 IO7 I/O GPIO7, ADC1_CH6, TOUCH_CH7 -10 IO8 I/O GPIO8, ADC1_CH7, TOUCH_CH8 -11 IO9 I/O GPIO9, ADC1_CH8, TOUCH_CH9 -12 IO10 I/O GPIO10, ADC1_CH9, TOUCH_CH10 -13 IO11 I/O GPIO11, ADC2_CH0, TOUCH_CH11 -14 IO12 I/O GPIO12, ADC2_CH1, TOUCH_CH12 -15 IO13 I/O GPIO13, ADC2_CH2, TOUCH_CH13 -16 IO14 I/O GPIO14, ADC2_CH3, TOUCH_CH14 -17 IO15 I/O GPIO15, ADC2_CH4, XTAL_32K_P -18 IO16 I/O GPIO16, ADC2_CH5, XTAL_32K_N -19 IO17 I/O GPIO17, ADC2_CH6, DAC_1 -20 5V0 P 5 V 电源 -21 GND G 接地 -==== ==== ========= ====================================== - - -J3 -^^^ - -==== ==== ===== ==================================== -序号 名称 类型 功能 -==== ==== ===== ==================================== -1 GND G 接地 -2 RST I CHIP_PU, 复位 -3 IO46 I GPIO46 -4 IO45 I/O GPIO45 -5 IO44 I/O GPIO44, U0RXD -6 IO43 I/O GPIO43, U0TXD -7 IO42 I/O GPIO42, MTMS -8 IO41 I/O GPIO41, MTDI -9 IO40 I/O GPIO40, MTDO -10 IO39 I/O GPIO39, MTCK -11 IO38 I/O GPIO38 -12 IO37 I/O GPIO37 -13 IO36 I/O GPIO36 -14 IO35 I/O GPIO35 -16 IO34 I/O GPIO34 -17 IO33 I/O GPIO33 -17 IO26 I/O GPIO26 -18 IO21 I/O GPIO21 -19 IO20 I/O GPIO20, ADC2_CH9, USB_D+ -20 IO19 I/O GPIO19, ADC2_CH8, USB_D- -21 IO18 I/O GPIO18, ADC2_CH7, DAC_2, RGB LED -==== ==== ===== ==================================== - -.. [#] P:电源;I:输入;O:输出;T:可设置为高阻。 - - -管脚布局 -^^^^^^^^ - -.. figure:: ../../../_static/esp32-s2_saola1-pinout.jpg - :align: center - :scale: 45% - :alt: ESP32-S2-Saola-1 管脚布局(点击放大) - :figclass: align-center - - ESP32-S2-Saola-1 管脚布局(点击放大) - - -硬件版本 -========== - -无历史版本。 - - -相关文档 -======== - -* `ESP32-S2-Saola-1 原理图`_ (PDF) -* `ESP32-S2-Saola-1 尺寸图`_ (PDF) -* `ESP32-S2 技术规格书`_ (PDF) -* `ESP32-S2-WROVER & ESP32-S2-WROVER-I 技术规格书`_ (PDF) -* `ESP32-S2-WROOM & ESP32-S2-WROOM-I 技术规格书`_ (PDF) -* `乐鑫产品选型工具`_ - -有关本开发板的更多设计文档,请联系我们的商务部门 `sales@espressif.com `_。 - -.. _ESP32-S2-Saola-1 原理图: https://dl.espressif.com/dl/schematics/ESP32-S2-SAOLA-1_V1.1_schematics.pdf -.. _ESP32-S2-Saola-1 尺寸图: https://dl.espressif.com/dl/schematics/ESP32-S2-Saola-1_V1.2_Dimensions.pdf -.. _ESP32-S2 技术规格书: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_cn.pdf -.. _ESP32-S2-WROVER & ESP32-S2-WROVER-I 技术规格书: https://www.espressif.com/sites/default/files/documentation/esp32-s2-wrover_esp32-s2-wrover-i_datasheet_cn.pdf -.. _ESP32-S2-WROOM & ESP32-S2-WROOM-I 技术规格书: https://www.espressif.com/sites/default/files/documentation/esp32-s2-wroom_esp32-s2-wroom-i_datasheet_cn.pdf -.. _乐鑫产品选型工具: https://products.espressif.com/#/product-selector?names= diff --git a/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitc-1-v1.0.rst b/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitc-1-v1.0.rst deleted file mode 100644 index 4db1d60fb30f..000000000000 --- a/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitc-1-v1.0.rst +++ /dev/null @@ -1,320 +0,0 @@ -=================== -ESP32-S3-DevKitC-1 -=================== - -:link_to_translation:`en: [English]` - -最新版本::doc:`user-guide-devkitc-1` - -本指南将帮助你快速上手 ESP32-S3-DevKitC-1,并提供该款开发板的详细信息。 - -ESP32-S3-DevKitC-1 是一款入门级开发板,搭载 Wi-Fi + Bluetooth® LE 模组 ESP32-S3-WROOM-1、ESP32-S3-WROOM-1U 或 ESP32-S3-WROOM-2。 - -板上模组的大部分管脚均已引出至开发板两侧排针,开发人员可根据实际需求,轻松通过跳线连接多种外围设备,也可将开发板插在面包板上使用。 - -.. figure:: ../../../_static/esp32-s3-devkitc-1-v1-isometric.png - :align: center - :alt: ESP32-S3-DevKitC-1(板载 ESP32-S3-WROOM-1 模组) - - ESP32-S3-DevKitC-1(板载 ESP32-S3-WROOM-1 模组) - - -本指南包括如下内容: - -- `入门指南`_:简要介绍了开发板和硬件、软件设置指南。 -- `硬件参考`_:详细介绍了开发板的硬件。 -- `硬件版本`_:介绍硬件历史版本和已知问题,并提供链接至历史版本开发板的入门指南(如有)。 -- `相关文档`_:列出了相关文档的链接。 - - -入门指南 -======== - -本小节将简要介绍 ESP32-S3-DevKitC-1,说明如何在 ESP32-S3-DevKitC-1 上烧录固件及相关准备工作。 - - -组件介绍 --------- - -.. _user-guide-s3-devkitc-1-v1-board-front: - -.. figure:: ../../../_static/ESP32-S3-DevKitC-1_v2-annotated-photo.png - :align: center - :alt: ESP32-S3-DevKitC-1 - 正面 - - ESP32-S3-DevKitC-1 - 正面 - -以下按照逆时针的顺序依次介绍开发板上的主要组件。 - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - 主要组件 - - 介绍 - * - ESP32-S3-WROOM-1/1U/2 - - ESP32-S3-WROOM-1、ESP32-S3-WROOM-1U 和 ESP32-S3-WROOM-2 是通用型 Wi-Fi + 低功耗蓝牙 MCU 模组,具有丰富的外设接口、强大的神经网络运算能力和信号处理能力,专为人工智能和 AIoT 市场打造。ESP32-S3-WROOM-1 和 ESP32-S3-WROOM-2 采用 PCB 板载天线,ESP32-S3-WROOM-1U 采用连接器连接外部天线。 - * - 5 V to 3.3 V LDO(5 V 转 3.3 V LDO) - - 电源转换器,输入 5 V,输出 3.3 V。 - * - Pin Headers(排针) - - 所有可用 GPIO 管脚(除 flash 的 SPI 总线)均已引出至开发板的排针。请查看 :ref:`user-guide-s3-devkitc-1-v1-header-blocks` 获取更多信息。 - * - USB-to-UART Port(USB 转 UART 接口) - - Micro-USB 接口,可用作开发板的供电接口,可烧录固件至芯片,也可作为通信接口,通过板载 USB 转 UART 桥接器与芯片通信。 - * - Boot Button(Boot 键) - - 下载按键。按住 **Boot** 键的同时按一下 **Reset** 键进入“固件下载”模式,通过串口下载固件。 - * - Reset Button(Reset 键) - - 复位按键。 - * - ESP32-S3 USB Port(ESP32-S3 USB 接口) - - ESP32-S3 USB OTG 接口,支持全速 USB 1.1 标准。ESP32-S3 USB 接口可用作开发板的供电接口,可烧录固件至芯片,可通过 USB 协议与芯片通信,也可用于 JTAG 调试。 - * - USB-to-UART Bridge(USB 转 UART 桥接器) - - 单芯片 USB 至 UART 桥接器,可提供高达 3 Mbps 的传输速率。 - * - RGB LED - - 可寻址 RGB 发光二极管,由 GPIO48 驱动。 - * - 3.3 V Power On LED(3.3 V 电源指示灯) - - 开发板连接 USB 电源后,该指示灯亮起。 - -.. note:: - - 在板载 ESP32-S3-WROOM-1/1U 模组系列(使用 8 线 SPI flash/PSRAM)的开发板和板载 ESP32-S3-WROOM-2 模组系列的开发板中,管脚 GPIO35、GPIO36 和 GPIO37 已用于内部 ESP32-S3 芯片与 SPI flash/PSRAM 之间的通信,外部不可使用。 - - -开始开发应用 -------------- - -通电前,请确保开发板完好无损。 - - -必备硬件 -^^^^^^^^ - -- ESP32-S3-DevKitC-1 -- USB 2.0 数据线(标准 A 型转 Micro-B 型) -- 电脑(Windows、Linux 或 macOS) - -.. 注解:: - - 请确保使用适当的 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 - - -硬件设置 -^^^^^^^^ - -通过 **USB 转 UART 接口** 连接开发板与电脑。软件暂不支持通过 **ESP32-S3 USB 接口** 连接。在后续步骤中,默认使用 **USB 转 UART 接口**。 - - -软件设置 -^^^^^^^^ - -请前往 :doc:`../../get-started/index`,在 :ref:`get-started-step-by-step` 小节查看如何快速设置开发环境,将应用程序烧录至你的开发板。 - - -内含组件和包装 ---------------- - -订购信息 -^^^^^^^^^^^^^^ - -该开发板有多种型号可供选择,详见下表。 - -.. list-table:: - :widths: 28 29 19 17 15 - :header-rows: 1 - - * - 订购代码 - - 搭载模组 - - Flash - - PSRAM - - SPI 电压 - * - ESP32-S3-DevKitC-1-N8 - - ESP32-S3-WROOM-1-N8 - - 8 MB QD - - — - - 3.3 V - * - ESP32-S3-DevKitC-1-N8R2 - - ESP32-S3-WROOM-1-N8R2 - - 8 MB QD - - 2 MB QD - - 3.3 V - * - ESP32-S3-DevKitC-1-N8R8 - - ESP32-S3-WROOM-1-N8R8 - - 8 MB QD - - 8 MB OT - - 3.3 V - * - ESP32-S3-DevKitC-1-N16R8V - - ESP32-S3-WROOM-2-N16R8V - - 16 MB OT - - 8 MB OT - - 1.8 V - * - ESP32-S3-DevKitC-1-N32R8V - - ESP32-S3-WROOM-2-N32R8V - - 32 MB OT - - 8 MB OT - - 1.8 V - * - ESP32-S3-DevKitC-1U-N8 - - ESP32-S3-WROOM-1U-N8 - - 8 MB QD - - — - - 3.3 V - * - ESP32-S3-DevKitC-1U-N8R2 - - ESP32-S3-WROOM-1U-N8R2 - - 8 MB QD - - 2 MB QD - - 3.3 V - * - ESP32-S3-DevKitC-1U-N8R8 - - ESP32-S3-WROOM-1U-N8R8 - - 8 MB QD - - 8 MB OT - - 3.3 V - -.. note:: - - 上表中,QD 指代 Quad SPI,OT 指代 Octal SPI。 - - -零售订单 -^^^^^^^^ - -如购买样品,每个开发板将以防静电袋或零售商选择的其他方式包装。 - -零售订单请前往 https://www.espressif.com/zh-hans/company/contact/buy-a-sample。 - - -批量订单 -^^^^^^^^ - -如批量购买,开发板将以大纸板箱包装。 - -批量订单请前往 https://www.espressif.com/zh-hans/contact-us/sales-questions。 - - -硬件参考 -======== - -功能框图 --------- - -ESP32-S3-DevKitC-1 的主要组件和连接方式如下图所示。 - -.. figure:: ../../../_static/ESP32-S3-DevKitC-1_v2-SystemBlock.png - :align: center - :scale: 70% - :alt: ESP32-S3-DevKitC-1(点击放大) - - ESP32-S3-DevKitC-1(点击放大) - - -电源选项 -^^^^^^^^ - -以下任一供电方式均可给开发板供电: - -- USB 转 UART 接口供电或 ESP32-S3 USB 接口供电(选择其一或同时供电),默认供电方式(推荐) -- 5V 和 G (GND) 排针供电 -- 3V3 和 G (GND) 排针供电 - - -.. _user-guide-s3-devkitc-1-v1-header-blocks: - -排针 ----- - -下表列出了开发板两侧排针(J1 和 J3)的 **名称** 和 **功能**,排针的名称如图 :ref:`user-guide-s3-devkitc-1-v1-board-front` 所示,排针的序号与 `开发板原理图 `_ (PDF) 一致。 - - -J1 -^^^ - -==== ==== ========== ===================================================================== -序号 名称 类型 [#]_ 功能 -==== ==== ========== ===================================================================== -1 3V3 P 3.3 V 电源 -2 3V3 P 3.3 V 电源 -3 RST I EN -4 4 I/O/T RTC_GPIO4, GPIO4, TOUCH4, ADC1_CH3 -5 5 I/O/T RTC_GPIO5, GPIO5, TOUCH5, ADC1_CH4 -6 6 I/O/T RTC_GPIO6, GPIO6, TOUCH6, ADC1_CH5 -7 7 I/O/T RTC_GPIO7, GPIO7, TOUCH7, ADC1_CH6 -8 15 I/O/T RTC_GPIO15, GPIO15, U0RTS, ADC2_CH4, XTAL_32K_P -9 16 I/O/T RTC_GPIO16, GPIO16, U0CTS, ADC2_CH5, XTAL_32K_N -10 17 I/O/T RTC_GPIO17, GPIO17, U1TXD, ADC2_CH6 -11 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, CLK_OUT3 -12 8 I/O/T RTC_GPIO8, GPIO8, TOUCH8, ADC1_CH7, SUBSPICS1 -13 3 I/O/T RTC_GPIO3, GPIO3, TOUCH3, ADC1_CH2 -14 46 I/O/T GPIO46 -15 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD, SUBSPIHD -16 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4, SUBSPICS0 -17 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5, SUBSPID -18 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6, SUBSPICLK -19 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7, SUBSPIQ -20 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS, SUBSPIWP -21 5V P 5 V 电源 -22 G G 接地 -==== ==== ========== ===================================================================== - - -J3 -^^^ - -==== ==== ========== ===================================================================== -序号 名称 类型 功能 -==== ==== ========== ===================================================================== -1 G G 接地 -2 TX I/O/T U0TXD, GPIO43, CLK_OUT1 -3 RX I/O/T U0RXD, GPIO44, CLK_OUT2 -4 1 I/O/T RTC_GPIO1, GPIO1, TOUCH1, ADC1_CH0 -5 2 I/O/T RTC_GPIO2, GPIO2, TOUCH2, ADC1_CH1 -6 42 I/O/T MTMS, GPIO42 -7 41 I/O/T MTDI, GPIO41, CLK_OUT1 -8 40 I/O/T MTDO, GPIO40, CLK_OUT2 -9 39 I/O/T MTCK, GPIO39, CLK_OUT3, SUBSPICS1 -10 38 I/O/T GPIO38, FSPIWP, SUBSPIWP -11 37 I/O/T SPIDQS, GPIO37, FSPIQ, SUBSPIQ -12 36 I/O/T SPIIO7, GPIO36, FSPICLK, SUBSPICLK -13 35 I/O/T SPIIO6, GPIO35, FSPID, SUBSPID -14 0 I/O/T RTC_GPIO0, GPIO0 -15 45 I/O/T GPIO45 -16 48 I/O/T GPIO48, SPICLK_N, SUBSPICLK_N_DIFF, RGB LED -17 47 I/O/T GPIO47, SPICLK_P, SUBSPICLK_P_DIFF -18 21 I/O/T RTC_GPIO21, GPIO21 -19 20 I/O/T RTC_GPIO20, GPIO20, U1CTS, ADC2_CH9, CLK_OUT1, USB_D+ -20 19 I/O/T RTC_GPIO19, GPIO19, U1RTS, ADC2_CH8, CLK_OUT2, USB_D- -21 G G 接地 -22 G G 接地 -==== ==== ========== ===================================================================== - - -.. [#] P:电源;I:输入;O:输出;T:可设置为高阻。 - - -有关管脚功能名称的解释,请参考 `芯片规格书 `_ (PDF)。 - - -管脚布局 -^^^^^^^^^^^ - -.. figure:: ../../../_static/ESP32-S3_DevKitC-1_pinlayout.jpg - :align: center - :scale: 50% - :alt: ESP32-S3-DevKitC-1(点击放大) - - ESP32-S3-DevKitC-1 管脚布局(点击放大) - - -硬件版本 -============ - -无历史版本。 - - -相关文档 -======== - -- `ESP32-S3 技术规格书 `_ (PDF) -- `ESP32-S3-WROOM-1 & ESP32-S3-WROOM-1U 技术规格书 `_ (PDF) -- `ESP32-S3-WROOM-2 技术规格书 `_ (PDF) -- `ESP32-S3-DevKitC-1 原理图 `_ (PDF) -- `ESP32-S3-DevKitC-1 PCB 布局图 `_ (PDF) -- `ESP32-S3-DevKitC-1 尺寸图 `_ (PDF) -- `ESP32-S3-DevKitC-1 尺寸图源文件 `_ (DXF) - 可使用 `Autodesk Viewer `_ 查看 - -有关本开发板的更多设计文档,请联系我们的商务部门 `sales@espressif.com `_。 diff --git a/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitc-1.rst b/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitc-1.rst deleted file mode 100644 index 7038a658d54b..000000000000 --- a/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitc-1.rst +++ /dev/null @@ -1,329 +0,0 @@ -======================== -ESP32-S3-DevKitC-1 v1.1 -======================== - -:link_to_translation:`en: [English]` - -更早版本::doc:`user-guide-devkitc-1-v1.0` - -本指南将帮助你快速上手 ESP32-S3-DevKitC-1,并提供该款开发板的详细信息。 - -ESP32-S3-DevKitC-1 是一款入门级开发板,搭载 Wi-Fi + Bluetooth® LE 模组 ESP32-S3-WROOM-1、ESP32-S3-WROOM-1U 或 ESP32-S3-WROOM-2。 - -板上模组的大部分管脚均已引出至开发板两侧排针,开发人员可根据实际需求,轻松通过跳线连接多种外围设备,也可将开发板插在面包板上使用。 - -.. figure:: ../../../_static/esp32-s3-devkitc-1-v1.1-isometric.png - :align: center - :alt: ESP32-S3-DevKitC-1(板载 ESP32-S3-WROOM-1 模组) - - ESP32-S3-DevKitC-1(板载 ESP32-S3-WROOM-1 模组) - - -本指南包括如下内容: - -- `入门指南`_:简要介绍了开发板和硬件、软件设置指南。 -- `硬件参考`_:详细介绍了开发板的硬件。 -- `硬件版本`_:介绍硬件历史版本和已知问题,并提供链接至历史版本开发板的入门指南(如有)。 -- `相关文档`_:列出了相关文档的链接。 - - -入门指南 -======== - -本小节将简要介绍 ESP32-S3-DevKitC-1,说明如何在 ESP32-S3-DevKitC-1 上烧录固件及相关准备工作。 - - -组件介绍 --------- - -.. _user-guide-s3-devkitc-1-v1.1-board-front: - -.. figure:: ../../../_static/ESP32-S3-DevKitC-1_v2-annotated-photo.png - :align: center - :alt: ESP32-S3-DevKitC-1 - 正面 - - ESP32-S3-DevKitC-1 - 正面 - -以下按照逆时针的顺序依次介绍开发板上的主要组件。 - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - 主要组件 - - 介绍 - * - ESP32-S3-WROOM-1/1U/2 - - ESP32-S3-WROOM-1、ESP32-S3-WROOM-1U 和 ESP32-S3-WROOM-2 是通用型 Wi-Fi + 低功耗蓝牙 MCU 模组,具有丰富的外设接口、强大的神经网络运算能力和信号处理能力,专为人工智能和 AIoT 市场打造。ESP32-S3-WROOM-1 和 ESP32-S3-WROOM-2 采用 PCB 板载天线,ESP32-S3-WROOM-1U 采用连接器连接外部天线。 - * - 5 V to 3.3 V LDO(5 V 转 3.3 V LDO) - - 电源转换器,输入 5 V,输出 3.3 V。 - * - Pin Headers(排针) - - 所有可用 GPIO 管脚(除 flash 的 SPI 总线)均已引出至开发板的排针。请查看 :ref:`user-guide-s3-devkitc-1-v1.1-header-blocks` 获取更多信息。 - * - USB-to-UART Port(USB 转 UART 接口) - - Micro-USB 接口,可用作开发板的供电接口,可烧录固件至芯片,也可作为通信接口,通过板载 USB 转 UART 桥接器与芯片通信。 - * - Boot Button(Boot 键) - - 下载按键。按住 **Boot** 键的同时按一下 **Reset** 键进入“固件下载”模式,通过串口下载固件。 - * - Reset Button(Reset 键) - - 复位按键。 - * - USB Port(USB 接口) - - ESP32-S3 USB OTG 接口,支持全速 USB 1.1 标准。ESP32-S3 USB 接口可用作开发板的供电接口,可烧录固件至芯片,可通过 USB 协议与芯片通信,也可用于 JTAG 调试。 - * - USB-to-UART Bridge(USB 转 UART 桥接器) - - 单芯片 USB 至 UART 桥接器,可提供高达 3 Mbps 的传输速率。 - * - RGB LED - - 可寻址 RGB 发光二极管,由 GPIO38 驱动。 - * - 3.3 V Power On LED(3.3 V 电源指示灯) - - 开发板连接 USB 电源后,该指示灯亮起。 - -.. note:: - - 在板载 ESP32-S3-WROOM-1/1U 模组系列(使用 8 线 SPI flash/PSRAM)的开发板和板载 ESP32-S3-WROOM-2 模组系列的开发板中,管脚 GPIO35、GPIO36 和 GPIO37 已用于内部 ESP32-S3 芯片与 SPI flash/PSRAM 之间的通信,外部不可使用。 - - -开始开发应用 -------------- - -通电前,请确保开发板完好无损。 - - -必备硬件 -^^^^^^^^ - -- ESP32-S3-DevKitC-1 -- USB 2.0 数据线(标准 A 型转 Micro-B 型) -- 电脑(Windows、Linux 或 macOS) - -.. 注解:: - - 请确保使用适当的 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 - - -硬件设置 -^^^^^^^^ - -通过 **USB 转 UART 接口** 或 **ESP32-S3 USB 接口** 连接开发板与电脑。在后续步骤中,默认使用 **USB 转 UART 接口**。 - - -软件设置 -^^^^^^^^ - -请前往 :doc:`../../get-started/index`,在 :ref:`get-started-step-by-step` 小节查看如何快速设置开发环境,将应用程序烧录至你的开发板。 - - -内含组件和包装 ---------------- - -订购信息 -^^^^^^^^^^^^^^ - -该开发板有多种型号可供选择,详见下表。 - -.. list-table:: - :widths: 28 29 19 17 15 - :header-rows: 1 - - * - 订购代码 - - 搭载模组 - - Flash - - PSRAM - - SPI 电压 - * - ESP32-S3-DevKitC-1-N8 - - ESP32-S3-WROOM-1-N8 - - 8 MB QD - - — - - 3.3 V - * - ESP32-S3-DevKitC-1-N8R2 - - ESP32-S3-WROOM-1-N8R2 - - 8 MB QD - - 2 MB QD - - 3.3 V - * - ESP32-S3-DevKitC-1-N8R8 - - ESP32-S3-WROOM-1-N8R8 - - 8 MB QD - - 8 MB OT - - 3.3 V - * - ESP32-S3-DevKitC-1-N16R8V - - ESP32-S3-WROOM-2-N16R8V - - 16 MB OT - - 8 MB OT - - 1.8 V - * - ESP32-S3-DevKitC-1-N32R8V - - ESP32-S3-WROOM-2-N32R8V - - 32 MB OT - - 8 MB OT - - 1.8 V - * - ESP32-S3-DevKitC-1U-N8 - - ESP32-S3-WROOM-1U-N8 - - 8 MB QD - - — - - 3.3 V - * - ESP32-S3-DevKitC-1U-N8R2 - - ESP32-S3-WROOM-1U-N8R2 - - 8 MB QD - - 2 MB QD - - 3.3 V - * - ESP32-S3-DevKitC-1U-N8R8 - - ESP32-S3-WROOM-1U-N8R8 - - 8 MB QD - - 8 MB OT - - 3.3 V - -.. note:: - - 上表中,QD 指代 Quad SPI,OT 指代 Octal SPI。 - - -零售订单 -^^^^^^^^ - -如购买样品,每个开发板将以防静电袋或零售商选择的其他方式包装。 - -零售订单请前往 https://www.espressif.com/zh-hans/company/contact/buy-a-sample。 - - -批量订单 -^^^^^^^^ - -如批量购买,开发板将以大纸板箱包装。 - -批量订单请前往 https://www.espressif.com/zh-hans/contact-us/sales-questions。 - - -硬件参考 -======== - -功能框图 --------- - -ESP32-S3-DevKitC-1 的主要组件和连接方式如下图所示。 - -.. figure:: ../../../_static/ESP32-S3-DevKitC-1_v2-SystemBlock.png - :align: center - :scale: 70% - :alt: ESP32-S3-DevKitC-1(点击放大) - - ESP32-S3-DevKitC-1(点击放大) - - -电源选项 -^^^^^^^^ - -以下任一供电方式均可给开发板供电: - -- USB 转 UART 接口供电或 ESP32-S3 USB 接口供电(选择其一或同时供电),默认供电方式(推荐) -- 5V 和 G (GND) 排针供电 -- 3V3 和 G (GND) 排针供电 - - -.. _user-guide-s3-devkitc-1-v1.1-header-blocks: - -排针 ----- - -下表列出了开发板两侧排针(J1 和 J3)的 **名称** 和 **功能**,排针的名称如图 :ref:`user-guide-s3-devkitc-1-v1.1-board-front` 所示,排针的序号与 `开发板原理图 `_ (PDF) 一致。 - - -J1 -^^^ - -==== ==== ========== ===================================================================== -序号 名称 类型 [#]_ 功能 -==== ==== ========== ===================================================================== -1 3V3 P 3.3 V 电源 -2 3V3 P 3.3 V 电源 -3 RST I EN -4 4 I/O/T RTC_GPIO4, GPIO4, TOUCH4, ADC1_CH3 -5 5 I/O/T RTC_GPIO5, GPIO5, TOUCH5, ADC1_CH4 -6 6 I/O/T RTC_GPIO6, GPIO6, TOUCH6, ADC1_CH5 -7 7 I/O/T RTC_GPIO7, GPIO7, TOUCH7, ADC1_CH6 -8 15 I/O/T RTC_GPIO15, GPIO15, U0RTS, ADC2_CH4, XTAL_32K_P -9 16 I/O/T RTC_GPIO16, GPIO16, U0CTS, ADC2_CH5, XTAL_32K_N -10 17 I/O/T RTC_GPIO17, GPIO17, U1TXD, ADC2_CH6 -11 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, CLK_OUT3 -12 8 I/O/T RTC_GPIO8, GPIO8, TOUCH8, ADC1_CH7, SUBSPICS1 -13 3 I/O/T RTC_GPIO3, GPIO3, TOUCH3, ADC1_CH2 -14 46 I/O/T GPIO46 -15 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD, SUBSPIHD -16 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4, SUBSPICS0 -17 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5, SUBSPID -18 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6, SUBSPICLK -19 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7, SUBSPIQ -20 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS, SUBSPIWP -21 5V P 5 V 电源 -22 G G 接地 -==== ==== ========== ===================================================================== - - -J3 -^^^ - -==== ==== ========== ===================================================================== -序号 名称 类型 功能 -==== ==== ========== ===================================================================== -1 G G 接地 -2 TX I/O/T U0TXD, GPIO43, CLK_OUT1 -3 RX I/O/T U0RXD, GPIO44, CLK_OUT2 -4 1 I/O/T RTC_GPIO1, GPIO1, TOUCH1, ADC1_CH0 -5 2 I/O/T RTC_GPIO2, GPIO2, TOUCH2, ADC1_CH1 -6 42 I/O/T MTMS, GPIO42 -7 41 I/O/T MTDI, GPIO41, CLK_OUT1 -8 40 I/O/T MTDO, GPIO40, CLK_OUT2 -9 39 I/O/T MTCK, GPIO39, CLK_OUT3, SUBSPICS1 -10 38 I/O/T GPIO38, FSPIWP, SUBSPIWP, RGB LED -11 37 I/O/T SPIDQS, GPIO37, FSPIQ, SUBSPIQ -12 36 I/O/T SPIIO7, GPIO36, FSPICLK, SUBSPICLK -13 35 I/O/T SPIIO6, GPIO35, FSPID, SUBSPID -14 0 I/O/T RTC_GPIO0, GPIO0 -15 45 I/O/T GPIO45 -16 48 I/O/T GPIO48, SPICLK_N, SUBSPICLK_N_DIFF -17 47 I/O/T GPIO47, SPICLK_P, SUBSPICLK_P_DIFF -18 21 I/O/T RTC_GPIO21, GPIO21 -19 20 I/O/T RTC_GPIO20, GPIO20, U1CTS, ADC2_CH9, CLK_OUT1, USB_D+ -20 19 I/O/T RTC_GPIO19, GPIO19, U1RTS, ADC2_CH8, CLK_OUT2, USB_D- -21 G G 接地 -22 G G 接地 -==== ==== ========== ===================================================================== - - -.. [#] P:电源;I:输入;O:输出;T:可设置为高阻。 - - -有关管脚功能名称的解释,请参考 `ESP32-S3 技术规格书 `_ (PDF)。 - - -管脚布局 -^^^^^^^^^^^ - -.. figure:: ../../../_static/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg - :align: center - :scale: 50% - :alt: ESP32-S3-DevKitC-1(点击放大) - - ESP32-S3-DevKitC-1 管脚布局(点击放大) - - -硬件版本 -============ - -:doc:`首次发布 ` - -.. note:: - - 目前首次发布和 v1.1 版本的开发板均可订购,两个版本的主要差异在于 RGB LED 所连接的管脚不同。首次发布版本的 RGB LED 连接到 GPIO48,而 v1.1 版本的 RGB LED 连接到 GPIO38。 - - -相关文档 -======== - -- `ESP32-S3 技术规格书 `_ (PDF) -- `ESP32-S3-WROOM-1 & ESP32-S3-WROOM-1U 技术规格书 `_ (PDF) -- `ESP32-S3-WROOM-2 技术规格书 `_ (PDF) -- `ESP32-S3-DevKitC-1 原理图 `_ (PDF) -- `ESP32-S3-DevKitC-1 PCB 布局图 `_ (PDF) -- `ESP32-S3-DevKitC-1 尺寸图 `_ (PDF) -- `ESP32-S3-DevKitC-1 尺寸图源文件 `_ (DXF) - 可使用 `Autodesk Viewer `_ 查看 - -有关本开发板的更多设计文档,请联系我们的商务部门 `sales@espressif.com `_。 - -.. toctree:: - :hidden: - - user-guide-devkitc-1-v1.0 diff --git a/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitm-1.rst b/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitm-1.rst deleted file mode 100644 index c39d0a540685..000000000000 --- a/docs/zh_CN/hw-reference/esp32s3/user-guide-devkitm-1.rst +++ /dev/null @@ -1,258 +0,0 @@ -=================== -ESP32-S3-DevKitM-1 -=================== - -:link_to_translation:`en: [English]` - -本指南将帮助你快速上手 ESP32-S3-DevKitM-1,并提供该款开发板的详细信息。 - -ESP32-S3-DevKitM-1 是一款入门级开发板,搭载的是 Wi-Fi+蓝牙 LE 模组 ESP32-S3-MINI-1 或 ESP32-S3-MINI-1U,该款模组因小尺寸而得名。 - -板上模组的大部分管脚均已引出至开发板两侧排针,开发人员可根据实际需求,轻松通过跳线连接多种外围设备,也可将开发板插在面包板上使用。 - -.. figure:: ../../../_static/esp32-s3-devkitm-1-v1-isometric.png - :align: center - :scale: 70% - :alt: ESP32-S3-DevKitM-1(板载 ESP32-S3-MINI-1 模组) - :figclass: align-center - - ESP32-S3-DevKitM-1(板载 ESP32-S3-MINI-1 模组) - - -本指南包括如下内容: - -- `入门指南`_:简要介绍了开发板和硬件、软件设置指南。 -- `硬件参考`_:详细介绍了开发板的硬件。 -- `相关文档`_:列出了相关文档的链接。 - - -入门指南 -======== - -本小节将简要介绍 ESP32-S3-DevKitM-1,说明如何在 ESP32-S3-DevKitM-1 上烧录固件及相关准备工作。 - - -组件介绍 --------- - -.. _user-guide-s3-devkitm-1-v1-board-front: - -.. figure:: ../../../_static/ESP32-S3-DevKitM-1_v1-annotated-photo.png - :align: center - :alt: ESP32-S3-DevKitM-1 - 正面 - :figclass: align-center - - ESP32-S3-DevKitM-1 - 正面 - -以下按照逆时针的顺序依次介绍开发板上的主要组件。 - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - 主要组件 - - 介绍 - * - ESP32-S3-MINI-1/1U - - ESP32-S3-MINI-1 和 ESP32-S3-MINI-1U 是通用型 Wi-Fi + 低功耗蓝牙 MCU 模组,具有丰富的外设接口。ESP32-S3-MINI-1 采用 PCB 板载天线,ESP32-S3-MINI-1U 采用连接器连接外部天线。两款模组的核心是 ESP32-S3FN8 芯片。该芯片带有 8 MB flash,由于 flash 直接封装在芯片中,因此 ESP32-S3-MINI-1/1U 模组具有较小的封装尺寸。 - * - 5 V to 3.3 V LDO(5 V 转 3.3 V LDO) - - 电源转换器,输入 5 V,输出 3.3 V。 - * - Pin Headers(排针) - - 所有可用 GPIO 管脚(除 flash 的 SPI 总线)均已引出至开发板的排针。请查看 :ref:`user-guide-s3-DevKitM-1-header-blocks` 获取更多信息。 - * - USB-to-UART Port(USB 转 UART 接口) - - Micro-USB 接口,可用作开发板的供电接口,可烧录固件至芯片,也可作为通信接口,通过板载 USB 转 UART 桥接器与芯片通信。 - * - Boot Button(Boot 键) - - 下载按键。按住 **Boot** 键的同时按一下 **Reset** 键进入“固件下载”模式,通过串口下载固件。 - * - Reset Button(Reset 键) - - 复位按键。 - * - ESP32-S3 USB Port(ESP32-S3 USB 接口) - - ESP32-S3 USB OTG 接口,支持全速 USB 1.1 标准。ESP32-S3 USB 接口可用作开发板的供电接口,可烧录固件至芯片,可通过 USB 协议与芯片通信,也可用于 JTAG 调试。 - * - USB-to-UART Bridge(USB 转 UART 桥接器) - - 单芯片 USB 至 UART 桥接器,可提供高达 3 Mbps 的传输速率。 - * - RGB LED - - 可寻址 RGB 发光二极管,由 GPIO48 驱动。 - * - 3.3 V Power On LED(3.3 V 电源指示灯) - - 开发板连接 USB 电源后,该指示灯亮起。 - - -开始开发应用 -------------- - -通电前,请确保开发板完好无损。 - - -必备硬件 -^^^^^^^^ - -- ESP32-S3-DevKitM-1 -- USB 2.0 数据线(标准 A 型转 Micro-B 型) -- 电脑(Windows、Linux 或 macOS) - -.. 注解:: - - 请确保使用适当的 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 - - -硬件设置 -^^^^^^^^ - -通过 **USB 转 UART 接口** 或 **ESP32-S3 USB 接口** 连接开发板与电脑。在后续步骤中,默认使用 **USB 转 UART 接口**。 - - -软件设置 -^^^^^^^^ - -请前往 :doc:`../../get-started/index`,在 :ref:`get-started-step-by-step` 小节查看如何快速设置开发环境,将应用程序烧录至你的开发板。 - - -内含组件和包装 ---------------- - -零售订单 -^^^^^^^^ - -如购买样品,每个开发板将以防静电袋或零售商选择的其他方式包装。 - -零售订单请前往 https://www.espressif.com/zh-hans/company/contact/buy-a-sample。 - - -批量订单 -^^^^^^^^ - -如批量购买,开发板将以大纸板箱包装。 - -批量订单请前往 https://www.espressif.com/zh-hans/contact-us/sales-questions。 - - -硬件参考 -======== - -功能框图 --------- - -ESP32-S3-DevKitM-1 的主要组件和连接方式如下图所示。 - -.. figure:: ../../../_static/ESP32-S3-DevKitM-1_v1_SystemBlock.png - :align: center - :scale: 70% - :alt: ESP32-S3-DevKitM-1(点击放大) - :figclass: align-center - - ESP32-S3-DevKitM-1(点击放大) - - -电源选项 -^^^^^^^^ - -以下任一供电方式均可给开发板供电: - -- USB 转 UART 接口供电或 ESP32-S3 USB 接口供电(选择其一或同时供电),默认供电方式(推荐) -- 5V 和 G (GND) 排针供电 -- 3V3 和 G (GND) 排针供电 - - -.. _user-guide-s3-DevKitM-1-header-blocks: - -排针 ----- - -下表列出了开发板两侧排针(J1 和 J3)的 **名称** 和 **功能**,排针的名称如图 :ref:`user-guide-s3-devkitm-1-v1-board-front` 所示,排针的序号与 `开发板原理图 `_ (PDF) 一致。 - - -J1 -^^^ - -==== ==== ========== ===================================================================== -序号 名称 类型 [#]_ 功能 -==== ==== ========== ===================================================================== -1 3V3 P 3.3 V 电源 -2 0 I/O/T RTC_GPIO0, GPIO0 -3 1 I/O/T RTC_GPIO1, GPIO1, TOUCH1, ADC1_CH0 -4 2 I/O/T RTC_GPIO2, GPIO2, TOUCH2, ADC1_CH1 -5 3 I/O/T RTC_GPIO3, GPIO3, TOUCH3, ADC1_CH2 -6 4 I/O/T RTC_GPIO4, GPIO4, TOUCH4, ADC1_CH3 -7 5 I/O/T RTC_GPIO5, GPIO5, TOUCH5, ADC1_CH4 -8 6 I/O/T RTC_GPIO6, GPIO6, TOUCH6, ADC1_CH5 -9 7 I/O/T RTC_GPIO7, GPIO7, TOUCH7, ADC1_CH6 -10 8 I/O/T RTC_GPIO8, GPIO8, TOUCH8, ADC1_CH7, SUBSPICS1 -11 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD, SUBSPIHD -12 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4, SUBSPICS0 -13 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5, SUBSPID -14 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6, SUBSPICLK -15 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7, SUBSPIQ -16 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS, SUBSPIWP -17 15 I/O/T RTC_GPIO15, GPIO15, U0RTS, ADC2_CH4, XTAL_32K_P -18 16 I/O/T RTC_GPIO16, GPIO16, U0CTS, ADC2_CH5, XTAL_32K_N -19 17 I/O/T RTC_GPIO17, GPIO17, U1TXD, ADC2_CH6 -20 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, CLK_OUT3 -21 5V P 5 V 电源 -22 G G 接地 -==== ==== ========== ===================================================================== - - -J3 -^^^ - -==== ==== ========== ===================================================================== -序号 名称 类型 功能 -==== ==== ========== ===================================================================== -1 G G 接地 -2 RST I EN -3 46 I/O/T GPIO46 -4 45 I/O/T GPIO45 -5 RX I/O/T U0RXD, GPIO44, CLK_OUT2 -6 TX I/O/T U0TXD, GPIO43, CLK_OUT1 -7 42 I/O/T MTMS, GPIO42 -8 41 I/O/T MTDI, GPIO41, CLK_OUT1 -9 40 I/O/T MTDO, GPIO40, CLK_OUT2 -10 39 I/O/T MTCK, GPIO39, CLK_OUT3, SUBSPICS1 -11 38 I/O/T GPIO38, FSPIWP, SUBSPIWP -12 37 I/O/T SPIDQS, GPIO37, FSPIQ, SUBSPIQ -13 36 I/O/T SPIIO7, GPIO36, FSPICLK, SUBSPICLK -14 35 I/O/T SPIIO6, GPIO35, FSPID, SUBSPID -15 34 I/O/T SPIIO5, GPIO34, FSPICS0, SUBSPICS0 -16 33 I/O/T SPIIO4, GPIO33, FSPIHD, SUBSPIHD -17 26 I/O/T SPICS1, GPIO26 -18 21 I/O/T RTC_GPIO21, GPIO21 -19 20 I/O/T RTC_GPIO20, GPIO20, U1CTS, ADC2_CH9, CLK_OUT1, USB_D+ -20 19 I/O/T RTC_GPIO19, GPIO19, U1RTS, ADC2_CH8, CLK_OUT2, USB_D- -21 48 I/O/T SPICLK_N, GPIO48, SUBSPICLK_N_DIFF, RGB LED -22 47 I/O/T SPICLK_P, GPIO47, SUBSPICLK_P_DIFF -==== ==== ========== ===================================================================== - - -.. [#] P:电源;I:输入;O:输出;T:可设置为高阻。 - - - -有关管脚功能名称的解释,请参考 `ESP32-S3 技术规格书 `_ (PDF)。 - - -管脚布局 -^^^^^^^^^^^ - -.. figure:: ../../../_static/ESP32-S3_DevKitM-1_pinlayout.jpg - :align: center - :scale: 50% - :alt: ESP32-S3-DevKitM-1(点击放大) - :figclass: align-center - - ESP32-S3-DevKitM-1 管脚布局(点击放大) - - -硬件版本 -============ - -无历史版本。 - - -相关文档 -======== - -- `ESP32-S3 技术规格书 `_ (PDF) -- `ESP32-S3-MINI-1 & ESP32-S3-MINI-1U 技术规格书 `_ (PDF) -- `ESP32-S3-DevKitM-1 原理图 `_ (PDF) -- `ESP32-S3-DevKitM-1 PCB 布局图 `_ (PDF) -- `ESP32-S3-DevKitM-1 尺寸图 `_ (PDF) -- `ESP32-S3-DevKitM-1 尺寸图源文件 `_ (DXF) - 可使用 `Autodesk Viewer `_ 查看 - -有关本开发板的更多设计文档,请联系我们的商务部门 `sales@espressif.com `_。 diff --git a/docs/zh_CN/migration-guides/release-5.x/5.4/index.rst b/docs/zh_CN/migration-guides/release-5.x/5.4/index.rst index 156a9900b68e..e2256533e951 100644 --- a/docs/zh_CN/migration-guides/release-5.x/5.4/index.rst +++ b/docs/zh_CN/migration-guides/release-5.x/5.4/index.rst @@ -9,3 +9,5 @@ gcc system bluetooth-classic + storage + wifi diff --git a/docs/zh_CN/migration-guides/release-5.x/5.4/storage.rst b/docs/zh_CN/migration-guides/release-5.x/5.4/storage.rst new file mode 100644 index 000000000000..edb535412acb --- /dev/null +++ b/docs/zh_CN/migration-guides/release-5.x/5.4/storage.rst @@ -0,0 +1,7 @@ +存储 +======= + +SPI flash 驱动 +^^^^^^^^^^^^^^^^^^^^^^ + +XMC-C 系列闪存 suspend 功能的支持已被移除。根据闪存制造商的反馈,在某些情况下,XMC-C 闪存需要在 resume 和下一条命令之间间隔 1 毫秒。这对于软件请求来说时间太长。基于上述原因,为了安全使用 suspend 功能,我们决定取消 XMC-C 系列的闪存挂起支持。但是你依旧可以强行通过 `CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND` 的配置使能这个功能。如果您有任何疑问,请联系 espressif 业务支持。 diff --git a/docs/zh_CN/migration-guides/release-5.x/5.4/system.rst b/docs/zh_CN/migration-guides/release-5.x/5.4/system.rst index dbe6984ddd7b..b86411e98f75 100644 --- a/docs/zh_CN/migration-guides/release-5.x/5.4/system.rst +++ b/docs/zh_CN/migration-guides/release-5.x/5.4/system.rst @@ -3,11 +3,17 @@ :link_to_translation:`en:[English]` +ESP-Common +---------- + +``__VA_NARG__`` 及其相关宏已被重新命名以避免命名冲突,请使用带有 ESP 前缀的新名称,例如 ``ESP_VA_NARG``。 + 日志 ------ - `esp_log_buffer_hex` 已弃用,应使用 `ESP_LOG_BUFFER_HEX` 替代。 - `esp_log_buffer_char` 已弃用,应使用 `ESP_LOG_BUFFER_CHAR` 替代。 +- ``CONFIG_LOG_COLORS`` 的默认值设置为 false。默认情况下,IDF Monitor 在主机端添加颜色。如需在其他控制台监视器的日志输出中启用颜色,请将 ``CONFIG_LOG_COLORS`` 设置为 true。如需在 IDF Monitor 中关闭自动的日志颜色显示,请运行命令: ``idf.py monitor --disable-auto-color``。 ESP ROM --------- diff --git a/docs/zh_CN/migration-guides/release-5.x/5.4/wifi.rst b/docs/zh_CN/migration-guides/release-5.x/5.4/wifi.rst new file mode 100644 index 000000000000..ed9be5db8df9 --- /dev/null +++ b/docs/zh_CN/migration-guides/release-5.x/5.4/wifi.rst @@ -0,0 +1,24 @@ +Wi-Fi +===== + +:link_to_translation:`en:[English]` + + +Wi-Fi 扫描和连接 +------------------------ + + 以下类型已被更改: + - :component_file:`esp_wifi/include/esp_wifi_he_types.h` + + - :cpp:struct:`esp_wifi_htc_omc_t` 中: + + - ``uph_id``, ``ul_pw_headroom``, ``min_tx_pw_flag`` 字段被弃用 + + - :component_file:`esp_wifi/include/esp_wifi_types_generic.h` + + - :cpp:struct:`wifi_ap_record_t` 中: + + - ``bandwidth`` 的类型从 ``uint8_t`` 更改为 ``wifi_bandwidth_t`` + + + diff --git a/docs/zh_CN/security/flash-encryption.rst b/docs/zh_CN/security/flash-encryption.rst index da68d9e4b515..34433b3bdf46 100644 --- a/docs/zh_CN/security/flash-encryption.rst +++ b/docs/zh_CN/security/flash-encryption.rst @@ -39,7 +39,7 @@ flash 加密功能用于加密与 {IDF_TARGET_NAME} 搭载使用的片外 flash 启用 flash 加密后,会默认加密以下类型的数据: -- :ref:`second-stage-bootloader` (固件引导加载程序) +- :ref:`second-stage-bootloader` - 分区表 - :ref:`nvs_encr_key_partition` - Otadata @@ -48,7 +48,7 @@ flash 加密功能用于加密与 {IDF_TARGET_NAME} 搭载使用的片外 flash 其他类型的数据将视情况进行加密: - 分区表中标有 ``encrypted`` 标志的分区。如需了解详情,请参考 :ref:`encrypted-partition-flag`。 -- 如果启用了安全启动,则会对安全启动引导程序摘要进行加密(见下文)。 +- 如果启用了安全启动,则会对安全启动引导加载程序摘要进行加密(见下文)。 .. _flash-encryption-efuse: @@ -175,39 +175,39 @@ flash 加密操作由 {IDF_TARGET_NAME} 上的多个 eFuse 控制,具体 eFuse flash 的加密过程 ------------------ -假设 eFuse 值处于默认状态,且固件的引导加载程序编译为支持 flash 加密,则 flash 加密的具体过程如下: +假设 eFuse 值处于默认状态,且二级引导加载程序编译为支持 flash 加密,则 flash 加密的具体过程如下: .. only:: not SOC_FLASH_ENCRYPTION_XTS_AES - 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。 + 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。一级 (ROM) 引导加载程序加载二级引导加载程序。 - 2. 固件的引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b0000000``)。因为该值为 0(偶数位),固件的引导加载程序将配置并启用 flash 加密块,同时将 ``FLASH_CRYPT_CONFIG`` eFuse 的值编程为 0xF。关于 flash 加密块的更多信息,请参考 *{IDF_TARGET_NAME} 技术参考手册* > *eFuse 控制器 (eFuse)* > *flash 加密块* [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。 + 2. 二级引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b0000000``)。因为该值为 0(偶数位),二级引导加载程序将配置并启用 flash 加密块,同时将 ``FLASH_CRYPT_CONFIG`` eFuse 的值编程为 0xF。关于 flash 加密块的更多信息,请参考 *{IDF_TARGET_NAME} 技术参考手册* > *eFuse 控制器 (eFuse)* > *flash 加密块* [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。 - 3. 固件引导加载程序首先检查 eFuse 中是否已经存在有效密钥(例如用 espefuse 工具烧写的密钥),如果存在,则会跳过密钥生成,并将该密钥用于 flash 加密过程。否则,固件引导加载程序会使用 RNG(随机数发生器)模块生成一个 AES-256 位密钥,并将其写入 ``flash_encryption`` eFuse 中。由于已设置了 ``flash_encryption`` eFuse 的读保护位和写保护位,因此无法通过软件访问密钥。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。 + 3. 二级引导加载程序首先检查 eFuse 中是否已经存在有效密钥(例如用 espefuse 工具烧写的密钥),如果存在,则会跳过密钥生成,并将该密钥用于 flash 加密过程。否则,二级引导加载程序会使用 RNG(随机数发生器)模块生成一个 AES-256 位密钥,并将其写入 ``flash_encryption`` eFuse 中。由于已设置了 ``flash_encryption`` eFuse 的读保护位和写保护位,因此无法通过软件访问密钥。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。 - 4. flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有 ``加密`` 标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 + 4. flash 加密块将加密 flash 的内容(二级引导加载程序、应用程序、以及标有 ``加密`` 标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 - 5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b0000001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数个比特位。 + 5. 二级引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b0000001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数个比特位。 - 6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序仅设置 ``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE`` 的 eFuse 位,以便 UART 引导加载程序重新烧录加密的二进制文件。此外, ``{IDF_TARGET_CRYPT_CNT}`` 的 eFuse 位不受写入保护。 + 6. 对于 :ref:`flash-enc-development-mode`,二级引导加载程序仅设置 ``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE`` 的 eFuse 位,以便 UART 引导加载程序重新烧录加密的二进制文件。此外, ``{IDF_TARGET_CRYPT_CNT}`` 的 eFuse 位不受写入保护。 - 7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置 ``DISABLE_DL_ENCRYPT``、``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE`` 的 eFuse 位为 1,以防止 UART 引导加载程序解密 flash 内容。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 + 7. 对于 :ref:`flash-enc-release-mode`,二级引导加载程序设置 ``DISABLE_DL_ENCRYPT``、``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE`` 的 eFuse 位为 1,以防止 UART 引导加载程序解密 flash 内容。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 - 8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 + 8. 重新启动设备以开始执行加密镜像。二级引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 .. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256 - 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。 + 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。一级 (ROM) 引导加载程序加载二级引导加载程序。 - 2. 固件的引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),固件引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 *{IDF_TARGET_NAME} 技术参考手册* > *eFuse 控制器 (eFuse)* > *自动加密块* [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。 + 2. 二级引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),二级引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 *{IDF_TARGET_NAME} 技术参考手册* > *eFuse 控制器 (eFuse)* > *自动加密块* [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。 - 3. 固件引导加载程序首先检查 eFuse 中是否已经存在有效密钥(例如用 espefuse 工具烧写的密钥),如果存在,则会跳过密钥生成,并将该密钥用于 flash 加密过程。否则,固件引导加载程序使用 RNG(随机数发生器)模块生成一个 256 位或 512 位的密钥,具体位数取决于 :ref:`生成的 XTS-AES 密钥的大小 `,然后将其分别写入一个或两个 `BLOCK_KEYN` eFuse 中。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于上述一个或两个 ``BLOCK_KEYN`` eFuse 已设置了读保护和写保护位,因此无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。 + 3. 二级引导加载程序首先检查 eFuse 中是否已经存在有效密钥(例如用 espefuse 工具烧写的密钥),如果存在,则会跳过密钥生成,并将该密钥用于 flash 加密过程。否则,二级引导加载程序使用 RNG(随机数发生器)模块生成一个 256 位或 512 位的密钥,具体位数取决于 :ref:`生成的 XTS-AES 密钥的大小 `,然后将其分别写入一个或两个 `BLOCK_KEYN` eFuse 中。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于上述一个或两个 ``BLOCK_KEYN`` eFuse 已设置了读保护和写保护位,因此无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。 - 4. flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 + 4. flash 加密块将加密 flash 的内容(二级引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 - 5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。 + 5. 二级引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。 - 6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,固件引导加载程序默认置位以下 eFuse 位: + 6. 对于 :ref:`flash-enc-development-mode`,二级引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,二级引导加载程序默认置位以下 eFuse 位: .. list:: @@ -217,45 +217,45 @@ flash 的加密过程 - ``HARD_DIS_JTAG`` - ``DIS_LEGACY_SPI_BOOT`` - 7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置所有在开发模式下设置的 eFuse 位。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 + 7. 对于 :ref:`flash-enc-release-mode`,二级引导加载程序设置所有在开发模式下设置的 eFuse 位。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 - 8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 + 8. 重新启动设备以开始执行加密镜像。二级引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 .. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and not SOC_FLASH_ENCRYPTION_XTS_AES_256 and not SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK - 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。 + 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。一级 (ROM) 引导加载程序加载二级引导加载程序。 - 2. 固件的引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),固件引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。 + 2. 二级引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),二级引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。 - 3. 固件的引导加载程序使用 RNG(随机数发生器)模块生成 256 位密钥,然后将其写入 `BLOCK_KEYN` eFuse。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于 ``BLOCK_KEYN`` eFuse 已设置了读保护和写保护位,因此无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。如果 eFuse 中已经存在有效密钥(例如用 espefuse 工具烧写的密钥),则会跳过密钥生成,并将该密钥用于 flash 加密过程。 + 3. 二级引导加载程序使用 RNG(随机数发生器)模块生成 256 位密钥,然后将其写入 `BLOCK_KEYN` eFuse。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于 ``BLOCK_KEYN`` eFuse 已设置了读保护和写保护位,因此无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。如果 eFuse 中已经存在有效密钥(例如用 espefuse 工具烧写的密钥),则会跳过密钥生成,并将该密钥用于 flash 加密过程。 - 4. flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 + 4. flash 加密块将加密 flash 的内容(二级引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 - 5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。 + 5. 二级引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。 - 6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,固件引导加载程序设置 ``DIS_DOWNLOAD_ICACHE``、 ``DIS_PAD_JTAG``、 ``DIS_USB_JTAG`` 和 ``DIS_LEGACY_SPI_BOOT`` eFuse 位。 + 6. 对于 :ref:`flash-enc-development-mode`,二级引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,二级引导加载程序设置 ``DIS_DOWNLOAD_ICACHE``、 ``DIS_PAD_JTAG``、 ``DIS_USB_JTAG`` 和 ``DIS_LEGACY_SPI_BOOT`` eFuse 位。 - 7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 + 7. 对于 :ref:`flash-enc-release-mode`,二级引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 - 8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 + 8. 重新启动设备以开始执行加密镜像。二级引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 .. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK - 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。 + 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载二级引导加载程序。 - 2. 固件的引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),固件引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。 + 2. 二级引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),二级引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。 - 3. 固件的引导加载程序使用 RNG(随机数发生器)模块生成 256 位或 128 位密钥(具体位数取决于 :ref:`生成的 XTS-AES 密钥大小 `),然后将其写入 `BLOCK_KEY0` eFuse。同时,根据所选选项,软件对 ``XTS_KEY_LENGTH_256`` 进行更新。由于 ``BLOCK_KEY0`` eFuse 已设置写保护和读保护位,故无法通过软件访问密钥。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。若使用 128 位 flash 加密密钥,则整个 eFuse 密钥块都受写保护,但只有低 128 位受读保护,高 128 位是可读的,以满足安全启动的需要。如果 flash 加密密钥是 256 位,那么 ``XTS_KEY_LENGTH_256`` 为 1,否则为 0。为防止意外将 eFuse 从 0 改为 1,为 RELEASE 模式设置了一个写保护位。如果 eFuse 中已经存在有效密钥(例如用 espefuse 工具烧写的密钥),则跳过密钥生成,并将该密钥用于 flash 加密过程。 + 3. 二级引导加载程序使用 RNG(随机数发生器)模块生成 256 位或 128 位密钥(具体位数取决于 :ref:`生成的 XTS-AES 密钥大小 `),然后将其写入 `BLOCK_KEY0` eFuse。同时,根据所选选项,软件对 ``XTS_KEY_LENGTH_256`` 进行更新。由于 ``BLOCK_KEY0`` eFuse 已设置写保护和读保护位,故无法通过软件访问密钥。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。若使用 128 位 flash 加密密钥,则整个 eFuse 密钥块都受写保护,但只有低 128 位受读保护,高 128 位是可读的,以满足安全启动的需要。如果 flash 加密密钥是 256 位,那么 ``XTS_KEY_LENGTH_256`` 为 1,否则为 0。为防止意外将 eFuse 从 0 改为 1,为 RELEASE 模式设置了一个写保护位。如果 eFuse 中已经存在有效密钥(例如用 espefuse 工具烧写的密钥),则跳过密钥生成,并将该密钥用于 flash 加密过程。 - 4. flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 + 4. flash 加密块将加密 flash 的内容(二级引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 - 5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。 + 5. 二级引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。 - 6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,固件引导加载程序设置 ``DIS_DOWNLOAD_ICACHE``、``DIS_PAD_JTAG`` 和 ``DIS_DIRECT_BOOT`` eFuse 位。 + 6. 对于 :ref:`flash-enc-development-mode`,二级引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,二级引导加载程序设置 ``DIS_DOWNLOAD_ICACHE``、``DIS_PAD_JTAG`` 和 ``DIS_DIRECT_BOOT`` eFuse 位。 - 7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 + 7. 对于 :ref:`flash-enc-release-mode`,二级引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 - 8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 + 8. 重新启动设备以开始执行加密镜像。二级引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 在开发阶段常需编写不同的明文 flash 镜像并测试 flash 的加密过程。这要求固件下载模式能够根据需求不断加载新的明文镜像。但是,在制造和生产过程中,出于安全考虑,固件下载模式不应有权限访问 flash 内容。 @@ -316,7 +316,7 @@ flash 加密设置 这个命令不包括任何应该写入 flash 分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。 -该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为“加密”的分区,然后复位。就地加密可能需要时间,对于大分区最多需要一分钟。之后,应用程序在运行时解密并执行命令。 +该命令将向 flash 写入未加密的镜像:二级引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,二级引导加载程序会加密:二级引导加载程序、应用程序分区和标记为“加密”的分区,然后复位。就地加密可能需要时间,对于大分区最多需要一分钟。之后,应用程序在运行时解密并执行命令。 下面是启用 flash 加密后 {IDF_TARGET_NAME} 首次启动时的样例输出: @@ -486,7 +486,7 @@ flash 加密设置 这个命令不包括任何应该被写入 flash 上的分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。 - 该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。 + 该命令将向 flash 写入未加密的镜像:二级引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,二级引导加载程序会加密:二级引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。 如果使用开发模式,那么更新和重新烧录二进制文件最简单的方法是 :ref:`encrypt-partitions`。 @@ -549,7 +549,7 @@ flash 加密设置 这个命令不包括任何应该被写入 flash 分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。 - 该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。 + 该命令将向 flash 写入未加密的镜像:二级引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,二级引导加载程序会加密:二级引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。 一旦在发布模式下启用 flash 加密,引导加载程序将写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse。 @@ -576,14 +576,14 @@ flash 加密设置 外部启用 flash 加密 ---------------------------------- -在上述过程中,对与 flash 加密相关的 eFuse 是通过固件引导加载程序烧写的,或者,也可以借助 ``espefuse`` 工具烧写 eFuse。如需了解详情,请参考 :ref:`enable-flash-encryption-externally`。 +在上述过程中,对与 flash 加密相关的 eFuse 是通过二级引导加载程序烧写的,或者,也可以借助 ``espefuse`` 工具烧写 eFuse。如需了解详情,请参考 :ref:`enable-flash-encryption-externally`。 可能出现的错误 ----------------- 一旦启用 flash 加密,``{IDF_TARGET_CRYPT_CNT}`` 的 eFuse 值将设置为奇数位。这意味着所有标有加密标志的分区都会包含加密的密本。如果 {IDF_TARGET_NAME} 错误地加载了明文数据,则会出现以下三种典型的错误情况: -1. 如果通过 **明文固件引导加载程序镜像** 重新烧录了引导加载程序分区,则 ROM 加载器将无法加载固件引导加载程序,并会显示以下错误类型: +1. 如果通过 **明文二级引导加载程序镜像** 重新烧录了引导加载程序分区,则 ROM 加载器将无法加载二级引导加载程序,并会显示以下错误类型: .. only:: esp32 @@ -635,7 +635,7 @@ flash 加密设置 如果 flash 内容被擦除或损坏,也会出现这个错误。 -2. 如果固件的引导加载程序已加密,但通过 **明文分区表镜像** 重新烧录了分区表,引导加载程序将无法读取分区表,从而出现以下错误: +2. 如果二级引导加载程序已加密,但通过 **明文分区表镜像** 重新烧录了分区表,引导加载程序将无法读取分区表,从而出现以下错误: .. code-block:: bash @@ -727,7 +727,7 @@ flash 加密范围 - flash 中可执行的应用程序代码 (IROM)。 - 所有存储于 flash 中的只读数据 (DROM)。 - 通过函数 :cpp:func:`spi_flash_mmap` 访问的任意数据。 -- ROM 引导加载程序读取的固件引导加载程序镜像。 +- ROM 引导加载程序读取的二级引导加载程序镜像。 .. important:: @@ -976,7 +976,7 @@ flash 加密的高级功能 ``FLASH_CRYPT_CONFIG`` eFuse 决定 flash 加密密钥中随块偏移“调整”的位数。详情可参考 :ref:`flash-encryption-algorithm`。 - 首次启动固件引导加载程序时,该值始终设置为最大值 `0xF`。 + 首次启动二级引导加载程序时,该值始终设置为最大值 `0xF`。 可手动写入这些 eFuse,并在首次启动前对其写保护,以便选择不同的调整值。但不推荐该操作。 diff --git a/docs/zh_CN/security/secure-boot-v1.rst b/docs/zh_CN/security/secure-boot-v1.rst index bff6c2691af6..69ee5be89de8 100644 --- a/docs/zh_CN/security/secure-boot-v1.rst +++ b/docs/zh_CN/security/secure-boot-v1.rst @@ -30,11 +30,11 @@ - 为理解安全启动过程,请熟悉标准 :doc:`../api-guides/startup`。 -- 安全启动过程会验证启动过程的两个阶段,包括初始软件引导加载程序和随后的分区与应用加载,形成一条信任链。 +- 安全启动过程会验证启动过程的两个阶段,包括二级引导加载程序的加载和随后的分区与应用加载,形成一条信任链。 安全启动过程概述 ----------------------------- +--------------------- 以下是对安全启动过程的宏观概述,操作指南请参阅 :ref:`secure-boot-how-to`,进一步的技术细节请参阅 :ref:`secure-boot-technical-details`: @@ -42,18 +42,18 @@ 2. 安全启动默认在构建过程中签名镜像和分区表数据。配置项 ``Secure boot private signing key`` 是指向 PEM 格式文件中 ECDSA 公钥/私钥对的文件路径。 -3. 启用安全启动支持的 ESP-IDF 负责构建软件引导加载程序镜像,签名验证所需公钥已集成到引导加载程序镜像中。此软件引导加载程序镜像将刷写到 0x1000 偏移地址。 +3. 启用安全启动支持的 ESP-IDF 负责构建二级引导加载程序镜像,签名验证所需公钥已集成到该镜像中。此二级引导加载程序镜像将烧写到 0x1000 偏移地址。 -4. 初次启动时,软件引导加载程序按以下方式启用安全启动: +4. 初次启动时,二级引导加载程序按以下方式启用安全启动: - - 硬件安全启动支持生成设备安全引导加载程序密钥以及安全摘要。密钥借助硬件随机数生成,随后存储在 eFuse 中,受读写保护。硬件安全启动还支持生成安全摘要,摘要源自密钥、初始向量 (IV) 和引导加载程序镜像内容。 + - 硬件安全启动支持生成设备安全引导加载程序密钥以及安全摘要。密钥借助硬件随机数生成,随后存储在 eFuse 中,受读写保护。硬件安全启动还支持生成安全摘要,摘要源自密钥、初始向量 (IV) 和该引导加载程序镜像的内容。 - 安全摘要将刷写到 flash 中的 0x0 偏移地址。 - 根据安全启动配置,烧录 eFuse 以禁用 JTAG 和 ROM 基本解释器。**强烈建议** 禁用 JTAG 和 ROM 基本解释器。 - - 烧录 ABS_DONE_0 eFuse 后,引导加载程序将始终启用安全启动,软件引导加载程序也随之受到保护。此后,芯片只有在摘要匹配时才会启动引导加载程序镜像。 + - 烧录 ABS_DONE_0 eFuse 后,该二级引导加载程序将始终启用安全启动,并随之受到保护。此后,芯片只有在摘要匹配时才会启动引导加载程序镜像。 -5. 在后续启动过程中,ROM 引导加载程序检测到安全启动 eFuse 已烧录,读取 0x0 处保存的摘要,然后使用硬件安全启动支持来将其与新计算的摘要进行对比。如果摘要不匹配,启动过程终止。摘要读取和对比完全由硬件完成,软件无法读取计算的摘要。更多技术详情,请参阅 :ref:`secure-boot-hardware-support`。 +5. 在后续启动过程中,一级 (ROM) 引导加载程序检测到安全启动 eFuse 已烧录,读取 0x0 处保存的摘要,然后使用硬件安全启动支持来将其与新计算的摘要进行对比。如果摘要不匹配,启动过程终止。摘要读取和对比完全由硬件完成,软件无法读取计算的摘要。更多技术详情,请参阅 :ref:`secure-boot-hardware-support`。 -6. 在安全启动模式下运行时,软件引导加载程序使用安全启动签名密钥,该密钥的公钥已嵌入引导加载程序本身,并作为引导加载程序的一部分进行验证,以在启动前验证附加到所有后续分区表和应用程序镜像的签名。 +6. 在安全启动模式下运行时,二级引导加载程序使用安全启动签名密钥,该密钥的公钥已嵌入该引导加载程序本身,并作为该引导加载程序的一部分进行验证,以在启动前验证附加到所有后续分区表和应用程序镜像的签名。 密钥 @@ -61,7 +61,7 @@ 安全启动过程中使用以下密钥: -- 安全引导加载程序密钥是一个 256 位 AES 密钥,存储在 eFuse 块 2 中。引导加载程序可以使用内部硬件随机数生成器自行生成该密钥,无需手动提供。也可以选择提供该密钥,请参阅 :ref:`secure-boot-reflashable`。在启用安全启动之前,存储该密钥的 eFuse 受到读取和写入保护,防止软件访问。 +- 安全引导加载程序密钥是一个 256 位 AES 密钥,存储在 eFuse 块 2 中。安全引导加载程序可以使用内部硬件随机数生成器自行生成该密钥,无需手动提供。也可以选择提供该密钥,请参阅 :ref:`secure-boot-reflashable`。在启用安全启动之前,存储该密钥的 eFuse 受到读取和写入保护,防止软件访问。 - eFuse 块 2 默认编码方案为 ``None``,块中存储了一个 256 位密钥。在某些版本的 {IDF_TARGET_NAME} 上,编码方案设置为 ``3/4 Encoding``,CODING_SCHEME eFuse 值为 1,且块中必须存储一个 192 位密钥。 @@ -73,9 +73,9 @@ - ``secure boot signing key`` 是标准的 ECDSA 公钥/私钥对,以 PEM 格式存储,请参阅 :ref:`secure-boot-image-signing-algorithm`。 - - 该密钥对的公钥用于验证签名,但不用于创建签名。它编译到软件引导加载程序中,并在启动继续前验证启动过程的第二阶段,包括分区表和应用程序镜像。该公钥可以自由分发,无需保密。 + - 该密钥对的公钥仅用于验证签名,但不用于创建签名。它编译到二级引导加载程序中,并在启动继续前验证启动过程的第二阶段,包括分区表和应用程序镜像。该公钥可以自由分发,无需保密。 - - 该密钥对的私钥必须严格保密。一旦持有该私钥,即可用它对配置了安全启动和匹配公钥的引导加载程序进行身份验证。 + - 该密钥对的私钥必须严格保密。一旦持有该私钥,即可用它对任何配置了安全启动和匹配公钥的引导加载程序进行身份验证。 引导加载程序大小 @@ -117,7 +117,7 @@ 如果启用了安全启动,``idf.py flash`` 不会烧录引导加载程序。 -8. 重置 {IDF_TARGET_NAME} 以启动烧录的软件引导加载程序。该软件引导加载程序会在芯片上启用安全启动,验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。 +8. 重置 {IDF_TARGET_NAME} 以启动烧录的二级引导加载程序。该二级引导加载程序会在芯片上启用安全启动,验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。 .. note:: @@ -127,12 +127,12 @@ 如果在初次启动过程中重置或关闭了 {IDF_TARGET_NAME},它会在下次启动时重新开始上述步骤。 -9. 在后续启动过程中,安全启动硬件将使用安全引导加载程序密钥验证软件引导加载程序是否更改,随后,软件引导加载程序将使用安全启动签名密钥的公钥部分来验证已签名的分区表和应用程序镜像。 +9. 在后续启动过程中,安全启动硬件将使用安全引导加载程序密钥验证二级引导加载程序是否更改,随后,二级引导加载程序将使用安全启动签名密钥的公钥部分来验证已签名的分区表和应用程序镜像。 .. _secure-boot-reflashable: -可重复烧录的软件引导加载程序 +可重复烧录的二级引导加载程序 ------------------------------- 对于生产设备,推荐使用 ``Secure Boot: One-Time Flash`` 配置。该模式下,每个设备都对应拥有始终存储在设备内部的唯一密钥。 @@ -229,7 +229,7 @@ 安全启动硬件支持 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -安全启动验证的第一阶段为检查软件引导加载程序,该检查通过硬件完成。{IDF_TARGET_NAME} 的安全启动支持硬件提供以下三种基本操作: +安全启动验证的第一阶段为检查二级引导加载程序,该检查通过硬件完成。{IDF_TARGET_NAME} 的安全启动支持硬件提供以下三种基本操作: 1. 通过硬件随机数生成器生成一系列随机字节。 diff --git a/docs/zh_CN/security/secure-boot-v2.rst b/docs/zh_CN/security/secure-boot-v2.rst index 640a32889ebc..2db4b0aaa7b8 100644 --- a/docs/zh_CN/security/secure-boot-v2.rst +++ b/docs/zh_CN/security/secure-boot-v2.rst @@ -29,9 +29,9 @@ .. only:: esp32 - 芯片版本低于 v3.0 的 ESP32 安全启动请参阅 :doc:`secure-boot-v1`。如果你的芯片版本支持安全启动 v2,推荐使用此模式,相比安全启动 v1 更安全且灵活。 + 芯片版本低于 v3.0 的 ESP32 安全启动请参阅 :doc:`secure-boot-v1`。如果当前芯片版本支持安全启动 v2,推荐使用此模式,相比安全启动 v1 更安全且灵活。 - 安全启动 v2 使用基于 {IDF_TARGET_SBV2_SCHEME} 的应用程序和引导加载程序 (bootloader) :ref:`second-stage-bootloader` 验证。若需要使用 {IDF_TARGET_SBV2_SCHEME} 方案对应用程序签名,且无需对 bootloader 签名,同样可以参考本文档。 + 安全启动 v2 使用基于 {IDF_TARGET_SBV2_SCHEME} 的应用程序和 :ref:`second-stage-bootloader` 验证。若需要使用 {IDF_TARGET_SBV2_SCHEME} 方案对应用程序签名,且无需对引导加载程序签名,同样可以参考本文档。 .. only:: esp32 @@ -49,7 +49,7 @@ 背景 ---------- -安全启动通过检查每个启动的软件是否已签名来确保设备不会运行任何未经授权(即未签名)的代码。在 {IDF_TARGET_NAME} 上,这些软件包括第二阶段的 bootloader 和每个应用程序的二进制文件。注意,第一阶段的 bootloader 是无法更改的 ROM 代码,因此不需要签名。 +安全启动通过检查每个启动的软件是否已签名来确保设备不会运行任何未经授权(即未签名)的代码。在 {IDF_TARGET_NAME} 上,这些软件包括二级引导加载程序和每个应用程序的二进制文件。注意,一级 (ROM) 引导加载程序是无法更改的 ROM 代码,因此不需要签名。 .. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC) @@ -65,9 +65,9 @@ {IDF_TARGET_NAME} 的安全启动包括以下步骤: -1. 第一阶段 bootloader (ROM boot) 仍处于 ROM 中,加载第二阶段 bootloader,并验证第二阶段 bootloader 的 {IDF_TARGET_SBV2_SCHEME} 签名。验证通过后方可进入第二阶段。 +1. 一级 (ROM) 引导加载程序加载二级引导加载程序,并验证二级引导加载程序的 {IDF_TARGET_SBV2_SCHEME} 签名。验证通过后,方可运行二级引导加载程序。 -2. 第二阶段 bootloader 加载特定应用程序镜像时,会验证应用程序的 {IDF_TARGET_SBV2_SCHEME} 签名。若验证通过,则执行应用程序镜像。 +2. 二级引导加载程序加载特定应用程序镜像,并验证应用程序的 {IDF_TARGET_SBV2_SCHEME} 签名。若验证通过,则执行应用程序镜像。 优势 @@ -83,12 +83,12 @@ - 芯片在量产时最多能生成并存储三个公钥。 - - {IDF_TARGET_NAME} 支持永久注销个别公钥,对此可以选择保守或激进的配置。 + - {IDF_TARGET_NAME} 支持永久撤销个别公钥,对此可以选择保守或激进的配置。 - - 保守配置:在此情况下,只有在 bootloader 和应用程序成功迁移到新密钥后才会注销旧密钥。 + - 保守配置:在此情况下,只有在引导加载程序和应用程序成功迁移到新密钥后才会注销旧密钥。 - 激进配置:在此情况下,只要使用此密钥验证失败,就会立即注销该密钥。 -- 应用程序和软件 bootloader 采用相同的镜像格式和签名验证方法。 +- 应用程序和二级引导加载程序采用相同的镜像格式和签名验证方法。 - 设备不存储任何机密信息,因此可以免受被动侧通道攻击的影响,如时序分析或功耗分析。 @@ -98,39 +98,39 @@ 以下为使用安全启动 v2 流程的概述。有关如何启用安全启动,请参阅 :ref:`secure-boot-v2-howto`。 -安全启动 v2 使用专用的 *签名块* 验证 bootloader 镜像和应用程序二进制镜像,每个镜像末尾都附加了一个单独生成的签名块。 +安全启动 v2 使用专用的 *签名块* 验证引导加载程序镜像和应用程序二进制镜像,每个镜像末尾都附加了一个单独生成的签名块。 .. only:: esp32 - 在 ESP32 芯片版本 v3.0 中,bootloader 或应用程序镜像只能附加一个签名块。 + 在 ESP32 芯片版本 v3.0 中,引导加载程序或应用程序镜像只能附加一个签名块。 .. only:: esp32c2 - 在 {IDF_TARGET_NAME} 中,bootloader 或应用程序镜像只能附加一个签名块。 + 在 {IDF_TARGET_NAME} 中,引导加载程序或应用程序镜像只能附加一个签名块。 .. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS - 在 {IDF_TARGET_NAME} 中,bootloader 或应用程序镜像至多可以附加三个签名块。 + 在 {IDF_TARGET_NAME} 中,引导加载程序或应用程序镜像至多可以附加三个签名块。 每个签名块包含前一个镜像的签名和相应的 {IDF_TARGET_SBV2_KEY} 公钥。有关格式详情,请参阅 :ref:`signature-block-format`。{IDF_TARGET_SBV2_KEY} 公钥的摘要存储在 eFuse 中。 -应用程序镜像不仅在每次启动时验证,也会在每次空中升级 (OTA) 时验证。如果当前所选 OTA 应用程序镜像无法验证,bootloader 将回退,并寻找其他正确签名的应用程序镜像。 +应用程序镜像不仅在每次启动时验证,也会在每次空中升级 (OTA) 时验证。如果当前所选 OTA 应用程序镜像无法验证,引导加载程序将回退,并寻找其他正确签名的应用程序镜像。 安全启动 v2 流程遵循以下步骤: 1. 启动时,ROM 代码检查 eFuse 中的安全启动 v2 位。如果禁用了安全启动,则执行普通启动;如果启用了安全启动,将继续以下步骤。 -2. ROM 代码验证 bootloader 的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。 +2. ROM 代码验证引导加载程序的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。 -3. ROM 代码使用原始镜像数据、相应的签名块以及 eFuse 验证 bootloader 镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。 +3. ROM 代码使用原始镜像数据、相应的签名块以及 eFuse 验证引导加载程序镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。 -4. ROM 代码执行 bootloader 。 +4. ROM 代码执行引导加载程序。 -5. bootloader 验证应用程序镜像的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。 +5. 引导加载程序验证应用程序镜像的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。 -6. bootloader 使用原始镜像数据、相应的签名块以及 eFuse 验证 bootloader 镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。如果验证失败,但发现了其他应用程序镜像, bootloader 将使用步骤 5 到 7 验证另一个镜像。该过程将重复,直至找到有效镜像,或所有镜像验证完毕。 +6. 引导加载程序使用原始镜像数据、相应的签名块以及 eFuse 验证引导加载程序镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。如果验证失败,但发现了其他应用程序镜像,引导加载程序将使用步骤 5 到 7 验证另一个镜像。该过程将重复,直至找到有效镜像,或所有镜像验证完毕。 -7. bootloader 执行经验证的应用程序镜像。 +7. 引导加载程序执行经验证的应用程序镜像。 .. _signature-block-format: @@ -313,29 +313,29 @@ 如果存储在某个签名块中的公钥是适用于当前设备的有效公钥,且该签名块中存储的签名与从 flash 中读取的镜像数据计算出的签名匹配,则该镜像通过验证。 -1. 将嵌入在 bootloader 签名块中的公钥生成的 SHA-256 哈希摘要与存储在 eFuse 中的摘要进行比较,如果公钥的哈希摘要无法与 eFuse 中的任何哈希摘要匹配,则验证失败。 +1. 将嵌入在引导加载程序签名块中的公钥生成的 SHA-256 哈希摘要与存储在 eFuse 中的摘要进行比较,如果公钥的哈希摘要无法与 eFuse 中的任何哈希摘要匹配,则验证失败。 2. 生成应用程序镜像摘要,将其与签名块中的镜像摘要进行匹配,如果无法匹配,则验证失败。 .. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC) - 3. 使用公钥,采用 RSA-PSS(RFC8017 的第 8.1.2 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。 + 3. 使用公钥,采用 RSA-PSS(RFC8017 的第 8.1.2 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。 .. only:: SOC_SECURE_BOOT_V2_ECC and not SOC_SECURE_BOOT_V2_RSA - 3. 使用公钥,采用 ECDSA(RFC6090 的第 5.3.3 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。 + 3. 使用公钥,采用 ECDSA(RFC6090 的第 5.3.3 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。 .. only:: SOC_SECURE_BOOT_V2_ECC and SOC_SECURE_BOOT_V2_RSA - 1. 使用公钥,采用 RSA-PSS(RFC8017 的第 8.1.2 节)算法或 ECDSA(RFC6090 的第 5.3.3 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。 + 1. 使用公钥,采用 RSA-PSS(RFC8017 的第 8.1.2 节)算法或 ECDSA(RFC6090 的第 5.3.3 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。 bootloader 大小 ------------------ -启用安全启动和/或 flash 加密都会增加 bootloader 的大小,因此可能需要更新分区表偏移量,请参阅 :ref:`bootloader-size`。 +启用安全启动和/或 flash 加密都会增加引导加载程序的大小,因此可能需要更新分区表偏移量,请参阅 :ref:`bootloader-size`。 -禁用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 时,bootloader 将使用 ``esptool`` 的 ``elf2image`` 命令中的 ``--pad-to-size`` 选项进行扇区填充,每个扇区大小为 4 KB。 +禁用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 时,引导加载程序将使用 ``esptool`` 的 ``elf2image`` 命令中的 ``--pad-to-size`` 选项进行扇区填充,每个扇区大小为 4 KB。 .. _efuse-usage: @@ -361,11 +361,11 @@ bootloader 大小 - BLOCK_KEYX - 该块包含其在 KEY_PURPOSE_X 中烧录的功能的对应数据,并存储公钥的 SHA-256 哈希摘要。公钥模数、指数、预先计算的 R 和 M' 值的 SHA-256 哈希摘要都将写入 eFuse 密钥块。这个摘要大小为 776 字节,偏移量从 36 到 812,如 :ref:`signature-block-format` 所示。注意,必须设置写保护位,但切勿设置读保护位。 - - KEY_REVOKEX - 与 3 个密钥块中的每一个相对应的注销标记。例如,设置 KEY_REVOKE2 将注销密钥功能为 SECURE_BOOT_DIGEST2 的密钥块。 + - KEY_REVOKEX - 与 3 个密钥块中的每一个相对应的撤销标记。例如,设置 KEY_REVOKE2 将撤销密钥功能为 SECURE_BOOT_DIGEST2 的密钥块。 - - SECURE_BOOT_AGGRESSIVE_REVOKE - 启用激进的密钥注销。只要与此密钥的验证失败,密钥就会立即注销。 + - SECURE_BOOT_AGGRESSIVE_REVOKE - 启用激进的密钥撤销。只要与此密钥的验证失败,密钥就会立即撤销。 - 为确保后续不会有攻击者添加受信任的密钥,应使用 KEY_REVOKEX 注销所有未使用的密钥摘要槽。若未启用 :ref:`CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS`,应用程序启动时,将在 :cpp:func:`esp_secure_boot_init_checks` 中检查和修复注销操作。 + 为确保后续不会有攻击者添加受信任的密钥,应使用 KEY_REVOKEX 撤销所有未使用的密钥摘要槽。若未启用 :ref:`CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS`,应用程序启动时,将在 :cpp:func:`esp_secure_boot_init_checks` 中检查和修复撤销操作。 密钥必须为可读密钥,以便软件访问。如果密钥设置了读保护,软件只能读取到全为零的数据,导致签名验证失败,启动中止。 @@ -405,17 +405,17 @@ bootloader 大小 在生产环境下,建议使用 OpenSSL 或其他行业标准的加密程序生成密钥对,详情请参阅 :ref:`secure-boot-v2-generate-key`。 -7. 运行 ``idf.py bootloader`` 构建启用了安全启动的 bootloader ,构建输出中会包含一个烧录命令的提示,使用 ``esptool.py write_flash`` 烧录。 +7. 运行 ``idf.py bootloader`` 构建启用了安全启动的引导加载程序,构建输出中会包含一个烧录命令的提示,使用 ``esptool.py write_flash`` 烧录。 -8. 当你准备好烧录 bootloader 时,请运行指定命令并等待烧录完成。注意,此处的指定命令需要手动输入,构建系统不会执行此过程。 +8. 烧录引导加载程序前,请运行指定命令并等待烧录完成。注意,此处的指定命令需要手动输入,构建系统不会执行此过程。 9. 运行 ``idf.py flash`` 构建并烧录分区表以及刚刚构建的应用程序镜像,该镜像使用步骤 6 中生成的签名密钥进行签名。 .. note:: - 如果启用了安全启动,``idf.py flash`` 不会烧录 bootloader 。 + 如果启用了安全启动,``idf.py flash`` 不会烧录引导加载程序。 -10. 重置 {IDF_TARGET_NAME},它将启动你烧录的软件 bootloader 。该软件 bootloader 会在芯片上启用安全启动,然后验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。 +10. 重置 {IDF_TARGET_NAME},它将启动你烧录的二级引导加载程序。该二级引导加载程序会在芯片上启用安全启动,然后验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。 .. note:: @@ -425,26 +425,26 @@ bootloader 大小 如果在初次启动过程中重置或关闭了 {IDF_TARGET_NAME},它会在下次启动时重新开始上述步骤。 -11. 在后续启动过程中,安全启动硬件会验证软件 bootloader 是否更改,软件 bootloader 会使用其附加的签名块中经验证的公钥部分,验证已签名的应用程序镜像。 +11. 在后续启动过程中,安全启动硬件会验证二级引导加载程序是否更改,二级引导加载程序会使用其附加的签名块中经验证的公钥部分,验证已签名的应用程序镜像。 启用安全启动后的限制 ----------------------------------------- -- 任何更新过的 bootloader 或应用程序都需要使用与已存储在 eFuse 中的摘要相匹配的密钥来签名。 +- 任何更新过的引导加载程序或应用程序都需要使用与已存储在 eFuse 中的摘要相匹配的密钥来签名。 - 注意,启用安全启动或 flash 加密会禁用 ROM 中的 USB-OTG USB 栈,阻止通过该端口进行串行仿真或设备固件更新 (DFU)。 +- 一旦启用安全启动,就无法再对 eFuse 密钥进行读保护,这可以避免攻击者对存储公共密钥摘要的 eFuse 块进行读保护,进而导致系统无法验证和处理签名,系统服务无法正常运行。有关读保护密钥的更多信息,请参阅下方详细说明。 + 烧录读保护密钥 ~~~~~~~~~~~~~~~ -一旦启用安全启动,就无法再对 eFuses 进行读保护,这可以避免攻击者对存储公共密钥摘要的 eFuse 块进行读保护,进而导致系统无法验证和处理签名,系统服务无法正常运行。 - -如果第二阶段 bootloader 启用了 :doc:`/security/flash-encryption`,它会确保在第一次启动时生成的 flash 加密密钥被读保护。 - -如需在设备启用安全启动后对密钥进行读保护,如: +**读保护密钥**: +以下密钥受到读保护后,相应的硬件将直接访问这些密钥(软件无法读取): .. list:: + :SOC_FLASH_ENC_SUPPORTED:* flash 加密密钥 :SOC_HMAC_SUPPORTED:* HMAC 密钥 @@ -453,19 +453,28 @@ bootloader 大小 :SOC_KEY_MANAGER_SUPPORTED:* 密钥管理器密钥 -请在启用安全启动的同时启用配置项 :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`,以防止禁用 eFuses 读保护功能。 +**不受读保护的密钥**: +因软件访问需要(软件可读取),以下密钥不受读保护: + +.. list:: -建议在启用安全启动之前,完成全部密钥的烧录。 + :SOC_SECURE_BOOT_SUPPORTED:* 安全启动公共密钥摘要 + * 用户数据 -如需启用配置项 :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`,请在所有读保护 eFuses 密钥烧录后,使用 ``esp_efuse.h`` 的 ``esp_efuse_write_field_bit()`` API 烧录 eFuses {IDF_TARGET_EFUSE_WR_DIS_RD_DIS}。 +启用安全启动后,默认禁用 eFuses 读保护功能。如后续需在应用程序中对某个 eFuse(例如上述读保护密钥列表中的密钥)进行读保护,请在启用安全启动的同时启用配置项 :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`。 +建议在启用安全启动之前,完成全部密钥的烧录。如需启用配置项 :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`,请在所有读保护 eFuse 密钥烧录后,使用 :cpp:func:`esp_efuse_write_field_bit` 烧录 eFuse {IDF_TARGET_EFUSE_WR_DIS_RD_DIS}。 + +.. note:: + + 如果在启用安全启动时,第二阶段引导加载程序启用了 :doc:`/security/flash-encryption`,则首次启动时生成的 flash 加密密钥已经受到读保护。 .. _secure-boot-v2-generate-key: 生成安全启动签名密钥 ---------------------------------- -构建系统会提示你,使用 ``idf.py secure-generate-signing-key`` 命令生成新签名密钥。 +根据构建系统提示,使用 ``idf.py secure-generate-signing-key`` 命令生成新签名密钥。 .. only:: esp32 or SOC_SECURE_BOOT_V2_RSA @@ -522,7 +531,7 @@ bootloader 大小 idf.py secure-sign-data BINARY_FILE --keyfile PRIVATE_SIGNING_KEY -上述命令将镜像签名附加到现有的二进制文件中,你可以使用 `--output` 参数将签名后的二进制文件写入单独的文件: +上述命令将镜像签名附加到现有的二进制文件中,可以使用 `--output` 参数将签名后的二进制文件写入单独的文件: .. code-block:: @@ -532,7 +541,7 @@ bootloader 大小 使用预计算的签名进行签名 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -如果你拥有为镜像生成的有效预计算签名及相应公钥,你可以使用这些签名生成一个签名扇区,并将其附加到镜像中。注意,预计算的签名应计算在镜像中的所有字节,包括安全填充字节。 +如果存在为镜像生成的有效预计算签名及相应公钥,可以使用这些签名生成一个签名扇区,并将其附加到镜像中。注意,预计算的签名应计算在镜像中的所有字节,包括安全填充字节。 在此情况下,应禁用选项 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 来构建固件镜像。该镜像将进行安全填充,并使用以下命令,生成带签名的二进制文件: @@ -546,7 +555,7 @@ bootloader 大小 使用外部硬件安全模块 (HSM) 进行签名 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -为了提高安全性,你可能会使用外部硬件安全模块 (HSM) 存储私钥,该私钥无法直接访问,但具备一个接口,可以生成二进制文件及其相应公钥的签名。 +为了提高安全性,可能需要使用外部硬件安全模块 (HSM) 存储私钥,该私钥无法直接访问,但具备一个接口,可以生成二进制文件及其相应公钥的签名。 在此情况下,请禁用选项 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 并构建固件。随后,可以将已进行安全填充的镜像提供给外部硬件安全模块来生成签名。请参阅 `使用外部 HSM 签名 `_ 生成已签名镜像。 @@ -569,7 +578,7 @@ bootloader 大小 * 在具备高质量熵源的系统上生成签名密钥。 * 时刻对签名密钥保密,泄漏此密钥将危及安全启动系统。 * 不允许第三方使用 ``idf.py secure-`` 命令来观察密钥生成或签名过程的任何细节,这两个过程都容易受到定时攻击或其他侧信道攻击的威胁。 -* 在安全启动配置中启用所有安全启动选项,包括 flash 加密、禁用 JTAG、禁用 BASIC ROM 解释器和禁用 UART bootloader 的加密 flash 访问。 +* 在安全启动配置中启用所有安全启动选项,包括 flash 加密、禁用 JTAG、禁用 BASIC ROM 解释器和禁用 UART 引导加载程序的加密 flash 访问。 * 结合 :doc:`flash-encryption` 使用安全启动,防止本地读取 flash 内容。 .. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS @@ -580,18 +589,18 @@ bootloader 大小 * 应独立计算并分别存储 1 到 3 个 {IDF_TARGET_SBV2_KEY} 公钥对(密钥 #0, #1, #2)。 * 完成烧录后,应设置 KEY_DIGEST eFuse 为写保护位。 * 未使用的 KEY_DIGEST 槽必须烧录其相应的 KEY_REVOKE eFuse,以永久禁用。请在设备离开工厂前完成此操作。 - * 烧录 eFuse 可以由软件 bootloader 在首次从 menuconfig 启用 ``Secure Boot v2`` 后进行,也可以使用 ``espefuse.py``,后者与 ROM 中的串行 bootloader 通信。 + * 烧录 eFuse 可以由二级引导加载程序在首次从 menuconfig 启用 ``Secure Boot v2`` 后进行,也可以使用 ``espefuse.py``,后者与 ROM 中的串行引导加载程序通信。 * KEY_DIGEST 应从密钥摘要 #0 开始,按顺序编号。如果使用了密钥摘要 #1,则必须使用密钥摘要 #0。如果使用了密钥摘要 #2,则必须使用密钥摘要 #0 和 #1。 - * 软件 bootloader 不支持 OTA 升级,它将至少由一个私钥签名,也可能使用全部三个私钥,并在工厂内烧录。 + * 二级引导加载程序不支持 OTA 升级,它将至少由一个私钥签名,也可能使用全部三个私钥,并在工厂内烧录。 * 应用程序应仅由单个私钥签名,其他私钥应妥善保管。但如果需要注销某些私钥,也可以使用多个签名私钥,请参阅下文的 :ref:`secure-boot-v2-key-revocation`。 多个密钥管理 ------------- - * 在烧录 bootloader 之前,应使用设备整个生命周期所需的所有私钥对 bootloader 签名。 + * 在烧录引导加载程序之前,应使用设备整个生命周期所需的所有私钥对引导加载程序签名。 * 构建系统每次只能使用一个私钥签名,如果需要,你必须手动运行命令以附加更多签名。 - * 你可以使用 ``idf.py secure-sign-data`` 的附加功能,此命令也将在启用安全启动 v2 的 bootloader 编译的末尾显示。 + * 你可以使用 ``idf.py secure-sign-data`` 的附加功能,此命令也将在启用安全启动 v2 的引导加载程序编译的末尾显示。 .. code-block:: @@ -606,18 +615,19 @@ bootloader 大小 .. _secure-boot-v2-key-revocation: - 注销密钥管理 + 撤销密钥管理 -------------- * 密钥按线性顺序处理,即密钥 #0、密钥 #1、密钥 #2。 + * 撤销一个密钥后,其余未被撤销的密钥仍可用于应用程序签名。例如,如密钥 #1 被撤销,仍然可以使用密钥 #0 和密钥 #2 给应用程序签名。 * 应用程序每次应只使用一个密钥签名,尽量避免暴露未使用的私钥。 - * bootloader 可以使用来自工厂的多个函数签名。 + * 引导加载程序可以使用来自工厂的多个函数签名。 .. note:: 请注意,启用配置 :ref:`CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS` 只能确保 **应用程序** 不会撤销未使用的摘要槽。 - 若想在设备首次启动时启用安全启动,那么即使启用了上述配置,bootloader 也会在启用安全启动时撤销未使用的摘要槽,因为保留未使用的密钥槽会构成安全隐患。 - 如果在开发流程中需要保留未使用摘要槽,则应从外部启用安全启动 (:ref:`enable-secure-boot-v2-externally`),而不是在启动设备时启用安全启动,这样 bootloader 就无需启用安全启动,从而避免安全隐患。 + 若想在设备首次启动时启用安全启动,那么即使启用了上述配置,引导加载程序也会在启用安全启动时撤销未使用的摘要槽,因为保留未使用的密钥槽会构成安全隐患。 + 如果在开发流程中需要保留未使用摘要槽,则应从外部启用安全启动 (:ref:`enable-secure-boot-v2-externally`),而不是在启动设备时启用安全启动,这样引导加载程序就无需启用安全启动,从而避免安全隐患。 保守方法 ~~~~~~~~~~~~ @@ -628,11 +638,15 @@ bootloader 大小 2. 新的 OTA 更新写入未使用的 OTA 应用程序分区。 3. 验证新应用程序的签名块。对比公钥与 eFuse 中烧录的摘要,并使用已验证的公钥验证应用程序。 4. 将活动分区设置为新的 OTA 应用程序分区。 - 5. 设备重置并加载使用密钥 #N-1 验证的 bootloader ,随后启动使用密钥 #N 验证的新应用程序。 - 6. 新应用程序使用密钥 #N 验证 bootloader ,这是最后的检查,然后运行代码注销密钥 #N-1,即设置 KEY_REVOKE eFuse 位。 + 5. 设备重置并加载使用密钥 #N-1 验证的引导加载程序,随后启动使用密钥 #N 验证的新应用程序。 + 6. 新应用程序使用密钥 #N 验证引导加载程序,这是最后的检查,然后运行代码注销密钥 #N-1,即设置 KEY_REVOKE eFuse 位。 7. 可以使用 API `esp_ota_revoke_secure_boot_public_key()` 注销密钥 #N-1。 - * 类似的方法也可以用于物理重新烧录,以使用新的密钥,还可以同时更改 bootloader 的内容。 + * 类似的方法也可以用于物理重新烧录,以使用新的密钥,还可以同时更改引导加载程序的内容。 + + .. note:: + + 当前未使用的密钥可以被撤销。例如,如果活动应用程序由密钥 #0 签名,但密钥 #1 已被泄露,请通过上述方法撤销密钥 #1。新的 OTA 更新应继续使用密钥 #0 签名,并且可以使用 API `esp_ota_revoke_secure_boot_public_key (SECURE_BOOT_PUBLIC_KEY_INDEX_[N])` 来撤销密钥 #N(在此例中,N 为 1)。撤销该密钥后,其余密钥以后仍可用于给应用程序签名。 .. _secure-boot-v2-aggressive-key-revocation: @@ -640,13 +654,13 @@ bootloader 大小 激进方法 ~~~~~~~~~~~~~~ - ROM 代码具备一项额外功能,即在签名验证失败时可以注销公钥摘要。 + ROM 代码具备一项额外功能,即在签名验证失败时可以撤销公钥摘要。 请烧录 ``SECURE_BOOT_AGGRESSIVE_REVOKE`` eFuse 或启用 :ref:`CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE` 以启用此功能。 - 注销密钥仅适用于成功启用了安全启动的情况。此外,在签名块无效或镜像摘要无效的情况下不会注销密钥,仅在签名验证失败时,即在 :ref:`verify_image` 的第 3 步中验证失败时,才会执行注销操作。 + 撤销密钥仅适用于成功启用了安全启动的情况。此外,在签名块无效或镜像摘要无效的情况下不会撤销密钥,仅在签名验证失败时,即在 :ref:`verify_image` 的第 3 步中验证失败时,才会执行撤销操作。 - 一旦注销了密钥,它将无法再用于验证镜像签名。该功能提供了强大的物理攻击防护,但如果由于签名验证失败而注销了所有密钥,可能会导致设备再也无法使用。 + 一旦撤销了密钥,它将无法再用于验证镜像签名。该功能提供了强大的物理攻击防护,但如果由于签名验证失败而撤销了所有密钥,可能会导致设备再也无法使用。 .. _secure-boot-v2-technical-details: @@ -654,17 +668,16 @@ bootloader 大小 技术细节 ----------------- -以下章节包含安全启动元件的详细参考描述: - +以下章节包含安全启动元件的详细参考描述。 -手动命令 -~~~~~~~~~~~~~~~ +安全启动已集成到 ESP-IDF 构建系统中,因此 ``idf.py build`` 将进行应用程序镜像签名。启用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 后,``idf.py bootloader`` 将生成一个已签名的引导加载程序。 -安全启动已集成到 ESP-IDF 构建系统中,因此 ``idf.py build`` 将进行应用程序镜像签名。启用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 后,``idf.py bootloader`` 将生成一个已签名的 bootloader 。 +另外,也可以使用 ``idf.py`` 或 ``openssl`` 工具生成独立签名并进行验证。建议使用 ``idf.py``,但如果需在非 ESP-IDF 环境中生成或验证签名,也可以使用 ``openssl`` 命令,因为安全引导 v2 生成签名符合标准的签名算法。 -然而,也可以使用 ``idf.py`` 工具生成独立的签名和摘要。 +用 ``idf.py`` 生成和验证签名 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -二进制镜像签名: +1. 二进制镜像签名: .. code-block:: @@ -672,6 +685,79 @@ bootloader 大小 Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 签名私钥的 PEM 文件。 +2. 验证签名的二进制镜像: + + .. code-block:: + + idf.py secure-verify-signature --keyfile ./my_signing_key.pem image_signed.bin + +Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 公钥/私钥签名的 PEM 文件。 + +用 OpenSSL 生成和验证签名 +~~~~~~~~~~~~~~~~~~~~~~~~~ + +最好使用 ``idf.py`` 工具生成和验证签名,但如果需要使用 OpenSSL 执行这些操作,可参考以下命令: + +1. 生成需要计算签名的二进制文件镜像的摘要。 + + .. code-block:: bash + + openssl dgst -sha256 -binary BINARY_FILE > DIGEST_BINARY_FILE + +2. 使用上一步计算出的摘要生成该镜像的签名。 + + .. only:: SOC_SECURE_BOOT_V2_RSA + + 用于生成 RSA-PSS 签名: + + .. code-block:: bash + + openssl pkeyutl -sign \ + -in DIGEST_BINARY_FILE \ + -inkey PRIVATE_SIGNING_KEY \ + -out SIGNATURE_FILE \ + -pkeyopt digest:sha256 \ + -pkeyopt rsa_padding_mode:pss \ + -pkeyopt rsa_pss_saltlen:32 + + .. only:: SOC_SECURE_BOOT_V2_ECC + + 用于生成 ECDSA 签名: + + .. code-block:: bash + + openssl pkeyutl -sign \ + -in DIGEST_BINARY_FILE \ + -inkey PRIVATE_SIGNING_KEY \ + -out SIGNATURE_FILE + +3. 验证生成的签名。 + + .. only:: SOC_SECURE_BOOT_V2_RSA + + For verifying an RSA-PSS signature: + + .. code-block:: bash + + openssl pkeyutl -verify \ + -in DIGEST_BINARY_FILE \ + -pubin -inkey PUBLIC_SIGNING_KEY \ + -sigfile SIGNATURE_FILE \ + -pkeyopt rsa_padding_mode:pss \ + -pkeyopt rsa_pss_saltlen:32 \ + -pkeyopt digest:sha256 + + .. only:: SOC_SECURE_BOOT_V2_ECC + + 用于验证 ECDSA 签名: + + .. code-block:: bash + + openssl pkeyutl -verify \ + -in DIGEST_BINARY_FILE \ + -pubin -inkey PUBLIC_SIGNING_KEY \ + -sigfile SIGNATURE_FILE + .. _secure-boot-v2-and-flash-encr: @@ -694,7 +780,7 @@ Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 签名私钥的 PEM 文件。 无需启用硬件安全启动选项,即可在 OTA 更新时验证应用程序的安全启动 v2 签名。这种方法采用了与安全启动 v2 相同的应用程序签名方案,但不同于硬件安全启动,软件安全启动无法阻止能够写入 flash 的攻击者绕过签名验证。 -如果在启动时无法接受安全启动验证的延迟,和/或威胁模型不包括物理访问或攻击者在 flash 中写入 bootloader 或应用程序分区,则适合使用未启用硬件安全启动的验证。 +如果在启动时无法接受安全启动验证的延迟,和/或威胁模型不包括物理访问或攻击者在 flash 中写入引导加载程序或应用程序分区,则适合使用未启用硬件安全启动的验证。 在此模式下,当前运行的应用程序签名块中的公钥将用于验证新更新的应用程序签名。更新时,不会验证运行中的应用程序签名,而是假定它有效。通过这种方式,系统建立了从当前运行的应用程序到新更新的应用程序之间的信任链。 @@ -750,6 +836,6 @@ Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 签名私钥的 PEM 文件。 JTAG 调试 ~~~~~~~~~~~~~~ -启用安全启动模式时,eFuse 会默认禁用 JTAG。初次启动时,bootloader 即禁用 JTAG 调试功能,并启用安全启动模式。 +启用安全启动模式时,eFuse 会默认禁用 JTAG。初次启动时,引导加载程序即禁用 JTAG 调试功能,并启用安全启动模式。 有关在启用安全启动或已签名应用程序验证的情况下使用 JTAG 调试的更多信息,请参阅 :ref:`jtag-debugging-security-features`。 diff --git a/docs/zh_CN/security/security-features-enablement-workflows.rst b/docs/zh_CN/security/security-features-enablement-workflows.rst index d7f9a8a3ddf4..9d63510bc5ce 100644 --- a/docs/zh_CN/security/security-features-enablement-workflows.rst +++ b/docs/zh_CN/security/security-features-enablement-workflows.rst @@ -18,6 +18,11 @@ 这份指南介绍了一系列工作流程,从而在外部主机的协助下启用设备的安全功能。这些工作流程分为多个阶段,每个阶段都会在主机上生成签名/加密密钥,从而在发生电力或其他故障时,提高恢复几率。此外,在主机的协助下,这些流程将加快整体配置过程(例如,在主机上加密固件要比在设备上加密更快)。 +.. only:: TARGET_SUPPORT_QEMU + + .. important:: + + 可以在 :doc:`../api-guides/tools/qemu` 中虚拟测试 {IDF_TARGET_NAME} 目标芯片的安全功能。安全工作流程建立后,便可在真实硬件上继续操作。 目标 ---- @@ -25,7 +30,7 @@ #. 用逐步指令简化启用安全功能的传统工作流程。 #. 设计比基于固件的传统工作流更加灵活的工作流。 #. 将工作流划分为多个小操作,从而提高可靠性。 -#. 消除对 :ref:`second-stage-bootloader` (固件引导加载程序)的依赖。 +#. 消除对 :ref:`second-stage-bootloader` 的依赖。 准备工作 -------- @@ -297,7 +302,7 @@ :esp32: - :ref:`选择 UART ROM 下载模式(永久禁用(推荐))` (注意,此选项仅在 :ref:`CONFIG_ESP32_REV_MIN` 设为 3 (ESP32 V3) 时可用)。UART ROM 下载模式在默认设置中自动启用,但建议永久禁用此模式以减少攻击者可用的选项。 :not esp32: - :ref:`选择发布模式 ` (注意,若选择发布模式,则将烧录 ``EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT`` eFuse 位,ROM 下载模式下 flash 加密硬件将被禁用)。 :not esp32: - :ref:`选择 UART ROM 下载模式(永久切换到安全模式(推荐))`。这是推荐的默认选项,如果不需要,也可将其更改为永久禁用 UART ROM 下载模式。 - - :ref:`选择适当的引导程序日志级别 `。 + - :ref:`选择适当的引导加载程序日志级别 `。 - 保存配置并退出。 7. 构建、加密并烧录二进制文件 @@ -324,7 +329,7 @@ .. only:: esp32 - 如果 ESP32 在 eFuse 中使用非默认的 :ref:`FLASH_CRYPT_CONFIG 值 `,需要将 ``--flash_crypt_conf`` 参数传递给 ``espsecure.py`` 以设置匹配值。如果设备自行配置 flash 加密,则不会发生这种情况,但是如果手动烧录了 eFuses 启用 flash 加密,就有可能发生。 + 如果 ESP32 在 eFuse 中使用非默认的 :ref:`FLASH_CRYPT_CONFIG 值 `,需要将 ``--flash_crypt_conf`` 参数传递给 ``espsecure.py`` 以设置匹配值。如果通过二级引导加载程序配置 flash 加密,则不会发生这种情况,但是如果手动烧录了 eFuses 启用 flash 加密,就有可能发生。 使用 ``espsecure.py decrypt_flash_data`` 命令时,可以用相同的选项(和不同的输入或输出文件)来解密密文 flash 或之前加密的文件。 @@ -518,7 +523,7 @@ flash 加密指南 6. 构建二进制文件 - 默认情况下,ROM 引导加载程序只会验证 :ref:`second-stage-bootloader` (固件引导加载程序)。只有在启用 :ref:`CONFIG_SECURE_BOOT` 选项(并将 :ref:`CONFIG_SECURE_BOOT_VERSION` 设置为 ``SECURE_BOOT_V2_ENABLED``)时,固件引导加载程序才会在构建引导加载程序时验证应用程序分区。 + 默认情况下,一级 (ROM) 引导加载程序只会验证 :ref:`second-stage-bootloader`。只有在启用 :ref:`CONFIG_SECURE_BOOT` 选项(并将 :ref:`CONFIG_SECURE_BOOT_VERSION` 设置为 ``SECURE_BOOT_V2_ENABLED``)时,二级引导加载程序才会在构建引导加载程序时验证应用程序分区。 A) 打开 :ref:`project-configuration-menu`,在 ``Security features`` 中设置 ``Enable hardware Secure Boot in bootloader`` 启用 Secure Boot。 diff --git a/docs/zh_CN/security/security.rst b/docs/zh_CN/security/security.rst index 455c79723f77..104c38b7fbcb 100644 --- a/docs/zh_CN/security/security.rst +++ b/docs/zh_CN/security/security.rst @@ -13,6 +13,12 @@ 在本指南中,最常用的命令形式为 ``idf.py secure-``,这是对应 ``espsecure.py `` 的封装。基于 ``idf.py`` 的命令能提供更好的用户体验,但与基于 ``espsecure.py`` 的命令相比,可能会损失一部分高级功能。 +.. only:: TARGET_SUPPORT_QEMU + + .. important:: + + 可以在 :doc:`../api-guides/tools/qemu` 中虚拟测试 {IDF_TARGET_NAME} 目标芯片的安全功能。安全工作流程建立后,便可在真实硬件上继续操作。 + 目标 ---- diff --git a/docs/zh_CN/versions.rst b/docs/zh_CN/versions.rst index fca9f997a457..41f12afa55d3 100644 --- a/docs/zh_CN/versions.rst +++ b/docs/zh_CN/versions.rst @@ -125,7 +125,7 @@ ESP-IDF 的每个主要版本和次要版本(V4.1、V4.2 等)的支持期限 idf.py --version -此外,由于 ESP-IDF 的版本也已编译至固件中,因此你也可以使用宏 ``IDF_VER`` 查看 ESP-IDF 的版本(以字符串的格式)。ESP-IDF 默认引导程序会在设备启动时打印 ESP-IDF 的版本。请注意,在 GitHub 仓库中的代码更新时,代码中的版本信息仅会在源代码重新编译或在清除编译时才会更新,因此打印出来的版本可能并不是最新的。 +此外,由于 ESP-IDF 的版本也已编译至固件中,因此你也可以使用宏 ``IDF_VER`` 查看 ESP-IDF 的版本(以字符串的格式)。ESP-IDF 默认引导加载程序会在设备启动时打印 ESP-IDF 的版本。请注意,在 GitHub 仓库中的代码更新时,代码中的版本信息仅会在源代码重新编译或在清除编译时才会更新,因此打印出来的版本可能并不是最新的。 如果编写的代码需要支持多个 ESP-IDF 版本,可以在编译时使用 :ref:`compile-time macros` 检查版本。 diff --git a/examples/bluetooth/.build-test-rules.yml b/examples/bluetooth/.build-test-rules.yml index 2033d2a278a3..20f2345ef9ba 100644 --- a/examples/bluetooth/.build-test-rules.yml +++ b/examples/bluetooth/.build-test-rules.yml @@ -19,7 +19,20 @@ examples/bluetooth/bluedroid/ble: <<: *bt_default_depends disable: - if: SOC_BT_SUPPORTED != 1 - + depends_components: + - bt + - esp_phy + - nvs_flash + - esp_coex + - esp_log + - esp_console + - mbedtls + - vfs + - esp_driver_gpio + - esp_driver_i2s + - esp_driver_uart + depends_filepatterns: + - examples/bluetooth/bluedroid/ble/pytest_ble_test.py examples/bluetooth/bluedroid/ble/ble_hid_device_demo: disable: @@ -27,9 +40,43 @@ examples/bluetooth/bluedroid/ble/ble_hid_device_demo: depends_components: - esp_driver_gpio +examples/bluetooth/bluedroid/ble/ble_throughput: + <<: *bt_default_depends + disable: + - if: SOC_BT_SUPPORTED != 1 + depends_components: + - bt + - esp_phy + - nvs_flash + - esp_coex + - esp_log + - esp_console + - mbedtls + - vfs + - esp_driver_gpio + - esp_driver_i2s + - esp_driver_uart + depends_filepatterns: + - examples/bluetooth/bluedroid/ble_50/pytest_ble_throughput_test.py + examples/bluetooth/bluedroid/ble_50: + <<: *bt_default_depends disable: - if: SOC_BLE_50_SUPPORTED != 1 + depends_components: + - bt + - esp_phy + - nvs_flash + - esp_coex + - esp_log + - esp_console + - mbedtls + - vfs + - esp_driver_gpio + - esp_driver_i2s + - esp_driver_uart + depends_filepatterns: + - examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py examples/bluetooth/bluedroid/classic_bt: disable: diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.esp32c2_xtal26m_receiver b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.esp32c2_xtal26m_receiver new file mode 100644 index 000000000000..9c392443402b --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.esp32c2_xtal26m_receiver @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_IBEACON_RECEIVER=y diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.esp32c2_xtal26m_sender b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.esp32c2_xtal26m_sender new file mode 100644 index 000000000000..420137b8bace --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.esp32c2_xtal26m_sender @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_IBEACON_SENDER=y diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.receiver b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.receiver new file mode 100644 index 000000000000..b78485c510f6 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.receiver @@ -0,0 +1 @@ +CONFIG_IBEACON_RECEIVER=y diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.sender b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.sender new file mode 100644 index 000000000000..d463a13eaf47 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.ci.sender @@ -0,0 +1 @@ +CONFIG_IBEACON_SENDER=y diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/pytest_ble_throughput_test.py b/examples/bluetooth/bluedroid/ble/ble_throughput/pytest_ble_throughput_test.py new file mode 100644 index 000000000000..f7194312ec80 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/pytest_ble_throughput_test.py @@ -0,0 +1,162 @@ +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import os.path +import time +from typing import Tuple + +import pytest +from pytest_embedded_idf.dut import IdfDut + + +# Case 1: gatt write throughput test +@pytest.mark.esp32 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32c61 +@pytest.mark.esp32c5 +@pytest.mark.esp32h2 +@pytest.mark.esp32s3 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, app_path, config, erase_all', [ + (2, + f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', + 'write', 'y'), + ], + indirect=True, +) +def test_gatt_write_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + server = dut[0] + client = dut[1] + client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + client.expect_exact('GATT client register, status 0', timeout=30) + server.expect_exact('GATT server register, status 0', timeout=30) + server.expect_exact('Advertising start successfully', timeout=30) + client.expect_exact('Scanning start successfully', timeout=30) + client.expect_exact('Device found ', timeout=30) + server.expect_exact('Service start, status 0', timeout=30) + server.expect_exact(f'Connected, conn_id 0, remote {client_addr}', timeout=30) + client.expect_exact(f'Connected, conn_id 0, remote {server_addr}', timeout=30) + client.expect_exact('MTU exchange, status 0, MTU 517', timeout=30) + server.expect_exact('MTU exchange, MTU 517', timeout=30) + client.expect_exact('Service search complete', timeout=30) + start_time = time.time() + while time.time() - start_time < 30: + throughput = int(server.expect(r'GATTC write Bit rate = (\d+) Byte/s', timeout=30).group(1).decode('utf8')) + assert throughput > 50000 or throughput < 95000 + + +# Case 2: gatt write throughput test for ESP32C2 26mhz xtal +@pytest.mark.esp32c2 +@pytest.mark.wifi_two_dut +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_all', [ + (2, 'esp32c2|esp32c2', '74880', + f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', + 'esp32c2_xtal26m_write', 'y'), + ], + indirect=True, +) +def test_c2_26mhz_xtal_write_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + server = dut[0] + client = dut[1] + client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + client.expect_exact('GATT client register, status 0', timeout=30) + server.expect_exact('GATT server register, status 0', timeout=30) + server.expect_exact('Advertising start successfully', timeout=30) + client.expect_exact('Scanning start successfully', timeout=30) + client.expect_exact('Device found ', timeout=30) + server.expect_exact('Service start, status 0', timeout=30) + server.expect_exact(f'Connected, conn_id 0, remote {client_addr}', timeout=30) + client.expect_exact(f'Connected, conn_id 0, remote {server_addr}', timeout=30) + client.expect_exact('MTU exchange, status 0, MTU 517', timeout=30) + server.expect_exact('MTU exchange, MTU 517', timeout=30) + client.expect_exact('Service search complete', timeout=30) + start_time = time.time() + while time.time() - start_time < 30: + throughput = int(server.expect(r'GATTC write Bit rate = (\d+) Byte/s', timeout=30).group(1).decode('utf8')) + assert throughput > 50000 or throughput < 95000 + + +# Case 3: gatt notify throughput test +@pytest.mark.esp32 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32c61 +@pytest.mark.esp32c5 +@pytest.mark.esp32h2 +@pytest.mark.esp32s3 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, app_path, config, erase_all', [ + (2, + f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', + 'notify', 'y'), + ], + indirect=True, +) +def test_gatt_notify_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + server = dut[0] + client = dut[1] + client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + client.expect_exact('GATT client register, status 0', timeout=30) + server.expect_exact('GATT server register, status 0', timeout=30) + server.expect_exact('Advertising start successfully', timeout=30) + client.expect_exact('Scanning start successfully', timeout=30) + client.expect_exact('Device found ', timeout=30) + server.expect_exact('Service start, status 0', timeout=30) + server.expect_exact(f'Connected, conn_id 0, remote {client_addr}', timeout=30) + client.expect_exact(f'Connected, conn_id 0, remote {server_addr}', timeout=30) + client.expect_exact('MTU exchange, status 0, MTU 517', timeout=30) + server.expect_exact('MTU exchange, MTU 517', timeout=30) + client.expect_exact('Service search complete', timeout=30) + client.expect_exact('Notification register successfully', timeout=30) + server.expect_exact('Notification enable', timeout=30) + start_time = time.time() + while time.time() - start_time < 30: + throughput = int(client.expect(r'Notify Bit rate = (\d+) Byte/s', timeout=30).group(1).decode('utf8')) + assert throughput > 50000 or throughput < 95000 + + +# Case 4: gatt notify throughput test for ESP32C2 26mhz xtal +@pytest.mark.esp32c2 +@pytest.mark.wifi_two_dut +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_all', [ + (2, 'esp32c2|esp32c2', '74880', + f'{os.path.join(os.path.dirname(__file__), "throughput_server")}|{os.path.join(os.path.dirname(__file__), "throughput_client")}', + 'esp32c2_xtal26m_notify', 'y'), + ], + indirect=True, +) +def test_c2_26mhz_xtal_notify_throughput(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + server = dut[0] + client = dut[1] + client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + client.expect_exact('GATT client register, status 0', timeout=30) + server.expect_exact('GATT server register, status 0', timeout=30) + server.expect_exact('Advertising start successfully', timeout=30) + client.expect_exact('Scanning start successfully', timeout=30) + client.expect_exact('Device found ', timeout=30) + server.expect_exact('Service start, status 0', timeout=30) + server.expect_exact(f'Connected, conn_id 0, remote {client_addr}', timeout=30) + client.expect_exact(f'Connected, conn_id 0, remote {server_addr}', timeout=30) + client.expect_exact('MTU exchange, status 0, MTU 517', timeout=30) + server.expect_exact('MTU exchange, MTU 517', timeout=30) + client.expect_exact('Service search complete', timeout=30) + client.expect_exact('Notification register successfully', timeout=30) + server.expect_exact('Notification enable', timeout=30) + start_time = time.time() + while time.time() - start_time < 30: + throughput = int(client.expect(r'Notify Bit rate = (\d+) Byte/s', timeout=30).group(1).decode('utf8')) + assert throughput > 50000 or throughput < 95000 diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.esp32c2_xtal26m_notify b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.esp32c2_xtal26m_notify new file mode 100644 index 000000000000..0448a5d2a501 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.esp32c2_xtal26m_notify @@ -0,0 +1,7 @@ + +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT=y +CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT=n diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.esp32c2_xtal26m_write b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.esp32c2_xtal26m_write new file mode 100644 index 000000000000..5874287ec33d --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.esp32c2_xtal26m_write @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT=y +CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT=n diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.notify b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.notify new file mode 100644 index 000000000000..db7b616debaf --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.notify @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT=y +CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT=n diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.write b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.write new file mode 100644 index 000000000000..a47edbf18265 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.ci.write @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT=y +CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT=n diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.esp32c2_xtal26m_notify b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.esp32c2_xtal26m_notify new file mode 100644 index 000000000000..0448a5d2a501 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.esp32c2_xtal26m_notify @@ -0,0 +1,7 @@ + +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT=y +CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT=n diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.esp32c2_xtal26m_write b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.esp32c2_xtal26m_write new file mode 100644 index 000000000000..5874287ec33d --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.esp32c2_xtal26m_write @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT=y +CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT=n diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.notify b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.notify new file mode 100644 index 000000000000..db7b616debaf --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.notify @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT=y +CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT=n diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.write b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.write new file mode 100644 index 000000000000..a47edbf18265 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.ci.write @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT=y +CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT=n diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 000000000000..e77ed1d26cd5 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,5 @@ + +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.ci.name b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.ci.name new file mode 100644 index 000000000000..6d9fd6470c4d --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32c2 b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32c2 index 298663d0a39a..9759e23400c7 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32c2 +++ b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32c2 @@ -7,3 +7,7 @@ CONFIG_BT_ENABLED=y CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y # CONFIG_BT_LE_50_FEATURE_SUPPORT is not set CONFIG_BT_LE_HCI_EVT_BUF_SIZE=257 + +# XTAL Freq Config +CONFIG_XTAL_FREQ_26=y +CONFIG_XTAL_FREQ=26 diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 000000000000..6ab0a7ab9d47 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.ci.name b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.ci.name new file mode 100644 index 000000000000..d8e23a54e91e --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.ci.name @@ -0,0 +1,3 @@ + +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 000000000000..6ab0a7ab9d47 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.ci.name b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.ci.name new file mode 100644 index 000000000000..d8e23a54e91e --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.ci.name @@ -0,0 +1,3 @@ + +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 000000000000..6ab0a7ab9d47 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.ci.name b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.ci.name new file mode 100644 index 000000000000..d8e23a54e91e --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.ci.name @@ -0,0 +1,3 @@ + +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c2 b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c2 index 7e477f7373d3..f13b703dc9fb 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c2 +++ b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c2 @@ -6,3 +6,6 @@ CONFIG_BT_ENABLED=y CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y # CONFIG_BT_LE_50_FEATURE_SUPPORT is not set CONFIG_BT_LE_HCI_EVT_BUF_SIZE=257 +# XTAL Freq Config +CONFIG_XTAL_FREQ_26=y +CONFIG_XTAL_FREQ=26 diff --git a/examples/bluetooth/bluedroid/ble/pytest_ble_test.py b/examples/bluetooth/bluedroid/ble/pytest_ble_test.py new file mode 100644 index 000000000000..9de955b30014 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/pytest_ble_test.py @@ -0,0 +1,265 @@ +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import os.path +from typing import Tuple + +import pexpect +import pytest +from pytest_embedded_idf.dut import IdfDut + + +# Case 1: gatt client and gatt server test +@pytest.mark.esp32 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32c5 +@pytest.mark.esp32h2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c61 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, app_path, config, erase_all', [ + (2, + f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', + 'name', 'y'), + ], + indirect=True, +) +def test_gatt_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + gatt_client = dut[1] + gatt_server = dut[0] + gatt_client_addr = gatt_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + gatt_server_addr = gatt_server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + gatt_client.expect_exact('GATT client register, status 0', timeout=30) + gatt_server.expect_exact('GATT server register, status 0', timeout=30) + gatt_server.expect_exact('Advertising start successfully', timeout=30) + gatt_client.expect_exact('Scanning start successfully', timeout=30) + gatt_client.expect_exact(f'Connected, conn_id 0, remote {gatt_server_addr}', timeout=30) + gatt_server.expect_exact(f'Connected, conn_id 0, remote {gatt_client_addr}', timeout=30) + gatt_client.expect_exact('Connection params update, status 0', timeout=30) + gatt_server.expect_exact('Connection params update, status 0', timeout=30) + gatt_client.expect_exact('Service discover complete', timeout=30) + gatt_client.expect_exact('Service search complete', timeout=30) + gatt_client.expect_exact('MTU exchange, status 0, MTU 500', timeout=30) + gatt_server.expect_exact('MTU exchange, MTU 500', timeout=30) + gatt_server.expect_exact('Notification enable', timeout=30) + gatt_client.expect_exact('Notification received', timeout=30) + gatt_client_output = gatt_client.expect(pexpect.TIMEOUT, timeout=10) + gatt_server_output = gatt_server.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(gatt_client_output) and 'boot:' not in str(gatt_client_output) + assert 'rst:' not in str(gatt_server_output) and 'boot:' not in str(gatt_server_output) + assert 'Disconnected' not in str(gatt_client_output) + assert 'Disconnected' not in str(gatt_server_output) + + +# Case 2: gatt client and gatt server test for ESP32C2 26mhz xtal +@pytest.mark.esp32c2 +@pytest.mark.wifi_two_dut +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_all', [ + (2, 'esp32c2|esp32c2', '74880', + f'{os.path.join(os.path.dirname(__file__), "gatt_server")}|{os.path.join(os.path.dirname(__file__), "gatt_client")}', + 'esp32c2_xtal26m', 'y'), + ], + indirect=True, +) +def test_c2_26mhz_xtal_gatt_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + gatt_client = dut[1] + gatt_server = dut[0] + gatt_client_addr = gatt_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') + gatt_server_addr = gatt_server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') + gatt_client.expect_exact('GATT client register, status 0', timeout=30) + gatt_server.expect_exact('GATT server register, status 0', timeout=30) + gatt_server.expect_exact('Advertising start successfully', timeout=30) + gatt_client.expect_exact('Scanning start success', timeout=30) + gatt_client.expect_exact(f'Connected, conn_id 0, remote {gatt_server_addr}', timeout=30) + gatt_server.expect_exact(f'Connected, conn_id 0, remote {gatt_client_addr}', timeout=30) + gatt_client.expect_exact('Connection params update, status 0', timeout=30) + gatt_server.expect_exact('Connection params update, status 0', timeout=30) + gatt_client.expect_exact('Service discover complete', timeout=30) + gatt_client.expect_exact('Service search complete', timeout=30) + gatt_client.expect_exact('MTU exchange, status 0, MTU 500', timeout=30) + gatt_server.expect_exact('MTU exchange, MTU 500', timeout=30) + gatt_server.expect_exact('Notification enable', timeout=30) + gatt_client.expect_exact('Notification received', timeout=30) + gatt_client_output = gatt_client.expect(pexpect.TIMEOUT, timeout=10) + gatt_server_output = gatt_server.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(gatt_client_output) and 'boot:' not in str(gatt_client_output) + assert 'rst:' not in str(gatt_server_output) and 'boot:' not in str(gatt_server_output) + assert 'Disconnected' not in str(gatt_client_output) + assert 'Disconnected' not in str(gatt_server_output) + + +# Case 3: gatt security server and gatt security client test +@pytest.mark.esp32 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32c5 +@pytest.mark.esp32h2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c61 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, app_path, config, erase_all', [ + (2, + f'{os.path.join(os.path.dirname(__file__), "gatt_security_server")}|{os.path.join(os.path.dirname(__file__), "gatt_security_client")}', + 'name', 'y'), + ], + indirect=True, +) +def test_gatt_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut], target: Tuple) -> None: + gatt_security_client = dut[1] + gatt_security_server = dut[0] + gatt_security_client_addr = gatt_security_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + gatt_security_client.expect_exact('GATT client register, status 0', timeout=30) + gatt_security_server.expect_exact('GATT server register, status 0', timeout=30) + gatt_security_client.expect_exact('Local privacy config successfully', timeout=30) + gatt_security_server.expect_exact('Local privacy config successfully', timeout=30) + gatt_security_server.expect_exact('Advertising start successfully', timeout=30) + gatt_security_client.expect_exact('Scanning start successfully', timeout=30) + gatt_security_client.expect_exact('Device found BE', timeout=30) + # can not get rpa_address, so not check server address + gatt_security_client.expect_exact(f'Connected, conn_id 0, remote ', timeout=30) + if target == ('esp32', 'esp32'): + gatt_security_server.expect_exact(f'Connected, conn_id 0, remote', timeout=30) + else: + gatt_security_server.expect_exact(f'Connected, conn_id 0, remote {gatt_security_client_addr}', timeout=30) + gatt_security_client.expect_exact('Key exchanged, key_type ESP_LE_KEY_PID', timeout=30) + gatt_security_client.expect_exact('Key exchanged, key_type ESP_LE_KEY_LENC', timeout=30) + gatt_security_client.expect_exact('Key exchanged, key_type ESP_LE_KEY_PENC', timeout=30) + gatt_security_client.expect_exact('Key exchanged, key_type ESP_LE_KEY_LID', timeout=30) + + gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_LENC', timeout=30) + gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_PENC', timeout=30) + gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_LID', timeout=30) + gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_PID', timeout=30) + if target == ('esp32', 'esp32'): + gatt_security_server.expect_exact(f'Authentication complete, addr_type 1, addr ', timeout=30) + else: + gatt_security_server.expect_exact(f'Authentication complete, addr_type 0, addr {gatt_security_client_addr}', timeout=30) + gatt_security_client.expect_exact(f'Authentication complete, addr_type 1, addr ', timeout=30) + gatt_security_server.expect_exact('Pairing successfully', timeout=30) + gatt_security_server.expect_exact('Bonded devices number 1', timeout=30) + gatt_security_client.expect_exact('Pairing successfully', timeout=30) + gatt_security_client.expect_exact('Service search complete', timeout=30) + gatt_security_client_output = gatt_security_client.expect(pexpect.TIMEOUT, timeout=10) + gatt_security_server_output = gatt_security_server.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(gatt_security_client_output) and 'boot:' not in str(gatt_security_client_output) + assert 'rst:' not in str(gatt_security_server_output) and 'boot:' not in str(gatt_security_server_output) + assert 'Disconnected' not in str(gatt_security_client_output) + assert 'Disconnected' not in str(gatt_security_server_output) + + +# Case 4: gatt security server and gatt security client test for ESP32C2 26mhz xtal +@pytest.mark.esp32c2 +@pytest.mark.wifi_two_dut +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_all', [ + (2, 'esp32c2|esp32c2', '74880', + f'{os.path.join(os.path.dirname(__file__), "gatt_security_server")}|{os.path.join(os.path.dirname(__file__), "gatt_security_client")}', + 'esp32c2_xtal26m', 'y'), + ], + indirect=True, +) +def test_c2_26mhz_xtal_gatt_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + gatt_security_client = dut[1] + gatt_security_server = dut[0] + gatt_security_client_addr = gatt_security_client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + gatt_security_client.expect_exact('GATT client register, status 0', timeout=30) + gatt_security_server.expect_exact('GATT server register, status 0', timeout=30) + gatt_security_client.expect_exact('Local privacy config successfully', timeout=30) + gatt_security_server.expect_exact('Local privacy config successfully', timeout=30) + gatt_security_server.expect_exact('Advertising start successfully', timeout=30) + gatt_security_client.expect_exact('Scanning start successfully', timeout=30) + gatt_security_client.expect_exact('Device found BE', timeout=30) + # can not get rpa_address, so not check server address + gatt_security_client.expect_exact(f'Connected, conn_id 0, remote ', timeout=30) + gatt_security_server.expect_exact(f'Connected, conn_id 0, remote {gatt_security_client_addr}', timeout=30) + gatt_security_client.expect_exact('Key exchanged, key_type ESP_LE_KEY_PID', timeout=30) + gatt_security_client.expect_exact('Key exchanged, key_type ESP_LE_KEY_LENC', timeout=30) + gatt_security_client.expect_exact('Key exchanged, key_type ESP_LE_KEY_PENC', timeout=30) + gatt_security_client.expect_exact('Key exchanged, key_type ESP_LE_KEY_LID', timeout=30) + + gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_LENC', timeout=30) + gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_PENC', timeout=30) + gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_LID', timeout=30) + gatt_security_server.expect_exact('Key exchanged, key_type ESP_LE_KEY_PID', timeout=30) + gatt_security_server.expect_exact(f'Authentication complete, addr_type 0, addr {gatt_security_client_addr}', timeout=30) + gatt_security_client.expect_exact(f'Authentication complete, addr_type 1, addr ', timeout=30) + gatt_security_server.expect_exact('Pairing successfully', timeout=30) + gatt_security_server.expect_exact('Bonded devices number 1', timeout=30) + gatt_security_client.expect_exact('Pairing successfully', timeout=30) + gatt_security_client.expect_exact('Service search complete', timeout=30) + gatt_security_client_output = gatt_security_client.expect(pexpect.TIMEOUT, timeout=10) + gatt_security_server_output = gatt_security_server.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(gatt_security_client_output) and 'boot:' not in str(gatt_security_client_output) + assert 'rst:' not in str(gatt_security_server_output) and 'boot:' not in str(gatt_security_server_output) + assert 'Disconnected' not in str(gatt_security_client_output) + assert 'Disconnected' not in str(gatt_security_server_output) + + +# Case 5: ble ibeacon test +@pytest.mark.esp32 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32c5 +@pytest.mark.esp32h2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c61 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, app_path, config, erase_all', [ + (2, + f'{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}|{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}', + 'sender|receiver', 'y'), + ], + indirect=True, +) +def test_ble_ibeacon_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + ibeacon_sender = dut[0] + ibeacon_receiver = dut[1] + + ibeacon_sender_addr = ibeacon_sender.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + ibeacon_sender.expect_exact('Advertising start successfully', timeout=30) + ibeacon_receiver.expect_exact('Scanning start successfully', timeout=30) + ibeacon_receiver.expect_exact('iBeacon Found', timeout=30) + ibeacon_receiver.expect_exact(f'IBEACON_DEMO: Device address: {ibeacon_sender_addr}', timeout=30) + ibeacon_receiver.expect_exact('IBEACON_DEMO: Proximity UUID:', timeout=30) + ibeacon_receiver.expect_exact('Major: 0x27b7 (10167)', timeout=30) + ibeacon_receiver.expect_exact('Minor: 0xf206 (61958)', timeout=30) + ibeacon_receiver.expect_exact('Measured power (RSSI at a 1m distance):', timeout=30) + ibeacon_receiver.expect_exact('RSSI of packet: ', timeout=30) + + +# Case 5: ble ibeacon test for ESP32C2 26mhz xtal +@pytest.mark.esp32c2 +@pytest.mark.wifi_two_dut +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_all', [ + (2, 'esp32c2|esp32c2', '74880', + f'{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}|{os.path.join(os.path.dirname(__file__), "ble_ibeacon")}', + 'esp32c2_xtal26m_sender|esp32c2_xtal26m_receiver', 'y'), + ], + indirect=True, +) +def test_c2_26mhz_ble_ibeacon_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + ibeacon_sender = dut[0] + ibeacon_receiver = dut[1] + + ibeacon_sender_addr = ibeacon_sender.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + ibeacon_sender.expect_exact('Advertising start successfully', timeout=30) + ibeacon_receiver.expect_exact('Scanning start successfully', timeout=30) + ibeacon_receiver.expect_exact('iBeacon Found', timeout=30) + ibeacon_receiver.expect_exact(f'IBEACON_DEMO: Device address: {ibeacon_sender_addr}', timeout=30) + ibeacon_receiver.expect_exact('IBEACON_DEMO: Proximity UUID:', timeout=30) + ibeacon_receiver.expect_exact('Major: 0x27b7 (10167)', timeout=30) + ibeacon_receiver.expect_exact('Minor: 0xf206 (61958)', timeout=30) + ibeacon_receiver.expect_exact('Measured power (RSSI at a 1m distance):', timeout=30) + ibeacon_receiver.expect_exact('RSSI of packet: ', timeout=30) diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 000000000000..6ab0a7ab9d47 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.ci.name b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.ci.name new file mode 100644 index 000000000000..6d9fd6470c4d --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 000000000000..6ab0a7ab9d47 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.ci.name b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.ci.name new file mode 100644 index 000000000000..6d9fd6470c4d --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_adv/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/bluedroid/ble_50/periodic_adv/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 000000000000..6ab0a7ab9d47 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/periodic_adv/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_adv/sdkconfig.ci.name b/examples/bluetooth/bluedroid/ble_50/periodic_adv/sdkconfig.ci.name new file mode 100644 index 000000000000..6d9fd6470c4d --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/periodic_adv/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_sync/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/bluedroid/ble_50/periodic_sync/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 000000000000..6ab0a7ab9d47 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/periodic_sync/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_sync/sdkconfig.ci.name b/examples/bluetooth/bluedroid/ble_50/periodic_sync/sdkconfig.ci.name new file mode 100644 index 000000000000..6d9fd6470c4d --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/periodic_sync/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=1 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py b/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py new file mode 100644 index 000000000000..b5b02e87f809 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble_50/pytest_ble50_test.py @@ -0,0 +1,143 @@ +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import os.path +from typing import Tuple + +import pytest +from pytest_embedded_idf.dut import IdfDut + + +# Case 1: ble50 security client and ble50 security server test +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32c5 +@pytest.mark.esp32h2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c61 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, app_path, config, erase_all', [ + (2, + f'{os.path.join(os.path.dirname(__file__), "ble50_security_server")}|{os.path.join(os.path.dirname(__file__), "ble50_security_client")}', + 'name', 'y'), + ], + indirect=True, +) +def test_ble50_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + server = dut[0] + client = dut[1] + client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + server.expect_exact('Extended advertising params set, status 0', timeout=30) + server.expect_exact('Extended advertising data set, status 0', timeout=30) + server.expect_exact('Extended advertising start, status 0', timeout=30) + client.expect_exact('Extended scanning start successfully', timeout=30) + client.expect_exact(f'Connected, conn_id 0, remote {server_addr}', timeout=30) + server.expect_exact(f'Connected, conn_id 0, remote {client_addr}', timeout=30) + server.expect_exact('Pairing successfully', timeout=30) + client.expect_exact('Pairing successfully', timeout=30) + server.expect_exact('Bonded devices number 1', timeout=30) + server.expect_exact('Characteristic write', timeout=30) + client.expect_exact('Service discover complete', timeout=30) + client.expect_exact('Service search complete', timeout=30) + client.expect_exact('MTU exchange, status 0', timeout=30) + client.expect_exact('Descriptor write successfully', timeout=30) + + +# Case 2: ble50 security client and ble50 security server test for ESP32C2 26mhz xtal +@pytest.mark.esp32c2 +@pytest.mark.wifi_two_dut +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_all', [ + (2, 'esp32c2|esp32c2', '74880', + f'{os.path.join(os.path.dirname(__file__), "ble50_security_server")}|{os.path.join(os.path.dirname(__file__), "ble50_security_client")}', + 'esp32c2_xtal26m', 'y'), + ], + indirect=True, +) +def test_c2_26mhz_xtal_ble50_security_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + server = dut[0] + client = dut[1] + client_addr = client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + server_addr = server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + + server.expect_exact('Extended advertising params set, status 0', timeout=30) + server.expect_exact('Extended advertising data set, status 0', timeout=30) + server.expect_exact('Extended advertising start, status 0', timeout=30) + client.expect_exact('Extended scanning start successfully', timeout=30) + client.expect_exact(f'Connected, conn_id 0, remote {server_addr}', timeout=30) + server.expect_exact(f'Connected, conn_id 0, remote {client_addr}', timeout=30) + server.expect_exact('Pairing successfully', timeout=30) + client.expect_exact('Pairing successfully', timeout=30) + server.expect_exact('Bonded devices number 1', timeout=30) + server.expect_exact('Characteristic write', timeout=30) + client.expect_exact('Service discover complete', timeout=30) + client.expect_exact('Service search complete', timeout=30) + client.expect_exact('MTU exchange, status 0', timeout=30) + client.expect_exact('Descriptor write successfully', timeout=30) + + +# Case 3: period_adv and period_sync test +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.esp32c5 +@pytest.mark.esp32h2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c61 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, app_path, config, erase_all', [ + (2, + f'{os.path.join(os.path.dirname(__file__), "periodic_adv")}|{os.path.join(os.path.dirname(__file__), "periodic_sync")}', + 'name', 'y'), + ], + indirect=True, +) +def test_period_adv_sync_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + adv_dut = dut[0] + sync_dut = dut[1] + + adv_dut.expect_exact('Extended advertising params set, status 0', timeout=30) + adv_dut.expect_exact('Extended advertising random address set, status 0', timeout=30) + adv_dut.expect_exact('Extended advertising data set, status 0', timeout=30) + adv_dut.expect_exact('Extended advertising start, status 0', timeout=30) + adv_dut.expect_exact('Periodic advertising params set, status 0', timeout=30) + adv_dut.expect_exact('Periodic advertising data set, status 0', timeout=30) + adv_dut.expect_exact('Periodic advertising start, status 0', timeout=30) + sync_dut.expect_exact('Extended scanning params set, status 0', timeout=30) + sync_dut.expect_exact('Extended scanning start, status 0', timeout=30) + sync_dut.expect_exact(f'Create sync with the peer device BE', timeout=30) + sync_dut.expect_exact('Periodic advertising sync establish, status 0', timeout=30) + sync_dut.expect_exact('Periodic adv report, sync handle ', timeout=30) + + +# Case 4: period_adv and period_sync test for ESP32C2 26mhz xtal +@pytest.mark.esp32c2 +@pytest.mark.wifi_two_dut +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_all', [ + (2, 'esp32c2|esp32c2', '74880', + f'{os.path.join(os.path.dirname(__file__), "periodic_adv")}|{os.path.join(os.path.dirname(__file__), "periodic_sync")}', + 'esp32c2_xtal26m', 'y'), + ], + indirect=True, +) +def test_c2_26mhz_xtal_period_adv_sync_func(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + adv_dut = dut[0] + sync_dut = dut[1] + + adv_dut.expect_exact('Extended advertising params set, status 0', timeout=30) + adv_dut.expect_exact('Extended advertising random address set, status 0', timeout=30) + adv_dut.expect_exact('Extended advertising data set, status 0', timeout=30) + adv_dut.expect_exact('Extended advertising start, status 0', timeout=30) + adv_dut.expect_exact('Periodic advertising params set, status 0', timeout=30) + adv_dut.expect_exact('Periodic advertising data set, status 0', timeout=30) + adv_dut.expect_exact('Periodic advertising start, status 0', timeout=30) + sync_dut.expect_exact('Extended scanning params set, status 0', timeout=30) + sync_dut.expect_exact('Extended scanning start, status 0', timeout=30) + sync_dut.expect_exact(f'Create sync with the peer device BE', timeout=30) + sync_dut.expect_exact('Periodic advertising sync establish, status 0', timeout=30) + sync_dut.expect_exact('Periodic adv report, sync handle ', timeout=30) diff --git a/examples/bluetooth/esp_ble_mesh/aligenie_demo/README.md b/examples/bluetooth/esp_ble_mesh/aligenie_demo/README.md index e1be95e4ac3b..dbc9e9134c83 100644 --- a/examples/bluetooth/esp_ble_mesh/aligenie_demo/README.md +++ b/examples/bluetooth/esp_ble_mesh/aligenie_demo/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh AliGenie Example ============================= diff --git a/examples/bluetooth/esp_ble_mesh/aligenie_demo/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/aligenie_demo/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..19b9555dce5b --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/aligenie_demo/sdkconfig.defaults.esp32c61 @@ -0,0 +1,17 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n + +# +# light driver config +# +CONFIG_LIGHT_GPIO_RED=4 +CONFIG_LIGHT_GPIO_GREEN=5 +CONFIG_LIGHT_GPIO_BLUE=6 +CONFIG_LIGHT_GPIO_COLD=7 +CONFIG_LIGHT_GPIO_WARM=10 +# end of light driver config diff --git a/examples/bluetooth/esp_ble_mesh/directed_forwarding/README.md b/examples/bluetooth/esp_ble_mesh/directed_forwarding/README.md index 8b68cddd7f10..5d5550dd972a 100644 --- a/examples/bluetooth/esp_ble_mesh/directed_forwarding/README.md +++ b/examples/bluetooth/esp_ble_mesh/directed_forwarding/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | # Directed Forwarding diff --git a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/main/board.h b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/main/board.h index 28890cdf2b8f..3f7a9b378707 100644 --- a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/main/board.h @@ -35,6 +35,8 @@ extern "C" { #define LED_B GPIO_NUM_47 #elif defined(CONFIG_BLE_MESH_ESP32C6_DEV) #define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 diff --git a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_client/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/main/board.h b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/main/board.h index 18d88b2a632b..975543b9f9fc 100644 --- a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/main/board.h @@ -34,6 +34,8 @@ extern "C" { #define LED_B GPIO_NUM_47 #elif defined(CONFIG_BLE_MESH_ESP32C6_DEV) #define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 diff --git a/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/directed_forwarding/df_server/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_client/README.md b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_client/README.md index b5e495bb5298..373a1bf82491 100644 --- a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_client/README.md +++ b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Fast Provisioning Client example ======================== diff --git a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_client/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_client/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_client/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/README.md b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/README.md index 6b4b2d8027a5..76a918c3c728 100644 --- a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/README.md +++ b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Fast Provisioning Server example ======================== diff --git a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/main/board.h b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/main/board.h index 7bb44d1d9c0c..a58820dd6133 100644 --- a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/main/board.h @@ -36,6 +36,10 @@ extern "C" { #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 #define LED_B GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define LED_R GPIO_NUM_8 +#define LED_G GPIO_NUM_8 +#define LED_B GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 diff --git a/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/README.md b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/README.md index e3f313d9baf2..b5f569475dcf 100644 --- a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/README.md +++ b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Client Model Demo ======================== diff --git a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/main/board.h b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/main/board.h index 6d7eb19bf31b..ee604c5cf5eb 100644 --- a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/main/board.h @@ -37,6 +37,10 @@ extern "C" { #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 #define LED_B GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define LED_R GPIO_NUM_8 +#define LED_G GPIO_NUM_8 +#define LED_B GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 diff --git a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_client/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/README.md b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/README.md index 4e9f4de38923..022003ec1619 100644 --- a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/README.md +++ b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Node demo ========================== diff --git a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/main/board.h b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/main/board.h index 918904c4d175..2be1b508af7e 100644 --- a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/main/board.h @@ -36,6 +36,10 @@ extern "C" { #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 #define LED_B GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define LED_R GPIO_NUM_8 +#define LED_G GPIO_NUM_8 +#define LED_B GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 diff --git a/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/provisioner/README.md b/examples/bluetooth/esp_ble_mesh/provisioner/README.md index 4411669d5f77..a9da37420e41 100644 --- a/examples/bluetooth/esp_ble_mesh/provisioner/README.md +++ b/examples/bluetooth/esp_ble_mesh/provisioner/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Provisioner demo ================================ diff --git a/examples/bluetooth/esp_ble_mesh/provisioner/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/provisioner/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/provisioner/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/README.md b/examples/bluetooth/esp_ble_mesh/remote_provisioning/README.md index 6de56d73ff61..b802d03e39aa 100644 --- a/examples/bluetooth/esp_ble_mesh/remote_provisioning/README.md +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | # Remote Provisioning (See the README.md file in the upper level 'examples' directory for more information about examples.) diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/main/board.h b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/main/board.h index e5466c5dca88..3b04417b5b03 100644 --- a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/main/board.h @@ -30,6 +30,8 @@ extern "C" { #define BLE_MESH_LED_STRIP_IO GPIO_NUM_47 #elif defined(CONFIG_BLE_MESH_ESP32C6_DEV) #define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32C5_DEV) diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_client/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/main/board.h b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/main/board.h index e5466c5dca88..3b04417b5b03 100644 --- a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/main/board.h @@ -30,6 +30,8 @@ extern "C" { #define BLE_MESH_LED_STRIP_IO GPIO_NUM_47 #elif defined(CONFIG_BLE_MESH_ESP32C6_DEV) #define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32C5_DEV) diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/rpr_server/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/main/board.h b/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/main/board.h index e5466c5dca88..3b04417b5b03 100644 --- a/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/main/board.h @@ -30,6 +30,8 @@ extern "C" { #define BLE_MESH_LED_STRIP_IO GPIO_NUM_47 #elif defined(CONFIG_BLE_MESH_ESP32C6_DEV) #define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define BLE_MESH_LED_STRIP_IO GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32C5_DEV) diff --git a/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/remote_provisioning/unprov_dev/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_client/README.md b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_client/README.md index c763b6b43abd..f14a98364ad7 100644 --- a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_client/README.md +++ b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Sensor Client Example ================================== diff --git a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_client/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_client/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_client/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/README.md b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/README.md index 2088b00e4e8b..3257ab5c7780 100644 --- a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/README.md +++ b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Sensor Server Example ================================== diff --git a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/main/board.h b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/main/board.h index 918904c4d175..2be1b508af7e 100644 --- a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/main/board.h @@ -36,6 +36,10 @@ extern "C" { #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 #define LED_B GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define LED_R GPIO_NUM_8 +#define LED_G GPIO_NUM_8 +#define LED_B GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 diff --git a/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/sensor_models/sensor_server/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_client/README.md b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_client/README.md index 1a68ab9e5d18..3cc724b88b30 100644 --- a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_client/README.md +++ b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Vendor Client Example ================================== diff --git a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_client/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_client/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_client/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/README.md b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/README.md index 9bc9df87a244..7a3849086c6e 100644 --- a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/README.md +++ b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | ESP BLE Mesh Vendor Server Example ================================== diff --git a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/main/Kconfig.projbuild index cb2988a8c873..3402e93a56b6 100644 --- a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/main/Kconfig.projbuild @@ -38,6 +38,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/main/board.h b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/main/board.h index 918904c4d175..2be1b508af7e 100644 --- a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/main/board.h @@ -36,6 +36,10 @@ extern "C" { #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 #define LED_B GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define LED_R GPIO_NUM_8 +#define LED_G GPIO_NUM_8 +#define LED_B GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32H2_DEV) #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 diff --git a/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/vendor_models/vendor_server/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/esp_ble_mesh/wifi_coexist/README.md b/examples/bluetooth/esp_ble_mesh/wifi_coexist/README.md index e86e1db95471..a08bc1d28764 100644 --- a/examples/bluetooth/esp_ble_mesh/wifi_coexist/README.md +++ b/examples/bluetooth/esp_ble_mesh/wifi_coexist/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | ESP-BLE-MESH and Wi-Fi Coexistence Example ============================================= diff --git a/examples/bluetooth/esp_ble_mesh/wifi_coexist/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/wifi_coexist/main/Kconfig.projbuild index 9344866edb3c..c86c9aebb416 100644 --- a/examples/bluetooth/esp_ble_mesh/wifi_coexist/main/Kconfig.projbuild +++ b/examples/bluetooth/esp_ble_mesh/wifi_coexist/main/Kconfig.projbuild @@ -33,6 +33,10 @@ menu "Example Configuration" bool "ESP32C5-DevKitC" depends on IDF_TARGET_ESP32C5 + config BLE_MESH_ESP32C61_DEV + bool "ESP32C61-DevKitC" + depends on IDF_TARGET_ESP32C61 + endchoice endmenu diff --git a/examples/bluetooth/esp_ble_mesh/wifi_coexist/main/board.h b/examples/bluetooth/esp_ble_mesh/wifi_coexist/main/board.h index 1bbda4d6bebe..7eca5b0f11f9 100644 --- a/examples/bluetooth/esp_ble_mesh/wifi_coexist/main/board.h +++ b/examples/bluetooth/esp_ble_mesh/wifi_coexist/main/board.h @@ -32,6 +32,10 @@ #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 #define LED_B GPIO_NUM_8 +#elif defined(CONFIG_BLE_MESH_ESP32C61_DEV) +#define LED_R GPIO_NUM_8 +#define LED_G GPIO_NUM_8 +#define LED_B GPIO_NUM_8 #elif defined(CONFIG_BLE_MESH_ESP32C5_DEV) #define LED_R GPIO_NUM_8 #define LED_G GPIO_NUM_8 diff --git a/examples/bluetooth/esp_ble_mesh/wifi_coexist/sdkconfig.defaults.esp32c61 b/examples/bluetooth/esp_ble_mesh/wifi_coexist/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000000..a96a75c54663 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/wifi_coexist/sdkconfig.defaults.esp32c61 @@ -0,0 +1,7 @@ +# Override some defaults so BT stack is enabled +# by default in this example +CONFIG_IDF_TARGET="esp32c61" +CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n +CONFIG_BT_LE_50_FEATURE_SUPPORT=n diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/README.md b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/README.md index 6c32318b9fe4..8f3339a66ec8 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/README.md +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/README.md @@ -5,6 +5,8 @@ (See the README.md file in the upper level 'examples' directory for more information about examples.) +**This example relies on the BLE controller. Currently, the ESP32/ESP32-C3/ESP32-S3/ESP32-C2 does not support the relevant vendor HCI, so please use the chip modules listed under Supported Targets.** + Please check the [tutorial](tutorial/Ble_Multiple_Connections_Central_Example_Walkthrough.md) for more information about this example. ## How to Use Example diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/README.md b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/README.md index 8035d1b64192..95d7358bbddb 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/README.md +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/README.md @@ -5,6 +5,8 @@ (See the README.md file in the upper level 'examples' directory for more information about examples.) +**This example relies on the BLE controller. Currently, the ESP32/ESP32-C3/ESP32-S3/ESP32-C2 does not support the relevant vendor HCI, so please use the chip modules listed under Supported Targets.** + Please check the [tutorial](tutorial/Ble_Multiple_Connections_Peripheral_Example_Walkthrough.md) for more information about this example. ## How to Use Example diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 800f136a09c9..a890bfbe07f3 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -183,6 +183,15 @@ menu "Example Connection Configuration" help Select the Ethernet PHY device to use in the example. + config EXAMPLE_ETH_PHY_GENERIC + bool "Generic 802.3 PHY" + help + Any Ethernet PHY chip compliant with IEEE 802.3 can be used. However, while + basic functionality should always work, some specific features might be limited, + even if the PHY meets IEEE 802.3 standard. A typical example is loopback + functionality, where certain PHYs may require setting a specific speed mode to + operate correctly. + config EXAMPLE_ETH_PHY_IP101 bool "IP101" help diff --git a/examples/common_components/protocol_examples_common/eth_connect.c b/examples/common_components/protocol_examples_common/eth_connect.c index 8e89dbe28eb3..86e856527c2b 100644 --- a/examples/common_components/protocol_examples_common/eth_connect.c +++ b/examples/common_components/protocol_examples_common/eth_connect.c @@ -103,7 +103,9 @@ static esp_netif_t *eth_start(void) esp32_emac_config.smi_gpio.mdc_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; esp32_emac_config.smi_gpio.mdio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); -#if CONFIG_EXAMPLE_ETH_PHY_IP101 +#if CONFIG_EXAMPLE_ETH_PHY_GENERIC + s_phy = esp_eth_phy_new_generic(&phy_config); +#elif CONFIG_EXAMPLE_ETH_PHY_IP101 s_phy = esp_eth_phy_new_ip101(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_RTL8201 s_phy = esp_eth_phy_new_rtl8201(&phy_config); diff --git a/examples/ethernet/basic/components/ethernet_init/Kconfig.projbuild b/examples/ethernet/basic/components/ethernet_init/Kconfig.projbuild index caca0c4211a0..325908b57537 100644 --- a/examples/ethernet/basic/components/ethernet_init/Kconfig.projbuild +++ b/examples/ethernet/basic/components/ethernet_init/Kconfig.projbuild @@ -17,6 +17,15 @@ menu "Example Ethernet Configuration" help Select the Ethernet PHY device to use in the example. + config EXAMPLE_ETH_PHY_GENERIC + bool "Generic 802.3 PHY" + help + Any Ethernet PHY chip compliant with IEEE 802.3 can be used. However, while + basic functionality should always work, some specific features might be limited, + even if the PHY meets IEEE 802.3 standard. A typical example is loopback + functionality, where certain PHYs may require setting a specific speed mode to + operate correctly. + config EXAMPLE_ETH_PHY_IP101 bool "IP101" help diff --git a/examples/ethernet/basic/components/ethernet_init/ethernet_init.c b/examples/ethernet/basic/components/ethernet_init/ethernet_init.c index b34304e4a372..831e8cb2079d 100644 --- a/examples/ethernet/basic/components/ethernet_init/ethernet_init.c +++ b/examples/ethernet/basic/components/ethernet_init/ethernet_init.c @@ -83,7 +83,9 @@ static esp_eth_handle_t eth_init_internal(esp_eth_mac_t **mac_out, esp_eth_phy_t // Create new ESP32 Ethernet MAC instance esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // Create new PHY instance based on board configuration -#if CONFIG_EXAMPLE_ETH_PHY_IP101 +#if CONFIG_EXAMPLE_ETH_PHY_GENERIC + esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config); +#elif CONFIG_EXAMPLE_ETH_PHY_IP101 esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_RTL8201 esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config); diff --git a/examples/ethernet/basic/pytest_eth_basic.py b/examples/ethernet/basic/pytest_eth_basic.py index 44ce6db4af2f..74c5a2ac63fe 100644 --- a/examples/ethernet/basic/pytest_eth_basic.py +++ b/examples/ethernet/basic/pytest_eth_basic.py @@ -10,6 +10,7 @@ @pytest.mark.esp32 @pytest.mark.parametrize('config', [ pytest.param('default_ip101', marks=[pytest.mark.ethernet_router]), + pytest.param('default_generic', marks=[pytest.mark.ethernet_router]), pytest.param('default_dm9051', marks=[pytest.mark.eth_dm9051]), ], indirect=True) def test_esp_eth_basic( diff --git a/examples/ethernet/basic/sdkconfig.ci.default_generic b/examples/ethernet/basic/sdkconfig.ci.default_generic new file mode 100644 index 000000000000..dae839a7c87d --- /dev/null +++ b/examples/ethernet/basic/sdkconfig.ci.default_generic @@ -0,0 +1,11 @@ +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_GENERIC=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 + +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ETH_PHY_INTERFACE_RMII=y +CONFIG_ETH_RMII_CLK_INPUT=y diff --git a/examples/get-started/blink/sdkconfig.defaults.esp32p4 b/examples/get-started/blink/sdkconfig.defaults.esp32p4 new file mode 100644 index 000000000000..cc80f60a684e --- /dev/null +++ b/examples/get-started/blink/sdkconfig.defaults.esp32p4 @@ -0,0 +1,2 @@ +CONFIG_BLINK_GPIO=44 +CONFIG_BLINK_LED_STRIP=y diff --git a/examples/openthread/.build-test-rules.yml b/examples/openthread/.build-test-rules.yml index 7518ec1873d0..9b1091798958 100644 --- a/examples/openthread/.build-test-rules.yml +++ b/examples/openthread/.build-test-rules.yml @@ -38,8 +38,8 @@ examples/openthread/ot_rcp: enable: - if: SOC_IEEE802154_SUPPORTED == 1 disable_test: - - if: IDF_TARGET not in ["esp32c6"] - reason: only test on esp32c6 + - if: IDF_TARGET not in ["esp32h2", "esp32c6"] + reason: only test on esp32h2 and esp32c6 <<: *openthread_dependencies examples/openthread/ot_sleepy_device/deep_sleep: @@ -59,3 +59,11 @@ examples/openthread/ot_sleepy_device/light_sleep: temporary: true reason: Not supported yet, TZ-958 <<: [*openthread_dependencies, *openthread_sleep_dependencies] + +examples/openthread/ot_trel: + enable: + - if: SOC_WIFI_SUPPORTED == 1 + disable_test: + - if: IDF_TARGET not in ["esp32c6", "esp32s3"] + reason: only test on esp32c6 and esp32s3 + <<: *openthread_dependencies diff --git a/examples/openthread/ot_br/sdkconfig.ci.br_spi b/examples/openthread/ot_br/sdkconfig.ci.br_spi new file mode 100644 index 000000000000..1778799eb74b --- /dev/null +++ b/examples/openthread/ot_br/sdkconfig.ci.br_spi @@ -0,0 +1 @@ +CONFIG_OPENTHREAD_RADIO_SPINEL_SPI=y diff --git a/components/soc/esp32c3/register/soc/.gitkeep b/examples/openthread/ot_cli/sdkconfig.ci.cli similarity index 100% rename from components/soc/esp32c3/register/soc/.gitkeep rename to examples/openthread/ot_cli/sdkconfig.ci.cli diff --git a/examples/openthread/ot_cli/sdkconfig.ci.cli_c6 b/examples/openthread/ot_cli/sdkconfig.ci.cli_c6 deleted file mode 100644 index a7f4dfb8225d..000000000000 --- a/examples/openthread/ot_cli/sdkconfig.ci.cli_c6 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_IDF_TARGET="esp32c6" -CONFIG_IDF_TARGET_ESP32C6=y diff --git a/examples/openthread/ot_cli/sdkconfig.ci.cli_h2 b/examples/openthread/ot_cli/sdkconfig.ci.cli_h2 deleted file mode 100644 index 485c06eac5e7..000000000000 --- a/examples/openthread/ot_cli/sdkconfig.ci.cli_h2 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_IDF_TARGET="esp32h2" -CONFIG_IDF_TARGET_ESP32H2=y diff --git a/examples/openthread/ot_cli/sdkconfig.ci.disable_cli b/examples/openthread/ot_cli/sdkconfig.ci.disable_cli index 51c321da5e26..a281edc22b0b 100644 --- a/examples/openthread/ot_cli/sdkconfig.ci.disable_cli +++ b/examples/openthread/ot_cli/sdkconfig.ci.disable_cli @@ -1,4 +1,2 @@ -CONFIG_IDF_TARGET="esp32h2" -CONFIG_IDF_TARGET_ESP32H2=y CONFIG_OPENTHREAD_CLI=n CONFIG_OPENTHREAD_CLI_ESP_EXTENSION=n diff --git a/examples/openthread/ot_rcp/sdkconfig.ci.rcp_spi b/examples/openthread/ot_rcp/sdkconfig.ci.rcp_spi new file mode 100644 index 000000000000..87b895575be4 --- /dev/null +++ b/examples/openthread/ot_rcp/sdkconfig.ci.rcp_spi @@ -0,0 +1 @@ +CONFIG_OPENTHREAD_RCP_SPI=y diff --git a/examples/openthread/ot_rcp/sdkconfig.ci.rcp b/examples/openthread/ot_rcp/sdkconfig.ci.rcp_uart similarity index 100% rename from examples/openthread/ot_rcp/sdkconfig.ci.rcp rename to examples/openthread/ot_rcp/sdkconfig.ci.rcp_uart diff --git a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy_c6 b/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy similarity index 78% rename from examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy_c6 rename to examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy index c4abd6d67017..9f3ddc2c93b7 100644 --- a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy_c6 +++ b/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy @@ -1,5 +1,3 @@ -CONFIG_IDF_TARGET="esp32c6" -CONFIG_IDF_TARGET_ESP32C6=y CONFIG_OPENTHREAD_NETWORK_CHANNEL=12 CONFIG_OPENTHREAD_NETWORK_MASTERKEY="aabbccddeeff00112233445566778899" CONFIG_ESP_SLEEP_DEBUG=y diff --git a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy_h2 b/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy_h2 deleted file mode 100644 index b7fa32376fac..000000000000 --- a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.ci.sleepy_h2 +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_IDF_TARGET="esp32h2" -CONFIG_IDF_TARGET_ESP32H2=y -CONFIG_OPENTHREAD_NETWORK_CHANNEL=12 -CONFIG_OPENTHREAD_NETWORK_MASTERKEY="aabbccddeeff00112233445566778899" -CONFIG_ESP_SLEEP_DEBUG=y -CONFIG_LOG_MAXIMUM_LEVEL_DEBUG=y -CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y diff --git a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults.esp32c6 b/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults.esp32c6 index 2c90c3e7eeb2..229cb8cc6b28 100644 --- a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults.esp32c6 +++ b/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults.esp32c6 @@ -1,5 +1,3 @@ -CONFIG_IDF_TARGET="esp32c6" - # # Sleep Config # diff --git a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults.esp32h2 b/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults.esp32h2 deleted file mode 100644 index ba2980822cac..000000000000 --- a/examples/openthread/ot_sleepy_device/light_sleep/sdkconfig.defaults.esp32h2 +++ /dev/null @@ -1 +0,0 @@ -CONFIG_IDF_TARGET="esp32h2" diff --git a/examples/openthread/ot_trel/CMakeLists.txt b/examples/openthread/ot_trel/CMakeLists.txt new file mode 100644 index 000000000000..b12d49bfa300 --- /dev/null +++ b/examples/openthread/ot_trel/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(esp_ot_cli) diff --git a/examples/openthread/ot_trel/README.md b/examples/openthread/ot_trel/README.md new file mode 100644 index 000000000000..5cc60dfa2f12 --- /dev/null +++ b/examples/openthread/ot_trel/README.md @@ -0,0 +1,133 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | + +# Thread Radio Encapsulation Link Example + +This example demonstrates a Thread Radio Encapsulation Link (TREL) Example. + +## How to use example + +### Hardware Required + +To run this example, a board with Wi-Fi module (for example ESP32-S3) is required. + +### Configure the project + +``` +idf.py menuconfig +``` + +The Wi-Fi ssid and password should be set through the menuconfig: +``` +Component config → → Example Connection Configuration → → WiFi SSID +Component config → → Example Connection Configuration → → WiFi Password +``` + +The example can run with the default configuration. OpenThread Command Line is enabled with UART as the default interface. Additionally, USB JTAG is also supported and can be activated through the menuconfig: + +``` +Component config → ESP System Settings → Channel for console output → USB Serial/JTAG Controller +``` + +### Build, Flash, and Run + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py build +idf.py -p PORT erase-flash flash monitor +``` + +Now you'll get an OpenThread command line shell. + +### Example Output + +The `help` command will print all of the supported commands. +```bash +> help +I(7058) OPENTHREAD:[INFO]-CLI-----: execute command: help +bbr +bufferinfo +ccathreshold +channel +child +childip +childmax +childsupervision +childtimeout +coap +contextreusedelay +counters +dataset +delaytimermin +diag +discover +dns +domainname +eidcache +eui64 +extaddr +extpanid +factoryreset +... +``` + +## Set Up Network + +To run this example, at least two ESP32-S3 boards flashed with this ot_trel example are required. And they must connect to the same wifi AP. + +On the first device, run the following commands: +```bash +> factoryreset +... # the device will reboot + +> dataset init new +Done +> dataset commit active +Done +> ifconfig up +Done +> thread start +Done + +# After some seconds + +> state +leader +Done +``` +Now the first device has formed a Thread network as a leader. Get some information which will be used in next steps: +```bash +> ipaddr +fdde:ad00:beef:0:0:ff:fe00:fc00 +fdde:ad00:beef:0:0:ff:fe00:8000 +fdde:ad00:beef:0:a7c6:6311:9c8c:271b +fe80:0:0:0:5c27:a723:7115:c8f8 + +# Get the Active Dataset +> dataset active -x +0e080000000000010000000300001835060004001fffe00208fe7bb701f5f1125d0708fd75cbde7c6647bd0510b3914792d44f45b6c7d76eb9306eec94030f4f70656e5468726561642d35383332010258320410e35c581af5029b054fc904a24c2b27700c0402a0fff8 +``` + +On the second device, set the active dataset from leader, and start Thread interface: +```bash +> factoryreset +... # the device will reboot + +> dataset set active 0e080000000000010000000300001835060004001fffe00208fe7bb701f5f1125d0708fd75cbde7c6647bd0510b3914792d44f45b6c7d76eb9306eec94030f4f70656e5468726561642d35383332010258320410e35c581af5029b054fc904a24c2b27700c0402a0fff8 +> ifconfig up +Done +> thread start +Done + +# After some seconds + +> state +router # child is also a valid state +Done +``` +The second device has joined the Thread network as a router (or a child). + +## Extension commands + +You can refer to the [extension command](https://github.com/espressif/esp-thread-br/blob/main/components/esp_ot_cli_extension/README.md) about the extension commands. diff --git a/examples/openthread/ot_trel/main/CMakeLists.txt b/examples/openthread/ot_trel/main/CMakeLists.txt new file mode 100644 index 000000000000..cea684e5f9f0 --- /dev/null +++ b/examples/openthread/ot_trel/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "esp_ot_trel.c" + INCLUDE_DIRS ".") diff --git a/examples/openthread/ot_trel/main/Kconfig.projbuild b/examples/openthread/ot_trel/main/Kconfig.projbuild new file mode 100644 index 000000000000..7a37072f9494 --- /dev/null +++ b/examples/openthread/ot_trel/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "OpenThread TREL Example" + + config OPENTHREAD_AUTO_START + bool 'Enable the automatic start mode.' + default False + help + If enabled, the Openthread Device will create or connect to thread network with pre-configured + network parameters automatically. Otherwise, user need to configure Thread via CLI command manually. +endmenu diff --git a/examples/zigbee/esp_zigbee_rcp/main/esp_zigbee_rcp.h b/examples/openthread/ot_trel/main/esp_ot_config.h similarity index 60% rename from examples/zigbee/esp_zigbee_rcp/main/esp_zigbee_rcp.h rename to examples/openthread/ot_trel/main/esp_ot_config.h index c8f59a51a311..be8eff0e21cb 100644 --- a/examples/zigbee/esp_zigbee_rcp/main/esp_zigbee_rcp.h +++ b/examples/openthread/ot_trel/main/esp_ot_config.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: CC0-1.0 * - * Zigbee RCP Example + * OpenThread Command Line Example * * This example code is in the Public Domain (or CC0 licensed, at your option.) * @@ -11,16 +11,21 @@ * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. */ -#include "esp_zigbee_core.h" -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { \ - .radio_mode = RADIO_MODE_NATIVE, \ +#pragma once + +#include "sdkconfig.h" +#include "esp_openthread_types.h" + +#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_TREL, \ } -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ +#if CONFIG_OPENTHREAD_CONSOLE_TYPE_UART +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ { \ - .host_connection_mode = HOST_CONNECTION_MODE_RCP_UART, \ + .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ .host_uart_config = { \ .port = 0, \ .uart_config = \ @@ -37,3 +42,17 @@ .tx_pin = UART_PIN_NO_CHANGE, \ }, \ } +#elif CONFIG_OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_CLI_USB, \ + .host_usb_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(), \ + } +#endif + +#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ + { \ + .storage_partition_name = "nvs", \ + .netif_queue_size = 10, \ + .task_queue_size = 10, \ + } diff --git a/examples/openthread/ot_trel/main/esp_ot_trel.c b/examples/openthread/ot_trel/main/esp_ot_trel.c new file mode 100644 index 000000000000..05b7251da4fc --- /dev/null +++ b/examples/openthread/ot_trel/main/esp_ot_trel.c @@ -0,0 +1,139 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * OpenThread Command Line Example + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include + +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_event.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_netif_types.h" +#include "esp_openthread.h" +#include "esp_openthread_cli.h" +#include "esp_openthread_lock.h" +#include "esp_openthread_netif_glue.h" +#include "esp_openthread_types.h" +#include "esp_ot_config.h" +#include "esp_vfs_eventfd.h" +#include "driver/uart.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "hal/uart_types.h" +#include "nvs_flash.h" +#include "openthread/cli.h" +#include "openthread/instance.h" +#include "openthread/logging.h" +#include "openthread/tasklet.h" +#include "protocol_examples_common.h" +#include "mdns.h" + +#if !CONFIG_EXAMPLE_CONNECT_WIFI && !CONFIG_EXAMPLE_CONNECT_ETHERNET +#error No netif for TREL! +#endif + +#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE +#include "ot_led_strip.h" +#endif + +#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION +#include "esp_ot_cli_extension.h" +#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION + + +#define TAG "ot_esp_trel" + +static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t *config) +{ + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); + esp_netif_t *netif = esp_netif_new(&cfg); + assert(netif != NULL); + ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init(config))); + + return netif; +} + +static void ot_task_worker(void *aContext) +{ + esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + + ESP_ERROR_CHECK(example_connect()); + + // Initialize the OpenThread stack + ESP_ERROR_CHECK(esp_openthread_init(&config)); + +#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE + ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); +#endif + +#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC + // The OpenThread log level directly matches ESP log level + (void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL); +#endif + // Initialize the OpenThread cli +#if CONFIG_OPENTHREAD_CLI + esp_openthread_cli_init(); +#endif + + esp_netif_t *openthread_netif; + // Initialize the esp_netif bindings + openthread_netif = init_openthread_netif(&config); + esp_netif_set_default_netif(openthread_netif); + +#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION + esp_cli_custom_command_init(); +#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION + + // Run the main loop +#if CONFIG_OPENTHREAD_CLI + esp_openthread_cli_create_task(); +#endif +#if CONFIG_OPENTHREAD_AUTO_START + otOperationalDatasetTlvs dataset; + otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); + ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); +#endif + esp_openthread_launch_mainloop(); + + // Clean up + esp_openthread_netif_glue_deinit(); + esp_netif_destroy(openthread_netif); + + esp_vfs_eventfd_unregister(); + vTaskDelete(NULL); +} + +void app_main(void) +{ + // Used eventfds: + // * netif + // * ot task queue + esp_vfs_eventfd_config_t eventfd_config = { + .max_fds = 2, + }; + + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); + ESP_ERROR_CHECK(mdns_init()); + ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-trel")); + xTaskCreate(ot_task_worker, "ot_trel_main", 8192, xTaskGetCurrentTaskHandle(), 5, NULL); +} diff --git a/examples/openthread/ot_trel/main/idf_component.yml b/examples/openthread/ot_trel/main/idf_component.yml new file mode 100644 index 000000000000..a52a17085f02 --- /dev/null +++ b/examples/openthread/ot_trel/main/idf_component.yml @@ -0,0 +1,11 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/esp_ot_cli_extension: + version: "~1.2.0" + espressif/mdns: "^1.0.3" + idf: + version: ">=4.1.0" + protocol_examples_common: + path: ${IDF_PATH}/examples/common_components/protocol_examples_common + ot_led: + path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led diff --git a/examples/zigbee/esp_zigbee_rcp/partitions.csv b/examples/openthread/ot_trel/partitions.csv similarity index 73% rename from examples/zigbee/esp_zigbee_rcp/partitions.csv rename to examples/openthread/ot_trel/partitions.csv index e72a9f10a232..641bcc9afcc4 100644 --- a/examples/zigbee/esp_zigbee_rcp/partitions.csv +++ b/examples/openthread/ot_trel/partitions.csv @@ -2,5 +2,4 @@ # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 548K, -zb_storage, data, fat, 0x9a000, 16K, +factory, app, factory, 0x10000, 0x170000, diff --git a/examples/openthread/ot_trel/sdkconfig.ci.trel b/examples/openthread/ot_trel/sdkconfig.ci.trel new file mode 100644 index 000000000000..994413fa4fcb --- /dev/null +++ b/examples/openthread/ot_trel/sdkconfig.ci.trel @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CONNECT_WIFI=y +CONFIG_EXAMPLE_WIFI_SSID="OTCITE" +CONFIG_EXAMPLE_WIFI_PASSWORD="otcitest888" diff --git a/examples/openthread/ot_trel/sdkconfig.defaults b/examples/openthread/ot_trel/sdkconfig.defaults new file mode 100644 index 000000000000..99f65081b92b --- /dev/null +++ b/examples/openthread/ot_trel/sdkconfig.defaults @@ -0,0 +1,43 @@ +# +# Partition Table +# +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# mbedTLS +# +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y +CONFIG_MBEDTLS_ECJPAKE_C=y +# end of mbedTLS + +# +# OpenThread +# +CONFIG_OPENTHREAD_ENABLED=y +CONFIG_OPENTHREAD_BORDER_ROUTER=n +CONFIG_OPENTHREAD_DNS64_CLIENT=y +CONFIG_OPENTHREAD_RADIO_154_NONE=y +CONFIG_OPENTHREAD_RADIO_TREL=y +# end of OpenThread + +# +# lwIP +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 +CONFIG_LWIP_IPV6_NUM_ADDRESSES=8 +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM=y +CONFIG_LWIP_IPV6_AUTOCONFIG=y +# end of lwIP + +# +# Configurations for optimizing the size of firmware +# +CONFIG_COMPILER_OPTIMIZATION_SIZE=y diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index ea9dc3353db3..2abb6e4cb9c5 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -59,6 +59,9 @@ # Case 14: Curl a website over HTTPS via DNS and NAT64 # A border router joins a Wi-Fi network and forms a Thread network, a Thread devices attached to it and curl a https website. +# Case 15: Thread network formation and attaching with TREL +# A TREL device forms a Thread network, other TREL devices attach to it, then test ping connection between them. + @pytest.fixture(scope='module', name='Init_avahi') def fixture_Init_avahi() -> bool: @@ -91,11 +94,16 @@ def fixture_Init_interface() -> bool: @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32h2|esp32s3'), + ('rcp_spi|cli|br_spi', 3, + f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', + 'esp32h2|esp32c6|esp32s3'), ], indirect=True, ) @@ -161,7 +169,7 @@ def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None: @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -210,7 +218,7 @@ def test_Bidirectional_IPv6_connectivity(Init_interface:bool, dut: Tuple[IdfDut, @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -260,7 +268,7 @@ def test_multicast_forwarding_A(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -311,7 +319,7 @@ def test_multicast_forwarding_B(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -367,7 +375,7 @@ def test_service_discovery_of_Thread_device(Init_interface:bool, Init_avahi:bool @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -430,7 +438,7 @@ def test_service_discovery_of_WiFi_device(Init_interface:bool, Init_avahi:bool, @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -465,7 +473,7 @@ def test_ICMP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -518,7 +526,7 @@ def test_UDP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -575,11 +583,11 @@ def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N @pytest.mark.openthread_sleep @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('cli_h2|sleepy_c6', 2, + ('cli|sleepy', 2, f'{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device/light_sleep")}', 'esp32h2|esp32c6'), - ('cli_c6|sleepy_h2', 2, + ('cli|sleepy', 2, f'{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device/light_sleep")}', 'esp32c6|esp32h2'), @@ -627,7 +635,7 @@ def test_ot_sleepy_device(dut: Tuple[IdfDut, IdfDut]) -> None: @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|br', 2, + ('rcp_uart|br', 2, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32s3'), @@ -666,7 +674,7 @@ def test_basic_startup(dut: Tuple[IdfDut, IdfDut]) -> None: @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -703,7 +711,7 @@ def test_NAT64_DNS(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|br', 2, + ('rcp_uart|br', 2, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', 'esp32c6|esp32s3'), @@ -761,7 +769,7 @@ def test_br_meshcop(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, Idf @pytest.mark.flaky(reruns=1, reruns_delay=1) @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('rcp|cli_h2|br', 3, + ('rcp_uart|cli|br', 3, f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', @@ -787,3 +795,53 @@ def test_https_NAT64_DNS(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut] ocf.execute_command(br, 'factoryreset') ocf.execute_command(cli, 'factoryreset') time.sleep(3) + + +# Case 15: Thread network formation and attaching with TREL +@pytest.mark.supported_targets +@pytest.mark.esp32c6 +@pytest.mark.openthread_br +@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.parametrize( + 'config, count, app_path, target', [ + ('trel|trel', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_trel")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_trel")}', + 'esp32c6|esp32s3'), + ], + indirect=True, +) +def test_trel_connect(dut: Tuple[IdfDut, IdfDut]) -> None: + trel_s3 = dut[1] + trel_c6 = dut[0] + trel_list = [trel_c6] + router_extaddr_list = ['7766554433221101'] + + trel_s3.expect('IPv4 address:', timeout=10) + trel_c6.expect('IPv4 address:', timeout=10) + ocf.init_thread(trel_s3) + for trel in trel_list: + ocf.init_thread(trel) + trel_leader_para = copy.copy(default_br_ot_para) + trel_leader_para.bbr = False + ocf.joinThreadNetwork(trel_s3, trel_leader_para) + trel_para = copy.copy(default_cli_ot_para) + trel_para.dataset = ocf.getDataset(trel_s3) + try: + order = 0 + for trel in trel_list: + trel_para.exaddr = router_extaddr_list[order] + order = order + 1 + ocf.joinThreadNetwork(trel, trel_para) + for trel in trel_list: + trel_mleid_addr = ocf.get_mleid_addr(trel) + trel_s3_mleid_addr = ocf.get_mleid_addr(trel_s3) + rx_nums = ocf.ot_ping(trel, trel_s3_mleid_addr, 5)[1] + assert rx_nums == 5 + rx_nums = ocf.ot_ping(trel_s3, trel_mleid_addr, 5)[1] + assert rx_nums == 5 + finally: + ocf.execute_command(trel_s3, 'factoryreset') + for trel in trel_list: + ocf.execute_command(trel, 'factoryreset') + time.sleep(3) diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index e8ad2c13719f..1764bbee248a 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -102,7 +102,7 @@ examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm: - if: SOC_I2S_SUPPORTS_TDM != 1 or (SOC_I2C_SUPPORTED != 1 or SOC_GPSPI_SUPPORTED != 1) reason: rely on I2S TDM mode to receive audio, I2C to config es7210 and SPI to save audio to SD card disable_test: - - if: IDF_TARGET == "esp32p4" + - if: IDF_TARGET in ["esp32p4", "esp32c61"] temporary: true reason: lack of runners depends_components: diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild b/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild index 6e81a71006e1..e433698706b9 100644 --- a/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild +++ b/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild @@ -13,7 +13,7 @@ menu "Example DSI Configuration" endchoice choice EXAMPLE_MIPI_DSI_DISP_HRES - bool "Set MIPI CSI horizontal resolution" + bool "Set MIPI DSI horizontal resolution" default EXAMPLE_MIPI_DSI_DISP_HRES_800 if EXAMPLE_LCD_PATTERN_ILI9881C default EXAMPLE_MIPI_DSI_DISP_HRES_1024 if EXAMPLE_LCD_PATTERN_EK79007 default EXAMPLE_MIPI_DSI_DISP_HRES_800 @@ -30,7 +30,7 @@ menu "Example DSI Configuration" default 1024 if EXAMPLE_MIPI_DSI_DISP_HRES_1024 choice EXAMPLE_MIPI_DSI_DISP_VRES - bool "Set MIPI CSI vertical resolution" + bool "Set MIPI DSI vertical resolution" default EXAMPLE_MIPI_DSI_DISP_VRES_1280 if EXAMPLE_LCD_PATTERN_ILI9881C default EXAMPLE_MIPI_DSI_DISP_VRES_600 if EXAMPLE_LCD_PATTERN_EK79007 default EXAMPLE_MIPI_DSI_DISP_VRES_1280 diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/example_dsi_init.c b/examples/peripherals/camera/camera_dsi/components/dsi_init/example_dsi_init.c index 9424c27960c4..955f45d7942b 100644 --- a/examples/peripherals/camera/camera_dsi/components/dsi_init/example_dsi_init.c +++ b/examples/peripherals/camera/camera_dsi/components/dsi_init/example_dsi_init.c @@ -36,7 +36,7 @@ void example_dsi_resource_alloc(esp_lcd_dsi_bus_handle_t *mipi_dsi_bus, esp_lcd_ .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = EXAMPLE_MIPI_DSI_DPI_CLK_MHZ, .virtual_channel = 0, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, + .in_color_format = LCD_COLOR_FMT_RGB565, .video_timing = { .h_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES, .v_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, diff --git a/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c b/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c index 27b22cdaa4d9..89b7bbc88a48 100644 --- a/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c +++ b/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c @@ -1,11 +1,9 @@ -/* GPIO Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ #include #include #include diff --git a/examples/peripherals/gpio/matrix_keyboard/README.md b/examples/peripherals/gpio/matrix_keyboard/README.md index 31cd207e55db..76d095e41721 100644 --- a/examples/peripherals/gpio/matrix_keyboard/README.md +++ b/examples/peripherals/gpio/matrix_keyboard/README.md @@ -23,7 +23,7 @@ This matrix keyboard driver is interrupt-driven, supports a configurable debounc This example can run on any target that has the dedicated feature (e.g. ESP32-S2). It's not necessary for your matrix board to have pull-up resisters on row/column lines. The driver has enabled internal pull-up resister by default. A typical matrix board should look as follows: -``` +```text row_0 +--------+-------------------+------------------------------+-----------------+ | | | | + | + | + @@ -51,7 +51,7 @@ row_n +--------+-------------------+------------------------------+----------- Build the project and flash it to the board, then run monitor tool to view serial output: -``` +```text idf.py -p PORT flash monitor ``` @@ -63,7 +63,7 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output -``` +```text I (2883) example: press event, key code = 0002 I (3003) example: release event, key code = 0002 I (5053) example: press event, key code = 0001 @@ -77,3 +77,7 @@ I (8923) example: release event, key code = 0103 I (9543) example: press event, key code = 0203 I (9683) example: release event, key code = 0203 ``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h index 825ae3146931..f4598c74cb9e 100644 --- a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h +++ b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c index daf1b6a3416f..48b7a23506e9 100644 --- a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c +++ b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,24 +7,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/timers.h" -#include "esp_compiler.h" #include "esp_log.h" +#include "esp_check.h" #include "driver/dedic_gpio.h" #include "driver/gpio.h" +#include "esp_private/gpio.h" #include "matrix_keyboard.h" -#include "esp_rom_sys.h" static const char *TAG = "mkbd"; -#define MKBD_CHECK(a, msg, tag, ret, ...) \ - do { \ - if (unlikely(!(a))) { \ - ESP_LOGE(TAG, "%s(%d): " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret_code = ret; \ - goto tag; \ - } \ - } while (0) - typedef struct matrix_kbd_t matrix_kbd_t; struct matrix_kbd_t { @@ -91,45 +82,36 @@ static void matrix_kbd_debounce_timer_callback(TimerHandle_t xTimer) esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handle_t *mkbd_handle) { - esp_err_t ret_code = ESP_OK; + esp_err_t ret = ESP_OK; matrix_kbd_t *mkbd = NULL; - MKBD_CHECK(config, "matrix keyboard configuration can't be null", err, ESP_ERR_INVALID_ARG); - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(config && mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); mkbd = calloc(1, sizeof(matrix_kbd_t) + (config->nr_row_gpios) * sizeof(uint32_t)); - MKBD_CHECK(mkbd, "allocate matrix keyboard context failed", err, ESP_ERR_NO_MEM); + ESP_RETURN_ON_FALSE(mkbd, ESP_ERR_NO_MEM, TAG, "no mem for matrix keyboard context"); + + // Create a ont-shot os timer, used for key debounce + mkbd->debounce_timer = xTimerCreate("kb_debounce", pdMS_TO_TICKS(config->debounce_ms), pdFALSE, mkbd, matrix_kbd_debounce_timer_callback); + ESP_GOTO_ON_FALSE(mkbd->debounce_timer, ESP_FAIL, err, TAG, "create debounce timer failed"); mkbd->nr_col_gpios = config->nr_col_gpios; mkbd->nr_row_gpios = config->nr_row_gpios; - // GPIO pad configuration - // Each GPIO used in matrix key board should be able to input and output - // In case the keyboard doesn't design a resister to pull up row/col line - // We enable the internal pull up resister, enable Open Drain as well - gpio_config_t io_conf = { - .mode = GPIO_MODE_INPUT_OUTPUT_OD, - .pull_up_en = 1 - }; - - for (int i = 0; i < config->nr_row_gpios; i++) { - io_conf.pin_bit_mask = 1ULL << config->row_gpios[i]; - gpio_config(&io_conf); - } - dedic_gpio_bundle_config_t bundle_row_config = { .gpio_array = config->row_gpios, .array_size = config->nr_row_gpios, + // Each GPIO used in matrix key board should be able to input and output .flags = { .in_en = 1, .out_en = 1, }, }; - MKBD_CHECK(dedic_gpio_new_bundle(&bundle_row_config, &mkbd->row_bundle) == ESP_OK, - "create row bundle failed", err, ESP_FAIL); + ESP_GOTO_ON_ERROR(dedic_gpio_new_bundle(&bundle_row_config, &mkbd->row_bundle), err, TAG, "create row bundle failed"); - for (int i = 0; i < config->nr_col_gpios; i++) { - io_conf.pin_bit_mask = 1ULL << config->col_gpios[i]; - gpio_config(&io_conf); + // In case the keyboard doesn't design a resister to pull up row/col line + // We enable the internal pull up resister, enable Open Drain as well + for (int i = 0; i < config->nr_row_gpios; i++) { + gpio_pullup_en(config->row_gpios[i]); + gpio_od_enable(config->row_gpios[i]); } dedic_gpio_bundle_config_t bundle_col_config = { @@ -140,8 +122,12 @@ esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handl .out_en = 1, }, }; - MKBD_CHECK(dedic_gpio_new_bundle(&bundle_col_config, &mkbd->col_bundle) == ESP_OK, - "create col bundle failed", err, ESP_FAIL); + ESP_GOTO_ON_ERROR(dedic_gpio_new_bundle(&bundle_col_config, &mkbd->col_bundle), err, TAG, "create col bundle failed"); + + for (int i = 0; i < config->nr_col_gpios; i++) { + gpio_pullup_en(config->col_gpios[i]); + gpio_od_enable(config->col_gpios[i]); + } // Disable interrupt dedic_gpio_bundle_set_interrupt_and_callback(mkbd->row_bundle, (1 << config->nr_row_gpios) - 1, @@ -149,45 +135,35 @@ esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handl dedic_gpio_bundle_set_interrupt_and_callback(mkbd->col_bundle, (1 << config->nr_col_gpios) - 1, DEDIC_GPIO_INTR_NONE, NULL, NULL); - // Create a ont-shot os timer, used for key debounce - mkbd->debounce_timer = xTimerCreate("kb_debounce", pdMS_TO_TICKS(config->debounce_ms), pdFALSE, mkbd, matrix_kbd_debounce_timer_callback); - MKBD_CHECK(mkbd->debounce_timer, "create debounce timer failed", err, ESP_FAIL); - * mkbd_handle = mkbd; return ESP_OK; err: - if (mkbd) { - if (mkbd->debounce_timer) { - xTimerDelete(mkbd->debounce_timer, 0); - } - if (mkbd->col_bundle) { - dedic_gpio_del_bundle(mkbd->col_bundle); - } - if (mkbd->row_bundle) { - dedic_gpio_del_bundle(mkbd->row_bundle); - } - free(mkbd); + if (mkbd->debounce_timer) { + xTimerDelete(mkbd->debounce_timer, 0); } - return ret_code; + if (mkbd->col_bundle) { + dedic_gpio_del_bundle(mkbd->col_bundle); + } + if (mkbd->row_bundle) { + dedic_gpio_del_bundle(mkbd->row_bundle); + } + free(mkbd); + return ret; } esp_err_t matrix_kbd_uninstall(matrix_kbd_handle_t mkbd_handle) { - esp_err_t ret_code = ESP_OK; - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); xTimerDelete(mkbd_handle->debounce_timer, 0); dedic_gpio_del_bundle(mkbd_handle->col_bundle); dedic_gpio_del_bundle(mkbd_handle->row_bundle); free(mkbd_handle); return ESP_OK; -err: - return ret_code; } esp_err_t matrix_kbd_start(matrix_kbd_handle_t mkbd_handle) { - esp_err_t ret_code = ESP_OK; - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); // row lines set to high level dedic_gpio_bundle_write(mkbd_handle->row_bundle, (1 << mkbd_handle->nr_row_gpios) - 1, (1 << mkbd_handle->nr_row_gpios) - 1); @@ -203,15 +179,11 @@ esp_err_t matrix_kbd_start(matrix_kbd_handle_t mkbd_handle) DEDIC_GPIO_INTR_BOTH_EDGE, matrix_kbd_row_isr_callback, mkbd_handle); return ESP_OK; -err: - return ret_code; } esp_err_t matrix_kbd_stop(matrix_kbd_handle_t mkbd_handle) { - esp_err_t ret_code = ESP_OK; - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); - + ESP_RETURN_ON_FALSE(mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); xTimerStop(mkbd_handle->debounce_timer, 0); // Disable interrupt @@ -221,17 +193,12 @@ esp_err_t matrix_kbd_stop(matrix_kbd_handle_t mkbd_handle) DEDIC_GPIO_INTR_NONE, NULL, NULL); return ESP_OK; -err: - return ret_code; } esp_err_t matrix_kbd_register_event_handler(matrix_kbd_handle_t mkbd_handle, matrix_kbd_event_handler handler, void *args) { - esp_err_t ret_code = ESP_OK; - MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(mkbd_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); mkbd_handle->event_handler = handler; mkbd_handle->event_handler_args = args; return ESP_OK; -err: - return ret_code; } diff --git a/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c b/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c index fd1008e90ba9..657d24136a02 100644 --- a/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c +++ b/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c @@ -1,11 +1,9 @@ -/* Matrix Keyboard (based on dedicated GPIO) example - - This example code is in the Public Domain (or CC0 licensed, at your option.) +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ #include #include "esp_log.h" #include "matrix_keyboard.h" diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/README.md b/examples/peripherals/i2s/i2s_basic/i2s_pdm/README.md index 6b6235f531c6..125d839e4ee1 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_pdm/README.md +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # I2S Basic PDM Mode Example diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py b/examples/peripherals/i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py index 444e1a5f97d9..036ae8788fb8 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/pytest_i2s_pdm.py @@ -11,6 +11,7 @@ @pytest.mark.esp32c6 @pytest.mark.esp32h2 @pytest.mark.esp32p4 +@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/examples/peripherals/i2s/i2s_basic/i2s_std/README.md b/examples/peripherals/i2s/i2s_basic/i2s_std/README.md index 5fc29993f73f..9ab8188df323 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_std/README.md +++ b/examples/peripherals/i2s/i2s_basic/i2s_std/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | # I2S Basic Standard Mode Example diff --git a/examples/peripherals/i2s/i2s_basic/i2s_std/pytest_i2s_std.py b/examples/peripherals/i2s/i2s_basic/i2s_std/pytest_i2s_std.py index 81c60e6d4fdd..8c4fe8f7b771 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_std/pytest_i2s_std.py +++ b/examples/peripherals/i2s/i2s_basic/i2s_std/pytest_i2s_std.py @@ -12,6 +12,7 @@ @pytest.mark.esp32c6 @pytest.mark.esp32h2 @pytest.mark.esp32p4 +@pytest.mark.esp32c61 @pytest.mark.generic def test_i2s_basic_example(dut: Dut) -> None: diff --git a/examples/peripherals/i2s/i2s_basic/i2s_tdm/README.md b/examples/peripherals/i2s/i2s_basic/i2s_tdm/README.md index f0b30749e4cf..1755a1f9514f 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_tdm/README.md +++ b/examples/peripherals/i2s/i2s_basic/i2s_tdm/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # I2S Basic TDM Mode Example diff --git a/examples/peripherals/i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py b/examples/peripherals/i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py index 80c1bbf321b6..3d0005b90982 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py +++ b/examples/peripherals/i2s/i2s_basic/i2s_tdm/pytest_i2s_tdm.py @@ -10,6 +10,7 @@ @pytest.mark.esp32c6 @pytest.mark.esp32h2 @pytest.mark.esp32p4 +@pytest.mark.esp32c61 @pytest.mark.generic def test_i2s_tdm_example(dut: Dut) -> None: diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md index b3b26f69ebde..85cc1c9486e4 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md +++ b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # I2S TDM Example -- ES7210 4-Ch ADC Codec diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md b/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md index 0ab480ffb284..79aee879b643 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | # I2S ES8311 Example diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/pytest_i2s_es8311.py b/examples/peripherals/i2s/i2s_codec/i2s_es8311/pytest_i2s_es8311.py index c888db7af6d7..54404601b03d 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/pytest_i2s_es8311.py +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/pytest_i2s_es8311.py @@ -12,6 +12,7 @@ @pytest.mark.esp32c6 @pytest.mark.esp32h2 @pytest.mark.esp32p4 +@pytest.mark.esp32c61 @pytest.mark.generic def test_i2s_es8311_example_generic(dut: Dut) -> None: dut.expect('i2s es8311 codec example start') diff --git a/examples/peripherals/isp/multi_pipelines/README.md b/examples/peripherals/isp/multi_pipelines/README.md index 71139ba6b41a..bfd80fbec16d 100644 --- a/examples/peripherals/isp/multi_pipelines/README.md +++ b/examples/peripherals/isp/multi_pipelines/README.md @@ -14,6 +14,7 @@ This example demonstrates how to use the ISP (image signal processor) to work wi - ISP Demosaic feature - ISP GAMMA feature - ISP Color feature +- ISP LSC feature ## Usage diff --git a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c index 15a9289cf6c1..3f2db636db8e 100644 --- a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c +++ b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c @@ -347,6 +347,28 @@ void app_main(void) ESP_ERROR_CHECK(esp_isp_color_configure(isp_proc, &color_config)); ESP_ERROR_CHECK(esp_isp_color_enable(isp_proc)); +#if CONFIG_ESP32P4_REV_MIN_FULL >= 100 + esp_isp_lsc_gain_array_t gain_array = {}; + esp_isp_lsc_config_t lsc_config = { + .gain_array = &gain_array, + }; + size_t gain_size = 0; + ESP_ERROR_CHECK(esp_isp_lsc_allocate_gain_array(isp_proc, &gain_array, &gain_size)); + + isp_lsc_gain_t gain_val = { + .decimal = 204, + .integer = 0, + }; + for (int i = 0; i < gain_size; i++) { + gain_array.gain_r[i].val = gain_val.val; + gain_array.gain_gr[i].val = gain_val.val; + gain_array.gain_gb[i].val = gain_val.val; + gain_array.gain_b[i].val = gain_val.val; + } + ESP_ERROR_CHECK(esp_isp_lsc_configure(isp_proc, &lsc_config)); + ESP_ERROR_CHECK(esp_isp_lsc_enable(isp_proc)); +#endif + typedef struct af_task_param_t { isp_proc_handle_t isp_proc; esp_sccb_io_handle_t dw9714_io_handle; diff --git a/examples/peripherals/lcd/i2c_oled/main/idf_component.yml b/examples/peripherals/lcd/i2c_oled/main/idf_component.yml index c890e61f8d80..e7c49c66f6e9 100644 --- a/examples/peripherals/lcd/i2c_oled/main/idf_component.yml +++ b/examples/peripherals/lcd/i2c_oled/main/idf_component.yml @@ -1,4 +1,4 @@ dependencies: - lvgl/lvgl: "~8.3.0" + lvgl/lvgl: "8.3.0" esp_lcd_sh1107: "^1" esp_lvgl_port: "^1" diff --git a/examples/peripherals/lcd/i80_controller/main/idf_component.yml b/examples/peripherals/lcd/i80_controller/main/idf_component.yml index 982d037d3757..f57987ae6bf1 100644 --- a/examples/peripherals/lcd/i80_controller/main/idf_component.yml +++ b/examples/peripherals/lcd/i80_controller/main/idf_component.yml @@ -1,2 +1,2 @@ dependencies: - lvgl/lvgl: "~8.4.0" + lvgl/lvgl: "8.4.0" diff --git a/examples/peripherals/lcd/mipi_dsi/main/idf_component.yml b/examples/peripherals/lcd/mipi_dsi/main/idf_component.yml index 856f24237a48..b445b5e83e8d 100644 --- a/examples/peripherals/lcd/mipi_dsi/main/idf_component.yml +++ b/examples/peripherals/lcd/mipi_dsi/main/idf_component.yml @@ -1,4 +1,4 @@ dependencies: - lvgl/lvgl: "~9.2.0" + lvgl/lvgl: "9.2.0" esp_lcd_ili9881c: "^1.0.0" esp_lcd_ek79007: "^1.0.0" diff --git a/examples/peripherals/lcd/mipi_dsi/main/mipi_dsi_lcd_example_main.c b/examples/peripherals/lcd/mipi_dsi/main/mipi_dsi_lcd_example_main.c index 8ae435e7e490..80f8e08f81cd 100644 --- a/examples/peripherals/lcd/mipi_dsi/main/mipi_dsi_lcd_example_main.c +++ b/examples/peripherals/lcd/mipi_dsi/main/mipi_dsi_lcd_example_main.c @@ -216,7 +216,7 @@ void app_main(void) .virtual_channel = 0, .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = EXAMPLE_MIPI_DSI_DPI_CLK_MHZ, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888, + .in_color_format = LCD_COLOR_FMT_RGB888, .video_timing = { .h_size = EXAMPLE_MIPI_DSI_LCD_H_RES, .v_size = EXAMPLE_MIPI_DSI_LCD_V_RES, diff --git a/examples/peripherals/lcd/rgb_panel/README.md b/examples/peripherals/lcd/rgb_panel/README.md index 97b991546138..dcc4b947e2d2 100644 --- a/examples/peripherals/lcd/rgb_panel/README.md +++ b/examples/peripherals/lcd/rgb_panel/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-S3 | -| ----------------- | -------- | +| Supported Targets | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | # RGB LCD Panel Example @@ -19,8 +19,8 @@ This example uses 3 kinds of **buffering mode**: ### Hardware Required -* An ESP development board, which has RGB LCD peripheral supported and **Octal PSRAM** onboard -* A general RGB panel, 16 bit-width, with HSYNC, VSYNC and DE signal +* An ESP development board, which supports the RGB LCD peripheral +* A general RGB panel, 16/24 bit-width, with HSYNC, VSYNC and DE signal * An USB cable for power supply and programming ### Hardware Connection @@ -36,7 +36,7 @@ The connection between ESP Board and the LCD is as follows: | | | | | PCLK+--------------+PCLK | | | | | -| DATA[15:0]+--------------+DATA[15:0] | +| DATA[N:0]+--------------+DATA[N:0] | | | | | | HSYNC+--------------+HSYNC | | | | | @@ -55,9 +55,9 @@ The connection between ESP Board and the LCD is as follows: Run `idf.py menuconfig` and go to `Example Configuration`: -1. Choose whether to `Use double Frame Buffer` -2. Choose whether to `Avoid tearing effect` (available only when step `1` was chosen to false) -3. Choose whether to `Use bounce buffer` (available only when step `1` was chosen to false) +1. `Use single frame buffer`: The RGB LCD driver allocates one frame buffer and mount it to the DMA. The example also allocates one draw buffer for the LVGL library. The draw buffer contents are copied to the frame buffer by the CPU. +2. `Use double frame buffer`: The RGB LCD driver allocates two frame buffers and mount them to the DMA. The LVGL library draws directly to the offline frame buffer while the online frame buffer is displayed by the RGB LCD controller. +3. `Use bounce buffer`: The RGB LCD driver allocates one frame buffer and two bounce buffers. The bounce buffers are mounted to the DMA. The frame buffer contents are copied to the bounce buffers by the CPU. The example also allocates one draw buffer for the LVGL library. The draw buffer contents are copied to the frame buffer by the CPU. 4. Choose the number of LCD data lines in `RGB LCD Data Lines` 5. Set the GPIOs used by RGB LCD peripheral in `GPIO assignment`, e.g. the synchronization signals (HSYNC, VSYNC, DE) and the data lines @@ -97,16 +97,13 @@ I (1102) main_task: Returned from app_main() * Why the LCD doesn't light up? * Please pay attention to the level used to turn on the LCD backlight, some LCD module needs a low level to turn it on, while others take a high level. You can change the backlight level macro `EXAMPLE_LCD_BK_LIGHT_ON_LEVEL` in [lvgl_example_main.c](main/rgb_lcd_example_main.c). -* No memory for frame buffer +* Where to allocate the frame buffer? * The frame buffer of RGB panel is located in ESP side (unlike other controller based LCDs, where the frame buffer is located in external chip). As the frame buffer usually consumes much RAM (depends on the LCD resolution and color depth), we recommend to put the frame buffer into PSRAM (like what we do in this example). However, putting frame buffer in PSRAM will limit the maximum PCLK due to the bandwidth of **SPI0**. -* LCD screen drift +* Why LCD screen drifts? * Slow down the PCLK frequency * Adjust other timing parameters like PCLK clock edge (by `pclk_active_neg`), sync porches like VBP (by `vsync_back_porch`) according to your LCD spec - * Enable `CONFIG_SPIRAM_FETCH_INSTRUCTIONS` and `CONFIG_SPIRAM_RODATA`, which can saves some bandwidth of SPI0 from being consumed by ICache. -* LCD screen tear effect - * Using double frame buffers - * Or adding an extra synchronization mechanism between writing (by Cache) and reading (by EDMA) the frame buffer. -* Low PCLK frequency + * Enable `CONFIG_SPIRAM_XIP_FROM_PSRAM`, which can saves some bandwidth of SPI0 from being consumed by ICache. +* How to further increase the PCLK frequency? * Enable `CONFIG_EXAMPLE_USE_BOUNCE_BUFFER`, which will make the LCD controller fetch data from internal SRAM (instead of the PSRAM), but at the cost of increasing CPU usage. * Enable `CONFIG_SPIRAM_XIP_FROM_PSRAM` can also help if the you're not using the bounce buffer mode. These two configurations can save some **SPI0** bandwidth from being consumed by ICache. * Why the RGB timing is correct but the LCD doesn't show anything? diff --git a/examples/peripherals/lcd/rgb_panel/main/Kconfig.projbuild b/examples/peripherals/lcd/rgb_panel/main/Kconfig.projbuild index 34415bb278ca..5dc913d6da38 100644 --- a/examples/peripherals/lcd/rgb_panel/main/Kconfig.projbuild +++ b/examples/peripherals/lcd/rgb_panel/main/Kconfig.projbuild @@ -1,23 +1,29 @@ menu "Example Configuration" - config EXAMPLE_DOUBLE_FB - bool "Use double Frame Buffer" - default "n" + choice EXAMPLE_LCD_BUFFER_MODE + prompt "RGB LCD Buffer Mode" + default EXAMPLE_USE_SINGLE_FB help - Enable this option, driver will allocate two frame buffers. + Select the LCD buffer mode. - config EXAMPLE_USE_BOUNCE_BUFFER - depends on !EXAMPLE_DOUBLE_FB - bool "Use bounce buffer" - help - Enable bounce buffer mode can achieve higher PCLK frequency at the cost of higher CPU consumption. + config EXAMPLE_USE_SINGLE_FB + bool "Use single frame buffer" + help + Allocate one frame buffer in the driver. + Allocate one draw buffer in LVGL. - config EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM - depends on !EXAMPLE_DOUBLE_FB - bool "Avoid tearing effect" - default "y" - help - Enable this option, the example will use a pair of semaphores to avoid the tearing effect. - Note, if the Double Frame Buffer is used, then we can also avoid the tearing effect without the lock. + config EXAMPLE_USE_DOUBLE_FB + bool "Use double frame buffer" + help + Allocate two frame buffers in the driver. + The frame buffers also work as ping-pong draw buffers in LVGL. + + config EXAMPLE_USE_BOUNCE_BUFFER + bool "Use bounce buffer" + help + Allocate one frame buffer in the driver. + Allocate two bounce buffers in the driver. + Allocate one draw buffer in LVGL. + endchoice choice EXAMPLE_LCD_DATA_LINES prompt "RGB LCD Data Lines" @@ -27,11 +33,15 @@ menu "Example Configuration" config EXAMPLE_LCD_DATA_LINES_16 bool "16 data lines" + + config EXAMPLE_LCD_DATA_LINES_24 + bool "24 data lines" endchoice config EXAMPLE_LCD_DATA_LINES int default 16 if EXAMPLE_LCD_DATA_LINES_16 + default 24 if EXAMPLE_LCD_DATA_LINES_24 menu "GPIO assignment" config EXAMPLE_LCD_VSYNC_GPIO @@ -114,5 +124,45 @@ menu "Example Configuration" int "DATA15 GPIO" help GPIO pin number for data bus[15]. + config EXAMPLE_LCD_DATA16_GPIO + int "DATA16 GPIO" + depends on EXAMPLE_LCD_DATA_LINES > 16 + help + GPIO pin number for data bus[16]. + config EXAMPLE_LCD_DATA17_GPIO + int "DATA17 GPIO" + depends on EXAMPLE_LCD_DATA_LINES > 16 + help + GPIO pin number for data bus[17]. + config EXAMPLE_LCD_DATA18_GPIO + int "DATA18 GPIO" + depends on EXAMPLE_LCD_DATA_LINES > 16 + help + GPIO pin number for data bus[18]. + config EXAMPLE_LCD_DATA19_GPIO + int "DATA19 GPIO" + depends on EXAMPLE_LCD_DATA_LINES > 16 + help + GPIO pin number for data bus[19]. + config EXAMPLE_LCD_DATA20_GPIO + int "DATA20 GPIO" + depends on EXAMPLE_LCD_DATA_LINES > 16 + help + GPIO pin number for data bus[20]. + config EXAMPLE_LCD_DATA21_GPIO + int "DATA21 GPIO" + depends on EXAMPLE_LCD_DATA_LINES > 16 + help + GPIO pin number for data bus[21]. + config EXAMPLE_LCD_DATA22_GPIO + int "DATA22 GPIO" + depends on EXAMPLE_LCD_DATA_LINES > 16 + help + GPIO pin number for data bus[22]. + config EXAMPLE_LCD_DATA23_GPIO + int "DATA23 GPIO" + depends on EXAMPLE_LCD_DATA_LINES > 16 + help + GPIO pin number for data bus[23]. endmenu endmenu diff --git a/examples/peripherals/lcd/rgb_panel/main/idf_component.yml b/examples/peripherals/lcd/rgb_panel/main/idf_component.yml index f929e7f74a09..4ca86dce7ec3 100644 --- a/examples/peripherals/lcd/rgb_panel/main/idf_component.yml +++ b/examples/peripherals/lcd/rgb_panel/main/idf_component.yml @@ -1,2 +1,2 @@ dependencies: - lvgl/lvgl: "~9.2.0" + lvgl/lvgl: "9.2.0" diff --git a/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c b/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c index 8823c8c01d08..d9b983617d21 100644 --- a/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c +++ b/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c @@ -10,7 +10,6 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" #include "esp_timer.h" #include "esp_lcd_panel_ops.h" #include "esp_lcd_panel_rgb.h" @@ -61,17 +60,31 @@ static const char *TAG = "example"; #define EXAMPLE_PIN_NUM_DATA13 CONFIG_EXAMPLE_LCD_DATA13_GPIO #define EXAMPLE_PIN_NUM_DATA14 CONFIG_EXAMPLE_LCD_DATA14_GPIO #define EXAMPLE_PIN_NUM_DATA15 CONFIG_EXAMPLE_LCD_DATA15_GPIO +#if CONFIG_EXAMPLE_LCD_DATA_LINES > 16 +#define EXAMPLE_PIN_NUM_DATA16 CONFIG_EXAMPLE_LCD_DATA16_GPIO +#define EXAMPLE_PIN_NUM_DATA17 CONFIG_EXAMPLE_LCD_DATA17_GPIO +#define EXAMPLE_PIN_NUM_DATA18 CONFIG_EXAMPLE_LCD_DATA18_GPIO +#define EXAMPLE_PIN_NUM_DATA19 CONFIG_EXAMPLE_LCD_DATA19_GPIO +#define EXAMPLE_PIN_NUM_DATA20 CONFIG_EXAMPLE_LCD_DATA20_GPIO +#define EXAMPLE_PIN_NUM_DATA21 CONFIG_EXAMPLE_LCD_DATA21_GPIO +#define EXAMPLE_PIN_NUM_DATA22 CONFIG_EXAMPLE_LCD_DATA22_GPIO +#define EXAMPLE_PIN_NUM_DATA23 CONFIG_EXAMPLE_LCD_DATA23_GPIO +#endif -#if CONFIG_EXAMPLE_DOUBLE_FB +#if CONFIG_EXAMPLE_USE_DOUBLE_FB #define EXAMPLE_LCD_NUM_FB 2 #else #define EXAMPLE_LCD_NUM_FB 1 -#endif // CONFIG_EXAMPLE_DOUBLE_FB +#endif // CONFIG_EXAMPLE_USE_DOUBLE_FB #if CONFIG_EXAMPLE_LCD_DATA_LINES_16 #define EXAMPLE_DATA_BUS_WIDTH 16 #define EXAMPLE_PIXEL_SIZE 2 #define EXAMPLE_LV_COLOR_FORMAT LV_COLOR_FORMAT_RGB565 +#elif CONFIG_EXAMPLE_LCD_DATA_LINES_24 +#define EXAMPLE_DATA_BUS_WIDTH 24 +#define EXAMPLE_PIXEL_SIZE 3 +#define EXAMPLE_LV_COLOR_FORMAT LV_COLOR_FORMAT_RGB888 #endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -86,23 +99,13 @@ static const char *TAG = "example"; // LVGL library is not thread-safe, this example will call LVGL APIs from different tasks, so use a mutex to protect it static _lock_t lvgl_api_lock; -// we use two semaphores to sync the VSYNC event and the LVGL task, to avoid potential tearing effect -#if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM -SemaphoreHandle_t sem_vsync_end; -SemaphoreHandle_t sem_gui_ready; -#endif - extern void example_lvgl_demo_ui(lv_display_t *disp); -static bool example_on_vsync_event(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_data) +static bool example_notify_lvgl_flush_ready(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_ctx) { - BaseType_t high_task_awoken = pdFALSE; -#if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM - if (xSemaphoreTakeFromISR(sem_gui_ready, &high_task_awoken) == pdTRUE) { - xSemaphoreGiveFromISR(sem_vsync_end, &high_task_awoken); - } -#endif - return high_task_awoken == pdTRUE; + lv_display_t *disp = (lv_display_t *)user_ctx; + lv_display_flush_ready(disp); + return false; } static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) @@ -112,13 +115,8 @@ static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uin int offsetx2 = area->x2; int offsety1 = area->y1; int offsety2 = area->y2; -#if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM - xSemaphoreGive(sem_gui_ready); - xSemaphoreTake(sem_vsync_end, portMAX_DELAY); -#endif // pass the draw buffer to the driver esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, px_map); - lv_display_flush_ready(disp); } static void example_increase_lvgl_tick(void *arg) @@ -165,14 +163,6 @@ static void example_bsp_set_lcd_backlight(uint32_t level) void app_main(void) { -#if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM - ESP_LOGI(TAG, "Create semaphores"); - sem_vsync_end = xSemaphoreCreateBinary(); - assert(sem_vsync_end); - sem_gui_ready = xSemaphoreCreateBinary(); - assert(sem_gui_ready); -#endif - ESP_LOGI(TAG, "Turn off LCD backlight"); example_bsp_init_lcd_backlight(); example_bsp_set_lcd_backlight(EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL); @@ -209,6 +199,16 @@ void app_main(void) EXAMPLE_PIN_NUM_DATA13, EXAMPLE_PIN_NUM_DATA14, EXAMPLE_PIN_NUM_DATA15, +#if CONFIG_EXAMPLE_LCD_DATA_LINES > 16 + EXAMPLE_PIN_NUM_DATA16, + EXAMPLE_PIN_NUM_DATA17, + EXAMPLE_PIN_NUM_DATA18, + EXAMPLE_PIN_NUM_DATA19, + EXAMPLE_PIN_NUM_DATA20, + EXAMPLE_PIN_NUM_DATA21, + EXAMPLE_PIN_NUM_DATA22, + EXAMPLE_PIN_NUM_DATA23 +#endif }, .timings = { .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, @@ -246,7 +246,7 @@ void app_main(void) // create draw buffers void *buf1 = NULL; void *buf2 = NULL; -#if CONFIG_EXAMPLE_DOUBLE_FB +#if CONFIG_EXAMPLE_USE_DOUBLE_FB ESP_LOGI(TAG, "Use frame buffers as LVGL draw buffers"); ESP_ERROR_CHECK(esp_lcd_rgb_panel_get_frame_buffer(panel_handle, 2, &buf1, &buf2)); // set LVGL draw buffers and direct mode @@ -259,14 +259,14 @@ void app_main(void) assert(buf1); // set LVGL draw buffers and partial mode lv_display_set_buffers(display, buf1, buf2, draw_buffer_sz, LV_DISPLAY_RENDER_MODE_PARTIAL); -#endif // CONFIG_EXAMPLE_DOUBLE_FB +#endif // CONFIG_EXAMPLE_USE_DOUBLE_FB // set the callback which can copy the rendered image to an area of the display lv_display_set_flush_cb(display, example_lvgl_flush_cb); ESP_LOGI(TAG, "Register event callbacks"); esp_lcd_rgb_panel_event_callbacks_t cbs = { - .on_vsync = example_on_vsync_event, + .on_color_trans_done = example_notify_lvgl_flush_ready, }; ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, display)); diff --git a/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py b/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py index 7b0c751ee557..d9af5c60c31e 100644 --- a/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py +++ b/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py @@ -15,7 +15,29 @@ ], indirect=True, ) -def test_rgb_lcd_lvgl(dut: Dut) -> None: +def test_rgb_lcd_lvgl_esp32s3(dut: Dut) -> None: + dut.expect_exact('example: Turn off LCD backlight') + dut.expect_exact('example: Install RGB LCD panel driver') + dut.expect_exact('example: Initialize RGB LCD panel') + dut.expect_exact('example: Turn on LCD backlight') + dut.expect_exact('example: Initialize LVGL library') + dut.expect_exact('example: Install LVGL tick timer') + dut.expect_exact('example: Create LVGL task') + dut.expect_exact('example: Display LVGL UI') + + +@pytest.mark.esp32p4 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'single_fb_with_bb', + 'single_fb_no_bb', + 'double_fb', + ], + indirect=True, +) +def test_rgb_lcd_lvgl_esp32p4(dut: Dut) -> None: dut.expect_exact('example: Turn off LCD backlight') dut.expect_exact('example: Install RGB LCD panel driver') dut.expect_exact('example: Initialize RGB LCD panel') diff --git a/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.double_fb b/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.double_fb index 12cbd3b12c52..5f206e081933 100644 --- a/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.double_fb +++ b/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.double_fb @@ -1 +1 @@ -CONFIG_EXAMPLE_DOUBLE_FB=y +CONFIG_EXAMPLE_USE_DOUBLE_FB=y diff --git a/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.single_fb_no_bb b/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.single_fb_no_bb index 097e4478f9c8..0244809f4cda 100644 --- a/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.single_fb_no_bb +++ b/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.single_fb_no_bb @@ -1,2 +1 @@ -CONFIG_EXAMPLE_DOUBLE_FB=n -CONFIG_EXAMPLE_USE_BOUNCE_BUFFER=n +CONFIG_EXAMPLE_USE_SINGLE_FB=y diff --git a/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.single_fb_with_bb b/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.single_fb_with_bb index 1bd247da1c47..9257f289a3aa 100644 --- a/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.single_fb_with_bb +++ b/examples/peripherals/lcd/rgb_panel/sdkconfig.ci.single_fb_with_bb @@ -1,2 +1 @@ -CONFIG_EXAMPLE_DOUBLE_FB=n CONFIG_EXAMPLE_USE_BOUNCE_BUFFER=y diff --git a/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults.esp32p4 b/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults.esp32p4 new file mode 100644 index 000000000000..b5b09d8c107f --- /dev/null +++ b/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults.esp32p4 @@ -0,0 +1,46 @@ +# enable the experimental features for higher PSRAM speed +CONFIG_IDF_EXPERIMENTAL_FEATURES=y + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_HEX=y +CONFIG_SPIRAM_SPEED_200M=y + +# LCD_CAM support 24 data lines at most +CONFIG_EXAMPLE_LCD_DATA_LINES_24=y +CONFIG_LV_COLOR_DEPTH_24=y + +# Default GPIO assignment +CONFIG_EXAMPLE_LCD_VSYNC_GPIO=41 +CONFIG_EXAMPLE_LCD_HSYNC_GPIO=39 +CONFIG_EXAMPLE_LCD_DE_GPIO=43 +CONFIG_EXAMPLE_LCD_PCLK_GPIO=33 + +# B0:B7 <=> DATA0:DATA7 +CONFIG_EXAMPLE_LCD_DATA0_GPIO=34 +CONFIG_EXAMPLE_LCD_DATA1_GPIO=12 +CONFIG_EXAMPLE_LCD_DATA2_GPIO=10 +CONFIG_EXAMPLE_LCD_DATA3_GPIO=40 +CONFIG_EXAMPLE_LCD_DATA4_GPIO=42 +CONFIG_EXAMPLE_LCD_DATA5_GPIO=27 +CONFIG_EXAMPLE_LCD_DATA6_GPIO=29 +CONFIG_EXAMPLE_LCD_DATA7_GPIO=31 + +# G0:G7 <=> DATA8:DATA15 +CONFIG_EXAMPLE_LCD_DATA8_GPIO=16 +CONFIG_EXAMPLE_LCD_DATA9_GPIO=14 +CONFIG_EXAMPLE_LCD_DATA10_GPIO=21 +CONFIG_EXAMPLE_LCD_DATA11_GPIO=23 +CONFIG_EXAMPLE_LCD_DATA12_GPIO=26 +CONFIG_EXAMPLE_LCD_DATA13_GPIO=28 +CONFIG_EXAMPLE_LCD_DATA14_GPIO=30 +CONFIG_EXAMPLE_LCD_DATA15_GPIO=32 + +# R0:R7 <=> DATA16:DATA23 +CONFIG_EXAMPLE_LCD_DATA16_GPIO=22 +CONFIG_EXAMPLE_LCD_DATA17_GPIO=20 +CONFIG_EXAMPLE_LCD_DATA18_GPIO=18 +CONFIG_EXAMPLE_LCD_DATA19_GPIO=6 +CONFIG_EXAMPLE_LCD_DATA20_GPIO=0 +CONFIG_EXAMPLE_LCD_DATA21_GPIO=15 +CONFIG_EXAMPLE_LCD_DATA22_GPIO=17 +CONFIG_EXAMPLE_LCD_DATA23_GPIO=19 diff --git a/examples/peripherals/lcd/spi_lcd_touch/main/idf_component.yml b/examples/peripherals/lcd/spi_lcd_touch/main/idf_component.yml index 1ce88fe63e8e..9f43889e3d1e 100644 --- a/examples/peripherals/lcd/spi_lcd_touch/main/idf_component.yml +++ b/examples/peripherals/lcd/spi_lcd_touch/main/idf_component.yml @@ -1,5 +1,5 @@ dependencies: - lvgl/lvgl: "~9.2.0" + lvgl/lvgl: "9.2.0" esp_lcd_ili9341: "^1.0" esp_lcd_gc9a01: "^1.0" esp_lcd_touch_stmpe610: "^1.0" diff --git a/examples/peripherals/mcpwm/mcpwm_sync/main/mcpwm_sync_example_main.c b/examples/peripherals/mcpwm/mcpwm_sync/main/mcpwm_sync_example_main.c index c05aa0e00005..bb7279d0f753 100644 --- a/examples/peripherals/mcpwm/mcpwm_sync/main/mcpwm_sync_example_main.c +++ b/examples/peripherals/mcpwm/mcpwm_sync/main/mcpwm_sync_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -28,6 +28,12 @@ static void example_setup_sync_strategy(mcpwm_timer_handle_t timers[]) // | | | // v v v // timer0 timer1 timer2 + gpio_config_t sync_gpio_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT(EXAMPLE_SYNC_GPIO), + }; + ESP_ERROR_CHECK(gpio_config(&sync_gpio_conf)); + ESP_LOGI(TAG, "Create GPIO sync source"); mcpwm_sync_handle_t gpio_sync_source = NULL; mcpwm_gpio_sync_src_config_t gpio_sync_config = { @@ -35,7 +41,6 @@ static void example_setup_sync_strategy(mcpwm_timer_handle_t timers[]) .gpio_num = EXAMPLE_SYNC_GPIO, .flags.pull_down = true, .flags.active_neg = false, // by default, a posedge pulse can trigger a sync event - .flags.io_loop_back = true, // then we can trigger a sync event using `gpio_set_level` on the same GPIO }; ESP_ERROR_CHECK(mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync_source)); @@ -50,8 +55,9 @@ static void example_setup_sync_strategy(mcpwm_timer_handle_t timers[]) } ESP_LOGI(TAG, "Trigger a pulse on the GPIO as a sync event"); - gpio_set_level(EXAMPLE_SYNC_GPIO, 0); - gpio_set_level(EXAMPLE_SYNC_GPIO, 1); + ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_SYNC_GPIO, 0)); + ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_SYNC_GPIO, 1)); + ESP_ERROR_CHECK(gpio_reset_pin(EXAMPLE_SYNC_GPIO)); } #endif // CONFIG_EXAMPLE_SYNC_FROM_GPIO diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c index 41de582782c5..6ad6b4d238c5 100644 --- a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c @@ -82,8 +82,6 @@ esp_err_t esp_probe_priv_init_hardware(esp_probe_handle_t handle, esp_probe_conf .valid_gpio_num = GPIO_NUM_NC, // Does not need valid gpio, all data gpio are used as sampling channel .flags = { .clk_gate_en = false, - .io_loop_back = true, - .io_no_init = true, } }; memcpy(parlio_rx_cfg.data_gpio_nums, config->probe_gpio, PARLIO_RX_UNIT_MAX_DATA_WIDTH * sizeof(gpio_num_t)); diff --git a/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/idf_component.yml b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/idf_component.yml index fcdb51a8629b..7dba8c85e006 100644 --- a/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/idf_component.yml +++ b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/idf_component.yml @@ -1,3 +1,3 @@ dependencies: idf: ">=5.1" - lvgl/lvgl: "~8.3.0" + lvgl/lvgl: "8.3.0" diff --git a/examples/peripherals/timer_group/gptimer_capture_hc_sr04/README.md b/examples/peripherals/timer_group/gptimer_capture_hc_sr04/README.md index 26ed2f38b78f..4843828bc25b 100644 --- a/examples/peripherals/timer_group/gptimer_capture_hc_sr04/README.md +++ b/examples/peripherals/timer_group/gptimer_capture_hc_sr04/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | -| ----------------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # HC-SR04 Example based on GPTimer Capture and ETM diff --git a/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py b/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py index 0c668e45bb15..2756fe0fa292 100644 --- a/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py +++ b/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py @@ -6,6 +6,7 @@ @pytest.mark.esp32c5 @pytest.mark.esp32c6 +@pytest.mark.esp32c61 @pytest.mark.esp32h2 @pytest.mark.esp32p4 @pytest.mark.generic diff --git a/examples/peripherals/usb/host/cdc/cdc_acm_vcp/sdkconfig.defaults b/examples/peripherals/usb/host/cdc/cdc_acm_vcp/sdkconfig.defaults index 990777805d61..a3e635c9d8d5 100644 --- a/examples/peripherals/usb/host/cdc/cdc_acm_vcp/sdkconfig.defaults +++ b/examples/peripherals/usb/host/cdc/cdc_acm_vcp/sdkconfig.defaults @@ -2,3 +2,4 @@ # Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration # CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_USB_HOST_HUBS_SUPPORTED=y diff --git a/examples/peripherals/usb/host/hid/sdkconfig.defaults b/examples/peripherals/usb/host/hid/sdkconfig.defaults new file mode 100644 index 000000000000..bf1b553b2388 --- /dev/null +++ b/examples/peripherals/usb/host/hid/sdkconfig.defaults @@ -0,0 +1,4 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_USB_HOST_HUBS_SUPPORTED=y diff --git a/examples/peripherals/usb/host/msc/main/msc_example_main.c b/examples/peripherals/usb/host/msc/main/msc_example_main.c index eb934a568103..630c95e6b157 100644 --- a/examples/peripherals/usb/host/msc/main/msc_example_main.c +++ b/examples/peripherals/usb/host/msc/main/msc_example_main.c @@ -29,6 +29,11 @@ static const char *TAG = "example"; #define APP_QUIT_PIN GPIO_NUM_0 // BOOT button on most boards #define BUFFER_SIZE 4096 // The read/write performance can be improved with larger buffer for the cost of RAM, 4kB is enough for most usecases +// IMPORTANT NOTE +// MSC Class Driver is not fully support connecting devices through external Hub. +// TODO: Remove this line after MSC Class Driver will support it +static bool dev_present = false; + /** * @brief Application Queue and its messages ID */ @@ -78,7 +83,7 @@ static void gpio_cb(void *arg) static void msc_event_cb(const msc_host_event_t *event, void *arg) { if (event->event == MSC_DEVICE_CONNECTED) { - ESP_LOGI(TAG, "MSC device connected"); + ESP_LOGI(TAG, "MSC device connected (usb_addr=%d)", event->device.address); app_message_t message = { .id = APP_DEVICE_CONNECTED, .data.new_dev_address = event->device.address, @@ -274,47 +279,56 @@ void app_main(void) xQueueReceive(app_queue, &msg, portMAX_DELAY); if (msg.id == APP_DEVICE_CONNECTED) { - // 1. MSC flash drive connected. Open it and map it to Virtual File System - ESP_ERROR_CHECK(msc_host_install_device(msg.data.new_dev_address, &msc_device)); - const esp_vfs_fat_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 3, - .allocation_unit_size = 8192, - }; - ESP_ERROR_CHECK(msc_host_vfs_register(msc_device, MNT_PATH, &mount_config, &vfs_handle)); - - // 2. Print information about the connected disk - msc_host_device_info_t info; - ESP_ERROR_CHECK(msc_host_get_device_info(msc_device, &info)); - msc_host_print_descriptors(msc_device); - print_device_info(&info); - - // 3. List all the files in root directory - ESP_LOGI(TAG, "ls command output:"); - struct dirent *d; - DIR *dh = opendir(MNT_PATH); - assert(dh); - while ((d = readdir(dh)) != NULL) { - printf("%s\n", d->d_name); + if (dev_present) { + ESP_LOGW(TAG, "MSC Example handles only one device at a time"); + } else { + // 0. Change flag + dev_present = true; + // 1. MSC flash drive connected. Open it and map it to Virtual File System + ESP_ERROR_CHECK(msc_host_install_device(msg.data.new_dev_address, &msc_device)); + const esp_vfs_fat_mount_config_t mount_config = { + .format_if_mount_failed = false, + .max_files = 3, + .allocation_unit_size = 8192, + }; + ESP_ERROR_CHECK(msc_host_vfs_register(msc_device, MNT_PATH, &mount_config, &vfs_handle)); + + // 2. Print information about the connected disk + msc_host_device_info_t info; + ESP_ERROR_CHECK(msc_host_get_device_info(msc_device, &info)); + msc_host_print_descriptors(msc_device); + print_device_info(&info); + + // 3. List all the files in root directory + ESP_LOGI(TAG, "ls command output:"); + struct dirent *d; + DIR *dh = opendir(MNT_PATH); + assert(dh); + while ((d = readdir(dh)) != NULL) { + printf("%s\n", d->d_name); + } + closedir(dh); + + // 4. The disk is mounted to Virtual File System, perform some basic demo file operation + file_operations(); + + // 5. Perform speed test + speed_test(); + + ESP_LOGI(TAG, "Example finished, you can disconnect the USB flash drive"); } - closedir(dh); - - // 4. The disk is mounted to Virtual File System, perform some basic demo file operation - file_operations(); - - // 5. Perform speed test - speed_test(); - - ESP_LOGI(TAG, "Example finished, you can disconnect the USB flash drive"); } if ((msg.id == APP_DEVICE_DISCONNECTED) || (msg.id == APP_QUIT)) { - if (vfs_handle) { - ESP_ERROR_CHECK(msc_host_vfs_unregister(vfs_handle)); - vfs_handle = NULL; - } - if (msc_device) { - ESP_ERROR_CHECK(msc_host_uninstall_device(msc_device)); - msc_device = NULL; + if (dev_present) { + dev_present = false; + if (vfs_handle) { + ESP_ERROR_CHECK(msc_host_vfs_unregister(vfs_handle)); + vfs_handle = NULL; + } + if (msc_device) { + ESP_ERROR_CHECK(msc_host_uninstall_device(msc_device)); + msc_device = NULL; + } } if (msg.id == APP_QUIT) { // This will cause the usb_task to exit diff --git a/examples/peripherals/usb/host/msc/sdkconfig.defaults b/examples/peripherals/usb/host/msc/sdkconfig.defaults new file mode 100644 index 000000000000..bf1b553b2388 --- /dev/null +++ b/examples/peripherals/usb/host/msc/sdkconfig.defaults @@ -0,0 +1,4 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_USB_HOST_HUBS_SUPPORTED=y diff --git a/examples/peripherals/usb/host/usb_host_lib/main/class_driver.c b/examples/peripherals/usb/host/usb_host_lib/main/class_driver.c index 594488df5193..5a89e40dea3a 100644 --- a/examples/peripherals/usb/host/usb_host_lib/main/class_driver.c +++ b/examples/peripherals/usb/host/usb_host_lib/main/class_driver.c @@ -13,21 +13,40 @@ #define CLIENT_NUM_EVENT_MSG 5 typedef enum { - ACTION_OPEN_DEV = 0x01, - ACTION_GET_DEV_INFO = 0x02, - ACTION_GET_DEV_DESC = 0x04, - ACTION_GET_CONFIG_DESC = 0x08, - ACTION_GET_STR_DESC = 0x10, - ACTION_CLOSE_DEV = 0x20, - ACTION_EXIT = 0x40, - ACTION_RECONNECT = 0x80, + ACTION_OPEN_DEV = (1 << 0), + ACTION_GET_DEV_INFO = (1 << 1), + ACTION_GET_DEV_DESC = (1 << 2), + ACTION_GET_CONFIG_DESC = (1 << 3), + ACTION_GET_STR_DESC = (1 << 4), + ACTION_CLOSE_DEV = (1 << 5), } action_t; +#define DEV_MAX_COUNT 128 + typedef struct { usb_host_client_handle_t client_hdl; uint8_t dev_addr; usb_device_handle_t dev_hdl; - uint32_t actions; + action_t actions; +} usb_device_t; + +typedef struct { + struct { + union { + struct { + uint8_t unhandled_devices: 1; /**< Device has unhandled devices */ + uint8_t shutdown: 1; /**< */ + uint8_t reserved6: 6; /**< Reserved */ + }; + uint8_t val; /**< Class drivers' flags value */ + } flags; /**< Class drivers' flags */ + usb_device_t device[DEV_MAX_COUNT]; /**< Class drivers' static array of devices */ + } mux_protected; /**< Mutex protected members. Must be protected by the Class mux_lock when accessed */ + + struct { + usb_host_client_handle_t client_hdl; + SemaphoreHandle_t mux_lock; /**< Mutex for protected members */ + } constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ } class_driver_t; static const char *TAG = "CLASS"; @@ -38,79 +57,94 @@ static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void * class_driver_t *driver_obj = (class_driver_t *)arg; switch (event_msg->event) { case USB_HOST_CLIENT_EVENT_NEW_DEV: - if (driver_obj->dev_addr == 0) { - driver_obj->dev_addr = event_msg->new_dev.address; - //Open the device next - driver_obj->actions |= ACTION_OPEN_DEV; - } + // Save the device address + xSemaphoreTake(driver_obj->constant.mux_lock, portMAX_DELAY); + driver_obj->mux_protected.device[event_msg->new_dev.address].dev_addr = event_msg->new_dev.address; + driver_obj->mux_protected.device[event_msg->new_dev.address].dev_hdl = NULL; + // Open the device next + driver_obj->mux_protected.device[event_msg->new_dev.address].actions |= ACTION_OPEN_DEV; + // Set flag + driver_obj->mux_protected.flags.unhandled_devices = 1; + xSemaphoreGive(driver_obj->constant.mux_lock); break; case USB_HOST_CLIENT_EVENT_DEV_GONE: - if (driver_obj->dev_hdl != NULL) { - //Cancel any other actions and close the device next - driver_obj->actions = ACTION_CLOSE_DEV; + // Cancel any other actions and close the device next + xSemaphoreTake(driver_obj->constant.mux_lock, portMAX_DELAY); + for (uint8_t i = 0; i < DEV_MAX_COUNT; i++) { + if (driver_obj->mux_protected.device[i].dev_hdl == event_msg->dev_gone.dev_hdl) { + driver_obj->mux_protected.device[i].actions = ACTION_CLOSE_DEV; + // Set flag + driver_obj->mux_protected.flags.unhandled_devices = 1; + } } + xSemaphoreGive(driver_obj->constant.mux_lock); break; default: - //Should never occur + // Should never occur abort(); } } -static void action_open_dev(class_driver_t *driver_obj) +static void action_open_dev(usb_device_t *device_obj) { - assert(driver_obj->dev_addr != 0); - ESP_LOGI(TAG, "Opening device at address %d", driver_obj->dev_addr); - ESP_ERROR_CHECK(usb_host_device_open(driver_obj->client_hdl, driver_obj->dev_addr, &driver_obj->dev_hdl)); - //Get the device's information next - driver_obj->actions &= ~ACTION_OPEN_DEV; - driver_obj->actions |= ACTION_GET_DEV_INFO; + assert(device_obj->dev_addr != 0); + ESP_LOGI(TAG, "Opening device at address %d", device_obj->dev_addr); + ESP_ERROR_CHECK(usb_host_device_open(device_obj->client_hdl, device_obj->dev_addr, &device_obj->dev_hdl)); + // Get the device's information next + device_obj->actions |= ACTION_GET_DEV_INFO; } -static void action_get_info(class_driver_t *driver_obj) +static void action_get_info(usb_device_t *device_obj) { - assert(driver_obj->dev_hdl != NULL); + assert(device_obj->dev_hdl != NULL); ESP_LOGI(TAG, "Getting device information"); usb_device_info_t dev_info; - ESP_ERROR_CHECK(usb_host_device_info(driver_obj->dev_hdl, &dev_info)); + ESP_ERROR_CHECK(usb_host_device_info(device_obj->dev_hdl, &dev_info)); ESP_LOGI(TAG, "\t%s speed", (char *[]) { "Low", "Full", "High" }[dev_info.speed]); - ESP_LOGI(TAG, "\tbConfigurationValue %d", dev_info.bConfigurationValue); + ESP_LOGI(TAG, "\tParent info:"); + if (dev_info.parent.dev_hdl) { + usb_device_info_t parent_dev_info; + ESP_ERROR_CHECK(usb_host_device_info(dev_info.parent.dev_hdl, &parent_dev_info)); + ESP_LOGI(TAG, "\t\tBus addr: %d", parent_dev_info.dev_addr); + ESP_LOGI(TAG, "\t\tPort: %d", dev_info.parent.port_num); - //Get the device descriptor next - driver_obj->actions &= ~ACTION_GET_DEV_INFO; - driver_obj->actions |= ACTION_GET_DEV_DESC; + } else { + ESP_LOGI(TAG, "\t\tPort: ROOT"); + } + ESP_LOGI(TAG, "\tbConfigurationValue %d", dev_info.bConfigurationValue); + // Get the device descriptor next + device_obj->actions |= ACTION_GET_DEV_DESC; } -static void action_get_dev_desc(class_driver_t *driver_obj) +static void action_get_dev_desc(usb_device_t *device_obj) { - assert(driver_obj->dev_hdl != NULL); + assert(device_obj->dev_hdl != NULL); ESP_LOGI(TAG, "Getting device descriptor"); const usb_device_desc_t *dev_desc; - ESP_ERROR_CHECK(usb_host_get_device_descriptor(driver_obj->dev_hdl, &dev_desc)); + ESP_ERROR_CHECK(usb_host_get_device_descriptor(device_obj->dev_hdl, &dev_desc)); usb_print_device_descriptor(dev_desc); - //Get the device's config descriptor next - driver_obj->actions &= ~ACTION_GET_DEV_DESC; - driver_obj->actions |= ACTION_GET_CONFIG_DESC; + // Get the device's config descriptor next + device_obj->actions |= ACTION_GET_CONFIG_DESC; } -static void action_get_config_desc(class_driver_t *driver_obj) +static void action_get_config_desc(usb_device_t *device_obj) { - assert(driver_obj->dev_hdl != NULL); + assert(device_obj->dev_hdl != NULL); ESP_LOGI(TAG, "Getting config descriptor"); const usb_config_desc_t *config_desc; - ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(driver_obj->dev_hdl, &config_desc)); + ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(device_obj->dev_hdl, &config_desc)); usb_print_config_descriptor(config_desc, NULL); - //Get the device's string descriptors next - driver_obj->actions &= ~ACTION_GET_CONFIG_DESC; - driver_obj->actions |= ACTION_GET_STR_DESC; + // Get the device's string descriptors next + device_obj->actions |= ACTION_GET_STR_DESC; } -static void action_get_str_desc(class_driver_t *driver_obj) +static void action_get_str_desc(usb_device_t *device_obj) { - assert(driver_obj->dev_hdl != NULL); + assert(device_obj->dev_hdl != NULL); usb_device_info_t dev_info; - ESP_ERROR_CHECK(usb_host_device_info(driver_obj->dev_hdl, &dev_info)); + ESP_ERROR_CHECK(usb_host_device_info(device_obj->dev_hdl, &dev_info)); if (dev_info.str_desc_manufacturer) { ESP_LOGI(TAG, "Getting Manufacturer string descriptor"); usb_print_string_descriptor(dev_info.str_desc_manufacturer); @@ -123,25 +157,59 @@ static void action_get_str_desc(class_driver_t *driver_obj) ESP_LOGI(TAG, "Getting Serial Number string descriptor"); usb_print_string_descriptor(dev_info.str_desc_serial_num); } - //Nothing to do until the device disconnects - driver_obj->actions &= ~ACTION_GET_STR_DESC; } -static void action_close_dev(class_driver_t *driver_obj) +static void action_close_dev(usb_device_t *device_obj) { - ESP_ERROR_CHECK(usb_host_device_close(driver_obj->client_hdl, driver_obj->dev_hdl)); - driver_obj->dev_hdl = NULL; - driver_obj->dev_addr = 0; - //We need to connect a new device - driver_obj->actions &= ~ACTION_CLOSE_DEV; - driver_obj->actions |= ACTION_RECONNECT; + ESP_ERROR_CHECK(usb_host_device_close(device_obj->client_hdl, device_obj->dev_hdl)); + device_obj->dev_hdl = NULL; + device_obj->dev_addr = 0; +} + +static void class_driver_device_handle(usb_device_t *device_obj) +{ + uint8_t actions = device_obj->actions; + device_obj->actions = 0; + + while (actions) { + if (actions & ACTION_OPEN_DEV) { + action_open_dev(device_obj); + } + if (actions & ACTION_GET_DEV_INFO) { + action_get_info(device_obj); + } + if (actions & ACTION_GET_DEV_DESC) { + action_get_dev_desc(device_obj); + } + if (actions & ACTION_GET_CONFIG_DESC) { + action_get_config_desc(device_obj); + } + if (actions & ACTION_GET_STR_DESC) { + action_get_str_desc(device_obj); + } + if (actions & ACTION_CLOSE_DEV) { + action_close_dev(device_obj); + } + + actions = device_obj->actions; + device_obj->actions = 0; + } } void class_driver_task(void *arg) { class_driver_t driver_obj = {0}; + usb_host_client_handle_t class_driver_client_hdl = NULL; ESP_LOGI(TAG, "Registering Client"); + + SemaphoreHandle_t mux_lock = xSemaphoreCreateMutex(); + if (mux_lock == NULL) { + ESP_LOGE(TAG, "Unable to create class driver mutex"); + vTaskSuspend(NULL); + return; + } + usb_host_client_config_t client_config = { .is_synchronous = false, //Synchronous clients currently not supported. Set this to false .max_num_event_msg = CLIENT_NUM_EVENT_MSG, @@ -150,52 +218,62 @@ void class_driver_task(void *arg) .callback_arg = (void *) &driver_obj, }, }; - ESP_ERROR_CHECK(usb_host_client_register(&client_config, &driver_obj.client_hdl)); + ESP_ERROR_CHECK(usb_host_client_register(&client_config, &class_driver_client_hdl)); + + driver_obj.constant.mux_lock = mux_lock; + driver_obj.constant.client_hdl = class_driver_client_hdl; + + for (uint8_t i = 0; i < DEV_MAX_COUNT; i++) { + driver_obj.mux_protected.device[i].client_hdl = class_driver_client_hdl; + } + s_driver_obj = &driver_obj; while (1) { - if (driver_obj.actions == 0) { - usb_host_client_handle_events(driver_obj.client_hdl, portMAX_DELAY); - } else { - if (driver_obj.actions & ACTION_OPEN_DEV) { - action_open_dev(&driver_obj); + // Driver has unhandled devices, handle all devices first + if (driver_obj.mux_protected.flags.unhandled_devices) { + xSemaphoreTake(driver_obj.constant.mux_lock, portMAX_DELAY); + for (uint8_t i = 0; i < DEV_MAX_COUNT; i++) { + if (driver_obj.mux_protected.device[i].actions) { + class_driver_device_handle(&driver_obj.mux_protected.device[i]); + } } - if (driver_obj.actions & ACTION_GET_DEV_INFO) { - action_get_info(&driver_obj); - } - if (driver_obj.actions & ACTION_GET_DEV_DESC) { - action_get_dev_desc(&driver_obj); - } - if (driver_obj.actions & ACTION_GET_CONFIG_DESC) { - action_get_config_desc(&driver_obj); - } - if (driver_obj.actions & ACTION_GET_STR_DESC) { - action_get_str_desc(&driver_obj); - } - if (driver_obj.actions & ACTION_CLOSE_DEV) { - action_close_dev(&driver_obj); - } - if (driver_obj.actions & ACTION_EXIT) { + driver_obj.mux_protected.flags.unhandled_devices = 0; + xSemaphoreGive(driver_obj.constant.mux_lock); + } else { + // Driver is active, handle client events + if (driver_obj.mux_protected.flags.shutdown == 0) { + usb_host_client_handle_events(class_driver_client_hdl, portMAX_DELAY); + } else { + // Shutdown the driver break; } - if (driver_obj.actions & ACTION_RECONNECT) { - driver_obj.actions = 0; - } } } - ESP_LOGI(TAG, "Deregistering Client"); - ESP_ERROR_CHECK(usb_host_client_deregister(driver_obj.client_hdl)); + ESP_LOGI(TAG, "Deregistering Class Client"); + ESP_ERROR_CHECK(usb_host_client_deregister(class_driver_client_hdl)); + if (mux_lock != NULL) { + vSemaphoreDelete(mux_lock); + } vTaskSuspend(NULL); } void class_driver_client_deregister(void) { - if (s_driver_obj->dev_hdl != NULL) { - s_driver_obj->actions = ACTION_CLOSE_DEV; + // Mark all opened devices + xSemaphoreTake(s_driver_obj->constant.mux_lock, portMAX_DELAY); + for (uint8_t i = 0; i < DEV_MAX_COUNT; i++) { + if (s_driver_obj->mux_protected.device[i].dev_hdl != NULL) { + // Mark device to close + s_driver_obj->mux_protected.device[i].actions |= ACTION_CLOSE_DEV; + // Set flag + s_driver_obj->mux_protected.flags.unhandled_devices = 1; + } } - s_driver_obj->actions |= ACTION_EXIT; + s_driver_obj->mux_protected.flags.shutdown = 1; + xSemaphoreGive(s_driver_obj->constant.mux_lock); // Unblock, exit the loop and proceed to deregister client - ESP_ERROR_CHECK(usb_host_client_unblock(s_driver_obj->client_hdl)); + ESP_ERROR_CHECK(usb_host_client_unblock(s_driver_obj->constant.client_hdl)); } diff --git a/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c b/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c index e6c2a8df92dd..f1a2dc348a53 100644 --- a/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c +++ b/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -120,26 +120,26 @@ static void usb_host_lib_task(void *arg) xTaskNotifyGive(arg); bool has_clients = true; - bool has_devices = true; - while (has_clients || has_devices) { + bool has_devices = false; + while (has_clients) { uint32_t event_flags; ESP_ERROR_CHECK(usb_host_lib_handle_events(portMAX_DELAY, &event_flags)); if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { - ESP_LOGI(TAG, "No more clients"); - has_clients = false; + ESP_LOGI(TAG, "Get FLAGS_NO_CLIENTS"); if (ESP_OK == usb_host_device_free_all()) { - ESP_LOGI(TAG, "All devices marked as free"); + ESP_LOGI(TAG, "All devices marked as free, no need to wait FLAGS_ALL_FREE event"); + has_clients = false; } else { - ESP_LOGI(TAG, "Wait for the ALL FREE EVENT"); + ESP_LOGI(TAG, "Wait for the FLAGS_ALL_FREE"); + has_devices = true; } } - if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { - ESP_LOGI(TAG, "No more devices"); - has_devices = false; + if (has_devices && event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { + ESP_LOGI(TAG, "Get FLAGS_ALL_FREE"); + has_clients = false; } - } - ESP_LOGI(TAG, "No more clients and devices"); + ESP_LOGI(TAG, "No more clients and devices, uninstall USB Host library"); //Uninstall the USB Host Library ESP_ERROR_CHECK(usb_host_uninstall()); @@ -167,7 +167,7 @@ void app_main(void) TaskHandle_t host_lib_task_hdl, class_driver_task_hdl; - //Create usb host lib task + // Create usb host lib task BaseType_t task_created; task_created = xTaskCreatePinnedToCore(usb_host_lib_task, "usb_host", @@ -178,19 +178,20 @@ void app_main(void) 0); assert(task_created == pdTRUE); - //Wait unit the USB host library is installed + // Wait unit the USB host library is installed ulTaskNotifyTake(false, 1000); - //Create class driver task + // Create class driver task task_created = xTaskCreatePinnedToCore(class_driver_task, "class", - 4096, + 5 * 1024, NULL, CLASS_TASK_PRIORITY, &class_driver_task_hdl, 0); assert(task_created == pdTRUE); - vTaskDelay(10); //Add a short delay to let the tasks run + // Add a short delay to let the tasks run + vTaskDelay(10); while (1) { if (xQueueReceive(app_event_queue, &evt_queue, portMAX_DELAY)) { @@ -198,22 +199,20 @@ void app_main(void) // User pressed button usb_host_lib_info_t lib_info; ESP_ERROR_CHECK(usb_host_lib_info(&lib_info)); - if (lib_info.num_devices == 0) { - // End while cycle - break; - } else { - ESP_LOGW(TAG, "To shutdown example, remove all USB devices and press button again."); - // Keep polling + if (lib_info.num_devices != 0) { + ESP_LOGW(TAG, "Shutdown with attached devices."); } + // End while cycle + break; } } } - //Deregister client + // Deregister client class_driver_client_deregister(); vTaskDelay(10); - //Delete the tasks + // Delete the tasks vTaskDelete(class_driver_task_hdl); vTaskDelete(host_lib_task_hdl); diff --git a/examples/peripherals/usb/host/usb_host_lib/sdkconfig.defaults b/examples/peripherals/usb/host/usb_host_lib/sdkconfig.defaults new file mode 100644 index 000000000000..bf1b553b2388 --- /dev/null +++ b/examples/peripherals/usb/host/usb_host_lib/sdkconfig.defaults @@ -0,0 +1,4 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_USB_HOST_HUBS_SUPPORTED=y diff --git a/examples/protocols/http_server/file_serving/pytest_http_server_file_serving.py b/examples/protocols/http_server/file_serving/pytest_http_server_file_serving.py index 66f1faa9db4a..ff0c0e8ef55d 100644 --- a/examples/protocols/http_server/file_serving/pytest_http_server_file_serving.py +++ b/examples/protocols/http_server/file_serving/pytest_http_server_file_serving.py @@ -31,11 +31,12 @@ def test_examples_protocol_http_server_file_serving(dut: Dut) -> None: binary_file = os.path.join(dut.app.binary_path, 'file_server.bin') bin_size = os.path.getsize(binary_file) logging.info('file_server_bin_size : {}KB'.format(bin_size // 1024)) - logging.info('Erasing the flash on the chip') + logging.info('Erasing the storage partition on the chip') + dut.serial.erase_partition('storage') # Upload binary and start testing logging.info('Starting http file serving simple test app') - dut.expect('Initializing SPIFFS', timeout=30) + dut.expect('Initializing SPIFFS', timeout=60) if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True: dut.expect('Please input ssid password:') diff --git a/examples/protocols/https_server/simple/pytest_https_server_simple.py b/examples/protocols/https_server/simple/pytest_https_server_simple.py index 86aa6a3f42f4..b86fafde337e 100644 --- a/examples/protocols/https_server/simple/pytest_https_server_simple.py +++ b/examples/protocols/https_server/simple/pytest_https_server_simple.py @@ -1,8 +1,7 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import http.client import logging import os @@ -149,22 +148,22 @@ def test_examples_protocol_https_server_simple(dut: Dut) -> None: logging.info('Response obtained does not match with correct response') raise RuntimeError('Failed to test SSL connection') - current_cipher = dut.expect(r'Current Ciphersuite(.*)', timeout=5)[0] - logging.info('Current Ciphersuite {}'.format(current_cipher)) - - # Close the connection - conn.close() + if dut.app.sdkconfig.get('CONFIG_EXAMPLE_ENABLE_HTTPS_USER_CALLBACK') is True: + current_cipher = dut.expect(r'Current Ciphersuite(.*)', timeout=5)[0] + logging.info('Current Ciphersuite {}'.format(current_cipher)) - logging.info('Checking user callback: Obtaining client certificate...') + logging.info('Checking user callback: Obtaining client certificate...') - serial_number = dut.expect(r'serial number\s*:([^\n]*)', timeout=5)[0] - issuer_name = dut.expect(r'issuer name\s*:([^\n]*)', timeout=5)[0] - expiry = dut.expect(r'expires on ((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() + serial_number = dut.expect(r'serial number\s*:([^\n]*)', timeout=5)[0] + issuer_name = dut.expect(r'issuer name\s*:([^\n]*)', timeout=5)[0] + expiry = dut.expect(r'expires on ((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() - logging.info('Serial No. {}'.format(serial_number)) - logging.info('Issuer Name {}'.format(issuer_name)) - logging.info('Expires on {}'.format(expiry)) + logging.info('Serial No. {}'.format(serial_number)) + logging.info('Issuer Name {}'.format(issuer_name)) + logging.info('Expires on {}'.format(expiry)) + # Close the connection + conn.close() logging.info('Correct response obtained') logging.info('SSL connection test successful\nClosing the connection') @@ -220,21 +219,21 @@ def test_examples_protocol_https_server_simple_dynamic_buffers(dut: Dut) -> None logging.info('Response obtained does not match with correct response') raise RuntimeError('Failed to test SSL connection') - current_cipher = dut.expect(r'Current Ciphersuite(.*)', timeout=5)[0] - logging.info('Current Ciphersuite {}'.format(current_cipher)) + if dut.app.sdkconfig.get('CONFIG_EXAMPLE_ENABLE_HTTPS_USER_CALLBACK') is True: + current_cipher = dut.expect(r'Current Ciphersuite(.*)', timeout=5)[0] + logging.info('Current Ciphersuite {}'.format(current_cipher)) - # Close the connection - conn.close() - - logging.info('Checking user callback: Obtaining client certificate...') + logging.info('Checking user callback: Obtaining client certificate...') - serial_number = dut.expect(r'serial number\s*:([^\n]*)', timeout=5)[0] - issuer_name = dut.expect(r'issuer name\s*:([^\n]*)', timeout=5)[0] - expiry = dut.expect(r'expires on\s*:((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() + serial_number = dut.expect(r'serial number\s*:([^\n]*)', timeout=5)[0] + issuer_name = dut.expect(r'issuer name\s*:([^\n]*)', timeout=5)[0] + expiry = dut.expect(r'expires on\s*:((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() - logging.info('Serial No. : {}'.format(serial_number)) - logging.info('Issuer Name : {}'.format(issuer_name)) - logging.info('Expires on : {}'.format(expiry)) + logging.info('Serial No. : {}'.format(serial_number)) + logging.info('Issuer Name : {}'.format(issuer_name)) + logging.info('Expires on : {}'.format(expiry)) + # Close the connection + conn.close() logging.info('Correct response obtained') logging.info('SSL connection test successful\nClosing the connection') diff --git a/examples/protocols/https_server/simple/sdkconfig.defaults b/examples/protocols/https_server/simple/sdkconfig.defaults index a9595bf0c1a2..02e8335f9caa 100644 --- a/examples/protocols/https_server/simple/sdkconfig.defaults +++ b/examples/protocols/https_server/simple/sdkconfig.defaults @@ -1 +1,2 @@ CONFIG_ESP_HTTPS_SERVER_ENABLE=y +CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 diff --git a/examples/protocols/https_server/wss_server/sdkconfig.defaults b/examples/protocols/https_server/wss_server/sdkconfig.defaults index 0a73bafe0cce..c4c0211210e8 100644 --- a/examples/protocols/https_server/wss_server/sdkconfig.defaults +++ b/examples/protocols/https_server/wss_server/sdkconfig.defaults @@ -1,2 +1,3 @@ CONFIG_ESP_HTTPS_SERVER_ENABLE=y +CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 CONFIG_HTTPD_WS_SUPPORT=y diff --git a/examples/protocols/https_x509_bundle/main/https_x509_bundle_example_main.c b/examples/protocols/https_x509_bundle/main/https_x509_bundle_example_main.c index 966aa8173e39..33e3040cf909 100644 --- a/examples/protocols/https_x509_bundle/main/https_x509_bundle_example_main.c +++ b/examples/protocols/https_x509_bundle/main/https_x509_bundle_example_main.c @@ -43,11 +43,24 @@ #include "esp_tls.h" #include "esp_crt_bundle.h" +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL +#define MAX_URLS 9 +#else #define MAX_URLS 2 +#endif static const char *web_urls[MAX_URLS] = { "https://www.howsmyssl.com/a/check", "https://espressif.com", +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL + "https://letsencrypt.org", + "https://www.identrust.com", + "https://www.globalsign.com", + "https://www.sectigo.com", + "https://www.digicert.com", + "https://www.godaddy.com", + "https://rainmaker.espressif.com", // Amazon +#endif }; static const char *TAG = "example"; diff --git a/examples/protocols/https_x509_bundle/pytest_https_x509_bundle.py b/examples/protocols/https_x509_bundle/pytest_https_x509_bundle.py index 12ef0d1f1d2f..ec3f115bd81a 100644 --- a/examples/protocols/https_x509_bundle/pytest_https_x509_bundle.py +++ b/examples/protocols/https_x509_bundle/pytest_https_x509_bundle.py @@ -1,10 +1,9 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os import pytest -from common_test_methods import get_env_config_variable from pytest_embedded import Dut @@ -21,17 +20,11 @@ def test_examples_protocol_https_x509_bundle(dut: Dut) -> None: binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin') bin_size = os.path.getsize(binary_file) logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024)) - # Connect to AP - if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True: - dut.expect('Please input ssid password:') - env_name = 'wifi_ap' - ap_ssid = get_env_config_variable(env_name, 'ap_ssid') - ap_password = get_env_config_variable(env_name, 'ap_password') - dut.write(f'{ap_ssid} {ap_password}') dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30) # start test num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode()) - dut.expect(r'Connection established to ([\s\S]*)', timeout=30) + for _ in range(num_URLS): + dut.expect(r'Connection established to ([\s\S]*)', timeout=30) dut.expect('Completed {} connections'.format(num_URLS), timeout=60) @@ -44,15 +37,25 @@ def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None: binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin') bin_size = os.path.getsize(binary_file) logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024)) - # Connect to AP - if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True: - dut.expect('Please input ssid password:') - env_name = 'wifi_ap' - ap_ssid = get_env_config_variable(env_name, 'ap_ssid') - ap_password = get_env_config_variable(env_name, 'ap_password') - dut.write(f'{ap_ssid} {ap_password}') dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30) # start test num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode()) dut.expect(r'Connection established to ([\s\S]*)', timeout=30) dut.expect('Completed {} connections'.format(num_URLS), timeout=60) + + +@pytest.mark.qemu +@pytest.mark.esp32 +@pytest.mark.host_test +@pytest.mark.parametrize('config', ['default_crt_bundle',], indirect=True) +def test_examples_protocol_https_x509_bundle_default_crt_bundle_stress_test(dut: Dut) -> None: + # check and log bin size + binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin') + bin_size = os.path.getsize(binary_file) + logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024)) + dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30) + # start test + num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode()) + for _ in range(num_URLS): + dut.expect(r'Connection established to ([\s\S]*)', timeout=30) + dut.expect('Completed {} connections'.format(num_URLS), timeout=60) diff --git a/examples/protocols/https_x509_bundle/sdkconfig.ci.default_crt_bundle b/examples/protocols/https_x509_bundle/sdkconfig.ci.default_crt_bundle new file mode 100644 index 000000000000..d0e1451c3e32 --- /dev/null +++ b/examples/protocols/https_x509_bundle/sdkconfig.ci.default_crt_bundle @@ -0,0 +1,8 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y + +# QEMU-Related configurations +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_USE_OPENETH=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_ETH_USE_SPI_ETHERNET=n diff --git a/examples/protocols/mqtt/custom_outbox/sdkconfig.ci.esp32c6 b/examples/protocols/mqtt/custom_outbox/sdkconfig.ci.esp32c6 new file mode 100644 index 000000000000..1686559de403 --- /dev/null +++ b/examples/protocols/mqtt/custom_outbox/sdkconfig.ci.esp32c6 @@ -0,0 +1 @@ +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/protocols/mqtt/tcp/README.md b/examples/protocols/mqtt/tcp/README.md index be639641e776..cb9f2cca07c1 100644 --- a/examples/protocols/mqtt/tcp/README.md +++ b/examples/protocols/mqtt/tcp/README.md @@ -64,7 +64,150 @@ DATA=data It is possible to use Wi-Fi connection on targets that do not support native Wi-Fi peripheral. This example demonstrates using `esp_wifi_remote` on ESP32P4 in the test configuration defined as `sdkconfig.ci.p4_wifi`. This configuration requires another ESP target with native Wi-Fi support physically connected to the ESP32-P4. -### Configure master-slave verification +This uses [esp_hosted](https://components.espressif.com/components/espressif/esp_hosted) project by default, please refer to its documentation for more details. +Note, that `esp_hosted` library currently transmits Wi-Fi credentials in plain text. In case this is a concern, please choose the `eppp` option in `esp_wifi_remote` configuration menu (`CONFIG_ESP_WIFI_REMOTE_LIBRARY_EPPP=y`) and setup master-slave verification (please see [eppp: Configure master-slave verification](#eppp)). + +### esp-hosted: Configure the slave project + +You first need to build and flash the slave project. It's possible to perform this action directly from the host project, these commands can be used to set the slave target device (for example ESP32C6), build and flash the slave project. You will have to hold the RST button to keep the host device (ESP32-P4) in reset while flashing the slave device. +``` +idf.py -C managed_components/espressif__esp_hosted/slave/ -B build_slave set-target esp32c6 +idf.py -C managed_components/espressif__esp_hosted/slave/ -B build_slave build flash monitor +``` + +### esp-hosted: Example Output of the slave device + +``` +I (348) cpu_start: Unicore app +I (357) cpu_start: Pro cpu start user code +I (357) cpu_start: cpu freq: 160000000 Hz +I (357) app_init: Application information: +I (360) app_init: Project name: network_adapter +I (365) app_init: App version: qa-test-full-master-esp32c5-202 +I (372) app_init: Compile time: Aug 30 2024 08:10:15 +I (378) app_init: ELF file SHA256: 6220fafe8... +I (383) app_init: ESP-IDF: v5.4-dev-2600-g1157a27964c-dirt +I (390) efuse_init: Min chip rev: v0.0 +I (395) efuse_init: Max chip rev: v0.99 +I (400) efuse_init: Chip rev: v0.1 +I (405) heap_init: Initializing. RAM available for dynamic allocation: +I (412) heap_init: At 4082FCD0 len 0004C940 (306 KiB): RAM +I (418) heap_init: At 4087C610 len 00002F54 (11 KiB): RAM +I (424) heap_init: At 50000000 len 00003FE8 (15 KiB): RTCRAM +I (432) spi_flash: detected chip: generic +I (435) spi_flash: flash io: dio +I (440) sleep_gpio: Configure to isolate all GPIO pins in sleep state +I (447) sleep_gpio: Enable automatic switching of GPIO sleep configuration +I (454) coexist: coex firmware version: 8da3f50af +I (481) coexist: coexist rom version 5b8dcfa +I (481) main_task: Started on CPU0 +I (481) main_task: Calling app_main() +I (482) fg_mcu_slave: ********************************************************************* +I (491) fg_mcu_slave: ESP-Hosted-MCU Slave FW version :: 0.0.6 +I (501) fg_mcu_slave: Transport used :: SDIO only +I (510) fg_mcu_slave: ********************************************************************* +I (519) fg_mcu_slave: Supported features are: +I (524) fg_mcu_slave: - WLAN over SDIO +I (528) h_bt: - BT/BLE +I (531) h_bt: - HCI Over SDIO +I (535) h_bt: - BLE only +I (539) fg_mcu_slave: capabilities: 0xd +I (543) fg_mcu_slave: Supported extended features are: +I (549) h_bt: - BT/BLE (extended) +I (553) fg_mcu_slave: extended capabilities: 0x0 +I (563) h_bt: ESP Bluetooth MAC addr: 40:4c:ca:5b:a0:8a +I (564) BLE_INIT: Using main XTAL as clock source +I (574) BLE_INIT: ble controller commit:[7491a85] +I (575) BLE_INIT: Bluetooth MAC: 40:4c:ca:5b:a0:8a +I (581) phy_init: phy_version 310,dde1ba9,Jun 4 2024,16:38:11 +I (641) phy: libbtbb version: 04952fd, Jun 4 2024, 16:38:26 +I (642) SDIO_SLAVE: Using SDIO interface +I (642) SDIO_SLAVE: sdio_init: sending mode: SDIO_SLAVE_SEND_STREAM +I (648) SDIO_SLAVE: sdio_init: ESP32-C6 SDIO RxQ[20] timing[0] + +I (1155) fg_mcu_slave: Start Data Path +I (1165) fg_mcu_slave: Initial set up done +I (1165) slave_ctrl: event ESPInit +``` + +### esp_hosted: Example Output of the master device (ESP32-P4) + +``` +I (1833) sdio_wrapper: Function 0 Blocksize: 512 +I (1843) sdio_wrapper: Function 1 Blocksize: 512 +I (1843) H_SDIO_DRV: SDIO Host operating in STREAMING MODE +I (1853) H_SDIO_DRV: generate slave intr +I (1863) transport: Received INIT event from ESP32 peripheral +I (1873) transport: EVENT: 12 +I (1873) transport: EVENT: 11 +I (1873) transport: capabilities: 0xd +I (1873) transport: Features supported are: +I (1883) transport: * WLAN +I (1883) transport: - HCI over SDIO +I (1893) transport: - BLE only +I (1893) transport: EVENT: 13 +I (1893) transport: ESP board type is : 13 + +I (1903) transport: Base transport is set-up + +I (1903) transport: Slave chip Id[12] +I (1913) hci_stub_drv: Host BT Support: Disabled +I (1913) H_SDIO_DRV: Received INIT event +I (1923) rpc_evt: EVENT: ESP INIT + +I (1923) rpc_wrap: Received Slave ESP Init +I (2703) rpc_core: <-- RPC_Req [0x116], uid 1 +I (2823) rpc_rsp: --> RPC_Resp [0x216], uid 1 +I (2823) rpc_core: <-- RPC_Req [0x139], uid 2 +I (2833) rpc_rsp: --> RPC_Resp [0x239], uid 2 +I (2833) rpc_core: <-- RPC_Req [0x104], uid 3 +I (2843) rpc_rsp: --> RPC_Resp [0x204], uid 3 +I (2843) rpc_core: <-- RPC_Req [0x118], uid 4 +I (2933) rpc_rsp: --> RPC_Resp [0x218], uid 4 +I (2933) example_connect: Connecting to Cermakowifi... +I (2933) rpc_core: <-- RPC_Req [0x11c], uid 5 +I (2943) rpc_evt: Event [0x2b] received +I (2943) rpc_evt: Event [0x2] received +I (2953) rpc_evt: EVT rcvd: Wi-Fi Start +I (2953) rpc_core: <-- RPC_Req [0x101], uid 6 +I (2973) rpc_rsp: --> RPC_Resp [0x21c], uid 5 +I (2973) H_API: esp_wifi_remote_connect +I (2973) rpc_core: <-- RPC_Req [0x11a], uid 7 +I (2983) rpc_rsp: --> RPC_Resp [0x201], uid 6 +I (3003) rpc_rsp: --> RPC_Resp [0x21a], uid 7 +I (3003) example_connect: Waiting for IP(s) +I (5723) rpc_evt: Event [0x2b] received +I (5943) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x400309fe +0x400309fe: wifi_sta_receive at /home/david/esp/idf/components/esp_wifi/src/wifi_netif.c:38 + +I (7573) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:424c:caff:fe5b:a088, type: ESP_IP6_ADDR_IS_LINK_LOCAL +I (9943) esp_netif_handlers: example_netif_sta ip: 192.168.0.29, mask: 255.255.255.0, gw: 192.168.0.1 +I (9943) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.0.29 +I (9943) example_common: Connected to example_netif_sta +I (9953) example_common: - IPv4 address: 192.168.0.29, +I (9963) example_common: - IPv6 address: fe80:0000:0000:0000:424c:caff:fe5b:a088, type: ESP_IP6_ADDR_IS_LINK_LOCAL +I (9973) mqtt_example: Other event id:7 +I (9973) main_task: Returned from app_main() +I (10253) mqtt_example: MQTT_EVENT_CONNECTED +I (10253) mqtt_example: sent publish successful, msg_id=45053 +I (10253) mqtt_example: sent subscribe successful, msg_id=34643 +I (10263) mqtt_example: sent subscribe successful, msg_id=2358 +I (10263) mqtt_example: sent unsubscribe successful, msg_id=57769 +I (10453) mqtt_example: MQTT_EVENT_PUBLISHED, msg_id=45053 +I (10603) mqtt_example: MQTT_EVENT_SUBSCRIBED, msg_id=34643 +I (10603) mqtt_example: sent publish successful, msg_id=0 +I (10603) mqtt_example: MQTT_EVENT_SUBSCRIBED, msg_id=2358 +I (10613) mqtt_example: sent publish successful, msg_id=0 +I (10613) mqtt_example: MQTT_EVENT_UNSUBSCRIBED, msg_id=57769 +I (10713) mqtt_example: MQTT_EVENT_DATA +TOPIC=/topic/qos0 +DATA=data +I (10863) mqtt_example: MQTT_EVENT_DATA +TOPIC=/topic/qos0 +DATA=data +``` + +### eppp: Configure master-slave verification In order to secure the physical connection between the ESP32-P4 (master) and the slave device, it is necessary to set certificates and keys for each side. To bootstrap this step, you can use one-time generated self-signed RSA keys and certificates running: @@ -72,7 +215,7 @@ To bootstrap this step, you can use one-time generated self-signed RSA keys and ./managed_components/espressif__esp_wifi_remote/examples/test_certs/generate_test_certs.sh espressif.local ``` -### Configure the slave project +#### eppp: Configure the slave project It is recommended to create a new project from `esp_wifi_remote` component's example with ``` @@ -91,7 +234,7 @@ Please follow these steps to setup the slave application: - `CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY` -- slave's private key * `idf.py build flash monitor` -### Configure the master project (ESP32-P4) +#### eppp: Configure the master project (ESP32-P4) similarly to the slave project, we have to configure * the physical connection @@ -105,7 +248,7 @@ After project configuration, you build and flash the board with idf.py build flash monitor ``` -### Example Output of the slave device +### eppp: Example Output of the slave device ``` I (7982) main_task: Returned from app_main() @@ -183,7 +326,7 @@ I (15682) rpc_server: Main DNS:185.162.24.55 I (15682) rpc_server: IP address:192.168.0.33 ``` -### Example Output of the master device (ESP32-P4) +### eppp: Example Output of the master device (ESP32-P4) ``` I (445) example_connect: Start example_connect. diff --git a/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_eppp b/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_eppp new file mode 100644 index 000000000000..8d423df47066 --- /dev/null +++ b/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_eppp @@ -0,0 +1,5 @@ +CONFIG_IDF_TARGET="esp32p4" +CONFIG_EXAMPLE_CONNECT_WIFI=y +CONFIG_ESP_WIFI_REMOTE_LIBRARY_EPPP=y +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=17 +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=16 diff --git a/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_wifi b/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_wifi index 7a5574c7f3aa..a2ea93a35971 100644 --- a/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_wifi +++ b/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_wifi @@ -1,4 +1,3 @@ CONFIG_IDF_TARGET="esp32p4" CONFIG_EXAMPLE_CONNECT_WIFI=y -CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=17 -CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=16 +CONFIG_ESP_WIFI_REMOTE_LIBRARY_HOSTED=y diff --git a/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild b/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild index be36720ad3c1..a0aa2888d07b 100644 --- a/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild +++ b/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild @@ -58,6 +58,13 @@ menu "Example Configuration" default 1 if EXAMPLE_PROV_TRANSPORT_BLE default 2 if EXAMPLE_PROV_TRANSPORT_SOFTAP + config EXAMPLE_PROV_ENABLE_APP_CALLBACK + bool "Enable provisioning manager app callback" + default n + help + This is for advanced use-cases like modifying Wi-Fi configuration parameters. This + executes a blocking app callback when any provisioning event is triggered. + config EXAMPLE_RESET_PROVISIONED bool default n @@ -71,13 +78,13 @@ menu "Example Configuration" default y prompt "Reset provisioned credentials and state machine after session failure" help - Enable reseting provisioned credentials and state machine after session failure. + Enable resetting provisioned credentials and state machine after session failure. This will restart the provisioning service after retries are exhausted. config EXAMPLE_PROV_MGR_MAX_RETRY_CNT int default 5 - prompt "Max retries before reseting provisioning state machine" + prompt "Max retries before resetting provisioning state machine" depends on EXAMPLE_RESET_PROV_MGR_ON_FAILURE help Set the Maximum retry to avoid reconnecting to an inexistent AP or if credentials diff --git a/examples/provisioning/wifi_prov_mgr/main/app_main.c b/examples/provisioning/wifi_prov_mgr/main/app_main.c index 233e450fea80..b1a7b76ab262 100644 --- a/examples/provisioning/wifi_prov_mgr/main/app_main.c +++ b/examples/provisioning/wifi_prov_mgr/main/app_main.c @@ -280,6 +280,34 @@ static void wifi_prov_print_qr(const char *name, const char *username, const cha ESP_LOGI(TAG, "If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", QRCODE_BASE_URL, payload); } +#ifdef CONFIG_EXAMPLE_PROV_ENABLE_APP_CALLBACK +void wifi_prov_app_callback(void *user_data, wifi_prov_cb_event_t event, void *event_data) +{ + /** + * This is blocking callback, any configurations that needs to be set when a particular + * provisioning event is triggered can be set here. + */ + switch (event) { + case WIFI_PROV_SET_STA_CONFIG: { + /** + * Wi-Fi configurations can be set here before the Wi-Fi is enabled in + * STA mode. + */ + wifi_config_t *wifi_config = (wifi_config_t*)event_data; + (void) wifi_config; + break; + } + default: + break; + } +} + +const wifi_prov_event_handler_t wifi_prov_event_handler = { + .event_cb = wifi_prov_app_callback, + .user_data = NULL, +}; +#endif /* EXAMPLE_PROV_ENABLE_APP_CALLBACK */ + void app_main(void) { /* Initialize NVS partition */ @@ -327,6 +355,9 @@ void app_main(void) #ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP .scheme = wifi_prov_scheme_softap, #endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */ +#ifdef CONFIG_EXAMPLE_PROV_ENABLE_APP_CALLBACK + .app_event_handler = wifi_prov_event_handler, +#endif /* EXAMPLE_PROV_ENABLE_APP_CALLBACK */ /* Any default scheme specific event handler that you would * like to choose. Since our example application requires diff --git a/examples/security/README.md b/examples/security/README.md new file mode 100644 index 000000000000..2d9f53a4c760 --- /dev/null +++ b/examples/security/README.md @@ -0,0 +1,39 @@ +# Security Examples + +## Security Features App + +This example demonstrates how to enable most of the security features on the ESP32 series SoC with the help of host-based tools such as (idf.py, esptool, espsecure). The example also supports the use of QEMU emulated ESP32-C3 for testing the security features without the need for physical hardware. +Note: Currently, this example is only supported on the ESP32-C3 SoC. +The example demonstrates the following security features: +* Secure Boot V2 +* Flash Encryption +* HMAC-based NVS Encryption +* Secure JTAG Return Material Access + +## Flash Encryption + +The Flash Encryption example for the ESP32 series SoC demonstrates how to enable and use flash encryption in Development and Release modes. +It includes: +* Checking the status of flash encryption and relevant eFuses. +* Writing to and reading from encrypted flash partitions. +* Initializing FATFS and NVS partitions, both encrypted and non-encrypted. +* Flashing the example in different modes, with guidance on handling encrypted data. + +## NVS Encryption - HMAC + +This example demonstrates how to use NVS (Non-Volatile Storage) encryption with an HMAC-based encryption key protection scheme on Espressif SoC chips. The encryption keys are derived from an HMAC key stored in eFuse, ensuring they are not stored in flash memory. This approach eliminates the need for a separate nvs_keys partition and does not require flash encryption to be enabled. +The steps include: +* Generating a secure HMAC key using the host tool. +* Burning the HMAC key into the eFuse. +* Enabling the HMAC-based NVS encryption scheme. +* Reading and writing to the encrypted NVS partition. + +## HMAC Soft JTAG + +The "JTAG Re-enable Example" demonstrates how to use the HMAC peripheral to securely re-enable a software-disabled JTAG interface after authentication on supported ESP32 Series SoCs. This is useful for implementing the Return Material Access (RMA) feature for a device. +The steps include: +* Generating a 32-byte HMAC key. +* Burning the key to an eFuse. +* Generating token data from the key. +* Using commands to re-enable JTAG access. + diff --git a/examples/security/security_features_app/README.md b/examples/security/security_features_app/README.md index 9272b81c2278..ea48a61b2565 100644 --- a/examples/security/security_features_app/README.md +++ b/examples/security/security_features_app/README.md @@ -1,25 +1,24 @@ | Supported Targets | ESP32-C3 | | ----------------- | -------- | +# Security Features Application -# All Secure - -This example demonstrates how to enable all of the available security features on the esp32c3 target at once. +This example demonstrates how to enable all of the available security features on the ESP32-C3 target at once. This example shall use combination of host based python tools and firmware for enabling all the related security eFuses. -For simplicity the security features such as Secure Boot V2, Flash Encryption, NVS Encryption shall be enabled through host based python tools (e.g., espefuse). +For simplicity, the security features such as Secure Boot V2, Flash Encryption, NVS Encryption shall be enabled through host based python tools (e.g., espefuse). Some additional security eFuses shall be enabled in the firmware. **The device that has followed all the steps mentioned below can be used for production use-cases.** > [!CAUTION] -> The instructions in the example directly burn eFuses and once done, it cannot be reverted. Please go through the below steps carefully before executing the example. All the steps must be followed without any changes and in the exact sequence, otherwise the device may end up in an unrecoverable state. +> The instructions in the example directly burn eFuses and once done, it cannot be reverted. Please go through the below steps carefully before executing the example. All the steps must be followed without any changes and in the exact sequence, otherwise the device may end up in an unrecoverable state. Follow the [QEMU workflow](#enable-security-features-with-help-of-qemu) if you want to test the example without the risk of bricking an actual device. ### Hardware Required -* A development board with ESP32C3 SoC +* A development board with ESP32-C3 SoC * A USB cable for power supply and programming -**Note: The hardware is not required if you plan to run the example with help of QEMU.** +**Note: The hardware is not required if you plan to run the example with help of [QEMU](#enable-security-features-with-help-of-qemu).** ## Pre-requisites @@ -32,7 +31,7 @@ export ESPPORT=/* Serial port to which esp is connected */
Setup serial port for QEMU - If you are enabling eFuses on esp32c3 emulated using QEMU then we shall set the serial port as follows: + If you are enabling eFuses on ESP32-C3 emulated using QEMU then we shall set the serial port as follows: export ESPPORT=socket://localhost:5555 @@ -40,19 +39,23 @@ export ESPPORT=/* Serial port to which esp is connected */
-**Please make sure to perform this step every time when you open a new terminal to use `esptool/espefuse` commands.** +**Make sure to perform this step every time when you open a new terminal to use `esptool/espefuse` commands.** ### 2. Erase flash We shall erase the flash on the device to ensure a clean state. -```idf.py -p $ESPPORT erase_flash``` +``` +idf.py -p $ESPPORT erase_flash +``` ### 3. Install esptool We shall require esptool utility which can be installed as follows: -```pip install esptool``` +``` +pip install esptool +``` ### 4. Installing qemu (optional) @@ -112,7 +115,8 @@ When the application is built (later in the workflow) the `bootloader` and `appl ``` espsecure.py sign_data --version 2 --keyfile /* Signing key placeholder */ --output bootloader-signed.bin build/bootloader/bootloader.bin - + ``` + ``` espsecure.py sign_data --version 2 --keyfile /* Signing key placeholder */ --output my-app-signed.bin build/security_features.bin ``` @@ -122,7 +126,7 @@ When the application is built (later in the workflow) the `bootloader` and `appl Details about the Flash Encryption protocol can be found at the [Flash Encryption documentation](https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/security/flash-encryption.html) The indicates the status of Flash Encryption feature for the chip. The example also demonstrates writing and reading encrypted partitions in flash. -Please follow below steps to enable Flash Encryption: +Follow below steps to enable Flash Encryption: 1. Generate Flash Encryption keys @@ -163,9 +167,11 @@ It can be done with following commands: ``` espsecure.py encrypt_flash_data --aes_xts --keyfile my_flash_encryption_key.bin --address 0x0 --output encrypted_data/bootloader-enc.bin build/bootloader/bootloader.bin - +``` +``` espsecure.py encrypt_flash_data --aes_xts --keyfile my_flash_encryption_key.bin --address 0xD000 --output encrypted_data/partition-table-enc.bin build/partition_table/partition-table.bin - +``` +``` espsecure.py encrypt_flash_data --aes_xts --keyfile my_flash_encryption_key.bin --address 0x20000 --output encrypted_data/security_features-enc.bin build/security_features_app.bin ``` @@ -200,7 +206,7 @@ We shall use the [nvs_partition_gen.py](../../../components/nvs_flash/nvs_partit Execute following command to generate the encrypted NVS partition. ``` - python3 nvs_partition_gen.py encrypt /* CSV placeholder */ nvs_encr_partition.bin /* NVS partition offset */ --inputkey keys/nvs_encr_key.bin + python3 $IDF_PATH/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py encrypt /* CSV placeholder */ nvs_encr_partition.bin /* NVS partition offset */ --inputkey keys/nvs_encr_key.bin ``` * `CSV placeholder`: CSV file which contains data of the NVS partition. See [CSV file format](https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/api-reference/storage/nvs_partition_gen.html#csv-file-format) for more details. * `NVS partition offset`: NVS partition offset. Can be found out by executing `idf.py partition-table` @@ -463,7 +469,7 @@ A hex file containing the eFuse configuration of ESP32C3 v0.3 (ECO3) has been ke This command shall start a serial connection with QEMU. Keep this running in one terminal and execute espefuse commands in an alternate terminal. - After espefuse commands are used to update the eFuses of the emulated esp the eFuse file generated in *Step 1* shall get ovwewritten. To revert to the original state, execute the command provided in *Step 1* once again. + After espefuse commands are used to update the eFuses of the emulated esp the eFuse file generated in *Step 1* shall get overwritten. To revert to the original state, execute the command provided in *Step 1* once again. 3. Execute the commands to enable security features diff --git a/examples/storage/.build-test-rules.yml b/examples/storage/.build-test-rules.yml index 4e7e8c66cbe3..66a4e3d1c6a3 100644 --- a/examples/storage/.build-test-rules.yml +++ b/examples/storage/.build-test-rules.yml @@ -19,29 +19,6 @@ examples/storage/emmc: - if: IDF_TARGET == "esp32s3" reason: only support on esp32s3 -examples/storage/ext_flash_fatfs: - depends_components: - - fatfs - - vfs - - spi_flash - - driver - disable: - - if: IDF_TARGET in ["esp32p4", "esp32c5", "esp32c61"] - temporary: true - reason: not supported on p4 and c5 # TODO: [ESP32C5] IDF-8715, [ESP32C61] IDF-9314 - disable_test: - - if: IDF_TARGET not in ["esp32"] - temporary: true - reason: lack of runners - -examples/storage/fatfsgen: - depends_components: - - fatfs - - vfs - disable_test: - - if: IDF_TARGET != "esp32" - reason: only one target needed - examples/storage/nvs_rw_blob: depends_components: - nvs_flash @@ -110,12 +87,9 @@ examples/storage/perf_benchmark: - wear_levelling - esp_partition - esp_driver_sdmmc - disable: - - if: IDF_TARGET in ["esp32c5", "esp32c61"] - temporary: true - reason: not supported yet # TODO: [ESP32C5] IDF-8704, IDF-10314, [ESP32C61] IDF-9314 disable_test: - if: IDF_TARGET == "esp32p4" and CONFIG_NAME in ["sdmmc_1line", "sdmmc_4line", "sdspi_1line"] + - if: IDF_TARGET in ["esp32c61"] temporary: true reason: lack of runners, build only # TODO: IDF-8970 diff --git a/examples/storage/README.md b/examples/storage/README.md index bb5c821fe89d..ebfb75833d59 100644 --- a/examples/storage/README.md +++ b/examples/storage/README.md @@ -7,10 +7,11 @@ This directory contains a range of examples ESP-IDF projects. These are intended The examples are grouped into sub-directories by category. Each category directory contains one or more example projects: +* `fatfs_basic` minimal example of FatFS usage on SPI FLASH +* `fatfs_advanced` example demonstrates how to use advanced features for working with FatFS such as automatic partition generation * `custom_flash_driver` example demonstrates how to implement your own flash chip driver by overriding the default driver. * `emmc` example demonstrates how to use an eMMC chip with an ESP device. * `ext_flash_fatfs` example demonstrates how to use FATFS partition with external SPI FLASH chip. -* `fatfsgen` example demonstrates how to use FATFS partition * `nvs_rw_blob` example demonstrates how to read and write a single integer value and a blob (binary large object) using NVS to preserve them between ESP module restarts. * `nvs_rw_value` example demonstrates how to read and write a single integer value using NVS. * `nvs_rw_value_cxx` example demonstrates how to read and write a single integer value using NVS (it uses the C++ NVS handle API). diff --git a/examples/storage/ext_flash_fatfs/main/CMakeLists.txt b/examples/storage/ext_flash_fatfs/main/CMakeLists.txt deleted file mode 100644 index c8a5c30e46be..000000000000 --- a/examples/storage/ext_flash_fatfs/main/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -idf_component_register(SRCS "ext_flash_fatfs_example_main.c") diff --git a/examples/storage/fatfs/.build-test-rules.yml b/examples/storage/fatfs/.build-test-rules.yml new file mode 100644 index 000000000000..4f3ae3aa16a7 --- /dev/null +++ b/examples/storage/fatfs/.build-test-rules.yml @@ -0,0 +1,24 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +examples/storage/fatfs: + depends_components: + - fatfs + - vfs + disable_test: + - if: IDF_TARGET != "esp32" + reason: only one target needed + +examples/storage/fatfs/ext_flash: + depends_components: + - fatfs + - vfs + - spi_flash + - driver + disable: + - if: IDF_TARGET in ["esp32p4", "esp32c5", "esp32c61"] + temporary: true + reason: not supported on p4 and c5 # TODO: [ESP32C5] IDF-8715, [ESP32C61] IDF-9314 + disable_test: + - if: IDF_TARGET not in ["esp32"] + temporary: true + reason: lack of runners diff --git a/examples/storage/ext_flash_fatfs/CMakeLists.txt b/examples/storage/fatfs/ext_flash/CMakeLists.txt similarity index 91% rename from examples/storage/ext_flash_fatfs/CMakeLists.txt rename to examples/storage/fatfs/ext_flash/CMakeLists.txt index 93841c0e29c3..66233663cd75 100644 --- a/examples/storage/ext_flash_fatfs/CMakeLists.txt +++ b/examples/storage/fatfs/ext_flash/CMakeLists.txt @@ -4,4 +4,4 @@ cmake_minimum_required(VERSION 3.16) # external SPI flash driver not currently supported for ESP32-S2 include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(ext_flash_fatfs) +project(fatfs_ext_flash) diff --git a/examples/storage/ext_flash_fatfs/README.md b/examples/storage/fatfs/ext_flash/README.md similarity index 94% rename from examples/storage/ext_flash_fatfs/README.md rename to examples/storage/fatfs/ext_flash/README.md index 0014bd8d3146..349fd1ba3ee3 100644 --- a/examples/storage/ext_flash_fatfs/README.md +++ b/examples/storage/fatfs/ext_flash/README.md @@ -5,7 +5,7 @@ (See the README.md file in the upper level 'examples' directory for more information about examples.) -This example is similar to the [wear levelling](../wear_levelling/README.md) example, except that it uses an external SPI Flash chip. This can be useful if you need to add more storage to a module with only 4 MB flash size. +This example is similar to the [wear levelling](../../wear_levelling/README.md) example, except that it uses an external SPI Flash chip. This can be useful if you need to add more storage to a module with only 4 MB flash size. The flow of the example is as follows: diff --git a/examples/storage/fatfs/ext_flash/main/CMakeLists.txt b/examples/storage/fatfs/ext_flash/main/CMakeLists.txt new file mode 100644 index 000000000000..dea52d1cb4a5 --- /dev/null +++ b/examples/storage/fatfs/ext_flash/main/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "fatfs_ext_flash_example_main.c") diff --git a/examples/storage/ext_flash_fatfs/main/ext_flash_fatfs_example_main.c b/examples/storage/fatfs/ext_flash/main/fatfs_ext_flash_example_main.c similarity index 98% rename from examples/storage/ext_flash_fatfs/main/ext_flash_fatfs_example_main.c rename to examples/storage/fatfs/ext_flash/main/fatfs_ext_flash_example_main.c index aa2a2c0990b9..4e10057d10f0 100644 --- a/examples/storage/ext_flash_fatfs/main/ext_flash_fatfs_example_main.c +++ b/examples/storage/fatfs/ext_flash/main/fatfs_ext_flash_example_main.c @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ /* Example of FAT filesystem on external Flash. This example code is in the Public Domain (or CC0 licensed, at your option.) diff --git a/examples/storage/ext_flash_fatfs/pytest_ext_flash_fatfs.py b/examples/storage/fatfs/ext_flash/pytest_fatfs_ext_flash.py similarity index 99% rename from examples/storage/ext_flash_fatfs/pytest_ext_flash_fatfs.py rename to examples/storage/fatfs/ext_flash/pytest_fatfs_ext_flash.py index afe81763a3ab..56dd334a49aa 100644 --- a/examples/storage/ext_flash_fatfs/pytest_ext_flash_fatfs.py +++ b/examples/storage/fatfs/ext_flash/pytest_fatfs_ext_flash.py @@ -1,7 +1,5 @@ # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 - - import pytest from pytest_embedded import Dut diff --git a/examples/storage/fatfs/fatfsgen/CMakeLists.txt b/examples/storage/fatfs/fatfsgen/CMakeLists.txt new file mode 100644 index 000000000000..0399bf40c59a --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(fatfs_fatfsgen) diff --git a/examples/storage/fatfs/fatfsgen/README.md b/examples/storage/fatfs/fatfsgen/README.md new file mode 100644 index 000000000000..772cf9cd8e80 --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/README.md @@ -0,0 +1,69 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | + +# FATFS partition generation example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates how to use the FATFS partition +generation tool [fatfsgen.py](../../../../components/fatfs/fatfsgen.py) to automatically create a FATFS +filesystem image from the contents of a host folder during build, with an option of +automatically flashing the created image on invocation of `idf.py -p PORT flash`. +Beware that the minimal required size of the flash is 4 MB. +You can specify using menuconfig weather example will use read-only or read-write mode. The default option is read-write mode. +To change it just use menuconfig: + +```shell +idf.py menuconfig +``` + +Then select `Example Configuration` a chose `Mode for generated FATFS image` either `Read-Write Mode` or `Read-Only Mode`. +`Read-Only` option indicates generating raw fatfs image without wear levelling support. +On the other hand, for `Read-Write` the generated fatfs image will support wear levelling thus can be mounted in read-write mode. + + +The following gives an overview of the example: + +1. There is a directory `fatfs_long_name_image` from which the FATFS filesystem image will be created. + +2. Based on the RO/RW configuration either `fatfs_create_rawflash_image` or `fatfs_create_spiflash_image` respectively, +is used to specify that a FATFS image should be created during build for the `storage` partition. +For CMake, it is called from [the main component's CMakeLists.txt](./main/CMakeLists.txt). +`FLASH_IN_PROJECT` specifies that the created image +should be flashed on invocation of `idf.py -p PORT flash` together with app, bootloader, partition table, etc. +The image is created on the example's build directory with the output filename `storage.bin`. + +3. Upon invocation of `idf.py -p PORT flash monitor`, application loads and +finds there is already a valid FATFS filesystem in the `storage` partition with files same as those in `fatfs_image` directory. The application is then +able to read those files. + +## How to use example + +### Build and flash + +To run the example, type the following command: + +```CMake +# CMake +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example output + +Here is the example's console output: + +``` +... +I (322) example: Mounting FAT filesystem +I (332) example: Reading file +I (332) example: Read from file: 'this is test' +I (332) example: Unmounting FAT filesystem +I (342) example: Done +``` + +The logic of the example is contained in a [single source file](./main/fatfsgen_example_main.c), +and it should be relatively simple to match points in its execution with the log outputs above. diff --git a/examples/storage/fatfsgen/fatfs_long_name_image/hellolongname.txt b/examples/storage/fatfs/fatfsgen/fatfs_image/hellolongname.txt similarity index 100% rename from examples/storage/fatfsgen/fatfs_long_name_image/hellolongname.txt rename to examples/storage/fatfs/fatfsgen/fatfs_image/hellolongname.txt diff --git a/examples/storage/fatfsgen/fatfs_long_name_image/sublongnames/testlongfilenames.txt b/examples/storage/fatfs/fatfsgen/fatfs_image/subdir/testlongfilenames.txt similarity index 100% rename from examples/storage/fatfsgen/fatfs_long_name_image/sublongnames/testlongfilenames.txt rename to examples/storage/fatfs/fatfsgen/fatfs_image/subdir/testlongfilenames.txt diff --git a/examples/storage/fatfs/fatfsgen/main/CMakeLists.txt b/examples/storage/fatfs/fatfsgen/main/CMakeLists.txt new file mode 100644 index 000000000000..1b625a37226d --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/main/CMakeLists.txt @@ -0,0 +1,18 @@ +idf_component_register(SRCS "fatfsgen_example_main.c" + INCLUDE_DIRS ".") + +# Create a FATFS image from the contents of the 'fatfs_long_name_image' directory +# that fits the partition named 'storage'. FLASH_IN_PROJECT indicates that +# the generated image should be flashed when the entire project is flashed to +# the target with 'idf.py -p PORT flash'. +# If read-only mode is set (CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY) +# the generated image will be raw without wear levelling support. +# Otherwise it will support wear levelling and thus enable read-write mounting of the image in the device. + +set(image ../fatfs_image) + +if(CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY) + fatfs_create_rawflash_image(storage ${image} FLASH_IN_PROJECT PRESERVE_TIME) +else() + fatfs_create_spiflash_image(storage ${image} FLASH_IN_PROJECT PRESERVE_TIME) +endif() diff --git a/examples/storage/fatfs/fatfsgen/main/Kconfig.projbuild b/examples/storage/fatfs/fatfsgen/main/Kconfig.projbuild new file mode 100644 index 000000000000..ef79d394562b --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/main/Kconfig.projbuild @@ -0,0 +1,10 @@ +menu "Example Configuration" + + config EXAMPLE_FATFS_MODE_READ_ONLY + bool "Read only mode for generated FATFS image" + default y + help + If read-only mode is set, the generated fatfs image will be raw (without wear levelling support). + Otherwise it will support wear levelling that enables read-write mounting. + +endmenu diff --git a/examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c b/examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c new file mode 100644 index 000000000000..abc01a900a89 --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c @@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "esp_err.h" +#include "sdkconfig.h" + +static const char *TAG = "example"; + +// Mount path for the partition +const char *base_path = "/spiflash"; + + +void app_main(void) +{ + // To mount device we need name of device partition, define base_path + // and allow format partition in case if it is new one and was not formatted before + const esp_vfs_fat_mount_config_t mount_config = { + .max_files = 4, + .format_if_mount_failed = false, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, + .use_one_fat = false, + }; + +#if CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY + ESP_LOGI(TAG, "Mounting FAT filesystem in read-only mode"); + esp_err_t err = esp_vfs_fat_spiflash_mount_ro(base_path, "storage", &mount_config); +#else + ESP_LOGI(TAG, "Mounting FAT filesystem in read/write mode"); + static wl_handle_t wl_handle = WL_INVALID_HANDLE; + esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, "storage", &mount_config, &wl_handle); +#endif + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err)); + return; + } + + char line[128]; + + FILE *f; + char *pos; + ESP_LOGI(TAG, "Reading file"); + + const char *host_filename1 = "/spiflash/subdir/testlongfilenames.txt"; + + struct stat info; + struct tm timeinfo; + char buffer[32]; + + if(stat(host_filename1, &info) < 0){ + ESP_LOGE(TAG, "Failed to read file stats"); + return; + } + localtime_r(&info.st_mtime, &timeinfo); + strftime(buffer, sizeof(buffer), "%Y-%m-%d", &timeinfo); + + ESP_LOGI(TAG, "The file '%s' was modified at date: %s", host_filename1, buffer); + + + f = fopen(host_filename1, "rb"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed to open file for reading"); + return; + } + fgets(line, sizeof(line), f); + fclose(f); + // strip newline + pos = strchr(line, '\n'); + if (pos) { + *pos = '\0'; + } + ESP_LOGI(TAG, "Read from file: '%s'", line); + + // Unmount FATFS + ESP_LOGI(TAG, "Unmounting FAT filesystem"); + +#if CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY + ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_ro(base_path, "storage")); +#else + ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_rw_wl(base_path, wl_handle)); +#endif + + ESP_LOGI(TAG, "Done"); +} diff --git a/examples/storage/fatfs/fatfsgen/partitions_example.csv b/examples/storage/fatfs/fatfsgen/partitions_example.csv new file mode 100644 index 000000000000..a3fee302e29b --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/partitions_example.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, diff --git a/examples/storage/fatfs/fatfsgen/pytest_fatfs_fatfsgen_example.py b/examples/storage/fatfs/fatfsgen/pytest_fatfs_fatfsgen_example.py new file mode 100644 index 000000000000..e0966604ebeb --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/pytest_fatfs_fatfsgen_example.py @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import os +import re +from datetime import datetime +from typing import List + +import pytest +from pytest_embedded import Dut + +idf_path = os.environ['IDF_PATH'] # get value of IDF_PATH from environment +parttool_dir = os.path.join(idf_path, 'components', 'partition_table') + + +@pytest.mark.esp32 +@pytest.mark.generic +@pytest.mark.parametrize('config', ['test_read_only_partition_gen_ln', + 'test_read_write_partition_gen_ln', + ], indirect=True) +def test_examples_fatfs_fatfsgen(config: str, dut: Dut) -> None: + # Expects list of strings sequentially + def expect_all(msg_list: List[str], to: int) -> None: + for msg in msg_list: + dut.expect(msg, timeout=to) + + # Expects prefix string followed by date in the format 'yyyy-mm-dd' + def expect_date(prefix: str, to: int) -> datetime: + expect_str = prefix + '(\\d+)-(\\d+)-(\\d+)' + match_ = dut.expect(re.compile(str.encode(expect_str)), timeout=to) + year_ = int(match_[1].decode()) + month_ = int(match_[2].decode()) + day_ = int(match_[3].decode()) + return datetime(year_, month_, day_) + + # Calculates absolute difference in days between date_reference and date_actual. + # Raises exception if difference exceeds tolerance + def evaluate_dates(date_reference: datetime, date_actual: datetime, days_tolerance: int) -> None: + td = date_actual - date_reference + if abs(td.days) > days_tolerance: + raise Exception(f'Too big date difference. Actual: {date_actual}, reference: {date_reference}, tolerance: {days_tolerance} day(s)') + + # Expect timeout + timeout = 20 + + # We tolerate 30 days difference between actual file creation and date when test was executed. + tolerance = 30 + filename = 'sublongnames/testlongfilenames.txt' + date_ref = datetime.today() + + if config in ['test_read_write_partition_gen']: + filename_expected = f'/spiflash/{filename}' + expect_all(['example: Mounting FAT filesystem', + 'example: Opening file', + 'example: File written', + 'example: Reading file', + 'example: Read from file: \'This is written by the device\'', + 'example: Reading file'], timeout) + date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout) + evaluate_dates(date_ref, date_act, tolerance) + expect_all(['example: Read from file: \'This is generated on the host\'', + 'example: Unmounting FAT filesystem', + 'example: Done'], timeout) + + elif config in ['test_read_only_partition_gen']: + filename_expected = f'/spiflash/{filename}' + expect_all(['example: Mounting FAT filesystem', + 'example: Reading file'], timeout) + date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout) + evaluate_dates(date_ref, date_act, tolerance) + expect_all(['example: Read from file: \'this is test\'', + 'example: Unmounting FAT filesystem', + 'example: Done'], timeout) diff --git a/examples/storage/fatfs/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln b/examples/storage/fatfs/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln new file mode 100644 index 000000000000..5122126dcbc5 --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY=y +CONFIG_FATFS_LFN_HEAP=y +CONFIG_FATFS_LFN_NONE=n +CONFIG_FATFS_LFN_STACK=n diff --git a/examples/storage/fatfs/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln b/examples/storage/fatfs/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln new file mode 100644 index 000000000000..33a0ccfad3d4 --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY=n +CONFIG_FATFS_LFN_HEAP=y +CONFIG_FATFS_LFN_NONE=n +CONFIG_FATFS_LFN_STACK=n diff --git a/examples/storage/fatfs/fatfsgen/sdkconfig.defaults b/examples/storage/fatfs/fatfsgen/sdkconfig.defaults new file mode 100644 index 000000000000..7dd3c63608f0 --- /dev/null +++ b/examples/storage/fatfs/fatfsgen/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" +CONFIG_FATFS_LFN_HEAP=y diff --git a/examples/storage/fatfs/fs_operations/CMakeLists.txt b/examples/storage/fatfs/fs_operations/CMakeLists.txt new file mode 100644 index 000000000000..2f478de10ddd --- /dev/null +++ b/examples/storage/fatfs/fs_operations/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(fatfs_fs_operations) diff --git a/examples/storage/fatfs/fs_operations/README.md b/examples/storage/fatfs/fs_operations/README.md new file mode 100644 index 000000000000..e11f3077b502 --- /dev/null +++ b/examples/storage/fatfs/fs_operations/README.md @@ -0,0 +1,94 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | + +# FATFS Filesystem Operations Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates some of the POSIX functions available for working with the FATFS filesystem. +Including basic read and write operations, as well as creating moving, and deleting files and directories. + +## Overview + +1. Partition labeled `storage` is mounted (and formatted if necessary) as FATFS filesystem to `/spiflash` mountpoint. + +2. All existing files and directories in the root directory are deleted. + +3. File `hello.txt` is created and written to. + +4. File `hello.txt` is inspected using `fstat` function showing file size and last modification time. + +5. File `hello.txt` is written to again, appending to the end of the file. + +6. File `hello.txt` is read from and the contents are printed to the console. + +7. New directory `new_dir` is created. + +8. All files and directories in the root directory are listed. + +9. File `hello.txt` is moved and renamed to `new_dir/hello_renamed.txt`. + +## How to use example + +### Build and flash + +To run the example, type the following command: + +```CMake +# CMake +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example output + +Here is the example's console output: + +``` +... +I (323) example: Mounting FAT filesystem +I (333) example: Deleting everything in /spiflash: +I (333) example: Deleting everything in /spiflash/new_dir: +I (673) example: Creating a file +I (683) example: Writing to the file +I (733) example: File stats: + File size: 13 bytes + File modification time: Thu Jan 1 00:00:00 1970 + +I (743) example: Wait for 1 seconds +I (1743) example: Write more to the file +I (1743) example: File stats: + File size: 26 bytes + File modification time: Thu Jan 1 00:00:00 1970 + +I (1743) example: Go to the beginning of the file +I (1753) example: Reading from file: +Hello World! +Hello World! + +I (1753) example: Closing file +I (1993) example: Listing files in /spiflash: +/spiflash: + file : hello.txt +I (1993) example: Creating a new directory +I (2383) example: Listing files in /spiflash: +/spiflash: + file : hello.txt + directory: new_dir +I (2383) example: Rename a file +I (2503) example: Listing files in /spiflash: +/spiflash: + directory: new_dir +I (2503) example: Listing files in /spiflash/new_dir: +/spiflash/new_dir: + file : hello_renamed.txt +I (2513) example: Unmounting FAT filesystem +I (2643) example: Done +... +``` + +The logic of the example is contained in a [single source file](./main/fatfs_fs_operations_example_main.c), +and it should be relatively simple to match points in its execution with the log outputs above. diff --git a/examples/storage/fatfs/fs_operations/main/CMakeLists.txt b/examples/storage/fatfs/fs_operations/main/CMakeLists.txt new file mode 100644 index 000000000000..a5ae965fc4cd --- /dev/null +++ b/examples/storage/fatfs/fs_operations/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "fatfs_fs_operations_example_main.c" + INCLUDE_DIRS ".") diff --git a/examples/storage/fatfs/fs_operations/main/fatfs_fs_operations_example_main.c b/examples/storage/fatfs/fs_operations/main/fatfs_fs_operations_example_main.c new file mode 100644 index 000000000000..c2dd5bc226a9 --- /dev/null +++ b/examples/storage/fatfs/fs_operations/main/fatfs_fs_operations_example_main.c @@ -0,0 +1,207 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "sdkconfig.h" + +static const char *TAG = "example"; + +// Mount path for the partition +static const char *base_path = "/spiflash"; + +// File name +static const char *filename = "/spiflash/hello.txt"; + +// Function to dump contents of a directory +static void list_dir(const char *path); + +// Best effort recursive function to clean a directory +static void clean_dir(const char *path); + +void app_main(void) +{ + ESP_LOGI(TAG, "Mounting FAT filesystem"); + + // To mount device we need name of device partition, define base_path + // and allow format partition in case if it is new one and was not formatted before + const esp_vfs_fat_mount_config_t mount_config = { + .max_files = 4, + .format_if_mount_failed = true, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, + .use_one_fat = false, + }; + + wl_handle_t wl_handle = WL_INVALID_HANDLE; + + esp_err_t err = ESP_OK; + + err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, "storage", &mount_config, &wl_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err)); + return; + } + + // Ensure the working directory is empty + clean_dir(base_path); + + ESP_LOGI(TAG, "Creating a file"); + + // Unlike C standard library which uses FILE*, POSIX API uses file descriptors for file operations + int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0); + if (fd < 0) { + ESP_LOGE(TAG, "Failed to open file for writing"); + return; + } + + ESP_LOGI(TAG, "Writing to the file"); + const char *text = "Hello World!\n"; + write(fd, text, strlen(text)); + + struct stat info; + // We have to use `stat` instead of `fstat`, because `fstat` currently isn't fully supported + if (stat(filename, &info) < 0) { + ESP_LOGE(TAG, "Failed to stat file: %s", strerror(errno)); + close(fd); + return; + } + + ESP_LOGI( + TAG, + "File stats:\n" + "\tFile size: %ld bytes\n" + "\tFile modification time: %s", + info.st_size, + ctime(&info.st_mtime) + ); + + ESP_LOGI(TAG, "Wait for 3 seconds"); + sleep(3); + + ESP_LOGI(TAG, "Write more to the file"); + write(fd, text, strlen(text)); + + ESP_LOGI(TAG, "Force cached data and metadata to the filesystem"); + fsync(fd); + + if (stat(filename, &info) < 0) { + ESP_LOGE(TAG, "Failed to stat file: %s", strerror(errno)); + close(fd); + return; + } + + ESP_LOGI( + TAG, + "File stats:\n" + "\tFile size: %ld bytes\n" + "\tFile modification time: %s", + info.st_size, + ctime(&info.st_mtime) + ); + + ESP_LOGI(TAG, "Go to the beginning of the file"); + lseek(fd, 0, SEEK_SET); + + ESP_LOGI(TAG, "Reading from file:"); + + char buf[128] = {0}; + + ssize_t len = read(fd, buf, sizeof(buf) - 1); + if (len < 0) { + ESP_LOGE(TAG, "Failed to read file: %s", strerror(errno)); + close(fd); + return; + } + + printf("%.*s\n", len, buf); + + ESP_LOGI(TAG, "Closing file"); + close(fd); + + // List files in the directory + list_dir(base_path); + + ESP_LOGI(TAG, "Creating a new directory"); + if (mkdir("/spiflash/new_dir", 0777) < 0) { + ESP_LOGE(TAG, "Failed to create a new directory: %s", strerror(errno)); + return; + } + + // List files in the directory + list_dir(base_path); + + ESP_LOGI(TAG, "Rename a file"); + + if (rename(filename, "/spiflash/new_dir/hello_renamed.txt") < 0) { + ESP_LOGE(TAG, "Failed to rename file: %s", strerror(errno)); + return; + } + + // List files in the directory + list_dir(base_path); + list_dir("/spiflash/new_dir"); + + ESP_LOGI(TAG, "Unmounting FAT filesystem"); + ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_rw_wl(base_path, wl_handle)); + + ESP_LOGI(TAG, "Done"); +} + +void list_dir(const char *path) +{ + ESP_LOGI(TAG, "Listing files in %s:", path); + + DIR *dir = opendir(path); + if (!dir) { + ESP_LOGE(TAG, "Failed to open directory: %s", strerror(errno)); + return; + } + + printf("%s:\n", path); + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + printf( + " %s: %s\n", + (entry->d_type == DT_DIR) + ? "directory" + : "file ", + entry->d_name + ); + } + + closedir(dir); +} + +void clean_dir(const char *path) +{ + ESP_LOGI(TAG, "Deleting everything in %s:", path); + + DIR *dir = opendir(path); + if (!dir) { + ESP_LOGE(TAG, "Failed to open directory: %s", strerror(errno)); + return; + } + + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + char full_path[64] = {0}; + snprintf(full_path, sizeof(full_path), "%.20s/%.40s", path, entry->d_name); + if (entry->d_type == DT_DIR) + clean_dir(full_path); + if (remove(full_path) != 0) { + ESP_LOGE(TAG, "Failed to remove %s: %s", full_path, strerror(errno)); + } + } + + closedir(dir); +} diff --git a/examples/storage/fatfsgen/partitions_example.csv b/examples/storage/fatfs/fs_operations/partitions_example.csv similarity index 100% rename from examples/storage/fatfsgen/partitions_example.csv rename to examples/storage/fatfs/fs_operations/partitions_example.csv diff --git a/examples/storage/fatfs/fs_operations/pytest_fatfs_fs_operations_example.py b/examples/storage/fatfs/fs_operations/pytest_fatfs_fs_operations_example.py new file mode 100644 index 000000000000..4067c80d134c --- /dev/null +++ b/examples/storage/fatfs/fs_operations/pytest_fatfs_fs_operations_example.py @@ -0,0 +1,80 @@ +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +from datetime import datetime +from typing import List + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32 +@pytest.mark.generic +def test_examples_fatfs_fs_operations(config: str, dut: Dut) -> None: + # Expects list of strings sequentially + def expect_all(msg_list: List[str], to: int) -> None: + for msg in msg_list: + dut.expect(msg, timeout=to) + + def parse_date() -> datetime: + months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + + pattern = r'([A-Z][a-z]{2}) ([A-Z][a-z]{2}) ([ \d]\d) (\d{2}):(\d{2}):(\d{2}) (\d{4})' + + match = dut.expect(pattern) + return datetime( + month=months.index(match[2].decode('utf-8')) + 1, + day=int(match[3]), + hour=int(match[4]), + minute=int(match[5]), + second=int(match[6]), + year=int(match[7]), + ) + + expect_all( + [ + 'example: Mounting FAT filesystem', + 'example: Creating a file', + 'example: Writing to the file', + 'example: File stats:', + 'File size:', + ], + 5 + ) + + original = parse_date() + + expect_all( + [ + 'example: Wait for 3 seconds', + 'example: Write more to the file', + 'example: Force cached data and metadata to the filesystem', + 'File size:', + ], + 5 + ) + + updated = parse_date() + + assert updated > original + + expect_all( + [ + 'example: Go to the beginning of the file', + 'example: Reading from file', + 'Hello World!', + 'Hello World!', + 'example: Closing file', + 'example: Listing files in /spiflash:', + 'hello.txt', + 'example: Creating a new directory', + 'example: Listing files in /spiflash:', + 'hello.txt', + 'new_dir', + 'example: Rename a file', + 'example: Listing files in /spiflash:', + 'new_dir', + 'example: Listing files in /spiflash/new_dir:', + 'hello_renamed.txt', + ], + 5 + ) diff --git a/examples/storage/fatfs/fs_operations/sdkconfig.defaults b/examples/storage/fatfs/fs_operations/sdkconfig.defaults new file mode 100644 index 000000000000..e5ac9375337f --- /dev/null +++ b/examples/storage/fatfs/fs_operations/sdkconfig.defaults @@ -0,0 +1,7 @@ +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_FATFS_LFN_HEAP=y +CONFIG_FATFS_LFN_NONE=n +CONFIG_FATFS_LFN_STACK=n diff --git a/examples/storage/fatfs/getting_started/CMakeLists.txt b/examples/storage/fatfs/getting_started/CMakeLists.txt new file mode 100644 index 000000000000..b5959836791d --- /dev/null +++ b/examples/storage/fatfs/getting_started/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(fatfs_getting_started) diff --git a/examples/storage/fatfs/getting_started/README.md b/examples/storage/fatfs/getting_started/README.md new file mode 100644 index 000000000000..626f9323cbb0 --- /dev/null +++ b/examples/storage/fatfs/getting_started/README.md @@ -0,0 +1,44 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | + +# FATFS minimal example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates the minimal setup required to store persistent data on SPI Flash using the FAT filesystem. +Beware that the minimal required size of the flash is 4 MB. + +## How to use example + +### Build and flash + +To run the example, type the following command: + +```CMake +# CMake +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example output + +Here is the example's console output: + +``` +... +I (321) example: Mounting FAT filesystem +I (331) example: Filesystem mounted +I (331) example: Opening file +I (731) example: File written +I (731) example: Reading file +I (741) example: Read from file: 'Hello World!' +I (741) example: Unmounting FAT filesystem +I (851) example: Done +... +``` + +The logic of the example is contained in a [single source file](./main/fatfs_getting_started_main.c), +and it should be relatively simple to match points in its execution with the log outputs above. diff --git a/examples/storage/fatfs/getting_started/main/CMakeLists.txt b/examples/storage/fatfs/getting_started/main/CMakeLists.txt new file mode 100644 index 000000000000..fec5d19cadad --- /dev/null +++ b/examples/storage/fatfs/getting_started/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "fatfs_getting_started_main.c" + INCLUDE_DIRS ".") diff --git a/examples/storage/fatfs/getting_started/main/fatfs_getting_started_main.c b/examples/storage/fatfs/getting_started/main/fatfs_getting_started_main.c new file mode 100644 index 000000000000..ae8529160e04 --- /dev/null +++ b/examples/storage/fatfs/getting_started/main/fatfs_getting_started_main.c @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "sdkconfig.h" + +static const char *TAG = "example"; + +// Mount path for the partition +const char *base_path = "/spiflash"; + +// Handle of the wear levelling library instance +static wl_handle_t s_wl_handle = WL_INVALID_HANDLE; + +void app_main(void) +{ + ESP_LOGI(TAG, "Mounting FAT filesystem"); + // To mount device we need name of device partition, define base_path + // and allow format partition in case if it is new one and was not formatted before + const esp_vfs_fat_mount_config_t mount_config = { + .max_files = 4, // Number of files that can be open at a time + .format_if_mount_failed = true, // If true, try to format the partition if mount fails + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, // Size of allocation unit, cluster size. + .use_one_fat = false, // Use only one FAT table (reduce memory usage), but decrease reliability of file system in case of power failure. + }; + + // Mount FATFS filesystem located on "storage" partition in read-write mode + esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, "storage", &mount_config, &s_wl_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err)); + return; + } + + ESP_LOGI(TAG, "Filesystem mounted"); + + ESP_LOGI(TAG, "Opening file"); + + const char *filename = "/spiflash/example.txt"; + + FILE *f = fopen(filename, "wb"); + if (f == NULL) { + perror("fopen"); // Print reason why fopen failed + ESP_LOGE(TAG, "Failed to open file for writing"); + return; + } + + fprintf(f, "Hello World!\n"); + fclose(f); + + ESP_LOGI(TAG, "File written"); + + // Open file for reading + ESP_LOGI(TAG, "Reading file"); + + f = fopen(filename, "r"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed to open file for reading"); + return; + } + + char line[128]; + + fgets(line, sizeof(line), f); + fclose(f); + + // strip newline + char *pos = strchr(line, '\n'); + if (pos) { + *pos = '\0'; + } + + ESP_LOGI(TAG, "Read from file: '%s'", line); + + // Unmount FATFS + ESP_LOGI(TAG, "Unmounting FAT filesystem"); + + ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_rw_wl(base_path, s_wl_handle)); + + ESP_LOGI(TAG, "Done"); +} diff --git a/examples/storage/fatfs/getting_started/partitions_example.csv b/examples/storage/fatfs/getting_started/partitions_example.csv new file mode 100644 index 000000000000..1c79321a107c --- /dev/null +++ b/examples/storage/fatfs/getting_started/partitions_example.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, diff --git a/examples/storage/fatfs/getting_started/pytest_fatfs_getting_started_example.py b/examples/storage/fatfs/getting_started/pytest_fatfs_getting_started_example.py new file mode 100644 index 000000000000..e7f9d7d78a72 --- /dev/null +++ b/examples/storage/fatfs/getting_started/pytest_fatfs_getting_started_example.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32 +@pytest.mark.generic +def test_examples_fatfs_getting_started(dut: Dut) -> None: + dut.expect('example: Mounting FAT filesystem', timeout=90) + dut.expect('example: Filesystem mounted', timeout=90) + dut.expect('example: Opening file', timeout=90) + dut.expect('example: File written', timeout=90) + dut.expect('example: Reading file', timeout=90) + dut.expect('example: Read from file: \'Hello World!\'', timeout=90) + dut.expect('example: Unmounting FAT filesystem', timeout=90) + dut.expect('example: Done', timeout=90) diff --git a/examples/storage/fatfsgen/sdkconfig.defaults b/examples/storage/fatfs/getting_started/sdkconfig.defaults similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.defaults rename to examples/storage/fatfs/getting_started/sdkconfig.defaults diff --git a/examples/storage/perf_benchmark/README.md b/examples/storage/perf_benchmark/README.md index d3f4f6b5d17b..d18c76cbe9c3 100644 --- a/examples/storage/perf_benchmark/README.md +++ b/examples/storage/perf_benchmark/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | # Storage performance benchmark example diff --git a/examples/storage/perf_benchmark/main/perf_benchmark_example_tests.c b/examples/storage/perf_benchmark/main/perf_benchmark_example_tests.c index 1e40685f15cd..789e6ce305bc 100644 --- a/examples/storage/perf_benchmark/main/perf_benchmark_example_tests.c +++ b/examples/storage/perf_benchmark/main/perf_benchmark_example_tests.c @@ -50,7 +50,7 @@ static void print_results(const char *name, double time, size_t size, int repeat void spiflash_speed_test_raw_run(size_t repeat_count) { const size_t buf_size = CONFIG_EXAMPLE_TARGET_RW_SIZE; - uint32_t* buf = (uint32_t*) calloc(1, buf_size); + uint32_t* buf = (uint32_t*) heap_caps_calloc(1, buf_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_CACHE_ALIGNED | MALLOC_CAP_DMA); assert(buf != NULL); esp_fill_random(buf, buf_size); @@ -159,7 +159,7 @@ static void run_fs_tests(const char *base_path, const char *type, bool new_file, assert(tiny_size < less_than_target_size); const size_t buf_size = more_than_target_size; - uint32_t* buf = (uint32_t*) calloc(1, buf_size); + uint32_t* buf = (uint32_t*) heap_caps_calloc(1, buf_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_CACHE_ALIGNED | MALLOC_CAP_DMA); assert(buf != NULL); esp_fill_random(buf, buf_size); @@ -219,7 +219,8 @@ void sdcard_speed_test_raw_run(sdmmc_card_t *card, size_t repeat_count) size_t sector_count = CONFIG_EXAMPLE_TARGET_RW_SIZE / sector_size; size_t subsection_sector_count = sector_count / 4; - char *buf = (char *) calloc(1, sector_count * sector_size); + // Best performance is achieved when the buffer is internal (not PSRAM) and aligned to RAM line size + char *buf = (char *) heap_caps_calloc(1, sector_count * sector_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_CACHE_ALIGNED | MALLOC_CAP_DMA); assert(buf != NULL); struct timeval tv_start; diff --git a/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py b/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py index 0b7f3b14ffb8..defa143f8955 100644 --- a/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py +++ b/examples/storage/perf_benchmark/pytest_perf_benchmark_example.py @@ -57,6 +57,8 @@ def test_examples_perf_benchmark_sdcard_sdmmc(dut: Dut) -> None: @pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDFCI-2059, temporary lack runner') @pytest.mark.esp32c3 @pytest.mark.esp32s2 +@pytest.mark.esp32c5 +@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C5 C61 GPSPI same, so testing on C5 is enough') @pytest.mark.sdcard_spimode @pytest.mark.parametrize( 'config', diff --git a/examples/storage/sd_card/sdspi/CMakeLists.txt b/examples/storage/sd_card/sdspi/CMakeLists.txt index d41a683007d3..e140d486250e 100644 --- a/examples/storage/sd_card/sdspi/CMakeLists.txt +++ b/examples/storage/sd_card/sdspi/CMakeLists.txt @@ -2,7 +2,6 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) -list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/storage/sd_card/sdmmc/components/sd_card") set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) diff --git a/examples/storage/sd_card/sdspi/main/idf_component.yml b/examples/storage/sd_card/sdspi/main/idf_component.yml new file mode 100644 index 000000000000..b755a62b1472 --- /dev/null +++ b/examples/storage/sd_card/sdspi/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + sd_card: + path: ${IDF_PATH}/examples/storage/sd_card/sdmmc/components/sd_card diff --git a/examples/storage/sd_card/sdspi/pytest_sdspi_card_example.py b/examples/storage/sd_card/sdspi/pytest_sdspi_card_example.py index 616c5cafdbc3..4cfac08bf1ac 100644 --- a/examples/storage/sd_card/sdspi/pytest_sdspi_card_example.py +++ b/examples/storage/sd_card/sdspi/pytest_sdspi_card_example.py @@ -7,6 +7,7 @@ from pytest_embedded import Dut +@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 diff --git a/examples/storage/semihost_vfs/README.md b/examples/storage/semihost_vfs/README.md index 0cf77e01fa4f..0ce5acc0eacc 100644 --- a/examples/storage/semihost_vfs/README.md +++ b/examples/storage/semihost_vfs/README.md @@ -97,7 +97,7 @@ There are two outputs produced by example: ``` W (274) example: Switch to semihosted stdout W (274) example: Switched back to UART stdout - I (274) example: Wrote 2798 bytes + I (274) example: Wrote 2776 bytes ====================== HOST DATA START ========================= The following are the graphical (non-control) characters defined by ISO 8859-1 (1987). Descriptions in words aren't all that helpful, @@ -115,4 +115,3 @@ There are two outputs produced by example: ====================== HOST DATA END ========================= I (694) example: Read 6121 bytes ``` - diff --git a/examples/storage/semihost_vfs/pytest_semihost_vfs.py b/examples/storage/semihost_vfs/pytest_semihost_vfs.py index aff2e51227aa..90af90e29e20 100644 --- a/examples/storage/semihost_vfs/pytest_semihost_vfs.py +++ b/examples/storage/semihost_vfs/pytest_semihost_vfs.py @@ -1,6 +1,5 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 - import os import shutil import tempfile @@ -42,7 +41,10 @@ def prepare() -> t.Generator[None, None, None]: def test_semihost_vfs(dut: IdfDut) -> None: dut.expect_exact('example: Switch to semihosted stdout') dut.expect_exact('example: Switched back to UART stdout') - dut.expect_exact('example: Wrote 2798 bytes') + if dut.app.sdkconfig.get('LOG_COLORS') is True: + dut.expect_exact('example: Wrote 2798 bytes') + else: + dut.expect_exact('example: Wrote 2776 bytes') dut.expect_exact('====================== HOST DATA START =========================') with open(HOST_FILE_PATH) as f: diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index ddb33070ef08..c5311cbf9f62 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -1,10 +1,10 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps examples/system/app_trace_basic: - disable: + disable_test: - if: IDF_TARGET in ["esp32c6", "esp32h2", "esp32p4", "esp32c5", "esp32c61"] temporary: true - reason: targets not supported yet, TODO[C61] IDF-9264 IDF-10992 + reason: usb-serial-jtag tests are not stable yet. TODO[C61] IDF-10992 examples/system/base_mac_address: depends_components: @@ -169,14 +169,8 @@ examples/system/ota/native_ota_example: - protocol_examples_common examples/system/ota/otatool: - disable: - - if: IDF_TARGET in ["esp32h2"] - temporary: true - reason: target esp32h2 is not supported yet - disable_test: - - if: IDF_TARGET in ["esp32c61"] - reason: target esp32c61 is not supported yet - + enable: + - if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["esp32c5", "esp32c61"] examples/system/ota/pre_encrypted_ota: disable: @@ -299,6 +293,12 @@ examples/system/ulp/lp_core/gpio_intr_pulse_counter: depends_components: - ulp +examples/system/ulp/lp_core/gpio_wakeup: + enable: + - if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_RTCIO_PIN_COUNT > 0) + depends_components: + - ulp + examples/system/ulp/lp_core/inter_cpu_critical_section/: enable: - if: SOC_LP_CORE_SUPPORTED == 1 diff --git a/examples/system/app_trace_basic/README.md b/examples/system/app_trace_basic/README.md index 2da31cd059a6..151e992d1a40 100644 --- a/examples/system/app_trace_basic/README.md +++ b/examples/system/app_trace_basic/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | # Application Level Tracing Example (Basic) diff --git a/examples/system/efuse/pytest_system_efuse_example.py b/examples/system/efuse/pytest_system_efuse_example.py index b7e922a62593..6d205104590b 100644 --- a/examples/system/efuse/pytest_system_efuse_example.py +++ b/examples/system/efuse/pytest_system_efuse_example.py @@ -552,11 +552,9 @@ def test_examples_efuse_with_virt_secure_boot_v2_pre_loaded(dut: Dut) -> None: @pytest.mark.esp32c3 @pytest.mark.esp32c2 -# TODO: [ESP32C5] IDF-10043 -# @pytest.mark.esp32c5 -# TODO: [ESP32C61] IDF-10102 -# @pytest.mark.esp32c61 +@pytest.mark.esp32c5 @pytest.mark.esp32c6 +@pytest.mark.esp32c61 @pytest.mark.esp32h2 @pytest.mark.esp32p4 @pytest.mark.esp32s2 @@ -629,11 +627,9 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(dut: Dut) -> None: @pytest.mark.esp32c3 @pytest.mark.esp32c2 -# TODO: [ESP32C5] IDF-10043 -# @pytest.mark.esp32c5 -# TODO: [ESP32C61] IDF-10102 -# @pytest.mark.esp32c61 +@pytest.mark.esp32c5 @pytest.mark.esp32c6 +@pytest.mark.esp32c61 @pytest.mark.esp32h2 @pytest.mark.esp32p4 @pytest.mark.esp32s2 diff --git a/examples/system/freertos/basic_freertos_smp_usage/main/lock_example.c b/examples/system/freertos/basic_freertos_smp_usage/main/lock_example.c index 670b13edc120..409e2095b62d 100644 --- a/examples/system/freertos/basic_freertos_smp_usage/main/lock_example.c +++ b/examples/system/freertos/basic_freertos_smp_usage/main/lock_example.c @@ -78,7 +78,7 @@ static void inc_num_atomic_iter(void *arg) static void inc_num_mutex(void *arg) { - int task_index = *(int*)arg; + int task_index = (int)arg; ESP_LOGI(TAG, "mutex task %d created", task_index); while (!timed_out) { @@ -159,7 +159,7 @@ int comp_lock_entry_func(int argc, char **argv) s_global_num = 0; // create 2 tasks to increase a shared number in turn for (thread_id = 0; thread_id < SHARE_RES_THREAD_NUM; thread_id++) { - xTaskCreatePinnedToCore(inc_num_mutex, NULL, 4096, &thread_id, TASK_PRIO_3, NULL, tskNO_AFFINITY); + xTaskCreatePinnedToCore(inc_num_mutex, NULL, 4096, (void *)thread_id, TASK_PRIO_3, NULL, tskNO_AFFINITY); } // time out and stop running after 5 seconds diff --git a/examples/system/freertos/basic_freertos_smp_usage/pytest_smp_examples.py b/examples/system/freertos/basic_freertos_smp_usage/pytest_smp_examples.py index 5019db6a4b40..fa7ac3b547d7 100644 --- a/examples/system/freertos/basic_freertos_smp_usage/pytest_smp_examples.py +++ b/examples/system/freertos/basic_freertos_smp_usage/pytest_smp_examples.py @@ -13,10 +13,13 @@ def test_creating_task( dut.expect(r'esp32(?:[a-zA-Z]\d)?>') # test creating_task dut.write('create_task') - dut.expect('create task example: task#0 is running on core#0') - dut.expect('create task example: task#1 is running on core#0') - dut.expect(r'create task example: task#2 is running on core#\d') - dut.expect(r'create task example: task#3 is running on core#\d') + expected_patterns = [ + 'create task example: task#0 is running on core#0', + 'create task example: task#1 is running on core#0', + r'create task example: task#2 is running on core#\d', + r'create task example: task#3 is running on core#\d', + ] + dut.expect(expected_patterns, expect_all=True) @pytest.mark.esp32c3 @@ -46,14 +49,14 @@ def test_locks( dut.expect(r'esp32(?:[a-zA-Z]\d)?>') # test locks dut.write('lock') - dut.expect(r'lock example: mutex task took \d+ us on core\d') - dut.expect(r'lock example: spinlock task took \d+ us on core\d') - dut.expect(r'lock example: atomic task took \d+ us on core\d') - dut.expect(r'task0 read value = 0 on core #\d') - dut.expect('task0 set value = 1') - dut.expect(r'task\d read value = 1 on core #\d') - dut.expect(r'task\d set value = 2') - dut.expect(r'task0 read value = 2 on core #\d') + expected_patterns = [ + r'lock example: mutex task took \d+ us on core\d', + r'lock example: spinlock task took \d+ us on core\d', + r'lock example: atomic task took \d+ us on core\d', + r'task\d read value = \d on core #\d', + r'task\d set value = \d', + ] + dut.expect(expected_patterns, expect_all=True) @pytest.mark.esp32c3 diff --git a/examples/system/nmi_isr/main/nmi_isr_main.c b/examples/system/nmi_isr/main/nmi_isr_main.c index f2e86d5f4257..030577e92154 100644 --- a/examples/system/nmi_isr/main/nmi_isr_main.c +++ b/examples/system/nmi_isr/main/nmi_isr_main.c @@ -26,6 +26,7 @@ void app_main(void) printf("example: Start\n"); + gpio_reset_pin(EXAMPLE_GPIO_IN); /* Make sure we have a pull-down on the input GPIO to prevent noise (when disconnected) */ gpio_pulldown_en(EXAMPLE_GPIO_IN); gpio_set_direction(EXAMPLE_GPIO_IN, GPIO_MODE_INPUT_OUTPUT); diff --git a/examples/system/ota/otatool/README.md b/examples/system/ota/otatool/README.md index 255b22320037..859fb55977c2 100644 --- a/examples/system/ota/otatool/README.md +++ b/examples/system/ota/otatool/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | # OTA Tool Example diff --git a/examples/system/ota/otatool/pytest_otatool.py b/examples/system/ota/otatool/pytest_otatool.py index 8a9d0b21af78..c07703473696 100644 --- a/examples/system/ota/otatool/pytest_otatool.py +++ b/examples/system/ota/otatool/pytest_otatool.py @@ -26,14 +26,7 @@ def _real_test_func(dut: Dut) -> None: subprocess.check_call([sys.executable, script_path, '--binary', binary_path]) -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 -@pytest.mark.esp32s3 -@pytest.mark.esp32c5 -# @pytest.mark.esp32c61 #IDF-11309 -@pytest.mark.esp32c6 -@pytest.mark.esp32p4 +@pytest.mark.supported_targets @pytest.mark.generic def test_otatool_example(dut: Dut) -> None: _real_test_func(dut) diff --git a/examples/system/ota/simple_ota_example/pytest_simple_ota.py b/examples/system/ota/simple_ota_example/pytest_simple_ota.py index c7c1992f0326..bbc7d27be62f 100644 --- a/examples/system/ota/simple_ota_example/pytest_simple_ota.py +++ b/examples/system/ota/simple_ota_example/pytest_simple_ota.py @@ -225,6 +225,11 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du 2. Fetch OTA image over HTTPS 3. Reboot with the new OTA image """ + # CONFIG_PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS==y, it includes partitions_two_ota_encr_nvs.csv + FACTORY_ADDRESS = '0x20000' + OTA_0_ADDRESS = '0x120000' + # OTA_1_ADDRESS = '0x220000' + # start test # Erase flash dut.serial.erase_flash() @@ -234,7 +239,7 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du thread1.daemon = True thread1.start() try: - dut.expect(f'Loaded app from partition at offset {OTA_0_ADDRESS}', timeout=30) + dut.expect(f'Loaded app from partition at offset {FACTORY_ADDRESS}', timeout=30) dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10) # Parse IP address of STA env_name = 'flash_encryption_wifi_high_traffic' if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True else None @@ -245,7 +250,7 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du dut.write(f'https://{host_ip}:8000/simple_ota.bin') dut.expect('OTA Succeed, Rebooting...', timeout=60) # after reboot - dut.expect(f'Loaded app from partition at offset {OTA_1_ADDRESS}', timeout=30) + dut.expect(f'Loaded app from partition at offset {OTA_0_ADDRESS}', timeout=30) dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10) dut.expect('OTA example app_main start', timeout=10) finally: diff --git a/examples/system/ulp/lp_core/gpio_wakeup/CMakeLists.txt b/examples/system/ulp/lp_core/gpio_wakeup/CMakeLists.txt new file mode 100644 index 000000000000..8c1a422f3f46 --- /dev/null +++ b/examples/system/ulp/lp_core/gpio_wakeup/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ulp_lp_core_gpio_wakeup_example) diff --git a/examples/system/ulp/lp_core/gpio_wakeup/README.md b/examples/system/ulp/lp_core/gpio_wakeup/README.md new file mode 100644 index 000000000000..66925750726f --- /dev/null +++ b/examples/system/ulp/lp_core/gpio_wakeup/README.md @@ -0,0 +1,26 @@ +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | +| ----------------- | -------- | -------- | -------- | +# ULP-LP-Core simple example with GPIO Interrupt: + +This example demonstrates how to program the LP-Core coprocessor to wake up from a RTC IO interrupt, instead of waking periodically from the ULP timer. + +ULP program written in C can be found across `ulp/main.c`. The build system compiles and links this program, converts it into binary format, and embeds it into the .rodata section of the ESP-IDF application. + +At runtime, the main code running on the ESP (found in lp_core_gpio_wake_up_example_main.c) loads ULP program into the `RTC_SLOW_MEM` memory region using `ulp_lp_core_load_binary` function. The main code then configures the ULP GPIO wakeup source and starts the coprocessor by using `ulp_lp_core_run` followed by putting the chip into deep sleep mode. + +When the wakeup source pin is pulled low the LP-Core coprocessor is woken up, sends a wakeup signal to the main CPU and goes back to sleep again. + +In this example the input signal is connected to GPIO2. To change the pin number, check the Chip Pin List document and adjust `WAKEUP_PIN` variable in main.c. + + +## Example output + +``` +Not a LP-Core wakeup, initializing it! +Entering deep sleep + +... + +LP-Core woke up the main CPU! +Entering deep sleep +``` diff --git a/examples/system/ulp/lp_core/gpio_wakeup/main/CMakeLists.txt b/examples/system/ulp/lp_core/gpio_wakeup/main/CMakeLists.txt new file mode 100644 index 000000000000..9970ae3effb9 --- /dev/null +++ b/examples/system/ulp/lp_core/gpio_wakeup/main/CMakeLists.txt @@ -0,0 +1,27 @@ +# Set usual component variables +set(COMPONENT_SRCS "lp_core_gpio_wake_up_example_main.c") +set(COMPONENT_ADD_INCLUDEDIRS "") +set(COMPONENT_REQUIRES ulp driver) + +register_component() + +# +# ULP support additions to component CMakeLists.txt. +# +# 1. The ULP app name must be unique (if multiple components use ULP). +set(ulp_app_name ulp_${COMPONENT_NAME}) +# +# 2. Specify all C and Assembly source files. +# Files should be placed into a separate directory (in this case, ulp/), +# which should not be added to COMPONENT_SRCS. +set(ulp_riscv_sources "ulp/main.c") + +# +# 3. List all the component source files which include automatically +# generated ULP export file, ${ulp_app_name}.h: +set(ulp_exp_dep_srcs "lp_core_gpio_wake_up_example_main.c") + +# +# 4. Call function to build ULP binary and embed in project using the argument +# values above. +ulp_embed_binary(${ulp_app_name} "${ulp_riscv_sources}" "${ulp_exp_dep_srcs}") diff --git a/examples/system/ulp/lp_core/gpio_wakeup/main/lp_core_gpio_wake_up_example_main.c b/examples/system/ulp/lp_core/gpio_wakeup/main/lp_core_gpio_wake_up_example_main.c new file mode 100644 index 000000000000..7de67d59c366 --- /dev/null +++ b/examples/system/ulp/lp_core/gpio_wakeup/main/lp_core_gpio_wake_up_example_main.c @@ -0,0 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* ULP LP-Core GPIO wake-up example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include "esp_sleep.h" +#include "driver/rtc_io.h" +#include "ulp_lp_core.h" +#include "ulp_main.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define WAKEUP_PIN 2 + +extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); +extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end"); + +static void init_ulp_program(void); + +static void wakeup_gpio_init(void) +{ + /* Configure the button GPIO as input, enable wakeup */ + rtc_gpio_init(WAKEUP_PIN); + rtc_gpio_set_direction(WAKEUP_PIN, RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_pulldown_dis(WAKEUP_PIN); + rtc_gpio_pullup_en(WAKEUP_PIN); + rtc_gpio_wakeup_enable(WAKEUP_PIN, GPIO_INTR_LOW_LEVEL); +} + +void app_main(void) +{ + /* If user is using USB-serial-jtag then idf monitor needs some time to + * re-connect to the USB port. We wait 1 sec here to allow for it to make the reconnection + * before we print anything. Otherwise the chip will go back to sleep again before the user + * has time to monitor any output. + */ + vTaskDelay(pdMS_TO_TICKS(1000)); + + wakeup_gpio_init(); + + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + /* not a wakeup from ULP, load the firmware */ + if (cause != ESP_SLEEP_WAKEUP_ULP) { + printf("Not a ULP wakeup, initializing it! \n"); + init_ulp_program(); + } + + /* ULP read and detected a change in WAKEUP_PIN, prints */ + if (cause == ESP_SLEEP_WAKEUP_ULP) { + printf("ULP woke up the main CPU! \n"); + } + + /* Go back to sleep, only the ULP will run */ + printf("Entering deep sleep\n\n"); + + /* Small delay to ensure the messages are printed */ + vTaskDelay(100 / portTICK_PERIOD_MS); + + ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup()); + + esp_deep_sleep_start(); +} + +static void init_ulp_program(void) +{ + esp_err_t err = ulp_lp_core_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start)); + ESP_ERROR_CHECK(err); + + /* Start the program */ + ulp_lp_core_cfg_t cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_IO, + }; + + err = ulp_lp_core_run(&cfg); + ESP_ERROR_CHECK(err); +} diff --git a/examples/system/ulp/lp_core/gpio_wakeup/main/ulp/main.c b/examples/system/ulp/lp_core/gpio_wakeup/main/ulp/main.c new file mode 100644 index 000000000000..0f630ddc0cc6 --- /dev/null +++ b/examples/system/ulp/lp_core/gpio_wakeup/main/ulp/main.c @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include "ulp_lp_core.h" +#include "ulp_lp_core_utils.h" +#include "ulp_lp_core_gpio.h" + + +int main (void) +{ + ulp_lp_core_wakeup_main_processor(); + + /* Wakeup interrupt is a level interrupt, wait 1 sec to + allow user to release button to avoid waking up the ULP multiple times */ + ulp_lp_core_delay_us(1000*1000); + ulp_lp_core_gpio_clear_intr_status(); + + return 0; +} diff --git a/examples/system/ulp/lp_core/gpio_wakeup/sdkconfig.defaults b/examples/system/ulp/lp_core/gpio_wakeup/sdkconfig.defaults new file mode 100644 index 000000000000..456833bc8c36 --- /dev/null +++ b/examples/system/ulp/lp_core/gpio_wakeup/sdkconfig.defaults @@ -0,0 +1,9 @@ +# Enable ULP +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_TYPE_LP_CORE=y +CONFIG_ULP_COPROC_RESERVE_MEM=8128 +# Set log level to Warning to produce clean output +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_BOOTLOADER_LOG_LEVEL=2 +CONFIG_LOG_DEFAULT_LEVEL_WARN=y +CONFIG_LOG_DEFAULT_LEVEL=2 diff --git a/examples/wifi/iperf/sdkconfig.defaults.esp32c5 b/examples/wifi/iperf/sdkconfig.defaults.esp32c5 index 7c3a67ad310d..338b88f5700e 100644 --- a/examples/wifi/iperf/sdkconfig.defaults.esp32c5 +++ b/examples/wifi/iperf/sdkconfig.defaults.esp32c5 @@ -12,7 +12,7 @@ CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP_WIFI_RX_BA_WIN=22 CONFIG_ESP_WIFI_NVS_ENABLED=n -CONFIG_LWIP_TCP_SND_BUF_DEFAULT=57600 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=50400 CONFIG_LWIP_TCP_WND_DEFAULT=65535 CONFIG_LWIP_TCP_RECVMBOX_SIZE=48 CONFIG_LWIP_UDP_RECVMBOX_SIZE=64 diff --git a/examples/wifi/itwt/main/Kconfig.projbuild b/examples/wifi/itwt/main/Kconfig.projbuild index 9eb0e46e7be5..8d8dd52b2e18 100644 --- a/examples/wifi/itwt/main/Kconfig.projbuild +++ b/examples/wifi/itwt/main/Kconfig.projbuild @@ -38,6 +38,12 @@ menu "Example Configuration" help Set static gateway address. + config EXAMPLE_TWT_ENABLE_KEEP_ALIVE_QOS_NULL + bool "enable keep alive qos null" + default n + help + Enable send QOS NULL to keep alive during TWT. + menu "iTWT Configuration" config EXAMPLE_ITWT_TRIGGER_ENABLE bool "trigger-enabled" diff --git a/examples/wifi/itwt/main/itwt_main.c b/examples/wifi/itwt/main/itwt_main.c index e2f4ecc77191..c1e44d8eb2f7 100644 --- a/examples/wifi/itwt/main/itwt_main.c +++ b/examples/wifi/itwt/main/itwt_main.c @@ -49,6 +49,12 @@ static const char *TAG = "itwt"; #define DEFAULT_PWD CONFIG_EXAMPLE_WIFI_PASSWORD #define ITWT_SETUP_SUCCESS 1 +#if CONFIG_EXAMPLE_TWT_ENABLE_KEEP_ALIVE_QOS_NULL +bool keep_alive_enabled = true; +#else +bool keep_alive_enabled = false; +#endif + #if CONFIG_EXAMPLE_ITWT_TRIGGER_ENABLE uint8_t trigger_enabled = 1; #else @@ -264,6 +270,12 @@ static void wifi_itwt(void) ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); + wifi_twt_config_t wifi_twt_config = { + .post_wakeup_event = false, + .twt_enable_keep_alive = keep_alive_enabled, + }; + ESP_ERROR_CHECK(esp_wifi_sta_twt_config(&wifi_twt_config)); + esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT20); esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX); esp_wifi_set_ps(WIFI_PS_MIN_MODEM); diff --git a/examples/wifi/power_save/main/Kconfig.projbuild b/examples/wifi/power_save/main/Kconfig.projbuild index 877fe14b7b26..e06b5874fd30 100644 --- a/examples/wifi/power_save/main/Kconfig.projbuild +++ b/examples/wifi/power_save/main/Kconfig.projbuild @@ -40,7 +40,7 @@ menu "Example Configuration" choice EXAMPLE_WIFI_BAND_MODE prompt "wifi band" default EXAMPLE_WIFI_BAND_MODE_2G - depends on SOC_WIFI_HE_SUPPORT_5G + depends on SOC_WIFI_SUPPORT_5G help WiFi band for the example to use. diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index bb35a5c36233..00224c2f2775 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -36,7 +36,7 @@ #define DEFAULT_PS_MODE WIFI_PS_NONE #endif /*CONFIG_POWER_SAVE_MODEM*/ -#if SOC_WIFI_HE_SUPPORT_5G +#if CONFIG_SOC_WIFI_SUPPORT_5G #if CONFIG_EXAMPLE_WIFI_BAND_MODE_2G #define DEFAULT_WIFI_BAND_MODE WIFI_BAND_MODE_2G_ONLY #elif CONFIG_EXAMPLE_WIFI_BAND_MODE_5G @@ -89,7 +89,7 @@ static void wifi_power_save(void) ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); -#if SOC_WIFI_HE_SUPPORT_5G +#if CONFIG_SOC_WIFI_SUPPORT_5G ESP_ERROR_CHECK(esp_wifi_set_band_mode(DEFAULT_WIFI_BAND_MODE)); #endif ESP_ERROR_CHECK(esp_wifi_set_inactive_time(WIFI_IF_STA, DEFAULT_BEACON_TIMEOUT)); diff --git a/examples/wifi/scan/main/scan.c b/examples/wifi/scan/main/scan.c index 243b4a7a98f8..2dd34ff907a4 100644 --- a/examples/wifi/scan/main/scan.c +++ b/examples/wifi/scan/main/scan.c @@ -22,7 +22,7 @@ #define DEFAULT_SCAN_LIST_SIZE CONFIG_EXAMPLE_SCAN_LIST_SIZE #ifdef CONFIG_EXAMPLE_USE_SCAN_CHANNEL_BITMAP -#define USE_CHANNEL_BTIMAP 1 +#define USE_CHANNEL_BITMAP 1 #define CHANNEL_LIST_SIZE 3 static uint8_t channel_list[CHANNEL_LIST_SIZE] = {1, 6, 11}; #endif /*CONFIG_EXAMPLE_USE_SCAN_CHANNEL_BITMAP*/ @@ -59,6 +59,12 @@ static void print_auth_mode(int authmode) case WIFI_AUTH_WPA2_WPA3_PSK: ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_WPA3_PSK"); break; + case WIFI_AUTH_WPA3_ENTERPRISE: + ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA3_ENTERPRISE"); + break; + case WIFI_AUTH_WPA2_WPA3_ENTERPRISE: + ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_WPA3_ENTERPRISE"); + break; case WIFI_AUTH_WPA3_ENT_192: ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA3_ENT_192"); break; @@ -140,7 +146,7 @@ static void print_cipher_type(int pairwise_cipher, int group_cipher) } } -#ifdef USE_CHANNEL_BTIMAP +#ifdef USE_CHANNEL_BITMAP static void array_2_channel_bitmap(const uint8_t channel_list[], const uint8_t channel_list_size, wifi_scan_config_t *scan_config) { for(uint8_t i = 0; i < channel_list_size; i++) { @@ -148,7 +154,7 @@ static void array_2_channel_bitmap(const uint8_t channel_list[], const uint8_t c scan_config->channel_bitmap.ghz_2_channels |= (1 << channel); } } -#endif /*USE_CHANNEL_BTIMAP*/ +#endif /*USE_CHANNEL_BITMAP*/ /* Initialize Wi-Fi as sta and set scan method */ @@ -171,7 +177,7 @@ static void wifi_scan(void) ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); -#ifdef USE_CHANNEL_BTIMAP +#ifdef USE_CHANNEL_BITMAP wifi_scan_config_t *scan_config = (wifi_scan_config_t *)calloc(1,sizeof(wifi_scan_config_t)); if (!scan_config) { ESP_LOGE(TAG, "Memory Allocation for scan config failed!"); @@ -183,7 +189,7 @@ static void wifi_scan(void) #else esp_wifi_scan_start(NULL, true); -#endif /*USE_CHANNEL_BTIMAP*/ +#endif /*USE_CHANNEL_BITMAP*/ ESP_LOGI(TAG, "Max AP number ap_info can hold = %u", number); ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count)); diff --git a/examples/zigbee/.build-test-rules.yml b/examples/zigbee/.build-test-rules.yml index 793bc65b937c..eb8c7d7bccdb 100644 --- a/examples/zigbee/.build-test-rules.yml +++ b/examples/zigbee/.build-test-rules.yml @@ -8,28 +8,15 @@ examples/zigbee/esp_zigbee_gateway: enable: - - if: SOC_WIFI_SUPPORTED == 1 and IDF_TARGET not in ["esp32c2", "esp32c5", "esp32c61"] - reason: not supported esp32c2 and esp32c5 and esp32c61 - <<: *zigbee_dependencies - -examples/zigbee/esp_zigbee_rcp: - enable: - - if: SOC_IEEE802154_SUPPORTED == 1 - disable: - - if: IDF_TARGET == "esp32c5" - temporary: true - reason: Not supported yet + - if: SOC_WIFI_SUPPORTED == 1 and IDF_TARGET not in ["esp32c2", "esp32c61"] + reason: not supported esp32c2 and esp32c61 <<: *zigbee_dependencies examples/zigbee/light_sample: enable: - if: SOC_IEEE802154_SUPPORTED == 1 - disable: - - if: IDF_TARGET == "esp32c5" - temporary: true - reason: Not supported yet disable_test: - - if: IDF_TARGET == "esp32c6" + - if: IDF_TARGET != "esp32h2" temporary: true reason: only test on esp32h2 <<: *zigbee_dependencies diff --git a/examples/zigbee/common/zcl_utility/include/zcl_utility.h b/examples/zigbee/common/zcl_utility/include/zcl_utility.h new file mode 100644 index 000000000000..760bf7e10b50 --- /dev/null +++ b/examples/zigbee/common/zcl_utility/include/zcl_utility.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: LicenseRef-Included + * + * Zigbee Common + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "esp_check.h" +#include "esp_zigbee_core.h" + +/*! Maximum length of ManufacturerName string field */ +#define ESP_ZB_ZCL_CLUSTER_ID_BASIC_MANUFACTURER_NAME_MAX_LEN 32 + +/*! Maximum length of ModelIdentifier string field */ +#define ESP_ZB_ZCL_CLUSTER_ID_BASIC_MODEL_IDENTIFIER_MAX_LEN 32 + +/** optional basic manufacturer information */ +typedef struct zcl_basic_manufacturer_info_s { + char *manufacturer_name; + char *model_identifier; +} zcl_basic_manufacturer_info_t; + +/** + * @brief Adds manufacturer information to the ZCL basic cluster of endpoint + * + * @param[in] ep_list The pointer to the endpoint list with @p endpoint_id + * @param[in] endpoint_id The endpoint identifier indicating where the ZCL basic cluster resides + * @param[in] info The pointer to the basic manufacturer information + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid argument + */ +esp_err_t esp_zcl_utility_add_ep_basic_manufacturer_info(esp_zb_ep_list_t *ep_list, uint8_t endpoint_id, zcl_basic_manufacturer_info_t *info); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/examples/zigbee/common/zcl_utility/src/zcl_utility.c b/examples/zigbee/common/zcl_utility/src/zcl_utility.c new file mode 100644 index 000000000000..c88d6cd8bc8f --- /dev/null +++ b/examples/zigbee/common/zcl_utility/src/zcl_utility.c @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: LicenseRef-Included + * + * Zigbee Common + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. + */ +#include "esp_check.h" +#include "stdio.h" +#include "string.h" +#include "zcl_utility.h" +#include + +static const char *TAG = "ZCL_UTILITY"; + +esp_err_t esp_zcl_utility_add_ep_basic_manufacturer_info(esp_zb_ep_list_t *ep_list, uint8_t endpoint_id, zcl_basic_manufacturer_info_t *info) +{ + esp_err_t ret = ESP_OK; + esp_zb_cluster_list_t *cluster_list = NULL; + esp_zb_attribute_list_t *basic_cluster = NULL; + + cluster_list = esp_zb_ep_list_get_ep(ep_list, endpoint_id); + ESP_RETURN_ON_FALSE(cluster_list, ESP_ERR_INVALID_ARG, TAG, "Failed to find endpoint id: %d in list: %p", endpoint_id, ep_list); + basic_cluster = esp_zb_cluster_list_get_cluster(cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + ESP_RETURN_ON_FALSE(basic_cluster, ESP_ERR_INVALID_ARG, TAG, "Failed to find basic cluster in endpoint: %d", endpoint_id); + ESP_RETURN_ON_FALSE((info && info->manufacturer_name), ESP_ERR_INVALID_ARG, TAG, "Invalid manufacturer name"); + ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, info->manufacturer_name)); + ESP_RETURN_ON_FALSE((info && info->model_identifier), ESP_ERR_INVALID_ARG, TAG, "Invalid model identifier"); + ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, info->model_identifier)); + return ret; +} diff --git a/examples/zigbee/esp_zigbee_gateway/README.md b/examples/zigbee/esp_zigbee_gateway/README.md index 1a6fadfe8f31..e313e611e9c1 100644 --- a/examples/zigbee/esp_zigbee_gateway/README.md +++ b/examples/zigbee/esp_zigbee_gateway/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | # Gateway Example @@ -13,7 +13,7 @@ The ESP Zigbee SDK provides more examples and tools for productization: By default, two SoCs are required to run this example: * An ESP32 series Wi-Fi SoC (ESP32, ESP32-C, ESP32-S, etc) loaded with this esp_zigbee_gateway example. -* An ESP32-H2 802.15.4 SoC loaded with [esp_zigbee_rcp](../esp_zigbee_rcp) example +* An ESP32-H2 802.15.4 SoC loaded with [ot_rcp](../../openthread/ot_rcp/) example Connect the two SoCs via UART, below is an example setup with ESP32-DevKitC and ESP32-H2-DevKitC: ![Zigbee_gateway](../../openthread/ot_br/image/thread-border-router-esp32-esp32h2.jpg) @@ -28,6 +28,10 @@ ESP32 pin | ESP32-H2 pin The example could also run on a single SoC which supports both Wi-Fi and Zigbee (e.g., ESP32-C6), but since there is only one RF path in ESP32-C6, which means Wi-Fi and Zigbee can't receive simultaneously, it has a significant impact on performance. Hence the two SoCs solution is recommended. +## Configure the RCP + +The `OPENTHREAD_NCP_VENDOR_HOOK` of `ot_rcp` should be selected via menuconfig when the [ot_rcp](../../openthread/ot_rcp/) example is built. Then use `idf.py -p PORT erase-flash` to flash the RCP firmware to ESP32-H2-DevKitC. + ## Configure the project Before project configuration and build, make sure to set the correct chip target using `idf.py set-target `. @@ -50,19 +54,80 @@ As you run the example, you will see the following log: esp_zigbee_gateway: ``` -I (660) ESP_ZB_GATEWAY: status: -1 -I (670) ESP_ZB_GATEWAY: Zigbee stack initialized -I (680) ESP_ZB_GATEWAY: Zigbee rcp device booted -I (1280) ESP_ZB_GATEWAY: Start network formation -I (3060) ESP_ZB_GATEWAY: Formed network successfully (Extended PAN ID: f9:54:2d:01:a0:03:f7:84, PAN ID: 0x8651, Channel:13, Short Address: 0x0000) -I (4060) ESP_ZB_GATEWAY: status: 0 -I (4400) ESP_ZB_GATEWAY: Network steering started +I (499) main_task: Calling app_main() +I (519) ESP_RADIO_SPINEL: spinel UART interface initialization completed +I (519) ESP_RADIO_SPINEL: Spinel UART interface has been successfully enabled +I (519) ZB_ESP_SPINEL: Spinel UART interface enable successfully +I (529) main_task: Returned from app_main() +I(529) OPENTHREAD:[I] P-RadioSpinel-: RCP reset: RESET_POWER_ON +I(539) OPENTHREAD:[I] P-RadioSpinel-: Software reset RCP successfully +I (569) ZB_ESP_SPINEL: Radio spinel workflow register successfully +I (769) ESP_ZB_GATEWAY: Production configuration is ready +W (769) ESP_ZB_GATEWAY: Production configuration is not present +I (769) example_connect: Start example_connect. +I (779) pp: pp rom version: e7ae62f +I (779) net80211: net80211 rom version: e7ae62f +I (799) wifi:wifi driver task: 3fca80d8, prio:23, stack:6656, core=0 +I (799) wifi:wifi firmware version: 3ce09e5 +I (799) wifi:wifi certification version: v7.0 +I (799) wifi:config NVS flash: enabled +I (799) wifi:config nano formatting: disabled +I (809) wifi:Init data frame dynamic rx buffer num: 32 +I (809) wifi:Init static rx mgmt buffer num: 5 +I (819) wifi:Init management short buffer num: 32 +I (819) wifi:Init dynamic tx buffer num: 32 +I (819) wifi:Init static tx FG buffer num: 2 +I (829) wifi:Init static rx buffer size: 1600 +I (829) wifi:Init static rx buffer num: 10 +I (839) wifi:Init dynamic rx buffer num: 32 +I (839) wifi_init: rx ba win: 6 +I (839) wifi_init: tcpip mbox: 32 +I (849) wifi_init: udp mbox: 6 +I (849) wifi_init: tcp mbox: 6 +I (849) wifi_init: tcp tx win: 5760 +I (859) wifi_init: tcp rx win: 5760 +I (859) wifi_init: tcp mss: 1440 +I (869) wifi_init: WiFi IRAM OP enabled +I (869) wifi_init: WiFi RX IRAM OP enabled +I (879) phy_init: phy_version 670,b7bc9b9,Apr 30 2024,10:54:13 +W (879) phy_init: failed to load RF calibration data (0x1102), falling back to full calibration +I (989) wifi:mode : sta (f4:12:fa:41:a7:f4) +I (989) wifi:enable tsf +I (999) example_connect: Connecting to esp-office-2.4G... +I (999) example_connect: Waiting for IP(s) +I (3409) wifi:new:<13,0>, old:<1,0>, ap:<255,255>, sta:<13,0>, prof:1 +I (3649) wifi:state: init -> auth (b0) +I (3719) wifi:state: auth -> assoc (0) +I (3759) wifi:state: assoc -> run (10) +I (3769) wifi:connected with esp-office-2.4G, aid = 1, channel 13, BW20, bssid = 9c:3a:9a:04:18:92 +I (3769) wifi:security: WPA2-PSK, phy: bgn, rssi: -42 +I (3769) wifi:pm start, type: 1 + +I (3779) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us +I (3789) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000 +I (3819) wifi:AP's beacon interval = 102400 us, DTIM period = 1 +I (3849) wifi:idx:0 (ifx:0, 9c:3a:9a:04:18:92), tid:0, ssn:0, winSize:64 +I (4799) esp_netif_handlers: example_netif_sta ip: 192.168.200.133, mask: 255.255.252.0, gw: 192.168.200.1 +I (4799) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.200.133 +I (5509) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:f612:faff:fe41:a7f4, type: ESP_IP6_ADDR_IS_LINK_LOCAL +I (5509) example_common: Connected to example_netif_sta +I (5519) example_common: - IPv4 address: 192.168.200.133, +I (5519) example_common: - IPv6 address: fe80:0000:0000:0000:f612:faff:fe41:a7f4, type: ESP_IP6_ADDR_IS_LINK_LOCAL +I (5529) wifi:Set ps type: 0, coexist: 0 + +I (5539) ESP_ZB_GATEWAY: Initialize Zigbee stack +I (5549) ESP_ZB_GATEWAY: Device started up in factory-reset mode +I (5549) ESP_ZB_GATEWAY: Start network formation +W (5729) ESP_ZB_GATEWAY: Network(0xb8e9) closed, devices joining not allowed. +I (5729) ESP_ZB_GATEWAY: Formed network successfully (Extended PAN ID: 60:55:f9:ff:fe:f7:73:e8, PAN ID: 0xb8e9, Channel:13, Short Address: 0x0000) +I (6339) ESP_ZB_GATEWAY: Network(0xb8e9) is open for 180 seconds +I (6339) ESP_ZB_GATEWAY: Network steering started ``` ## Gateway Functions - * After Zigbee gateway starts up, it will read MAC ieee address and Zigbee stack version number from the Zigbee rcp and start working together with Zigbee rcp via UART communication to form a Zigbee network - * More Gateway functionalities supporting Wi-Fi interaction will come later + * When the device starts up, it will attempt to connect to a Wi-Fi network and then interface with the OT-RCP via UART to form a Zigbee network. + * For more Gateway functionalities, please refer to [matter zigbee bridge](https://github.com/espressif/esp-matter/tree/main/examples/bridge_apps/zigbee_bridge/) and [Rainmaker Zigbee Gateway](https://github.com/espressif/esp-rainmaker/tree/master/examples/zigbee_gateway) examples. ## Troubleshooting diff --git a/examples/zigbee/esp_zigbee_gateway/main/esp_zigbee_gateway.c b/examples/zigbee/esp_zigbee_gateway/main/esp_zigbee_gateway.c index b5fedf4587a2..a0eb05f9500d 100644 --- a/examples/zigbee/esp_zigbee_gateway/main/esp_zigbee_gateway.c +++ b/examples/zigbee/esp_zigbee_gateway/main/esp_zigbee_gateway.c @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * SPDX-License-Identifier: CC0-1.0 + * SPDX-License-Identifier: LicenseRef-Included * * Zigbee Gateway Example * @@ -17,20 +17,17 @@ #include "freertos/task.h" #include "driver/usb_serial_jtag.h" #include "esp_coexist.h" +#include "esp_check.h" #include "esp_log.h" #include "esp_netif.h" +#include "esp_vfs_dev.h" +#include "esp_vfs_usb_serial_jtag.h" #include "esp_vfs_eventfd.h" #include "esp_wifi.h" #include "nvs_flash.h" #include "protocol_examples_common.h" #include "esp_zigbee_gateway.h" - -#include "driver/uart_vfs.h" -#include "driver/usb_serial_jtag_vfs.h" - -#if (!defined ZB_MACSPLIT_HOST && defined ZB_MACSPLIT_DEVICE) -#error Only Zigbee gateway host device should be defined -#endif +#include "zb_config_platform.h" static const char *TAG = "ESP_ZB_GATEWAY"; @@ -61,7 +58,7 @@ esp_err_t esp_zb_gateway_console_init(void) static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); + ESP_RETURN_ON_FALSE(esp_zb_bdb_start_top_level_commissioning(mode_mask) == ESP_OK, , TAG, "Failed to start Zigbee bdb commissioning"); } void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) @@ -70,18 +67,19 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) esp_err_t err_status = signal_struct->esp_err_status; esp_zb_app_signal_type_t sig_type = *p_sg_p; esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; - esp_zb_zdo_signal_macsplit_dev_boot_params_t *rcp_version = NULL; switch (sig_type) { case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - ESP_LOGI(TAG, "Zigbee stack initialized"); +#if CONFIG_EXAMPLE_CONNECT_WIFI +#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE + esp_coex_wifi_i154_enable(); +#endif /* CONFIG_ESP_COEX_SW_COEXIST_ENABLE */ + ESP_RETURN_ON_FALSE(example_connect() == ESP_OK, , TAG, "Failed to connect to Wi-Fi"); + ESP_RETURN_ON_FALSE(esp_wifi_set_ps(WIFI_PS_MIN_MODEM) == ESP_OK, , TAG, "Failed to set Wi-Fi minimum modem power save type"); +#endif /* CONFIG_EXAMPLE_CONNECT_WIFI */ + ESP_LOGI(TAG, "Initialize Zigbee stack"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); break; - case ESP_ZB_MACSPLIT_DEVICE_BOOT: - ESP_LOGI(TAG, "Zigbee rcp device booted"); - rcp_version = (esp_zb_zdo_signal_macsplit_dev_boot_params_t *)esp_zb_app_signal_get_params(p_sg_p); - ESP_LOGI(TAG, "Running RCP Version: %s", rcp_version->version_str); - break; case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: if (err_status == ESP_OK) { @@ -90,6 +88,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) ESP_LOGI(TAG, "Start network formation"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); } else { + esp_zb_bdb_open_network(180); ESP_LOGI(TAG, "Device rebooted"); } } else { @@ -128,6 +127,10 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) } } break; + case ESP_ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY: + ESP_LOGI(TAG, "Production configuration is %s", err_status == ESP_OK ? "ready" : "not present"); + esp_zb_set_node_descriptor_manufacturer_code(ESP_MANUFACTURER_CODE); + break; default: ESP_LOGI(TAG, "ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); @@ -141,8 +144,25 @@ static void esp_zb_task(void *pvParameters) esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZC_CONFIG(); esp_zb_init(&zb_nwk_cfg); esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); + esp_zb_ep_list_t *ep_list = esp_zb_ep_list_create(); + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_endpoint_config_t endpoint_config = { + .endpoint = ESP_ZB_GATEWAY_ENDPOINT, + .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .app_device_id = ESP_ZB_HA_REMOTE_CONTROL_DEVICE_ID, + .app_device_version = 0, + }; + + esp_zb_attribute_list_t *basic_cluser = esp_zb_basic_cluster_create(NULL); + esp_zb_basic_cluster_add_attr(basic_cluser, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, ESP_MANUFACTURER_NAME); + esp_zb_basic_cluster_add_attr(basic_cluser, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, ESP_MODEL_IDENTIFIER); + esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluser, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_ep_list_add_gateway_ep(ep_list, cluster_list, endpoint_config); + esp_zb_device_register(ep_list); ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); + esp_zb_stack_main_loop(); + vTaskDelete(NULL); } void app_main(void) @@ -159,14 +179,5 @@ void app_main(void) #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG ESP_ERROR_CHECK(esp_zb_gateway_console_init()); #endif -#if CONFIG_EXAMPLE_CONNECT_WIFI - ESP_ERROR_CHECK(example_connect()); -#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE - ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_MIN_MODEM)); - esp_coex_wifi_i154_enable(); -#else - ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); -#endif -#endif - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); + xTaskCreate(esp_zb_task, "Zigbee_main", 8192, NULL, 5, NULL); } diff --git a/examples/zigbee/esp_zigbee_gateway/main/esp_zigbee_gateway.h b/examples/zigbee/esp_zigbee_gateway/main/esp_zigbee_gateway.h index 2bc61f0e2bd5..03a880bb59c2 100644 --- a/examples/zigbee/esp_zigbee_gateway/main/esp_zigbee_gateway.h +++ b/examples/zigbee/esp_zigbee_gateway/main/esp_zigbee_gateway.h @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * SPDX-License-Identifier: CC0-1.0 + * SPDX-License-Identifier: LicenseRef-Included * * Zigbee Gateway Example * @@ -19,6 +19,17 @@ #define MAX_CHILDREN 10 /* the max amount of connected devices */ #define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ #define ESP_ZB_PRIMARY_CHANNEL_MASK (1l << 13) /* Zigbee primary channel mask use in the example */ +#define ESP_ZB_GATEWAY_ENDPOINT 1 /* Gateway endpoint identifier */ +#define APP_PROD_CFG_CURRENT_VERSION 0x0001 /* Production configuration version */ + +/* Basic manufacturer information */ +#define ESP_MANUFACTURER_CODE 0x131B /* Customized manufacturer code */ +#define ESP_MANUFACTURER_NAME "\x09""ESPRESSIF" /* Customized manufacturer name */ +#define ESP_MODEL_IDENTIFIER "\x07"CONFIG_IDF_TARGET /* Customized model identifier */ + +/* RCP connection pins */ +#define HOST_RX_PIN_TO_RCP_TX 4 +#define HOST_TX_PIN_TO_RCP_RX 5 #define ESP_ZB_ZC_CONFIG() \ { \ @@ -32,17 +43,17 @@ #if CONFIG_ZB_RADIO_NATIVE #define ESP_ZB_DEFAULT_RADIO_CONFIG() \ { \ - .radio_mode = RADIO_MODE_NATIVE, \ + .radio_mode = ZB_RADIO_MODE_NATIVE, \ } #else #define ESP_ZB_DEFAULT_RADIO_CONFIG() \ { \ - .radio_mode = RADIO_MODE_UART_RCP, \ + .radio_mode = ZB_RADIO_MODE_UART_RCP, \ .radio_uart_config = { \ .port = 1, \ .uart_config = \ { \ - .baud_rate = 115200, \ + .baud_rate = 460800, \ .data_bits = UART_DATA_8_BITS, \ .parity = UART_PARITY_DISABLE, \ .stop_bits = UART_STOP_BITS_1, \ @@ -50,13 +61,13 @@ .rx_flow_ctrl_thresh = 0, \ .source_clk = UART_SCLK_DEFAULT, \ }, \ - .rx_pin = 4, \ - .tx_pin = 5, \ + .rx_pin = HOST_RX_PIN_TO_RCP_TX, \ + .tx_pin = HOST_TX_PIN_TO_RCP_RX, \ }, \ } #endif #define ESP_ZB_DEFAULT_HOST_CONFIG() \ { \ - .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ + .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, \ } diff --git a/examples/zigbee/esp_zigbee_gateway/main/idf_component.yml b/examples/zigbee/esp_zigbee_gateway/main/idf_component.yml index 5346a089ab53..d3a34266983c 100644 --- a/examples/zigbee/esp_zigbee_gateway/main/idf_component.yml +++ b/examples/zigbee/esp_zigbee_gateway/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: - espressif/esp-zboss-lib: "1.0.9" - espressif/esp-zigbee-lib: "1.0.9" + espressif/esp-zboss-lib: "~1.6.0" + espressif/esp-zigbee-lib: "~1.6.0" ## Required IDF version idf: version: ">=5.0.0" diff --git a/examples/zigbee/esp_zigbee_rcp/CMakeLists.txt b/examples/zigbee/esp_zigbee_rcp/CMakeLists.txt deleted file mode 100644 index 6cf79c44b312..000000000000 --- a/examples/zigbee/esp_zigbee_rcp/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# For more information about build system see -# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.16) -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(esp_zigbee_rcp) diff --git a/examples/zigbee/esp_zigbee_rcp/README.md b/examples/zigbee/esp_zigbee_rcp/README.md deleted file mode 100644 index a930b7fc814f..000000000000 --- a/examples/zigbee/esp_zigbee_rcp/README.md +++ /dev/null @@ -1,34 +0,0 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | - -# Rcp Example - -This test code shows how to configure Zigbee rcp (radio co-processor) device. Rcp doesn't function alone, it needs to work together with Zigbee gateway (see [esp_zigbee_gateway example](../esp_zigbee_gateway)) - -## Hardware Required - -* One development board with ESP32-H2 SoC acting as Zigbee rcp (loaded with esp_zigbee_rcp example) -* A USB cable for power supply and programming -* Choose ESP32 or ESP32-S3 as Zigbee gateway. The connection and setup refer to the Zigbee gateway example for setup details (see [esp_zigbee_gateway example](../esp_zigbee_gateway)) -* TX, RX pin can be also configured by user in esp_zigbee_rcp.h - -## Configure the project - -Before project configuration and build, make sure to set the correct chip target using `idf.py --preview set-target TARGET` command. - -## Erase the NVRAM - -Before flash it to the board, it is recommended to erase NVRAM if user doesn't want to keep the previous examples or other projects stored info using `idf.py -p PORT erase-flash` - -## Build and Flash - -Build the project, flash it to the board by running `idf.py -p build flash` - -## Rcp Functions - - * After rcp starts up, it will send its own MAC ieee address and Zigbee stack version number to the Zigbee gateway and start working together with Zigbee gateway via UART communication - * For more log info please see Zigbee gateway side - -## Troubleshooting - -For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon diff --git a/examples/zigbee/esp_zigbee_rcp/main/CMakeLists.txt b/examples/zigbee/esp_zigbee_rcp/main/CMakeLists.txt deleted file mode 100644 index fe9c25c12f16..000000000000 --- a/examples/zigbee/esp_zigbee_rcp/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "esp_zigbee_rcp.c" - INCLUDE_DIRS ".") diff --git a/examples/zigbee/esp_zigbee_rcp/main/esp_zigbee_rcp.c b/examples/zigbee/esp_zigbee_rcp/main/esp_zigbee_rcp.c deleted file mode 100644 index 2c419ab68db6..000000000000 --- a/examples/zigbee/esp_zigbee_rcp/main/esp_zigbee_rcp.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: CC0-1.0 - * - * Zigbee RCP Example - * - * This example code is in the Public Domain (or CC0 licensed, at your option.) - * - * Unless required by applicable law or agreed to in writing, this - * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. - */ - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "zb_scheduler.h" -#include "esp_zigbee_rcp.h" - -#if (defined ZB_MACSPLIT_HOST && !defined ZB_MACSPLIT_DEVICE) -#error Only Zigbee rcp device should be defined -#endif -static const char *TAG = "ESP_ZB_RCP"; - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) -{ - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = *p_sg_p; - if (err_status == ESP_OK) { - } else if (sig_type == ESP_ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY) { - ESP_LOGI(TAG, "Production config is not present or invalid"); - } else { - ESP_LOGI(TAG, "Device started FAILED status %d", err_status); - } -} - -static void esp_zb_task(void *pvParameters) -{ - esp_zb_rcp_init(); - esp_zb_rcp_main_loop_iteration(); -} - -void app_main(void) -{ - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - ESP_ERROR_CHECK(nvs_flash_init()); - /* load Zigbee rcp platform config to initialization */ - esp_zb_macsplit_set_version(RCP_COMPILE_DEFINE); - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} diff --git a/examples/zigbee/esp_zigbee_rcp/main/idf_component.yml b/examples/zigbee/esp_zigbee_rcp/main/idf_component.yml deleted file mode 100644 index c186c3c8cad5..000000000000 --- a/examples/zigbee/esp_zigbee_rcp/main/idf_component.yml +++ /dev/null @@ -1,7 +0,0 @@ -## IDF Component Manager Manifest File -dependencies: - espressif/esp-zboss-lib: "1.0.9" - espressif/esp-zigbee-lib: "1.0.9" - ## Required IDF version - idf: - version: ">=5.0.0" diff --git a/examples/zigbee/esp_zigbee_rcp/sdkconfig.defaults b/examples/zigbee/esp_zigbee_rcp/sdkconfig.defaults deleted file mode 100644 index b337975d5c93..000000000000 --- a/examples/zigbee/esp_zigbee_rcp/sdkconfig.defaults +++ /dev/null @@ -1,17 +0,0 @@ -# -# Partition Table -# -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_OFFSET=0x8000 -CONFIG_PARTITION_TABLE_MD5=y -# end of Partition Table - -# -# ZBOSS Source -# -CONFIG_ZB_ENABLED=y -CONFIG_ZB_RCP=y -# end of ZBOSS Source -# end of Component config diff --git a/examples/zigbee/light_sample/HA_on_off_light/README.md b/examples/zigbee/light_sample/HA_on_off_light/README.md index a22052d60866..1078416c3bac 100644 --- a/examples/zigbee/light_sample/HA_on_off_light/README.md +++ b/examples/zigbee/light_sample/HA_on_off_light/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | -------- | # Light Bulb Example @@ -34,24 +34,28 @@ Build the project, flash it to the board, and start the monitor tool to view the As you run the example, you will see the following log: ``` -I (394) main_task: Calling app_main() -I (404) gpio: GPIO[8]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 -I (404) phy_init: phy_version 220,2dbbbe7,Sep 25 2023,20:39:25 -I (464) phy: libbtbb version: 90c587c, Sep 25 2023, 20:39:57 -I (474) ESP_ZB_COLOR_DIMM_LIGHT: ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL -I (474) ESP_ZB_COLOR_DIMM_LIGHT: Zigbee stack initialized -I (484) ESP_ZB_COLOR_DIMM_LIGHT: Start network steering -I (484) main_task: Returned from app_main() -I (9614) ESP_ZB_COLOR_DIMM_LIGHT: ZDO signal: NWK Permit Join (0x36), status: ESP_OK -I (9834) ESP_ZB_COLOR_DIMM_LIGHT: ZDO signal: NWK Permit Join (0x36), status: ESP_OK -I (9834) ESP_ZB_COLOR_DIMM_LIGHT: Joined network successfully (Extended PAN ID: 60:55:f9:00:00:f6:07:b4, PAN ID: 0x2a74, Channel:13) -I (32944) ESP_ZB_COLOR_DIMM_LIGHT: Received message: endpoint(10), cluster(0x6), attribute(0x0), data size(1) -I (32944) ESP_ZB_COLOR_DIMM_LIGHT: Light sets to On -I (33984) ESP_ZB_COLOR_DIMM_LIGHT: Received message: endpoint(10), cluster(0x6), attribute(0x0), data size(1) -I (33984) ESP_ZB_COLOR_DIMM_LIGHT: Light sets to Off -I (35304) ESP_ZB_COLOR_DIMM_LIGHT: ZDO signal: NLME Status Indication (0x32), status: ESP_OK -I (35534) ESP_ZB_COLOR_DIMM_LIGHT: Received message: endpoint(10), cluster(0x6), attribute(0x0), data size(1) -I (35534) ESP_ZB_COLOR_DIMM_LIGHT: Light sets to On +I (403) app_start: Starting scheduler on CPU0 +I (408) main_task: Started on CPU0 +I (408) main_task: Calling app_main() +I (428) phy: phy_version: 230,2, 9aae6ea, Jan 15 2024, 11:17:12 +I (428) phy: libbtbb version: 944f18e, Jan 15 2024, 11:17:25 +I (438) main_task: Returned from app_main() +I (548) ESP_ZB_ON_OFF_LIGHT: ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL +I (548) ESP_ZB_ON_OFF_LIGHT: Initialize Zigbee stack +W (548) rmt: channel resolution loss, real=10666666 +I (558) gpio: GPIO[8]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 +I (548) ESP_ZB_ON_OFF_LIGHT: Deferred driver initialization successful +I (568) ESP_ZB_ON_OFF_LIGHT: Device started up in factory-reset mode +I (578) ESP_ZB_ON_OFF_LIGHT: Start network steering +I (3558) ESP_ZB_ON_OFF_LIGHT: Joined network successfully (Extended PAN ID: 74:4d:bd:ff:fe:63:f7:30, PAN ID: 0x13af, Channel:13, Short Address: 0x7c16) +I (10238) ESP_ZB_ON_OFF_LIGHT: Received message: endpoint(10), cluster(0x6), attribute(0x0), data size(1) +I (10238) ESP_ZB_ON_OFF_LIGHT: Light sets to On +I (10798) ESP_ZB_ON_OFF_LIGHT: Received message: endpoint(10), cluster(0x6), attribute(0x0), data size(1) +I (10798) ESP_ZB_ON_OFF_LIGHT: Light sets to Off +I (11228) ESP_ZB_ON_OFF_LIGHT: Received message: endpoint(10), cluster(0x6), attribute(0x0), data size(1) +I (11228) ESP_ZB_ON_OFF_LIGHT: Light sets to On +I (11618) ESP_ZB_ON_OFF_LIGHT: Received message: endpoint(10), cluster(0x6), attribute(0x0), data size(1) +I (11618) ESP_ZB_ON_OFF_LIGHT: Light sets to Off ``` ## Light Control Functions diff --git a/examples/zigbee/light_sample/HA_on_off_light/main/CMakeLists.txt b/examples/zigbee/light_sample/HA_on_off_light/main/CMakeLists.txt index 61bef7bbbef9..15343efb83ce 100644 --- a/examples/zigbee/light_sample/HA_on_off_light/main/CMakeLists.txt +++ b/examples/zigbee/light_sample/HA_on_off_light/main/CMakeLists.txt @@ -1,6 +1,4 @@ idf_component_register( - SRCS - "esp_zb_light.c" - "light_driver.c" - INCLUDE_DIRS "." + SRC_DIRS "." "../../../common/zcl_utility/src" + INCLUDE_DIRS "." "../../../common/zcl_utility/include" ) diff --git a/examples/zigbee/light_sample/HA_on_off_light/main/esp_zb_light.c b/examples/zigbee/light_sample/HA_on_off_light/main/esp_zb_light.c index a77ac5dc94f6..4f3256c5578c 100644 --- a/examples/zigbee/light_sample/HA_on_off_light/main/esp_zb_light.c +++ b/examples/zigbee/light_sample/HA_on_off_light/main/esp_zb_light.c @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * SPDX-License-Identifier: CC0-1.0 + * SPDX-License-Identifier: LicenseRef-Included * * Zigbee HA_on_off_light Example * @@ -11,7 +11,6 @@ * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. */ - #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_check.h" @@ -26,9 +25,15 @@ static const char *TAG = "ESP_ZB_ON_OFF_LIGHT"; /********************* Define functions **************************/ +static esp_err_t deferred_driver_init(void) +{ + light_driver_init(LIGHT_DEFAULT_OFF); + return ESP_OK; +} + static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); + ESP_RETURN_ON_FALSE(esp_zb_bdb_start_top_level_commissioning(mode_mask) == ESP_OK, , TAG, "Failed to start Zigbee commissioning"); } void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) @@ -38,12 +43,13 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) esp_zb_app_signal_type_t sig_type = *p_sg_p; switch (sig_type) { case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - ESP_LOGI(TAG, "Zigbee stack initialized"); + ESP_LOGI(TAG, "Initialize Zigbee stack"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); break; case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: if (err_status == ESP_OK) { + ESP_LOGI(TAG, "Deferred driver initialization %s", deferred_driver_init() ? "failed" : "successful"); ESP_LOGI(TAG, "Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); if (esp_zb_bdb_is_factory_new()) { ESP_LOGI(TAG, "Start network steering"); @@ -119,11 +125,17 @@ static void esp_zb_task(void *pvParameters) esp_zb_init(&zb_nwk_cfg); esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); esp_zb_ep_list_t *esp_zb_on_off_light_ep = esp_zb_on_off_light_ep_create(HA_ESP_LIGHT_ENDPOINT, &light_cfg); + zcl_basic_manufacturer_info_t info = { + .manufacturer_name = ESP_MANUFACTURER_NAME, + .model_identifier = ESP_MODEL_IDENTIFIER, + }; + + esp_zcl_utility_add_ep_basic_manufacturer_info(esp_zb_on_off_light_ep, HA_ESP_LIGHT_ENDPOINT, &info); esp_zb_device_register(esp_zb_on_off_light_ep); esp_zb_core_action_handler_register(zb_action_handler); esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); + esp_zb_stack_main_loop(); } void app_main(void) @@ -134,6 +146,5 @@ void app_main(void) }; ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - light_driver_init(LIGHT_DEFAULT_OFF); xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); } diff --git a/examples/zigbee/light_sample/HA_on_off_light/main/esp_zb_light.h b/examples/zigbee/light_sample/HA_on_off_light/main/esp_zb_light.h index 5def811a87fb..3f4a751c6729 100644 --- a/examples/zigbee/light_sample/HA_on_off_light/main/esp_zb_light.h +++ b/examples/zigbee/light_sample/HA_on_off_light/main/esp_zb_light.h @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * SPDX-License-Identifier: CC0-1.0 + * SPDX-License-Identifier: LicenseRef-Included * * Zigbee HA_on_off_light Example * @@ -14,13 +14,18 @@ #include "esp_zigbee_core.h" #include "light_driver.h" +#include "zcl_utility.h" /* Zigbee configuration */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN -#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ -#define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ +#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ +#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN /* aging timeout of device */ +#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ +#define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ +#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ + +/* Basic manufacturer information */ +#define ESP_MANUFACTURER_NAME "\x09""ESPRESSIF" /* Customized manufacturer name */ +#define ESP_MODEL_IDENTIFIER "\x07"CONFIG_IDF_TARGET /* Customized model identifier */ #define ESP_ZB_ZED_CONFIG() \ { \ @@ -34,10 +39,10 @@ #define ESP_ZB_DEFAULT_RADIO_CONFIG() \ { \ - .radio_mode = RADIO_MODE_NATIVE, \ + .radio_mode = ZB_RADIO_MODE_NATIVE, \ } #define ESP_ZB_DEFAULT_HOST_CONFIG() \ { \ - .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ + .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, \ } diff --git a/examples/zigbee/light_sample/HA_on_off_light/main/idf_component.yml b/examples/zigbee/light_sample/HA_on_off_light/main/idf_component.yml index 8578e73e678c..198da019c3d5 100644 --- a/examples/zigbee/light_sample/HA_on_off_light/main/idf_component.yml +++ b/examples/zigbee/light_sample/HA_on_off_light/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: - espressif/esp-zboss-lib: "1.0.9" - espressif/esp-zigbee-lib: "1.0.9" + espressif/esp-zboss-lib: "~1.6.0" + espressif/esp-zigbee-lib: "~1.6.0" espressif/led_strip: "~2.0.0" ## Required IDF version idf: diff --git a/examples/zigbee/light_sample/HA_on_off_switch/README.md b/examples/zigbee/light_sample/HA_on_off_switch/README.md index b02dc682ecec..61f4128bf1a8 100644 --- a/examples/zigbee/light_sample/HA_on_off_switch/README.md +++ b/examples/zigbee/light_sample/HA_on_off_switch/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | -------- | # Light Switch Example @@ -34,31 +34,34 @@ Build the project, flash it to the board, and start the monitor tool to view the As you run the example, you will see the following log: ``` -I (388) main_task: Calling app_main() -I (398) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:2 -I (398) phy_init: phy_version 220,2dbbbe7,Sep 25 2023,20:39:25 -I (478) phy: libbtbb version: 90c587c, Sep 25 2023, 20:39:57 -I (488) ESP_ZB_ON_OFF_SWITCH: ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL -I (488) ESP_ZB_ON_OFF_SWITCH: Zigbee stack initialized -I (488) ESP_ZB_ON_OFF_SWITCH: Start network formation -I (498) main_task: Returned from app_main() -I (998) ESP_ZB_ON_OFF_SWITCH: ZDO signal: NWK Permit Join (0x36), status: ESP_OK -I (998) ESP_ZB_ON_OFF_SWITCH: Formed network successfully (Extended PAN ID: 60:55:f9:00:00:f6:07:b4, PAN ID: 0x2a74, Channel:13) -I (1468) ESP_ZB_ON_OFF_SWITCH: ZDO signal: NWK Permit Join (0x36), status: ESP_OK -I (1468) ESP_ZB_ON_OFF_SWITCH: Network steering started -I (14228) ESP_ZB_ON_OFF_SWITCH: ZDO signal: NWK Device Associated (0x12), status: ESP_OK -I (14728) ESP_ZB_ON_OFF_SWITCH: ZDO signal: ZDO Device Update (0x30), status: ESP_OK -I (14788) ESP_ZB_ON_OFF_SWITCH: New device commissioned or rejoined (short: 0xe399) -I (14858) ESP_ZB_ON_OFF_SWITCH: Found light -I (14858) ESP_ZB_ON_OFF_SWITCH: Try to bind On/Off -I (14858) ESP_ZB_ON_OFF_SWITCH: Bound successfully! -I (14858) ESP_ZB_ON_OFF_SWITCH: The light originating from address(0xe399) on endpoint(10) -I (15338) ESP_ZB_ON_OFF_SWITCH: ZDO signal: ZDO Device Authorized (0x2f), status: ESP_OK -I (15408) ESP_ZB_ON_OFF_SWITCH: ZDO signal: NWK Permit Join (0x36), status: ESP_OK -I (35838) ESP_ZB_ON_OFF_SWITCH: ZDO signal: NLME Status Indication (0x32), status: ESP_OK -I (38548) ESP_ZB_ON_OFF_SWITCH: Send 'on_off toggle' command -I (39598) ESP_ZB_ON_OFF_SWITCH: Send 'on_off toggle' command -I (41148) ESP_ZB_ON_OFF_SWITCH: Send 'on_off toggle' command +I (441) main_task: Started on CPU0 +I (441) main_task: Calling app_main() +I (461) phy: phy_version: 230,2, 9aae6ea, Jan 15 2024, 11:17:12 +I (461) phy: libbtbb version: 944f18e, Jan 15 2024, 11:17:25 +I (471) main_task: Returned from app_main() +I (601) ESP_ZB_ON_OFF_SWITCH: ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL +I (601) ESP_ZB_ON_OFF_SWITCH: Initialize Zigbee stack +I (611) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:2 +I (611) ESP_ZB_ON_OFF_SWITCH: Deferred driver initialization successful +I (621) ESP_ZB_ON_OFF_SWITCH: Device started up in factory-reset mode +I (621) ESP_ZB_ON_OFF_SWITCH: Start network formation +W (781) ESP_ZB_ON_OFF_SWITCH: Network(0x13af) closed, devices joining not allowed. +I (781) ESP_ZB_ON_OFF_SWITCH: Formed network successfully (Extended PAN ID: 74:4d:bd:ff:fe:63:f7:30, PAN ID: 0x13af, Channel:13, Short Address: 0x0000) +I (1391) ESP_ZB_ON_OFF_SWITCH: Network(0x13af) is open for 180 seconds +I (1391) ESP_ZB_ON_OFF_SWITCH: Network steering started +I (9561) ESP_ZB_ON_OFF_SWITCH: ZDO signal: NWK Device Associated (0x12), status: ESP_OK +I (9561) ESP_ZB_ON_OFF_SWITCH: ZDO signal: ZDO Device Update (0x30), status: ESP_OK +I (9601) ESP_ZB_ON_OFF_SWITCH: New device commissioned or rejoined (short: 0x7c16) +I (9671) ESP_ZB_ON_OFF_SWITCH: Found light +I (9671) ESP_ZB_ON_OFF_SWITCH: Try to bind On/Off +I (9681) ESP_ZB_ON_OFF_SWITCH: Bound successfully! +I (9681) ESP_ZB_ON_OFF_SWITCH: The light originating from address(0x7c16) on endpoint(10) +I (9751) ESP_ZB_ON_OFF_SWITCH: ZDO signal: ZDO Device Authorized (0x2f), status: ESP_OK +I (9781) ESP_ZB_ON_OFF_SWITCH: Network(0x13af) is open for 180 seconds +I (16451) ESP_ZB_ON_OFF_SWITCH: Send 'on_off toggle' command +I (17011) ESP_ZB_ON_OFF_SWITCH: Send 'on_off toggle' command +I (17441) ESP_ZB_ON_OFF_SWITCH: Send 'on_off toggle' command +I (17831) ESP_ZB_ON_OFF_SWITCH: Send 'on_off toggle' command ``` ## Light Control Functions diff --git a/examples/zigbee/light_sample/HA_on_off_switch/main/CMakeLists.txt b/examples/zigbee/light_sample/HA_on_off_switch/main/CMakeLists.txt index b996c0f78a5e..15343efb83ce 100644 --- a/examples/zigbee/light_sample/HA_on_off_switch/main/CMakeLists.txt +++ b/examples/zigbee/light_sample/HA_on_off_switch/main/CMakeLists.txt @@ -1,6 +1,4 @@ idf_component_register( - SRCS - "esp_zb_switch.c" - "switch_driver.c" - INCLUDE_DIRS "." + SRC_DIRS "." "../../../common/zcl_utility/src" + INCLUDE_DIRS "." "../../../common/zcl_utility/include" ) diff --git a/examples/zigbee/light_sample/HA_on_off_switch/main/esp_zb_switch.c b/examples/zigbee/light_sample/HA_on_off_switch/main/esp_zb_switch.c index 2750377202b4..64459f04b310 100644 --- a/examples/zigbee/light_sample/HA_on_off_switch/main/esp_zb_switch.c +++ b/examples/zigbee/light_sample/HA_on_off_switch/main/esp_zb_switch.c @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * SPDX-License-Identifier: CC0-1.0 + * SPDX-License-Identifier: LicenseRef-Included * * Zigbee HA_on_off_switch Example * @@ -15,6 +15,8 @@ #include "string.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp_err.h" +#include "esp_check.h" #include "esp_log.h" #include "nvs_flash.h" #include "ha/esp_zigbee_ha_standard.h" @@ -35,7 +37,7 @@ static switch_func_pair_t button_func_pair[] = { static const char *TAG = "ESP_ZB_ON_OFF_SWITCH"; -static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) +static void zb_buttons_handler(switch_func_pair_t *button_func_pair) { if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { /* implemented light switch toggle functionality */ @@ -43,14 +45,23 @@ static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) cmd_req.zcl_basic_cmd.src_endpoint = HA_ONOFF_SWITCH_ENDPOINT; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - ESP_EARLY_LOGI(TAG, "Send 'on_off toggle' command"); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + ESP_EARLY_LOGI(TAG, "Send 'on_off toggle' command"); } } +static esp_err_t deferred_driver_init(void) +{ + ESP_RETURN_ON_FALSE(switch_driver_init(button_func_pair, PAIR_SIZE(button_func_pair), zb_buttons_handler), ESP_FAIL, TAG, + "Failed to initialize switch driver"); + return ESP_OK; +} + static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); + ESP_RETURN_ON_FALSE(esp_zb_bdb_start_top_level_commissioning(mode_mask) == ESP_OK, , TAG, "Failed to start Zigbee bdb commissioning"); } static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) @@ -94,17 +105,19 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; switch (sig_type) { case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - ESP_LOGI(TAG, "Zigbee stack initialized"); + ESP_LOGI(TAG, "Initialize Zigbee stack"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); break; case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: if (err_status == ESP_OK) { + ESP_LOGI(TAG, "Deferred driver initialization %s", deferred_driver_init() ? "failed" : "successful"); ESP_LOGI(TAG, "Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); if (esp_zb_bdb_is_factory_new()) { ESP_LOGI(TAG, "Start network formation"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); } else { + esp_zb_bdb_open_network(180); ESP_LOGI(TAG, "Device rebooted"); } } else { @@ -161,10 +174,16 @@ static void esp_zb_task(void *pvParameters) esp_zb_init(&zb_nwk_cfg); esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); esp_zb_ep_list_t *esp_zb_on_off_switch_ep = esp_zb_on_off_switch_ep_create(HA_ONOFF_SWITCH_ENDPOINT, &switch_cfg); + zcl_basic_manufacturer_info_t info = { + .manufacturer_name = ESP_MANUFACTURER_NAME, + .model_identifier = ESP_MODEL_IDENTIFIER, + }; + + esp_zcl_utility_add_ep_basic_manufacturer_info(esp_zb_on_off_switch_ep, HA_ONOFF_SWITCH_ENDPOINT, &info); esp_zb_device_register(esp_zb_on_off_switch_ep); esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); + esp_zb_stack_main_loop(); } void app_main(void) @@ -175,6 +194,6 @@ void app_main(void) }; ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - switch_driver_init(button_func_pair, PAIR_SIZE(button_func_pair), esp_zb_buttons_handler); + xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); } diff --git a/examples/zigbee/light_sample/HA_on_off_switch/main/esp_zb_switch.h b/examples/zigbee/light_sample/HA_on_off_switch/main/esp_zb_switch.h index d4d95a0a0e43..32a6dc9edf08 100644 --- a/examples/zigbee/light_sample/HA_on_off_switch/main/esp_zb_switch.h +++ b/examples/zigbee/light_sample/HA_on_off_switch/main/esp_zb_switch.h @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * - * SPDX-License-Identifier: CC0-1.0 + * SPDX-License-Identifier: LicenseRef-Included * * Zigbee HA_on_off_switch Example * @@ -13,12 +13,17 @@ */ #include "esp_zigbee_core.h" #include "switch_driver.h" +#include "zcl_utility.h" /* Zigbee configuration */ -#define MAX_CHILDREN 10 /* the max amount of connected devices */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define HA_ONOFF_SWITCH_ENDPOINT 1 /* esp light switch device endpoint */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK (1l << 13) /* Zigbee primary channel mask use in the example */ +#define MAX_CHILDREN 10 /* the max amount of connected devices */ +#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ +#define HA_ONOFF_SWITCH_ENDPOINT 1 /* esp light switch device endpoint */ +#define ESP_ZB_PRIMARY_CHANNEL_MASK (1l << 13) /* Zigbee primary channel mask use in the example */ + +/* Basic manufacturer information */ +#define ESP_MANUFACTURER_NAME "\x09""ESPRESSIF" /* Customized manufacturer name */ +#define ESP_MODEL_IDENTIFIER "\x07"CONFIG_IDF_TARGET /* Customized model identifier */ #define ESP_ZB_ZC_CONFIG() \ { \ @@ -31,10 +36,10 @@ #define ESP_ZB_DEFAULT_RADIO_CONFIG() \ { \ - .radio_mode = RADIO_MODE_NATIVE, \ + .radio_mode = ZB_RADIO_MODE_NATIVE, \ } #define ESP_ZB_DEFAULT_HOST_CONFIG() \ { \ - .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ + .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, \ } diff --git a/examples/zigbee/light_sample/HA_on_off_switch/main/idf_component.yml b/examples/zigbee/light_sample/HA_on_off_switch/main/idf_component.yml index c186c3c8cad5..ad32c63b48e5 100644 --- a/examples/zigbee/light_sample/HA_on_off_switch/main/idf_component.yml +++ b/examples/zigbee/light_sample/HA_on_off_switch/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: - espressif/esp-zboss-lib: "1.0.9" - espressif/esp-zigbee-lib: "1.0.9" + espressif/esp-zboss-lib: "~1.6.0" + espressif/esp-zigbee-lib: "~1.6.0" ## Required IDF version idf: version: ">=5.0.0" diff --git a/examples/zigbee/light_sample/HA_on_off_switch/main/switch_driver.c b/examples/zigbee/light_sample/HA_on_off_switch/main/switch_driver.c index 2acf388944e0..8c03708cc854 100644 --- a/examples/zigbee/light_sample/HA_on_off_switch/main/switch_driver.c +++ b/examples/zigbee/light_sample/HA_on_off_switch/main/switch_driver.c @@ -67,7 +67,7 @@ static void IRAM_ATTR gpio_isr_handler(void *arg) } /** - * @brief Enable GPIO (switchs refer to) isr + * @brief Enable GPIO (switches refer to) isr * * @param enabled enable isr if true. */ @@ -159,7 +159,7 @@ static bool switch_driver_gpio_init(switch_func_pair_t *button_func_pair, uint8_ return false; } /* start gpio task */ - xTaskCreate(switch_driver_button_detected, "button_detected", 2048, NULL, 10, NULL); + xTaskCreate(switch_driver_button_detected, "button_detected", 4096, NULL, 10, NULL); /* install gpio isr service */ gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); for (int i = 0; i < button_num; ++i) { diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index e74f913eb543..12da05ef74e8 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -161,6 +161,10 @@ components_not_formatted_permanent: - "/examples/peripherals/dac/dac_continuous/dac_audio/main/audio_example_file.h" # Coredump (generated) - /components/espcoredump/include_core_dump/elf.h + # OpenOCD stub binaries (generated) + - /components/esp_system/openocd_stub_bins/*.inc + - /components/esp_system/openocd_stub_bins/esp32c6/*.inc + - /components/esp_system/openocd_stub_bins/esp32h2/*.inc docs: # Docs directory contains some .inc files, which are not C include files diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 8ef3d3f7c3d8..dced1b1ab5dd 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -499,9 +499,6 @@ components/nvs_flash/src/nvs_pagemanager.hpp components/nvs_flash/src/nvs_partition_lookup.cpp components/nvs_flash/src/nvs_partition_lookup.hpp components/nvs_flash/src/nvs_test_api.h -components/nvs_flash/test_nvs_host/main.cpp -components/nvs_flash/test_nvs_host/sdkconfig.h -components/nvs_flash/test_nvs_host/test_intrusive_list.cpp components/protocomm/include/transports/protocomm_console.h components/protocomm/include/transports/protocomm_httpd.h components/riscv/include/riscv/csr.h @@ -527,33 +524,6 @@ components/soc/esp32/include/soc/touch_sensor_channel.h components/soc/esp32/include/soc/uart_pins.h components/soc/esp32/include/soc/wdev_reg.h components/soc/esp32/ledc_periph.c -components/soc/esp32c3/include/soc/apb_saradc_reg.h -components/soc/esp32c3/include/soc/assist_debug_reg.h -components/soc/esp32c3/include/soc/bb_reg.h -components/soc/esp32c3/include/soc/boot_mode.h -components/soc/esp32c3/include/soc/extmem_reg.h -components/soc/esp32c3/include/soc/fe_reg.h -components/soc/esp32c3/include/soc/gpio_reg.h -components/soc/esp32c3/include/soc/gpio_struct.h -components/soc/esp32c3/include/soc/i2c_reg.h -components/soc/esp32c3/include/soc/interrupt_core0_reg.h -components/soc/esp32c3/include/soc/ledc_reg.h -components/soc/esp32c3/include/soc/nrx_reg.h -components/soc/esp32c3/include/soc/reset_reasons.h -components/soc/esp32c3/include/soc/rtc_i2c_reg.h -components/soc/esp32c3/include/soc/sensitive_reg.h -components/soc/esp32c3/include/soc/sensitive_struct.h -components/soc/esp32c3/include/soc/soc_pins.h -components/soc/esp32c3/include/soc/spi_mem_reg.h -components/soc/esp32c3/include/soc/systimer_reg.h -components/soc/esp32c3/include/soc/systimer_struct.h -components/soc/esp32c3/include/soc/uart_pins.h -components/soc/esp32c3/include/soc/uart_reg.h -components/soc/esp32c3/include/soc/uhci_reg.h -components/soc/esp32c3/include/soc/usb_serial_jtag_reg.h -components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h -components/soc/esp32c3/include/soc/wdev_reg.h -components/soc/esp32c3/interrupts.c components/soc/esp32c3/ledc_periph.c components/soc/esp32s2/adc_periph.c components/soc/esp32s2/include/soc/bb_reg.h @@ -568,63 +538,9 @@ components/soc/esp32s2/include/soc/touch_sensor_pins.h components/soc/esp32s2/include/soc/uart_pins.h components/soc/esp32s2/include/soc/wdev_reg.h components/soc/esp32s2/ledc_periph.c -components/soc/esp32s3/include/soc/apb_saradc_reg.h -components/soc/esp32s3/include/soc/assist_debug_reg.h -components/soc/esp32s3/include/soc/assist_debug_struct.h -components/soc/esp32s3/include/soc/bb_reg.h -components/soc/esp32s3/include/soc/boot_mode.h -components/soc/esp32s3/include/soc/extmem_reg.h -components/soc/esp32s3/include/soc/extmem_struct.h -components/soc/esp32s3/include/soc/fe_reg.h -components/soc/esp32s3/include/soc/gpio_reg.h -components/soc/esp32s3/include/soc/hinf_reg.h -components/soc/esp32s3/include/soc/hinf_struct.h -components/soc/esp32s3/include/soc/host_reg.h -components/soc/esp32s3/include/soc/host_struct.h -components/soc/esp32s3/include/soc/i2c_reg.h -components/soc/esp32s3/include/soc/i2c_struct.h -components/soc/esp32s3/include/soc/interrupt_core0_reg.h -components/soc/esp32s3/include/soc/interrupt_core0_struct.h -components/soc/esp32s3/include/soc/interrupt_core1_reg.h -components/soc/esp32s3/include/soc/interrupt_core1_struct.h -components/soc/esp32s3/include/soc/interrupt_struct.h -components/soc/esp32s3/include/soc/ledc_reg.h -components/soc/esp32s3/include/soc/ledc_struct.h components/soc/esp32s3/include/soc/mpu_caps.h -components/soc/esp32s3/include/soc/nrx_reg.h -components/soc/esp32s3/include/soc/peri_backup_reg.h -components/soc/esp32s3/include/soc/peri_backup_struct.h -components/soc/esp32s3/include/soc/reset_reasons.h -components/soc/esp32s3/include/soc/rtc_i2c_reg.h -components/soc/esp32s3/include/soc/rtc_i2c_struct.h -components/soc/esp32s3/include/soc/rtc_io_reg.h -components/soc/esp32s3/include/soc/rtc_io_struct.h -components/soc/esp32s3/include/soc/sdmmc_pins.h -components/soc/esp32s3/include/soc/sdmmc_reg.h -components/soc/esp32s3/include/soc/sensitive_reg.h -components/soc/esp32s3/include/soc/sensitive_struct.h -components/soc/esp32s3/include/soc/soc_ulp.h -components/soc/esp32s3/include/soc/spi_mem_reg.h -components/soc/esp32s3/include/soc/spi_mem_struct.h -components/soc/esp32s3/include/soc/spi_reg.h -components/soc/esp32s3/include/soc/spi_struct.h -components/soc/esp32s3/include/soc/syscon_struct.h -components/soc/esp32s3/include/soc/system_reg.h -components/soc/esp32s3/include/soc/system_struct.h -components/soc/esp32s3/include/soc/systimer_reg.h -components/soc/esp32s3/include/soc/systimer_struct.h -components/soc/esp32s3/include/soc/touch_channel.h -components/soc/esp32s3/include/soc/uart_pins.h -components/soc/esp32s3/include/soc/uart_reg.h -components/soc/esp32s3/include/soc/uart_struct.h -components/soc/esp32s3/include/soc/uhci_reg.h -components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h -components/soc/esp32s3/include/soc/usb_wrap_reg.h -components/soc/esp32s3/include/soc/usb_wrap_struct.h -components/soc/esp32s3/include/soc/wdev_reg.h components/soc/esp32s3/ledc_periph.c components/soc/include/soc/gpio_periph.h -components/soc/include/soc/ledc_periph.h components/soc/lldesc.c components/spi_flash/include/spi_flash_chip_boya.h components/spi_flash/include/spi_flash_chip_gd.h @@ -958,9 +874,6 @@ examples/mesh/manual_networking/main/mesh_main.c examples/network/simple_sniffer/main/cmd_sniffer.c examples/network/simple_sniffer/main/cmd_sniffer.h examples/network/simple_sniffer/main/simple_sniffer_example_main.c -examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c -examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h -examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c examples/peripherals/ledc/ledc_basic/main/ledc_basic_example_main.c examples/peripherals/ledc/ledc_fade/main/ledc_fade_example_main.c examples/peripherals/sdio/host/main/app_main.c @@ -1026,7 +939,6 @@ examples/security/flash_encryption/main/flash_encrypt_main.c examples/storage/custom_flash_driver/components/custom_chip_driver/chip_drivers.c examples/storage/custom_flash_driver/components/custom_chip_driver/spi_flash_chip_eon.c examples/storage/custom_flash_driver/main/main.c -examples/storage/ext_flash_fatfs/main/ext_flash_fatfs_example_main.c examples/storage/nvs_rw_blob/main/nvs_blob_example_main.c examples/storage/nvs_rw_value/main/nvs_value_example_main.c examples/storage/nvs_rw_value_cxx/main/nvs_value_example_main.cpp diff --git a/tools/ci/check_examples_extra_component_dirs.sh b/tools/ci/check_examples_extra_component_dirs.sh index 207efff7f4d8..ac71e5975a55 100755 --- a/tools/ci/check_examples_extra_component_dirs.sh +++ b/tools/ci/check_examples_extra_component_dirs.sh @@ -5,7 +5,7 @@ set -uo pipefail # Examples shouldn't use EXTRA_COMPONENT_DIRS, instead the dependencies should be specified in idf_component.yml files output=$(find ${IDF_PATH}/examples -name "CMakeLists.txt" -not -path "**/managed_components/**" -not -path "**/build/**") -files=$(egrep "set\(EXTRA_COMPONENT_DIRS" ${output} | cut -d ":" -f 1) +files=$(egrep "EXTRA_COMPONENT_DIRS" ${output} | cut -d ":" -f 1) found_issues=0 for file in ${files} do diff --git a/tools/ci/dynamic_pipelines/report.py b/tools/ci/dynamic_pipelines/report.py index bbfb6b6df0d6..ca41156462e5 100644 --- a/tools/ci/dynamic_pipelines/report.py +++ b/tools/ci/dynamic_pipelines/report.py @@ -11,6 +11,7 @@ import yaml from artifacts_handler import ArtifactType +from gitlab import GitlabUpdateError from gitlab_api import Gitlab from idf_build_apps import App from idf_build_apps.constants import BuildStatus @@ -254,6 +255,10 @@ def _update_mr_comment(self, comment: str, print_retry_jobs_message: bool) -> No ) del_retry_job_pic_pattern = re.escape(RETRY_JOB_TITLE) + r'.*?' + re.escape(f'{RETRY_JOB_PICTURE_PATH})') + new_comment = f'{COMMENT_START_MARKER}\n\n{comment}' + if print_retry_jobs_message: + new_comment += retry_job_picture_comment + for note in self.mr.notes.list(iterator=True): if note.body.startswith(COMMENT_START_MARKER): updated_str = self._get_updated_comment(note.body, comment) @@ -264,14 +269,13 @@ def _update_mr_comment(self, comment: str, print_retry_jobs_message: bool) -> No updated_str += retry_job_picture_comment note.body = updated_str - note.save() + try: + note.save() + except GitlabUpdateError: + print('Failed to update MR comment, Creating a new comment') + self.mr.notes.create({'body': new_comment}) break else: - # Create a new comment if no existing comment is found - new_comment = f'{COMMENT_START_MARKER}\n\n{comment}' - if print_retry_jobs_message: - new_comment += retry_job_picture_comment - self.mr.notes.create({'body': new_comment}) def _get_updated_comment(self, existing_comment: str, new_comment: str) -> str: diff --git a/tools/ci/dynamic_pipelines/scripts/child_pipeline_build_apps.py b/tools/ci/dynamic_pipelines/scripts/child_pipeline_build_apps.py index 1f31deb539c3..a76631f70250 100644 --- a/tools/ci/dynamic_pipelines/scripts/child_pipeline_build_apps.py +++ b/tools/ci/dynamic_pipelines/scripts/child_pipeline_build_apps.py @@ -66,7 +66,7 @@ check_app_dependencies=True, parallel_count=args.parallel_count, parallel_index=args.parallel_index, - collect_size_info='size_info_@p.txt', + collect_size_info='size_info.txt', collect_app_info=args.collect_app_info, junitxml=args.junitxml, copy_sdkconfig=True, diff --git a/tools/ci/dynamic_pipelines/scripts/generate_target_test_child_pipeline.py b/tools/ci/dynamic_pipelines/scripts/generate_target_test_child_pipeline.py index bea461414b44..019bc789a615 100644 --- a/tools/ci/dynamic_pipelines/scripts/generate_target_test_child_pipeline.py +++ b/tools/ci/dynamic_pipelines/scripts/generate_target_test_child_pipeline.py @@ -8,7 +8,6 @@ """ import argparse import glob -import logging import os import typing as t from collections import Counter @@ -21,16 +20,15 @@ from dynamic_pipelines.constants import DEFAULT_TARGET_TEST_CHILD_PIPELINE_FILEPATH from dynamic_pipelines.constants import DEFAULT_TARGET_TEST_CHILD_PIPELINE_NAME from dynamic_pipelines.constants import DEFAULT_TEST_PATHS -from dynamic_pipelines.constants import KNOWN_GENERATE_TEST_CHILD_PIPELINE_WARNINGS_FILEPATH +from dynamic_pipelines.constants import ( + KNOWN_GENERATE_TEST_CHILD_PIPELINE_WARNINGS_FILEPATH, +) from dynamic_pipelines.models import EmptyJob from dynamic_pipelines.models import Job from dynamic_pipelines.models import TargetTestJob from dynamic_pipelines.utils import dump_jobs_to_yaml -from gitlab.v4.objects import Project -from gitlab_api import Gitlab from idf_build_apps import App from idf_ci.app import import_apps_from_txt -from idf_ci_utils import IDF_PATH from idf_pytest.script import get_pytest_cases @@ -50,22 +48,17 @@ def get_tags_with_amount(s: str) -> t.List[str]: def get_target_test_jobs( - project: Project, paths: str, apps: t.List[App] -) -> t.Tuple[t.List[Job], t.List[str], t.Dict[str, t.List[str]]]: + paths: str, apps: t.List[App], exclude_runner_tags: t.Set[str] +) -> t.Tuple[t.List[Job], t.List[str], t.List[str]]: """ Return the target test jobs and the extra yaml files to include """ - issues: t.Dict[str, t.List[str]] = { - 'no_env_marker_test_cases': [], - 'no_runner_tags': [], - } - if mr_labels := os.getenv('CI_MERGE_REQUEST_LABELS'): print(f'MR labels: {mr_labels}') if BUILD_ONLY_LABEL in mr_labels.split(','): print('MR has build only label, skip generating target test child pipeline') - return [EmptyJob()], [], issues + return [EmptyJob()], [], [] pytest_cases = get_pytest_cases( paths, @@ -73,10 +66,11 @@ def get_target_test_jobs( marker_expr='not host_test', # since it's generating target-test child pipeline ) + no_env_marker_test_cases: t.List[str] = [] res = defaultdict(list) for case in pytest_cases: if not case.env_markers: - issues['no_env_marker_test_cases'].append(case.item.nodeid) + no_env_marker_test_cases.append(case.item.nodeid) continue res[(case.target_selector, tuple(sorted(case.env_markers)))].append(case) @@ -84,13 +78,8 @@ def get_target_test_jobs( target_test_jobs: t.List[Job] = [] for (target_selector, env_markers), cases in res.items(): runner_tags = get_tags_with_amount(target_selector) + list(env_markers) - # we don't need to get all runner, as long as we get one runner, it's fine - runner_list = project.runners.list(status='online', tag_list=','.join(runner_tags), get_all=False) - if not runner_list: - issues['no_runner_tags'].append(','.join(runner_tags)) - logging.warning(f'No runner found for {",".join(runner_tags)}, required by cases:') - for case in cases: - logging.warning(f' - {case.item.nodeid}') + if ','.join(runner_tags) in exclude_runner_tags: + print('WARNING: excluding test cases with runner tags:', runner_tags) continue target_test_job = TargetTestJob( @@ -115,63 +104,54 @@ def get_target_test_jobs( if fast_pipeline_flag: extra_include_yml = ['tools/ci/dynamic_pipelines/templates/fast_pipeline.yml'] - issues['no_env_marker_test_cases'] = sorted(issues['no_env_marker_test_cases']) - issues['no_runner_tags'] = sorted(issues['no_runner_tags']) - - return target_test_jobs, extra_include_yml, issues + no_env_marker_test_cases.sort() + return target_test_jobs, extra_include_yml, no_env_marker_test_cases def generate_target_test_child_pipeline( - project: Project, paths: str, apps: t.List[App], output_filepath: str, ) -> None: - target_test_jobs, extra_include_yml, issues = get_target_test_jobs(project, paths, apps) - with open(KNOWN_GENERATE_TEST_CHILD_PIPELINE_WARNINGS_FILEPATH) as fr: known_warnings_dict = yaml.safe_load(fr) or dict() + exclude_runner_tags_set = set(known_warnings_dict.get('no_runner_tags', [])) + # EXCLUDE_RUNNER_TAGS is a string separated by ';' + # like 'esp32,generic;esp32c3,wifi' + if exclude_runner_tags := os.getenv('EXCLUDE_RUNNER_TAGS'): + exclude_runner_tags_set.update(exclude_runner_tags.split(';')) + + target_test_jobs, extra_include_yml, no_env_marker_test_cases = get_target_test_jobs( + paths=paths, + apps=apps, + exclude_runner_tags=exclude_runner_tags_set, + ) + known_no_env_marker_test_cases = set(known_warnings_dict.get('no_env_marker_test_cases', [])) - no_env_marker_test_cases = set(issues['no_env_marker_test_cases']) + no_env_marker_test_cases_set = set(no_env_marker_test_cases) no_env_marker_test_cases_fail = False - if no_env_marker_test_cases - known_no_env_marker_test_cases: + if no_env_marker_test_cases_set - known_no_env_marker_test_cases: print('ERROR: NEW "no_env_marker_test_cases" detected:') - for case in no_env_marker_test_cases - known_no_env_marker_test_cases: + for case in no_env_marker_test_cases_set - known_no_env_marker_test_cases: print(f' - {case}') no_env_marker_test_cases_fail = True - print('Please add at least one environment markers to the test cases listed above. ' - 'You may check all the env markers here: tools/ci/idf_pytest/constants.py') - - known_no_runner_tags = set(known_warnings_dict.get('no_runner_tags', [])) - no_runner_tags = set(issues['no_runner_tags']) - - no_runner_tags_fail = False - if no_runner_tags - known_no_runner_tags: - print('ERROR: NEW "no_runner_tags" detected:') - for tag in no_runner_tags - known_no_runner_tags: - print(f' - {tag}') - no_runner_tags_fail = True - print( - '- If you\'re the owner of the missing runners, ' - 'please make sure the runners are online and have the required tags.\n' - '- If you\'re the owner of the test cases that require the missing tags, ' - 'please add at least one runner with the required tags.\n' - '- For other users, please contact the runner owner first, ' - 'or report this issue in our internal CI channel.\n' - 'If the issue cannot be solved in a short time, ' - 'please add the missing tags to the "no_runner_tags" section ' - 'under the file inside ESP-IDF repo: ' - f'{os.path.relpath(KNOWN_GENERATE_TEST_CHILD_PIPELINE_WARNINGS_FILEPATH, IDF_PATH)}.' + 'Please add at least one environment markers to the test cases listed above. ' + 'You may check all the env markers here: tools/ci/idf_pytest/constants.py' ) - if no_env_marker_test_cases_fail or no_runner_tags_fail: + if no_env_marker_test_cases_fail: raise SystemExit('Failed to generate target test child pipeline.') - dump_jobs_to_yaml(target_test_jobs, output_filepath, DEFAULT_TARGET_TEST_CHILD_PIPELINE_NAME, extra_include_yml) + dump_jobs_to_yaml( + target_test_jobs, + output_filepath, + DEFAULT_TARGET_TEST_CHILD_PIPELINE_NAME, + extra_include_yml, + ) print(f'Generate child pipeline yaml file {output_filepath} with {sum(j.parallel for j in target_test_jobs)} jobs') @@ -187,18 +167,6 @@ def generate_target_test_child_pipeline( default=DEFAULT_TEST_PATHS, help='Paths to the apps to build.', ) - parser.add_argument( - '--project-id', - type=int, - default=os.getenv('CI_PROJECT_ID'), - help='Project ID', - ) - parser.add_argument( - '--pipeline-id', - type=int, - default=os.getenv('PARENT_PIPELINE_ID'), - help='Pipeline ID', - ) parser.add_argument( '-o', '--output', @@ -215,15 +183,12 @@ def generate_target_test_child_pipeline( args = parser.parse_args() - gl_project = Gitlab(args.project_id).project - apps = [] for f in glob.glob(args.app_info_filepattern): apps.extend(import_apps_from_txt(f)) generate_target_test_child_pipeline( - gl_project, - args.paths, - apps, - args.output, + paths=args.paths, + apps=apps, + output_filepath=args.output, ) diff --git a/tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml b/tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml index 431664867235..bf5fb01c573c 100644 --- a/tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml +++ b/tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml @@ -7,7 +7,7 @@ .dynamic_build_template: extends: - .before_script:build - - .after_script:build:ccache:upload-when-fail + - .after_script:build:ccache-show-stats:upload-failed-job-logs image: $ESP_ENV_IMAGE stage: build variables: @@ -37,6 +37,7 @@ --collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt" --modified-components ${MR_MODIFIED_COMPONENTS} --junitxml "build_summary_${CI_JOB_NAME_SLUG}.xml" + - run_cmd python tools/ci/artifacts_handler.py upload --type size_reports .dynamic_target_test_template: extends: @@ -63,8 +64,8 @@ - pytest-embedded/ # Child pipeline reports won't be collected in the main one # https://gitlab.com/groups/gitlab-org/-/epics/8205 -# reports: -# junit: XUNIT_RESULT.xml +# reports: +# junit: XUNIT_RESULT.xml when: always expire_in: 1 week script: diff --git a/tools/ci/dynamic_pipelines/templates/known_generate_test_child_pipeline_warnings.yml b/tools/ci/dynamic_pipelines/templates/known_generate_test_child_pipeline_warnings.yml index 3feff2eb1800..70ff179d234b 100644 --- a/tools/ci/dynamic_pipelines/templates/known_generate_test_child_pipeline_warnings.yml +++ b/tools/ci/dynamic_pipelines/templates/known_generate_test_child_pipeline_warnings.yml @@ -1,3 +1,6 @@ +# This is the file that contains the known warnings for the generate_test_child_pipeline.py script. +# no_env_marker_test_cases: List of test cases that do not have environment markers. +# each item shall be the test node id, you may check the error message to get the node id. no_env_marker_test_cases: - components/nvs_flash/test_apps/pytest_nvs_flash.py::test_nvs_flash[default] - components/vfs/test_apps/pytest_vfs.py::test_vfs_ccomp[ccomp] @@ -7,12 +10,23 @@ no_env_marker_test_cases: - examples/storage/nvs_rw_value/pytest_nvs_rw_value.py::test_examples_nvs_rw_value - examples/storage/nvs_rw_value_cxx/pytest_nvs_rw_value_cxx.py::test_examples_nvs_rw_value_cxx - examples/storage/wear_levelling/pytest_wear_levelling_example.py::test_wear_levelling_example + +# no_runner_tags: List of runner tags that has no test runner set. +# each item shall be a comma separated list of runner tags. +# NOTE: +# 1. for multi dut tests, the runner tag shall be _, e.g. esp32_2 instead of esp32,esp32 +# 2. don't have spaces in the comma separated list. no_runner_tags: - esp32,ip101 - esp32c2,jtag,xtal_40mhz - esp32c3,flash_multi - esp32c3,sdcard_sdmode + - esp32c5,generic - esp32c5,jtag + - esp32c5,wifi_ap + - esp32c5,wifi_router + - esp32c5_2,generic_multi_device + - esp32c5_2,wifi_two_dut - esp32c6,jtag - esp32c61,jtag - esp32h2,jtag diff --git a/tools/ci/idf_ci/uploader.py b/tools/ci/idf_ci/uploader.py index 8310c3e11a7e..8ecff4ccbcf9 100644 --- a/tools/ci/idf_ci/uploader.py +++ b/tools/ci/idf_ci/uploader.py @@ -16,6 +16,7 @@ from idf_build_apps.utils import rmdir from idf_ci_utils import IDF_PATH from idf_pytest.constants import DEFAULT_BUILD_LOG_FILENAME +from idf_pytest.constants import DEFAULT_SIZE_JSON_FILENAME class AppDownloader: @@ -60,9 +61,6 @@ class AppUploader(AppDownloader): ArtifactType.LOGS: [ DEFAULT_BUILD_LOG_FILENAME, ], - ArtifactType.SIZE_REPORTS: [ - 'size.json', - ], } def __init__(self, pipeline_id: t.Union[str, int, None] = None) -> None: @@ -108,12 +106,13 @@ def upload_app(self, app_build_path: str, artifact_type: t.Optional[ArtifactType else: upload_types = [artifact_type] + # Upload of size.json files is handled by GitLab CI via "artifacts_handler.py" script. print(f'Uploading {app_build_path} {[k.value for k in upload_types]} to minio server') for upload_type in upload_types: uploaded |= self._upload_app(app_build_path, upload_type) if uploaded: - rmdir(app_build_path, exclude_file_patterns=DEFAULT_BUILD_LOG_FILENAME) + rmdir(app_build_path, exclude_file_patterns=[DEFAULT_BUILD_LOG_FILENAME, DEFAULT_SIZE_JSON_FILENAME]) def _download_app(self, app_build_path: str, artifact_type: ArtifactType) -> None: app_path, build_dir = os.path.split(app_build_path) diff --git a/tools/ci/idf_pytest/constants.py b/tools/ci/idf_pytest/constants.py index 5039f615f155..dadb57fd8dcc 100644 --- a/tools/ci/idf_pytest/constants.py +++ b/tools/ci/idf_pytest/constants.py @@ -153,6 +153,7 @@ 'tools/ci/ignore_build_warnings.txt', ] DEFAULT_BUILD_LOG_FILENAME = 'build_log.txt' +DEFAULT_SIZE_JSON_FILENAME = 'size.json' class CollectMode(str, Enum): diff --git a/tools/ci/idf_pytest/script.py b/tools/ci/idf_pytest/script.py index be99053ef66d..0ff8b5e14fe1 100644 --- a/tools/ci/idf_pytest/script.py +++ b/tools/ci/idf_pytest/script.py @@ -25,6 +25,7 @@ from .constants import CollectMode from .constants import DEFAULT_BUILD_LOG_FILENAME from .constants import DEFAULT_CONFIG_RULES_STR +from .constants import DEFAULT_SIZE_JSON_FILENAME from .constants import PytestCase from .plugin import IdfPytestEmbedded @@ -162,7 +163,7 @@ def get_all_apps( build_dir='build_@t_@w', config_rules_str=config_rules_str or DEFAULT_CONFIG_RULES_STR, build_log_filename=DEFAULT_BUILD_LOG_FILENAME, - size_json_filename='size.json', + size_json_filename=DEFAULT_SIZE_JSON_FILENAME, check_warnings=True, manifest_rootpath=IDF_PATH, compare_manifest_sha_filepath=compare_manifest_sha_filepath, diff --git a/tools/ci/python_packages/common_test_methods.py b/tools/ci/python_packages/common_test_methods.py index 80392fbc27ec..fe5db2a9e73d 100644 --- a/tools/ci/python_packages/common_test_methods.py +++ b/tools/ci/python_packages/common_test_methods.py @@ -1,12 +1,19 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import logging import os import socket -from typing import Any, List +from typing import Any +from typing import List + +try: + import netifaces +except ImportError: + from unittest.mock import MagicMock + + netifaces = MagicMock() + logging.warning('netifaces is not installed. Please install it to get network interface information.') -import netifaces import yaml ENV_CONFIG_FILE_SEARCH = [ diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 2ddc408ab5e4..156bcf12bc40 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -253,7 +253,7 @@ function(__build_init idf_path) if(IS_DIRECTORY ${component_dir}) __component_dir_quick_check(is_component ${component_dir}) if(is_component) - __component_add(${component_dir} ${prefix}) + __component_add(${component_dir} ${prefix} "idf_components") endif() endif() endforeach() @@ -283,9 +283,29 @@ endfunction() # during build (see the COMPONENTS argument description for command idf_build_process) # # @param[in] component_dir directory of the component +# @param[in, optional] component_source source of the component, defaults to "project_components" function(idf_build_component component_dir) idf_build_get_property(prefix __PREFIX) - __component_add(${component_dir} ${prefix} 0) + + # if argvc is 1, then component_source is not specified + # this should only happen when users call this function directly + if(${ARGC} EQUAL 1) + set(component_source "project_components") + else() + set(component_source ${ARGV1}) + endif() + + # component_source must be one of the following (sorted by the override order): + set(valid_component_sources "idf_components" + "project_managed_components" + "project_extra_components" + "project_components") + + if(NOT component_source IN_LIST valid_component_sources) + message(FATAL_ERROR "Invalid component source '${component_source}'.") + endif() + + __component_add(${component_dir} ${prefix} ${component_source}) endfunction() # @@ -504,6 +524,7 @@ macro(idf_build_process target) cmake_parse_arguments(_ "${options}" "${single_value}" "${multi_value}" ${ARGN}) idf_build_set_property(BOOTLOADER_BUILD "${BOOTLOADER_BUILD}") + idf_build_set_property(NON_OS_BUILD "${NON_OS_BUILD}") idf_build_set_property(IDF_TOOLCHAIN "${IDF_TOOLCHAIN}") @@ -611,7 +632,7 @@ macro(idf_build_process target) endforeach() if(NOT "${__components_with_manifests}" STREQUAL "") - message(WARNING "\"idf_component.yml\" file was found for components:\n${__components_with_manifests}" + message(NOTICE "\"idf_component.yml\" file was found for components:\n${__components_with_manifests}" "However, the component manager is not enabled.") endif() endif() diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake index 18bab3b38695..1ad0ed05edee 100644 --- a/tools/cmake/component.cmake +++ b/tools/cmake/component.cmake @@ -138,7 +138,7 @@ endfunction() # Add a component to process in the build. The components are keeped tracked of in property # __COMPONENT_TARGETS in component target form. # -function(__component_add component_dir prefix) +function(__component_add component_dir prefix component_source) # For each component, two entities are created: a component target and a component library. The # component library is created during component registration (the actual static/interface library). # On the other hand, component targets are created early in the build @@ -186,6 +186,9 @@ function(__component_add component_dir prefix) __component_set_property(${component_target} COMPONENT_NAME ${component_name}) __component_set_property(${component_target} COMPONENT_DIR ${component_dir}) __component_set_property(${component_target} COMPONENT_ALIAS ${component_alias}) + if(component_source) + __component_set_property(${component_target} COMPONENT_SOURCE ${component_source}) + endif() __component_set_property(${component_target} __PREFIX ${prefix}) diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index cb70e61e77c1..7527f19bd76b 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -61,7 +61,7 @@ if(NOT "$ENV{IDF_COMPONENT_MANAGER}" EQUAL "0") idf_build_set_property(IDF_COMPONENT_MANAGER 1) endif() # Set component manager interface version -idf_build_set_property(__COMPONENT_MANAGER_INTERFACE_VERSION 2) +idf_build_set_property(__COMPONENT_MANAGER_INTERFACE_VERSION 3) # # Parse and store the VERSION argument provided to the project() command. @@ -420,11 +420,11 @@ function(__project_init components_var test_components_var) idf_build_set_property(CXX_COMPILE_OPTIONS "${extra_cxxflags}" APPEND) idf_build_set_property(COMPILE_OPTIONS "${extra_cppflags}" APPEND) - function(__project_component_dir component_dir) + function(__project_component_dir component_dir component_source) get_filename_component(component_dir "${component_dir}" ABSOLUTE) # The directory itself is a valid idf component if(EXISTS ${component_dir}/CMakeLists.txt) - idf_build_component(${component_dir}) + idf_build_component(${component_dir} ${component_source}) else() idf_build_get_property(exclude_dirs EXTRA_COMPONENT_EXCLUDE_DIRS) # otherwise, check whether the subfolders are potential idf components @@ -433,7 +433,7 @@ function(__project_init components_var test_components_var) if(IS_DIRECTORY ${component_dir} AND NOT ${component_dir} IN_LIST exclude_dirs) __component_dir_quick_check(is_component ${component_dir}) if(is_component) - idf_build_component(${component_dir}) + idf_build_component(${component_dir} ${component_source}) endif() endif() endforeach() @@ -451,11 +451,11 @@ function(__project_init components_var test_components_var) if(NOT EXISTS ${component_abs_path}) message(FATAL_ERROR "Directory specified in COMPONENT_DIRS doesn't exist: ${component_abs_path}") endif() - __project_component_dir(${component_dir}) + __project_component_dir(${component_dir} "project_components") endforeach() else() if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/main") - __project_component_dir("${CMAKE_CURRENT_LIST_DIR}/main") + __project_component_dir("${CMAKE_CURRENT_LIST_DIR}/main" "project_components") endif() paths_with_spaces_to_list(EXTRA_COMPONENT_DIRS) @@ -464,12 +464,12 @@ function(__project_init components_var test_components_var) if(NOT EXISTS ${component_abs_path}) message(FATAL_ERROR "Directory specified in EXTRA_COMPONENT_DIRS doesn't exist: ${component_abs_path}") endif() - __project_component_dir("${component_dir}") + __project_component_dir("${component_dir}" "project_extra_components") endforeach() # Look for components in the usual places: CMAKE_CURRENT_LIST_DIR/main, # extra component dirs, and CMAKE_CURRENT_LIST_DIR/components - __project_component_dir("${CMAKE_CURRENT_LIST_DIR}/components") + __project_component_dir("${CMAKE_CURRENT_LIST_DIR}/components" "project_components") endif() # For bootloader components, we only need to set-up the Kconfig files. @@ -521,7 +521,7 @@ function(__project_init components_var test_components_var) set(include 0) endif() if(include AND EXISTS ${component_dir}/test) - __component_add(${component_dir}/test ${component_name}) + __component_add(${component_dir}/test ${component_name} "project_components") list(APPEND test_components ${component_name}::test) endif() endif() @@ -884,6 +884,33 @@ macro(project project_name) # Add DFU build and flash targets __add_dfu_targets() + # Add uf2 related targets + idf_build_get_property(idf_path IDF_PATH) + idf_build_get_property(python PYTHON) + + set(UF2_ARGS --json "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json") + set(UF2_CMD ${python} "${idf_path}/tools/mkuf2.py" write --chip ${chip_model}) + + add_custom_target(uf2 + COMMAND ${CMAKE_COMMAND} + -D "IDF_PATH=${idf_path}" + -D "UF2_CMD=${UF2_CMD}" + -D "UF2_ARGS=${UF2_ARGS};-o;${CMAKE_CURRENT_BINARY_DIR}/uf2.bin" + -P "${idf_path}/tools/cmake/run_uf2_cmds.cmake" + USES_TERMINAL + VERBATIM + ) + + add_custom_target(uf2-app + COMMAND ${CMAKE_COMMAND} + -D "IDF_PATH=${idf_path}" + -D "UF2_CMD=${UF2_CMD}" + -D "UF2_ARGS=${UF2_ARGS};-o;${CMAKE_CURRENT_BINARY_DIR}/uf2-app.bin;--bin;app" + -P "${idf_path}/tools/cmake/run_uf2_cmds.cmake" + USES_TERMINAL + VERBATIM + ) + idf_build_executable(${project_elf}) __project_info("${test_components}") diff --git a/tools/cmake/run_uf2_cmds.cmake b/tools/cmake/run_uf2_cmds.cmake new file mode 100644 index 000000000000..1ed4d5c0fc5f --- /dev/null +++ b/tools/cmake/run_uf2_cmds.cmake @@ -0,0 +1,27 @@ +# A CMake script to run dfu-util from within ninja or make +# or another cmake-based build runner +# +# It is recommended to NOT USE this CMake script directly + +cmake_minimum_required(VERSION 3.16) + +set(UF2_CMD "${UF2_CMD}") +set(UF2_ARGS "${UF2_ARGS}") + +if(NOT UF2_CMD) + message(FATAL_ERROR "UF2_CMD must be specified on the CMake command line.") +endif() + +if(NOT UF2_ARGS) + message(FATAL_ERROR "UF2_ARGS must be specified on the CMake command line.") +endif() + +set(uf2_cmd_with_args ${UF2_CMD}) +list(APPEND uf2_cmd_with_args ${UF2_ARGS}) + +execute_process(COMMAND ${uf2_cmd_with_args} + RESULT_VARIABLE result) + +if(${result}) + message(FATAL_ERROR "${UF2_CMD} failed") +endif() diff --git a/tools/cmake/scripts/component_get_requirements.cmake b/tools/cmake/scripts/component_get_requirements.cmake index 89531881a4ed..bc94112e52ed 100644 --- a/tools/cmake/scripts/component_get_requirements.cmake +++ b/tools/cmake/scripts/component_get_requirements.cmake @@ -27,7 +27,7 @@ endfunction() function(__component_get_target var name_or_alias) idf_build_get_property(component_targets __COMPONENT_TARGETS) - # Assume first that the paramters is an alias. + # Assume first that the parameters is an alias. string(REPLACE "::" "_" name_or_alias "${name_or_alias}") set(component_target ___${name_or_alias}) @@ -119,7 +119,40 @@ function(__component_get_requirements) endfunction() set(CMAKE_BUILD_EARLY_EXPANSION 1) + +# smaller number means lower priority +set(__TARGETS_IDF_COMPONENTS "") # 0 +set(__TARGETS_PROJECT_MANAGED_COMPONENTS "") # 1 +set(__TARGETS_PROJECT_EXTRA_COMPONENTS "") # 2 +set(__TARGETS_PROJECT_COMPONENTS "") # 3 + foreach(__component_target ${__component_targets}) + __component_get_property(__component_source ${__component_target} COMPONENT_SOURCE) + + if("${__component_source}" STREQUAL "idf_components") + list(APPEND __TARGETS_IDF_COMPONENTS ${__component_target}) + elseif("${__component_source}" STREQUAL "project_managed_components") + list(APPEND __TARGETS_PROJECT_MANAGED_COMPONENTS ${__component_target}) + elseif("${__component_source}" STREQUAL "project_extra_components") + list(APPEND __TARGETS_PROJECT_EXTRA_COMPONENTS ${__component_target}) + elseif("${__component_source}" STREQUAL "project_components") + list(APPEND __TARGETS_PROJECT_COMPONENTS ${__component_target}) + else() + message(FATAL_ERROR "Unknown component source for component ${__component_target}: ${__component_source}") + endif() +endforeach() + +# priority higher ones goes first +set(__sorted_component_targets "") +foreach(__target IN LISTS __TARGETS_PROJECT_COMPONENTS + __TARGETS_PROJECT_EXTRA_COMPONENTS + __TARGETS_PROJECT_MANAGED_COMPONENTS + __TARGETS_IDF_COMPONENTS) + __component_get_property(__component_name ${__target} COMPONENT_NAME) + list(APPEND __sorted_component_targets ${__target}) +endforeach() + +foreach(__component_target ${__sorted_component_targets}) set(__component_requires "") set(__component_priv_requires "") set(__component_registered 0) @@ -141,11 +174,14 @@ foreach(__component_target ${__component_targets}) list(REMOVE_ITEM __component_priv_requires ${__component_alias} ${__component_name}) endif() + __component_get_property(__component_source ${__component_target} COMPONENT_SOURCE) + set(__contents "__component_set_property(${__component_target} REQUIRES \"${__component_requires}\") __component_set_property(${__component_target} PRIV_REQUIRES \"${__component_priv_requires}\") __component_set_property(${__component_target} __COMPONENT_REGISTERED ${__component_registered}) -__component_set_property(${__component_target} INCLUDE_DIRS \"${__component_include_dirs}\")" +__component_set_property(${__component_target} INCLUDE_DIRS \"${__component_include_dirs}\") +__component_set_property(${__component_target} __COMPONENT_SOURCE \"${__component_source}\")" ) if(__component_kconfig) diff --git a/tools/esp_prov/transport/transport_http.py b/tools/esp_prov/transport/transport_http.py index f17cfc8f6dee..1474e4627f3c 100644 --- a/tools/esp_prov/transport/transport_http.py +++ b/tools/esp_prov/transport/transport_http.py @@ -1,8 +1,9 @@ -# SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 # import socket -from http.client import HTTPConnection, HTTPSConnection +from http.client import HTTPConnection +from http.client import HTTPSConnection from utils import str_to_bytes @@ -12,7 +13,7 @@ class Transport_HTTP(Transport): def __init__(self, hostname, ssl_context=None): try: - socket.gethostbyname(hostname.split(':')[0]) + socket.getaddrinfo(hostname.split(':')[0], None) except socket.gaierror: raise RuntimeError(f'Unable to resolve hostname: {hostname}') @@ -35,7 +36,7 @@ def _send_post_request(self, path, data): # While establishing a session, the device sends the Set-Cookie header # with value 'session=cookie_session_id' in its first response of the session to the tool. # To maintain the same session, successive requests from the tool should include - # an additional 'Cookie' header with the above recieved value. + # an additional 'Cookie' header with the above received value. for hdr_key, hdr_val in response.getheaders(): if hdr_key == 'Set-Cookie': self.headers['Cookie'] = hdr_val diff --git a/tools/export_utils/shell_types.py b/tools/export_utils/shell_types.py index bb0d0c5ff54a..d2e346067237 100644 --- a/tools/export_utils/shell_types.py +++ b/tools/export_utils/shell_types.py @@ -1,10 +1,13 @@ # SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 +import getpass import os import re import shutil import sys import textwrap +from datetime import datetime +from datetime import timedelta from pathlib import Path from subprocess import run from tempfile import gettempdir @@ -18,6 +21,7 @@ import click from console_output import debug from console_output import status_message +from console_output import warn from utils import conf from utils import run_cmd @@ -27,10 +31,26 @@ def __init__(self, shell: str, deactivate_cmd: str, new_esp_idf_env: Dict[str,st self.shell = shell self.deactivate_cmd = deactivate_cmd self.new_esp_idf_env = new_esp_idf_env - self.tmp_dir_path = Path(gettempdir()) / 'esp_idf_activate' + + try: + self.tmp_dir_path = Path(gettempdir()) / ('esp_idf_activate_' + getpass.getuser()) + except Exception as e: + self.tmp_dir_path = Path(gettempdir()) / 'esp_idf_activate' + warn(f'Failed to get username with error: {e}. Using default temporary directory {self.tmp_dir_path}.') + if not conf.ARGS.debug and os.path.exists(self.tmp_dir_path): # Do not cleanup temporary directory when debugging - shutil.rmtree(self.tmp_dir_path) + for item in self.tmp_dir_path.iterdir(): + try: + if item.is_file(): + current_time = datetime.now() + file_creation_time = datetime.fromtimestamp(os.path.getctime(item)) + # delete files older than 1 hour to avoid datarace when using activation in parallel + if current_time - file_creation_time > timedelta(hours=1): + item.unlink() + except Exception as e: + warn(f'Failed to clean temp activation directory with file {item}: {e}') + self.tmp_dir_path.mkdir(parents=True, exist_ok=True) def export(self) -> None: diff --git a/tools/idf_py_actions/debug_ext.py b/tools/idf_py_actions/debug_ext.py index eb05437e9254..02d4f4f95670 100644 --- a/tools/idf_py_actions/debug_ext.py +++ b/tools/idf_py_actions/debug_ext.py @@ -408,14 +408,23 @@ def get_gdb_args(project_desc: Dict[str, Any]) -> List: return args def _get_gdbgui_version(ctx: Context) -> Tuple[int, ...]: - completed_process = subprocess.run(['gdbgui', '--version'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - captured_output = completed_process.stdout.decode('utf-8', 'ignore') - - if completed_process.returncode != 0: + try: + completed_process = subprocess.run(['gdbgui', '--version'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + subprocess_success = True + captured_output = completed_process.stdout.decode('utf-8', 'ignore') + except FileNotFoundError: + # This is happening at least with Python 3.12 when gdbgui is not installed + subprocess_success = False + + if not subprocess_success or completed_process.returncode != 0: if sys.version_info[:2] >= (3, 11) and sys.platform == 'win32': raise SystemExit('Unfortunately, gdbgui is supported only with Python 3.10 or older. ' 'See: https://github.com/espressif/esp-idf/issues/10116. ' 'Please use "idf.py gdb" or debug in Eclipse/Vscode instead.') + if sys.version_info[:2] >= (3, 13) and sys.platform != 'win32': + raise SystemExit('Unfortunately, gdbgui is supported only with Python 3.12 or older. ' + 'See: https://github.com/cs01/gdbgui/issues/494. ' + 'Please use "idf.py gdb" or debug in Eclipse/Vscode instead.') raise FatalError('Error starting gdbgui. Please make sure gdbgui has been installed with ' '"install.{sh,bat,ps1,fish} --enable-gdbgui" and can be started. ' f'Error: {captured_output}', ctx) diff --git a/tools/idf_py_actions/hints.yml b/tools/idf_py_actions/hints.yml index f17f3fa28740..67c57f3a7c63 100644 --- a/tools/idf_py_actions/hints.yml +++ b/tools/idf_py_actions/hints.yml @@ -443,3 +443,11 @@ - re: "discarded output section: .*\\.got" hint: "Some objects being linked were compiled with the \"-fpic\"/\"-fpie\" options. These options may be suitable for \"linux\" builds, but must not be applied for esp32XX targets." + +- + re: "(error: Total discarded sections size is \\d+ bytes)|(region [`'.\\w]+ overflowed by \\d+ bytes)" + hint: "The binary size has exceeded the limit. To resolve the issue consider reducing the binary size.\nYou can explore size optimization techniques in the documentation by running 'idf.py docs -sp api-guides/performance/size.html#reducing-overall-size'.\nNote that the linker performed the dead code elimination." + +- + re: "implicit declaration of function '__VA_NARG__'" + hint: "__VA_NARG_ has been renamed. Please use ESP_VA_NARG instead" diff --git a/tools/idf_py_actions/qemu_ext.py b/tools/idf_py_actions/qemu_ext.py index 685e9c8363ed..ad46a07ddeed 100644 --- a/tools/idf_py_actions/qemu_ext.py +++ b/tools/idf_py_actions/qemu_ext.py @@ -213,7 +213,7 @@ def _get_project_desc(args: PropertyDict, ctx: Context) -> Any: project_desc = json.load(f) return project_desc - def qemu(action: str, ctx: Context, args: PropertyDict, qemu_extra_args: str, gdb: bool, graphics: bool, efuse_file: str) -> None: + def qemu(action: str, ctx: Context, args: PropertyDict, qemu_extra_args: str, gdb: bool, graphics: bool, efuse_file: str, flash_file: str) -> None: project_desc = _get_project_desc(args, ctx) # Determine the target and check if we have the necessary QEMU binary @@ -230,11 +230,21 @@ def qemu(action: str, ctx: Context, args: PropertyDict, qemu_extra_args: str, gd # Generate flash image and efuse image flash_size = get_sdkconfig_value(project_desc['config_file'], 'CONFIG_ESPTOOLPY_FLASHSIZE') - bin_path = os.path.join(args.build_dir, 'qemu_flash.bin') - yellow_print(f'Generating flash image: {bin_path}') - subprocess.check_call([ - sys.executable, '-m', 'esptool', f'--chip={target}', 'merge_bin', f'--output={bin_path}', - f'--fill-flash-size={flash_size}', '@flash_args'], cwd=args.build_dir) + + if flash_file: + bin_path = flash_file + try: + open(bin_path, 'rb').close() + yellow_print(f'Using provided flash image: {bin_path}') + except FileNotFoundError: + red_print(f'The provided flash image file \"{bin_path}\" could not be found') + raise SystemExit(1) + else: + bin_path = os.path.join(args.build_dir, 'qemu_flash.bin') + yellow_print(f'Generating flash image: {bin_path}') + subprocess.check_call([ + sys.executable, '-m', 'esptool', f'--chip={target}', 'merge_bin', f'--output={bin_path}', + f'--fill-flash-size={flash_size}', '@flash_args'], cwd=args.build_dir) if efuse_file: efuse_bin_path = efuse_file @@ -251,12 +261,18 @@ def qemu(action: str, ctx: Context, args: PropertyDict, qemu_extra_args: str, gd # Prepare QEMU launch arguments qemu_args = [qemu_target_info.qemu_prog] qemu_args += qemu_target_info.qemu_args.split(' ') + # When boot mode is specified, the flash image is not required. + if not options.boot_mode: + qemu_args += [ + '-drive', f'file={bin_path},if=mtd,format=raw', + ] + qemu_args += [ - '-drive', f'file={bin_path},if=mtd,format=raw', '-drive', f'file={efuse_bin_path},if=none,format=raw,id=efuse', '-global', f'driver={qemu_target_info.efuse_device},property=drive,value=efuse', '-global', f'driver=timer.{target}.timg,property=wdt_disable,value=true', ] + if '-nic' not in qemu_extra_args: qemu_args += ['-nic', 'user,model=open_eth'] @@ -339,6 +355,13 @@ def cleanup_qemu() -> None: 'in build directory is used.'), 'is_flag': False, 'default': '', + }, + { + 'names': ['--flash-file'], + 'help': ('File used as the qemu flash image. If not specified, qemu_flash.bin file ' + 'in build directory is used.'), + 'is_flag': False, + 'default': '', } ] } diff --git a/tools/idf_py_actions/roms.json b/tools/idf_py_actions/roms.json index 40a4ff930a02..01524dc9cf1f 100644 --- a/tools/idf_py_actions/roms.json +++ b/tools/idf_py_actions/roms.json @@ -44,6 +44,13 @@ "build_date_str": "Feb 7 2021" } ], + "esp32c5": [ + { + "rev": 0, + "build_date_str_addr": "0x4004b3c4", + "build_date_str": "Mar 29 2024" + } + ], "esp32c6": [ { "rev": 0, diff --git a/tools/idf_py_actions/serial_ext.py b/tools/idf_py_actions/serial_ext.py index 9d8c1b3a3a7c..502ca5ecec0d 100644 --- a/tools/idf_py_actions/serial_ext.py +++ b/tools/idf_py_actions/serial_ext.py @@ -105,6 +105,7 @@ def monitor( timestamps: bool, timestamp_format: str, force_color: bool, + disable_auto_color: bool, ) -> None: """ Run esp_idf_monitor to watch build output @@ -187,6 +188,9 @@ def monitor( if force_color or os.name == 'nt': monitor_args += ['--force-color'] + if disable_auto_color: + monitor_args += ['--disable-auto-color'] + idf_py = [PYTHON] + _get_commandline_options(ctx) # commands to re-run idf.py monitor_args += ['-m', ' '.join("'%s'" % a for a in idf_py)] hints = not args.no_hints @@ -1011,6 +1015,11 @@ def efuse_write_protect(action: str, ctx: click.core.Context, args: PropertyDict 'is_flag': True, 'help': 'Always print ANSI for colors', }, + { + 'names': ['--disable-auto-color'], + 'is_flag': True, + 'help': 'Disable auto coloring logs', + }, ], 'order_dependencies': [ 'flash', diff --git a/tools/idf_tools.py b/tools/idf_tools.py index a928c0465671..17617c15056d 100755 --- a/tools/idf_tools.py +++ b/tools/idf_tools.py @@ -2574,7 +2574,10 @@ def action_install_python_env(args): # type: ignore reinstall = args.reinstall idf_python_env_path, _, virtualenv_python, idf_version = get_python_env_path() - is_virtualenv = hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix) + nix_store = os.environ.get('NIX_STORE') + is_nix = nix_store is not None and sys.base_prefix.startswith(nix_store) and sys.prefix.startswith(nix_store) + + is_virtualenv = not is_nix and (hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)) if is_virtualenv and (not os.path.exists(idf_python_env_path) or reinstall): fatal('This script was called from a virtual environment, can not create a virtual environment again') raise SystemExit(1) diff --git a/tools/ldgen/ldgen/fragments.py b/tools/ldgen/ldgen/fragments.py index 0acd81f605d8..80cc167e207a 100644 --- a/tools/ldgen/ldgen/fragments.py +++ b/tools/ldgen/ldgen/fragments.py @@ -1,13 +1,34 @@ # -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 # - -from typing import Any, Dict, List, Optional, Set, Tuple, Union - -from pyparsing import (Combine, Forward, Group, IndentedBlock, Keyword, LineEnd, Literal, OneOrMore, Opt, - ParseFatalException, SkipTo, Suppress, Word, ZeroOrMore, alphanums, alphas, delimited_list, - nums, rest_of_line) +from typing import Any +from typing import Dict +from typing import List +from typing import Optional +from typing import Set +from typing import Tuple +from typing import Union + +from pyparsing import alphanums +from pyparsing import alphas +from pyparsing import Combine +from pyparsing import delimited_list +from pyparsing import Forward +from pyparsing import Group +from pyparsing import IndentedBlock +from pyparsing import Keyword +from pyparsing import LineEnd +from pyparsing import Literal +from pyparsing import nums +from pyparsing import OneOrMore +from pyparsing import Opt +from pyparsing import ParseFatalException +from pyparsing import rest_of_line +from pyparsing import SkipTo +from pyparsing import Suppress +from pyparsing import Word +from pyparsing import ZeroOrMore class Empty: @@ -227,11 +248,11 @@ class Sort(EntryFlag): _keywords = Keyword('name') | Keyword('alignment') | Keyword('init_priority') SORT = (Keyword('SORT').suppress() + Suppress('(') - + _keywords.set_results_name('first') - + Opt(Suppress(',') + _keywords.set_results_name('second')) + + Opt(_keywords.set_results_name('first') + + Opt(Suppress(',') + _keywords.set_results_name('second'))) + Suppress(')')) - def __init__(self, first: str, second: Optional[str] = None): + def __init__(self, first: Optional[str] = None, second: Optional[str] = None): self.first = first self.second = second @@ -244,7 +265,7 @@ def __eq__(self, other): @staticmethod def parse(toks): - return Sort(toks.first, toks.second or None) + return Sort(toks.first or None, toks.second or None) class Flag: diff --git a/tools/ldgen/test/test_fragments.py b/tools/ldgen/test/test_fragments.py index 9cc3899e989c..c7e72892eef4 100755 --- a/tools/ldgen/test/test_fragments.py +++ b/tools/ldgen/test/test_fragments.py @@ -705,6 +705,7 @@ def test_sort_flag(self): archive: libmain.a entries: obj1 (default); + text->flash_text SORT(), text->flash_text SORT(name), rodata->flash_rodata SORT(alignment), data->dram0_data SORT(init_priority), @@ -717,7 +718,8 @@ def test_sort_flag(self): fragment_file = parse_fragment_file(test_fragment, self.sdkconfig) fragment = fragment_file.fragments[0] - expected = [Flag('text', 'flash_text', [Sort('name')]), + expected = [Flag('text', 'flash_text', [Sort()]), + Flag('text', 'flash_text', [Sort('name')]), Flag('rodata', 'flash_rodata', [Sort('alignment')]), Flag('data', 'dram0_data', [Sort('init_priority')]), Flag('bss', 'dram0_bss', [Sort('name', 'alignment')]), diff --git a/tools/mocks/freertos/CMakeLists.txt b/tools/mocks/freertos/CMakeLists.txt index ce6111260ab5..9286bd3d2ce0 100644 --- a/tools/mocks/freertos/CMakeLists.txt +++ b/tools/mocks/freertos/CMakeLists.txt @@ -25,7 +25,8 @@ idf_component_mock(INCLUDE_DIRS ${include_dirs} ${original_freertos_dir}/esp_additions/include/freertos/idf_additions.h ${original_freertos_dir}/FreeRTOS-Kernel/include/freertos/task.h ${original_freertos_dir}/FreeRTOS-Kernel/include/freertos/event_groups.h - ${original_freertos_dir}/FreeRTOS-Kernel/include/freertos/queue.h) + ${original_freertos_dir}/FreeRTOS-Kernel/include/freertos/queue.h + ${original_freertos_dir}/FreeRTOS-Kernel/portable/linux/include/freertos/portmacro.h) idf_component_get_property(freertos_lib freertos COMPONENT_LIB) target_compile_definitions(${freertos_lib} PUBLIC "projCOVERAGE_TEST=0") diff --git a/tools/requirements/requirements.ci.txt b/tools/requirements/requirements.ci.txt index fa1ac259d40c..dfec5b20fc3c 100644 --- a/tools/requirements/requirements.ci.txt +++ b/tools/requirements/requirements.ci.txt @@ -15,3 +15,4 @@ pyyaml SimpleWebSocketServer pylint-gitlab minio +prettytable diff --git a/tools/requirements/requirements.gdbgui.txt b/tools/requirements/requirements.gdbgui.txt index 2d7f1cd434f7..60cbf384a70c 100644 --- a/tools/requirements/requirements.gdbgui.txt +++ b/tools/requirements/requirements.gdbgui.txt @@ -7,5 +7,6 @@ # gdbgui Python 3.11 issue https://github.com/cs01/gdbgui/issues/447 was fixed in 0.15.2.0. Windows users need an # older Python to use since new gdbgui versions don't support Windows anymore. -gdbgui; sys_platform != 'win32' +# Python 3.13 is not supported: https://github.com/cs01/gdbgui/issues/494 +gdbgui; sys_platform != 'win32' and python_version < "3.13" gdbgui; sys_platform == 'win32' and python_version < "3.11" diff --git a/tools/test_apps/build_system/bootloader/sdkconfig.ci.verbose_logging b/tools/test_apps/build_system/bootloader/sdkconfig.ci.verbose_logging index 2ce67a363ce7..06028d51aba1 100644 --- a/tools/test_apps/build_system/bootloader/sdkconfig.ci.verbose_logging +++ b/tools/test_apps/build_system/bootloader/sdkconfig.ci.verbose_logging @@ -2,3 +2,4 @@ # Turn verbose log on for bootloader # CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE=y +CONFIG_PARTITION_TABLE_OFFSET=0xF000 diff --git a/tools/test_apps/security/secure_boot/pytest_secure_boot.py b/tools/test_apps/security/secure_boot/pytest_secure_boot.py index c570e8de430c..6bd5ae69cd14 100644 --- a/tools/test_apps/security/secure_boot/pytest_secure_boot.py +++ b/tools/test_apps/security/secure_boot/pytest_secure_boot.py @@ -80,10 +80,8 @@ def dut_start_secure_app(dut: Dut) -> None: # Test secure boot flow. # Correctly signed bootloader + correctly signed app should work @pytest.mark.esp32c3 -# TODO: [ESP32C5] IDF-10043 -# @pytest.mark.esp32c5 -# TODO: [ESP32C5] IDF-10102 -# @pytest.mark.esp32c61 +@pytest.mark.esp32c5 +@pytest.mark.esp32c61 @pytest.mark.esp32s3 @pytest.mark.esp32p4 def test_examples_security_secure_boot(dut: Dut) -> None: @@ -96,10 +94,8 @@ def test_examples_security_secure_boot(dut: Dut) -> None: # Test efuse key index and key block combination. # Any key index can be written to any key block and should work @pytest.mark.esp32c3 -# TODO: [ESP32C5] IDF-10043 -# @pytest.mark.esp32c5 -# TODO: [ESP32C5] IDF-10102 -# @pytest.mark.esp32c61 +@pytest.mark.esp32c5 +@pytest.mark.esp32c61 @pytest.mark.esp32s3 @pytest.mark.esp32p4 # Increasing the test timeout to 1200s as the test runs for 18 iterations @@ -122,10 +118,8 @@ def test_examples_security_secure_boot_key_combo(dut: Dut) -> None: # Test secure boot key revoke. # If a key is revoked, bootloader signed with that key should fail verification @pytest.mark.esp32c3 -# TODO: [ESP32C5] IDF-10043 -# @pytest.mark.esp32c5 -# TODO: [ESP32C5] IDF-10102 -# @pytest.mark.esp32c61 +@pytest.mark.esp32c5 +@pytest.mark.esp32c61 @pytest.mark.esp32s3 @pytest.mark.esp32p4 def test_examples_security_secure_boot_key_revoke(dut: Dut) -> None: @@ -145,10 +139,8 @@ def test_examples_security_secure_boot_key_revoke(dut: Dut) -> None: # Test bootloader signature corruption. # Corrupt one byte at a time of bootloader signature and test that the verification fails @pytest.mark.esp32c3 -# TODO: [ESP32C5] IDF-10043 -# @pytest.mark.esp32c5 -# TODO: [ESP32C5] IDF-10102 -# @pytest.mark.esp32c61 +@pytest.mark.esp32c5 +@pytest.mark.esp32c61 @pytest.mark.esp32s3 @pytest.mark.esp32p4 @pytest.mark.timeout(18000) @@ -186,10 +178,8 @@ def test_examples_security_secure_boot_corrupt_bl_sig(dut: Dut) -> None: # Test app signature corruption. # Corrupt app signature, one byte at a time, and test that the verification fails @pytest.mark.esp32c3 -# TODO: [ESP32C5] IDF-10043 -# @pytest.mark.esp32c5 -# TODO: [ESP32C5] IDF-10102 -# @pytest.mark.esp32c61 +@pytest.mark.esp32c5 +@pytest.mark.esp32c61 @pytest.mark.esp32s3 @pytest.mark.esp32p4 @pytest.mark.timeout(18000) diff --git a/tools/test_apps/storage/.build-test-rules.yml b/tools/test_apps/storage/.build-test-rules.yml index d27c0ab8933f..f0ab55097ce2 100644 --- a/tools/test_apps/storage/.build-test-rules.yml +++ b/tools/test_apps/storage/.build-test-rules.yml @@ -1,5 +1,13 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps +tools/test_apps/storage/fatfsgen: + depends_components: + - fatfs + - vfs + disable_test: + - if: IDF_TARGET != "esp32" + reason: only one target needed + tools/test_apps/storage/partition_table_readonly: disable_test: - if: IDF_TARGET not in ["esp32", "esp32c3"] diff --git a/examples/storage/fatfsgen/CMakeLists.txt b/tools/test_apps/storage/fatfsgen/CMakeLists.txt similarity index 100% rename from examples/storage/fatfsgen/CMakeLists.txt rename to tools/test_apps/storage/fatfsgen/CMakeLists.txt diff --git a/examples/storage/fatfsgen/README.md b/tools/test_apps/storage/fatfsgen/README.md similarity index 100% rename from examples/storage/fatfsgen/README.md rename to tools/test_apps/storage/fatfsgen/README.md diff --git a/examples/storage/fatfsgen/fatfs_image/hello.txt b/tools/test_apps/storage/fatfsgen/fatfs_image/hello.txt similarity index 100% rename from examples/storage/fatfsgen/fatfs_image/hello.txt rename to tools/test_apps/storage/fatfsgen/fatfs_image/hello.txt diff --git a/examples/storage/fatfsgen/fatfs_image/sub/test.txt b/tools/test_apps/storage/fatfsgen/fatfs_image/sub/test.txt similarity index 100% rename from examples/storage/fatfsgen/fatfs_image/sub/test.txt rename to tools/test_apps/storage/fatfsgen/fatfs_image/sub/test.txt diff --git a/tools/test_apps/storage/fatfsgen/fatfs_long_name_image/hellolongname.txt b/tools/test_apps/storage/fatfsgen/fatfs_long_name_image/hellolongname.txt new file mode 100644 index 000000000000..45caad272569 --- /dev/null +++ b/tools/test_apps/storage/fatfsgen/fatfs_long_name_image/hellolongname.txt @@ -0,0 +1 @@ +This is generated on the host; long name it has diff --git a/tools/test_apps/storage/fatfsgen/fatfs_long_name_image/sublongnames/testlongfilenames.txt b/tools/test_apps/storage/fatfsgen/fatfs_long_name_image/sublongnames/testlongfilenames.txt new file mode 100644 index 000000000000..e8c8c6d51ffb --- /dev/null +++ b/tools/test_apps/storage/fatfsgen/fatfs_long_name_image/sublongnames/testlongfilenames.txt @@ -0,0 +1 @@ +this is test; long name it has diff --git a/examples/storage/fatfsgen/main/CMakeLists.txt b/tools/test_apps/storage/fatfsgen/main/CMakeLists.txt similarity index 100% rename from examples/storage/fatfsgen/main/CMakeLists.txt rename to tools/test_apps/storage/fatfsgen/main/CMakeLists.txt diff --git a/examples/storage/fatfsgen/main/Kconfig.projbuild b/tools/test_apps/storage/fatfsgen/main/Kconfig.projbuild similarity index 100% rename from examples/storage/fatfsgen/main/Kconfig.projbuild rename to tools/test_apps/storage/fatfsgen/main/Kconfig.projbuild diff --git a/examples/storage/fatfsgen/main/fatfsgen_example_main.c b/tools/test_apps/storage/fatfsgen/main/fatfsgen_example_main.c similarity index 100% rename from examples/storage/fatfsgen/main/fatfsgen_example_main.c rename to tools/test_apps/storage/fatfsgen/main/fatfsgen_example_main.c diff --git a/tools/test_apps/storage/fatfsgen/partitions_example.csv b/tools/test_apps/storage/fatfsgen/partitions_example.csv new file mode 100644 index 000000000000..1c79321a107c --- /dev/null +++ b/tools/test_apps/storage/fatfsgen/partitions_example.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, diff --git a/examples/storage/fatfsgen/pytest_fatfsgen_example.py b/tools/test_apps/storage/fatfsgen/pytest_fatfsgen_example.py similarity index 100% rename from examples/storage/fatfsgen/pytest_fatfsgen_example.py rename to tools/test_apps/storage/fatfsgen/pytest_fatfsgen_example.py diff --git a/examples/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen rename to tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen diff --git a/examples/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_default_dt b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_default_dt similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_default_dt rename to tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_default_dt diff --git a/examples/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln rename to tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln diff --git a/examples/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln_default_dt b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln_default_dt similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln_default_dt rename to tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_only_partition_gen_ln_default_dt diff --git a/examples/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen rename to tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen diff --git a/examples/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_default_dt b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_default_dt similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_default_dt rename to tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_default_dt diff --git a/examples/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln rename to tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln diff --git a/examples/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln_default_dt b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln_default_dt similarity index 100% rename from examples/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln_default_dt rename to tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln_default_dt diff --git a/tools/test_apps/storage/fatfsgen/sdkconfig.defaults b/tools/test_apps/storage/fatfsgen/sdkconfig.defaults new file mode 100644 index 000000000000..47363c32d517 --- /dev/null +++ b/tools/test_apps/storage/fatfsgen/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y diff --git a/tools/test_apps/system/cxx_build_test/main/test_i2c_lcd.cpp b/tools/test_apps/system/cxx_build_test/main/test_i2c_lcd.cpp index cb058d62c06c..716e6d4eb0ef 100644 --- a/tools/test_apps/system/cxx_build_test/main/test_i2c_lcd.cpp +++ b/tools/test_apps/system/cxx_build_test/main/test_i2c_lcd.cpp @@ -52,6 +52,7 @@ void test_i2c_lcd_apis(void) .trans_queue_depth = 4, .flags = { .enable_internal_pullup = true, + .allow_pd = false, } }; diff --git a/tools/test_apps/system/panic/CMakeLists.txt b/tools/test_apps/system/panic/CMakeLists.txt index 3305b7b4f6f6..e9db4327f57b 100644 --- a/tools/test_apps/system/panic/CMakeLists.txt +++ b/tools/test_apps/system/panic/CMakeLists.txt @@ -17,7 +17,7 @@ if(CONFIG_TEST_MEMPROT) endif() endif() -if(NOT CONFIG_TEST_MEMPROT AND NOT CONFIG_ESP_COREDUMP_CAPTURE_DRAM AND NOT CONFIG_SPIRAM) +if(NOT CONFIG_TEST_MEMPROT AND NOT CONFIG_ESP_COREDUMP_CAPTURE_DRAM) # Enable UBSAN checks # # shift-base sanitizer is disabled due to the following pattern found in register header files: diff --git a/tools/test_apps/system/panic/main/include/test_panic.h b/tools/test_apps/system/panic/main/include/test_panic.h index 71733add77e4..32d051265544 100644 --- a/tools/test_apps/system/panic/main/include/test_panic.h +++ b/tools/test_apps/system/panic/main/include/test_panic.h @@ -31,7 +31,7 @@ void test_hw_stack_guard_cpu1(void); #endif // CONFIG_FREERTOS_UNICORE #endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD -#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM void test_panic_extram_stack_heap(void); #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY void test_panic_extram_stack_bss(void); diff --git a/tools/test_apps/system/panic/main/test_app_main.c b/tools/test_apps/system/panic/main/test_app_main.c index b55f7de76526..a824e25e5bd1 100644 --- a/tools/test_apps/system/panic/main/test_app_main.c +++ b/tools/test_apps/system/panic/main/test_app_main.c @@ -95,7 +95,7 @@ void app_main(void) HANDLE_TEST(test_name, test_hw_stack_guard_cpu1); #endif // CONFIG_FREERTOS_UNICORE #endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD -#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM HANDLE_TEST(test_name, test_panic_extram_stack_heap); #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY HANDLE_TEST(test_name, test_panic_extram_stack_bss); diff --git a/tools/test_apps/system/panic/main/test_panic.c b/tools/test_apps/system/panic/main/test_panic.c index 6f58469d826b..eafc9daddfee 100644 --- a/tools/test_apps/system/panic/main/test_panic.c +++ b/tools/test_apps/system/panic/main/test_panic.c @@ -96,7 +96,7 @@ void test_hw_stack_guard_cpu1(void) #endif // CONFIG_FREERTOS_UNICORE #endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD -#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM static void stack_in_extram(void* arg) { (void) arg; @@ -130,7 +130,7 @@ void test_panic_extram_stack_bss(void) vTaskDelay(1000); } #endif -#endif // ESP_COREDUMP_ENABLE_TO_FLASH && SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY +#endif // ESP_COREDUMP_ENABLE_TO_FLASH && FREERTOS_TASK_CREATE_ALLOW_EXT_MEM #if !CONFIG_FREERTOS_UNICORE diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index 1f2cdccb268e..d0c093e35751 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -29,6 +29,7 @@ pytest.mark.esp32c5, pytest.mark.esp32c6, pytest.mark.esp32h2, + pytest.mark.esp32c61, ] TARGETS_RISCV_DUAL_CORE = [ @@ -50,12 +51,12 @@ CONFIGS = [ pytest.param('coredump_flash_bin_crc', marks=TARGETS_ALL), pytest.param('coredump_flash_elf_sha', marks=TARGETS_ALL), + pytest.param('coredump_flash_elf_soft_sha', marks=TARGETS_ALL), pytest.param('coredump_uart_bin_crc', marks=TARGETS_ALL), pytest.param('coredump_uart_elf_crc', marks=TARGETS_ALL), pytest.param('coredump_flash_custom_stack', marks=TARGETS_RISCV), - # TODO: Move esp32c61 to TARGETS_RISCV once Core Dump is supported (IDF-9268) - pytest.param('gdbstub', marks=TARGETS_ALL + [pytest.mark.esp32c61]), - pytest.param('panic', marks=TARGETS_ALL + [pytest.mark.esp32c61]), + pytest.param('gdbstub', marks=TARGETS_ALL), + pytest.param('panic', marks=TARGETS_ALL), ] CONFIGS_DUAL_CORE = [ @@ -84,7 +85,6 @@ pytest.param('coredump_flash_bin_crc', marks=TARGETS_RISCV), pytest.param('coredump_uart_bin_crc', marks=TARGETS_RISCV), pytest.param('coredump_uart_elf_crc', marks=TARGETS_RISCV), - # TODO: Add stack guard support to the ESP32-C61: IDF-9269 pytest.param('gdbstub', marks=TARGETS_RISCV), pytest.param('panic', marks=TARGETS_RISCV), ] @@ -980,7 +980,7 @@ def test_hw_stack_guard_cpu(dut: PanicTestDut, cpu: int) -> None: assert end_addr > start_addr -@pytest.mark.temp_skip_ci(targets=['esp32c5'], reason='TODO: IDF-8662') +@pytest.mark.temp_skip_ci(targets=['esp32c5', 'esp32c61'], reason='TODO: IDF-8662 and IDF-9269') @pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD, indirect=True) @pytest.mark.generic def test_hw_stack_guard_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> None: @@ -989,7 +989,6 @@ def test_hw_stack_guard_cpu0(dut: PanicTestDut, config: str, test_func_name: str common_test(dut, config) -@pytest.mark.temp_skip_ci(targets=['esp32c5'], reason='TODO: IDF-8662') @pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD_DUAL_CORE, indirect=True) @pytest.mark.generic def test_hw_stack_guard_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> None: @@ -1036,7 +1035,7 @@ def test_capture_dram(dut: PanicTestDut, config: str, test_func_name: str) -> No assert int(dut.gdb_data_eval_expr('g_cd_iram')) == 0x4243 assert int(dut.gdb_data_eval_expr('g_cd_dram')) == 0x4344 - if dut.target != 'esp32c2': + if dut.target not in ['esp32c61', 'esp32c2']: assert int(dut.gdb_data_eval_expr('g_rtc_data_var')) == 0x55AA assert int(dut.gdb_data_eval_expr('g_rtc_fast_var')) == 0xAABBCCDD diff --git a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_elf_soft_sha b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_elf_soft_sha new file mode 100644 index 000000000000..e426d2e4d1c4 --- /dev/null +++ b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_elf_soft_sha @@ -0,0 +1,5 @@ +CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y +CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y +CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +CONFIG_MBEDTLS_HARDWARE_SHA=n diff --git a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32 b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32 index 26769c3c5981..065b49d68b24 100644 --- a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32 +++ b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32 @@ -5,7 +5,7 @@ CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y # We need to have the coredump info log CONFIG_LOG_DEFAULT_LEVEL_INFO=y CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y CONFIG_ESP_COREDUMP_CAPTURE_DRAM=y diff --git a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32s2 b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32s2 index ad1a91fa8119..7c372f58f2c2 100644 --- a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32s2 +++ b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32s2 @@ -5,7 +5,7 @@ CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y # We need to have the coredump info log CONFIG_LOG_DEFAULT_LEVEL_INFO=y CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y CONFIG_ESP_COREDUMP_CAPTURE_DRAM=y diff --git a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32s3 b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32s3 index 46903a022352..a1533240cb6b 100644 --- a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32s3 +++ b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_bss_esp32s3 @@ -5,7 +5,7 @@ CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y # We need to have the coredump info log CONFIG_LOG_DEFAULT_LEVEL_INFO=y CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y CONFIG_ESP_COREDUMP_CAPTURE_DRAM=y diff --git a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32 b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32 index 18391318a374..a98716641a9a 100644 --- a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32 +++ b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32 @@ -5,5 +5,5 @@ CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y # We need to have the coredump info log CONFIG_LOG_DEFAULT_LEVEL_INFO=y CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y diff --git a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32s2 b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32s2 index 981803c0be23..dddebf12c098 100644 --- a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32s2 +++ b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32s2 @@ -5,5 +5,5 @@ CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y # We need to have the coredump info log CONFIG_LOG_DEFAULT_LEVEL_INFO=y CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y diff --git a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32s3 b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32s3 index ff952817bde2..552021189427 100644 --- a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32s3 +++ b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_stack_heap_esp32s3 @@ -5,5 +5,5 @@ CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y # We need to have the coredump info log CONFIG_LOG_DEFAULT_LEVEL_INFO=y CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y diff --git a/tools/test_build_system/conftest.py b/tools/test_build_system/conftest.py index 74b96ae7a1f6..865c018863d0 100644 --- a/tools/test_build_system/conftest.py +++ b/tools/test_build_system/conftest.py @@ -51,7 +51,7 @@ def _session_work_dir(request: FixtureRequest) -> typing.Generator[typing.Tuple[ work_dir = request.config.getoption('--work-dir') if work_dir: - work_dir = os.path.join(work_dir, datetime.datetime.utcnow().strftime('%Y-%m-%d_%H-%M-%S')) + work_dir = os.path.join(work_dir, datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d_%H-%M-%S')) logging.debug(f'using work directory: {work_dir}') os.makedirs(work_dir, exist_ok=True) clean_dir = None diff --git a/tools/test_build_system/pytest.ini b/tools/test_build_system/pytest.ini index 433952425ad5..fe058544ee37 100644 --- a/tools/test_build_system/pytest.ini +++ b/tools/test_build_system/pytest.ini @@ -19,3 +19,4 @@ markers = idf_copy: specify the prefix of the destination directory where IDF should be copied idf_copy_with_space: ensures that destination directory where IDF is copied contain space force_temp_work_dir: force temporary folder as the working directory + with_idf_components: automatically create/delete components under IDF_PATH diff --git a/tools/test_build_system/test_components.py b/tools/test_build_system/test_components.py index e7333c8d4548..1cbff9706fa9 100644 --- a/tools/test_build_system/test_components.py +++ b/tools/test_build_system/test_components.py @@ -2,8 +2,10 @@ # SPDX-License-Identifier: Apache-2.0 import json import logging +import os import shutil from pathlib import Path +from typing import Generator import pytest from test_build_system_helpers import append_to_file @@ -12,6 +14,31 @@ from test_build_system_helpers import replace_in_file +@pytest.fixture(autouse=True) +def create_idf_components(request: pytest.FixtureRequest) -> Generator: + """ + Auto create/remove components under IDF_PATH. + Use it by applying the marker to the test function: + + >>> @pytest.mark.with_idf_components(['cmp1', 'cmp2', ...]) + """ + mark = request.node.get_closest_marker('with_idf_components') + if mark is None: + yield + else: + idf_path = Path(os.environ['IDF_PATH']) + created_paths = [] + for name in mark.args[0]: + (idf_path / 'components' / name).mkdir(parents=True) + (idf_path / 'components' / name / 'CMakeLists.txt').write_text('idf_component_register()') + created_paths.append(str((idf_path / 'components' / name).as_posix())) + + yield + + for path in created_paths: + shutil.rmtree(path) + + def test_component_extra_dirs(idf_py: IdfPyFunc, test_app_copy: Path) -> None: logging.info('Setting EXTRA_COMPONENT_DIRS works') shutil.move(test_app_copy / 'main', test_app_copy / 'different_main' / 'main') @@ -124,19 +151,100 @@ def test_component_overridden_dir(idf_py: IdfPyFunc, test_app_copy: Path, defaul assert 'kconfig:{}'.format((idf_path / 'components' / 'hal').as_posix()) in ret.stdout, 'Failed to verify original `main` directory' -def test_components_prioritizer_over_extra_components_dir(idf_py: IdfPyFunc, test_app_copy: Path) -> None: - logging.info('Project components prioritized over EXTRA_COMPONENT_DIRS') +def test_project_components_overrides_extra_components(idf_py: IdfPyFunc, test_app_copy: Path) -> None: + logging.info('Project components override components defined in EXTRA_COMPONENT_DIRS') (test_app_copy / 'extra_dir' / 'my_component').mkdir(parents=True) (test_app_copy / 'extra_dir' / 'my_component' / 'CMakeLists.txt').write_text('idf_component_register()') replace_in_file(test_app_copy / 'CMakeLists.txt', '# placeholder_before_include_project_cmake', 'set(EXTRA_COMPONENT_DIRS extra_dir)') - ret = idf_py('reconfigure') - assert str((test_app_copy / 'extra_dir' / 'my_component').as_posix()) in ret.stdout, 'Unable to find component specified in EXTRA_COMPONENT_DIRS' + idf_py('reconfigure') + with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + data = json.load(f) + assert str((test_app_copy / 'extra_dir' / 'my_component').as_posix()) in data.get('build_component_paths') + (test_app_copy / 'components' / 'my_component').mkdir(parents=True) (test_app_copy / 'components' / 'my_component' / 'CMakeLists.txt').write_text('idf_component_register()') - ret = idf_py('reconfigure') - assert str((test_app_copy / 'components' / 'my_component').as_posix()) in ret.stdout, 'Project components should be prioritized over EXTRA_COMPONENT_DIRS' + idf_py('reconfigure') + with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + data = json.load(f) + assert str((test_app_copy / 'components' / 'my_component').as_posix()) in data.get('build_component_paths') + assert str((test_app_copy / 'extra_dir' / 'my_component').as_posix()) not in data.get('build_component_paths') + + +def test_extra_components_overrides_managed_components(idf_py: IdfPyFunc, test_app_copy: Path) -> None: + logging.info('components defined in EXTRA_COMPONENT_DIRS override managed components') + (test_app_copy / 'main' / 'idf_component.yml').write_text(""" + dependencies: + example/cmp: "*" + """) + idf_py('reconfigure') + with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + data = json.load(f) + assert str((test_app_copy / 'managed_components' / 'example__cmp').as_posix()) in data.get( + 'build_component_paths') + + (test_app_copy / 'extra_dir' / 'cmp').mkdir(parents=True) + (test_app_copy / 'extra_dir' / 'cmp' / 'CMakeLists.txt').write_text('idf_component_register()') + replace_in_file(test_app_copy / 'CMakeLists.txt', + '# placeholder_before_include_project_cmake', + 'set(EXTRA_COMPONENT_DIRS extra_dir)') + idf_py('reconfigure') + with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + data = json.load(f) + assert str((test_app_copy / 'extra_dir' / 'cmp').as_posix()) in data.get('build_component_paths') + assert str((test_app_copy / 'managed_components' / 'example__cmp').as_posix()) not in data.get( + 'build_component_paths') + + +@pytest.mark.with_idf_components(['cmp']) +def test_managed_components_overrides_idf_components(idf_py: IdfPyFunc, test_app_copy: Path) -> None: + logging.info('Managed components override components defined in IDF_PATH/components') + # created idf component 'cmp' in marker + idf_path = Path(os.environ['IDF_PATH']) + idf_py('reconfigure') + with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + data = json.load(f) + assert str((idf_path / 'components' / 'cmp').as_posix()) in data.get( + 'build_component_paths') + + (test_app_copy / 'main' / 'idf_component.yml').write_text(""" +dependencies: + example/cmp: "*" + """) + idf_py('reconfigure') + with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + data = json.load(f) + assert str((test_app_copy / 'managed_components' / 'example__cmp').as_posix()) in data.get( + 'build_component_paths') + assert str((idf_path / 'components' / 'cmp').as_posix()) not in data.get( + 'build_component_paths') + + +def test_manifest_local_source_overrides_extra_components(idf_py: IdfPyFunc, test_app_copy: Path) -> None: + (test_app_copy / '..' / 'extra_dir' / 'cmp').mkdir(parents=True) + (test_app_copy / '..' / 'extra_dir' / 'cmp' / 'CMakeLists.txt').write_text('idf_component_register()') + replace_in_file(test_app_copy / 'CMakeLists.txt', + '# placeholder_before_include_project_cmake', + 'set(EXTRA_COMPONENT_DIRS ../extra_dir)') + idf_py('reconfigure') + with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + data = json.load(f) + assert str((test_app_copy / '..' / 'extra_dir' / 'cmp').resolve().as_posix()) in data.get('build_component_paths') + + (test_app_copy / '..' / 'cmp').mkdir(parents=True) + (test_app_copy / '..' / 'cmp' / 'CMakeLists.txt').write_text('idf_component_register()') + with open(test_app_copy / 'main' / 'idf_component.yml', 'w') as f: + f.write(""" +dependencies: + cmp: + path: '../../cmp' + """) + idf_py('reconfigure') + with open(test_app_copy / 'build' / 'project_description.json', 'r') as f: + data = json.load(f) + assert str((test_app_copy / '..' / 'cmp').resolve().as_posix()) in data.get('build_component_paths') + assert str((test_app_copy / '..' / 'extra_dir' / 'cmp').resolve().as_posix()) not in data.get('build_component_paths') def test_exclude_components_not_passed(idf_py: IdfPyFunc, test_app_copy: Path) -> None: diff --git a/tools/test_idf_py/test_idf_py.py b/tools/test_idf_py/test_idf_py.py index 9ccdfe09242a..9daac230c33c 100755 --- a/tools/test_idf_py/test_idf_py.py +++ b/tools/test_idf_py/test_idf_py.py @@ -549,5 +549,38 @@ def test_merge_bin(self): self.assertIn(f'Merged binary {merged_binary_name} will be created in the build directory...', output) +class TestUF2Commands(TestWrapperCommands): + """ + Test if uf2 commands are invoked as expected. + This test is not testing the functionality of mkuf2.py/idf.py uf2, but the invocation of the command from idf.py. + """ + + def test_uf2(self): + uf2_command = [sys.executable, idf_py_path, 'uf2'] + output = self.call_command(uf2_command) + self.assertIn('Executing:', output) + + def test_uf2_with_envvars(self): + # Values do not really matter, they should not be used. + os.environ['ESPBAUD'] = '115200' + os.environ['ESPPORT'] = '/dev/ttyUSB0' + self.test_uf2() + os.environ.pop('ESPBAUD') + os.environ.pop('ESPPORT') + + def test_uf2_app(self): + uf2_app_command = [sys.executable, idf_py_path, 'uf2-app'] + output = self.call_command(uf2_app_command) + self.assertIn('Executing:', output) + + def test_uf2_app_with_envvars(self): + # Values do not really matter, they should not be used. + os.environ['ESPBAUD'] = '115200' + os.environ['ESPPORT'] = '/dev/ttyUSB0' + self.test_uf2_app() + os.environ.pop('ESPBAUD') + os.environ.pop('ESPPORT') + + if __name__ == '__main__': main() diff --git a/tools/tools.json b/tools/tools.json index 54b3037af734..7fab2a8ec491 100644 --- a/tools/tools.json +++ b/tools/tools.json @@ -605,46 +605,46 @@ "versions": [ { "linux-amd64": { - "sha256": "f8c68541fa38307bc0c0763b7e1e3fe4e943d5d45da07d817a73b492e103b652", - "size": 2373094, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-amd64-0.12.0-esp32-20240821.tar.gz" + "sha256": "e82b0f036dc99244bead5f09a86e91bb2365cbcd1122ac68261e5647942485df", + "size": 2398717, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-amd64-0.12.0-esp32-20241016.tar.gz" }, "linux-arm64": { - "sha256": "4d6e263d84e447354dc685848557d6c284dda7fe007ee451f729a7edfa7baad7", - "size": 2251272, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-arm64-0.12.0-esp32-20240821.tar.gz" + "sha256": "8f8daf5bd22ec5d2fa9257b0862ec33da18ee677e023fb9a9eb17f74ce208c76", + "size": 2271584, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-arm64-0.12.0-esp32-20241016.tar.gz" }, "linux-armel": { - "sha256": "9d45679f2c4cf450d5e2350047cf57bb76dde2487d30cebce0a72c9173b5c45b", - "size": 2390074, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-armel-0.12.0-esp32-20240821.tar.gz" + "sha256": "bc9c020ecf20e2000f76cffa44305fd5bc44d2e688ea78cce423399d33f19767", + "size": 2414206, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-armel-0.12.0-esp32-20241016.tar.gz" }, "linux-armhf": { - "sha256": "7f56d6a0c73e3988891a0781adee4973e6b9ea4bb4584cacb88384cb3db59050", - "size": 2232548, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-armhf-0.12.0-esp32-20240821.tar.gz" + "sha256": "2cd6436465333e998000b1c311d301b295d8ebaa3fb1c9aa9d4393539dc16ec6", + "size": 2258623, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-armhf-0.12.0-esp32-20241016.tar.gz" }, "macos": { - "sha256": "565c8fabc5f19a6e7a0864a294d74b307eec30b9291d16d3fc90e273f0330cb4", - "size": 2485320, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-macos-0.12.0-esp32-20240821.tar.gz" + "sha256": "02a2dffe801a2d005fa9e614d80ff8173395b2cb0b5d3118d0229d094a9946a7", + "size": 2508089, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-macos-0.12.0-esp32-20241016.tar.gz" }, "macos-arm64": { - "sha256": "68c5c7cf3d15b9810939a5edabc6ff2c9f4fc32262de91fc292a180bc5cc0637", - "size": 2530336, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-macos-arm64-0.12.0-esp32-20240821.tar.gz" + "sha256": "c382f9e884d6565cb6089bff5f200f4810994667d885f062c3d3c5625a0fa9d6", + "size": 2552569, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-macos-arm64-0.12.0-esp32-20241016.tar.gz" }, - "name": "v0.12.0-esp32-20240821", + "name": "v0.12.0-esp32-20241016", "status": "recommended", "win32": { - "sha256": "463fc2903ddaf03f86ff50836c5c63cc696550b0446140159eddfd2e85570c5d", - "size": 2916409, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-win32-0.12.0-esp32-20240821.zip" + "sha256": "3b5d615e0a72cc771a45dd469031312d5881c01d7b6bc9edb29b8b6bda8c2e90", + "size": 2946244, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-win32-0.12.0-esp32-20241016.zip" }, "win64": { - "sha256": "550f57369f1f1f6cc600b5dffa3378fd6164d8ea8db7c567cf41091771f090cb", - "size": 2916408, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-win64-0.12.0-esp32-20240821.zip" + "sha256": "5e7b2fd1947d3a8625f6a11db7a2340cf2f41ff4c61284c022c7d7c32b18780a", + "size": 2946244, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-win64-0.12.0-esp32-20241016.zip" } } ] @@ -863,11 +863,11 @@ "versions": [ { "any": { - "sha256": "a26609b415710f0163d785850c769752717004059c129c472e9a0cbd54e0422c", - "size": 3258247, - "url": "https://github.com/espressif/esp-rom-elfs/releases/download/20240305/esp-rom-elfs-20240305.tar.gz" + "sha256": "921f000164a421c7628fbfee55b173384aafaa51883adc65cd27bf9b0af9e9a9", + "size": 3540038, + "url": "https://github.com/espressif/esp-rom-elfs/releases/download/20241011/esp-rom-elfs-20241011.tar.gz" }, - "name": "20240305", + "name": "20241011", "status": "recommended" } ]